fix(protocol): Normalize all keywords to uppercase to resolve TUI routing duplicates
Some checks failed
Deploy-Agent-V15-Stdin / JOB-V15-STDIN (push) Failing after 2s

This commit is contained in:
2026-04-19 15:31:25 -04:00
parent 455a1a62b2
commit e8c66c7e4a
4 changed files with 72 additions and 30 deletions

View File

@@ -45,16 +45,16 @@ The OpenCortex TUI Client is a standalone Common Lisp application built on **Cro
(let ((msg (opencortex:read-framed-message *stream*)))
(cond ((eq msg :eof) (setf *is-running* nil))
((eq msg :error) (setf *status-text* "Protocol Error"))
((and (listp msg) (eq (getf msg :type) :EVENT))
(let ((payload (getf msg :payload)))
(when (eq (getf payload :action) :handshake)
((and (listp msg) (eq (getf msg :TYPE) :EVENT))
(let ((payload (getf msg :PAYLOAD)))
(when (eq (getf payload :ACTION) :handshake)
(setf *status-text* "Ready"))))
((and (listp msg) (eq (getf msg :type) :STATUS))
((and (listp msg) (eq (getf msg :TYPE) :STATUS))
(setf *status-text* (format nil "[Scribe: ~a] [Gardener: ~a]"
(getf msg :scribe)
(getf msg :gardener))))
((and (listp msg) (eq (getf msg :type) :CHAT))
(enqueue-msg (getf msg :text)))
(getf msg :SCRIBE)
(getf msg :GARDENER))))
((and (listp msg) (eq (getf msg :TYPE) :CHAT))
(enqueue-msg (getf msg :TEXT)))
(t (enqueue-msg (format nil "~s" msg))))))
(error (c) (setf *status-text* (format nil "Net Error: ~a" c)) (setf *is-running* nil)))
(sleep 0.05)))
@@ -109,7 +109,7 @@ The OpenCortex TUI Client is a standalone Common Lisp application built on **Cro
(let ((cmd (coerce *input-buffer* 'string)))
(setf (fill-pointer *input-buffer*) 0)
(when (> (length cmd) 0)
(let ((framed (opencortex:frame-message (format nil "~s" (list :type :EVENT :payload (list :sensor :chat-message :text cmd))))))
(let ((framed (opencortex:frame-message (format nil "~s" (list :TYPE :EVENT :PAYLOAD (list :SENSOR :chat-message :TEXT cmd))))))
(format *stream* "~a" framed)
(finish-output *stream*)))
(when (string= cmd "/exit") (setf *is-running* nil))))

View File

@@ -32,8 +32,8 @@ Provide a secure, local, and low-latency terminal interface for the OpenCortex.
The gateway runs a multi-threaded TCP server. Each connection is handled in its own thread. Inbound lines are wrapped in a Signal and processed. The `:cli` actuator retrieves the `:reply-stream` from the signal context to send the response back to the specific connected client.
** 2. Semantic Interfaces
- Inbound: `(:sensor :chat-message :channel :cli :text "...")`
- Outbound: `(:type :REQUEST :target :cli :text "...")`
- Inbound: `(:SENSOR :chat-message :channel :cli :TEXT "...")`
- Outbound: `(:TYPE :REQUEST :target :cli :TEXT "...")`
* Phase D: Build (Implementation)
@@ -55,15 +55,15 @@ The CLI actuator writes the agent's response back to the client's network stream
#+begin_src lisp
(defun execute-cli-action (action context)
"Sends a framed message back to the connected CLI client."
(let* ((payload (getf action :payload))
(text (or (getf payload :text) (getf action :text)))
(let* ((payload (getf action :PAYLOAD))
(text (or (getf payload :TEXT) (getf action :TEXT)))
(stream (getf context :reply-stream)))
(handler-case
(if (and stream (open-stream-p stream))
(progn
(format stream "~a" (frame-message (format nil "~s" (list :type :CHAT :text text))))
(format stream "~a" (frame-message (format nil "~s" (list :TYPE :CHAT :TEXT text))))
(finish-output stream)
(format stream "~a" (frame-message (format nil "~s" '(:TYPE :STATUS :scribe :idle :gardener :sleeping))))
(format stream "~a" (frame-message (format nil "~s" '(:TYPE :STATUS :SCRIBE :idle :GARDENER :sleeping))))
(finish-output stream))
(harness-log "CLI ERROR: No active or open reply stream for signal."))
(error (c) (harness-log "CLI ACTUATOR ERROR: ~a" c)))))
@@ -77,13 +77,13 @@ Handles an individual TCP connection. It reads lines until the connection is clo
"Handles TUI slash commands by returning structured Lisp s-expressions."
(cond
((string= cmd "/status")
(format stream "~a" (frame-message (format nil "~s" '(:TYPE :STATUS :scribe :idle :gardener :sleeping))))
(format stream "~a" (frame-message (format nil "~s" '(:TYPE :STATUS :SCRIBE :idle :GARDENER :sleeping))))
(finish-output stream))
((string= cmd "/exit")
(prin1 '(:type :info :text "Goodbye!") stream)
(prin1 '(:TYPE :info :TEXT "Goodbye!") stream)
(terpri stream)
(finish-output stream))
(t (prin1 (list :type :error :text (format nil "Unknown command: ~a" cmd)) stream)
(t (prin1 (list :TYPE :error :TEXT (format nil "Unknown command: ~a" cmd)) stream)
(terpri stream)
(finish-output stream))))
@@ -95,7 +95,7 @@ Handles an individual TCP connection. It reads lines until the connection is clo
;; 1. Send Handshake
(format stream "~a" (frame-message (format nil "~s" (make-hello-message "0.1.0"))))
(finish-output stream)
(format stream "~a" (frame-message (format nil "~s" '(:TYPE :STATUS :scribe :idle :gardener :sleeping))))
(format stream "~a" (frame-message (format nil "~s" '(:TYPE :STATUS :SCRIBE :idle :GARDENER :sleeping))))
(finish-output stream)
;; 2. Communication Loop
@@ -103,8 +103,8 @@ Handles an individual TCP connection. It reads lines until the connection is clo
(let ((msg (read-framed-message stream)))
(cond ((eq msg :eof) (return))
((eq msg :error) (return))
(t (if (and (listp msg) (stringp (getf msg :text)) (char= (char (getf msg :text) 0) #\/))
(handle-cli-slash-command (getf msg :text) stream)
(t (if (and (listp msg) (stringp (getf msg :TEXT)) (char= (char (getf msg :TEXT) 0) #\/))
(handle-cli-slash-command (getf msg :TEXT) stream)
(progn
(harness-log "CLI: Received input -> ~s" msg)
(inject-stimulus msg :stream stream))))))))

View File

@@ -32,16 +32,16 @@
(let ((msg (opencortex:read-framed-message *stream*)))
(cond ((eq msg :eof) (setf *is-running* nil))
((eq msg :error) (setf *status-text* "Protocol Error"))
((and (listp msg) (eq (getf msg :type) :EVENT))
(let ((payload (getf msg :payload)))
(when (eq (getf payload :action) :handshake)
((and (listp msg) (eq (getf msg :TYPE) :EVENT))
(let ((payload (getf msg :PAYLOAD)))
(when (eq (getf payload :ACTION) :handshake)
(setf *status-text* "Ready"))))
((and (listp msg) (eq (getf msg :type) :STATUS))
((and (listp msg) (eq (getf msg :TYPE) :STATUS))
(setf *status-text* (format nil "[Scribe: ~a] [Gardener: ~a]"
(getf msg :scribe)
(getf msg :gardener))))
((and (listp msg) (eq (getf msg :type) :CHAT))
(enqueue-msg (getf msg :text)))
(getf msg :SCRIBE)
(getf msg :GARDENER))))
((and (listp msg) (eq (getf msg :TYPE) :CHAT))
(enqueue-msg (getf msg :TEXT)))
(t (enqueue-msg (format nil "~s" msg))))))
(error (c) (setf *status-text* (format nil "Net Error: ~a" c)) (setf *is-running* nil)))
(sleep 0.05)))
@@ -96,7 +96,7 @@
(let ((cmd (coerce *input-buffer* 'string)))
(setf (fill-pointer *input-buffer*) 0)
(when (> (length cmd) 0)
(let ((framed (opencortex:frame-message (format nil "~s" (list :type :EVENT :payload (list :sensor :chat-message :text cmd))))))
(let ((framed (opencortex:frame-message (format nil "~s" (list :TYPE :EVENT :PAYLOAD (list :SENSOR :chat-message :TEXT cmd))))))
(format *stream* "~a" framed)
(finish-output *stream*)))
(when (string= cmd "/exit") (setf *is-running* nil))))

42
verify_response.py Normal file
View File

@@ -0,0 +1,42 @@
import socket, time, sys
def verify():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(20)
s.connect(("localhost", 9105))
# We need to read handshake and status first to clear the pipe
full_data = b""
while len(full_data) < 50: # Expecting at least handshake + status
chunk = s.recv(4096)
if not chunk: break
full_data += chunk
print(f"Data received: {full_data.decode()}")
# Send "Hi"
# Make sure we use the right length.
# (:TYPE :EVENT :PAYLOAD (:SENSOR :CHAT-MESSAGE :TEXT "Hi")) is 57 chars.
# Let s calculate it.
payload = '(:TYPE :EVENT :PAYLOAD (:SENSOR :CHAT-MESSAGE :TEXT "Hi"))'
length = len(payload)
msg = f"{length:06x}{payload}".encode()
print(f"Sending: {msg.decode()}")
s.sendall(msg)
# Read response
while True:
chunk = s.recv(4096)
if not chunk: break
print(f"Received chunk: {chunk.decode()}")
if ":CHAT" in chunk.decode() or "Neural Cascade Failure" in chunk.decode():
print("SUCCESS: Response received!")
break
s.close()
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
verify()