Opencode巧施连环计,调试强绷俩小时
唯鱼和熊掌不可兼得矣,Windows:我打Tauri,真的假的...
背景
在长期使用了 Opencode Desktop v1.14.29 配合oh-my-openagent(以下简称 OMO)插件后,发现 OMO 会频繁出现 subagent 调用 GPT-5 Nano 而非原 selection Minimax M2.7,非常头疼。把 Opencode Desktop 用自带的上游更新包更新到 v1.14.39,起初默认安装位置没有定到自己的路径下还没有太在意,但后来 OMO 插件反复卸了重装还未生效。
和金山的工程师 Beacon 一起调试了两个小时,诡异的事情一波三折,真相也逐渐露出水面…
本文记录整个排查过程和最终结论。整个过程都在 opencode 上推进,使用 DeepSeek V4 Pro 辅助跟踪系统文件、比对日志差异、分析进程命令行参数。
时间线
第一阶段:发现 Desktop 与 CLI 不同步
Opencode Desktop 更新到 v1.14.39 后,OMO 彻底不工作了。怎么重装都没用——插件列表里能看到、绿灯也亮,但 Agent 下拉菜单始终是原生 Plan/Build。
于是直接在 opencode 对话里让它自行排查——第一个关键发现是:
| 组件 | 版本 |
|---|---|
OpenCode.exe(Desktop 壳) | 1.14.39 |
opencode-cli.exe(捆绑的 sidecar) | 1.14.29 |
Desktop 的自动更新只更新了 GUI 壳,没有同步更新它内嵌的 CLI sidecar。当时它给出的结论是”插件 API 版本不兼容”,建议手动升级 CLI。虽然 opencode upgrade 因为交互式提示而卡死,但这个发现引出了一个更关键的问题——
为什么 Desktop 的更新流程会漏掉 CLI?
第二阶段:定位架构变更
顺着 CLI 不同步的线索查下去,发现了一件关键的事情:v1.14.34 这一版 Opencode Desktop 进行了一次重大架构变更——从 Tauri 换到了 Electron。同时,上游不再将 CLI 二进制随 Desktop 一起分发,opencode-cli.exe 从此和 Desktop 分家。
这意味着:
- v1.14.34 之前:Desktop 基于 Tauri,附带独立的 CLI 二进制(支持 Bun 运行时)
- v1.14.34 之后:Desktop 基于 Electron,sidecar 改由
app.asar内的 Node.js 进程提供,不再依赖外部 CLI;CLI 单独提供下载
问题就出在这个 Node.js sidecar 上——它和独立 CLI 的运行时环境不同,而 OMO 恰好依赖 CLI 独有的能力,例如在 OMO 的 installation.md 中就提到应该使用bun/bunx进行安装,这也是我电脑上压根没bun的情况下,可以在旧版本上顺利装上 OMO 的原因。此外,这也解释了为什么会出现前面找不到默认安装路径的问题:这就不是一个架构,当然识别不到。
第三阶段:对比 CLI 与 Desktop 的行为差异
为了进一步检查,用 winget 装了一套独立 CLI(SST.opencode v1.14.37,CLI 的更新略微慢于主线,还没有 v1.14.39 的包体)和 Bun(Oven-sh.Bun v1.3.13)。补齐工具链后:
- 独立 CLI:
opencode agent list显示全部 OMO agent(Sisyphus/Prometheus/Atlas/Hephaestus),正常可用 - Desktop:Agent 列表里也有这些 agent 注册,但 Desktop 不显示——问题出在 Desktop 的 sidecar 加载插件时失败了
两边 agent 列表都能看到 OMO 的注册项,但只有 CLI 能实际用上 Sisyphus。差距一定在加载阶段。
第四阶段:锁定日志中的致命错误
Desktop sidecar 的日志位于 ~\.local\share\opencode\log\。找到最近一次启动日志:
1
2
3
4
ERROR service=plugin path=oh-my-openagent
target=file:///C:/Users/Akuta/.cache/opencode/packages/oh-my-openagent@latest/...
error=Cannot destructure property 'spawn' of 'globalThis.Bun' as it is undefined.
failed to load plugin
同一时段 CLI 的日志则是:
1
INFO service=plugin path=oh-my-openagent loading plugin
这就全通了。
| 运行时 | Bun 支持 | oh-my-openagent |
|---|---|---|
| CLI v1.14.37(winget standalone 二进制) | 内置 | 正常加载 |
| Desktop v1.14.39 sidecar(app.asar 内 Node.js 进程) | 无 | globalThis.Bun 为 undefined,抛异常 |
也解释了为什么反复卸了重装都没用:配置文件是对的、模型配置是对的、插件包也下载到了缓存目录——但 deserialize JS 模块的第一步就崩了。 Desktop 的绿灯只检查 oh-my-openagent.json 文件是否存在,不校验 dist/index.js 是否求值成功。
尝试验证
把旧版 v1.14.33 的 CLI 二进制(183MB,Tauri 时代最后一版自带 Bun 支持的 CLI)放入 Desktop 安装目录,替换空文件。重启后无效——Desktop 日志中的 No CLI installation found, skipping sync 说明它虽然会检测外部 CLI,但 sidecar 始终用的是 app.asar 内部的 Node.js 进程,不会去调用外部二进制。
到这里排查基本宣告结束,可以确定问题出在上游了。
后续:Issue #3797
排查结束之后,正打算去 OMO 仓库提 issue,先搜了一下——发现#3797 已经被人提了,就提前四小时(兵贵神速啊),而且写得比我的详实得多,不过这位是 macOS 用户。
他直接定位到了 dist/index.js 中的 25 处 globalThis.Bun 顶层解构语句,给出了具体行号,还分析了为什么上一个版本修的 bun:sqlite 引入不够——那只解决了 ESM loader 层面的协议错误,但 globalThis.Bun.spawn 是运行时 API,Bun bundler 在每个用到 Bun.spawn() 的 chunk 开头都生成了未受保护的 var {spawn} = globalThis.Bun。
然后俩小时后就有了回复,而且也开始有 PR 着手修这个问题了,OMO 的活跃度相对还是可以的。我就顺着这条补了一个 Windows 的 write-up,看他们什么时候能搞定了。
结论
Debug Report
oh-my-openagent 在 Opencode Desktop v1.14.39 上无法生效,因为 Desktop sidecar 运行在 Node.js 上,缺少插件所需的 Bun 运行时。
归根结底,这是 v1.14.34 架构变更(Tauri→Electron,同时移除捆绑 CLI)引发的一系列连锁反应:
- Desktop 更新不同步更新 CLI sidecar → sidecar 保持旧版本
- 但即使 sidecar 版本一致,Electron 架构的 Node.js 进程也不支持
globalThis.Bun - 独立 CLI(winget 安装)是 standalone 二进制,自带 Bun 运行时,所以不受影响
为了 OMO 的 harness 能力,现在我是摆了,只好先暂时用一阵子 CLI 了。
“源神” Rust
我觉得从这件事中可以窥见很有趣的另一点是,一方面来说,人们或许已经意识到 Rust 是一门被过度吹捧的语言,尽管它内存安全、性能高,但开发心智非常大,包括被 Rust 信徒所推崇的 npm 替代品 bun,也存在着不小的问题,自己之前所发现的恶性 bug 至今还是 Open,tauri 的生态链也是不那么成熟的。我猜这也是 Opencode 想要把架构转回传统派 Electron 的原因之一。
AGI?还早得很
以前其实一直都用的 MiniMax M2.7 作为 Agent 主力(毕竟便宜),最近 DeepSeek 憋了很久的大招 v4 Pro 放了出来。本来想着没 coding plan 还挺贵,但最近正巧打折就充了 50,这次也算是好好体验了一把。算个总账的话共计 36M token(缓存命中 34.90M,未命中 0.99M,输出 0.15M),开销 4.8 块,两瓶可乐钱。开始修的时候 Beacon 还信心十足说 vibe 修服务器都只要了两块钱按说应该还好相信 DeepSeek 的实力,结果俩人加一 Agent 愣是折腾俩小时,最终因为是上游问题遗憾退场——修 Windows 上的玩意可比修 Linux 服务器难多了。
我觉得现阶段肯定还是有一些问题 AI 解决不了,大可不必把 LLM 吹到 AGI 那种程度。不过话又说回来,日志这种东西人还是很难看,搞了半天,还是不得不拿着 AI 工具读 AI 写的日志,查 AI 自己遗留的注册表和 winget 残留,最后发现是 AI 工具自己的架构变更把 AI 的插件给搞崩了:如果它的更新也有大幅度 vibe,那就真的很难绷得住了——Opencode 巧施连环计,把大伙全坑进去了。——我于是又想起来前段时间看的一段很令人悲伤的话:
有些人或许已经被 AI 巨头的鼓动吓得不敢停下脚步,而我们未来的工作,或许将围绕“给 AI 擦屁股”来展开了。