@@ -120,16 +120,14 @@ func (p *Parser) parseToolCall() *api.ToolCall {
120120 return nil
121121 }
122122
123- // only look for arguments after the tool name if the tool has parameters
124- // TODO (jmorganca): while probably uncommon, this doesn't support
125- // parsing arguments before the tool name, which may be needed in the future
126- args := map [string ]any {}
127- if len (tool .Function .Parameters .Properties ) > 0 {
128- var i int
129- if args , i = findArguments (* tool , p .buffer [end :]); args == nil {
130- return nil
123+ var args map [string ]any
124+ if found , i := findArguments (p .buffer ); found == nil {
125+ return nil
126+ } else {
127+ args = found
128+ if i > end {
129+ end = i
131130 }
132- end += i
133131 }
134132
135133 tc := & api.ToolCall {
@@ -217,93 +215,70 @@ func findTool(tools []api.Tool, buf []byte) (*api.Tool, int) {
217215// objects for functions that have all-optional parameters
218216// e.g. `{"name": "get_conditions", "arguments": {}}` will work but
219217// `{"name": "get_conditions"}` will not currently work
220- func findArguments (tool api. Tool , buffer []byte ) (map [string ]any , int ) {
218+ func findArguments (buffer []byte ) (map [string ]any , int ) {
221219 if len (buffer ) == 0 {
222220 return nil , 0
223221 }
224222
225223 var braces int
226224 var start int = - 1
227- var end int
228- var object []byte
229225
230- // find any outer json object
231226 for i , c := range buffer {
232227 if c == '{' {
233- braces ++
234- if start == - 1 {
228+ if braces == 0 {
235229 start = i
236230 }
237- }
238-
239- if c == '}' {
240- if start != - 1 {
241- braces --
242- if braces == 0 {
243- end = i + 1
244- object = buffer [start :end ]
245- break
231+ braces ++
232+ } else if c == '}' && braces > 0 {
233+ braces --
234+ if braces == 0 && start != - 1 {
235+ object := buffer [start : i + 1 ]
236+
237+ var data map [string ]any
238+ if err := json .Unmarshal (object , & data ); err != nil {
239+ start = - 1
240+ continue
246241 }
247- }
248- }
249- }
250242
251- if braces > 0 {
252- return nil , 0
253- }
243+ var findObject func (obj map [string ]any ) (map [string ]any , bool )
244+ findObject = func (obj map [string ]any ) (map [string ]any , bool ) {
245+ if _ , hasName := obj ["name" ]; hasName {
246+ if args , ok := obj ["arguments" ].(map [string ]any ); ok {
247+ return args , true
248+ }
249+ if args , ok := obj ["parameters" ].(map [string ]any ); ok {
250+ return args , true
251+ }
252+ return nil , true
253+ }
254254
255- var data map [string ]any
256- if err := json .Unmarshal (object , & data ); err != nil {
257- return nil , 0
258- }
255+ for _ , v := range obj {
256+ switch child := v .(type ) {
257+ case map [string ]any :
258+ if result , found := findObject (child ); found {
259+ return result , true
260+ }
261+ case []any :
262+ for _ , item := range child {
263+ if childObj , ok := item .(map [string ]any ); ok {
264+ if result , found := findObject (childObj ); found {
265+ return result , true
266+ }
267+ }
268+ }
269+ }
270+ }
259271
260- var find func (obj any ) map [string ]any
261- find = func (obj any ) map [string ]any {
262- switch obj := obj .(type ) {
263- case map [string ]any :
264- valid := true
265- // check if all keys in the object exist in the tool's parameters
266- for key := range obj {
267- if _ , exists := tool .Function .Parameters .Properties [key ]; ! exists {
268- valid = false
269- break
272+ return nil , false
270273 }
271- }
272274
273- // check for required parameters
274- // TODO (jmorganca): this should error instead of silently failing
275- if valid {
276- for _ , required := range tool .Function .Parameters .Required {
277- if _ , exists := obj [required ]; ! exists {
278- valid = false
279- break
280- }
275+ if args , found := findObject (data ); found {
276+ return args , i
281277 }
282- }
283278
284- if valid {
285- return obj
286- }
287-
288- for _ , value := range obj {
289- if result := find (value ); result != nil {
290- return result
291- }
292- }
293- case []any :
294- for _ , item := range obj {
295- if result := find (item ); result != nil {
296- return result
297- }
279+ return data , i
298280 }
299281 }
300-
301- return nil
302- }
303-
304- result := find (data )
305- if result != nil {
306- return result , end
307282 }
308283
309284 return nil , 0
0 commit comments