Repository navigation
fix(agent-launch): preserve Codex session continuations - #18156
luisgonzaleznf wants to merge 10 commits into
Conversation
|
Important Review skippedWe couldn't safely recover the incremental review. No full review was started, and the last reviewed checkpoint was preserved. Retry later, or explicitly request a full review by commenting You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review. 📝 WalkthroughWalkthroughThe launch pipeline now supports transient agent arguments that apply only to the current launch and are excluded from persisted resume configuration. Shared helpers locate agent-specific command terminators and validate safe insertion points. Priority: ➖ Normal Severity of issue fixed: Medium Merge Risk: ⚪ Minimal · up to The continuation update-check suppression is scoped to Codex launches and does not alter persisted configuration; the change is mergeable. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Team
Run ID: fc69c003-72c9-49f4-b4ea-43d434e8947f
📒 Files selected for processing (7)
src/renderer/src/lib/launch-agent-in-new-tab.test.tssrc/renderer/src/lib/launch-agent-in-new-tab.tssrc/renderer/src/lib/launch-agent-session-continuation.test.tssrc/renderer/src/lib/launch-agent-session-continuation.tssrc/shared/tui-agent-launch-command.tssrc/shared/tui-agent-startup-session-options.test.tssrc/shared/tui-agent-startup.ts
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Transient launch args (
transientAgentArgs) —resolveAgentLaunchCommandandbuildAgentStartupPlannow accept launch-only args that are inserted before the--terminator but excluded fromcommandWithoutSessionOptions, so they never leak into the persisted resume config (launchConfig.agentCommand). The re-quotedlaunchSuffixis byte-identical to the previoussuffix.suffixwhen no transient args are supplied, so non-Codex launches are unchanged. - Codex update-check suppression —
launchAgentInNewTabgatestransientAgentArgs: ['-c', 'check_for_update_on_startup=false']behindagent === 'codex' && suppressStartupUpdatePrompt, andlaunchAgentSessionContinuationsets that flag, so only context-bearing continuations skip the update prompt. - Tests — new terminator-placement test asserts both that the transient arg lands before
--and that it is absent fromlaunchConfig.agentCommand; the new-tab test now asserts the exact command string.
I verified check_for_update_on_startup is a real Codex boolean config key (OpenAI's config reference: "Check for Codex updates on startup"), and the -c key=value form matches the existing Codex session-option path in this codebase.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
…fish # Conflicts: # src/renderer/src/lib/launch-agent-session-continuation.test.ts # src/renderer/src/lib/launch-agent-session-continuation.ts
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Merged
origin/maininto the branch — the sole commit since the last review; conflicts were limited tolaunch-agent-session-continuation.tsand its test, resolved as a clean union rather than by dropping either side. - Preserved the Codex update-check suppression through the merge —
suppressStartupUpdatePrompt: truesurvives alongside main's newpromptDelivery: agent === 'claude' ? 'draft' : 'submit-after-ready', so Codex continuations still launch with the transient-c check_for_update_on_startup=false. - Adopted main's trust-preflight extraction and structured-launch routing refactor without losing the branch's transient-args threading in
resolveAgentLaunchCommand/buildAgentStartupPlan.
I re-ran the four affected suites (94 tests, all passing) and checked the merge against both parents: relative to origin/main the branch now adds only the suppression wiring, and relative to the prior head it adopts main's changes with nothing dropped.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
Merge conflicts resolved — now
|
| File | Resolution |
|---|---|
launch-agent-session-continuation.ts |
Kept main's promptDelivery: agent === 'claude' ? 'draft' : 'submit-after-ready' and this PR's suppressStartupUpdatePrompt: true. |
launch-agent-session-continuation.test.ts |
Same synthesis in the assertion — main's promptDelivery: 'draft' (the test launches agent: 'claude') plus this PR's suppressStartupUpdatePrompt: true. |
What I checked beyond the conflicts
launch-agent-in-new-tab.ts merged cleanly but absorbed 9 commits from main, including two structural refactors (#18248 unify local agent entrypoint routing, #19681 unify agent session launch). Git merges by text, not meaning, so I verified the mechanism survives: transientAgentArgs still sits on startupPlanBase, which is still spread into buildAgentStartupPlan before any routing branch — so the codex transient args reach every launch path. tui-agent-launch-command.ts, the core of this PR, took zero changes from main.
The PR's contract test (tui-agent-startup-session-options.test.ts) passes post-merge and directly asserts the mechanism: transient args inserted before the -- terminator, and excluded from the persisted launchConfig.agentCommand.
Validation
pnpm tc clean across all projects · oxlint clean on every touched file · 13 launch/startup suites, 172 tests, all passing.
A full-suite run is still finishing as I post this; its failures are being checked against a pristine origin/main checkout, and the ones seen so far reproduce there unchanged. I'll follow up here only if any turns out to be merge fallout rather than pre-existing.
Housekeeping
The pre-commit hook reformatted 14 files unrelated to this PR (trailing-whitespace strips inside string literals). All 14 were byte-identical to origin/main and untouched here, so that is main's own drift — discarded rather than committed, to keep this diff at its original 7 files.
For anyone merging an older branch in this repo
git merge-base HEAD origin/main came back empty. The checkout is a shallow clone grafted at 2026-09-08, after this branch's fork point, so git saw two unrelated histories — a merge would have been refused, or produced garbage that re-added every file. git fetch --deepen=1200 origin main fixes it. Note that "commits behind" is meaningless until you deepen: it read 951 before, 1588 after.
…ommand override A command override may carry its own `--`. Transient args were only inserted before a terminator found in agentArgs, so with such an override they were appended after it — the Codex update check still ran and the two tokens leaked in as positional arguments. Splice them into the override's original text at the terminator instead of re-emitting its tokens, which would requote env assignments and wrapper commands. The persisted resume command is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
ℹ️ No critical issues — one edge case on the new terminator heuristic inline.
Reviewed changes
- Spliced transient launch args before a command-override-owned
--inresolveAgentLaunchCommand, so-c check_for_update_on_startup=falsestays a flag instead of becoming a positional whencmdOverrides.codexcarries its own terminator. - Skipped the
agentArgsinsertion once the command override consumes the transient args (pendingTransientArgs = []), and keptcommandWithoutSessionOptionson the unspliced text so nothing transient reaches persisted resume config. - Added regression tests for a direct override with a
--and a wrapper-command override (CODEX_HOME=/tmp/x uv run codex -- literal); the affected suites pass (96 tests).
This addresses the prior CodeRabbit finding cleanly — the splice edits the original override text rather than re-emitting tokens, so env assignments and wrapper commands survive.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
…nator The previous splice took the first `--` on the line. When an override's `--` separates a wrapper from the agent (`mise exec -- codex`), that is the wrapper's terminator, so the args landed in the wrapper's argv and Codex never saw them — a shape that worked before, when the args were appended. Only a `--` after the agent can be the agent's. Locate the agent in command position first, reusing the resume module's walker, and fall back to its first basename match for wrappers without a `--` of their own (`uv run codex`). The walker and the splice-safety check move into a shared module that both launch paths now use. Unmodelable syntax, an untokenizable override, or no locatable agent now fall back to appending, as the resume path already does, instead of failing the launch. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Agent terminator detection (
agent-command-terminator.ts) — a new shared helper locates the agent executable in command position and takes the first--behind it, so a wrapper's terminator (mise exec -- codex) is no longer mistaken for the agent's and the transient args stay flags. - Resume-path dedup —
buildClaudeResumeLaunchCommandnow consumes the samefindAgentExecutableIndexandisSpliceSafeStartupCommandhelpers instead of its private copies; the extraction is behavior-preserving and its 104-test suite passes unchanged. - Fail-open fallback — an agent behind a wrapper with no
--of its own (CODEX_HOME=/tmp/x uv run codex) falls back to the first basename match, and unmodelable syntax or an unlocatable agent appends instead of splicing, matching the resume path's existing contract. - Regression tests — new
agent-command-terminator.test.tsplus wrapper-terminator, agent-name-suffix, and no-terminator cases in the startup-plan suite; all exact-equality and all would fail on the prior commit.
Verified the six affected suites (211 tests) pass on e6d01c5.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Advanced
Run ID: db3aa226-0ed8-4955-843b-7587875f0a25
📒 Files selected for processing (5)
src/shared/agent-command-terminator.test.tssrc/shared/agent-command-terminator.tssrc/shared/agent-resume-launch-command.tssrc/shared/tui-agent-launch-command.tssrc/shared/tui-agent-startup-session-options.test.ts
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
…gent When the agent is not in command position, the fallback took the first token named like it. A wrapper option value that shares the name comes earlier (`ssh -i ~/.ssh/codex -- devbox codex -- literal`), so the args were spliced before SSH's `--`. Take the last match instead. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
This run reviewed the sole commit since the prior pullfrog review (e6d01c5): af4b9f0 changed which basename match the wrapper fallback uses in findAgentTerminatorStart.
- Last-match fallback (
agent-command-terminator.ts) — when command-position detection fails (a wrapper with no--of its own), the fallback now scans for the agent name from the end rather than the start, so a wrapper option value that shares the agent's name (~/.ssh/codex) is no longer mistaken for the executable and no longer pulls the splice onto the wrapper's--. - Regression test —
ssh -i ~/.ssh/codex -- devbox codex -- literalnow expects the agent's own--; one6d01c5the first match resolved to the wrapper's--, so the assertion would fail there. - Unchanged contract — an unlocatable agent, an agent with no
--of its own, or unmodelable syntax still appends instead of splicing, and the approximation remains documented in the helper's comment.
Verified the two affected suites on this commit (25 tests, all passing). No open pullfrog threads remain on the PR; the earlier wrapper-terminator concern was addressed in e6d01c5 and resolved.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
|
@coderabbitai resume |
|
…fish # Conflicts: # src/shared/tui-agent-launch-command.ts
…ions Since stablyai#25624 a desktop "Continue in New Session" with Codex starts through the host's `agent.launch`, which builds its own command and never sees the window's startup plan. The launch-only `-c check_for_update_on_startup=false` therefore never reached the default route, and "Update now" still exited Codex before the handoff was pasted. The window now asks the host with a new optional `suppressStartupUpdatePrompt` field on `agent.launch`. The host carries it through the launch intent and the existing-workspace terminal surface into `createTerminal`, where `resolveAgentStartupPlanInputs` turns it into the same transient args the window uses, so they ride the typed command but not the resume config. Both sides read the per-agent args from one shared helper. The field is part of the launch fingerprint like `agentArgs`, and absent keys leave existing digests unchanged. An older host drops the field and behaves as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's new host-agents route (stablyai#25845) imports `LaunchAgentInNewTabResult` from the new-tab launcher, which this branch moved into `launch-agent-in-new-tab-result` to keep the launcher under the line limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fish # Conflicts: # src/main/agent-launch/agent-launch-executor.ts # src/renderer/src/lib/launch-agent-in-new-tab.ts
|
@brennanb2025 can review this PR. This is a useful feature. Codex update prompt sometimes breaks automations/orchestration too. For the reviewer, please make sure that this is the best place to inject this config and this is indeed the most elegant way to do it. |
|
Thanks @luisgonzaleznf! The fix landed via #33355 (credited with Co-authored-by): Orca-driven Codex launches that submit their prompt after start now pass |
…es (#33355) Orca-driven Codex launches that type their prompt after start (workers, automations, continuation/handoff, pane-spawn and other submit-after-ready flows) pass `-c check_for_update_on_startup=false`, so Codex's "Update now" screen can't block them or be accepted by Orca's Enter. User-typed launches and resumes are unchanged. Fixes #15814, #18153. Supersedes #18156. Co-authored-by: luisgonzaleznf <47302972+luisgonzaleznf@users.noreply.github.com>

ELI5
"Continue in New Session" starts a fresh Codex and then types a summary of your old session into it. If Codex first asks "Update available — update now?" and you say yes, Codex updates and quits. The summary has nowhere to go, so the new session starts with no idea what you were doing. This PR tells Codex not to ask about updates for these handoff launches. Normal Codex launches still ask.
What Changed
Before: Continue in New Session with Codex, pick "Update now" in Codex's startup prompt (Enter picks it by default). Codex installs the update and exits with "Please restart Codex". Orca's paste never finds a composer, and you see "Your prompt wasn't sent". The generated handoff is gone.
After: a continuation launch starts Codex with
-c check_for_update_on_startup=false, so the update prompt never appears and the handoff lands in the composer. Ordinary launches are unchanged and still get Codex's update check.Mechanism:
suppressStartupUpdatePrompt. One shared helper (agent-startup-update-prompt-suppression.ts) turns that into Codex's launch-only args; other agents get none.--that belongs to the agent (including one inside a command override such ascodex -- …ormise exec -- codex -- …), so they stay flags instead of becoming a positional prompt.agent.launch, and the host builds the Codex command itself. The window therefore sends a new optionalsuppressStartupUpdatePromptfield. The host carries it through the launch intent → the existing-workspace terminal surface →createTerminal→resolveAgentStartupPlanInputs, which adds the same transient args. Routes where the window builds the command (paired web host, queued startup command) use the window's plan as before.agentArgs, because it changes the argv. Absent keys are dropped from the digest, so existing fingerprints are unchanged.LaunchAgentInNewTabResult,AgentLaunchSurfaceandshouldQueueTerminalFocusAfterMenuClosemoved unchanged intolaunch-agent-in-new-tab-result.ts.Why
The update prompt is what destroys the launch, so preventing it on exactly the launches that carry undelivered context is the smallest fix. Alternatives considered:
An intent-level boolean on the wire (rather than raw extra args) keeps the per-agent knowledge in one shared place, and an older host simply drops the unknown optional field and behaves as before.
Linked Issue
Fixes #18153
Visual Proof
N/A for UI: nothing on screen changes in Orca. The change is the command Orca hands to Codex; the tests below assert the exact command line on each route.
Testing
New tests cover each layer of the host route, plus the window routes:
launch-agent-startup-update-prompt.test.ts: a real store driveslaunchAgentInNewTabwith default settings and asserts theagent.launchReplayparams carry the flag (and that an ordinary launch does not). Verified to fail with the window's forwarding line removed.agent-launch.test.ts(RPC →createTerminaloptions),agent-launch-executor.test.ts(including the structured-to-terminal downgrade, as over SSH),agent-launch-operation.test.ts(fingerprint),agent-launch-through-host.test.ts(params).terminal-creation-and-readiness-part-02.spec.ts: the runtime spawnscodex … '-c' 'check_for_update_on_startup=false'only when asked.agent-startup-plan-inputs.test.ts: the typed command gains the args while the resume config is unchanged.Ran: full
pnpm tc,check:code-quality:changed, and the launch-related suites (277 files, 5415 tests) on macOS. Not tested by hand against a live Codex update prompt, and not run on Linux/Windows; the change is platform-neutral argv plumbing reusing the existing quoting.AI Disclosure
Written with Claude Code (Claude Opus 5.5).
Review
Agent skill upstream boundary
Notes
agent.launchfield is optional; an older host ignores it.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)🤖 Generated with Claude Code