Files
passepartout/skills/org-skill-config-manager.lisp
Amr Gharbeia fc0c069d65 tests: Add FiveAM tests for v0.2.0 completion
Self-edit: 5 new tests (apply success/not-found/file-not-found, parse-location x2)
Config-manager: 4 new tests (get-oc-config-dir, save-providers, configure-provider)
Gateway-manager: 2 new tests (multiple-platforms, registration)

Tier 1 Chaos: Verified org files pass structural balance
Note: Some tests have issues - config tests use functions not exported, one self-edit test has search function issue. Pre-existing test failures in LITERATE-PROGRAMMING (2) and DIAGNOSTICS (1).
2026-04-28 15:19:49 -04:00

97 lines
4.5 KiB
Common Lisp

(in-package :opencortex)
(defparameter *skill-config-manager*
'(:name "config-manager"
:description "Manages system settings and LLM provider configurations."
:capabilities (:configure-provider :run-setup-wizard)
:type :deterministic)
"Skill metadata for the Config Manager.")
(defvar *provider-templates*
'((:ollama . (:name "Ollama (Local)" :fields ((:url :label "URL") (:model :label "Model")) :default-url "http://localhost:11434" :default-model "llama3"))
(:openrouter . (:name "OpenRouter" :fields ((:key :label "API Key" :secret t) (:model :label "Model")) :default-model "anthropic/claude-3-opus-20240229"))
(:openai . (:name "OpenAI" :fields ((:key :label "API Key" :secret t) (:model :label "Model")) :default-model "gpt-4-turbo"))
(:groq . (:name "Groq" :fields ((:key :label "API Key" :secret t) (:model :label "Model")) :default-model "mixtral-8x7b-32768"))
(:gemini . (:name "Google Gemini" :fields ((:key :label "API Key" :secret t) (:model :label "Model")) :default-model "gemini-1.5-pro"))
(:anthropic . (:name "Anthropic" :fields ((:key :label "API Key" :secret t) (:model :label "Model")) :default-model "claude-3-5-sonnet-20240620")))
"Templates for supported LLM providers.")
(defvar *providers* nil "Global registry of configured LLM providers.")
(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)))
(defun register-provider (id config)
"Update the global provider registry."
(setf (getf *providers* id) config))
(defun configure-provider (id)
"Guided configuration for a specific LLM provider template."
(let* ((template (cdr (assoc id *provider-templates*)))
(fields (getf template :fields))
(config nil))
(format t "~%--- Configuring ~a ---~%" (getf template :name))
(dolist (field-spec fields)
(let* ((field (first field-spec))
(label (getf (rest field-spec) :label))
(is-secret (getf (rest field-spec) :secret))
(default-key (intern (format nil "DEFAULT-~a" field) :keyword))
(default (getf template default-key))
(val (prompt-for label default)))
(if is-secret
(save-secret id field val)
(setf (getf config field) val))))
(register-provider id config)
(format t "✓ ~a metadata registered.~%" (getf template :name))))
(defun run-setup-wizard ()
"Entry point for the interactive OpenCortex Lisp Setup Wizard."
(format t "=== OpenCortex: Advanced Setup Wizard ===~%")
(let ((user (prompt-for "Your Name" "User"))
(agent (prompt-for "Agent Name" "OpenCortex")))
(format t "Welcome, ~a. I am ~a.~%" user agent))
(format t "~%Available Providers:~%")
(loop for (id . data) in *provider-templates* do (format t " ~a: ~a~%" id (getf data :name)))
(format t "~%Enter provider IDs to configure (comma separated, or 'all'): ")
(finish-output)
(let* ((input (read-line))
(ids (if (string= input "all")
(mapcar #'car *provider-templates*)
(mapcar (lambda (s) (intern (string-upcase (string-trim " " s)) :keyword))
(uiop:split-string input :separator ",")))))
(dolist (id ids)
(when (assoc id *provider-templates*)
(configure-provider id))))
(save-providers)
(format t "~%Setup complete. Running diagnostics...~%")
(doctor-run-all))