about summary refs log tree commit diff
diff options
context:
space:
mode:
authorArun Isaac2026-04-08 23:27:07 +0100
committerArun Isaac2026-04-08 23:53:06 +0100
commitc8bc059c89fe7feb4431dbee89adddda6ae0a62a (patch)
tree02add000b0c3814dbe037d9bc5c8fd401c082219
parent90a4d6cb32fd363d1c4fa97cbdd15365b1540db4 (diff)
downloadkaagum-c8bc059c89fe7feb4431dbee89adddda6ae0a62a.tar.gz
kaagum-c8bc059c89fe7feb4431dbee89adddda6ae0a62a.tar.lz
kaagum-c8bc059c89fe7feb4431dbee89adddda6ae0a62a.zip
Handle tool call parse failures early.
Report tool call parse failures immediately to the LLM without
bothering the client with permission requests; only notify the client.
-rw-r--r--kaakaa/tea.scm82
1 files changed, 50 insertions, 32 deletions
diff --git a/kaakaa/tea.scm b/kaakaa/tea.scm
index d486f10..19d85ee 100644
--- a/kaakaa/tea.scm
+++ b/kaakaa/tea.scm
@@ -259,38 +259,56 @@ and a list of effects."
 (define (next-state-tool-call state session-id call-json)
   "Given current @var{state} and a new tool @var{call-json}, return the next state
 and a list of effects."
-  (let ((call (spec->tool-call session-id
-                               (focus (compose session-cwd
-                                               (key-ref session-id)
-                                               state-sessions)
-                                      state)
-                               call-json))
-        (request-id (focus state-agent-request-id state)))
-    (values (-> state
-                ;; Queue tool call.
-                (push (state-tool-calls session-id)
-                      (cons (tool-call-id call)
-                            call)
-                      <>)
-                ;; Register this request so we can recall the details later
-                ;; when the response comes in.
-                (push state-requests-alist
-                      (cons request-id call)
-                      <>)
-                ;; Bump agent request ID.
-                (over state-agent-request-id
-                      1+
-                      <>))
-            (list (acp-message `(("jsonrpc" . "2.0")
-                                 ("id" . ,request-id)
-                                 ("method" . "session/request_permission")
-                                 ("params"
-                                  ("sessionId" . ,session-id)
-                                  ("toolCall"
-                                   ("toolCallId" . ,(tool-call-id call)))
-                                  ("options" .
-                                   ,(vector %tool-allow-once
-                                            %tool-reject-once)))))))))
+  (guard (c ((tool-call-parse-failure? c)
+             (let ((call-id (focus (key-ref "id") call-json)))
+               (values (-> state
+                           ;; Push tool call response onto messages.
+                           (push (state-messages session-id)
+                                 `(("role" . "tool")
+                                   ("tool_call_id" . ,call-id)
+                                   ("content" . ,(tool-call-parse-failure-message c)))
+                                 <>))
+                       ;; Notify client about invalid tool call.
+                       (list (acp-message `(("jsonrpc" . "2.0")
+                                            ("method" . "session/update")
+                                            ("params"
+                                             ("sessionId" . ,session-id)
+                                             ("update"
+                                              ("sessionUpdate" . "tool_call")
+                                              ("toolCallId" . ,call-id)
+                                              ("status" . "failed"))))))))))
+    (let ((call (spec->tool-call session-id
+                                 (focus (compose session-cwd
+                                                 (key-ref session-id)
+                                                 state-sessions)
+                                        state)
+                                 call-json))
+          (request-id (focus state-agent-request-id state)))
+      (values (-> state
+                  ;; Queue tool call.
+                  (push (state-tool-calls session-id)
+                        (cons (tool-call-id call)
+                              call)
+                        <>)
+                  ;; Register this request so we can recall the details later
+                  ;; when the response comes in.
+                  (push state-requests-alist
+                        (cons request-id call)
+                        <>)
+                  ;; Bump agent request ID.
+                  (over state-agent-request-id
+                        1+
+                        <>))
+              (list (acp-message `(("jsonrpc" . "2.0")
+                                   ("id" . ,request-id)
+                                   ("method" . "session/request_permission")
+                                   ("params"
+                                    ("sessionId" . ,session-id)
+                                    ("toolCall"
+                                     ("toolCallId" . ,(tool-call-id call)))
+                                    ("options" .
+                                     ,(vector %tool-allow-once
+                                              %tool-reject-once))))))))))
 
 (define (next-state-llm-response state response)
   "Given current @var{state} and a new LLM @var{response}, return the next state