fix(v0.2.0): resolve macro conflicts, sync load order, and fix skill packaging
- Standardized def-cognitive-tool to 5-argument signature. - Consolidated *cognitive-tools* as a hash table in package.lisp. - Removed skills from opencortex.asd to enforce dynamic Skill Engine loading. - Added missing (in-package :opencortex) to various skill files. - Fixed let/let* sequential binding issues in emacs-edit and self-edit. - Updated opencortex.sh to initialize skills before running doctor. - Fixed uiop:user-homedir-pathname usage in config-manager.
This commit is contained in:
@@ -400,18 +400,8 @@ EXAMPLES:
|
||||
#+begin_src lisp
|
||||
** Cognitive Tool Registration
|
||||
#+begin_src lisp :tangle (expand-file-name "skills.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/harness"))
|
||||
(defvar *cognitive-tools* nil "Registry of available Agent capabilities.")
|
||||
|
||||
(defmacro def-cognitive-tool (name arg-list &body body)
|
||||
"Registers a new cognitive tool (capability) into the global registry."
|
||||
`(setf (getf *cognitive-tools* ,name)
|
||||
(list :args ',arg-list
|
||||
:executor (lambda (args)
|
||||
(let ,(mapcar (lambda (arg)
|
||||
(let ((arg-name (if (listp arg) (first arg) arg)))
|
||||
`(,arg-name (getf args ,(intern (string arg-name) :keyword)))))
|
||||
arg-list)
|
||||
,@body)))))
|
||||
;; Cognitive tools are registered in *cognitive-tools* (defined in package.lisp)
|
||||
;; using the def-cognitive-tool macro.
|
||||
#+end_src
|
||||
|
||||
(def-cognitive-tool :eval "Evaluates raw Common Lisp code in the harness image. Use this for complex calculations or internal state inspection."
|
||||
|
||||
@@ -18,23 +18,7 @@
|
||||
(:file "harness/perceive")
|
||||
(:file "harness/reason")
|
||||
(:file "harness/act")
|
||||
(:file "harness/loop")
|
||||
|
||||
(:file "skills/org-skill-policy")
|
||||
(:file "skills/org-skill-bouncer")
|
||||
(:file "skills/org-skill-scribe")
|
||||
(:file "skills/org-skill-gardener")
|
||||
(:file "skills/org-skill-lisp-utils")
|
||||
(:file "skills/org-skill-literate-programming")
|
||||
(:file "skills/org-skill-engineering-standards")
|
||||
(:file "skills/org-skill-self-edit")
|
||||
(:file "skills/org-skill-emacs-edit")
|
||||
(:file "skills/org-skill-tool-permissions")
|
||||
(:file "skills/org-skill-self-fix")
|
||||
(:file "skills/org-skill-peripheral-vision")
|
||||
(:file "skills/org-skill-gateway-manager")
|
||||
(:file "skills/org-skill-diagnostics")
|
||||
(:file "skills/org-skill-config-manager"))
|
||||
(:file "harness/loop"))
|
||||
|
||||
:build-operation "program-op"
|
||||
:build-pathname "opencortex-server"
|
||||
|
||||
@@ -99,6 +99,7 @@ case "$COMMAND" in
|
||||
--eval '(load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))' \
|
||||
--eval "(push (truename \"$OC_DATA_DIR/\") asdf:*central-registry*)" \
|
||||
--eval '(ql:quickload :opencortex)' \
|
||||
--eval '(opencortex:initialize-all-skills)' \
|
||||
--eval '(opencortex:doctor-main)'
|
||||
;;
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ The *CLI Gateway* is the primary sensory and actuating interface for human inter
|
||||
* Implementation
|
||||
|
||||
#+begin_src lisp
|
||||
(in-package :opencortex)
|
||||
|
||||
(defvar *cli-port* 9105)
|
||||
(defvar *cli-server-socket* nil)
|
||||
|
||||
@@ -75,15 +75,38 @@ Secrets are appended to `~/.config/opencortex/.env`, while structural metadata i
|
||||
** Registry Persistence
|
||||
#+begin_src lisp :tangle (expand-file-name "org-skill-config-manager.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/skills"))
|
||||
(defvar *providers* nil "Global registry of configured LLM providers.")
|
||||
#+end_src
|
||||
|
||||
#+begin_src lisp :tangle (expand-file-name "org-skill-config-manager.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/skills"))
|
||||
(defun get-oc-config-dir ()
|
||||
"Returns the XDG-compliant config directory for OpenCortex."
|
||||
(let ((env (uiop:getenv "OC_CONFIG_DIR")))
|
||||
(if (and env (> (length env) 0))
|
||||
(uiop:ensure-directory-pathname env)
|
||||
(uiop:merge-pathnames* ".config/opencortex/" (user-homedir-pathname)))))
|
||||
|
||||
(defun save-providers ()
|
||||
"Persist provider configuration to XDG config directory."
|
||||
(let ((path (merge-pathnames "providers.lisp" (get-oc-config-dir))))
|
||||
(ensure-directories-exist path)
|
||||
(with-open-file (s path :direction :output :if-exists :supersede)
|
||||
(format s ";;; OpenCortex Provider Metadata~%~s~%" *providers*))))
|
||||
|
||||
(defun prompt-for (label &optional default)
|
||||
"Prompts the user for input on the CLI."
|
||||
(format t "~a~@[ [~a]~]: " label default)
|
||||
(finish-output)
|
||||
(let ((input (read-line)))
|
||||
(if (string= input "")
|
||||
(or default "")
|
||||
input)))
|
||||
|
||||
(defun save-secret (provider field val)
|
||||
"Appends a secret to the XDG .env file."
|
||||
(let ((env-file (merge-pathnames ".env" (get-oc-config-dir)))
|
||||
(var-name (format nil "~:@(~a_~a~)" provider field)))
|
||||
(ensure-directories-exist env-file)
|
||||
(with-open-file (out env-file :direction :output :if-exists :append :if-does-not-exist :create)
|
||||
(format out "~a=~a~%" var-name val))
|
||||
(setf (uiop:getenv var-name) val)))
|
||||
#+end_src
|
||||
|
||||
** Registry API
|
||||
|
||||
@@ -89,10 +89,10 @@ Converts AST back to org format, preserving structure.
|
||||
(defun emacs-edit-print-headline (ast &key indent-level)
|
||||
"Converts a HEADLINE AST node to org text.
|
||||
INDENT-LEVEL is number of leading asterisks."
|
||||
(let ((level (or indent-level 1))
|
||||
(stars (make-string level :initial-element #\*))
|
||||
(title (or (getf (getf ast :properties) :TITLE) ""))
|
||||
(todo (getf (getf ast :properties) :TODO)))
|
||||
(let* ((level (or indent-level 1))
|
||||
(stars (make-string level :initial-element #\*))
|
||||
(title (or (getf (getf ast :properties) :TITLE) ""))
|
||||
(todo (getf (getf ast :properties) :TODO)))
|
||||
(format nil "~a ~a~%~a"
|
||||
stars
|
||||
(if todo (format nil "[~a] " (string-upcase todo)) "")
|
||||
@@ -200,17 +200,17 @@ Add a new headline to an existing AST.
|
||||
(defun emacs-edit-add-headline (ast title &key todo properties)
|
||||
"Adds a new headline to AST.
|
||||
Returns modified AST."
|
||||
(let ((new-id (emacs-edit-generate-id))
|
||||
(new-props (list :ID new-id
|
||||
:TITLE title
|
||||
:TODO (or todo "TODO")
|
||||
:CREATED (format nil "[~a]"
|
||||
(multiple-value-bind (s mi h d mo y)
|
||||
(decode-universal-time (get-universal-time))
|
||||
(format nil "~a-~a-~a ~a:~a"
|
||||
y mo d h mi)))))
|
||||
(merged-props (loop for (k v) on properties by #'cddr
|
||||
collect k collect v)))
|
||||
(let* ((new-id (emacs-edit-generate-id))
|
||||
(new-props (list :ID new-id
|
||||
:TITLE title
|
||||
:TODO (or todo "TODO")
|
||||
:CREATED (format nil "[~a]"
|
||||
(multiple-value-bind (s mi h d mo y)
|
||||
(decode-universal-time (get-universal-time))
|
||||
(format nil "~a-~a-~a ~a:~a"
|
||||
y mo d h mi)))))
|
||||
(merged-props (loop for (k v) on properties by #'cddr
|
||||
collect k collect v)))
|
||||
|
||||
(setf merged-props (append merged-props new-props))
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ The *Homoiconic Memory* skill provides the core persistence layer for OpenCortex
|
||||
* Implementation
|
||||
|
||||
#+begin_src lisp
|
||||
(in-package :opencortex)
|
||||
|
||||
(defun memory-org-to-json (source)
|
||||
"Converts Org-mode source to JSON AST."
|
||||
|
||||
@@ -49,23 +49,33 @@ The *LLM Gateway* skill provides a unified interface for interacting with multip
|
||||
|
||||
** Cognitive Tools
|
||||
#+begin_src lisp :tangle (expand-file-name "org-skill-llm-gateway.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/skills"))
|
||||
(def-cognitive-tool :get-ollama-embedding (text)
|
||||
(let* ((host (or (uiop:getenv "OLLAMA_HOST") "localhost:11434"))
|
||||
(url (format nil "http://~a/api/embeddings" host))
|
||||
(body (cl-json:encode-json-to-string `((model . "nomic-embed-text") (prompt . ,text)))))
|
||||
(handler-case
|
||||
(let* ((response (dex:post url :headers '(("Content-Type" . "application/json")) :content body))
|
||||
(json (cl-json:decode-json-from-string response)))
|
||||
(cdr (assoc :embedding json)))
|
||||
(error (c) (harness-log "OLLAMA EMBED ERROR: ~a" c) nil))))
|
||||
(def-cognitive-tool :get-ollama-embedding
|
||||
"Generates vector embeddings via Ollama API."
|
||||
((:text :type :string :description "Text to embed."))
|
||||
:body (lambda (args)
|
||||
(let ((text (getf args :text)))
|
||||
(let* ((host (or (uiop:getenv "OLLAMA_HOST") "localhost:11434"))
|
||||
(url (format nil "http://~a/api/embeddings" host))
|
||||
(body (cl-json:encode-json-to-string `((model . "nomic-embed-text") (prompt . ,text)))))
|
||||
(handler-case
|
||||
(let* ((response (dex:post url :headers '(("Content-Type" . "application/json")) :content body))
|
||||
(json (cl-json:decode-json-from-string response)))
|
||||
(cdr (assoc :embedding json)))
|
||||
(error (c) (harness-log "OLLAMA EMBED ERROR: ~a" c) nil))))))
|
||||
#+end_src
|
||||
|
||||
#+begin_src lisp :tangle (expand-file-name "org-skill-llm-gateway.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/skills"))
|
||||
(def-cognitive-tool :ask-llm (prompt system-prompt provider model)
|
||||
(execute-llm-request :prompt prompt
|
||||
:system-prompt system-prompt
|
||||
:provider provider
|
||||
:model model))
|
||||
(def-cognitive-tool :ask-llm
|
||||
"Unified interface for interacting with LLM providers."
|
||||
((:prompt :type :string :description "The user prompt")
|
||||
(:system-prompt :type :string :description "The system prompt (optional)")
|
||||
(:provider :type :keyword :description "The provider (e.g., :ollama, :openai)")
|
||||
(:model :type :string :description "The model name"))
|
||||
:body (lambda (args)
|
||||
(execute-llm-request :prompt (getf args :prompt)
|
||||
:system-prompt (getf args :system-prompt)
|
||||
:provider (getf args :provider)
|
||||
:model (getf args :model))))
|
||||
#+end_src
|
||||
|
||||
** Skill Registration
|
||||
|
||||
@@ -37,6 +37,13 @@ Fast paren balancing for syntax errors.
|
||||
(concatenate 'string code (make-string (- opens closes) :initial-element #\))))
|
||||
((> closes opens)
|
||||
(concatenate 'string (make-string (- closes opens) :initial-element #\() code)))))
|
||||
|
||||
(defun copy-hash-table (table)
|
||||
"Returns a shallow copy of a hash table."
|
||||
(let ((new-table (make-hash-table :test (hash-table-test table)
|
||||
:size (hash-table-count table))))
|
||||
(maphash (lambda (k v) (setf (gethash k new-table) v)) table)
|
||||
new-table))
|
||||
#+end_src
|
||||
|
||||
** Parse Target Location
|
||||
@@ -152,8 +159,8 @@ Provide a fixed version of the code as a lisp form.")
|
||||
"Balances parentheses in a code string."
|
||||
((:code :type :string :description "The code to balance"))
|
||||
:body (lambda (args)
|
||||
(let ((code (getf args :code))
|
||||
(balanced (self-edit-balance-parens code)))
|
||||
(let* ((code (getf args :code))
|
||||
(balanced (self-edit-balance-parens code)))
|
||||
(handler-case
|
||||
(progn
|
||||
(read-from-string balanced)
|
||||
|
||||
@@ -12,7 +12,8 @@ The *Shell Actuator* provides a controlled interface for the OpenCortex to execu
|
||||
|
||||
* Implementation
|
||||
|
||||
#+begin_src lisp
|
||||
#+begin_src lisp :tangle (expand-file-name "org-skill-shell-actuator.lisp" (concat (or (getenv "INSTALL_DIR") ".") "/skills"))
|
||||
(in-package :opencortex)
|
||||
|
||||
(defparameter *allowed-commands* '("ls" "git" "rg" "grep" "date" "echo" "cat" "node" "python3" "sbcl"))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user