Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
ollama
Commits
4bcb04ad
Unverified
Commit
4bcb04ad
authored
Aug 22, 2025
by
Jeffrey Morgan
Committed by
GitHub
Aug 22, 2025
Browse files
tools: avoid matching braces that are part of tool content (#12039)
parent
e3d57087
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
184 additions
and
4 deletions
+184
-4
tools/tools.go
tools/tools.go
+30
-3
tools/tools_test.go
tools/tools_test.go
+154
-1
No files found.
tools/tools.go
View file @
4bcb04ad
...
@@ -224,22 +224,45 @@ func findArguments(buffer []byte) (map[string]any, int) {
...
@@ -224,22 +224,45 @@ func findArguments(buffer []byte) (map[string]any, int) {
return
nil
,
0
return
nil
,
0
}
}
start
:=
-
1
var
braces
int
var
braces
int
var
start
int
=
-
1
var
inString
,
escaped
bool
for
i
:=
range
buffer
{
c
:=
buffer
[
i
]
if
escaped
{
escaped
=
false
continue
}
if
c
==
'\\'
{
escaped
=
true
continue
}
if
c
==
'"'
{
inString
=
!
inString
continue
}
if
inString
{
continue
}
for
i
,
c
:=
range
buffer
{
if
c
==
'{'
{
if
c
==
'{'
{
if
braces
==
0
{
if
braces
==
0
{
start
=
i
start
=
i
}
}
braces
++
braces
++
}
else
if
c
==
'}'
&&
braces
>
0
{
}
else
if
c
==
'}'
{
braces
--
braces
--
if
braces
==
0
&&
start
!=
-
1
{
if
braces
==
0
&&
start
!=
-
1
{
object
:=
buffer
[
start
:
i
+
1
]
object
:=
buffer
[
start
:
i
+
1
]
var
data
map
[
string
]
any
var
data
map
[
string
]
any
if
err
:=
json
.
Unmarshal
(
object
,
&
data
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
(
object
,
&
data
);
err
!=
nil
{
// not a valid object, keep looking
start
=
-
1
start
=
-
1
continue
continue
}
}
...
@@ -282,6 +305,10 @@ func findArguments(buffer []byte) (map[string]any, int) {
...
@@ -282,6 +305,10 @@ func findArguments(buffer []byte) (map[string]any, int) {
return
data
,
i
return
data
,
i
}
}
if
braces
<
0
{
braces
=
0
}
}
}
}
}
...
...
tools/tools_test.go
View file @
4bcb04ad
package
tools
package
tools
import
(
import
(
"strings"
"testing"
"testing"
"text/template"
"text/template"
...
@@ -1140,11 +1141,163 @@ func TestFindArguments(t *testing.T) {
...
@@ -1140,11 +1141,163 @@ func TestFindArguments(t *testing.T) {
},
},
{
{
name
:
"deepseek"
,
name
:
"deepseek"
,
buffer
:
[]
byte
(
`
",
"arguments": {"location": "Tokyo"}}</tool_call>`
),
buffer
:
[]
byte
(
`"arguments": {"location": "Tokyo"}}</tool_call>`
),
want
:
map
[
string
]
any
{
want
:
map
[
string
]
any
{
"location"
:
"Tokyo"
,
"location"
:
"Tokyo"
,
},
},
},
},
{
name
:
"string with braces"
,
buffer
:
[]
byte
(
`{"name": "process_code", "arguments": {"code": "if (x > 0) { return true; }"}}`
),
want
:
map
[
string
]
any
{
"code"
:
"if (x > 0) { return true; }"
,
},
},
{
name
:
"string with nested json"
,
buffer
:
[]
byte
(
`{"name": "send_data", "arguments": {"payload": "{\"nested\": {\"key\": \"value\"}}"}}`
),
want
:
map
[
string
]
any
{
"payload"
:
`{"nested": {"key": "value"}}`
,
},
},
{
name
:
"string with escaped quotes and braces"
,
buffer
:
[]
byte
(
`{"name": "analyze", "arguments": {"text": "The JSON is: {\"key\": \"val{ue}\"}"}}`
),
want
:
map
[
string
]
any
{
"text"
:
`The JSON is: {"key": "val{ue}"}`
,
},
},
{
name
:
"multiple objects with string containing braces"
,
buffer
:
[]
byte
(
`{"name": "test", "arguments": {"query": "find } in text"}} {"name": "other"}`
),
want
:
map
[
string
]
any
{
"query"
:
"find } in text"
,
},
},
{
name
:
"unmatched closing brace in string"
,
buffer
:
[]
byte
(
`{"name": "search", "arguments": {"pattern": "regex: }"}}`
),
want
:
map
[
string
]
any
{
"pattern"
:
"regex: }"
,
},
},
{
name
:
"complex nested with mixed braces"
,
buffer
:
[]
byte
(
`{"name": "analyze", "arguments": {"data": "{\"items\": [{\"value\": \"}\"}, {\"code\": \"if (x) { return y; }\"}]}"}}`
),
want
:
map
[
string
]
any
{
"data"
:
`{"items": [{"value": "}"}, {"code": "if (x) { return y; }"}]}`
,
},
},
{
name
:
"string with newline and braces"
,
buffer
:
[]
byte
(
`{"name": "format", "arguments": {"template": "{\n \"key\": \"value\"\n}"}}`
),
want
:
map
[
string
]
any
{
"template"
:
"{
\n
\"
key
\"
:
\"
value
\"\n
}"
,
},
},
{
name
:
"string with unicode escape"
,
buffer
:
[]
byte
(
`{"name": "test", "arguments": {"text": "Unicode: \u007B and \u007D"}}`
),
want
:
map
[
string
]
any
{
"text"
:
"Unicode: { and }"
,
},
},
{
name
:
"array arguments"
,
buffer
:
[]
byte
(
`{"name": "batch", "arguments": ["item1", "item2", "{\"nested\": true}"]}`
),
want
:
nil
,
// This should return nil because arguments is not a map
},
{
name
:
"escaped backslash before quote"
,
buffer
:
[]
byte
(
`{"name": "path", "arguments": {"dir": "C:\\Program Files\\{App}\\"}}`
),
want
:
map
[
string
]
any
{
"dir"
:
`C:\Program Files\{App}\`
,
},
},
{
name
:
"single quotes not treated as string delimiters"
,
buffer
:
[]
byte
(
`{"name": "query", "arguments": {"sql": "SELECT * FROM users WHERE name = '{admin}'"}}`
),
want
:
map
[
string
]
any
{
"sql"
:
"SELECT * FROM users WHERE name = '{admin}'"
,
},
},
{
name
:
"incomplete json at buffer end"
,
buffer
:
[]
byte
(
`{"name": "test", "arguments": {"data": "some {"`
),
want
:
nil
,
},
{
name
:
"multiple escaped quotes"
,
buffer
:
[]
byte
(
`{"name": "echo", "arguments": {"msg": "He said \"Hello {World}\" loudly"}}`
),
want
:
map
[
string
]
any
{
"msg"
:
`He said "Hello {World}" loudly`
,
},
},
{
name
:
"json with comments style string"
,
buffer
:
[]
byte
(
`{"name": "code", "arguments": {"snippet": "// This is a comment with { and }"}}`
),
want
:
map
[
string
]
any
{
"snippet"
:
"// This is a comment with { and }"
,
},
},
{
name
:
"consecutive escaped backslashes"
,
buffer
:
[]
byte
(
`{"name": "test", "arguments": {"path": "C:\\\\{folder}\\\\"}}`
),
want
:
map
[
string
]
any
{
"path"
:
`C:\\{folder}\\`
,
},
},
{
name
:
"empty string with braces after"
,
buffer
:
[]
byte
(
`{"name": "test", "arguments": {"a": "", "b": "{value}"}}`
),
want
:
map
[
string
]
any
{
"a"
:
""
,
"b"
:
"{value}"
,
},
},
{
name
:
"unicode in key names"
,
buffer
:
[]
byte
(
`{"name": "test", "arguments": {"key{": "value", "key}": "value2"}}`
),
want
:
map
[
string
]
any
{
"key{"
:
"value"
,
"key}"
:
"value2"
,
},
},
{
name
:
"very long string with braces"
,
buffer
:
[]
byte
(
`{"name": "test", "arguments": {"data": "`
+
strings
.
Repeat
(
"a{b}c"
,
100
)
+
`"}}`
),
want
:
map
[
string
]
any
{
"data"
:
strings
.
Repeat
(
"a{b}c"
,
100
),
},
},
{
name
:
"tab characters and braces"
,
buffer
:
[]
byte
(
`{"name": "test", "arguments": {"code": "\tif (true) {\n\t\treturn;\n\t}"}}`
),
want
:
map
[
string
]
any
{
"code"
:
"
\t
if (true) {
\n\t\t
return;
\n\t
}"
,
},
},
{
name
:
"null byte in string"
,
buffer
:
[]
byte
(
`{"name": "test", "arguments": {"data": "before\u0000{after}"}}`
),
want
:
map
[
string
]
any
{
"data"
:
"before
\x00
{after}"
,
},
},
{
name
:
"escaped quote at end of string"
,
buffer
:
[]
byte
(
`{"name": "test", "arguments": {"data": "text with quote at end\\\""}}`
),
want
:
map
[
string
]
any
{
"data"
:
`text with quote at end\"`
,
},
},
{
name
:
"mixed array and object in arguments"
,
buffer
:
[]
byte
(
`{"name": "test", "arguments": {"items": ["{", "}", {"key": "value"}]}}`
),
want
:
map
[
string
]
any
{
"items"
:
[]
any
{
"{"
,
"}"
,
map
[
string
]
any
{
"key"
:
"value"
}},
},
},
}
}
for
_
,
tt
:=
range
tests
{
for
_
,
tt
:=
range
tests
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment