1414 (error " Failed to parse JSON: ~A " json-string)))
1515
1616(defun strip-markdown-json (text)
17- " Remove markdown fences around JSON in TEXT."
18- (let ((trimmed (string-trim ' (#\Space #\Newline #\Tab #\Return ) text) ))
19- ( if ( and (search " ```json" trimmed)
20- (search " ```" trimmed :start2 (1+ ( search " ```json " trimmed) )))
21- (subseq trimmed
22- (search " ```json " trimmed)
23- ( search " ``` " trimmed :start2 ( 1+ ( search " ``` json" trimmed)) ))
17+ " Remove markdown fences around JSON in TEXT."
18+ (let* ((trimmed (string-trim ' (#\Space #\Newline #\Tab #\Return ) text))
19+ (start (search " ```json" trimmed)) )
20+ ( if ( and start (search " ```" trimmed :start2 (1+ start )))
21+ (let ((json-start ( + start 7 ))
22+ (json-end (search " ```" trimmed :start2 ( 1+ start))) )
23+ ( subseq trimmed json-start json-end ))
2424 trimmed)))
2525
2626; ; Macro to define new agent classes
4949
5050; ; LLM back-end generic
5151(defgeneric agent-llm-call (agent prompt)
52- " Perform an LLM call with AGENT given PROMPT." )
52+ ( :documentation " Perform an LLM call with AGENT given PROMPT." ) )
5353
5454(defun make-agent (agent-type &rest initargs &key context)
5555 " Construct an agent of AGENT-TYPE with INITARGS and optional CONTEXT."
6767 (display-context (agent-context agent) " Context start:" ))
6868 (let* ((tools-info (with-output-to-string (out)
6969 (format out " tools:~% " )
70- (dolist (t (list-tools))
70+ (dolist (tool (list-tools))
7171 (format out " ~A : ~A~% "
72- (getf t :name )
73- (getf t :description )))))
72+ (getf tool :name )
73+ (getf tool :description )))))
7474 (prompt (format nil " ~A~% User Input: ~A~%~% If using tools, respond in JSON." tools-info user-input))
7575 (raw (agent-llm-call agent prompt))
7676 (clean (strip-markdown-json raw))
77- (parsed (safe-parse-json clean))
78- (actions (if (getf parsed :actions )
79- (getf parsed :actions )
80- (list parsed))))
81- (when *agent-verbose*
82- (format t " [agent-converse] raw: ~A~% clean: ~A~% actions: ~A~% " raw clean actions))
83- (loop with prev = nil
84- for action across actions
85- for name = (getf action :action )
86- for params = (getf action :parameters )
87- do (setf prev (apply #' execute-tool name
88- (map ' list (lambda (p)
89- (if (string-equal p " PREV_RESULT" ) prev p))
90- params)))
91- finally (return (or prev (format nil " ~A " raw)))))
77+ (parsed (handler-case
78+ (safe-parse-json clean)
79+ (error (err)
80+ (when *agent-verbose*
81+ (format t " [agent-converse] JSON parse error: ~A~% " err))
82+ nil ))))
83+ (unless (and parsed
84+ (or (getf parsed :actions )
85+ (getf parsed :action )))
86+ (when *agent-verbose*
87+ (format t " [agent-converse] returning raw response: ~A~% " clean))
88+ (return-from agent-converse clean))
89+ (let ((actions (if (getf parsed :actions )
90+ (getf parsed :actions )
91+ (list parsed))))
92+ (when *agent-verbose*
93+ (format t " [agent-converse] raw: ~A~% clean: ~A~% actions: ~A~% " raw clean actions))
94+ (loop with prev = nil
95+ for action across actions
96+ for name = (getf action :action )
97+ for params = (getf action :parameters )
98+ do (setf prev (apply #' execute-tool name
99+ (map ' list (lambda (p)
100+ (if (string-equal p " PREV_RESULT" ) prev p))
101+ params)))
102+ finally (return (or prev (format nil " ~A " raw)))))))
0 commit comments