Skip to content

fix(agent-launch): preserve Codex session continuations - #18156

Closed
luisgonzaleznf wants to merge 10 commits into
stablyai:mainfrom
luisgonzaleznf:luisgonzaleznf/parrotfish
Closed

luisgonzaleznf wants to merge 10 commits into
stablyai:mainfrom
luisgonzaleznf:luisgonzaleznf/parrotfish

Conversation

@luisgonzaleznf

@luisgonzaleznf luisgonzaleznf commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

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:

  • Continuation launches set suppressStartupUpdatePrompt. One shared helper (agent-startup-update-prompt-suppression.ts) turns that into Codex's launch-only args; other agents get none.
  • The args are transient: they go on the command Orca types, but never into the saved resume configuration, so resuming the session later does not keep skipping updates. They are inserted before any -- that belongs to the agent (including one inside a command override such as codex -- … or mise exec -- codex -- …), so they stay flags instead of becoming a positional prompt.
  • Host-launched route (new since feat(agent-launch): the desktop AI buttons start their agent through agent.launch #25624): with default settings, a desktop continuation now starts through the host's agent.launch, and the host builds the Codex command itself. The window therefore sends a new optional suppressStartupUpdatePrompt field. 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.
  • The field counts toward the launch's replay fingerprint, like agentArgs, because it changes the argv. Absent keys are dropped from the digest, so existing fingerprints are unchanged.
  • Housekeeping to stay under the 300-line limit: LaunchAgentInNewTabResult, AgentLaunchSurface and shouldQueueTerminalFocusAfterMenuClose moved unchanged into launch-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

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

New tests cover each layer of the host route, plus the window routes:

  • launch-agent-startup-update-prompt.test.ts: a real store drives launchAgentInNewTab with default settings and asserts the agent.launchReplay params 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 → createTerminal options), 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 spawns codex … '-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

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

Notes

  • SSH / remote: the host builds the command for the execution host, so SSH and WSL workspaces get the args from the same path. The executor test covers the SSH-style downgrade from structured chat to terminal.
  • Mixed versions: the new agent.launch field is optional; an older host ignores it.
  • New-workspace launches: the flag is honoured for terminals launched into an existing workspace (what continuations use). It is deliberately not threaded into the create-worktree startup terminal, which no continuation uses.

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)

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

We 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 @coderabbitai full review.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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: 82ce7e0c-77f5-4eed-8886-2264ca57e405

📥 Commits

Reviewing files that changed from the base of the PR and between e6d01c5 and af4b9f0.

📒 Files selected for processing (2)
  • src/shared/agent-command-terminator.test.ts
  • src/shared/agent-command-terminator.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/shared/agent-command-terminator.ts
  • src/shared/agent-command-terminator.test.ts

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


📝 Walkthrough

Walkthrough

The 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. launchAgentInNewTab adds the Codex update-check argument when enabled. Session continuation enables this option. Tests cover command generation, wrappers, shells, and persistence behavior.

Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to af4b9

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)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 61.54% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 13 functions across 10 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy the coding requirements in issue #18153. launchAgentSessionContinuation passes suppressStartupUpdatePrompt: true for context-bearing continuation launches. The new-tab path con…
Out of Scope Changes check ✅ Passed The changed source and test files support issue #18153. The shared command-terminator logic is required to place the launch-only Codex arguments correctly without changing wrapper commands or persiste…
Title check ✅ Passed The title clearly identifies the main change: preserving Codex session continuations during agent launches.
Description check ✅ Passed The description includes all required sections, explains the user impact and implementation, links issue #18153, documents testing and platform considerations, and marks the UI proof as not applicable…

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: fc69c003-72c9-49f4-b4ea-43d434e8947f

📥 Commits

Reviewing files that changed from the base of the PR and between e5a1e79 and 370bb45.

📒 Files selected for processing (7)
  • src/renderer/src/lib/launch-agent-in-new-tab.test.ts
  • src/renderer/src/lib/launch-agent-in-new-tab.ts
  • src/renderer/src/lib/launch-agent-session-continuation.test.ts
  • src/renderer/src/lib/launch-agent-session-continuation.ts
  • src/shared/tui-agent-launch-command.ts
  • src/shared/tui-agent-startup-session-options.test.ts
  • src/shared/tui-agent-startup.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment thread src/shared/tui-agent-launch-command.ts Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • Transient launch args (transientAgentArgs) — resolveAgentLaunchCommand and buildAgentStartupPlan now accept launch-only args that are inserted before the -- terminator but excluded from commandWithoutSessionOptions, so they never leak into the persisted resume config (launchConfig.agentCommand). The re-quoted launchSuffix is byte-identical to the previous suffix.suffix when no transient args are supplied, so non-Codex launches are unchanged.
  • Codex update-check suppression — launchAgentInNewTab gates transientAgentArgs: ['-c', 'check_for_update_on_startup=false'] behind agent === 'codex' && suppressStartupUpdatePrompt, and launchAgentSessionContinuation sets 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 from launchConfig.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.

Pullfrog  | View workflow run | Using 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

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • Merged origin/main into the branch — the sole commit since the last review; conflicts were limited to launch-agent-session-continuation.ts and its test, resolved as a clean union rather than by dropping either side.
  • Preserved the Codex update-check suppression through the merge — suppressStartupUpdatePrompt: true survives alongside main's new promptDelivery: 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.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@luisgonzaleznf

Copy link
Copy Markdown
Contributor Author

Merge conflicts resolved — now MERGEABLE

Merged origin/main into this branch (merge f49b6f8a03). It was 1588 commits behind.

The PR's own diff is unchanged: git diff --stat origin/main HEAD still reproduces the original commit exactly — 7 files, 52 insertions, 15 deletions. Nothing was added to the diff by the merge.

The 2 conflicts

Both in the same spot, both resolved by keeping both intents rather than picking a side:

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>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — one edge case on the new terminator heuristic inline.

Reviewed changes

  • Spliced transient launch args before a command-override-owned -- in resolveAgentLaunchCommand, so -c check_for_update_on_startup=false stays a flag instead of becoming a positional when cmdOverrides.codex carries its own terminator.
  • Skipped the agentArgs insertion once the command override consumes the transient args (pendingTransientArgs = []), and kept commandWithoutSessionOptions on 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.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Comment thread src/shared/tui-agent-launch-command.ts Outdated
…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>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 — buildClaudeResumeLaunchCommand now consumes the same findAgentExecutableIndex and isSpliceSafeStartupCommand helpers 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.ts plus 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.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: db3aa226-0ed8-4955-843b-7587875f0a25

📥 Commits

Reviewing files that changed from the base of the PR and between 2d32ffc and e6d01c5.

📒 Files selected for processing (5)
  • src/shared/agent-command-terminator.test.ts
  • src/shared/agent-command-terminator.ts
  • src/shared/agent-resume-launch-command.ts
  • src/shared/tui-agent-launch-command.ts
  • src/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.

Comment thread src/shared/agent-command-terminator.ts Outdated
…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>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 -- literal now expects the agent's own --; on e6d01c5 the 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.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@luisgonzaleznf

Copy link
Copy Markdown
Contributor Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Already reviewed the last commit. Use @coderabbitai full review to rerun a review of the entire changeset.

luisgonzaleznf and others added 5 commits October 7, 2026 19:35
…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
@AmethystLiang

AmethystLiang commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

@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.

@nwparker

Copy link
Copy Markdown
Contributor

Thanks @luisgonzaleznf! The fix landed via #33355 (credited with Co-authored-by): Orca-driven Codex launches that submit their prompt after start now pass -c check_for_update_on_startup=false, threaded as a launch option rather than a command splicer, without touching the saved resume command. Closing as superseded.

nwparker added a commit that referenced this pull request Oct 25, 2026
…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>
@nwparker nwparker closed this Oct 25, 2026
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.

Continue in New Session loses handoff when Codex self-updates

3 participants