summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/ai-config.el62
1 files changed, 42 insertions, 20 deletions
diff --git a/modules/ai-config.el b/modules/ai-config.el
index d8e73cf9..651acc74 100644
--- a/modules/ai-config.el
+++ b/modules/ai-config.el
@@ -118,38 +118,60 @@ Ensures gptel and backends are initialized."
((symbolp m) (symbol-name m))
(t (format "%s" m))))
-;; Backend/model switching commands (moved out of use-package so they are commandp)
+;; Backend/model switching helpers (pure logic, extracted for testability)
+
+(defun cj/gptel--build-model-list (backends model-fn)
+ "Build a flat list of all models across BACKENDS.
+BACKENDS is an alist of (NAME . BACKEND-OBJECT). MODEL-FN is called
+with each backend object and should return a list of model identifiers.
+Returns a list of entries: (DISPLAY-STRING BACKEND MODEL-STRING BACKEND-NAME)
+where DISPLAY-STRING is \"Backend: model\" for use in completing-read."
+ (mapcan
+ (lambda (pair)
+ (let* ((backend-name (car pair))
+ (backend (cdr pair))
+ (models (funcall model-fn backend)))
+ (mapcar (lambda (m)
+ (list (format "%s: %s" backend-name (cj/gptel--model-to-string m))
+ backend
+ (cj/gptel--model-to-string m)
+ backend-name))
+ models)))
+ backends))
+
+(defun cj/gptel--current-model-selection (backends current-backend current-model)
+ "Format the current backend/model as a display string.
+BACKENDS is the alist from `cj/gptel--available-backends'.
+CURRENT-BACKEND and CURRENT-MODEL are the active gptel settings.
+Returns a string like \"Anthropic - Claude: claude-opus-4-6\"."
+ (let ((backend-name (car (rassoc current-backend backends))))
+ (format "%s: %s"
+ (or backend-name "AI")
+ (cj/gptel--model-to-string current-model))))
+
+;; Backend/model switching commands
(defun cj/gptel-change-model ()
"Change the GPTel backend and select a model from that backend.
Present all available models from every backend, switching backends when
necessary. Prompt for whether to apply the selection globally or buffer-locally."
(interactive)
(let* ((backends (cj/gptel--available-backends))
- (all-models
- (mapcan
- (lambda (pair)
- (let* ((backend-name (car pair))
- (backend (cdr pair))
- (models (when (fboundp 'gptel-backend-models)
- (gptel-backend-models backend))))
- (mapcar (lambda (m)
- (list (format "%s: %s" backend-name (cj/gptel--model-to-string m))
- backend
- (cj/gptel--model-to-string m)
- backend-name))
- models)))
- backends))
- (current-backend-name (car (rassoc (bound-and-true-p gptel-backend) backends)))
- (current-selection (format "%s: %s"
- (or current-backend-name "AI")
- (cj/gptel--model-to-string (bound-and-true-p gptel-model))))
+ (all-models (cj/gptel--build-model-list
+ backends
+ (lambda (b)
+ (when (fboundp 'gptel-backend-models)
+ (gptel-backend-models b)))))
+ (current-selection (cj/gptel--current-model-selection
+ backends
+ (bound-and-true-p gptel-backend)
+ (bound-and-true-p gptel-model)))
(scope (completing-read "Set model for: " '("buffer" "global") nil t))
(selected (completing-read
(format "Select model (current: %s): " current-selection)
(mapcar #'car all-models) nil t nil nil current-selection)))
(let* ((model-info (assoc selected all-models))
(backend (nth 1 model-info))
- (model (intern (nth 2 model-info))) ;; Convert string to symbol
+ (model (intern (nth 2 model-info)))
(backend-name (nth 3 model-info)))
(if (string= scope "global")
(progn