#+TITLE: Skill: Gateway Manager (org-skill-gateway-manager.org) #+AUTHOR: Agent #+FILETAGS: :skill:setup:gateway: #+STARTUP: content * Overview The *Gateway Manager* skill provides the OpenCortex Agent with the capability to manage its own external communication channels (Gateways). * Phase A: Demand (Thinking) ** Architectural Invariant: Self-Linking In a traditional AI wrapper, the user manually edits a config file to add a bot token. In OpenCortex, the Agent should be able to say: "I have verified the Telegram token and successfully linked our connection." * Phase B: Protocol (Success Criteria) ** Test Suite Context #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/gateway-manager-tests.lisp" (expand-file-name "")) (defpackage :opencortex-gateway-manager-tests (:use :cl :fiveam :opencortex) (:export #:gateway-suite)) #+end_src #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/gateway-manager-tests.lisp" (expand-file-name "")) (in-package :opencortex-gateway-manager-tests) #+end_src #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/gateway-manager-tests.lisp" (expand-file-name "")) (def-suite gateway-suite :description "Verification of the Gateway Manager skill") #+end_src #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/gateway-manager-tests.lisp" (expand-file-name "")) (in-suite gateway-suite) #+end_src ** Logic Tests #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/gateway-manager-tests.lisp" (expand-file-name "")) (test test-gateway-registration "Verify that the skill can register a new gateway metadata block." (let ((opencortex::*gateways* nil)) (opencortex:skill-gateway-register :telegram '(:status :unverified)) (is (getf (getf opencortex::*gateways* :telegram) :status)))) (test test-gateway-multiple-platforms "Verify that multiple gateways can be registered simultaneously." (let ((opencortex::*gateways* nil)) (opencortex:skill-gateway-register :telegram '(:status :verified :token "abc123")) (opencortex:skill-gateway-register :signal '(:status :unverified)) (is (eq (getf (getf opencortex::*gateways* :telegram) :status) :verified)) (is (eq (getf (getf opencortex::*gateways* :signal) :status) :unverified)))) #+end_src * Phase C: Implementation (Build) ** Package Context #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/org-skill-gateway-manager.lisp" (expand-file-name "")) (in-package :opencortex) #+end_src ** Capability Definition #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/org-skill-gateway-manager.lisp" (expand-file-name "")) (defparameter *skill-gateway-manager* '(:name "gateway-manager" :description "Manages connections to external chat platforms." :capabilities (:link-gateway :list-gateways) :type :deterministic) "Skill metadata for the Gateway Manager.") #+end_src ** Registry Persistence #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/org-skill-gateway-manager.lisp" (expand-file-name "")) (defvar *gateways* nil "The internal registry of configured gateways.") #+end_src ** Persistence Stubs #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/org-skill-gateway-manager.lisp" (expand-file-name "")) (defun save-gateways () "Persist gateway metadata to XDG Config directory." (let ((path (merge-pathnames "gateways.lisp" (get-oc-config-dir)))) (ensure-directories-exist path) (with-open-file (s path :direction :output :if-exists :supersede) (format s ";;; OpenCortex Gateway Registry~%~s~%" *gateways*)))) #+end_src ** Registration Logic #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/org-skill-gateway-manager.lisp" (expand-file-name "")) (defun skill-gateway-register (platform metadata) "Internal function to update the gateway registry." (setf (getf *gateways* platform) metadata)) #+end_src ** Telegram Verification #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/org-skill-gateway-manager.lisp" (expand-file-name "")) (defun skill-gateway-verify-telegram (token) "Verifies a Telegram bot token via the getMe API." (let ((url (format nil "https://api.telegram.org/bot~a/getMe" token))) (handler-case (let* ((response (dex:get url)) (data (cl-json:decode-json-from-string response))) (if (cdr (assoc :ok data)) (let ((result (cdr (assoc :result data)))) (list :status :verified :username (cdr (assoc :username result)))) (list :status :failed :error "Invalid Token"))) (error (c) (list :status :failed :error (format nil "~a" c)))))) #+end_src ** Linkage Command #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/org-skill-gateway-manager.lisp" (expand-file-name "")) (defun skill-gateway-link (platform token) "Primary capability to link a new platform. Returns status plist." (harness-log "GATEWAY: Attempting to link ~a..." platform) (let ((verification (cond ((eq platform :telegram) (skill-gateway-verify-telegram token)) (t (list :status :verified :info "Platform verification pending implementation"))))) (if (eq (getf verification :status) :verified) (progn (save-secret platform :token token) (skill-gateway-register platform verification) (save-gateways) (list :status :success :platform platform :info verification)) (list :status :error :reason (getf verification :error))))) #+end_src ** CLI Main Wrapper #+begin_src lisp :tangle (concat (getenv "INSTALL_DIR") "/skills/org-skill-gateway-manager.lisp" (expand-file-name "")) (defun gateway-manager-main (platform token) "Main entry point for CLI-driven linkage." (if (and platform token) (let ((result (skill-gateway-link (intern (string-upcase platform) :keyword) token))) (format t "RESULT: ~s~%" result) (uiop:quit 0)) (progn (format t "Usage: opencortex link ~%") (uiop:quit 1)))) #+end_src