1. OpenCode 源码构建到底在做什么,为什么本地和 CI 都要先跑通
OpenCode 是一个开源的终端 Agent 项目,源码以 TypeScript 为主,最终产物是可以在 Linux、macOS、Windows 上独立运行的多平台二进制文件。所谓“源码构建”,就是把packages/opencode下的 TS 源码,通过bun run build编译、打包、交叉编译成dist/opencode-<os>-<arch>/bin/opencode这样的可执行文件。它适合两类人:一是想在本地改源码、加自定义工具、调 Agent 行为的开发者;二是要把构建流程搬进 CI、每次提交都产出可运行产物的团队。
我先把结论放前面:OpenCode 的构建本身不复杂,真正卡人的是两个点。第一是依赖安装阶段 npm 官方源访问慢,bun install会长时间停在解析阶段;第二是构建完成后,很多人不知道怎么验证产物是不是真的能跑,以及 Agent 运行时需要模型通道时该怎么统一配置。前者用镜像源解决,后者用 TaoToken 的统一 Key 和 API 通道解决。这篇就把从源码到可运行产物、再到构建后自检的完整链路写清楚,命令和配置都能直接复制。
需要先明确一个概念:bun run build不是 Bun 的内置命令,而是packages/opencode/package.json里定义的脚本。项目根目录也有一个package.json,但构建脚本在子包里,所以要么cd packages/opencode再执行,要么用--cwd指定目录。这一点在 CI 里尤其容易踩坑,因为 CI 的工作目录默认是仓库根目录,直接跑bun run build会提示找不到脚本。
构建产物是“独立可执行”的,意思是它把 Bun 运行时一起打包进去了,目标机器不需要装 Bun 或 Node.js 就能运行。这对分发很友好,但也意味着构建时间不短,因为默认会交叉编译十几个平台目标。如果你只是本地验证,完全没必要全量构建,build.ts里提供了--single选项,只构建当前平台,能省下大量时间。
下面按“环境准备 → 依赖安装 → 构建 → 自检 → 排障”的顺序展开,中间穿插 TaoToken 的接入配置,让构建出来的 Agent 能直接跑通一次真实请求。
2. 构建前置:Bun 环境、镜像源与 TaoToken 统一 Key 的准备
2.1 安装 Bun 并确认版本
OpenCode 用 Bun 作为包管理器和构建工具,所以第一步是装 Bun。Linux/macOS 下一条命令:
curl -fsSL https://bun.sh/install | bash装完记得让当前 shell 重新加载环境变量,或者直接开一个新终端:
source ~/.bashrc bun --versionWindows 用户用 PowerShell:
powershell -c "irm bun.sh/install.ps1 | iex"版本建议 1.1.x 以上,太老的 Bun 在交叉编译时对--target参数支持不完整,会出现产物缺失。确认版本后,把仓库克隆下来:
git clone https://github.com/sst/opencode.git cd opencode2.2 依赖安装卡住的根因与镜像源配置
bun install卡住的原因很直接:默认 registry 是 npm 官方源,国内访问解析慢、偶发超时。解决办法是临时或永久指定镜像源。临时方式:
bun install --registry https://registry.npmmirror.com永久方式是在项目根目录或用户目录放一个bunfig.toml:
[install] registry = "https://registry.npmmirror.com"我试过在 CI 里用临时参数更稳,因为 CI 环境干净,不依赖用户级配置。本地开发则建议写进bunfig.toml,省得每次敲。注意镜像源只影响依赖下载,不影响构建产物,构建过程仍然是本地编译。
2.3 TaoToken 统一 Key 的定位
构建出来的 OpenCode 是 Agent 运行时,它需要模型通道才能干活。TaoToken 在这里的角色是“统一 Key + 统一 API 通道”:你不用为每个模型供应商分别管一套 Key,而是拿一个 TaoToken 的 Key,通过统一的 Base URL 走所有模型请求。对构建后自检来说,这意味着你只需要配一次环境变量,就能验证 Agent 的请求链路是否通。
先去控制台创建 Key:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite
创建完在 API Keys 页面复制:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite
Base URL 统一用https://taotoken.net/api,注意这个地址不带任何查询参数。模型 ID 按你实际要用的填,比如claude-sonnet-4-20250514这类。三件套(Base URL、Key、Model ID)在后面的配置片段里会完整出现,缺一个都会导致 401 或模型不存在。
3. 可复制配置:构建脚本、环境变量与 Agent 通道设置
3.1 进入子包并执行构建
先确认构建脚本位置。打开packages/opencode/package.json,能看到类似这样的脚本定义:
{ "name": "opencode", "scripts": { "build": "bun run build.ts", "dev": "bun run src/index.ts" } }所以构建命令是:
cd packages/opencode bun run build如果不想切目录,用--cwd:
bun run --cwd packages/opencode build构建前可以先跑一下帮助,确认源码能正常解析:
bun run --cwd packages/opencode src/index.ts --help能打印出帮助信息,说明 TS 源码和依赖都没问题,再跑 build 成功率更高。
3.2 只构建当前平台:--single 选项
全量构建会编译allTargets里的十几个目标,包括 linux arm64/x64、musl 变体、darwin arm64/x64、win32 arm64/x64 等。本地验证没必要全跑,用--single:
bun run build --single这个选项在build.ts里控制是否跳过非当前平台的目标。生效后,dist/下只会出现当前系统对应的目录,比如 Ubuntu x86_64 下就是dist/opencode-linux-x64/。CI 里如果要做多平台分发,就去掉--single,但要注意构建机需要能交叉编译,Bun 的交叉编译对目标平台的 libc 有要求,musl 目标在 glibc 机器上构建时偶尔会报链接错误,后面排障章节会讲。
3.3 Agent 运行时的统一通道配置
构建产物要跑起来并发出模型请求,需要配置三件套。OpenCode 支持通过环境变量注入,推荐在项目根目录放一个.env或者直接在 shell 里 export。配置片段如下:
export OPENAI_BASE_URL="https://taotoken.net/api" export OPENAI_API_KEY="sk-你的TaoTokenKey" export OPENCODE_MODEL="claude-sonnet-4-20250514"如果你的 OpenCode 版本用的是自定义 provider 配置,可以在配置目录下写settings.json:
{ "provider": { "taotoken": { "baseURL": "https://taotoken.net/api", "apiKey": "sk-你的TaoTokenKey", "model": "claude-sonnet-4-20250514" } } }注意 Base URL 结尾不要带/v1之外的路径,TaoToken 的 API 入口就是https://taotoken.net/api,具体路径由 SDK 拼接。Key 不要提交到仓库,CI 里用 secrets 注入。Model ID 必须和通道支持的模型一致,写错会返回模型不存在的错误,而不是 401,这两个错误的排查方向完全不同。
3.4 CI 场景的最小构建配置
CI 里建议把依赖安装和构建分开,方便缓存。一个可用的 GitHub Actions 片段:
- name: Setup Bun uses: oven-sh/setup-bun@v1 with: bun-version: latest - name: Install deps run: bun install --registry https://registry.npmmirror.com - name: Build opencode run: bun run --cwd packages/opencode build --single env: OPENAI_BASE_URL: https://taotoken.net/api OPENAI_API_KEY: ${{ secrets.TAOTOKEN_KEY }}构建步骤带上环境变量,是为了让构建后的自检步骤能直接复用,不用重复注入。如果你的 CI 只做产物归档不做自检,环境变量可以只放在自检步骤。
4. 验证请求:构建产物自检与一次真实模型调用
4.1 确认产物存在与版本信息
构建成功后,进入产物目录看结构:
ls -la packages/opencode/dist/opencode-linux-x64/bin/应该能看到opencode可执行文件。先跑版本:
./packages/opencode/dist/opencode-linux-x64/bin/opencode --version能打印出版本号,说明二进制本身可执行、运行时打包完整。再直接运行:
./packages/opencode/dist/opencode-linux-x64/bin/opencode会进入 TUI 界面,右下角显示版本信息。到这一步,构建链路就算通了,但还没验证模型通道。
4.2 用统一 Key 跑一次真实请求
在 TUI 里发一条最简单的指令,比如让它解释当前目录结构。如果配置正确,会看到请求发出并返回内容。如果卡住或报错,先看错误类型:
- 401:Key 无效或没注入,检查
OPENAI_API_KEY是否 export 成功,echo $OPENAI_API_KEY确认非空。 - 模型不存在:Model ID 写错,对照通道支持的模型列表改。
- 连接失败:Base URL 写错,确认是
https://taotoken.net/api,没有多余路径。
也可以用非交互方式验证,比如让 Agent 执行一个简单任务并输出到 stdout,具体子命令按你版本的 CLI 帮助来:
./packages/opencode/dist/opencode-linux-x64/bin/opencode run "列出当前目录下的文件"这条命令能返回结果,说明从二进制到模型通道的整条链路都通了。构建后自检的核心就是这一步:产物能跑 + 通道能通,两个都过才算真正跑通。
4.3 验证模型对话通道是否独立可用
有时候 Agent 本身没问题,但你想确认 Key 和通道是否正常,可以单独打一次模型对话接口。TaoToken 提供了模型对话页面,直接在浏览器里发一条消息就能验证:https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite
这一步的意义是隔离变量:如果对话页面能通、Agent 不通,问题在 Agent 配置;如果两边都不通,问题在 Key 或通道。排障时先做这个隔离,能省很多时间。
4.4 长期编码场景的通道选择
如果你构建 OpenCode 是为了长期做编码任务、跑 Agent 工作流,单次请求的通道够用,但频繁调用建议用 Coding Plan,配额和稳定性更适合持续使用:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite
接入文档在:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite
文档里有各语言 SDK 的接入示例,配置项名称和上面片段一致,照着改 Base URL 和 Key 即可。
5. 本篇常见错排查:401、local proxy failed、reading choices 与 OAuth
5.1 401 Unauthorized
最常见的报错。原因通常是 Key 没注入到构建产物的运行环境。注意构建时注入的环境变量不会自动带到运行时,除非你在同一个 shell 里执行。CI 里如果构建和自检是两个 step,环境变量要在自检 step 重新声明。排查命令:
echo $OPENAI_API_KEY输出为空就是没注入。另外检查 Key 有没有多余空格,复制时容易带上换行。
5.2 local proxy failed
这个报错通常出现在 Agent 尝试走本地代理转发请求时。如果你没有配置任何本地代理,检查环境里有没有残留的HTTP_PROXY、HTTPS_PROXY变量:
env | grep -i proxy有残留就 unset 掉。另一种情况是 Base URL 写成了本地地址,比如http://localhost:xxxx,改成https://taotoken.net/api即可。这个错误和网络环境无关,纯粹是配置指向问题。
5.3 reading choices 相关报错
报错信息里出现reading 'choices'或类似字段读取失败,说明请求发出去了,但返回体结构不符合预期。常见原因是 Base URL 多写了路径,比如写成https://taotoken.net/api/v1/chat/completions,SDK 又拼了一次,导致返回的是 404 页面而不是 JSON。正确写法是只写到https://taotoken.net/api,路径交给 SDK。另一个原因是 Model ID 不被通道支持,返回了错误对象,SDK 解析choices时拿到 undefined。
5.4 OAuth 相关报错
OpenCode 某些版本支持 OAuth 登录流程,如果你没走 OAuth 而是用 API Key,却触发了 OAuth 校验,检查配置里有没有残留的 OAuth 字段。把 provider 配置精简成只有baseURL、apiKey、model三项,多余的认证字段删掉。如果确实需要 OAuth,按官方文档走,不要和 API Key 混用。
5.5 构建阶段的交叉编译错误
全量构建时,musl 目标在 glibc 机器上可能报链接错误。解决办法是本地用--single只构建当前平台,多平台分发交给 CI 的对应 runner。另外bun run build报“script not found”,检查是不是在仓库根目录执行的,根目录的package.json没有 build 脚本,必须进packages/opencode或用--cwd。
5.6 依赖安装超时
bun install卡在 resolving 阶段超过两分钟,基本就是源的问题。加--registry https://registry.npmmirror.com重跑。如果之前有半成品缓存,先删node_modules和bun.lockb再装,避免锁文件里记录了慢源地址。
6. 把构建链路固化成可复用流程
构建这件事,跑通一次不难,难的是每次都能跑通。我的做法是把命令固化成脚本,放在仓库里,本地和 CI 共用。一个scripts/build-local.sh:
#!/usr/bin/env bash set -euo pipefail bun install --registry https://registry.npmmirror.com bun run --cwd packages/opencode build --single ./packages/opencode/dist/opencode-linux-x64/bin/opencode --versionset -euo pipefail保证任何一步失败就退出,不会带着半成品继续跑。CI 里把--single换成全量,其余不变。环境变量通过 secrets 注入,脚本里不写死 Key。
另一个实用技巧是给构建产物加一个自检步骤,在 CI 里跑一次opencode run的简单任务,确认通道通。这样每次提交都能保证“产物可运行 + 模型通道可用”,而不是等到部署后才发现 Key 过期。自检用的 Key 建议单独建一个,配额小一点,避免 CI 跑飞。
最后提醒一句:构建产物里的 Bun 运行时版本和构建机的 Bun 版本绑定,升级 Bun 后建议重新构建,不要混用旧产物。产物目录dist/不要提交到仓库,加进.gitignore。按这套流程走,OpenCode 的源码构建在本地和 CI 都能稳定复现,剩下的就是按你的业务需求改 Agent 逻辑了。