Skip to content

Commit

Permalink
Merge pull request #55 from metacoma/ai-tmux-helper
Browse files Browse the repository at this point in the history
Ai tmux helper
  • Loading branch information
metacoma authored Nov 8, 2023
2 parents 2cc29b7 + 2cc0d45 commit ab14b68
Show file tree
Hide file tree
Showing 13 changed files with 415 additions and 75 deletions.
70 changes: 70 additions & 0 deletions files/ai-helper/ai-helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import pika
import pprint
import json
import re
from neo4j import GraphDatabase

rabbitmq_url = "amqp://user:[email protected]:30466/%2f"
neo4j_url = "bolt://192.168.49.2:31237"
neo4j_username = 'neo4j'
neo4j_password = 'password'

# Create a connection to RabbitMQ
connection = pika.BlockingConnection(pika.URLParameters(rabbitmq_url))
rabbitmq_channel = connection.channel()

exchange_name = "io-line"
result = rabbitmq_channel.queue_declare(queue="", exclusive=True)
queue_name = result.method.queue

rabbitmq_channel.queue_bind(exchange=exchange_name, queue=queue_name)

def get_last_io_document(host, tmux_session_name, tmux_pane_id, n):
query = """
MATCH (host:Node {node_type: "host", name: "%s"})-[:HAS_TMUX_SESSION]->(session:Node {node_type: "tmux_session", name: "%s"})-[:HAS_PANE]->(pane:Node {node_type: "tmux_pane", name: "%d"})-[:HAS_IO_CONTEXT]->(io_context:Node {node_type: "io_context"})-[:IO_DOCUMENT]->(io_document:Node {node_type: "io_document"})
WITH io_document
ORDER BY ID(io_document) DESC
LIMIT %d
RETURN io_document
""" % (host, tmux_session_name, int(tmux_pane_id), int(n))
print(query)
with GraphDatabase.driver(neo4j_url, auth=(neo4j_username, neo4j_password)) as driver:
with driver.session() as session:
result = session.run(query)
record = result.single()
return record

return None


def callback(ch, method, properties, body):
data = json.loads(body.decode())

# trigger pattern
# <user>@host:/home/user $ # ai request
pattern = r".*@.*\$ #.*"
if re.match(pattern, data['message']):
host = data['host']
tmux_session_name = data['metadata']['tmux']['session_name']
tmux_pane_id = data['metadata']['tmux']['pane_id']
last_document = get_last_io_document(host, tmux_session_name, tmux_pane_id, 1)
cmd_input = last_document['io_document'].get('name')
cmd_output = last_document['io_document'].get('output_data')

question = re.sub(r'^.*?#[ ]?', '', data['message'])
data = {
"tmux_pane_id": tmux_pane_id,
"tmux_session_name": tmux_session_name,
"host": host,
"question": question,
"terminal-command-sequence": [{
"input": cmd_input,
"output": cmd_output
}]
}
rabbitmq_channel.basic_publish(exchange='openai', routing_key='openai', body=json.dumps(data))
pprint.pprint(data)

rabbitmq_channel.basic_consume(queue=queue_name, on_message_callback=callback, auto_ack=True)
print("Waiting for messages. To exit, press Ctrl+C")
rabbitmq_channel.start_consuming()
6 changes: 6 additions & 0 deletions files/ai-helper/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pika
neo4j
grpcio
protobuf
libtmux
openai
3 changes: 1 addition & 2 deletions files/freeplane-io-context/freeplane-io-context.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{%- raw -%}
import pika
import pprint
import json
Expand Down Expand Up @@ -29,6 +28,7 @@
output_queue_name = "io-document"

exchange_name = os.getenv('EXCHANGE_NAME')
exchange_name = "io-context"
result = rabbitmq_channel.queue_declare(queue="", exclusive=True)
queue_name = result.method.queue

Expand Down Expand Up @@ -473,4 +473,3 @@ def callback(ch, method, properties, body):

print("Waiting for messages. To exit, press Ctrl+C")
rabbitmq_channel.start_consuming()
{%- endraw -%}
1 change: 0 additions & 1 deletion files/grpc/freeplane_grpc/python/freeplane_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

80 changes: 80 additions & 0 deletions files/openai-io-context/openai-io-context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import pika
import pprint
import json
import grpc
import re
import libtmux
import openai
import os
from neo4j import GraphDatabase

rabbitmq_url = "amqp://user:[email protected]:30466/%2f"
neo4j_url = "bolt://192.168.49.2:31237"
neo4j_username = 'neo4j'
neo4j_password = 'password'

openai.api_key = os.getenv("OPENAI_API_KEY")

FP_DETAILS_MAX_LINE = 4

# Create a connection to RabbitMQ
connection = pika.BlockingConnection(pika.URLParameters(rabbitmq_url))
rabbitmq_channel = connection.channel()

exchange_name = "openai"
result = rabbitmq_channel.queue_declare(queue="", exclusive=True)
queue_name = result.method.queue

rabbitmq_channel.queue_bind(exchange=exchange_name, queue=queue_name)

def callback(ch, method, properties, body):

messages = [
{"role": "system", "content":
"""I work in bash, enter commands, and receive responses in the form of text. The assistant is required to help me by answering my questions.
"""}
]
pprint.pprint(body.decode())

data = json.loads(body.decode())

openai_payload = {
"question": data['question'],
"terminal-command-sequence": data['terminal-command-sequence']
}

messages.append({"role": "user", "content": json.dumps(openai_payload)})

response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages
)
tmux_pane_id = data['tmux_pane_id']
tmux_session_name = data['tmux_session_name']

# Print the response and add it to the messages list
for i in range(len(response['choices'])):
chat_message = response['choices'][i]['message']['content']
print(f"Bot: #{i} {chat_message}")
# tmux_cmd = {
# "tmux_pane_id": "{tmux_pane_id}",
# "session_name": "{tmux_session_name}",
# "cmd": f"""cat<<OPENAI_EOF
#*************
#{chat_message}
#*************
#OPENAI_EOF
#"""
# }

tmux_cmd = {
"tmux_pane_id": tmux_pane_id,
"session_name": tmux_session_name,
"cmd": f"""echo{chat_message}"""
}
rabbitmq_channel.basic_publish(exchange='tmux', routing_key='tmux', body=json.dumps(tmux_cmd))
break

rabbitmq_channel.basic_consume(queue=queue_name, on_message_callback=callback, auto_ack=True)
print("Waiting for messages. To exit, press Ctrl+C")
rabbitmq_channel.start_consuming()
6 changes: 6 additions & 0 deletions files/openai-io-context/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pika
neo4j
grpcio
protobuf
libtmux
openai
34 changes: 34 additions & 0 deletions files/tmux-manager/rabbitmq-tmux-manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import pika
import pprint
import json
import re
import libtmux
import os

rabbitmq_url = "amqp://user:[email protected]:30466/%2f"

# Create a connection to RabbitMQ
connection = pika.BlockingConnection(pika.URLParameters(rabbitmq_url))
rabbitmq_channel = connection.channel()

exchange_name = "tmux"
result = rabbitmq_channel.queue_declare(queue="", exclusive=True)
queue_name = result.method.queue

rabbitmq_channel.queue_bind(exchange=exchange_name, queue=queue_name)

def callback(ch, method, properties, body):

pprint.pprint(body.decode())
tmux_cmd = json.loads(body.decode())

server = libtmux.Server()
tmux_pane_id = tmux_cmd['tmux_pane_id']
session_name = tmux_cmd['session_name']

session = server.find_where({"session_name": session_name})
session.panes.filter(pane_id = "%" + tmux_pane_id)[0].send_keys(tmux_cmd['cmd'])

rabbitmq_channel.basic_consume(queue=queue_name, on_message_callback=callback, auto_ack=True)
print("Waiting for messages. To exit, press Ctrl+C")
rabbitmq_channel.start_consuming()
2 changes: 2 additions & 0 deletions files/tmux-manager/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pika
libtmux
1 change: 1 addition & 0 deletions inventory/classes/mindwm/k8s.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ parameters:
mindwm:
k8s:
consumer_namespace: mindwm-consumers
vector_aggregator_port: 31399
43 changes: 43 additions & 0 deletions inventory/classes/rabbitmq/common.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,47 @@
---
parameters:
bash:
functions:
rabbitmq_payload_prepare: |
cat<<EOF
{
"vhost": "/",
"name": "",
"properties": {
"delivery_mode": 2,
"headers": {}
},
"routing_key": "key",
"delivery_mode": "1",
"payload":`jq @json`,
"headers": {},
"props": {},
"payload_encoding": "string"
}
EOF
rabbitmq_publish_data: |
local exchange=$1
user=${rabbitmq_user}
pass=${rabbitmq_password}
#TODO(@metacoma) fix hardcode
rmq_url="`minikube ip`:32100"
curl -vu "$user:$pass" -H "Accept: application/json" -H "Content-Type:application/json" -X POST -d @- http://$rmq_url/api/exchanges/%2f/$exchange/publish
# . functions.bash
# cat json | rabbitmq_publish_json exchange_name
rabbitmq_publish_json: |
local exchange=$1
rabbitmq_payload_prepare | rabbitmq_publish_data $exchange
rabbitmq_release_name: rabbitmq
rabbitmq_default_port: 5672
rabbitmq_k8s_namespace: rabbitmq
rabbitmq_exchanges:
io-line:
name: io-line
type: fanout
durable: true
io-context:
name: io-context
type: fanout
Expand All @@ -16,6 +54,11 @@ parameters:
name: tmux
type: fanout
durable: true
openai:
name: openai
type: fanout
durable: true

rabbitmq_version: 3.12.4
rabbitmq_user: user
rabbitmq_password: password
95 changes: 95 additions & 0 deletions inventory/classes/tmux/pipe-stream.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
classes:
- mindwm.k8s
parameters:
kapitan:
compile:
- input_paths:
- files/vector/pipe-pane2hexstream.pl
output_path: .
input_type: copy

- input_paths:
- jsonnet/vector-conf.jsonnet
output_path: vector/
input_type: jsonnet
output_type: yaml
bash:
functions:
tmux-pipe-stream: |
# PARENT_PID=`ps -o ppid= $$ | tr -d '[:space:]'`
SHELL_PID=$$
TMUX_SESSION_NAME=`tmux display-message -p '#S'`
VECTOR_UPSTREAM=`minikube ip`:${mindwm:k8s:vector_aggregator_port}
TMUX_PANE_ID=`echo $TMUX_PANE`
if [ -z "$TMUX_PANE_ID" ]; then
TMUX_PANE_ID=`tmux list-panes -t $TMUX_SESSION_NAME -F '#{pane_id} #{pane_active}' | awk '/1$/ {print $1}'`
fi
TMUX_PANE_ID=`echo $TMUX_PANE_ID | sed 's/[^0-9]//g'`
tmux pipe-pane -IO "perl ${compiled_dir}/pipe-pane2hexstream.pl | VECTOR_UPSTREAM='$VECTOR_UPSTREAM' SHELL_PID='$SHELL_PID' TMUX_SESSION_NAME='$TMUX_SESSION_NAME' TMUX_PANE_ID='$TMUX_PANE_ID' vector -q --config ${compiled_dir}/vector/tmux-bytestream.yaml"
vector:
config:
tmux-bytestream:
sources:
tmux-raw-bytestream:
type: "file_descriptor"
fd: 0
decoding:
codec: "bytes"
transforms:
tmux-bytestream:
type: remap
bash:
functions:
tmux-pipe-stream: |
# PARENT_PID=`ps -o ppid= $$ | tr -d '[:space:]'`
SHELL_PID=$$
TMUX_SESSION_NAME=`tmux display-message -p '#S'`
VECTOR_UPSTREAM=`minikube ip`:${mindwm:k8s:vector_aggregator_port}
TMUX_PANE_ID=`echo $TMUX_PANE`
if [ -z "$TMUX_PANE_ID" ]; then
TMUX_PANE_ID=`tmux list-panes -t $TMUX_SESSION_NAME -F '#{pane_id} #{pane_active}' | awk '/1$/ {print $1}'`
fi
TMUX_PANE_ID=`echo $TMUX_PANE_ID | sed 's/[^0-9]//g'`
tmux pipe-pane -IO "perl ${compiled_dir}/pipe-pane2hexstream.pl | VECTOR_UPSTREAM='$VECTOR_UPSTREAM' SHELL_PID='$SHELL_PID' TMUX_SESSION_NAME='$TMUX_SESSION_NAME' TMUX_PANE_ID='$TMUX_PANE_ID' vector -q --config ${compiled_dir}/vector/tmux-bytestream.yaml"
vector:
config:
tmux-bytestream:
sources:
tmux-raw-bytestream:
type: "file_descriptor"
fd: 0
decoding:
codec: "bytes"
transforms:
tmux-bytestream:
type: remap
inputs:
- tmux-raw-bytestream
source: |
.metadata.shell.pid = "\${SHELL_PID}"
.metadata.tmux.pane_id = "\${TMUX_PANE_ID}"
.metadata.tmux.session_name = "\${TMUX_SESSION_NAME}"
.metadata.window.id = "0x1abcdfegh"
.metadata.window.name = "WAYLAND_WORKAROUND"
sinks:
tmux-to-vector:
type: vector

inputs:
- tmux-bytestream
address: \${VECTOR_UPSTREAM}
version: "2"
acknowledgements:
enabled: false

Loading

0 comments on commit ab14b68

Please sign in to comment.