branch: elpa/gptel commit 51d39e9136c25a45dae58513e599377b87bc2902 Author: Tom Cahill <t...@tomwcahill.com> Commit: GitHub <nore...@github.com>
gptel-anthropic: Fix invalid duplication of tool_call message (#734) When a `message_delta` event is received, we append any tool calls from the response to the global vector of messages and then modify the `tool-use` lists in the FSM info to put them in the right shape for actually invoking tools. This can cause issues if an error occurs after those modifications have already been made - if the `gptel--json-read` call for the `message_delta`'s data fails because we don't yet have the full object, the error handler silently discards the error and resets the point to the start of the same event again. Next time we re-enter `gptel-curl--parse-stream`, we'll again try to process the `message_delta` event but because we modified the tool use blocks in the last invocation, we'll push duplicate messages with the incorrect format (`input` is empty and `args` has the contents that `input` is supposed to). For example, here's what the messages vector looks like when we encounter this issue in the repro script described by @kmontag in https://github.com/karthink/gptel/issues/725: ``` [(:role "user" :content "Open the file '~/example.el' and make 5 changes of your choosing. Make each change individually. Don't ask for clarification.") (:role "assistant" :content [(:type "text" :text #("I'll open the file and make 5 individual changes of my choosing. Let me first check the contents of the file." 0 9 (gptel response front-sticky (gptel)) 9 40 (gptel response front-sticky (gptel)) 40 87 (gptel response front-sticky (gptel)) 87 109 (gptel response front-sticky (gptel)))) (:type "tool_use" :id "toolu_01WHEjX2hivzCrcufv9RaCnY" :name "readFile" :input (:filename "~/example.el"))]) (:role "assistant" :content [(:type "tool_use" :id "01WHEjX2hivzCrcufv9RaCnY" :name "readFile" :input nil :args (:filename "~/example.el"))])] ``` --- gptel-anthropic.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gptel-anthropic.el b/gptel-anthropic.el index 9dd2214fed..dde7ab6cc5 100644 --- a/gptel-anthropic.el +++ b/gptel-anthropic.el @@ -117,7 +117,8 @@ information if the stream contains it. Not my best work, I know." ((looking-at "message_delta") ;; collect stop_reason, usage_tokens and prepare tools (forward-line 1) (forward-char 5) - (when-let* ((tool-use (plist-get info :tool-use))) + (when-let* ((tool-use (plist-get info :tool-use)) + (response (gptel--json-read))) (let* ((data (plist-get info :data)) (prompts (plist-get data :messages))) (plist-put ; Append a COPY of response text + tool-use to the prompts list @@ -139,8 +140,7 @@ information if the stream contains it. Not my best work, I know." (plist-put tool-call :input nil) (plist-put tool-call :id (gptel--anthropic-unformat-tool-id (plist-get tool-call :id)))) - tool-use))) - (when-let* ((response (gptel--json-read))) + tool-use)) (plist-put info :output-tokens (map-nested-elt response '(:usage :output_tokens))) (plist-put info :stop-reason