interrupted by user, not an error

pressing stop ended the turn with "Claude Code returned an error" — the agent
sdk reports interrupt() as an ordinary failed result, indistinguishable from a
real fault downstream. the sidecar now flags the session it interrupted and
rewrites that event to the existing durable 'stopped', which opencode already
emitted. escape stops the turn (bound to the chat subtree, not the document),
and the prompt comes back to the composer verbatim unless you've started typing
something else. history parity: claude files [Request interrupted by user] as a
user message, so the transcript reader maps those exact strings to the same
role instead of replaying them as something you typed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-07 01:18:57 +00:00
co-authored by Claude Opus 5
parent f3a3ae3b64
commit 29fc9722c1
9 changed files with 154 additions and 13 deletions
@@ -44,7 +44,9 @@ export type ClaudeSessionMessage =
isError?: boolean;
}
/** The seam between two parts of a merged `/clear` chain. `sessionId` is the part that ends there. */
| { role: 'divider'; sessionId: string };
| { role: 'divider'; sessionId: string }
/** A turn that was stopped. Claude files its own marker as a user message; the server unpicks it. */
| { role: 'interrupted' };
export type ClaudeSessionDetail = {
id: string;