Skip to content

feat(native-chat): show each chat's resume as it happens, and start more at once - #26361

Merged
brennanb2025 merged 8 commits into
mainfrom
brennanb2025/resume-chats-live-progress
Oct 8, 2026
Merged

brennanb2025 merged 8 commits into
mainfrom
brennanb2025/resume-chats-live-progress

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

ELI5

When Orca restarts, it offers to resume the chats that were working. Until now it started only three agents at a time and said nothing until every chat had answered, so you saw "Resuming 21 chats" for a long time with no idea which ones were done. Now more agents start at once, the status bar counts up ("Resuming chats 9/21"), and clicking it opens the dialog showing where every chat stands.

What Changed

Before

  • Status bar: "Resuming 21 chats" stayed up until the slowest chat answered. One slow chat held it for up to a minute, even when the other 20 were already working.
  • Dialog: reopening it mid-resume showed every chat as a ticked, disabled checkbox and a "Resuming…" footer. There was no per-chat status.
  • Speed: at most 3 agents started at a time, so 21 chats started in about 7 rounds.

After

  • Status bar: reads "Resuming chats 9/21" and counts up as each chat answers. It never counts backwards.
  • Each chat's row, mid-resume: a gray spinner sits where its checkbox was. Hovering or focusing it says where that chat is ("Waiting to start · 2s", "Starting · 1s", "Waiting for a reply · 4s").
  • When a chat settles: its spinner turns into a check. A chat that failed or couldn't be confirmed shows the same failure row as before, with guidance, Retry and Open chat. Retrying a chat shows only its new status, not the old failure next to it.
  • Above the list: a short counts line and filters for All / In progress / Resumed / Need you. Chats that need you are listed first.
  • When the run finishes: the dialog shows the summary ("Resumed 18 of 21 chats") with every chat's result. If you had closed the dialog, the status-bar entry or the toast's Show opens that summary. It stays until you've opened and closed it, the next resume starts, or Orca restarts; after that they open the usual list of chats still needing you. If every chat resumed, the footer is just Done. One toast still summarises the whole resume.
  • A chat that no longer needs resuming (for example one you already opened elsewhere) drops out of the count instead of sitting there as a spinner.
  • Speed: the host starts one agent per CPU core instead of 3, and that limit is shared by every resume on the machine.

Mechanism

  • Still one request per resume. The app sends one agentSession.restartContinue for the whole selection, exactly as before, and the host still reserves, checks and settles the chats as one action.
  • The host publishes each chat's progress while that action runs. Each chat's entry in the status feed the host already sends gets an optional restartResume.phase: queued (waiting for a start slot), starting, then continued, refused or unconfirmed, or skipped for a chat the host left out. It exists only while the action runs and is never saved; the host clears it when the action returns, and it is dropped if the app loses contact with the host. The reply also lists the skipped chats, in case a status update was missed.
  • The app only presents it. It remembers, in memory only, which chats this resume asked for and how far each has got, so a chat never goes backwards (the host clears the progress just before its reply arrives). Finished results come from the host's reply, and "Need you" always comes from the host's current failure list. Dismissing a failure removes it, and a chat the host still lists as failed is always shown. The finished summary ends when you've viewed and closed it, the next resume starts, or Orca restarts.
  • Shared start limit. The per-request limit of 3 moved into the host-wide resume admission (StructuredAgentSessionResumeAdmission), sized to os.availableParallelism(). A chat holds its slot only until its agent takes the message.

Why

  • The slowness was the batch reply plus the cap of 3, not the work. The host already continued each chat separately; only the reply to the app waited for all of them. Publishing each chat's progress on the existing status feed lets the app show it as it happens without splitting the work up.
  • Why not one request per chat: an earlier version of this PR did that. Each request repeated the host's whole bookkeeping for every chat on offer: 21 chats meant 84 saves of the recovery file instead of 4, and under slow disk reads some selected chats were silently skipped. One action with live progress avoids both.
  • The cap of 3 had no measured basis. Once an agent takes its message its slot frees, so all chats end up running together within seconds anyway. The cap only made the last chats wait several rounds. One start per core still bounds startup CPU, and it has to be host-wide so two resumes can't double it.

How this compares with the common pattern for recovering agent sessions

  • Host-owned recovery, with each session's state published by the host — follows the pattern. One host action owns the resume, and the per-chat state comes from the host's own status feed, not from the app guessing.
  • The start limit is host-wide — partial match. The common pattern bounds recovery work per host with a fixed worker count. Intended difference: here the limit covers only starting agents and is sized to the machine's cores; running agents are already bounded by what the user had open.
  • The progress view inside the resume dialog is Orca-only — intended difference. The common pattern resumes in the background and shows status on each session's own row. Orca already had a "resume these chats?" dialog; this adds the per-chat status asked for in it, rather than a new surface.

Linked Issue

N/A (maintainer change; no issue)

Visual Proof

Before: status bar during a resume (no per-chat information anywhere):

before

After — all taken on commit 26484ecd928 (this PR's head) in the real app, run hidden on macOS, with 8 chats interrupted by a real quit and relaunch. Only the agent was replaced by a test stand-in (5 quick chats, 1 slow, 1 that refuses, 1 that never confirms); everything else is the real app. The raw folder:… heading is the test's folder workspace, not part of this change.

Status bar while resuming:

status bar

The offer after the relaunch:

offer

Dialog reopened mid-run from the status bar — a spinner where the slow chat's checkbox is, checks for the resumed ones, failure icons for the two that need you:

mid-run

Hovering a chat's spinner says where it is ("Starting · 5s"):

tooltip

The run finished while the dialog was closed; clicking the status bar opens the summary — "Resumed 6 of 8 chats", the two that need you keep their guidance, Retry, Open chat and dismiss:

summary

After that summary is closed, the status bar opens the usual list of chats still needing you:

after close

Testing

  • vitest: every resume test, host and app side (28 files, 292 tests). New tests cover:

    • one request for a 21-chat resume;
    • each chat's progress arriving before the reply;
    • progress cleared when the action returns or fails, or the connection drops;
    • counts never going backwards through the host's cleanup;
    • the finished summary staying until viewed and closed, the next resume, or a restart;
    • skipped chats leaving the count;
    • unconfirmed chats never shown as failed;
    • dismissal, and retry showing only the current status;
    • an older host without progress (spinners until the reply);
    • the shared start limit.
  • pnpm tc:node, pnpm tc:web and orca-ci-checks pass, except one oxlint max-lines error in tests/e2e/cross-version-wire/structured-agent-session-surface-manifest.ts. That error is already on main; this PR doesn't touch the file.

  • Review probes ran the real host, recovery file, status feed and dialog together for a 21-chat resume with mixed results.

  • Live app check (macOS, hidden window, commit 26484ecd928): real quit/relaunch with 8 interrupted chats, agent replaced by a test stand-in. Passed: the offer; the status bar only counting up (0/8 → 6/8 → 7/8 → done); the mid-run dialog (spinner in the checkbox slot, counts, filters); the hover and keyboard-focus tooltip; closing and reopening mid-run; the "Resumed 6 of 8" summary from the status bar after the run finished with the dialog closed; and the usual list after that summary was closed. An earlier build of this PR also passed dismissing a failure and retry showing only the new result.

  • Not verified live: clicking the toast's Show (the toast had closed before the check reached it; unit tests cover it), Windows and Linux (the Windows attempt could not create interrupted chats over the remote connection), real Claude/Codex agents, and a speed measurement with real agents.

  • I manually tested these changes locally (hidden app with a test stand-in agent; see above)

  • Automated tests added/updated

Review

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • Compatibility: one optional field on the existing status feed, and one optional list on the existing reply. No new request or stream message. Older apps ignore the field. A newer app talking to an older host shows spinners until the reply arrives, as before. The phone app reads the same feed but never starts a resume; it ignores the field.
  • SSH: structured chats resume on the local host only, so there is no remote path to change. Folder workspaces work the same as git worktrees.
  • Known limit (not new for manual resumes): a resume request holds at most 512 chats. Automatic resume now names the chats it resumes, so a launch with more than 512 interrupted chats is refused. You can still resume them in smaller selections.
  • Platforms: os.availableParallelism() exists on every supported platform. On a 2-core machine the limit is 2 (it was 3).

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)

…ore at once

Resuming interrupted chats sent one request for the whole batch, and the
host answered only after every agent had replied, so "Resuming 21 chats"
stayed up until the slowest chat answered and the dialog could only say
"Resuming…" for every row. The host also started 3 agents at a time.

The desktop app now sends one request per chat, so each chat's result
lands as soon as it has one. The host keeps one start limit across all
of those requests, sized to the machine's cores instead of a fixed 3.

The status bar reads "Resuming chats 9/21". Reopening the dialog mid-run
shows a gray spinner where each resuming chat's checkbox was, with its
step (waiting to start, starting, waiting for a reply) and time in the
tooltip, then a check or the failure row when it settles. A line above
the list counts where the chats stand, with filters for In progress,
Resumed and Need you.
Resolve resume dialog and locale conflicts while preserving the landed
machine/project/workspace tree and per-chat progress in the checkbox column.
Keep retained finished summaries, current failure actions, and group selection
of current eligible chats; union translations with main's wording.
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review and QA status

The problem. After Orca restarted with many interrupted chats, the status bar said "Resuming 21 chats" for up to a minute and clicking it showed nothing per chat. Two causes: the host started only 3 agents at a time, and it answered the app once, after the slowest chat.

What changes for you.

  • The status bar now counts up, "Resuming chats 7/8", and never counts backwards.
  • Clicking it opens the dialog with each chat's own state: a gray spinner where its checkbox was, with hover or focus words ("Waiting to start" / "Starting" / "Waiting for a reply" + time), a check once resumed, and the usual failure row with guidance, Retry and Open chat when it needs you.
  • When the run finishes you get "Resumed X of N chats". If the dialog was closed, the status bar or the toast's Show opens that summary, which lasts until you've opened and closed it, the next resume starts, or Orca restarts.
  • More agents start at once: one per CPU core instead of 3, shared by every resume on the machine.

What review changed. The first version sent one request per chat. Review proved that repeated the host's whole bookkeeping for every chat: 21 chats meant 84 saves of the recovery file instead of 4, and under slow disk reads some selected chats were silently skipped. It also kept a second copy of each chat's result that went stale (a dismissed failure stayed under "Need you"; the toast and the dialog disagreed). It now sends one request per resume, and the host publishes each chat's progress, in memory only, on the status updates it already sends. Later rounds fixed:

  • the count jumping back to 0 just before the host's reply arrived;
  • a skipped chat showing as a fake spinner;
  • two edge cases where a chat that wasn't part of this resume (resumed from another window, or retried when the reply was lost) was hidden or miscounted;
  • three disagreements between the toast and the dialog.

Live testing then showed that after a run finished with the dialog closed you saw only the failures, never the summary; Brennan chose to keep the summary, and that is fixed too. All fixes are covered by tests: 28 files, 292 tests, typecheck, and the repo's static checks. A final pre-release review (network, crashes and retries, performance, cross-platform, security, compatibility including the phone app) found nothing blocking.

Deferred (not blocking):

  • Over 512 interrupted chats: automatic resume now names the chats it resumes, so a launch with more than 512 of them is refused by the existing request limit. Resuming smaller selections works. Manual resumes already had this limit.
  • Selection header during a run: the dialog's "Select all" header (from the recently merged tree layout) still shows its selection counts during a run. Cosmetic.
  • Start limit not measured: one start per core hasn't been measured with real agents on 2-core or very large machines.
  • Existing long timeout: an agent that never answers can hold a start slot for a long time. That timeout is already on main.

Verified.

  • The real app, run hidden on macOS at commit 26484ecd928 (this PR's head): 8 chats interrupted by a real quit and relaunch, with only the agent replaced by a test stand-in.
  • Passed: the offer, the status bar counting up, the mid-run dialog (spinner in the checkbox slot of main's new layout, counts, filters), the hover and keyboard-focus tooltip, "Resumed 6 of 8" from the status bar after a closed-dialog finish, and the usual list after that summary was closed. An earlier build of this PR also passed dismissing a failure, retry showing only the new result, and one toast per resume.
  • Screenshots (all from 26484ecd928) are in the PR description.
  • CI on 26484ecd928: 20 checks pass, none fail (the rest are skipped for drafts).

Not verified.

  • Clicking the toast's Show in the live app (the toast had closed; unit tests cover it).
  • Windows and Linux: the Windows attempt couldn't create interrupted chats over the remote connection.
  • Real Claude, Codex or OpenCode agents.
  • Speed with real agents.

@brennanb2025
brennanb2025 marked this pull request as ready for review October 8, 2026 09:47
@coderabbitai

coderabbitai Bot commented Oct 8, 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: 87342aa1-5f29-45d3-83e7-f1d5b8464262
📥 Commits

Reviewing files that changed from the base of the PR and between b1cd858 and 26484ec.

📒 Files selected for processing (50)
  • src/main/native-chat/agent-session-wire/structured-agent-session-host-types.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-host.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-audience.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-cap.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-offer-withdrawal.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-ownership.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume-contract.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume-host.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume-progress.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume-progress.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume-runner.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume-wiring.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-restart-resume.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-status-feed.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-status-summary-equality.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-status-summary.ts
  • src/renderer/src/components/NativeChatResumeOnRestartAgentRow.tsx
  • src/renderer/src/components/NativeChatResumeOnRestartGroups.tsx
  • src/renderer/src/components/NativeChatResumeOnRestartModal.list.test.tsx
  • src/renderer/src/components/NativeChatResumeOnRestartModal.test.tsx
  • src/renderer/src/components/NativeChatResumeOnRestartModal.tsx
  • src/renderer/src/components/NativeChatResumeRunPanel.tsx
  • src/renderer/src/components/NativeChatResumeRunStatusIcon.tsx
  • src/renderer/src/components/NativeChatResumeRunSummary.tsx
  • src/renderer/src/components/NativeChatResumeTreeRow.tsx
  • src/renderer/src/components/native-chat-restart-action-notifications.test.ts
  • src/renderer/src/components/native-chat-restart-action-notifications.ts
  • src/renderer/src/components/native-chat-resume-bulk-progress.test.tsx
  • src/renderer/src/components/native-chat-resume-failed-chat-watch.test.ts
  • src/renderer/src/components/native-chat-resume-finished-run.test.tsx
  • src/renderer/src/components/native-chat-resume-modal.test-support.tsx
  • src/renderer/src/components/native-chat-resume-offered-chat-watch.ts
  • src/renderer/src/components/native-chat-resume-on-restart-outcome-toast.test.ts
  • src/renderer/src/components/native-chat-resume-on-restart-store.ts
  • src/renderer/src/components/native-chat-resume-run-status-watch.ts
  • src/renderer/src/components/native-chat-resume-run-view.ts
  • src/renderer/src/components/native-chat-resume-run.test.ts
  • src/renderer/src/components/native-chat-resume-run.ts
  • src/renderer/src/components/native-chat-resume-skipped-progress.test.tsx
  • src/renderer/src/components/native-chat-resume-tree-state.ts
  • src/renderer/src/components/status-bar/NativeChatResumeStatusSegment.tsx
  • 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
  • src/shared/agent-session-status-snapshot-fold.test.ts
  • src/shared/agent-session-status-snapshot-fold.ts
  • src/shared/agent-session-wire.ts

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


📝 Walkthrough

Walkthrough

The host now publishes per-session restart-resume phases, reports skipped sessions, and shares a start limit across resume requests. The renderer tracks run progress from status-feed updates and displays per-chat status, summary counts, filters, and completed-run views. Resume actions now send explicit session IDs. Tests and translations were updated for the new progress and outcome flows.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 26484

This change adds per-chat progress and summaries for resuming interrupted chats, and lets the host start more resumes at once. No concrete defect was identified, so the change appears ready to merge after normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.07% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 71 functions across 44 files. (6 skipped:… 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 changes: per-chat resume progress and increased concurrent startup capacity.
Description check ✅ Passed The description is detailed and covers the required user impact, implementation, rationale, issue exception, visual proof, testing, compatibility, platform considerations, and checklist. It also repor…
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 45.07% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 71 functions across 44 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
  • Autopilot · 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 884be9a into main Oct 8, 2026
61 checks passed
brennanb2025 added a commit that referenced this pull request Oct 10, 2026
Fits the paired-server resume work onto #26361's live per-chat resume
progress: each machine keeps its own resume run (main's run model, now
per machine), the dialog's run panel and the status bar's done/total
count sum across machines, main's offered-chat watch replaces the PR's
copy, and main's target-based chat opening carries the PR's pairing
fence.
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