Skip to content

fix(acp): improve packaged codex startup fallback#1594

Merged
piorpua merged 3 commits intoiOfficeAI:mainfrom
JAVA-LW:codex/fix-codex-acp-platform-fallback
Mar 27, 2026
Merged

fix(acp): improve packaged codex startup fallback#1594
piorpua merged 3 commits intoiOfficeAI:mainfrom
JAVA-LW:codex/fix-codex-acp-platform-fallback

Conversation

@JAVA-LW
Copy link
Copy Markdown
Contributor

@JAVA-LW JAVA-LW commented Mar 20, 2026

Pull Request

Description

linux中同样有ACP报错问题,进行了修复,现在提交上去。
直接本地bun run start ,尝试发送消息就会报错,原因是ACP通讯问题,所以进行修复

Related Issues

Type of Change

  • [x ] Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update

Testing

  • Tested on macOS
  • Tested on Windows
  • Tested on Linux
  • My code follows the project's code style guidelines
  • I have performed a self-review of my own code
  • My changes generate no new warnings or errors

Screenshots

Additional Context


Thank you for contributing to AionUi! 🎉

@sentry
Copy link
Copy Markdown

sentry bot commented Mar 20, 2026

Codecov Report

❌ Patch coverage is 58.47458% with 49 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/process/agent/acp/acpConnectors.ts 67.41% 15 Missing and 14 partials ⚠️
src/process/agent/acp/index.ts 0.00% 19 Missing ⚠️
src/process/utils/shellEnv.ts 90.00% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 88d80b9dd2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +73 to +74
function resolveCodexAcpPlatformPackageSpecifier(packageName: string): string {
return process.platform === 'win32' ? `${packageName}@${CODEX_ACP_BRIDGE_VERSION}` : packageName;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Pin direct Codex ACP packages on POSIX

resolveCodexAcpPlatformPackageSpecifier() only appends @${CODEX_ACP_BRIDGE_VERSION} on Windows, so the new Linux/macOS startup path invokes bare @zed-industries/codex-acp-* package names. That means fresh Codex startups on POSIX will install whatever version is currently latest in the registry instead of the bridge version this app is pinned to, and a future upstream release can suddenly change protocol/behavior on one machine while others still run @zed-industries/[email protected]. The direct platform package should stay version-locked on every OS.

Useful? React with 👍 / 👎.

Comment on lines +409 to +412
const stat = await fs.stat(candidatePath);
if (stat.isFile() && stat.mtimeMs > selectedMtimeMs) {
selectedBinaryPath = candidatePath;
selectedMtimeMs = stat.mtimeMs;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject stale cached Codex binaries from older bridge versions

This cache probe chooses the newest codex-acp binary by mtime and executes it directly, but it never verifies that the cached package version matches CODEX_ACP_BRIDGE_VERSION. After an app upgrade, users who still have an older bridge cached under _npx will keep launching that stale binary and never give npx a chance to fetch the new bridge, so the packaged startup fix in this commit does not actually roll out until they manually purge the cache. Please read each candidate package's version before reusing it.

Useful? React with 👍 / 👎.

Comment on lines +564 to +565
const posixCacheCandidates = [path.join(homeDir, '.npm-cache'), path.join(homeDir, '.npm')];
const npmCacheBase = posixCacheCandidates.find((candidate) => existsSync(candidate)) || posixCacheCandidates[0];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Probe the actual _npx dir before preferring ~/.npm-cache

On POSIX this now prefers the first existing parent cache directory (~/.npm-cache before ~/.npm) without checking which one actually contains _npx. If a machine has a leftover ~/.npm-cache directory but npx is still using the default ~/.npm/_npx, both the new cached-binary lookup and the existing corrupted-cache cleanup paths will inspect/delete the wrong tree, so startup recovery silently stops working for that setup.

Useful? React with 👍 / 👎.

@kaizhou-lab
Copy link
Copy Markdown
Collaborator

kaizhou-lab commented Mar 20, 2026

感谢提交!在 Linux 上修复 ACP optional dependency 问题的思路很好,fallback 策略覆盖了缓存查找、平台直装和 meta 包回退,考虑得很全面。

提两个小建议:

1. 非 Windows 平台的包建议也锁定版本号

目前 resolveCodexAcpPlatformPackageSpecifier 只在 Windows 上拼接版本号:

function resolveCodexAcpPlatformPackageSpecifier(packageName: string): string {
  return process.platform === 'win32' ? `${packageName}@${CODEX_ACP_BRIDGE_VERSION}` : packageName;
}

这样 Linux/macOS 上 npx 会安装 latest 版本,如果上游发了不兼容的新版就会出问题。建议统一锁定:

function resolveCodexAcpPlatformPackageSpecifier(packageName: string): string {
  return `${packageName}@${CODEX_ACP_BRIDGE_VERSION}`;
}

2. resolveCodexAcpPlatformPackage 可以去掉

connectCodex 已经有完整的 fallback 机制(候选包逐个尝试,失败自动试下一个),所以不需要预先校验平台是否支持。不支持的平台 npx 安装失败后自然会回退到 meta 包。

直接拼字符串就够了:

const platformPackage = `@zed-industries/codex-acp-${process.platform}-${process.arch}@${CODEX_ACP_BRIDGE_VERSION}`;

这样 resolveCodexAcpPlatformPackageresolvePreferredCodexAcpPlatformPackageshouldPreferDirectCodexAcpPackage 三个函数和相关的 null 检查都可以删掉,逻辑会简洁很多。

@JAVA-LW
Copy link
Copy Markdown
Contributor Author

JAVA-LW commented Mar 20, 2026

感谢提交!在 Linux 上修复 ACP optional dependency 问题的思路很好,fallback 策略覆盖了缓存查找、平台直装和 meta 包回退,考虑得很全面。

提两个小建议:

1. 非 Windows 平台的包建议也锁定版本号

目前 resolveCodexAcpPlatformPackageSpecifier 只在 Windows 上拼接版本号:

function resolveCodexAcpPlatformPackageSpecifier(packageName: string): string {
  return process.platform === 'win32' ? `${packageName}@${CODEX_ACP_BRIDGE_VERSION}` : packageName;
}

这样 Linux/macOS 上 npx 会安装 latest 版本,如果上游发了不兼容的新版就会出问题。建议统一锁定:

function resolveCodexAcpPlatformPackageSpecifier(packageName: string): string {
  return `${packageName}@${CODEX_ACP_BRIDGE_VERSION}`;
}

2. resolveCodexAcpPlatformPackage 可以去掉

connectCodex 已经有完整的 fallback 机制(候选包逐个尝试,失败自动试下一个),所以不需要预先校验平台是否支持。不支持的平台 npx 安装失败后自然会回退到 meta 包。

直接拼字符串就够了:

const platformPackage = `@zed-industries/codex-acp-${process.platform}-${process.arch}@${CODEX_ACP_BRIDGE_VERSION}`;

这样 resolveCodexAcpPlatformPackageresolvePreferredCodexAcpPlatformPackageshouldPreferDirectCodexAcpPackage 三个函数和相关的 null 检查都可以删掉,逻辑会简洁很多。

gh 确实装好了,版本是 2.87.3。我已经把 PR #1594 的评论和你本地分支都对过了;当前本地和远端都还停在 88d80b9,也就是这些建议还没有被后续 commit 处理。

我的判断是:

  • getNpxCacheDir() 这条评论是成立的。现在的实现会在 POSIX 上优先选“先存在的父目录”而不是“真正存在 _npx 的目录”,代码在 shellEnv.ts#L549。这不只影响缓存命中,也会影响损坏缓存清理;AcpConnectionMcpProtocol 都在复用它。对应测试 getNpxCacheDir.test.ts#L68 现在也把这个偏弱的行为写死了,所以这条我建议采纳。

  • “POSIX 平台包统一锁到 CODEX_ACP_BRIDGE_VERSION” 这条不能直接照做。你项目里 bridge 版本固定在 acpTypes.ts#L38 的 0.9.5,但我直接查了 npm registry:
    @zed-industries/codex-acp-linux-x64 最新只有 0.9.2
    @zed-industries/codex-acp-linux-arm64 最新也是 0.9.2
    @zed-industries/codex-acp-darwin-x64 最新 0.9.4
    @zed-industries/codex-acp-darwin-arm64 才是 0.9.5
    我还验证了 npm view @zed-industries/[email protected],结果是 404。所以 reviewer 的“版本漂移风险”判断有道理,但“统一锁成 0.9.5” 现在会直接把 Linux 和部分 macOS 打挂。

  • resolveCodexAcpPlatformPackage() 那条“可以删掉、直接拼字符串”的建议,属于可选简化,不是必须修。单独看它问题不大,但它和上面那条“统一锁版本”绑在一起就不安全了。当前显式映射虽然啰嗦一点,但至少更可控,代码在 acpConnectors.ts#L73 一带。

  • “cached binary 要校验版本,不能直接按 mtime 取最新” 这个风险也是真实的,代码在 acpConnectors.ts#L377。但 review 里建议它必须匹配 CODEX_ACP_BRIDGE_VERSION,这在 POSIX 上同样会撞上平台包版本不齐的问题,所以也不能原样照搬。这个点如果要修,我更倾向于单独设计一个安全方案,而不是直接套评论里的写法。

我建议你现在的处理顺序是:先修 _npx 目录探测这条;另外两条和“统一锁版本”相关的 comment 先不要直接改,可以回评论说明 npm registry 目前平台包版本和 meta 包不齐平。你要的话,我下一步可以直接帮你做一个安全 follow-up patch,只改 _npx 探测和对应测试,再顺手帮你起一段回复 review comment 的文案。

@piorpua piorpua added the bot:reviewing Review in progress (mutex) label Mar 27, 2026
@piorpua piorpua added bot:reviewing Review in progress (mutex) and removed bot:reviewing Review in progress (mutex) labels Mar 27, 2026
@piorpua piorpua added bot:reviewing Review in progress (mutex) and removed bot:reviewing Review in progress (mutex) labels Mar 27, 2026
@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 27, 2026

Code Review:fix(acp): improve packaged codex startup fallback (#1594)

变更概述

本 PR 修复了 Linux 环境下的 Codex ACP 启动失败问题,主要新增了三项机制:(1) 通过扫描 npx 缓存目录直接定位已缓存的平台原生二进制文件;(2) 构建多候选包的顺序重试循环,根据平台优先直接包或元包;(3) 将 Codex 的连接超时从固定 70 秒提升至 150 秒,适配 Linux 上较慢的启动速度。此外同步增强了 getNpxCacheDir 以识别 npm_config_cache 环境变量和 ~/.npm-cache 路径。


方案评估

结论:✅ 方案合理

方案通过缓存二进制发现 + 多候选回退的两层机制解决了 Linux 上平台包安装不可靠的根本问题,与项目 ACP 架构一致。回退链路清晰,每次失败后调用 cleanup 再尝试下一个候选,逻辑正确。测试覆盖了 Windows、Linux、macOS 三平台的缓存命中和多级回退路径,质量较高。


问题清单

🟡 MEDIUM — Linux/macOS 平台包缺少版本固定

文件src/process/agent/acp/acpConnectors.ts,第 73–75 行

问题代码

function resolveCodexAcpPlatformPackageSpecifier(packageName: string): string {
  return process.platform === 'win32' ? `${packageName}@${CODEX_ACP_BRIDGE_VERSION}` : packageName;
}

问题说明:Windows 平台固定了版本(如 @zed-industries/[email protected]),但 Linux 和 macOS 直接使用不带版本的包名(如 @zed-industries/codex-acp-linux-x64),npm 会解析为 latest。若平台包发布了与当前协议版本(CODEX_ACP_BRIDGE_VERSION=0.9.5)不兼容的新版本,则可能出现协议不匹配故障。

修复建议

function resolveCodexAcpPlatformPackageSpecifier(packageName: string): string {
  return `${packageName}@${CODEX_ACP_BRIDGE_VERSION}`;
}

同步更新相关测试中的期望值。


🔵 LOW — lint: no-await-in-loop 在缓存扫描循环中

文件src/process/agent/acp/acpConnectors.ts,第 409 行

问题代码

const stat = await fs.stat(candidatePath);  // ← lint warning

问题说明:oxlint 报告 no-await-in-loop 警告。此处是顺序扫描多个缓存目录以找出最新二进制,可通过 Promise.allSettled 并行化以消除警告并提升性能。


🔵 LOW — lint: no-await-in-loop 在重试循环中(语义上合理但触发 lint)

文件src/process/agent/acp/acpConnectors.ts,第 587 行、第 610 行

问题说明:oxlint 报 no-await-in-loop,但此处的顺序重试是语义要求。可通过 oxlint 行内注释抑制:

// oxlint-disable-next-line no-await-in-loop
await connectNpxBackend({ ... });

🔵 LOW — 直接变异候选包数组(违反不可变原则)

文件src/process/agent/acp/acpConnectors.ts,第 614 行

问题代码

codexPackageCandidates.push(fallbackPackage);  // ← mutation

问题说明:在 for...of 迭代中直接 .push() 变异数组,违反项目不可变原则。建议通过重新赋值新数组来扩展候选列表。


🔵 LOW — POSIX 缓存目录默认值不标准

文件src/process/utils/shellEnv.ts,第 581 行

问题代码

const npmCacheBase = posixCacheCandidates.find((candidate) => existsSync(candidate)) || posixCacheCandidates[0];

问题说明:两个候选都不存在时默认 ~/.npm-cache,但 npm POSIX 标准默认为 ~/.npm。建议改为 posixCacheCandidates[1] 作为回退。


汇总

# 严重级别 文件 问题
1 🟡 MEDIUM acpConnectors.ts:73 Linux/macOS 平台包未固定版本
2 🔵 LOW acpConnectors.ts:409 no-await-in-loop 在缓存扫描循环
3 🔵 LOW acpConnectors.ts:587,610 no-await-in-loop 在重试循环
4 🔵 LOW acpConnectors.ts:614 直接变异候选包数组
5 🔵 LOW shellEnv.ts:581 POSIX 无缓存时默认 ~/.npm-cache 而非 ~/.npm

结论

⚠️ 有条件批准 — 方案整体正确,测试覆盖充分;MEDIUM 问题(平台包版本未固定)有潜在协议不匹配风险,建议修复后合并。


本报告由本地 pr-review skill 生成,包含完整项目上下文,无截断限制。

@piorpua piorpua added bot:ready-to-fix CONDITIONAL review done, waiting for bot fix bot:fixing Fix in progress (mutex) and removed bot:reviewing Review in progress (mutex) bot:ready-to-fix CONDITIONAL review done, waiting for bot fix labels Mar 27, 2026
piorpua pushed a commit that referenced this pull request Mar 27, 2026
Previously only Windows platform packages were versioned (e.g.
[email protected]), while Linux and macOS packages resolved
to 'latest', risking protocol mismatch if a newer incompatible version
was published.

Update resolveCodexAcpPlatformPackageSpecifier to always append
@CODEX_ACP_BRIDGE_VERSION regardless of platform, and update tests
to expect the versioned package specifier for linux-x64 and darwin-x64.

Review follow-up for #1594
@piorpua
Copy link
Copy Markdown
Contributor

piorpua commented Mar 27, 2026

PR Fix 验证报告

原始 PR: #1594
修复方式: 直接推送到 codex/fix-codex-acp-platform-fallback

# 严重级别 文件 问题 修复方式 状态
1 🟡 MEDIUM acpConnectors.ts:73 Linux/macOS 平台包未固定版本,npm 会解析为 latest 移除 win32 条件判断,对所有平台统一追加 @CODEX_ACP_BRIDGE_VERSION ✅ 已修复

总结: ✅ 已修复 1 个 | ❌ 未能修复 0 个

🔵 LOW 级别问题(4 个)已跳过(不阻塞合并,修复优先级低)。

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@piorpua piorpua merged commit ba4f50f into iOfficeAI:main Mar 27, 2026
14 checks passed
@piorpua piorpua added bot:done Auto-merged by bot and removed bot:fixing Fix in progress (mutex) labels Mar 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:done Auto-merged by bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants