mirror of
https://github.com/stablyai/orca.git
synced 2026-10-07 16:02:29 +00:00
feat(terminal): warn when a typed Codex joins Codex's shared server (STA-9051) (#24217)
* feat(terminal): warn when a typed Codex joins Codex's shared server Orca adds --no-daemon to the Codex it launches and to a codex typed in shells whose wrapper it controls, but a codex typed another way (fish, cmd.exe, a path-named binary) still joins Codex's shared server, which mixes up agent status across tabs. When a local pane's Codex is on that server, show a banner at the top of the pane with the command that turns auto-start off, a Copy button, "Don't show again" (a new setting next to the Codex server setting) and a per-pane dismiss. The banner takes layout space; the terminal refits below it. Main answers pty:isCodexOnSharedServer from the pane's outermost Codex command line (flags and subcommands that keep Codex embedded rule it out), the CODEX_HOME the pane launched with, and whether that home's server is live: a socket connect on macOS/Linux, the server's pid record plus creation time on Windows. The renderer asks only while the pane already shows Codex, on a short bounded ladder. Refs STA-9051 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: restore the Claude WSL trust-file fix (#23973) dropped by the banner commit Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(terminal): redesign the Codex shared-server banner and fix dialog Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(terminal): let the Codex shared-server fix run its commands The fix dialog now runs each step with the shared server's own Codex on the pane's CODEX_HOME, verifies the result (feature read back, server probed), and falls back to a copyable command on failure. Stopping asks first. Also: an apostrophe in a prompt no longer hides an opt-out flag, restored panes fall back to the saved pty id, and the IPC guards have a table test. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(terminal): give each fix step its own card and label the command it runs Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor(terminal): simplify the Codex shared-server banner after review - Read a subcommand only from Codex's first positional, so prompt words like "a", "update" or "review" no longer hide the banner. - Probe the server fresh on every ask; drop the probe cache. - Make the pty preload methods required and stub them on the web client, replacing the optional-method and paired-client checks. - Render the banner from the existing Codex pane portal loop. - Treat a non-zero or timed-out Codex command as failed; skip the read-back when the disable write failed. - Reserve the banner's space with a CSS :has() selector instead of a data attribute. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(terminal): make the Codex shared-server fix persist on Orca's mirror home - Step 1 now writes daemon_auto_start = false to the user's own Codex home when the pane runs on Orca's shared mirror home (as Windows panes do), then to the mirror home too; the mirror is rebuilt from the user's home on every launch, so a mirror-only write was lost. - The server probe is three-state (live / absent / unknown); stop reports success only once the server is proven gone. - The banner retires the one-time "runs Codex without its shared server" toast it contradicts. - A command line with no Codex program never counts as joining the server. - The fallback local PTY provider reports each pane's root pid. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(codex): keep Turn off in Orca's Codex home when ~/.codex has no config A pane on Orca's mirror home wrote the setting to ~/.codex first. With no ~/.codex the spawn failed on its cwd and Codex rejects a missing CODEX_HOME; and creating a config holding only this setting would make the next mirror replace every setting made in Orca's Codex. The mirror skips a missing or blank ~/.codex/config.toml, so write only the mirror home then. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(codex): promote [features].daemon_auto_start from Orca's Codex home Promotion now carries one [features] key alongside the [tui] keys, so a shared-server Turn off written in Orca's mirror home reaches ~/.codex/config.toml instead of being reverted by the next mirror. Table keys share one <table>.<key> scan for read, removal and upsert. Orca's own daemon socket override is never read as a user value, and a blank source config is seeded from the runtime like a missing one. * refactor(codex): run Turn off once, in the pane's own Codex home Settings promotion now carries the setting to ~/.codex, so the separate settings-home resolution and the two-home loop are gone. * fix(terminal): offer Stop server only after sharing is turned off Stopping while sharing is still on closes every sharing session, and the next Codex starts a new shared server. * fix(terminal): skip legacy mirror panes off Windows and quoted dotted keys A retained shared-home pane on macOS/Linux points at a mirror that is no longer promoted, so Turn off there would be reverted; name no home for it. A quoted top-level key such as "tui.theme" is one key, not [tui].theme. * fix(terminal): drop the Turn off note that promised the setting reaches Codex outside Orca Orca's tabs are what this fix is for; carrying the setting to ~/.codex is best-effort. * fix(terminal): keep the Turn off note that the setting also applies outside Orca It holds for nearly everyone; the rare Windows upgrade gaps don't justify hiding it. * fix(codex): promote Turn off to ~/.codex under an older Orca's baseline A pane on Orca's Windows mirror home writes daemon_auto_start = false into the mirror. A promotion baseline from an Orca that predates this key has no entry for it, so the next mirror pass kept the write as a conflict and then recorded it, and ~/.codex never got the setting. Turn off on a mirror-home pane now runs the same mirror pass a terminal launch runs before and after the write: the first records the key in the baseline, the second promotes the write to ~/.codex. The passes are synchronous, so they cannot interleave with a launch's pass. A failed pass is logged and does not fail Turn off, since the write still fixes Orca's tabs. Real-home panes are unchanged. --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
8b76683b40
commit
eefc49f7e3
@@ -0,0 +1,88 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { codexCommandLineJoinsSharedServer } from './codex-shared-server-command'
|
||||
|
||||
const NPM_LAUNCHER = 'node /Users/me/.npm-global/lib/node_modules/@openai/codex/bin/codex.js'
|
||||
const WINDOWS_LAUNCHER =
|
||||
'"node" "C:\\Users\\me\\AppData\\Roaming\\npm\\\\node_modules\\@openai\\codex\\bin\\codex.js"'
|
||||
const WINDOWS_NATIVE =
|
||||
'C:\\Users\\me\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex\\node_modules\\@openai\\codex-win32-x64\\vendor\\x86_64-pc-windows-msvc\\bin\\codex.exe'
|
||||
|
||||
describe('codexCommandLineJoinsSharedServer', () => {
|
||||
it.each([
|
||||
['bare native codex', 'codex'],
|
||||
['absolute native codex', '/Users/me/.local/bin/codex'],
|
||||
['platform binary', '/opt/codex/codex-aarch64-apple-darwin'],
|
||||
['npm node launcher', NPM_LAUNCHER],
|
||||
['node launcher with node flags', `node --no-warnings ${NPM_LAUNCHER.slice(5)}`],
|
||||
['Windows node launcher with quoted paths', WINDOWS_LAUNCHER],
|
||||
['Windows native child', WINDOWS_NATIVE],
|
||||
['Windows native child with args', `"${WINDOWS_NATIVE}" --model gpt-5`],
|
||||
['resume joins', 'codex resume --last'],
|
||||
['fork joins', 'codex fork'],
|
||||
['agents joins', 'codex agents'],
|
||||
['approval flags keep sharing', 'codex --dangerously-bypass-approvals-and-sandbox'],
|
||||
['model and approval values', 'codex -m gpt-5 -a on-request'],
|
||||
['a prompt', 'codex fix the flaky test'],
|
||||
['a prompt with the apply alias as a word', 'codex "fix a bug in the parser"'],
|
||||
['a prompt with a subcommand as a later word', 'codex "update the readme"'],
|
||||
['a prompt with review as a later word', 'codex "please review this"'],
|
||||
['a space-joined prompt with subcommand words', 'codex please review and update a test'],
|
||||
['a prompt after a valueless flag', 'codex --yolo fix a bug'],
|
||||
['a Windows path with spaces', '"C:\\Program Files\\My Codex\\codex.exe" fix a bug'],
|
||||
['launcher args', `${NPM_LAUNCHER} resume --last`]
|
||||
])('%s joins the shared server', (_label, commandLine) => {
|
||||
expect(codexCommandLineJoinsSharedServer(commandLine)).toBe(true)
|
||||
})
|
||||
|
||||
it.each([
|
||||
['no Codex program', 'claude --resume'],
|
||||
['an empty command line', ''],
|
||||
['--no-daemon', 'codex --no-daemon'],
|
||||
['--no-daemon through the launcher', `${NPM_LAUNCHER} --no-daemon`],
|
||||
['--no-daemon on Windows', `${WINDOWS_LAUNCHER} --no-daemon`],
|
||||
['--oss', 'codex --oss'],
|
||||
['--remote', 'codex --remote ws://host:1'],
|
||||
['--remote=', 'codex --remote=ws://host:1'],
|
||||
['--profile', 'codex --profile work'],
|
||||
['-p', 'codex -p work'],
|
||||
['-p glued to its value', 'codex -pwork'],
|
||||
['--strict-config', 'codex --strict-config'],
|
||||
['--dangerously-bypass-hook-trust', 'codex --dangerously-bypass-hook-trust'],
|
||||
['--search', 'codex --search'],
|
||||
['--approve-for-me', 'codex --approve-for-me'],
|
||||
['--not-so-yolo', 'codex --not-so-yolo'],
|
||||
['--enable', 'codex --enable worktrees'],
|
||||
['--disable=', 'codex --disable=worktrees'],
|
||||
['-c', 'codex -c model="o3"'],
|
||||
['-c glued', 'codex -cmodel=o3'],
|
||||
['--config', 'codex --config model=o3'],
|
||||
['--no-daemon before a prompt', 'codex --no-daemon "a"'],
|
||||
['exec', 'codex exec "summarize"'],
|
||||
['exec alias', 'codex e hi'],
|
||||
['exec after a flag value', 'codex -m gpt-5 exec hi'],
|
||||
['exec after a flag value through the launcher', `${NPM_LAUNCHER} -m gpt-5 exec hi`],
|
||||
['exec after a quoted Windows path', '"C:\\Program Files\\My Codex\\codex.exe" exec hi'],
|
||||
['review', 'codex review'],
|
||||
['queue', 'codex queue hi'],
|
||||
['mcp', 'codex mcp list'],
|
||||
['app-server', 'codex app-server --listen unix:// --managed-daemon'],
|
||||
[
|
||||
'the server Codex spawns on Windows',
|
||||
`"\\\\?\\${WINDOWS_NATIVE}" app-server daemon pid-update-loop`
|
||||
],
|
||||
['login', 'codex login'],
|
||||
['logout', 'codex logout'],
|
||||
['apply alias', 'codex a'],
|
||||
['cloud', 'codex cloud'],
|
||||
['completion', 'codex completion zsh'],
|
||||
['features', 'codex features disable daemon_auto_start'],
|
||||
['doctor', 'codex doctor'],
|
||||
['plugin', 'codex plugin list'],
|
||||
['sandbox', 'codex sandbox macos ls'],
|
||||
['debug', 'codex debug models'],
|
||||
['an apostrophe in a prompt before --no-daemon', "codex don't touch tests --no-daemon"],
|
||||
['an apostrophe through the launcher', `${NPM_LAUNCHER} don't break --oss`]
|
||||
])('%s stays off the shared server', (_label, commandLine) => {
|
||||
expect(codexCommandLineJoinsSharedServer(commandLine)).toBe(false)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user