branch: elpa/aidermacs commit 30d89248de27411bc85a1b750d317adbc050f83d Author: Mingde (Matthew) Zeng <matthew...@posteo.net> Commit: Mingde (Matthew) Zeng <matthew...@posteo.net>
Rewrite aidermacs-models to support aider 0.78.0 and xai Signed-off-by: Mingde (Matthew) Zeng <matthew...@posteo.net> --- README.md | 30 ++++++++++++++- aidermacs-models.el | 104 ++++++++++++++++++++++++++++++---------------------- aidermacs.el | 5 ++- 3 files changed, 92 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index b4eeae2a69..5807dadf0f 100644 --- a/README.md +++ b/README.md @@ -147,11 +147,37 @@ When Architect mode is enabled, the `aidermacs-default-model` setting is ignored ```emacs-lisp (setq aidermacs-use-architect-mode t) -;; Both default to aidermacs-default-model +``` +You can switch to it persistently by `M-x aidermacs-switch-to-architect-mode` (`3` in `aidermacs-transient-menu`), or temporarily with `M-x aidermacs-architect-this-code` (`r` in `aidermacs-transient-menu`). + +You can configure each model independently: +```emacs-lisp +;; Architect model for reasoning (defaults to aidermacs-default-model) (setq aidermacs-architect-model "sonnet") + +;; Editor model for code generation (defaults to aidermacs-default-model) (setq aidermacs-editor-model "deepseek/deepseek-chat") ``` +The model hierarchy works as follows: +- When Architect mode is enabled, `aidermacs-default-model` is ignored +- The Architect model handles high-level reasoning and solution design +- The Editor model executes the actual code changes +- You can configure both models independently or let them default to `aidermacs-default-model` + +*Note: These configurations will be overwritten by the existence of an `.aider.conf.yml` file (see [details](#Overwrite-Configuration-with-Configuration-File)).* + +### Customize Weak Model + +The Weak model is used for commit messages (if you have `aidermacs-auto-commits` set to `t`) and chat history summarization (default depends on –model). You can customize it using + +```emacs-lisp +;; default to nil +(setq aidermacs-weak-model "deepseek/deepseek-chat") +``` + +You can change the Weak model during a session by using `C-u o` (`aidermacs-change-model` with a prefix argument). In most cases, you won't need to change this as Aider will automatically select an appropriate Weak model based on your main model. + *Note: These configurations will be overwritten by the existence of an `.aider.conf.yml` file (see [details](#Overwrite-Configuration-with-Configuration-File)).* #### Architect Mode Confirmation @@ -246,7 +272,7 @@ With auto-commits disabled, you must manually commit changes using your preferre *Note: This configuration will be overwritten by the existence of an `.aider.conf.yml` file (see [details](#Overwrite-Configuration-with-Configuration-File)).* -### Customizing Aider Options with `aidermacs-extra-args` +### Customize Aider Options with `aidermacs-extra-args` If these configurations aren't sufficient, the `aidermacs-extra-args` variable enables passing any Aider-supported command-line options. diff --git a/aidermacs-models.el b/aidermacs-models.el index 0fe443c65d..1dcbfe1398 100644 --- a/aidermacs-models.el +++ b/aidermacs-models.el @@ -31,9 +31,11 @@ (declare-function aidermacs--send-command "aidermacs") (declare-function aidermacs-buffer-name "aidermacs") (declare-function aidermacs-exit "aidermacs") +(declare-function aidermacs-aider-version "aidermacs") (defvar aidermacs--current-output) (defvar aidermacs-use-architect-mode) +(defvar aidermacs--current-mode) (defgroup aidermacs-models nil "Model selection for Aidermacs." @@ -53,18 +55,13 @@ Defaults to `aidermacs-default-model' if not explicitly set." Defaults to `aidermacs-default-model' if not explicitly set." :type 'string) -(defcustom aidermacs-popular-models - '("sonnet" - "o1-mini" - "gemini/gemini-2.0-flash" - "r1" - "deepseek/deepseek-chat") - "List of available AI models for selection. -Each model should be in the format expected by the aidermacs CLI. -Also based on aidermacs LLM benchmark: https://aidermacs.chat/docs/leaderboards/" - :type '(repeat string)) - -(defvar aidermacs--cached-models aidermacs-popular-models +(defcustom aidermacs-weak-model nil + "Default weak AI model to use. +This is the model to use for commit messages and chat history summarization. +When nil, Aider sets it automatically based on the default model." + :type 'string) + +(defvar aidermacs--cached-models nil "Cache of available AI models.") (defconst aidermacs--api-providers @@ -159,14 +156,38 @@ API provider." (alist-get 'name model)))))) models)))))) -(defun aidermacs--select-model () - "Provide model selection with completion. -This is a private function used internally." - (condition-case nil - (let ((model (completing-read "Select AI model: " aidermacs--cached-models nil t))) - (when model - (aidermacs--send-command (format "/model %s" model)))) - (quit (message "Model selection cancelled")))) +(defun aidermacs--select-model (&optional set-weak-model) + "Provide model selection with completion, handling main/weak/editor models. +When SET-WEAK-MODEL is non-nil, only allow setting the weak model." + (let ((buf (get-buffer (aidermacs-get-buffer-name t)))) + (unless buf + (user-error "No active aidermacs session")) + (with-current-buffer buf + (condition-case nil + (let* ((aider-version (aidermacs-aider-version)) + (supports-specific-model (version<= "0.78.0" aider-version)) + (is-architect-mode (and (eq aidermacs--current-mode 'architect) supports-specific-model)) + (set-weak-model (and set-weak-model supports-specific-model)) + (model-type + (cond + (set-weak-model "Weak Model") + (is-architect-mode + (completing-read + "Select model type: " + '("Main/Reasoning Model" "Editing Model") + nil t)) + (t "Main Model"))) + (model (completing-read (format "Select %s: " model-type) aidermacs--cached-models nil t))) + (when model + (cond + (set-weak-model + (aidermacs--send-command (format "/weak-model %s" model))) + ((and is-architect-mode supports-specific-model) + (pcase model-type + ("Main/Reasoning Model" (aidermacs--send-command (format "/model %s" model))) + ("Editing Model" (aidermacs--send-command (format "/editor-model %s" model))))) + (t (aidermacs--send-command (format "/model %s" model)))))) + (quit (message "Model selection cancelled")))))) (defun aidermacs--get-available-models () "Get list of models supported by aider using the /models command. @@ -174,16 +195,14 @@ This fetches models from various API providers and caches them." (aidermacs--send-command "/models /" nil nil t (lambda () - (let* ((supported-models - (seq-filter - (lambda (line) - (string-prefix-p "- " line)) - (split-string aidermacs--current-output "\n" t))) - (models nil)) - (setq supported-models + (let* ((all-models (mapcar (lambda (line) (substring line 2)) ; Remove "- " prefix - supported-models)) + (seq-filter + (lambda (line) + (string-prefix-p "- " line)) + (split-string aidermacs--current-output "\n" t)))) + (models)) (dolist (provider-entry aidermacs--api-providers) (let* ((url (car provider-entry)) (config (cdr provider-entry)) @@ -193,12 +212,14 @@ This fetches models from various API providers and caches them." (condition-case err (let* ((fetched-models (aidermacs--fetch-openai-compatible-models url token-value)) (filtered-models (seq-filter (lambda (model) - (member model supported-models)) + (member model all-models)) fetched-models))) (setq models (append models filtered-models))) - (error (message "Failed to fetch models from %s: %s" url (error-message-string err))))))) - (setq aidermacs--cached-models models) - (aidermacs--select-model))))) + (error "Failed to fetch models from %s: %s" url (error-message-string err)))))) + ;; If we couldn't fetch any models from APIs, just use all supported models list + (if models + (setq aidermacs--cached-models models) + (setq aidermacs--cached-models all-models)))))) (defun aidermacs-clear-model-cache () "Clear the cached models, forcing a fresh fetch on next use. @@ -208,18 +229,13 @@ This is useful when available models have changed." (message "Model cache cleared")) ;;;###autoload -(defun aidermacs-change-model () - "Interactively select and change AI model in current aidermacs session." - (interactive) - (when (and aidermacs--cached-models - (equal aidermacs--cached-models aidermacs-popular-models) - (fboundp 'aidermacs-get-buffer-name) - (get-buffer (aidermacs-get-buffer-name))) - (setq aidermacs--cached-models nil)) - - (if aidermacs--cached-models - (aidermacs--select-model) - (aidermacs--get-available-models))) +(defun aidermacs-change-model (&optional arg) + "Interactively select and change AI model in current aidermacs session. +With prefix ARG, only allow setting the weak model." + (interactive "P") + (unless aidermacs--cached-models + (aidermacs--get-available-models)) + (aidermacs--select-model arg)) (provide 'aidermacs-models) ;;; aidermacs-models.el ends here diff --git a/aidermacs.el b/aidermacs.el index 4ce0dbcc71..d3e5c5de38 100644 --- a/aidermacs.el +++ b/aidermacs.el @@ -151,7 +151,7 @@ This is the file name without path." :if (lambda () aidermacs-auto-commits)) ("R" "Refresh Repo Map" aidermacs-refresh-repo-map) ("h" "Session History" aidermacs-show-output-history) - ("o" "Switch Model" aidermacs-change-model) + ("o" "Switch Model (C-u: weak-model)" aidermacs-change-model) ("?" "Aider Meta-level Help" aidermacs-help)]] ["File Actions" ["Add Files (C-u: read-only)" @@ -294,6 +294,9 @@ This function sets up the appropriate arguments and launches the process." (when (and (not aidermacs-auto-accept-architect) (version<= "0.77.0" aider-version)) '("--no-auto-accept-architect")) + ;; Add weak model if specified + (when aidermacs-weak-model + (list "--weak-model" aidermacs-weak-model)) (when aidermacs-subtree-only '("--subtree-only"))))) (final-args (append backend-args flat-extra-args)))