Skip to main content

Module runner

Module runner 

Source
Expand description

Unified agent runner — one-shot Claude Code spawn for the drone Agent block.

Spawns claude --print --output-format=stream-json as a non- interactive subprocess, drains its stdout through ClaudeTranslator, forwards each AgentEvent on the caller’s tx, and resolves the handle’s final_result with the structured AgentRunResult once the stream emits Done.

Headless and one-shot by design — the drone Agent block’s contract is “send task, wait for done, return result.” The interactive agent pane has its own PTY-based controller in blockcontroller/shell/lifecycle.rs; that path is NOT routed through this runner’s spawn — what’s shared is the translator + event shape, not the spawn function. (This used to cite a SPEC_UNIFIED_AGENT_TYPES spec that no longer exists anywhere in docs/; the pointer was dropped rather than replaced — see scripts/check-spec-citations.sh.) It DOES reuse this module’s commit-aware admission gate (admit_spawn / agent_commit_reserve_gb, pub(crate)) — see blockcontroller::shell::lifecycle::ShellController::start, which calls them right before spawning a claude/codex/ gemini/qwen interactive pane, mirroring this file’s run_agent gate.

Structs§

AgentRunHandle
Handle returned by run_agent. The caller already holds the mpsc::UnboundedReceiver<AgentEvent> they paired with the tx passed into run_agent; this handle adds the structured terminal value via final_result (drone Agent block’s downstream output).

Enums§

AgentError
Error returned by the runner.

Constants§

DEFAULT_AGENT_COMMIT_RESERVE_GB 🔒
Minimum free system commit (GB) required to admit a new agent spawn. Below this, launching another claude.exe risks pushing the system commit charge to its limit, where a failed allocation aborts the CEF host (Chromium OOM).
DEFAULT_CLAUDE_BIN 🔒
ENV_CLAUDE_BIN 🔒
Override the default claude binary name. Set to a full path (or a different binary) for testing or non-PATH installs.

Functions§

admit_spawn 🔒
Pure admission decision: is there enough free system commit to spawn another agent? None available (non-Windows, or the read failed) ⇒ admit — there’s no cheap commit limit to enforce. Strict < so a value exactly at the reserve is admitted. CEF-free / OS-free so it is fully unit-testable.
agent_commit_reserve_gb 🔒
append_capped_tail 🔒
Append chunk to a rolling tail buffer, compacting to the last cap bytes whenever it grows past 2 * cap (amortized O(1)). The exact final trim happens at EOF via trim_to_tail. Keeping the tail (not a prefix) matters because the CLI’s terminal error line is at the end of stderr.
drain_and_collect 🔒
Drain stdout line-by-line through ClaudeTranslator, forward every emitted event on tx, accumulate the terminal Cost / Done event payloads into an AgentRunResult, wait for the child to exit, and return the result.
drain_async_reader 🔒
Drain an arbitrary async reader of newline-delimited stream-json frames, forward every emitted AgentEvent on tx, and return an accumulator capturing the terminal Cost and Done values.
exit_signal 🔒
Extract the terminating signal (Unix only). On non-Unix there is no signal concept, so this is always None.
explain_failure 🔒
Await the captured stderr, classify the exit, log a warning, and render the human-readable explanation that becomes the run’s terminal error string. See docs/specs/SPEC_AGENT_FAILURE_DIAGNOSTICS_2026_06_11.md.
run_agent
Spawn claude --print --output-format=stream-json per the given AgentTask and AgentRef, drain its stdout through the shared ClaudeTranslator, forward each AgentEvent on tx, and resolve the returned handle’s final_result with an AgentRunResult constructed from the terminal Cost + Done events.
run_agent_with_bin 🔒
Internal entry point — same as run_agent but takes the claude binary path explicitly. Lets tests inject a known-nonexistent path to exercise the spawn-failure path without touching env vars (Rust 1.81+ flags std::env::set_var as unsound under concurrent test execution). The public run_agent is a thin shim that resolves the binary from $AGENTMUX_CLAUDE_BIN or the default.
trim_to_tail 🔒
Drop all but the last cap bytes of buf.