execute: remove execute_tool; use execute_code {tool} steps instead

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-04-16 21:18:12 +02:00
parent a5fd0a8156
commit ab96de2771
5 changed files with 5 additions and 84 deletions

View File

@ -30,7 +30,7 @@ pkg/backend/ — Backend interface + implementations (Ollama, OpenAI, An
pkg/config/ — Config struct and loader
pkg/mcp/ — MCP client
pkg/tools/ — Server and Dispatcher interfaces; tool definitions
pkg/tools/execute/ — execute.Server: execute_code, execute_tool, execute_pipe
pkg/tools/execute/ — execute.Server: execute_code, execute_pipe
```
## Install
@ -72,11 +72,9 @@ Controls landrun sandboxing for `execute_code`. Created automatically with defau
## Tools
Three built-in tools via `execute.Server`:
Two built-in tools via `execute.Server`:
**`execute_code`** — run one or more code snippets in a sandbox. Accepts a `steps` array; multiple steps run concurrently and results are returned in submission order. Each step is either inline `code` (with optional `language`) or a named `tool` script. Supported languages: bash (default), python3, perl, lua, awk, sed, jq, ed, expect, bc. Accepts `timeout` (per-step, default 30s) and `sandbox` (default: `default`).
**`execute_tool`** — run a named script from `OLLIE_TOOLS_PATH`. Language detected from shebang. Accepts `tool`, `args`, `timeout`, `sandbox`.
**`execute_code`** — run one or more steps in a sandbox. Accepts a `steps` array; multiple steps run concurrently and results are returned in submission order. Each step is either inline `{code, language}` or a named `{tool, args}` script (language detected from shebang). Supported inline languages: bash (default), python3, perl, lua, awk, sed, jq, ed, expect, bc. Accepts `timeout` (per-step, default 30s) and `sandbox` (default: `default`).
**`execute_pipe`** — run a sequential pipeline, chaining each stage's stdout to the next stage's stdin. Each stage is `{code}`, `{tool, args}`, or `{parallel: [...]}` for concurrent fan-out within a stage. Accepts `timeout` (per-stage) and `sandbox`.

View File

@ -106,8 +106,6 @@ func (e *Server) Dispatch(ctx context.Context, name string, args json.RawMessage
switch name {
case "execute_code":
return dispatchExecuteCode(ctx, e, args)
case "execute_tool":
return dispatchExecuteTool(ctx, e, args)
case "execute_pipe":
return dispatchExecutePipe(ctx, e, args)
default:

View File

@ -1,7 +1,7 @@
package execute
// execute_pipe constructs a pipeline of execute_code and execute_tool calls
// to enable the composition of tools and arbitrary code.
// execute_pipe constructs a sequential pipeline of code and tool steps,
// enabling composition of named scripts and arbitrary inline code.
import (
"context"

View File

@ -94,34 +94,6 @@ Examples:
}
}`),
},
{
Name: "execute_tool",
Description: `Run a named tool script from the tools directory.
Usage:
- Scripts located in: ollie/t (default: $HOME/mnt/ollie/t)
- Supported languages: bash, python3, perl, awk, sed, ed, jq, expect, bc, lua (detected from shebang)
- Use for named scripts, not inline shell commands
- Default timeout: 30 seconds
Tool Discovery:
- List tools: execute_code with 'ls ollie/t'
- Check script permissions before execution
Examples:
- Run bash tool: tool='script.sh', args=['arg1', 'arg2']
- Run python tool: tool='process.py', args=['--input', 'data.txt']`,
InputSchema: json.RawMessage(`{
"type": "object",
"required": ["tool"],
"properties": {
"tool": {"type": "string", "description": "Name of the tool script in the tools directory."},
"args": {"type": "array", "items": {"type": "string"}, "description": "Arguments for the tool script."},
"timeout": {"type": "integer", "description": "Timeout in seconds (default: 30)."},
"sandbox": {"type": "string", "description": "Sandbox name (default: default)."}
}
}`),
},
{
Name: "execute_pipe",
Description: `Run a sequential pipeline, chaining each stage's stdout to the next stage's stdin.

View File

@ -1,12 +1,6 @@
package execute
// execute_tool is a specific case of execute_code, such that the name of the
// script passed to `tool` is loaded into memory from `$OLLIE_9MOUNT/t/` and
// run with Execute(...).
import (
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
@ -171,44 +165,3 @@ func ReadTool(name string) (string, error) {
return string(data), nil
}
func dispatchExecuteTool(ctx context.Context, e *Server, args json.RawMessage) (string, error) {
var a struct {
Tool string `json:"tool"`
Args []string `json:"args"`
Timeout int `json:"timeout"`
Sandbox string `json:"sandbox"`
}
if err := json.Unmarshal(args, &a); err != nil {
return "", fmt.Errorf("execute_tool: bad args: %w", err)
}
if a.Tool == "" {
return "", fmt.Errorf("execute_tool: 'tool' is required")
}
if !e.allowed("execute_tool", fmt.Sprintf("execute_tool: %s %s", a.Tool, strings.Join(a.Args, " "))) {
return "", fmt.Errorf("execute_tool: denied by user")
}
toolCode, err := ReadTool(a.Tool)
if err != nil {
return "", err
}
language := detectLanguage(toolCode)
code := toolCode
if len(a.Args) > 0 {
code = injectArgs(language, a.Tool, a.Args, toolCode)
// injectArgs for file-based languages produces a bash command snippet;
// run it as bash rather than trying to pass it as a raw program argument.
switch language {
case "awk", "sed", "jq", "ed", "expect", "bc":
language = "bash"
}
}
timeout := a.Timeout
if timeout <= 0 {
timeout = 30
}
sandbox := a.Sandbox
if sandbox == "" {
sandbox = "default"
}
return e.Execute(ctx, code, language, timeout, sandbox, true)
}