Skip to content

fix(native-chat): put Continue in the card that says the reply stopped - #27097

Merged
brennanb2025 merged 3 commits into
mainfrom
brennanb2025/continue-in-stop-card
Oct 11, 2026
Merged

brennanb2025 merged 3 commits into
mainfrom
brennanb2025/continue-in-stop-card

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 3 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​186 $\color{#cf222e}{\Huge{\mathbf{−}}}$​17 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​169
Prod 10 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​63 $\color{#cf222e}{\Huge{\mathbf{−}}}$​50 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​13

ELI5

When Orca quits, crashes, or restarts for an update while an agent is replying, the native chat keeps the cut-off reply and shows a small card under it that says what happened ("Orca on Local Mac stopped unexpectedly while this response was in progress."). The way to pick the reply back up is a Continue button. That button lived somewhere else: a separate, faint row above the message box, often sitting outside the chat column. It was easy to miss and looked unrelated to the card that explains the stop.

Continue now sits inside that card, on the same line as the sentence, as a filled button with a play icon.

What Changed

Before: the card said the reply stopped, and a small ghost-style (no background) "Continue" button sat in its own row just above the message box, right-aligned to a fixed 56rem width that didn't match the chat column. Nothing tied it to the card.

After: the card reads like ⓘ Orca on Local Mac stopped unexpectedly while this response was in progress. [▶ Continue]. The separate row above the message box is gone. Clicking Continue works as before: the button disappears and the agent picks the reply back up. If the host can't continue, there is no button and the card says "You can continue in this conversation", the same as before.

Paired server with no name: the card used to fall back to the host's own stored sentence, which ends in "You can continue in this conversation." With the button now in the same card, that would say the same thing twice. Such a server is now called "the remote server" ("Orca on the remote server stopped unexpectedly while this response was in progress."), so the card is worded from the stop's cause exactly like a named machine. One new translated string, in all six locales.

Mechanism:

  • The chat already hands its transcript rows a small context object about Orca stops (NativeChatOrcaStopView: machine name, whether the host can continue). It now also carries which cut-off turn Continue is offered on (offeredTurnItemId) and a continueNow handler.
  • NativeChatNoticeRow, which draws the card, already knows the turn its stop row belongs to (block.orcaStop.turnItemId). When that matches the offered turn, it renders NativeChatInterruptedContinueButton beside the sentence. Only the card for the latest cut can match, so there is at most one button.
  • useNativeChatInterruptedContinuation is unchanged in what it decides (when Continue is offered, what a click sends, the failure line in the composer). continueNow is a plain useCallback over values that are already stable, so the context only changes when what the rows show changes, and transcript rows don't re-render on every chat render.
  • NativeChatInterruptedContinue (the old standalone row) is removed from NativeChatStructuredSession.

Why

This replaces #27042, which kept the separate row and only lined it up with the chat column. Lined up or not, the button still sat away from the sentence that explains why you'd press it.

Where this differs from the common pattern, labelled:

  • Intended: the action is in the transcript card, not the message box. The common pattern keeps resuming in the message box and puts no action in the transcript. Putting Continue in the card ties the action to the sentence that explains it, and matches Orca's own precedent of the Sign in button inside the same kind of card. It is safe to keep because sending a message still continues the chat, so a user who doesn't see the button (for example, scrolled up in history) loses nothing.
  • Intended: the button scrolls with the card. The old row was always mounted above the message box. The offered cut is always the latest turn, so its card is at the bottom of the transcript where the user already is. Stop cards never fold away. While a failed transcript read is being retried the transcript (and the button) is covered, but sending still continues.

The button is the default (primary) variant at xs size: primary because it is the one affirmative action in that state (a ghost button in muted card text is why it went unnoticed), xs to match the card's text row height per the style guide.

Linked Issue

None. Supersedes #27042 (follow-up to #25675, which added Continue).

Visual Proof

Captured live on a hidden test copy of Orca (macOS), with OpenCode talking to a local stand-in model. Orca was force-quit mid-reply, then reopened.

Before (main): Continue sits in its own faint row above the message box, apart from the card.

Before: Continue in its own row above the message box

After, dark: Continue is inside the card, on the same line as the sentence. Nothing above the message box.

After, dark theme

After, light:

After, light theme

After, narrow window (1000 px wide): the sentence wraps to three lines and the button stays inside the card.

After, narrow window

After clicking Continue: the button goes away, the agent picks the reply back up, and no error appears in the message box.

After clicking Continue

Testing

  • NativeChatNoticeRow.test.tsx: the card for the offered cut shows Continue next to its sentence and clicking it calls the handler; a card for a different turn shows no button; an unnamed paired server is worded from the cause.

  • NativeChatStructuredSession.orca-stop-continue.test.tsx (new): renders the real session, hook, context and rows with a journal holding an Orca-stop cut, and asserts exactly one Continue, beside the stop sentence, and no "You can continue" text. Fails if the unnamed-server wording is reverted.

  • NativeChatInterruptedContinue.test.tsx: existing behaviour tests (when Continue is offered, what it sends, refusals, the composer failure line) now drive the button from the view the rows receive.

  • 22 related test files (290 tests) pass on the tree merged with current main; orca-ci-checks (lint, code quality, localization, ratchets, typecheck) pass.

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

AI Disclosure

Review

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Renderer-only change. Same on macOS, Linux and Windows, and for local, SSH and paired-server chats: which chats get Continue is still decided by the host's capability and the journal, exactly as before. No data or wire changes. The only other visible change is the wording for a paired server with no name (see What Changed).

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

… reply

Continue sat in its own row above the message box, away from the
reply it continues and often outside the chat column. It now sits
inside the transcript's notice card that says why the reply stopped,
as a filled primary button beside that sentence.
- A paired server with no name is called "the remote server", so the card
  words the stop from its cause instead of the host's stored "You can
  continue in this conversation." beside the Continue button.
- Continue is an xs primary button that fits the text row without a margin
  workaround.
- continueNow is a plain useCallback: its inputs (target, session id, the
  composer error reporter) are already stable.
- Test the real chain: a cut journal through the structured session shows
  exactly one Continue, inside the stop card.
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review status: ready for a decision (still a draft, not merged)

The problem. When Orca quits, crashes, or restarts for an update while an agent is replying, the chat keeps the cut-off reply and shows a card under it saying Orca stopped. The way to pick the reply back up is a Continue button. On main that button is a faint, borderless "Continue" in its own row above the message box, apart from the card and often outside the chat column, so it is easy to miss and looks unrelated to the card.

What changes for the user. Continue is now a filled button inside that card, on the same line as the sentence ("Orca on Local Mac stopped unexpectedly while this response was in progress. [▶ Continue]"). The separate row above the message box is gone. Clicking it works as before. A paired server that has no name now reads "Orca on the remote server stopped unexpectedly…" instead of the host's stored sentence, so the card never says "You can continue in this conversation" right next to the button.

Fixed during review (commit e3bba00, then one merge of current main at 067d41b):

  • For a paired server with no name, the card could say "You can continue in this conversation" and also show the button. It is now worded from the stop's cause, like a named machine, using one new string in all six languages.
  • The button was a larger size pulled into the line with a negative margin. It is now the small size that fits the text row, with no margin workaround.
  • The click handler no longer needs a ref plus a layout effect; it is a plain useCallback over values that were already stable.
  • New test that renders the real session with a stop in the journal and checks there is exactly one Continue, inside the card.
  • The PR description claimed that putting the action in the card is the common pattern. That was wrong: the common pattern keeps resuming in the message box. The description now labels the card placement as an intended difference and says why it is safe: sending a message still continues the chat.

Deferred (small, not blocking):

  • The button's centre sits about 2 px below the centre of the first text line (measured live: 24 px button in a 20 px line, top-aligned). It is barely visible. Fixing it means changing the card's line height or alignment for every notice, which isn't worth it here.
  • Continue scrolls with the card. If you scroll far up in history, or a failed transcript read is being retried, the button isn't on screen. On main the row above the message box was always there. Sending a message still continues, so nothing is lost.
  • Pressing Continue twice very fast could in principle send two continues. This was already true on main. React updates the screen right after the first click, so the button should be gone before a second one; not verified live.
  • Wording difference for an unnamed paired server: while Orca is still checking whether it can continue, the card leaves out "You can continue in this conversation." A named machine already behaves this way on main.

Verified

  • Two review rounds plus an architecture review, which recommended keeping the design. A pre-release checklist pass found no P0 or P1 issues.
  • 22 related test files (290 tests) and orca-ci-checks pass on the tree merged with main, and CI is green (13 passed, 17 skipped).
  • Live on a hidden test copy of Orca on a Mac (screenshots in the description). It was force-quit mid-reply and reopened, on main and on this branch:
    • On main, Continue sits above the message box.
    • On this branch there is exactly one Continue, inside the card, in dark and light themes and at a narrow window width.
    • The tooltip text is right.
    • Clicking Continue removes the button, the reply resumes, and no error appears.

Not verified: a real agent (QA used OpenCode with a local stand-in model), SSH or paired-server chats live (unit tests cover the unnamed-server wording), Windows and Linux rendering, and screen-reader output.

@brennanb2025
brennanb2025 marked this pull request as ready for review October 11, 2026 17:30
@coderabbitai

coderabbitai Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 94521842-eece-4b09-b1df-216d7a49ff39

📥 Commits

Reviewing files that changed from the base of the PR and between 3c71318 and 067d41b.


📒 Files selected for processing (13)
  • src/renderer/src/components/native-chat/NativeChatInterruptedContinue.test.tsx
  • src/renderer/src/components/native-chat/NativeChatInterruptedContinue.tsx
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.test.tsx
  • src/renderer/src/components/native-chat/NativeChatNoticeRow.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.orca-stop-continue.test.tsx
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.tsx
  • src/renderer/src/components/native-chat/native-chat-orca-stop-context.ts
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.



📝 Walkthrough

Walkthrough

The continuation hook now exposes the offered turn and action through its view. An Orca stop notice shows a Continue button when the stopped turn matches the offered turn. The structured session uses the updated hook interface and no longer renders the previous composer-area control. Unnamed remote servers receive localized labels. Tests cover the button, turn matching, stop message, and remote-server wording.


Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 067d4

The Continue action is placed in the matching stop notice, with no actionable merge-blocking risk established by the supplied evidence.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 7 files. (6 skipped: 6… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check Passed The title clearly summarizes the main change: moving Continue into the card that reports the interrupted reply.
Description check Passed The description is detailed and covers the user impact, implementation, rationale, linked issue context, visual proof, testing, compatibility, and checklist. The manual-testing checkbox and build-comm…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.

Full details: Docstring Coverage

Explanation

Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 7 files. (6 skipped: 6 unsupported.)


  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brennanb2025
brennanb2025 merged commit 37c2b43 into main Oct 11, 2026
58 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