Skip to content

feat(acp): report run boundaries and background work over state_update - #150705

Open
IEatCodeDaily wants to merge 1 commit into
NousResearch:mainfrom
IEatCodeDaily:contrib/acp-background-state-update
Open

IEatCodeDaily wants to merge 1 commit into
NousResearch:mainfrom
IEatCodeDaily:contrib/acp-background-state-update

Conversation

@IEatCodeDaily

Copy link
Copy Markdown

What

ACP v2's state_update.background (agentclientprotocol #2738 / RFD #2452), carried over an ACP v1 connection as an opt-in extension notification _hermes-agent/state_update, modeled on _bb.dev/state_update (#149684) and extended with the background roster.

An editor opts in via clientCapabilities._meta["hermes-agent"].stateUpdate >= 1 (the bb.dev alias is honoured). Hermes then sends, per session:

  • running at every claim's message.start (with _meta.runId = the admission id), idle at message.complete (with stopReason)
  • background: the session's process.list roster as BackgroundWork items — running processes as running, exited as completed/failed with exitCode
  • an initial snapshot on every adopt (create/load/resume/reconnect/replay-gap), running when a turn is in flight

Known-follow-up rule

An exited process with a pending wake stays in the roster (terminal status) until the wake turn settles — the wake's message.start carries the async-result card (display_kind), and its message.complete finalizes the exit so it leaves the roster for good, even while the owner's finished-process registry still lists it. Removal is always preceded by a terminal report; an omitted/failed roster read omits the key (unreported), never an empty list (lying "quiet").

Safety

  • fully opt-in; no editor that does not declare the _meta sees any new notification
  • roster reads and ext_notification sends are boundary-guarded: a failure logs and skips, the projection pump never fails
  • per-session finalized bookkeeping is capped (32) and cleared on respawn

Tests

tests/acp_adapter/test_background_state_update.py — 18 tests, written red-first (16 failing before the change, all passing after): opt-in parse (both namespaces, version gating), running/idle boundaries with roster, stop-reason mapping, exited→completed/failed mapping with exitCode, hold-until-wake-settles (including registry eviction), roster-read failure fallback, notification failure isolation, adopt snapshots with/without an in-flight turn, no-opt-in silence. Neighbour pump tests (reattach/replay-gap/approval) pass unchanged; ruff clean.

Editors that declare clientCapabilities._meta["hermes-agent"|"bb.dev"].stateUpdate
(>= 1) now receive _hermes-agent/state_update notifications: running/idle at every
admission's message.start/message.complete (today message.start is dropped by the
projection), plus the session's process roster in ACP v2 state_update.background
shape, recomputed from process.list on every send.

Exited processes stay listed as completed/failed until the wake turn that reports
their result settles (the claim's message.start card names it), matching the v2
known-follow-up rule: finalized before removed, never silently dropped. Roster
reads and notification sends are boundary-guarded: neither can fail the pump.

This lets ACP v1 editors (T3 Code) await finite background commands: hold Working
while awaited work runs, wake with the result when it exits.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants