Skip to content

fix: make the app-server bridge opt-in so Computer Use keeps working - #8

Open
skychentian wants to merge 1 commit into
fish2lab:mainfrom
skychentian:fix/opt-in-app-server-bridge
Open

fix: make the app-server bridge opt-in so Computer Use keeps working#8
skychentian wants to merge 1 commit into
fish2lab:mainfrom
skychentian:fix/opt-in-app-server-bridge

Conversation

@skychentian

Copy link
Copy Markdown

Problem

Installing DSCodex sets CODEX_CLI_PATH globally via launchctl setenv. The Codex desktop app treats that variable as a hard override and abandons its local app-server daemon websocket (the transport that supports reconnect), routing every spawn — app-server, MCP servers (node_repl → Computer Use), and CLI — through the DSCodex shim over stdio.

The bridge was also fragile, so this hijack turned into outages:

  1. launchctl setenv does not survive reboots. Once DSCODEX_REAL_CODEX was lost, codex-wrapper.mjs printed an error and exit(1) — every spawn through the still-set CODEX_CLI_PATH hard-failed.
  2. The generated shim embedded an absolute version-manager node path (fnm/node-versions/vX/...) that disappears on the next Node upgrade, killing the shim.
  3. The Codex app snapshots CODEX_CLI_PATH into [mcp_servers.*.env] in config.toml, persisting the hijack even after launchctl unsetenv.

Net effect reported by users: Computer Use is blocked by DSCodex's environment variables, and app-server reconnect loops when the shim dies.

Fix

Model switching never needed the bridge — it works through the merged model catalog. The bridge only adds per-provider effort/speed memory in the desktop app, so it is now opt-in:

  • install no longer sets CODEX_CLI_PATH and actively removes DSCodex-owned copies left by older versions, including the ones the Codex app snapshotted into [mcp_servers.*.env] (new stripBridgeCliPath in config.mjs).
  • New dscodex bridge enable|disable|status command manages the opt-in; disable also strips the MCP-env snapshots.
  • Wrapper fallback chain (src/real-codex.mjs, shared with the CLI): launchctl → env → bundled app binary → PATH. A stale CODEX_CLI_PATH now degrades to stock Codex instead of exit(1).
  • Robust shim: resolves node from PATH at runtime, falling back to the absolute path baked at install time — fnm/nvm/Homebrew upgrades no longer strand it.
  • Doctor accepts a cleanly disabled bridge and only fails when an active DSCodex bridge is broken.

Bonus fix: catalog forward-compatibility

picker-smoke currently fails on a stock install: Codex now requires supports_reasoning_summaries in model_catalog_json entries, and a stale models_cache.json does not contain it — one unparseable entry takes down the whole catalog and app-server with it. buildCatalog now backfills known-required fields (NATIVE_ENTRY_DEFAULTS) on native entries with safe defaults; smoke passes again.

Tests

  • New: test/real-codex.test.mjs (fallback order, self-exclusion, reboot survival), stripBridgeCliPath cases, catalog backfill case.
  • Suite: 69/70 pass (1 pre-existing Windows VBS path assertion, unrelated).
  • Verified live on macOS: bridge disable clears the login-session env, doctor reports 6/6 ok, picker-smoke finds 🐳 V4 Flash with native GPT preserved.

Bumps version to 0.6.0 (behavior change: bridge off by default; bridge enable restores previous behavior).

Installing DSCodex used to set CODEX_CLI_PATH globally via launchctl. That
forces the Codex desktop app off its local app-server daemon websocket (the
transport with reconnect support) onto stdio through the DSCodex shim for
every spawn - app-server, MCP servers, and Computer Use included. The bridge
was also fragile: launchctl login variables do not survive reboots, so a
missing DSCODEX_REAL_CODEX made the wrapper exit(1), and the shim embedded a
version-manager node path that disappears on upgrade. Any of these left the
app unable to spawn Codex at all, which users saw as Computer Use being
blocked by DSCodex.

Model switching never needed the bridge - it works through the merged model
catalog. The bridge only adds per-provider effort/speed memory, so it is now
opt-in:

- install no longer sets CODEX_CLI_PATH and actively removes DSCodex-owned
  copies left by older versions, including the ones the Codex app snapshots
  into [mcp_servers.*.env]; new `dscodex bridge enable|disable|status`
  command manages the opt-in
- the wrapper resolves the stock Codex binary through a shared fallback
  chain (launchctl -> env -> bundled app binary -> PATH) instead of exiting
  when DSCODEX_REAL_CODEX is missing, so a stale CODEX_CLI_PATH degrades to
  stock Codex rather than hard-failing every spawn
- the shim resolves node from PATH at runtime and only falls back to the
  absolute path baked at install time, so fnm/nvm/Homebrew upgrades no
  longer strand it
- doctor now accepts a cleanly disabled bridge and only fails when an
  active DSCodex bridge is broken

Also backfill newly required catalog fields (supports_reasoning_summaries)
on native entries: Codex bumps can make a stale models_cache.json entry
unparseable, which takes down the whole model_catalog_json and the
app-server with it (picker smoke failed before this).

Bumps version to 0.6.0.
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