# 配置 DeepSee

[English](configure.md) | 中文

用户询问如何安装、配置或切换 DeepSee provider 时读这份文档。优先替用户把命令跑掉，而不是解释给他听。

## 配置放在哪

`~/.deepsee/config.json`，由 CLI 管理。优先级：CLI 参数 > 环境变量 > 配置文件 > 内置默认值。不设 `provider` 时按失败切换链依次尝试（有 `gemini-api` key 会先于 agent CLI 被试到），机器上什么都没配才会落在 `antigravity-cli`。

```bash
deepsee config init                     # 写入一份起步配置（已存在则拒绝，--force 重写）
deepsee config show                     # 生效的配置文件，API key 打码显示
deepsee config set provider <name>      # 更改默认 provider
deepsee config set <provider>.<field> <value>   # 字段：apiKey、apiKeys、baseUrl、model、extraBody
```

`config set` 写文件时权限为 0600。

## 配置文件的完整形状

所有内容都在四个顶层键之下，全部可选。下面的示例一次性展示了所有支持的键和字段（真实文件只需要写你用到的部分）。文件不存在就全用默认值。provider 的设置放在 `providers.<name>` 下面，不在顶层，手工编辑最常犯的就是这个错。

```json
{
  "provider": "gemini-api",
  "proxy": "http://127.0.0.1:7890",
  "reuse": { "claude": true, "codex": true, "opencode": false, "pi": true, "grok": true },
  "guards": {
    "allowModels": ["deepseek-v4-*", "glm-5.*", "minimax-m2.5*", "qwen3-coder*"],
    "denyModels": ["glm-*v*", "deepseek-vl*"],
    "denyWhenUnknown": false
  },
  "providers": {
    "antigravity-cli": { "model": "gemini-3.6-flash-low" },
    "gemini-api": {
      "apiKeys": ["AIza...one", "AIza...two"],
      "baseUrl": "https://generativelanguage.googleapis.com",
      "model": "gemini-flash-latest"
    },
    "openai": {
      "apiKey": "sk-...",
      "baseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1",
      "model": "qwen3.6-27b",
      "extraBody": { "thinking": { "type": "disabled" } }
    },
    "anthropic": {
      "apiKey": "sk-ant-...",
      "baseUrl": "https://api.anthropic.com",
      "model": "claude-haiku-4-5-20251001"
    },
    "claude-cli": { "model": "haiku" }
  }
}
```

字段含义：

- `provider`：不传 `-p` 时由哪个 provider 执行。标准名和别名都行（`agy`/`antigravity` 对应 `antigravity-cli`，`gemini` 对应 `gemini-api`，`openai-compat` 对应 `openai`，`claude` 对应 `anthropic`，`claude-code` 对应 `claude-cli`）。留空或缺失表示不钉任何一个：由失败切换链决定，已配置的 API provider 先于 agent CLI 被尝试。
- `providers.<name>.<field>`：支持 `apiKey`、`apiKeys`、`baseUrl`、`model`、`extraBody`。`apiKeys` 是 Gemini 轮换列表；配置文件中写 JSON 数组，`config set` 可传逗号或换行分隔，空白和重复项会自动移除，并按顺序尝试。旧的单数 `apiKey` 仍兼容。每个 provider 条目都可选，条目里的每个字段也都可选。别名键同样会被读取（存在 `gemini` 下的设置在解析到 `gemini-api` 时也能找到），冲突时标准键胜出。
- `providers.<name>.extraBody`：一个 JSON 对象，合并进 API provider（`gemini-api`、`openai`、`anthropic`）的请求体，用来传厂商有而 deepsee 没有对应参数的开关。最常见的用途是关掉思考，见下文小节。嵌套对象逐键合并，所以加一个开关不会动到该块里的其他内容。承载图片、提示词和 schema 约束的字段会被拒绝，报错会点名该字段。两个 CLI provider 不发请求体，所以在 `antigravity-cli` 或 `claude-cli` 上运行时它会被忽略，并在 `meta.warnings` 里说明。
- `guards`：调用 guard，给在同一个客户端里既跑纯文本模型又跑视觉模型的人用。两个列表都放 glob 模式（支持 `*` 和 `?`，不区分大小写，同时匹配模型名和 `provider/model`），用 `deepsee config set guards.denyModels '["gemini-3*"]'` 或 `guards.allowModels` 设置（JSON 数组或逗号分隔的列表都行，传空则清除）。两种写法表达同一个意图，选列表更短的那种：
  - 只用 `denyModels`：除了列出的视觉模型，其余全部运行引擎。适合你接入的模型大多是纯文本的情况。
  - `allowModels` 非空（白名单模式）：只有列出的模型运行引擎，其他所有已识别的模型一律拒绝。适合 2026 年的实际格局，纯文本模型才是那份短名单。deny 模式仍然优先于 allow 匹配，所以宽泛的 allow 可以把视觉变体剔出去，正如上面的示例：`glm-5.*` 放行文本系列，`glm-*v*` 抓住 `glm-5v-turbo`。allow 模式要锚定得紧一些（写 `deepseek-v4-*` 而不是 `deepseek*`），这样厂商下一代多模态型号会自动掉出名单，等你检查过再上场。
  - 按真正抵达模型的内容来列名单，而不是按它本来能看到什么：多模态模型如果躲在一个剥离图片的网关后面，照样需要 deepsee，而你的会话记录里存的是网关上报的模型名。`deepsee doctor` 的 Guard 一节会显示规则和一条实时判定，方便核对结果。
  - `denyWhenUnknown`（默认 `false`）决定在两种模式下，当没有任何信号能识别当前模型时怎么办：`false` 放行，`true` 拒绝。当前模型的检测来源从强到弱依次是：`DEEPSEE_MODEL` 环境变量（`none` 表示「按未知处理」）、harness 的会话存储、`--model` 自报。
- 环境变量会覆盖配置文件。Gemini 的优先级是 `GEMINI_API_KEYS`（逗号或换行列表）> `GEMINI_API_KEY` > 文件里的 `apiKeys` > 文件里的 `apiKey`。其他绑定为 `OPENAI_API_KEY`、`OPENAI_BASE_URL`、`ANTHROPIC_API_KEY`、`ANTHROPIC_BASE_URL`。除此之外，deepsee 还读取 `DEEPSEE_HARNESS`（粘贴恢复和 guard 的作用范围）、`DEEPSEE_MODEL`（guard 覆盖，见 `guards`），以及各 harness 自己注入的指纹，它们把 guard 的存储查询钉在当前 session 上：`CLAUDE_CODE_SESSION_ID`、`CODEX_THREAD_ID`，加上 harness 检测依赖的存在性标记（`CLAUDECODE`、`PI_CODING_AGENT`、`CODEX_SANDBOX`）。
- `reuse.<claude|codex|opencode|pi|grok>`：按 harness 记录的授权，决定能否花费本机其他登录态，由引导对话（`references/onboard.md`）写入。`true` 允许读图时复用该 harness（pi 的凭据加入 inline 区且所有 guard 照常生效，已登录的 Codex、OpenCode 的视觉模型或直接驱动的 pi 加入 agent 区，排在 `claude-cli` 之前），`false` 记下一次拒绝，用户不会被再次询问，缺失表示从未问过，什么都不会运行。`claude` 缺失视为已授权：`claude-cli` 作为内置 provider 早于这套模型存在，`reuse.claude false` 会把它移出链条（`-p claude-cli` 仍可钉死）。复用来的引擎不比用户自己的优先：分区只按速度档次排序。每个复用得来的答案都会在 `meta.warnings` 里加一行，说明花的是谁的额度，`deepsee doctor` 的 Reuse 一节会显示每个 harness 的决定和探测发现的结果（探测结果在 `~/.deepsee/auto-cache.json` 里缓存 6 小时，doctor 每次都重新探测）。用 `deepsee config set reuse.codex true` 设置（传空恢复为从未问过）。
- 未知的顶层键和未知的 provider 名会被忽略而不是报错，所以敲错字会无声失败：手工编辑后跑一下 `deepsee doctor`，它会显示哪些文件值和环境变量真正生效。

手工编辑没问题（保持文件是合法 JSON，权限 0600）。`deepsee config set` 做的是同一件事，只是多了护栏。

## 各 provider 配置步骤

### antigravity-cli（默认，免费，无需 key）

需要装好 Antigravity CLI 并完成登录：

```bash
curl -fsSL https://antigravity.google/cli/install.sh | bash
agy    # 用户需自己在浏览器完成登录，然后退出
```

任何免费 Google 账号都行，不需要 Google AI Pro。登录无法自动化，请让用户自己跑一次 `agy`。

### gemini-api（免费 key，最快的免费通道，5-10 秒）

1. 用户到 https://aistudio.google.com 创建一个 key（约三分钟，无需信用卡，免费额度不过期）。
2. 保存一把 key，或用换行一次放入多把：

```bash
deepsee config set gemini-api.apiKey <key>
# 或走环境变量：export GEMINI_API_KEY=<key>
# 多把：deepsee config set gemini-api.apiKeys $'key-one\nkey-two'
# 或环境变量：export GEMINI_API_KEYS=$'key-one\nkey-two'
```

遇到 401、403、429，或明确写着额度／限流的 4xx 回应时，DeepSee 会换下一把。普通请求错误、网络失败和服务器失败会立刻报出，因为换 key 只会重复同一个问题。`deepsee config show` 只显示多把 key 的数量，不会显示内容。在 DeepSeek Harness 中，同一份列表也能从 **DeepSee Settings** 编辑；浏览器端只能读取已保存数量。

默认使用 Google 会自动更新的 `gemini-flash-latest` 别名，新一代 Flash 发布后无需等待 DeepSee 更新即可使用。Google 可能把这个别名指向 stable、preview 或 experimental 版本；需要可重复结果的用户可执行 `deepsee config set gemini-api.model <model-id>` 固定版本。免费额度取决于别名当时对应的模型。免费档的数据可能被 Google 用于改进产品，用户要处理敏感图片时请提醒这一点。

### openai（任意 OpenAI 兼容的多模态端点）

需要三个值。以 DashScope 的 qwen 为例：

```bash
deepsee config set openai.baseUrl https://dashscope.aliyuncs.com/compatible-mode/v1
deepsee config set openai.apiKey <sk-key>
deepsee config set openai.model qwen3.6-27b
```

官方 OpenAI 的写法：baseUrl 用 `https://api.openai.com/v1`，配一个具备视觉能力的模型。对应的环境变量：`OPENAI_BASE_URL`、`OPENAI_API_KEY`。模型必须是多模态的，纯文本模型会失败或产生幻觉。这条路线没有服务端 schema 约束，偶发的结构错误会以明确报错的形式暴露出来，重试或换 provider 即可。

### anthropic（Claude API key）

```bash
deepsee config set anthropic.apiKey <sk-ant-key>
# 或：export ANTHROPIC_API_KEY=<key>
```

默认模型是 Claude Haiku（`claude-haiku-4-5-20251001`）。schema 通过强制工具调用来约束。

**`ANTHROPIC_BASE_URL` 陷阱。**deepsee 把 `ANTHROPIC_BASE_URL` 绑定到 `anthropic.baseUrl`，所以这个变量指向哪它就继承哪。如果用户在 shell 里设过它，用来把 Claude Code 路由到某个纯文本网关（在 Claude Code 界面下跑非 Claude 模型的常见做法），那么 `-p anthropic` 也会把视觉请求无声地发到那个网关，要么失败，要么返回的结果像没看过图，而且没有任何端点被换掉的提示。anthropic 的视觉表现异常时，先 `echo $ANTHROPIC_BASE_URL` 查一下。解法：给 deepsee 调用临时取消这个变量，或用 `deepsee config set anthropic.baseUrl https://api.anthropic.com` 钉死真实端点，或改用 `-p gemini-api`。

### claude-cli（Claude Code 登录态，无需 key）

借用已有的 `claude` 登录态，花的是用户的 Claude 订阅额度，不产生单独的 API 账单。需要装好并登录 Claude Code（用 `claude --version` 检查）。运行时只带 `--allowedTools Read`。只支持本地图片文件，远程 URL 请改用 gemini-api。默认模型别名 `haiku`。

```bash
deepsee config set provider claude-cli   # 用户愿意的话把它设为默认
```

## 关闭思考

推理模型答题前要先花掉思考预算。从图片里读文字用不上这些，所以在默认思考的模型上，一次识别白白变得又慢又贵。每家厂商给这个开关起的名字都不一样，也没有通用写法，所以 deepsee 只负责把你放进 `extraBody` 的内容原样发出去，名字怎么写去查厂商自己的文档。

```bash
deepsee config set openai.extraBody '{"thinking":{"type":"disabled"}}'   # 持久保存
deepsee -i shot.png --extra-body '{"thinking":{"type":"disabled"}}'      # 仅本次运行
deepsee config set openai.extraBody ''                                   # 清除
```

`--extra-body` 在该次运行中整体替换已存储的对象，而不是合并进去。

已知写法，截至 2026 年 8 月：

| 端点 | 要发送的字段 |
| :-- | :-- |
| MiMo 官方 API（`api.xiaomimimo.com/v1`） | `{"thinking":{"type":"disabled"}}` |
| MiMo Responses 格式路由 | `{"reasoning":{"effort":"none"}}` |
| Qwen、GLM、MiMo 等自建在 vLLM 或 SGLang 上 | `{"chat_template_kwargs":{"enable_thinking":false}}` |
| 接受 effort 档位的 OpenAI 风格网关 | `{"reasoning_effort":"low"}` |
| `gemini-api`，Gemini 3 系列 | `{"generationConfig":{"thinkingConfig":{"thinkingLevel":"LOW"}}}` |
| `gemini-api`，Gemini 2.5 Flash 与 Flash Lite | `{"generationConfig":{"thinkingConfig":{"thinkingBudget":0}}}` |
| `anthropic` | 什么都不用做，不主动要求就不思考 |

三个会咬人的地方：

- 不是每个模型都能关。Gemini 3 Pro 和 Gemini 2.5 Pro 没有关闭开关，只能调低档位。有些模型完全无视 effort 字段，照样思考。
- 严格的云（Groq 和 Cerebras 都在内）遇到不认识的字段会直接返回 400。以前能跑的请求现在报 400 并点名你的字段，说明那个网关要的是另一种写法，不是这一种。
- 另一些则会接受未知字段然后悄悄忽略，所以要验证它是否生效，别想当然。把 `meta.durationSeconds` 和 `meta.usage` 里的 token 数与不带 `extraBody` 的一次运行对比，两者都没变，就是字段没起作用。
- 较弱的模型可能得靠思考才能填满 schema。在同一张流程图上实测：`gemini-3.6-flash` 在 `thinkingLevel: LOW` 下从 12 秒缩到 5.7 秒，区块和转录内容不变，但 DashScope 上的 `qwen3.6-27b` 设了 `enable_thinking: false` 后开始漏掉版面区块必填的 `type`，deepsee 会拒绝这种结果而不是当作证据放行。刚关掉思考就出现结构错误，说明这就是代价，给那个模型把思考打开，或换到有服务端 schema 约束的路线。

## 替用户选 provider

- 想零配置且免费：`antigravity-cli`（需要 agy 登录，每张图 15-40 秒，密集或困难的图可试 `-m gemini-3.1-pro-high`）。
- 想又快又免费：`gemini-api`（三分钟领 key，5-10 秒）。
- 已经在给 Claude 付费：`claude-cli`（无需额外 key，agent 循环 20-45 秒）或 `anthropic`（API 计费）。
- 有偏好的多模态端点（qwen、GLM 等）：`openai`。

每个配好的 provider 也互为后备：一次运行按固定顺序尝试它们（5-10 秒的 inline API provider 先上，然后是 agent 类，对远程 URL 来说这个顺序同时也是一道安全边界），遇到报错、超时或违反 schema 的结果就故障转移。`config set provider <name>` 把某个 provider 提到它所在允许分区的最前面，`-p <name>` 钉死唯一一个，不做回退。`doctor` 会打印这些故障转移链，结果里的 `meta.attempts` 显示一次运行实际试了什么。

## 故障排查

- 报错点名了缺失的环境变量或某条 `config set` 命令：照着运行即可。
- `Provider CLI not found: agy`：安装 Antigravity CLI 或换 provider。
- `Claude CLI reported ...` 或结果为空：检查 `claude` 的登录状态。
- openai 路线报 `does not match the vision schema`：重试一次，仍不行就换 gemini-api 或 anthropic。
- `extraBody cannot override "<field>"`：该字段承载图片、提示词或 schema。把它从对象里去掉，留下厂商开关即可。
- 400 报错点名了你在 `extraBody` 里设的字段：那个网关不认识它。其他写法见上文关闭思考一节。
- `config init` 拒绝执行：文件已存在。先用 `deepsee config show` 查看，只有用户同意覆盖时才加 `--force`。
