Skip to content

Show the answer a running step is writing, provisional until the receipt - #22

Merged
DrDrewCain merged 1 commit into
mainfrom
feature/agent-answer-pane
Sep 13, 2026
Merged

DrDrewCain merged 1 commit into
mainfrom
feature/agent-answer-pane

Conversation

@DrDrewCain

Copy link
Copy Markdown
Contributor

What

Pairs with native PR #108 (agents.text_stream). When the host advertises it, each step a run is working on shows a Live answer pane: the answer as the model writes it, read off /v1/agent-runs/{id}/steps/{step}/text/stream with the SDK's rules (contiguous sequences from the cursor, an id naming its sequence, a gap the only sanctioned jump, foreign fields refused, a terminal only with read_receipt). Withdrawn text is cleared and said; a gap is said rather than spliced; once the run has a receipt the pane yields to the verified result. Reconnects from the last sequence on request; never restarts a run; independent of the run view's callback identity so status polls cannot reopen the stream.

Files: src/agents/answer-stream.ts (reader + address), src/agents/AnswerPane.tsx, ApiClient.answerStream, capability agents.text_stream, README.

Verification

  • tests/agent-answer.test.ts (14): sequence and terminal; withdraw/gap/end; resume continuity; eight refusals (id, repeated sequence, error frame, cut stream, unknown kind, foreign field, terminal without receipt, gap off the cursor); capability parsing.
  • tests/api.test.ts (+1): cursor as query and Last-Event-ID, bad ids/cursor refused before any request, non-SSE and redirects refused, 401 expires the session.
  • scripts/test-agents.cjs (+4 journeys, desktop + mobile): the pane arrives with the provisional text and no result, then yields to the verified result with exactly one stream opened; withdrawn text cleared and said; no pane without the capability. 32/32 native journeys, 523 unit tests, tsc and vite build clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_012aNJobunWMPFEa8mjsFQqY

When the host advertises agents.text_stream, each step a run is working
on shows a Live answer pane: the answer as the model writes it, read off
the host's text/event-stream route with the same rules as the SDK --
sequences contiguous from the cursor, an id naming its sequence, a gap
the only sanctioned jump, foreign fields refused, a terminal only with a
read receipt. Text written before a tool call is withdrawn and the pane
says so; a gap is said rather than papered over; when the run has a
receipt the pane yields to the verified result, which decides the
outcome. The pane reconnects from its last sequence on request and never
restarts a run. It does not depend on the run view's callback identity,
so a status poll cannot reopen the stream.

Fourteen unit tests over the reader and capability, an API client test
for the request shape, and four browser journeys: the pane arrives and
yields to the verified result on desktop and mobile, withdrawn text is
cleared and said, and no pane without the capability. 32 native
journeys and 523 unit tests pass; typecheck and build are clean.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aNJobunWMPFEa8mjsFQqY
@DrDrewCain
DrDrewCain merged commit 97d7c1b into main Sep 13, 2026
2 checks passed
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