Oversized tool results — spill-to-disk + retrieval (spill_retrieve)
Every tool call an agent adapter makes (LoopAgentAdapter, AnthropicAgentAdapter, BedrockAdapter,
VertexAdapter — including MCP tools consumed via McpToolAdapter, which previously had no cap at
all) is funneled through one dispatch pipeline (src/core/toolDispatch.ts). A registered
post-execute policy (src/tools/spillPolicy.ts) measures every result in UTF-8 bytes; a result
over config.spillByteBudget (default 30000 bytes, CYBERINE_SPILL_BYTE_BUDGET) is written in
full under the run's own directory (.local/runs/<runId>/spill/, never the worker's disposable
worktree) and replaced with a bounded head+tail preview plus a spill://<runId>/<file> locator:
[run_bash result spilled: 812004 bytes exceeds the 30000-byte budget. Showing head+tail below;
call spill_retrieve with locator "spill://<runId>/run_bash-....txt" to read the full text (or a
byte range of it).]
--- head (first 6000 bytes) ---
...
--- tail (last 3000 bytes) ---
...The worker reads it back with the spill_retrieve tool (registered in both the implementer and
read-only toolsets), optionally slicing by byte offset/length instead of pulling the whole
thing. run_bash, code_execution, fetch_url, and delegate_subtask no longer truncate their
own output internally — they hand the FULL result to this one coordinated policy instead of each
discarding its own tail at a separate hardcoded size. read_file is excluded (it is already
line-windowed, so spilling it would set up a read → spill → retrieve(=read again) loop for no
benefit).
Known Limitations and Deferred Work (src/tools/spillPolicy.ts, src/core/spillStore.ts). A
tool call made outside the workflow engine (a standalone script, Orchestrator.dispatch without
Task.runId set) still spills correctly but lands under an ad-hoc _adhoc bucket instead of a
real run directory, since there is no run to scope it to. Spilled files are never swept — they
live as long as the run directory does; a very long-running fleet that dispatches many oversized
results will accumulate spill files under .local/runs/<runId>/spill/ until the run directory
itself is cleaned up by whatever process manages .local/runs retention. grep_files /
glob_files / list_dir keep their own independent count-based caps (max_results /
MAX_ENTRIES) rather than being converted to this byte-based policy — they are still covered as a
backstop (an oversized result from any of them is spilled too), but a worker that legitimately
needs more than 200 matches still has to narrow its query rather than paginate via retrieval.
Consume external MCP servers as tools — McpToolAdapter
Cyberine can consume any external MCP server's tools as orchestrator Tools (the consume-side mirror of npm run mcp, which exposes Cyberine itself). Configure servers by env; nothing connects when...
History compaction spills oversized tool results instead of truncating to 80 chars
For a worker with historyCompression: true on its WorkerProfile (see src/core/workerProfiles.ts), once accumulated message history exceeds historyCompressionBudget (default 8000 tokens,...