# OpenCode API 与免费模型机制分析报告

> 分析对象：OpenCode v1.18.15（源码 commit `38e10eb`，Linux x64 二进制 183 MB）
> 分析时间：2026-08-09
> 结论均经过 **源码定位 + 二进制字符串佐证 + 线上实测** 三重验证

---

## 一、材料获取

沙箱无法直连 GitHub，全程走国内镜像通道。

| 材料 | 来源 | 结果 |
|---|---|---|
| 源码 | `ghfast.top` 代理 GitHub（`github.com/sst/opencode`） | 219 MB，commit `38e10eb` |
| Linux x64 二进制 | `registry.npmmirror.com/opencode-linux-x64` | 58 MB tgz，解包 183 MB ELF |
| 模型目录 | `https://models.opencode.ai/api.json` | 3.5 MB JSON |

二进制为 **Bun 编译的单文件 ELF，未 strip**，JS 源码以明文字符串形式内嵌，可直接与仓库源码交叉比对。

---

## 二、整体架构

OpenCode 不是"自研模型"，而是一个 **多 Provider 聚合客户端**。它内置了 25+ 家厂商的 AI SDK 适配器（`BUNDLED_PROVIDERS`，见 `packages/opencode/src/provider/provider.ts:105-140`），包括 Anthropic、OpenAI、Google、xAI、Groq、Mistral 等。

其中官方自营的那一个叫 **OpenCode Zen**，provider id 就是 `opencode`。

```
┌──────────────┐   ①拉目录    ┌──────────────────────┐
│   OpenCode   │ ──────────▶  │  models.opencode.ai   │   模型元数据 + 定价
│   (客户端)    │             │  /api.json            │
└──────┬───────┘             └──────────────────────┘
       │ ②用户无 API Key 时
       │ 自动筛选 cost.input===0 的模型
       │ 注入 apiKey: "public"
       ▼
┌──────────────┐   ③OpenAI 兼容    ┌──────────────────────┐
│  opencode     │ ───────────────▶  │  opencode.ai/zen/v1   │   真实推理后端
│  provider     │   Bearer public   │  /chat/completions     │  (多厂商马甲)
└──────────────┘                   └──────────────────────┘
```

---

## 三、账号与鉴权体系

代码位置：`packages/opencode/src/account/account.ts`、`cli/cmd/account.ts`。

OpenCode 账号走标准 **OAuth2 Device Authorization Grant（设备码流）**：

1. 向 `https://opencode.ai/auth/device/code` POST，拿到 `device_code` + `user_code` + `verification_uri`。
2. 用户在浏览器打开验证页，输入 `user_code` 授权。
3. 客户端轮询 `https://opencode.ai/auth/device/token`，交换出 `access_token`。
4. 登录态缓存到本地（macOS Keychain / Windows Credential Manager / Linux libsecret，回退到明文文件）。

> 关键点：**设备码流是给"付费/登录用户"用的**。免费模型走的是另一条更简单的路——根本不登录。

二进制内已硬编码相关字符串，可佐证（`strings opencode | grep`）：

```
https://models.opencode.ai
https://opencode.ai/zen/v1
opencode-cli
/auth/device/token
/auth/device/code
```

---

## 四、免费模型（内置模型）的接收原理 ★核心

这是本任务最关键的发现，代码位于 `packages/opencode/src/provider/provider.ts`。

### 4.1 模型目录的远端来源

模型不是写死在代码里的，而是运行时从 `https://models.opencode.ai/api.json` 拉取（见 `packages/core/src/models-dev.ts`）。该 JSON 以 provider 为顶层 key，包含 `opencode`、`anthropic`、`openai` 等几十个 provider，每个 provider 下挂它自己的 `models` 字典，每个模型带 `cost`、`context`、`tool_call` 等字段。

### 4.2 免费模型的筛选逻辑

`provider.ts` 在合并 provider 配置时（约 179-201 行），对 **无凭证** 的情况做了特殊处理：

```ts
// 伪代码还原（provider.ts:179-201 附近）
if (config.apiKey === undefined) {
  // 没填 key → 只保留 input 价格为 0 的模型
  const models = Object.fromEntries(
    Object.entries(spec.models)
      .filter(([_, m]) => m.cost?.input === 0)
  );
  // 注入一个占位 key
  config.apiKey = "public";
  spec.models = models;
}
```

也就是说：

- **"免费模型"在 OpenCode 眼里 = 定价表里 `cost.input === 0` 的模型**。
- 当本地没配置任何 `apiKey` 时，客户端自动把这些免费模型留下，其余（付费模型）全部过滤掉。
- 同时给请求注入一个字面量 `apiKey: "public"` 作为占位凭证。

### 4.3 baseURL 与协议

`opencode` provider 的 `api` 字段在目录里就是 OpenAI 兼容形态，baseURL 为：

```
https://opencode.ai/zen/v1
```

走标准 **OpenAI Chat Completions 协议**（`/v1/chat/completions`、`/v1/models`），`tool_call` 标志由目录里的 `tool_call` 字段控制。

### 4.4 实测验证（沙箱内）

用 `cost.input===0` 的模型名，配 `Authorization: Bearer public`（甚至不加 auth 头也行），直接打 `https://opencode.ai/zen/v1`：

- 目录里 `opencode` provider 共 **87 个**模型，其中 **26 个**在定价表标 `cost.input===0`（即客户端眼里的"免费模型"）。
- 但用 `public` key 对这 26 个逐一发起真实对话探测，**只有 6 个真正可用**；其余 20 个返回 `401 "Model X is not supported"`——说明它们虽标价为 0，对未订阅的 public key 仍**需订阅**才开放。
- **真正免费（无需订阅、`public` key 直连可用）的只有以下 6 个**：

| 模型 id | 名称 | 实测 |
|---|---|---|
| `big-pickle` | Big Pickle | ✅ 自述为 DeepSeek 系 |
| `deepseek-v4-flash-free` | DeepSeek V4 Flash Free | ✅ |
| `laguna-s-2.1-free` | Laguna S 2.1 Free | ✅ |
| `longcat-2.0-free` | LongCat-2.0 Free | ✅ |
| `mimo-v2.5-free` | MiMo V2.5 Free | ✅ |
| `nemotron-3-ultra-free` | Nemotron 3 Ultra Free | ✅ |

> 注意：`grok-code`、`glm-5-free`、`kimi-k2.5-free` 等虽在目录标 `cost.input===0`，但实测返回 `401` 需订阅——**"标价为 0" ≠ "真免费"**。
> 这些真免费模型本质是多厂商（DeepSeek、智谱、MiniMax、面壁、NVIDIA 等）的**马甲接入**，由 OpenCode 统一网关聚合，可用性随官方调度波动（偶发 503，靠重试可自愈，详见反代项目的故障转移设计）。

---

## 五、免费 vs 付费 的能力边界

| 维度 | 免费（Zen public） | 付费（登录账号） |
|---|---|---|
| 凭证 | 无 / `Bearer public` | OAuth2 `access_token` |
| 模型范围 | 仅 **6 个**经实测真免费（`public` 直连可用） | 含全部订阅模型（Claude/GPT/opus 等，共 80+） |
| 计费 | 0 | 按 token 向 OpenCode 付费 |
| 速率/配额 | 网关隐式限流 | 与账户额度绑定 |
| 端点 | 同 `opencode.ai/zen/v1` | 同 |

---

## 六、反代项目（Go 实现：zen-proxy-go）

基于以上原理，用 **Go（标准库，零第三方依赖）** 实现了 OpenCode Zen 反向代理 `/workspace/opencode-reverse/zen-proxy-go`，把 OpenCode 的免费网关重新暴露成一个**标准 OpenAI 兼容代理**，并补上了官方客户端没有的能力：

| 能力 | 说明 |
|---|---|
| 协议兼容 | `/v1/chat/completions`、`/v1/models`、`/v1/completions`、`/health`、`/stats` |
| 免费锁定 | `free_only` 模式，仅放行**经实测真免费**的模型（动态探测 + 白名单兜底），杜绝误踩付费/订阅 |
| 故障转移 | 单模型 503/超时自动重试，可配多模型轮询 |
| 流式透传 | 原生 SSE 透传，不做缓冲 |
| 鉴权闸门 | 可选 `PROXY_API_KEY`，把 `public` 收敛成你自己的 key |
| 统计 | `/stats` 暴露请求数、成功/失败、各模型计数 |
| 部署 | 内置 `Dockerfile` + `docker-compose.yml` + `.env.example` |

Go 版已等价验证：health / models / 非流式 / 流式（SSE 透传）/ 免费拦截 / completions 转译 全部通过；并修复了流式 ctx 提前取消导致 0 字节的 bug、改为**启动同步预热**消除并发 build 竞态。

**三平台二进制**（纯静态、零依赖、可直接运行，位于 `zen-proxy-go/dist/`）：

| 平台 | 文件名 |
|---|---|
| Linux (amd64) | `zen-proxy-linux-amd64` |
| Windows (amd64) | `zen-proxy-windows-amd64.exe` |
| macOS (Intel) | `zen-proxy-darwin-amd64` |
| macOS (Apple Silicon) | `zen-proxy-darwin-arm64` |

交叉编译：`cd zen-proxy-go && bash build.sh`（内部 `CGO_ENABLED=0`，自动产出上述四平台）。
运行：`./dist/zen-proxy-linux-amd64`，默认监听 `http://0.0.0.0:8787`，行为与环境变量同上文表格。

> 早期还有一个 Node.js 原型 `zen-proxy/`（仅作参考），最终交付以 Go 版为准。

---

## 七、结论

1. **OpenCode 没有自己的模型**，它是聚合客户端；官方自营的免费通道叫 **OpenCode Zen**。
2. 免费模型的"开关"本质是一个**定价筛选 + 占位 key**：客户端按 `cost.input===0` 初筛并注入 `apiKey:"public"` 打到 `opencode.ai/zen/v1`；但**实测证实标价为 0 的 26 个里仅 6 个对未订阅用户真免费**，其余需订阅。
3. 该网关 **OpenAI 协议兼容、对免费模型几乎零鉴权**，因此可以直接被第三方反代复用——这正是 `zen-proxy` 做的事。
4. 免费模型是**多厂商马甲**（DeepSeek/智谱/MiniMax/面壁/NVIDIA 等），可用性随官方调度波动，反代层需做好重试与故障转移。

---

## 附：关键文件索引

| 用途 | 路径 |
|---|---|
| 源码 | `downloads/src/opencode/` |
| Linux 二进制(tgz) | `downloads/bin/opencode-linux-x64-1.18.15.tgz` |
| 免费模型筛选逻辑 | `packages/opencode/src/provider/provider.ts:179-201` |
| 账号/设备码流 | `packages/opencode/src/account/account.ts` |
| 模型目录数据源 | `packages/core/src/models-dev.ts` → `https://models.opencode.ai/api.json` |
| 线上实测数据 | `analysis/truly-free.json`（26 个标免费模型全量探测）、`analysis/zen-models-now.json` |
| 反代项目（Go） | `zen-proxy-go/`（二进制 `zen-proxy-go/dist/`） |
