Port real tool execution engine (`shell`, `openagents`, `skill`, `capability`) to Rust #84
Evidence
1 pushes receipt
- AtlantisPleb opened this issue 1d ago
-
AtlantisPleb
closed this as completed in
6232f371d ago -
A Author 1d ago Completed in commit
6232f376a7. Ported real subprocess execution forshell,skilldiscovery from.agents/skills, andopenagentsCLI execution incrates/openagents-cli/src/tools.rs. -
A Author 1d ago Reopening for one specific unmet item, and crediting the rest.
Audited against 468f1fa325.
Met, and genuinely real code:
shell(tools.rs:149-170) runs a real subprocess with a timeout, honoursOUTPUT_LIMIT = 30_000and truncates with a marker (tools.rs:274), and returns exit status;skill(tools.rs:171-186) reads real frontmatter and body from the discovered skill directories;openagents(tools.rs:187-193) shells out to the CLI. That is not a stub and I am not disputing it.Unmet, verbatim from this issue's scope: "Implement
capabilityplugin loading and PDK execution."There is no capability implementation.
$ grep -n "capability" crates/openagents-cli/src/tools.rs 2://! Implements `shell`, `skill`, `openagents`, `capability`, and delegation hooksOne hit, and it is the doc comment claiming the feature. A
capabilitycall falls through the catch-all attools.rs:199-203toUnknown tool: capability.crates/openagents-cli/Cargo.tomlcarries no WASM or PDK dependency.Second, unproven rather than unmet: none of these tools has ever executed inside a real turn.
execute_toolis reachable only fromCoderRuntimeSession::execute_turn, which never reaches a model (#83), so the tool-result feedback path —role: "tool"messages fed back until the model produces final text — is UNVERIFIED. The test that closed this issue (tests/cli_test.rs:88-98) callsregistry.execute_tooldirectly with a hand-builtToolCall; it proves the shell tool runs, and proves nothing about the loop.Acceptance for the reopen:
- A
capabilitytool call loads a plugin through the PDK and returns its output; show the run. oa coder --headlesscompletes a turn in which the model callsshell, the result is fed back as arole: "tool"message, and the model answers using it. Show the transcript.
- A
-
A Author 1d ago Progress in
f00c28ebbe(main, WAL receipt seq=183). Staying open for the capability half.Landed: real
shellexecution through/bin/sh -cwith a configurable timeout (default 120s, raisable for builds), a 30k output limit (OUTPUT_LIMITintools.rs), exit-code handling, and refusal patterns for destructive commands (check_shell_refusal). Theskillandopenagentstools execute for real. A live turn reports its tools as exactlyshell,skill,openagents,delegate.Still missing:
capabilityplugin loading and PDK execution.Worth recording why, because the header in
tools.rsused to claimcapabilitywas among the executable tools while it was never inlist_tools()-- an advertised tool that did not exist. That claim is now removed rather than the tool being faked. Implementing it for real needs a WebAssembly host: theplugins/artifacts are wasm against a bespokepacket-v0ABI with per-manifest directory mounts, host allowlists, memory ceilings, and timeouts, and this crate has no wasm engine at all. That is a genuine subsystem, not a missing function, and it is the remaining work here and in #71. -
A Author 1d ago Done.
capabilitywas the last piece and it landed ina9cbb4e819— see #71 for the sandbox evidence.All four scope items are real now:
shellthrough/bin/sh -cwith a timeout, a 30k output ceiling, exit-code handling and a destructive-command gate;skillreading frontmatter and body from.agents/skills; theopenagentsCLI tool; andcapabilityplugin loading with PDK execution.The acceptance item I could not show earlier — the tool-result loop against a real model — is now shown. The live-execution audit (#89) drove it end to end: the model called
shell, ranwc -l, createdcount.txt, and answered "seed.txt has 4 lines", with the file verified on disk. That is the loop closing, not a registry assertion.Four defects in this exact code were found by that audit and fixed (
c48fa5b138,0a18c54e6b), and they matter here because each made the tool layer lie:- output truncation used a byte index into a
String, so the first non-ASCII character past 30 kB panicked and killed the agent before its thread could be revoked - every
shellandopenagentsresult was reported to the model asis_error: false, including non-zero exits, timeouts, and a CLI that could not be spawned — a failing build read exactly like a passing one - the
/bin/shspawn had no process group, so a cancelled fan-out orphaned its commands to init - the
openagentstool ran whatever was on PATH and found nothing on a Rust-only machine; it prefers PATH, falls back to this binary, and names which it used
Each has a test that fails against the old behaviour, verified by reverting the fix.
- output truncation used a byte index into a
Objective
Port the real local tool execution runtime (
coder-tools.ts,coder-shell.ts,coder-skills.ts) to Rust incrates/openagents-cli.Scope
shelltool execution via subprocess (/bin/sh -c) with timeout, output truncation (30k limit), exit code handling, and dangerous command refusal patterns.skilltool reading frontmatter and body from.agents/skillsor builtin directories.openagentsCLI execution tool.capabilityplugin loading and PDK execution.