Skip to content

[codex] Recover ACP runtime errors from snapshots#296

Draft
ijry wants to merge 1 commit into
xintaofei:mainfrom
ijry:codex/snapshot-last-error
Draft

[codex] Recover ACP runtime errors from snapshots#296
ijry wants to merge 1 commit into
xintaofei:mainfrom
ijry:codex/snapshot-last-error

Conversation

@ijry

@ijry ijry commented Jun 19, 2026

Copy link
Copy Markdown

Summary

This PR makes ACP runtime errors recoverable from the live session snapshot. The main user-visible case is a client that was offline or outside the replay window when the server emitted an AcpEvent::Error, such as:

ACP protocol error: Internal error: unexpected status 403 Forbidden ... rolling spend limit exceeded

Before this change, a live web client could show that error because it received the realtime event, while MCode/mobile or any reconnecting client could miss it and hydrate from a snapshot with no error detail.

Root Cause

SessionState already captured the latest AcpEvent::Error in last_error, but SessionState::to_snapshot() intentionally omitted it. That made the error delivery path realtime-only:

  • Online clients received AcpEvent::Error and updated ConnectionState.error.
  • Reconnecting/offline clients hydrated through LiveSessionSnapshot.
  • The snapshot did not include last_error, so clients that missed the realtime event had no durable source for the latest ACP runtime failure.

This is why a CodeG web session could show the spend-limit 403 under the input box, but an MCode/mobile client could show nothing or incomplete state after reconnect.

Changes

  • Expose SessionState.last_error as optional LiveSessionSnapshot.last_error.
  • Keep the field backward-compatible with serde(default, skip_serializing_if = "Option::is_none"), so normal snapshots omit it and older clients can ignore it.
  • Clear last_error when a new prompt enters Prompting, matching the existing frontend live reducer behavior where a new prompt clears the visible error scope.
  • Mirror the wire type in TypeScript as SessionLastError and LiveSessionSnapshot.last_error.
  • Denormalize snapshot last_error.message into SnapshotPatch.lastError.
  • Hydrate ConnectionState.error from fresh snapshots; for stale snapshots, only fill the error if the current live state does not already have a newer error.
  • Update the connection-context test mock to include the now-complete SnapshotPatch shape.

Compatibility / Client Guidance

The new field is optional and omitted when absent:

last_error?: { message: string; code?: string | null } | null

Native iOS/Android/MCode clients should treat last_error?.message as the snapshot recovery value for the same UI surface that currently consumes realtime ACP error events. The field is not an event replay replacement; it is the latest unresolved runtime error that lets a reconnecting client recover what it missed.

Clients should also preserve their realtime ordering rules: if a local state already observed a newer realtime error, an older/stale snapshot should not overwrite it.

Validation

  • cargo test --no-default-features --features test-utils --lib snapshot_carries_last_error_and_clears_on_next_prompt
  • pnpm test src/lib/snapshot-denormalize.test.ts src/contexts/acp-connections-context.test.tsx
  • pnpm exec eslint src/lib/snapshot-denormalize.ts src/lib/snapshot-denormalize.test.ts src/contexts/acp-connections-context.tsx src/contexts/acp-connections-context.test.tsx src/lib/types.ts
  • git diff --check

Note: the default cargo test --features test-utils path on Windows attempted to build the Tauri desktop target and failed before tests because ../out static assets were not present. The shared/server-side targeted command above avoids the desktop build-script asset requirement and exercises this ACP snapshot logic directly.

@ijry

ijry commented Jun 19, 2026

Copy link
Copy Markdown
Author
image 这种acp报错似乎如果其他端没实时在线获取到,比如App端掉线,过了很久才打开查看,看不到这个报错。需要写进to_snapshot。

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant