Function: gptel--handle-tool-use

gptel--handle-tool-use is a natively compiled function defined in gptel-request.el.

Signature

(gptel--handle-tool-use FSM)

Documentation

Run tool calls captured in FSM, and advance the state machine with the results.

Source Code

;; Defined in /nix/store/q3r7g81pvghw7a523kjk2k2zih3pfk8z-emacs-packages-deps/share/emacs/site-lisp/elpa/gptel-20261002.545/gptel-request.el
(defun gptel--handle-tool-use (fsm)
  "Run tool calls captured in FSM, and advance the state machine with the results."
  (when-let* ((info (gptel-fsm-info fsm))
              (backend (plist-get info :backend))
              ;; This function might run many times, so only act on the remaining tool calls.
              (tool-use (cl-remove-if (lambda (tc) (plist-get tc :result))
                                      (plist-get info :tool-use))))
    (with-current-buffer (plist-get info :buffer)
      (let ((pending-calls))
        (mapc                           ; Construct function calls
         (lambda (tool-call)
           (letrec ((args (plist-get tool-call :args))
                    (name (plist-get tool-call :name))
                    (tool-spec (cl-find-if (lambda (ts) (equal (gptel-tool-name ts) name))
                                           (plist-get info :tools)))
                    (process-tool-result (apply-partially #'gptel--process-tool-call
                                                          fsm tool-spec tool-call)))
             (if (null tool-spec)
                 (if (equal name gptel--ersatz-json-tool) ;Could be a JSON response
                     (progn ;Handle structured JSON output supplied as tool call
                       (funcall (plist-get info :callback)
                                (gptel--json-encode (plist-get tool-call :args)) info)
                       (plist-put info :tool-use ;Remove this tool call from the list
                                  (cl-remove-if (lambda (tc) (equal (plist-get tc :name)
                                                               gptel--ersatz-json-tool))
                                                (plist-get info :tool-use)))
                       (when (plist-get info :stream)
                         (funcall (plist-get info :callback) t info)))
		   (message "Unknown tool called by model: %s" name)
                   (funcall process-tool-result
                            (format "Error: Tool '%s' is not available. Available tools: %s"
                                    name (mapconcat #'gptel-tool-name
                                                    (plist-get info :tools) ", "))))
               (let ((confirm))         ;Check if tool requires confirmation
                 (cond      ;:confirm in tool-call (from hooks) takes precedence
                  ((and-let* ((call-confirm (plist-member tool-call :confirm)))
                     (prog1 t (setq confirm (cadr call-confirm)))))
                  ((and gptel-confirm-tool-calls ;global and tool-specific setting
                        (or (eq gptel-confirm-tool-calls t) ;always confirm, or
                            (and-let* ((confirm (gptel-tool-confirm tool-spec)))
                              (or (not (functionp confirm))
                                  (apply confirm (gptel--map-tool-args tool-spec args))))))
                   (setq confirm t)))
                 (if confirm  ;To send to callback for confirmation
                     (push (list tool-spec args process-tool-result) pending-calls)
                   (let ((arg-values (gptel--map-tool-args tool-spec args)))
                     (if (gptel-tool-async tool-spec) ;If not, run the tool
                         (apply (gptel-tool-function tool-spec)
                                process-tool-result arg-values)
                       (let ((result (condition-case errdata
                                         (apply (gptel-tool-function tool-spec) arg-values)
                                       (error (mapconcat #'gptel--to-string errdata " ")))))
                         (funcall process-tool-result result)))))))))
         tool-use)
        (when pending-calls
          (plist-put info :tool-pending t)
          (funcall (plist-get info :callback)
                   (cons 'tool-call pending-calls) info))))))