feat(gptel): implement safe Eval tool for AI agent
This commit is contained in:
@@ -442,6 +442,62 @@ Tries `patch -p1' first and falls back to `-p0'."
|
||||
(let ((tool (gptel-get-tool name)))
|
||||
(when tool
|
||||
(setf (gptel-tool-confirm tool) nil))))
|
||||
|
||||
;; Sobrescribir la tool "Eval" para que sea segura: con `inhibit-interaction',
|
||||
;; las llamadas interactivas (read-*, y-or-n-p, call-interactively, ...)
|
||||
;; lanzan error en vez de quedarse esperando input y colgar al agente.
|
||||
(gptel-make-tool
|
||||
:name "Eval"
|
||||
:function
|
||||
(lambda (expression)
|
||||
(let ((standard-output (generate-new-buffer " *gptel-agent-eval-elisp*"))
|
||||
(result nil) (output nil))
|
||||
(unwind-protect
|
||||
(condition-case err
|
||||
(progn
|
||||
(let ((inhibit-interaction t))
|
||||
(setq result (eval (read expression) t)))
|
||||
(when (> (buffer-size standard-output) 0)
|
||||
(setq output (with-current-buffer standard-output (buffer-string))))
|
||||
(concat
|
||||
(format "Result:\n%S" result)
|
||||
(and output (format "\n\nSTDOUT:\n%s" output))))
|
||||
((error user-error)
|
||||
(concat
|
||||
(if (eq (car err) 'inhibited-interaction)
|
||||
"Error: la expresión intentó pedir entrada al usuario de forma interactiva, lo cual está bloqueado en la tool Eval."
|
||||
(format "Error: eval failed with error %S: %S" (car err) (cdr err)))
|
||||
(and output (format "\n\nSTDOUT:\n%s" output)))))
|
||||
(kill-buffer standard-output))))
|
||||
:description "Evaluate Elisp EXPRESSION and return result and any printed output.
|
||||
|
||||
EXPRESSION can be anything to evaluate. It can be a function call, a
|
||||
variable, a quasi-quoted expression. The only requirement is that only
|
||||
the first sexp will be read and evaluated, so if you need to evaluate
|
||||
multiple expressions, make one call per expression. Do not combine
|
||||
expressions using progn etc. Just go expression by expression and try
|
||||
to make standalone single expressions.
|
||||
|
||||
Interactive operations are blocked: if the expression tries to prompt
|
||||
for input (read-*, y-or-n-p, call-interactively, etc.) it will error
|
||||
instead of waiting.
|
||||
|
||||
The return value is formatted to a string using %S, so a string will be
|
||||
returned as an escaped embedded string and literal forms will be
|
||||
compatible with `read' where possible. Some forms have no printed
|
||||
representation that can be read and will be represented with
|
||||
#<hash-notation> instead.
|
||||
|
||||
Output from `print', `prin1', and `princ' is captured and returned as STDOUT.
|
||||
Use `print' for diagnostic output, not `message' (which goes to *Messages*
|
||||
and is not captured)."
|
||||
:args '((:name "expression"
|
||||
:type string
|
||||
:description "A single elisp sexp to evaluate."))
|
||||
:category "gptel-agent"
|
||||
:confirm t
|
||||
:include t)
|
||||
|
||||
(gptel-agent-update)
|
||||
|
||||
;; Herramientas del agente (equivalente a las tools de opencode)
|
||||
|
||||
Reference in New Issue
Block a user