feat(acp/desktop): classify turn failures and persist them per agent#2240
Open
Orland00 wants to merge 4 commits into
Open
feat(acp/desktop): classify turn failures and persist them per agent#2240Orland00 wants to merge 4 commits into
Orland00 wants to merge 4 commits into
Conversation
Add a stable, machine-readable error_class discriminant (timeout, transport, agent_error, protocol, exited, cancelled, panic, error) to the turn_error and agent_panic observer payloads, additive alongside the existing outcome/error/code fields. Extracted into a pure classify_turn_failure(&PromptOutcome) so the mapping is unit-testable independent of the emit call sites, and it mirrors the existing outcome_label/is_transport_error groupings rather than inventing a new taxonomy. Signed-off-by: Orlando Lopez <orlando.lf19@gmail.com>
…discarding them activeAgentTurnsStore previously treated turn_error/agent_panic the same as turn_completed: endTurn() ran and the outcome/error/code payload was discarded, so the "Working in #channel" badge just vanished with no trace of the failure. Add a per-agent TurnFailure record (outcome, error, code, errorClass, timestamp) captured from the turn_error/agent_panic payload — including the new additive error_class field from the backend commit — and exposed via getLastTurnFailureForAgent / useLastTurnFailure. It is cleared only on a subsequent turn_completed (a successful completion is the "agent is healthy again" signal; a mere turn_started is not, so the badge doesn't flicker off and back on). Both new branches sit behind the same per-agent watermark gate as before, so the existing stale-replay guarantees (a replayed turn_error/agent_panic with a null turnId must not resurrect or re-trigger effects on a live/completed turn) are unchanged — verified with a new regression test. The failure map is also folded into the community-switch save/restore snapshot alongside the other four maps. Wired into ManagedAgentRow's existing StatusBlock, next to the process-exit-sourced `agent.lastError` surface, rendered through friendlyTurnErrorCopy so JSON-RPC codes still get friendly copy. Signed-off-by: Orlando Lopez <orlando.lf19@gmail.com>
Orland00
force-pushed
the
feat/1659-turn-error-classification
branch
from
July 21, 2026 17:23
2128600 to
dc4869b
Compare
Signed-off-by: Orlando Lopez <orlando.lf19@gmail.com>
Signed-off-by: Orlando Lopez <orlando.lf19@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1659.
Problem
Failed turns still burn tokens; when timeouts, transport flakes, auth expiry and panics all collapse into one vanishing "Turn error" badge, that spend is impossible to attribute or reduce. As discussed on the issue, the backend already derives a granular
outcome_label— the collapse happens in the desktop store, which handlesturn_error/agent_panicin the same fall-through asturn_completedand discards the entire error payload.Implementation
Two commits (split-able into separate PRs on request):
feat(acp)— additiveerror_classfield on theturn_errorandagent_panicpayloads: a stable machine discriminant (timeout/transport/agent_error/protocol/exited/cancelled/panic) derived in a pureclassify_turn_failure(&PromptOutcome)fn from the same data that drivesoutcome_labeland the existingis_transport_errorgrouping. Existing payload fields untouched; old frontends unaffected. No central schema doc exists for observer event kinds (grepped docs/, AGENTS.md, NOSTR.md), so the fn's doc comment is the documentation site, matching the existing convention.feat(desktop)—activeAgentTurnsStorenow splits the terminal-event fall-through:turn_completedclears a new per-agentlastFailureByAgententry;turn_error/agent_panicpersist{outcome, error, code, error_class, timestamp}. Both remain inside the pre-existing per-agent watermark gate, so the stale-replay guarantee (replayedturn_errorwith nullturnIdmust not resurrect state) is preserved — covered by a new regression test. The persisted failure renders inManagedAgentRow's existingStatusBlockthrough the existingfriendlyTurnErrorCopy, next to the process-exitlastErrorline — no new UI surface. Clearing happens on the next successful completion, not on turn start: a turn starting proves nothing about health and would make the badge flicker.Design notes:
errorClassis nullable on the frontend so a mixed-version fleet (older harness without the field) degrades gracefully tooutcome.resetActiveAgentTurnsStoreand the community-switch save/restore snapshot like the other four maps.Testing
classify_turn_failurebranch + payload assertions in the existingerror_outcome_emission_tests;cargo test -p buzz-acp580 passed,cargo clippy -p buzz-acp --all-targets -- -D warningsclean,cargo fmt --all -- --checkclean,cargo check --workspaceclean.pnpm -C desktop test3339 passed / 0 failed;typecheckandlint(biome) clean.Manual test: trigger any turn failure (e.g. kill the agent process mid-turn) → the agent row shows "Last turn error (exited): …" persistently; run a successful turn → the line clears.
Deferred
ManagedAgentRow's newmanaged-agent-last-turn-errornode (repo has no component-level tests for this row today) — happy to add a Playwright assertion if you want one.