hive-agent: dashboard Cancel and idle stalls for ACP agents
`/api/cancel` stopped a turn only by SIGINTing a child process whose argv0 is `claude`, so on an ACP agent it reported "no claude process to interrupt" and the turn ran on. The serve loop now stores the session's canceller on the `Bus` when the runtime has one, and `/api/cancel` uses it: the agent is sent `session/cancel`, and the next wake prompt carries the interrupted hint, as for a signalled claude turn. Without a canceller (claude), the SIGINT path is untouched. An ACP turn stopped by the idle watchdog (`HIVE_TURN_IDLE_SECS`) becomes `TurnError::AgentStall(note)`, handled like `ApiStall`: park for `HIVE_STALL_SLEEP_SECS`, requeue, and record `api_stall`. The TurnEnd note is the runtime's message (how long the agent was silent, whether it had to be killed, and that a silently retried provider error such as HTTP 429 looks like this), not the claude-specific `ApiStall` text. A cancel the agent ignores is a `Failed` turn. Refs #4391
This commit is contained in:
parent
bcbeb8ac9c
commit
91e47732a6
7 changed files with 115 additions and 9 deletions
|
|
@ -662,6 +662,9 @@ async fn serve_loop<S: Surface>(
|
|||
// The durable agent session, built once and reused for every turn +
|
||||
// idle compaction below (it's effectively stateless).
|
||||
let session = turn::make_session(&bus)?;
|
||||
if let Some(canceller) = hive_runtime::Runtime::canceller(&session) {
|
||||
bus.set_turn_canceller(canceller);
|
||||
}
|
||||
// Tracks the last observed pause state so the transitions get logged
|
||||
// once each instead of twelve lines a minute while parked.
|
||||
let mut was_paused = false;
|
||||
|
|
@ -1040,9 +1043,13 @@ async fn handle_turn_error_recovery<S: Surface>(
|
|||
S::requeue_inflight(socket).await;
|
||||
bus.emit_status("online");
|
||||
}
|
||||
if matches!(outcome, Err(turn::TurnError::ApiStall)) {
|
||||
// Idle watchdog killed claude on a suspected API stall. Park briefly to
|
||||
// let the API recover, then requeue — same shape as the rate-limit path.
|
||||
if matches!(
|
||||
outcome,
|
||||
Err(turn::TurnError::ApiStall | turn::TurnError::AgentStall(_))
|
||||
) {
|
||||
// Idle watchdog stopped the turn on a suspected API stall. Park briefly
|
||||
// to let the API recover, then requeue — same shape as the rate-limit
|
||||
// path.
|
||||
let secs = turn::stall_sleep_secs();
|
||||
bus.emit_status("api_stall");
|
||||
bus.emit(LiveEvent::Note {
|
||||
|
|
|
|||
Loading…
Reference in a new issue