tools: ignore braces inside JSON strings when detecting tool call end (#16937)

Parser.done() counted the tag's open/close characters ({}, []) without
tracking JSON string context, so a streamed tool call whose string
argument value contained a closing brace or bracket (e.g.
{"code": "if (x) { y }"}) was treated as complete too early and flushed to
the user as plain text instead of being parsed as a tool call.

findArguments() in the same file already tracks string context; apply the
same handling in done() so open/close characters inside string values are
ignored.
This commit is contained in:
Aditya Aggarwal
2026-06-28 00:30:55 +05:30
committed by GitHub
parent d26a58557d
commit 32a97b7493
2 changed files with 34 additions and 0 deletions
+16
View File
@@ -358,7 +358,23 @@ func (p *Parser) done() bool {
} }
var count int var count int
var inString, escaped bool
for _, c := range p.buffer { for _, c := range p.buffer {
if escaped {
escaped = false
continue
}
if c == '\\' {
escaped = true
continue
}
if c == '"' {
inString = !inString
continue
}
if inString {
continue
}
if c == byte(open) { if c == byte(open) {
count++ count++
} else if c == byte(close) { } else if c == byte(close) {
+18
View File
@@ -842,6 +842,24 @@ func TestDone(t *testing.T) {
buffer: []byte("[]"), buffer: []byte("[]"),
want: true, want: true,
}, },
{
name: "json close brace inside string",
tag: "{",
buffer: []byte("{\"note\": \"a}b\""),
want: false,
},
{
name: "json complete with brace inside string",
tag: "{",
buffer: []byte("{\"note\": \"a}b\"}"),
want: true,
},
{
name: "list close bracket inside string",
tag: "[",
buffer: []byte("[{\"note\": \"x]y\"}"),
want: false,
},
} }
for _, tt := range tests { for _, tt := range tests {