diff --git a/configs/init-ai.el b/configs/init-ai.el index 0a1ac20..5082982 100644 --- a/configs/init-ai.el +++ b/configs/init-ai.el @@ -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 +# 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)