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)))
|
(let ((tool (gptel-get-tool name)))
|
||||||
(when tool
|
(when tool
|
||||||
(setf (gptel-tool-confirm tool) nil))))
|
(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)
|
(gptel-agent-update)
|
||||||
|
|
||||||
;; Herramientas del agente (equivalente a las tools de opencode)
|
;; Herramientas del agente (equivalente a las tools de opencode)
|
||||||
|
|||||||
Reference in New Issue
Block a user