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:
@@ -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) {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user