branch: elpa/gptel
commit 0c32dbdbf4319b9d3cdd4302249d25c2a3495f1e
Author: Karthik Chikmagalur <[email protected]>
Commit: Karthik Chikmagalur <[email protected]>

    gptel: Improve preset validation, modify-spec handling
    
    * gptel.el (gptel--modify-value):  Use keywordp instead of
    checking for it the hard way.  I keep forgetting that keywordp
    exists.  (Like car-safe, this is a weird choice of functions to
    implement in C.)
    
    * gptel-transient.el (gptel--preset-mismatch-p,
    gptel--read-apply-preset): Set `gptel--preset' when applying a
    preset via `completing-read'.
    
    Try to handle modify-specs for :tools when checking if there is a
    preset mismatch.  Handle both tools and tool names in the :tools
    spec correctly. (#1099)
    
    Handling all possible modify-specs correctly in
    `gptel--preset-mismatch-p' is impossible, or at least impractical.
    For example, if a spec contains
    
      :system (:function 'do-something)
    
    where do-something is not idempotent, then we have nothing to
    compare the current system message (which is
    
      (do-something gptel--system-message))
    
    against gptel--system-message.
---
 gptel-transient.el | 23 +++++++++++++++--------
 gptel.el           |  4 +---
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/gptel-transient.el b/gptel-transient.el
index 662fc5ed740..769d3982833 100644
--- a/gptel-transient.el
+++ b/gptel-transient.el
@@ -89,6 +89,8 @@ For internal use only.")
          ((memq key '(:description :parents)) 'nil)
          ((eq key :system)
           (or (equal gptel--system-message val)
+              (functionp val)    ; Ignore functions, modify-specs for speed 
here
+              (and (consp val) (keywordp (car val)))
               (and-let* (((symbolp val))
                          (p (assq val gptel-directives)))
                 (equal gptel--system-message (cdr p)))
@@ -99,18 +101,22 @@ For internal use only.")
                 (eq gptel-backend val))
               (throw 'mismatch t)))
          ((eq key :tools)
-          (if (eq (car-safe val) :append)
-              (cl-loop for name in (cdr val) ;preset tools contained in 
gptel-tools
-                       unless (memq (gptel-get-tool name) gptel-tools)
-                       do (throw 'mismatch t))
-            (or (equal (sort val #'string-lessp) ;preset tools same as 
gptel-tools
-                       (sort (mapcar #'gptel-tool-name gptel-tools)
-                             #'string-lessp))
-                (throw 'mismatch t))))
+          (setq val (cl-loop ; Check against tool names, not tools (faster 
with sorting)
+                     for tool in (ensure-list (gptel--modify-value gptel-tools 
val))
+                     for tool-name = (or (and (stringp tool) tool)
+                                         (ignore-errors (gptel-tool-name 
tool)))
+                     if (not (member tool-name uniq-tool-names))
+                     collect tool-name into uniq-tool-names
+                     finally return uniq-tool-names))
+          (or (equal (sort val #'string-lessp) ;preset tools same as 
gptel-tools?
+                     (sort (mapcar #'gptel-tool-name gptel-tools)
+                           #'string-lessp))
+              (throw 'mismatch t)))
          (t (let* ((suffix (substring
                             (if (symbolp key) (symbol-name key) key) 1))
                    (sym (or (intern-soft (concat "gptel-" suffix))
                             (intern-soft (concat "gptel--" suffix)))))
+              ;; FIXME(modify-list): Fix for values specified with a spec, 
like :eval
               (or (null sym)
                   (and (boundp sym) (equal (eval sym) val))
                   (throw 'mismatch t)))))))))
@@ -530,6 +536,7 @@ which see."
                                   ('t "buffer-locally")
                                   (_ "globally")))
                         gptel--known-presets nil t)))))
+  (gptel--set-with-scope 'gptel--preset name gptel--set-buffer-locally)
   (gptel--apply-preset
    name (lambda (sym val)
           (gptel--set-with-scope sym val gptel--set-buffer-locally)))
diff --git a/gptel.el b/gptel.el
index 30dba91ccea..f6a15f1cf47 100644
--- a/gptel.el
+++ b/gptel.el
@@ -312,9 +312,7 @@ form it is returned as is.
 - :function will call val with ORIGINAL as its argument, and return the result.
 - :merge will treat ORIGINAL and NEW-SPEC as plists and return a merged plist,
   with NEW-SPEC taking precedence."
-  (if (not (and (consp new-spec)
-                (symbolp (car new-spec))
-                (string-prefix-p ":" (symbol-name (car new-spec)))))
+  (if (not (and (consp new-spec) (keywordp (car new-spec))))
       new-spec
     (let ((current original) (tail new-spec))
       (while tail

Reply via email to