diff --git a/library/context.lisp b/library/context.lisp index 5fc3eda..c425fb5 100644 --- a/library/context.lisp +++ b/library/context.lisp @@ -42,7 +42,7 @@ (defun context-get-system-logs (&optional limit) "Retrieves the most recent lines from the harness's internal log." (let ((log-limit (or limit (ignore-errors (parse-integer (uiop:getenv "CONTEXT_LOG_LIMIT"))) 20))) - (bt:with-lock-held (*logs-lock*) + (bordeaux-threads:with-lock-held (*logs-lock*) (let ((count (min log-limit (length *system-logs*)))) (subseq *system-logs* 0 count))))) diff --git a/library/loop.lisp b/library/loop.lisp index fd0e903..d4fa14d 100644 --- a/library/loop.lisp +++ b/library/loop.lisp @@ -1,7 +1,7 @@ (in-package :opencortex) (defvar *interrupt-flag* nil) -(defvar *interrupt-lock* (bt:make-lock "harness-interrupt-lock")) +(defvar *interrupt-lock* (bordeaux-threads:make-lock "harness-interrupt-lock")) (defvar *heartbeat-thread* nil) (defun process-signal (signal) @@ -11,9 +11,9 @@ (let ((depth (getf current-signal :depth 0)) (meta (getf current-signal :meta))) (when (> depth 10) (harness-log "METABOLISM ERROR: Max depth reached.") (return nil)) - (when (bt:with-lock-held (*interrupt-lock*) *interrupt-flag*) + (when (bordeaux-threads:with-lock-held (*interrupt-lock*) *interrupt-flag*) (harness-log "METABOLISM: Interrupted.") - (bt:with-lock-held (*interrupt-lock*) (setf *interrupt-flag* nil)) + (bordeaux-threads:with-lock-held (*interrupt-lock*) (setf *interrupt-flag* nil)) (return nil)) (handler-case (progn @@ -52,7 +52,7 @@ (setf *auto-save-interval* auto-save) (setf *heartbeat-save-counter* 0) (setf *heartbeat-thread* - (bt:make-thread + (bordeaux-threads:make-thread (lambda () (loop (sleep interval) @@ -92,7 +92,7 @@ (let ((sleep-interval (or (ignore-errors (parse-integer (uiop:getenv "DAEMON_SLEEP_INTERVAL"))) 3600))) (loop - (when (bt:with-lock-held (*interrupt-lock*) *interrupt-flag*) + (when (bordeaux-threads:with-lock-held (*interrupt-lock*) *interrupt-flag*) (harness-log "SHUTDOWN: Interrupt flag set. Saving memory...") (when *shutdown-save-enabled* (save-memory-to-disk)) (return)) diff --git a/library/package.lisp b/library/package.lisp index c3286dd..a0c3091 100644 --- a/library/package.lisp +++ b/library/package.lisp @@ -120,38 +120,20 @@ (in-package :opencortex) -(defun proto-get (plist key) - "Robustly retrieves a value from a plist, checking both uppercase and lowercase keyword versions." - (let* ((s (string key)) - (up (intern (string-upcase s) :keyword)) - (dn (intern (string-downcase s) :keyword))) - (or (getf plist up) (getf plist dn)))) - -(in-package :opencortex) - -(defun proto-get (plist key) - "Robustly retrieves a value from a plist, checking both uppercase and lowercase keyword versions." - (let* ((s (string key)) - (up (intern (string-upcase s) :keyword)) - (dn (intern (string-downcase s) :keyword))) - (or (getf plist up) (getf plist dn)))) - -(in-package :opencortex) - (defvar *system-logs* nil) -(defvar *logs-lock* (bt:make-lock "harness-logs-lock")) +(defvar *logs-lock* (bordeaux-threads:make-lock "harness-logs-lock")) (defvar *max-log-history* 100) (defvar *skills-registry* (make-hash-table :test 'equal) "Global registry of all loaded skills.") (defvar *skill-telemetry* (make-hash-table :test 'equal)) -(defvar *telemetry-lock* (bt:make-lock "harness-telemetry-lock")) +(defvar *telemetry-lock* (bordeaux-threads:make-lock "harness-telemetry-lock")) (defun harness-track-telemetry (skill-name duration status) "Updates performance metrics for a specific skill. Status should be :success or :rejected." (when skill-name - (bt:with-lock-held (*telemetry-lock*) + (bordeaux-threads:with-lock-held (*telemetry-lock*) (let ((entry (or (gethash skill-name *skill-telemetry*) (list :executions 0 :total-time 0 :failures 0)))) (incf (getf entry :executions)) (incf (getf entry :total-time) duration) @@ -179,7 +161,7 @@ (defun harness-log (msg &rest args) "Centralized logging for the harness." (let ((formatted-msg (apply #'format nil msg args))) - (bt:with-lock-held (*logs-lock*) + (bordeaux-threads:with-lock-held (*logs-lock*) (push formatted-msg *system-logs*) (when (> (length *system-logs*) *max-log-history*) (setq *system-logs* (subseq *system-logs* 0 *max-log-history*)))) diff --git a/library/perceive.lisp b/library/perceive.lisp index aa5d18b..f34a2a8 100644 --- a/library/perceive.lisp +++ b/library/perceive.lisp @@ -19,7 +19,7 @@ (setf (getf raw-message :meta) meta) (if async-p - (bt:make-thread + (bordeaux-threads:make-thread (lambda () (restart-case (handler-bind ((error (lambda (c) (harness-log "ASYNC ERROR: ~a" c) (invoke-restart 'skip-event)))) (process-signal raw-message)) @@ -51,7 +51,7 @@ (setf *foveal-focus-id* (ignore-errors (getf element :id))) (ingest-ast element)))) (:interrupt - (bt:with-lock-held (*interrupt-lock*) (setf *interrupt-flag* t))))) + (bordeaux-threads:with-lock-held (*interrupt-lock*) (setf *interrupt-flag* t))))) ((eq type :RESPONSE) (harness-log "GATE [Perceive]: Act Result -> ~a" (getf payload :status)))) diff --git a/library/skills.lisp b/library/skills.lisp index 3738d58..30d004f 100644 --- a/library/skills.lisp +++ b/library/skills.lisp @@ -321,3 +321,44 @@ EXAMPLES: (multiple-value-bind (out err code) (uiop:run-program (list "bash" "-c" cmd) :output :string :error-output :string :ignore-error-status t) (format nil "EXIT-CODE: ~a~%~%STDOUT:~%~a~%~%STDERR:~%~a" code out err))))) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (def-cognitive-tool :reload-skill "Reloads a skill from its Org-mode source file." + ((:skill :type :string :description "The skill name")) + :guard (lambda (args context) + (declare (ignore context)) + (let ((skill (getf args :skill))) + (or (uiop:file-exists-p skill) + (let ((dir (or (ignore-errors (uiop:getenv "SKILLS_DIR")) + (namestring (user-homedir-pathname))))) + (uiop:file-exists-p (merge-pathnames (format nil "~a.org" skill) dir)))))) + :body (lambda (args) + (let ((skill (getf args :skill)) + (dir (or (ignore-errors (uiop:getenv "SKILLS_DIR")) + (namestring (user-homedir-pathname))))) + (let ((file (merge-pathnames (format nil "~a.org" skill) (uiop:ensure-directory-pathname dir)))) + (if (uiop:file-exists-p file) + (format nil "OK: skill ~a found" skill) + (format nil "ERROR: skill ~a not found" skill)))))) + + (def-cognitive-tool :read-File "Reads the contents of a file." + ((:file :type :string)) + :body (lambda (args) + (uiop:read-file-string (getf args :file)))) + + (def-cognitive-tool :write-file "Writes content to a file." + ((:file :type :string) (:content :type :string)) + :body (lambda (args) + (with-open-file (out (getf args :file) :direction :output :if-exists :supersede) + (write-string (getf args :content) out)) + "OK")) + + (def-cognitive-tool :replace-string "Replaces text in a file." + ((:file :type :string) (:old :type :string) (:new :type :string)) + :body (lambda (args) + (let ((content (uiop:read-file-string (getf args :file)))) + (setf content (cl-ppcre:regex-replace-all (cl-ppcre:quote-meta-chars (getf args :old)) content (getf args :new))) + (with-open-file (out (getf args :file) :direction :output :if-exists :supersede) + (write-string content out)) + "OK"))) +) diff --git a/opencortex.asd b/opencortex.asd index 9831c32..43eb5cc 100644 --- a/opencortex.asd +++ b/opencortex.asd @@ -5,7 +5,6 @@ :license "AGPLv3" :description "The Probabilistic-Deterministic Lisp Machine Harness" :depends-on (:usocket :bordeaux-threads :dexador :uiop :cl-dotenv :cl-ppcre :hunchentoot :ironclad :str :cl-json :uuid) - :serial t :components ((:file "library/package") (:file "library/skills") (:file "library/communication")