add built-in tool_list and tool_load tools

This commit is contained in:
ollie 2026-07-28 23:21:42 +02:00
parent ba9f605119
commit 6735a6ab26
2 changed files with 72 additions and 1 deletions

View File

@ -43,7 +43,7 @@ var languagePatterns = map[string][]*regexp.Regexp{
"": bashPatterns,
}
// Dispatch routes a shell tool call.
// Dispatch routes tool calls to the appropriate handler.
func (e *Server) Dispatch(ctx context.Context, name string, args json.RawMessage) (string, error) {
if e.OnPreDispatch != nil {
e.OnPreDispatch()
@ -52,6 +52,10 @@ func (e *Server) Dispatch(ctx context.Context, name string, args json.RawMessage
switch name {
case "shell":
return dispatchShell(ctx, e, args)
case "tool_list":
return dispatchToolList(ctx, e, args)
case "tool_load":
return dispatchToolLoad(ctx, e, args)
default:
return "", fmt.Errorf("unknown execute tool: %s", name)
}
@ -147,3 +151,44 @@ func dispatchShell(ctx context.Context, e *Server, args json.RawMessage) (string
}
return e.executeWithStdin(ctx, a.Cmd, "bash", timeout, sandboxName, false, "")
}
// dispatchToolList lists all available tools from the global registry.
func dispatchToolList(ctx context.Context, e *Server, args json.RawMessage) (string, error) {
if e.toolRegistry == nil {
return "", fmt.Errorf("tool_list: no registry available")
}
summaries := e.toolRegistry.Summaries()
if len(summaries) == 0 {
return "(no tools found)", nil
}
var out strings.Builder
for _, s := range summaries {
out.WriteString(s.Name)
if s.Description != "" {
out.WriteString(" — ")
out.WriteString(s.Description)
}
out.WriteString("\n")
}
return strings.TrimRight(out.String(), "\n"), nil
}
// dispatchToolLoad loads a tool into the current session.
func dispatchToolLoad(ctx context.Context, e *Server, args json.RawMessage) (string, error) {
var a struct {
Name string `json:"name"`
}
if err := json.Unmarshal(args, &a); err != nil {
return "", fmt.Errorf("tool_load: bad args: %w", err)
}
if a.Name == "" {
return "", fmt.Errorf("tool_load: name is required")
}
if e.toolRegistry == nil || e.sessionID == "" {
return "", fmt.Errorf("tool_load: no session registry")
}
if err := e.toolRegistry.Load(e.sessionID, a.Name); err != nil {
return "", fmt.Errorf("tool_load: %w", err)
}
return fmt.Sprintf("loaded: %s", a.Name), nil
}

View File

@ -150,6 +150,32 @@ timeout applies to each call (default: 30s). A non-zero exit is an error.`,
}
}`),
},
{
Name: "tool_list",
Description: `List all available tools that can be loaded.
Usage: {"name": "toolname"} — if name is provided, loads that tool.
Otherwise lists all tools with descriptions.`,
InputSchema: json.RawMessage(`{
"type": "object",
"properties": {}
}`),
},
{
Name: "tool_load",
Description: `Load a tool by name into the current session.
Usage: {"name": "toolname"}
After loading, the tool becomes a native callable function.`,
InputSchema: json.RawMessage(`{
"type": "object",
"required": ["name"],
"properties": {
"name": {"type": "string", "description": "Tool name to load."}
}
}`),
},
}
if e.toolRegistry != nil && e.sessionID != "" {