@@ -89,57 +89,62 @@ func (c *codeModeTool) runJavascript(ctx context.Context, script string) (Script
8989
9090func callTool (ctx context.Context , tool tools.Tool , tracker * toolCallTracker ) func (args map [string ]any ) (string , error ) {
9191 return func (args map [string ]any ) (string , error ) {
92- var toolArgs struct {
93- Required []string `json:"required"`
94- }
95-
96- if err := tools .ConvertSchema (tool .Parameters , & toolArgs ); err != nil {
97- tracker .record (ToolCallInfo {
98- Name : tool .Name ,
99- Arguments : args ,
100- Error : err .Error (),
101- })
102- return "" , err
103- }
92+ output , filtered , err := invokeTool (ctx , tool , args )
10493
105- nonNilArgs := make (map [string ]any )
106- for k , v := range args {
107- if slices .Contains (toolArgs .Required , k ) || v != nil {
108- nonNilArgs [k ] = v
109- }
94+ info := ToolCallInfo {
95+ Name : tool .Name ,
96+ Arguments : filtered ,
11097 }
111-
112- arguments , err := json .Marshal (nonNilArgs )
11398 if err != nil {
114- tracker .record (ToolCallInfo {
115- Name : tool .Name ,
116- Arguments : nonNilArgs ,
117- Error : err .Error (),
118- })
119- return "" , err
99+ info .Error = err .Error ()
100+ } else {
101+ info .Result = output
120102 }
103+ tracker .record (info )
121104
122- result , err := tool .Handler (ctx , tools.ToolCall {
123- Function : tools.FunctionCall {
124- Name : tool .Name ,
125- Arguments : string (arguments ),
126- },
127- })
128- if err != nil {
129- tracker .record (ToolCallInfo {
130- Name : tool .Name ,
131- Arguments : nonNilArgs ,
132- Error : err .Error (),
133- })
134- return "" , err
105+ return output , err
106+ }
107+ }
108+
109+ // invokeTool calls a single tool handler, filtering out nil optional arguments.
110+ // It returns the output, the filtered arguments actually sent, and any error.
111+ func invokeTool (ctx context.Context , tool tools.Tool , args map [string ]any ) (string , map [string ]any , error ) {
112+ if tool .Handler == nil {
113+ return "" , args , fmt .Errorf ("tool %q is not available in code mode" , tool .Name )
114+ }
115+
116+ var schema struct {
117+ Required []string `json:"required"`
118+ }
119+ if err := tools .ConvertSchema (tool .Parameters , & schema ); err != nil {
120+ return "" , args , err
121+ }
122+
123+ // Strip nil optional arguments that goja passes for omitted parameters.
124+ filtered := make (map [string ]any )
125+ for k , v := range args {
126+ if slices .Contains (schema .Required , k ) || v != nil {
127+ filtered [k ] = v
135128 }
129+ }
136130
137- tracker .record (ToolCallInfo {
131+ arguments , err := json .Marshal (filtered )
132+ if err != nil {
133+ return "" , filtered , err
134+ }
135+
136+ result , err := tool .Handler (ctx , tools.ToolCall {
137+ Function : tools.FunctionCall {
138138 Name : tool .Name ,
139- Arguments : nonNilArgs ,
140- Result : result .Output ,
141- })
139+ Arguments : string (arguments ),
140+ },
141+ })
142+ if err != nil {
143+ return "" , filtered , err
144+ }
142145
143- return result .Output , nil
146+ if result == nil {
147+ return "" , filtered , nil
144148 }
149+ return result .Output , filtered , nil
145150}
0 commit comments