Skip to content

修复供应商切换状态丢失与 Fast/插件稳定性 / Fix provider-switch state loss and Fast/plugin stability#1345

Open
Yuimi-chaya wants to merge 7 commits into
BigPizzaV3:mainfrom
Yuimi-chaya:codex/provider-state-plugin-fast
Open

修复供应商切换状态丢失与 Fast/插件稳定性 / Fix provider-switch state loss and Fast/plugin stability#1345
Yuimi-chaya wants to merge 7 commits into
BigPizzaV3:mainfrom
Yuimi-chaya:codex/provider-state-plugin-fast

Conversation

@Yuimi-chaya

@Yuimi-chaya Yuimi-chaya commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

中文说明

摘要

本 PR 修复 Codex++ 在 API Key + 自定义 Base URL 场景下切换供应商时长期未完整处理的 Codex App 状态问题,并适配 Codex App / ChatGPT Desktop 新版入口与注入结构。

覆盖范围包括:工作区与可写目录状态、沙盒/projectless 状态、个性化设置、Browser/Chrome/Computer Use 内置插件兜底,以及通用 Fast/service tier 入口与模型识别稳定性。

为什么需要修复

Codex++ 已能同步会话数据库中的 provider,使历史对话在切换供应商后继续可见;但 Codex App 的 persisted state、live desktop config、内置插件缓存和 service-tier 状态此前没有被当成同一套用户环境同步。

这不是单纯的界面偏好问题,而会造成实际使用损失:

  • 用户习惯 Ctrl+Enter 提交、Enter 换行时,切换后恢复默认值可能让一次换行直接提交 prompt。
  • workspace roots、thread writable roots、project hints、projectless output directories 或沙盒状态丢失后,原本可写的工作区可能表现为只读,或每次启动重新进入项目。
  • pet/avatar、侧边栏/面板布局、onboarding 与 coachmark 状态重置后,每个供应商都像一套新安装环境。
  • Browser、Chrome、Computer Use 在 API-key 模式切换后可能显示“被组织禁用/地区不可用”,需要开 VPN 进入一次官方环境才能恢复。
  • Fast/service tier 在模型已经可用时仍可能显示“当前模型未读取”、误判不支持,或因新版 composer DOM / asset 名称变化而隐藏。

主要改动

1. Codex App 状态同步

  • 新增 allowlist-based .codex-global-state.json snapshot/merge 模块。
  • 保留 workspace roots、project order、thread workspace hints、thread writable roots、projectless output directories 等工作区恢复状态。
  • 保留安全的 persisted atom state,包括提交键行为、pet/avatar、布局、onboarding/coachmark、default service tier 与插件相关状态。
  • 写入前备份到 backups_state/app-state-sync,并维护 latest safe snapshot。
  • 写 provider config 前合并 live [desktop] table,保留 composerEnterBehaviorselected-avatar-idfollowUpQueueMode 等 Codex Desktop 设置。

这里同步的是已确认的 workspace/writable/sandbox/projectless 状态,不宣称绕过未知的 Codex App 原生 workspace trust gate。

2. 供应商切换入口与内置插件兜底

  • 在 launcher、relay switch、manager apply/clear injection 路径接入切换前 snapshot 与切换后 sync。
  • 在完整增强 + 插件市场解锁开启时默认启用 builtin plugin guard,并保留强制开关。
  • 保留并确保 browser@openai-bundledchrome@openai-bundledcomputer-use@openai-bundled 的本地 bundled 状态。
  • 保留/写入 js_repllocal_shellcomputer_use、Windows unelevated sandbox、notify 配置与 runtime export 兼容项。
  • guarded Windows 启动时设置 CODEX_ELECTRON_ENABLE_WINDOWS_COMPUTER_USE=1
  • 确保内置 remote marketplace snapshot 可在供应商切换后重新注册。

这些措施提供 config/cache/runtime 层兜底;若未来 App ASAR 新增更强的组织/地区 UI gate,仍可能需要单独的包体适配。

3. 通用 Fast/service tier 稳定性

  • active relay 的模型目录读取 live ~/.codex/config.toml,优先采用真实当前模型,并合并 profile model/model list。
  • 去除 Codex++ 模型后缀后再去重,减少显示与判断不一致。
  • 当前模型暂未读取时进入 pending,而不是立即判定 unsupported;请求路径保留 service_tier="priority",避免静默回退。
  • 从请求参数、可见 UI、backend catalog 与 last-known supported model 多源恢复模型。
  • optional asset loader 兼容新版资源拆分;旧 app-server-manager-signals-* 缺失时记录 skipped,不再持续报错。
  • Fast badge 从模型按钮、textarea、contenteditable、textbox 等候选节点推导 composer,适配新版 ChatGPT Desktop DOM。

功能入口

供应商设置 → Codex 增强。内置插件保护、插件市场解锁与 Fast/service tier 控制均在该区域配置。

安全边界

  • 不复制 auth.json、API Key、prompt history、provider token cache、permission maps 等敏感内容。
  • 状态同步严格使用 allowlist,不复制整个 global state。
  • 不修改用户图片、认证文件或全局 git/npm/cargo/proxy 配置。

验证

  • npm run check
  • npm run vite:build
  • node --check assets/inject/renderer-inject.js
  • cargo fmt --all --check
  • cargo test --workspace
  • 基于最新上游 main / Codex++ 1.2.34 验证。
  • 人工连续切换供应商后,个性化设置成功保留;无 VPN 时 Computer Use 与 Browser 可恢复可用;新版 composer 中 Fast 入口恢复显示。

English

Summary

This PR fixes Codex App state that Codex++ previously did not preserve completely when switching providers in the API-key + custom Base URL workflow. It also adapts the integration to newer Codex App / ChatGPT Desktop entry points and injection structures.

The scope includes workspace and writable-root state, sandbox/projectless state, personalization, local guards for bundled Browser/Chrome/Computer Use, and general Fast/service-tier model and UI stability.

Why this matters

Codex++ already updates conversation provider metadata so existing threads remain visible after a provider switch. However, persisted App state, live desktop config, bundled-plugin cache, and service-tier state were not treated as one continuous user environment.

This has practical consequences:

  • A user who expects Ctrl+Enter to submit and Enter to insert a newline can accidentally submit a prompt when the preference resets.
  • Losing workspace roots, thread writable roots, project hints, projectless output directories, or sandbox state can make a previously writable workspace appear read-only or reopen a project on every launch.
  • Resetting pet/avatar, sidebar/panel layout, onboarding, and coachmarks makes every provider behave like a fresh installation.
  • Browser, Chrome, and Computer Use can become organization/region-disabled after a switch in API-key mode until the App is opened once through VPN.
  • Fast/service tier can report an unread or unsupported model, or disappear when newer composer DOM and asset names no longer match old assumptions.

Main changes

1. Codex App state synchronization

  • Adds allowlist-based snapshot/merge handling for .codex-global-state.json.
  • Preserves workspace roots, project order, thread workspace hints, thread writable roots, projectless output directories, and related recovery state.
  • Preserves safe persisted atom state including submit-key behavior, pet/avatar, layout, onboarding/coachmarks, default service tier, and plugin-related state.
  • Creates backups under backups_state/app-state-sync before writes and maintains a latest safe snapshot.
  • Merges the live [desktop] table before provider config writes, preserving settings such as composerEnterBehavior, selected-avatar-id, and followUpQueueMode.

This preserves confirmed workspace/writable/sandbox/projectless state; it does not claim to bypass an unknown native workspace-trust gate.

2. Provider-switch hooks and bundled-plugin guard

  • Wires pre-switch snapshots and post-switch synchronization into launcher, relay-switch, and manager apply/clear-injection paths.
  • Enables the bundled-plugin guard by default when full enhancements and marketplace unlock are active, while retaining the force-enable switch.
  • Preserves local bundled state for browser@openai-bundled, chrome@openai-bundled, and computer-use@openai-bundled.
  • Preserves/writes js_repl, local_shell, computer_use, Windows unelevated sandbox, notify configuration, and runtime-export compatibility values.
  • Sets CODEX_ELECTRON_ENABLE_WINDOWS_COMPUTER_USE=1 for guarded Windows launches.
  • Re-registers the embedded remote marketplace snapshot after provider switches.

These are config/cache/runtime safeguards. A future stronger organization/region gate inside the App ASAR may still require a separate package-level adaptation.

3. General Fast/service-tier stability

  • Builds the active relay catalog from the live ~/.codex/config.toml, preferring the actual current model and merging profile model/model-list values.
  • Strips Codex++ model suffixes before deduplication.
  • Treats an unread model as pending instead of immediately unsupported and preserves service_tier="priority" on pending request paths.
  • Resolves models from request parameters, visible UI, backend catalog, and last-known supported state.
  • Uses optional asset loading for newer App bundles; a missing legacy app-server-manager-signals-* asset is skipped instead of repeatedly failing.
  • Derives the composer from model buttons, textarea, contenteditable, and textbox candidates so the Fast badge survives newer ChatGPT Desktop DOM changes.

Entry point

Provider settings → Codex enhancements. The bundled-plugin guard, marketplace unlock, and Fast/service-tier controls are configured in this section.

Safety boundaries

  • Does not copy auth.json, API keys, prompt history, provider token caches, permission maps, or similar sensitive data.
  • Uses an allowlist rather than copying the complete global state.
  • Does not modify user images, authentication files, or global git/npm/cargo/proxy settings.

Validation

  • npm run check
  • npm run vite:build
  • node --check assets/inject/renderer-inject.js
  • cargo fmt --all --check
  • cargo test --workspace
  • Validated against the latest upstream main / Codex++ 1.2.34.
  • Manual provider-switch testing preserved personalization; Computer Use and Browser recovered without VPN; the Fast entry remained visible in the newer composer.

… App 状态

为什么 / Why:
Codex++ 切换供应商时已经能保留会话,但 Codex App 的 persisted state 和 desktop settings 会丢失,导致工作区、输入习惯、布局和个性化体验回到默认值。
Provider switching already preserves conversations, but Codex App persisted state and desktop settings can be lost, resetting workspace roots, input behavior, layout, and personalization.

改动 / Changes:
- Add a safe allowlist-based .codex-global-state.json snapshot/merge module.
- Preserve safe workspace, project hint, service-tier, onboarding, layout, and personalization state.
- Preserve the live [desktop] table when writing provider config.toml, so settings such as Enter/Ctrl+Enter behavior and selected avatar are not overwritten by stale profile config.
- Back up global state before writing merged state.

安全边界 / Safety:
The sync deliberately excludes auth, API keys, prompt history, provider token cache, and permission maps.
同步刻意排除 auth、API Key、prompt history、provider token cache 和权限映射。
…供应商切换状态并加固内置插件守护

为什么 / Why:
Codex++ 的主要使用场景是自定义 URL + API key。切换供应商后,如果工作区状态、特殊插件本地缓存或 Computer Use 运行时配置被重置,用户会被迫重新安装工作区或开 VPN 进入一次官方环境。
Codex++ is commonly used with custom URLs and API keys. After switching providers, losing workspace state, special plugin cache, or Computer Use runtime config forces users to reinstall workspace state or open the official environment through VPN once.

改动 / Changes:
- Wire app-state capture/merge into launcher, relay switch, manager apply/clear paths.
- Make builtin plugin guard active when full enhancements and plugin marketplace unlock are enabled, while keeping the force switch for other cases.
- Preserve Browser, Chrome, Computer Use bundled plugin config and local openai-bundled marketplace state.
- Ensure js_repl, local_shell, computer_use, Windows unelevated sandbox, notify config, and runtime export compatibility.
- Set CODEX_ELECTRON_ENABLE_WINDOWS_COMPUTER_USE=1 for guarded Windows launches.
- Update manager UI/i18n so the old Computer Use switch is described as a force-enable guard.

安全边界 / Safety:
This is a local config/cache/runtime guard. It does not claim to bypass every possible organization or region gate inside Codex App ASAR.
这是本地 config/cache/runtime 兜底,不声称能 100% 绕过 Codex App ASAR 内部所有组织或地区 gate。
为什么 / Why:
Fast/service-tier 判断依赖当前模型。如果 active relay profile 的 model list 或 profile model 是旧值,而 live ~/.codex/config.toml 已经选择了 gpt-5.5,Codex++ 会误以为当前模型未读取或不支持。
Fast/service-tier decisions depend on the current model. If the active relay profile model list is stale while live ~/.codex/config.toml already selects gpt-5.5, Codex++ may think the current model is unread or unsupported.

改动 / Changes:
- Read the live Codex config model for the active relay profile catalog response.
- Put the effective current model first, then merge profile model and model list entries.
- Strip Codex++ model suffixes before catalog candidate dedupe.
- Add tests for live config winning over stale relay profile values.
… 注入并兼容新版 Codex 资产

为什么 / Why:
用户实际遇到过界面已选 gpt-5.5 且请求可用,但 Codex++ 仍提示“当前模型未读取”或隐藏 Fast 入口。新版 Codex Desktop 还移除了旧 app-server-manager-signals-* asset,并调整了 composer DOM,导致注入报错和右下角 Fast badge 缺失。
Users have seen gpt-5.5 selected and working while Codex++ still reports the current model as unread or hides Fast. Newer Codex Desktop builds also removed the old app-server-manager-signals-* asset and changed composer DOM, causing injection errors and missing composer Fast badge.

改动 / Changes:
- Treat unknown current model as pending, not unsupported; only known non-gpt-5.4 / gpt-5.5 models block Fast.
- Resolve model from request params, visible UI, backend catalog, and last-known supported model.
- Keep service_tier="priority" for pending supported paths instead of silently downgrading.
- Load old Codex app assets optionally and log skipped diagnostics when they are absent.
- Remove the hard-coded old app-server-manager asset import.
- Add composer placement fallbacks based on model buttons, textarea, contenteditable, and textbox nodes.
@Yuimi-chaya Yuimi-chaya marked this pull request as ready for review July 5, 2026 17:43
…e-plugin-fast

# Conflicts:
#	crates/codex-plus-core/src/relay_config.rs
…内置插件

为什么 / Why:
新版 Codex 已逐步整合进 ChatGPT Desktop。只同步会话数据库已不足以保持用户体验:供应商切换后,Browser/Chrome 可能再次变灰,工作区与可写根、沙盒设置、普通对话入口以及 Enter/Ctrl+Enter、宠物和布局等桌面设置仍可能回退。
The newer Codex experience is integrated into ChatGPT Desktop. Conversation database sync alone no longer preserves the working environment: Browser/Chrome can become unavailable again, while workspace/writable roots, sandbox state, projectless startup, Enter behavior, pets and layout can regress after a provider switch.

改动 / Changes:
- Extend the allowlisted App-state snapshot for current workspace, writable-root, projectless, service-tier and personalization keys.
- Preserve live desktop settings while applying provider config.
- Repair the local openai-bundled marketplace and Browser/Chrome/Computer Use entries after provider switches.
- Support current bundled plugin cache/runtime layouts without claiming to bypass unknown ASAR organization/region gates.
- Keep projectless startup stable and recognize packaged ChatGPT Desktop processes in watcher lifecycle handling.
- Add regression coverage for state backup/merge, plugin config, provider switching and ChatGPT process detection.

安全边界 / Safety:
状态同步仍采用白名单,并排除 auth、API Key、prompt history、provider token cache 和权限映射。
State sync remains allowlist-based and excludes auth, API keys, prompt history, provider token cache and permission maps.
@Yuimi-chaya

Copy link
Copy Markdown
Contributor Author

CI 说明

#1345 当前 Windows artifact 的失败来自未被本 PR 修改的上游测试:

crates/codex-plus-core/tests/ads.rs
fetch_ad_list_tries_backup_url_when_primary_fails
os error 10054: An existing connection was forcibly closed by the remote host

同一 job 中此前的核心测试为 118 passed; 0 failed,两个 macOS artifact job 也均已通过。本地 cargo test --workspace 已通过。

这是 Windows runner 上 loopback HTTP backup test 的网络/时序波动。PR 作者账号没有上游 Actions 的 rerun 权限,请维护者使用 Re-run failed jobs 重跑 Windows job;不建议为触发 CI 制造空提交或修改本 PR 业务代码。

CI note

The current Windows artifact failure is from an upstream test that this PR does not modify:

crates/codex-plus-core/tests/ads.rs
fetch_ad_list_tries_backup_url_when_primary_fails
os error 10054: An existing connection was forcibly closed by the remote host

The preceding core test suite in the same job reported 118 passed; 0 failed, both macOS artifact jobs passed, and local cargo test --workspace passed.

This appears to be a loopback HTTP timing/network flake on the Windows runner. The fork PR author cannot rerun upstream Actions jobs, so a maintainer should use Re-run failed jobs for the Windows job. No business-code change or empty commit is warranted for this failure.

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