#+TITLE: SKILL: Emacs Bridge Agent (Universal Literate Note) #+ID: skill-emacs-bridge #+STARTUP: content #+FILETAGS: :bridge:emacs:io:system:psf: * Overview The *Emacs Bridge Agent* is the primary sensory and motor interface to Emacs. It abstracts TCP socket management, allowing the core kernel to interact with buffers as native data structures. * Phase A: Demand (PRD) :PROPERTIES: :STATUS: FROZEN :END: ** 1. Purpose Define the transport layer for Org-Agent Communication Protocol (OACP). ** 2. User Needs - *Isolation:* Kernel remains transport-agnostic. - *Persistence:* Multi-client server support for simultaneous sessions. - *Dispatch:* Reliable routing of actions to actuators and sensors to the kernel. ** 3. Success Criteria *** TODO Socket Listener Initialization *** TODO Multi-client Connection Handling *** TODO OACP Message Framing Verification * Phase B: Blueprint (PROTOCOL) :PROPERTIES: :STATUS: SIGNED :END: ** 1. Architectural Intent Interfaces for TCP I/O and protocol framing. Source of truth is the OACP specification. ** 2. Semantic Interfaces #+begin_src lisp (defun start-emacs-server (&key (port 9105)) "Starts the OACP listener.") (defun broadcast-to-emacs (action-plist) "Sends a framed message to all connected clients.") #+end_src * Phase D: Build (Implementation) ** TCP Sensory Layer #+begin_src lisp :tangle ../projects/org-skill-emacs-bridge/src/bridge-logic.lisp (defun handle-emacs-client (stream) ;; Logic for parsing length-prefixed OACP messages (format nil "Handling client on stream: ~a" stream)) #+end_src ** Outbound Actuation #+begin_src lisp :tangle ../projects/org-skill-emacs-bridge/src/bridge-logic.lisp (defun stream-to-emacs (stream action-plist) "Streams a chunk of data to a specific Emacs client over OACP using framing." (let* (;; Ensure the message is wrapped in a :request envelope if it's just an action (envelope (if (getf action-plist :type) action-plist (list :type :request :id (get-universal-time) :target (getf action-plist :target) :payload (getf action-plist :payload)))) (msg (prin1-to-string envelope)) (len (length msg)) (framed (format nil "~6,'0x~a" len msg))) (write-string framed stream) (finish-output stream))) (defun broadcast-to-emacs (action-plist context) "Sends a framed message back to the client that sent the stimulus." (let ((stream (getf context :reply-stream))) (if stream (handler-case (stream-to-emacs stream action-plist) (error (c) (kernel-log "BRIDGE ERROR: Failed to write to Emacs: ~a" c))) (kernel-log "BRIDGE ERROR: No reply-stream in context.")))) #+end_src * Registration #+begin_src lisp (org-agent:register-actuator :emacs #'broadcast-to-emacs) (defskill :skill-emacs-bridge :priority 100 :trigger (lambda (context) nil) :neuro (lambda (context) nil) :symbolic (lambda (action context) action)) #+end_src