| Filename | Latest commit message | Latest commit date |
|---|---|---|
`Runtime` gets a fourth operation, `canceller()`: a handle that stops the turn in flight from outside `run`. The ACP backend returns one; claude returns `None`, because the harness stops a claude turn by signalling the `claude` process, and that path is unchanged. Both stops send the agent `session/cancel`: - `Canceller::cancel()`, when asked from outside. The turn then ends normally, reported with stop reason `cancelled` whatever reason the agent gives. opencode 1.15.10, for one, answers a cancelled prompt with `end_turn` (`acp/agent.ts` `prompt()` always returns `end_turn`). - The idle watchdog, once no `session/update` has arrived for `Config::idle_timeout`, the same field claude's watchdog reads. The turn fails with `AcpError::IdleTimeout`. An agent that has not answered the prompt 10s after `session/cancel` is killed (`IdleKilled` / `CancelIgnored`), and the next turn respawns it. The watchdog is also what ends a turn stuck on a provider HTTP 429. opencode 1.15.10 retries a retryable provider error with no attempt limit (`session/retry.ts` `policy`, `session/processor.ts` `Effect.retry`) and forwards neither `session.status` nor `session.error` over ACP (its `handleEvent` only handles `permission.asked` and `message.part.*`). So the ACP client sees nothing at all until the provider recovers. The `IdleTimeout` message says a silently retried provider error looks like this. Refs #4391 |
||
| .. | ||
| src | ||
| Cargo.toml | ||
| README.md | ||
hive-runtime
The layer an agent's turns are driven through: one Runtime interface
(run, compact, archive, canceller) with a backend per runtime.
- claude —
claude --printthrough thehive-claudecrate'sInfiniteSession. A pass-through: same spawn, same session handling, same errors. - acp — any Agent Client Protocol
agent, spawned from a command, args and env handed to it (
RuntimeSpec, read fromHIVE_RUNTIME/HIVE_ACP_COMMAND/HIVE_ACP_ARGS/HIVE_ACP_ENV). It knows no agent by name; which agent runs, and how it is configured, is decided in nix (services.hyperhive.agent.runtime,services.hyperhive.agent.acp.*).
Both backends report a turn through hive_claude::Sink in claude's
stream-json shape. The ACP backend translates session/update
notifications into it (text and thought chunks as whole blocks, tool calls as
tool_use + tool_result, MCP tools named mcp__<server>__<tool>), so the
harness's stream consumers read either backend unchanged. Context usage comes
from ACP usage_update.
The crate depends on no hyperhive binary crate, so hive-agent and
hive-subagent-mcp can both drive turns through it.
ACP backend: what it needs from the agent
mcpCapabilities.httpin itsinitializeresponse. The hyperhive tools are only served over HTTP, so an agent without it is refused at startup.loadSession, to pick its session back up after a harness restart. Without it every restart starts a new session.
ACP backend: stopping a turn
A turn is stopped with session/cancel: by the Canceller handle, or by the
idle watchdog once no session/update has arrived for
Config::idle_timeout. An agent that has not answered the prompt 10s later
is killed, and the next turn respawns it. A watchdog stop fails the turn
with AcpError::IdleTimeout (IdleKilled if the agent was killed). This is
the only way a provider error the agent retries without reporting it, such as
an HTTP 429, ends the turn.
ACP backend: not yet
compact returns Error::Unsupported.