branch: elpa/aidermacs
commit bf9ad44c7df2e8e632d39c47c1ee55e86a6b2a1f
Author: Arthur Heymans <art...@aheymans.xyz>
Commit: Arthur Heymans <art...@aheymans.xyz>

    Dynamically fetch models from providers
    
    Currently the following providers are supported: deepseek, openai,
    anthropic and openrouter.
    
    Signed-off-by: Arthur Heymans <art...@aheymans.xyz>
---
 aidermacs-models.el | 58 +++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 45 insertions(+), 13 deletions(-)

diff --git a/aidermacs-models.el b/aidermacs-models.el
index 464cc3bbbe..88944e9129 100644
--- a/aidermacs-models.el
+++ b/aidermacs-models.el
@@ -9,22 +9,54 @@
   "Model selection customization for aidermacs."
   :group 'aidermacs)
 
-(defcustom aidermacs-popular-models
-  '("anthropic/claude-3-5-sonnet-20241022"  ;; really good in practical
-    "o3-mini" ;; very powerful
-    "gemini/gemini-2.0-pro-exp-02-05"  ;; free
-    "r1"  ;; performance match o1, price << claude sonnet. weakness: small 
context
-    "deepseek/deepseek-chat"  ;; chatgpt-4o level performance, price is 1/100. 
weakness: small context
-    )
-  "List of available AI models for selection.
-Each model should be in the format expected by the aidermacs command line 
interface.
-Also based on aidermacs LLM benchmark: 
https://aidermacs.chat/docs/leaderboards/";
-  :type '(repeat string)
-  :group 'aidermacs-models)
+(require 'json)
+(require 'url)
+
+(defun fetch-openai-compatible-models (url)
+  "Fetch available models from an OpenAI compatible API endpoint at URL."
+  (let* ((url-parsed (url-generic-parse-url url))
+         (hostname (url-host url-parsed))
+         (prefix (cond ((string= hostname "api.openai.com") "openai")
+                      ((string= hostname "openrouter.ai") "openrouter")
+                      ((string= hostname "api.deepseek.com") "deepseek")
+                      ((string= hostname "api.anthropic.com") "anthropic")
+                      (t (error "Unknown API host: %s" hostname))))
+         (token (cond ((string= hostname "api.openai.com") (getenv 
"OPENAI_API_KEY"))
+                     ((string= hostname "openrouter.ai") (getenv 
"OPENROUTER_API_KEY"))
+                     ((string= hostname "api.deepseek.com") (getenv 
"DEEPSEEK_API_KEY"))
+                     ((string= hostname "api.anthropic.com") (getenv 
"ANTHROPIC_API_KEY"))
+                     (t (error "Unknown API host: %s" hostname)))))
+    (with-current-buffer
+        (let ((url-request-extra-headers
+               (if (string= hostname "api.anthropic.com")
+                   `(("x-api-key" . ,token)
+                     ("anthropic-version" . "2023-06-01"))
+                 `(("Authorization" . ,(concat "Bearer " token))))))
+          (url-retrieve-synchronously (concat url "/models")))
+      (goto-char url-http-end-of-headers)
+      (let* ((json-object-type 'alist)
+             (json-data (json-read))
+             (models (alist-get 'data json-data)))
+        (mapcar (lambda (model)
+                  (concat prefix "/" (alist-get 'id model)))
+                models)))))
+
+(defun aidermacs--get-available-models ()
+  "Get list of available models from multiple providers."
+  (let ((models nil))
+    (dolist (url '("https://api.openai.com/v1";
+                   "https://openrouter.ai/api/v1";
+                   "https://api.deepseek.com";
+                   "https://api.anthropic.com/v1";))
+      (condition-case err
+          (setq models (append models (fetch-openai-compatible-models url)))
+        (error (message "Failed to fetch models from %s: %s" url err))))
+    models))
 
 (defun aidermacs--select-model ()
   "Private function for model selection with completion."
-  (completing-read "Select AI model: " aidermacs-popular-models nil t nil nil 
(car aidermacs-popular-models)))
+  (let ((models (aidermacs--get-available-models)))
+    (completing-read "Select AI model: " models nil t)))
 
 ;;;###autoload
 (defun aidermacs-change-model ()

Reply via email to