branch: elpa/gptel commit b30cee0e738428366a15ebae85871afb88c6e2bb Author: Karthik Chikmagalur <karthikchikmaga...@gmail.com> Commit: Karthik Chikmagalur <karthikchikmaga...@gmail.com>
gptel: No advice for tool spec argument preprocessing (#794) * gptel.el (gptel--preprocess-tool-args, gptel--make-tool, gptel-tool, gptel--make-tool-internal): To work around inconsistent advice evaluation for cl-struct constructors, separate tool construction into two functions: `gptel--make-tool-internal' is the cl-struct constructor, now unadvised. `gptel--make-tool' runs the constructor after preprocessing the tool spec to change :types to strings (and possibly other accommodations in the future) the tool spec to change :types to strings (and possibly other accommodations in the future). Leave `gptel-make-tool' unchanged. The problem of inconsistent advice application to cl-struct constructors (which have a compiler macro attached) can be seen in the following example. Place the following in an elisp file and native-compile and load it: ;; -*- lexical-binding: t; -*- (cl-defstruct teststruct foo) (define-advice make-teststruct (:filter-args (rest) modify-args) (plist-put rest :foo "changed") rest) Now running (make-teststruct :foo "original") will cause the struct to have its :foo key set to either "original" or "changed", depending on whether the advice ran. Whether the advice runs appears to depend on the environment and the method of evaluation. - The advice runs when evaluated in IELM, via pp-eval-last-sexp or pp-eval-expression. - The advice doesn't run when evaluated via eval-last-sexp, eval-defun or eval-buffer. This requires further investigation. --- gptel.el | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/gptel.el b/gptel.el index 3fb4bad0df..c0ceeeb8eb 100644 --- a/gptel.el +++ b/gptel.el @@ -1526,7 +1526,7 @@ a tool, use `gptel-make-tool', which see." :type '(repeat gptel-tool)) (cl-defstruct (gptel-tool (:constructor nil) - (:constructor gptel--make-tool + (:constructor gptel--make-tool-internal (&key function name description args async category confirm include &allow-other-keys)) @@ -1547,11 +1547,6 @@ feed the LLM the results. You can add tools via (confirm nil :type boolean :documentation "Seek confirmation before running tool?") (include nil :type boolean :documentation "Include tool results in buffer?")) -(define-advice gptel--make-tool (:filter-args (rest) preprocess-args) - "Convert symbol :type values to strings in the args in REST." - (cl-callf gptel--preprocess-tool-args (plist-get rest :args)) - rest) - (defun gptel--preprocess-tool-args (spec) "Convert symbol :type values in tool SPEC to strings destructively." ;; NOTE: Do not use `sequencep' here, as that covers strings too and breaks @@ -1577,6 +1572,10 @@ feed the LLM the results. You can add tools via (gptel--preprocess-tool-args element)))))) spec) +(defun gptel--make-tool (&rest spec) + "Construct a gptel-tool according to SPEC." + (apply #'gptel--make-tool-internal (gptel--preprocess-tool-args spec))) + (defvar gptel--known-tools nil "Alist of gptel tools arranged by category.