Repository navigation
fix(agents): a resumed agent's chat is readable on the phone before its first new turn - #29664
Merged
Merged
Conversation
…ts first new turn (#10923)
…keep it through terminal evidence
Contributor
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 47 seconds. View limit details
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. Comment |
8 of 9 tasks
This was referenced Oct 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ELI5
When Orca resumes an old Codex conversation in a terminal, the phone's chat view showed nothing until you typed a new message. Orca started that resume itself, so it already knew which conversation the terminal holds. It now says so right away, and the phone (and anything else that reads agent status) can open the saved conversation immediately.
What Changed
Before: a resumed Codex session (desktop "Resume", a restart's cold restore, or any
terminal.createthat carries a resume session) was listed to the phone with no agent session at all. Phone chat had no transcript to ask for and stayed on its empty state until the user sent a message from the terminal. Claude did not have this gap, because Claude reports its session as soon as it starts.After: the moment Orca spawns a terminal that resumes a known session, the host records that session in its agent-status store as an identity-only row (the same kind of row Orca already keeps for a finished agent's resume identity). The phone's
session.tabs.listrow carriesagentTypeandagentStatus.providerSessionstraight away, andnativeChat.readSessionreturns the saved conversation. The agent's own first hook replaces the row as usual.Mechanism:
src/main/ipc/pty/pane/resume-launch-identity.tsis called from both spawn paths, the rendererpty:spawncommit and the runtime-controller commit. It seeds only for a fresh local spawn of a resumable agent with a valid resume session. It skips reattached processes, SSH panes (their relay owns those rows), Codex resumes that fell back to a fresh session, and Pi-family resumes that have no transcript file.AgentHookServer.recordLaunchResumeIdentity(server-ingest-terminal.ts) writes the row with observation originlaunch. It never overwrites a row the agent reported after the launch, and it marks the row so that a host restart before the first turn keeps it. The seed runs only after the spawn has committed, so a rejected spawn leaves nothing behind. Terminal evidence (OSC or process) that starts the first turn keeps the seeded session, because the seed'sdoneis a placeholder, not a finished turn.terminal.ensureAgentSession(a paired desktop or web client choosing "Resume" against a remote server, which is [Bug]: "Resume in Worktree" opens in Terminal despite Default view = Native, and chat view stays empty until a message is sent #12904's path) now passes its session to the spawn asresumeProviderSession, as the other host-built resume launches already did. That lets this path seed too, and gives its Codex resume the same Codex-home selection the local resume gets.Root cause: Codex runs its
SessionStarthook only when its first turn begins (run_pending_session_start_hooksin codex-rscore/src/session/turn.rs), and every other Codex hook is turn-scoped. So a resumed Codex sends nothing until the user types. Meanwhile the resume session Orca passed to the spawn (resumeProviderSession) was used only to choose the Codex home (spawn-preflight.ts,spawn-env-codex.ts). Nothing recorded it as the pane's identity.Wire compatibility: no wire change. The host publishes an existing optional field (
agentStatus.providerSession) earlier than before. Older phones already read it.Why
The execution host owns agent status in one store, and every reader (phone tab list, native chat,
worktree ps) joins on it. Seeding that store at the one place that knows the resume, which is the spawn, fixes every reader at once and follows the existing identity-only row model. Alternatives considered:codex resume --lastand cannot tell apart two panes in one folder.Linked Issue
Part of #10923 (also the "empty until you send one" symptom in #12904). Not a full fix; see Notes.
Visual Proof
N/A. This changes host-published status data, not UI. The phone renders the same chat view once the identity arrives; the e2e spec checks the phone's wire.
Testing
Reproduced first on fresh origin/main with a scripted phone client paired to an isolated headless
orca serve:providerSessionon main, andnativeChat.readSessionworks. The original headless-serve report is already fixed on main by the hook-row fallback.codex resume <id>(and--last) leaves the tab with noagentStatusuntil a message is sent. This is the failure fixed here.Tests:
tests/e2e/headless-serve-mobile-native-chat-identity.spec.ts: a phone paired to headless serve reads Codex and Claude chats, and reads a resumed Codex chat before its first turn. The resume case fails on main and passes with this change.src/main/agent-hooks/server-launch-resume-identity.test.ts: seeds the row, yields to the agent's own report, is replaced by the first hook, and survives a host restart. The restart case fails without the retention marker.src/main/ipc/pty/pane/resume-launch-identity.test.ts: the skip rules (reattach, SSH, dropped Codex resume, bad id, non-resumable agent, Pi without a file).terminal-creation-and-readiness-part-02.spec.ts:ensureAgentSessionpasses the session to the spawn.src/main/agent-hooks,src/main/ipc,src/main/runtime/session-constructionandorca-runtime.test.tsall pass single-worker. The static-analysis job steps were also run locally.Verified live, each in an isolated temp HOME and profile, background launch, no windows:
codex resume. The phone list carriesagentType: codexand the session id before any input, andnativeChat.readSessionreturns the transcript.Only in tests: the desktop renderer path and the restart path. Windows was not run.
AI Disclosure
Review
Agent skill upstream boundary
Notes
Not covered here, still open under #10923:
codex resumethe user types by hand: Orca did not launch it, so it does not know the session.resumeProviderSessionyet. The field already exists onterminal.create, so a later phone change can opt in.Codex review (gpt-6.1-sol, high), four rounds:
working. Fixing it would need a new persisted marker on status rows.SSH: SSH panes are skipped on purpose, because the relay on that host owns their status. Folder workspaces are covered because the seed is keyed by pane, not by git worktree.
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)