Skip to content

fix: keep the macOS app launcher off stale install paths - #536

Open
tlysanhuo wants to merge 2 commits into
zszz3:mainfrom
tlysanhuo:fix/macos-app-shim-version-drift
Open

fix: keep the macOS app launcher off stale install paths#536
tlysanhuo wants to merge 2 commits into
zszz3:mainfrom
tlysanhuo:fix/macos-app-shim-version-drift

Conversation

@tlysanhuo

Copy link
Copy Markdown
Contributor

Refs #499(问题 3:macOS app shim 版本漂移;顺带覆盖问题中"卸载旧版导致 PATH 回退"的部分)

问题

install-macos-app.cjs 生成的 launcher 把生成时的绝对路径(process.execPath + 包路径)烧进脚本,且只在手动 install-app 时生成、之后永不刷新:

  • 多版本共存(如 nvm 前缀的 0.13.3 + ~/.local 的 0.14.0):旧版生成的 launcher 里 [ -x node ] && [ -f cli ] 检查通过(旧文件都还在),App 双击后静默启动旧版,Info.plist 也一直显示旧版本号;
  • 卸载旧版:launcher 的烧入路径失效,退到 zsh -lc 'agent-recall-v2' 的 PATH 解析,结果取决于 PATH 顺序;且 uninstall.cjs 会无条件删除 app bundle——即使该 bundle 已被另一个保留版本刷新。

修复(v1 + v2 镜像,对应 #499 建议的三点)

  1. launcher 改为"登录 shell 解析优先、烧入路径作回退":先 /bin/zsh -lc 'command -v agent-recall-v2' 解析用户终端当前使用的安装,解析不到(如 PATH 已移除)再退回烧入的绝对路径;两者都失败时输出明确的中文错误提示并以非零退出(此前是 127 command not found)。旧版生成的 launcher 从此不可能在更新版本存在时继续启动旧版。
  2. 启动时版本校验:CLI 在 darwin 启动路径上读取已安装 bundle 的 CFBundleShortVersionString,与当前运行版本不一致时自动重新生成 bundle(刷新烧入路径与 plist 版本),不再要求用户手动重跑 install-app;未安装时的 TTY 提示行为不变。
  3. 卸载归属检查:uninstallMacosApp 接受 packagePath,launcher 仍引用本安装的烧入路径才删除;指向其他安装时返回 kept 并提示,避免卸载旧版时误删新版正在使用的启动器。launcher 不可读时保持历史删除行为。

测试

  • 新增行为回归测试 launcher prefers the current install over stale baked paths(仅 darwin,真实 zsh 执行):烧入旧版路径 + .zprofile 提供新版 CLI 时,断言启动的是新版;登录 shell 解析不到时,断言烧入路径兜底仍可启动。在修复前的代码上该测试失败(启动的是旧版),修复后通过。
  • 新增 uninstallMacosApp keeps bundles owned by another install:指向其他安装时 kept 且 bundle 保留,指向本安装时正常删除,无 package 上下文时保持历史行为。
  • 更新既有断言:launcher 中登录 shell 解析先于烧入路径执行,readInstalledMacosAppVersion 返回生成版本。
  • v1/v2 各 8/8 通过;v2 test:scripts 168/168、typecheck(tsc + dead-code + entrypoint)通过;v1 tsc --noEmit 通过。

说明

#499 的问题 2 已由 #531 合并修复;问题 4(幽灵 --manifest 参数)仍开放,本 PR 不涉及。

Address zszz3#499 problem 3 (macOS app shim version drift), in both V1 and V2:

- The generated launcher now resolves the CLI the way the user's terminal
  would (login shell) before falling back to the absolute paths baked at
  generation time. A bundle generated by an older install can no longer
  keep launching that stale version once a newer install appears, and a
  dead baked path degrades to the baked fallback with a clear error only
  when neither resolves.
- The CLI refreshes the app bundle at startup whenever the version
  recorded in its Info.plist drifts from the running install, so baked
  paths and the plist stay current without re-running install-app.
- Uninstall keeps a bundle whose launcher points at another install's
  baked paths instead of removing it blindly, so uninstalling the older
  of two installs no longer deletes the newer one's launcher.
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