Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/features/code-mode/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ agents:
ref: docker:github-official
```

Every toolset configured on the agent (the GitHub MCP server here) is wrapped: the model no longer sees the individual GitHub tools, only `run_tools_with_javascript`, with each wrapped tool documented as a JSDoc-commented function signature inside its description.
Every toolset configured on the agent (the GitHub MCP server here) is wrapped: the model no longer sees the individual GitHub tools, only `run_tools_with_javascript`, with each wrapped tool documented as TypeScript interfaces, type aliases, and function declarations inside its description.

To force Code Mode for every agent in a run regardless of their individual config, use the `--code-mode-tools` CLI flag (or the equivalent `--code-mode-tools` [runtime configuration flag](../cli/index.md#runtime-configuration-flags), accepted by `run`, `run --exec`, `serve api`, `serve mcp`, and the other commands that load an agent):

Expand Down
2 changes: 1 addition & 1 deletion pkg/tools/codemode/codemode.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func (c *codeModeTool) Tools(ctx context.Context) ([]tools.Tool, error) {
if isExcludedTool(tool) {
excludedTools = append(excludedTools, tool)
} else {
functionsDoc = append(functionsDoc, toolToJsDoc(tool))
functionsDoc = append(functionsDoc, toolToTypeScript(tool))
}
}
}
Expand Down
54 changes: 53 additions & 1 deletion pkg/tools/codemode/codemode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,26 @@ func TestCodeModeTool_Tools(t *testing.T) {
}`, string(outputSchema))
}

func TestCodeModeTool_TypeScriptDeclarationsInDescription(t *testing.T) {
t.Parallel()

tool := Wrap(&testToolSet{tools: []tools.Tool{{
Name: "find_item",
Description: "Find an item",
Parameters: map[string]any{"type": "object", "properties": map[string]any{"id": map[string]any{"type": "string"}}, "required": []any{"id"}},
OutputSchema: map[string]any{"type": "boolean"},
}}})

allTools, err := tool.Tools(t.Context())
require.NoError(t, err)
require.Len(t, allTools, 1)
assert.Contains(t, allTools[0].Description, "interface FindItemInput")
assert.Contains(t, allTools[0].Description, "id: string;")
assert.Contains(t, allTools[0].Description, "type FindItemOutput = boolean;")
assert.Contains(t, allTools[0].Description, "declare function FindItem(args: FindItemInput): FindItemOutput;")
assert.NotContains(t, allTools[0].Description, "Where Input follows the following JSON schema")
}

func TestCodeModeTool_Instructions(t *testing.T) {
t.Parallel()
tool := &codeModeTool{}
Expand Down Expand Up @@ -143,7 +163,7 @@ func TestCodeModeTool_CallHello(t *testing.T) {

result, err := allTools[0].Handler(t.Context(), tools.ToolCall{
Function: tools.FunctionCall{
Arguments: `{"script":"return hello_world();"}`,
Arguments: `{"script":"return HelloWorld();"}`,
},
}, tools.NopRuntime{})
require.NoError(t, err)
Expand All @@ -157,6 +177,38 @@ func TestCodeModeTool_CallHello(t *testing.T) {
require.Empty(t, scriptResult.StdOut)
}

func TestCodeModeTool_CallToolWithNonIdentifierName(t *testing.T) {
t.Parallel()
tool := Wrap(&testToolSet{
tools: []tools.Tool{
{
Name: "hello-world",
Handler: tools.NewHandler(func(ctx context.Context, args map[string]any) (*tools.ToolCallResult, error) {
return tools.ResultSuccess("Hello, World!"), nil
}),
},
},
})

allTools, err := tool.Tools(t.Context())
require.NoError(t, err)
require.Len(t, allTools, 1)
assert.Contains(t, allTools[0].Description, "declare function HelloWorld(args: HelloWorldInput): HelloWorldOutput;")

result, err := allTools[0].Handler(t.Context(), tools.ToolCall{
Function: tools.FunctionCall{
Arguments: `{"script":"return HelloWorld();"}`,
},
}, tools.NopRuntime{})
require.NoError(t, err)

var scriptResult ScriptResult
err = json.Unmarshal([]byte(result.Output), &scriptResult)
require.NoError(t, err)

require.Equal(t, "Hello, World!", scriptResult.Value)
}

func TestCodeModeTool_CallEcho(t *testing.T) {
t.Parallel()
type EchoArgs struct {
Expand Down
6 changes: 5 additions & 1 deletion pkg/tools/codemode/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,11 @@ func (c *codeModeTool) runJavascript(ctx context.Context, rt tools.Runtime, scri
}

for _, tool := range allTools {
_ = vm.Set(tool.Name, callTool(ctx, rt, tool, tracker))
call := callTool(ctx, rt, tool, tracker)
_ = vm.Set(tool.Name, call)
if name := typeName(tool.Name); name != tool.Name {
_ = vm.Set(name, call)
}
}
}

Expand Down
Loading
Loading