跳到正文
Hacker News· ilreb·· 5 天前AI 评分36

OpenCode 2.0 迁移指南:插件 API、服务端契约与配置格式的破坏性变更

Migrating to OpenCode 2.0

AI 导读

OpenCode 2.0 带来三处有意为之的破坏性变更:插件改用新 plugin API,服务端 API 与客户端契约更新,终端客户端配置从分层 tui.json(c) 文件改为单一全局 cli.json(自动迁移)。

正文 · AI 翻译

OpenCode 1 和 OpenCode 2 都使用 opencode 命令,默认不再并排安装。在安装 V2 之前,请移除由包管理器管理的 V1 安装;V2 的 curl 安装程序会替换 V1 二进制文件。

破坏性变更

V2 有三项有意的破坏性变更:

这些区域之外受支持的 V1 功能旨在与 V1 保持兼容。V1 schema 接受的一些字段从未有 V2 等价物,会被有意忽略;这些列在已接受但不支持的字段下。

.opencode/ 中现有的受支持服务器配置字段、代理定义、命令定义、技能和其他文件应继续无需更改即可工作。如果本指南中描述的受支持行为在 V2 中停止工作,请将其视为兼容性错误,而不是预期的迁移要求。

安装 V2

使用终端启动指南安装 V2 终端客户端。

你不需要在开始使用 V2 之前重写所有内容。一个实用的迁移方式是:

  1. 保留你现有的配置和基于文件的定义。
  2. 启动 V2 并验证模型、凭据、代理、权限和 MCP 服务器。
  3. 移植插件,因为 V1 插件实现无法在 V2 中运行。
  4. 移植调用服务器 API 的集成。
  5. 当你准备好时,将配置转换为原生 V2 形式。此步骤是可选的。

在验证迁移期间保留一份 V1 设置的副本。V1 和 V2 使用相同的配置位置,因此不要将 V1 指向已转换为仅原生 V2 形式的文件。

配置

本节涵盖 JSON/JSONC 配置以及 .opencode/ 下基于文件的定义。

使用你现有的配置

V2 从与 V1 相同的位置读取现有的全局和项目配置:

~/.config/opencode/opencode.json(c)
<project>/opencode.json(c)
<project>/.opencode/opencode.json(c)

V2 读取这些相同的位置。它在内存中规范化受支持的 V1 和原生 V2 字段,而不重写源文件。现有的受支持 V1 配置旨在继续工作,因此你无需转换它即可尝试或采用 V2。

让 OpenCode 进行迁移

V1 配置格式仍然受支持。原生 V2 格式是可选的,它使若干设置更加明确且符合人体工程学。

推荐的迁移路径是让 OpenCode 为你更新配置:

Migrate my OpenCode configuration, including file-based definitions, from the V1 format to the native V2 format.
Preserve its behavior and all unrelated settings.

OpenCode 可以检查完整文件,应用下面的相关更改,并避免重写不需要更改的设置。转换不需要一次性完成:受支持的 V1 和原生 V2 字段可以在顶层共存。当两种形式设置相同的规范值时,有效的原生 V2 值优先,无论 JSON 键的顺序如何。

嵌套混合是有意限制的。OpenCode 识别 mcp、compaction 和 experimental 内的混合 V1 和 V2 成员,但它不会递归推断单个代理、提供者、命令或模型内部的格式。请将每个嵌套条目完全保持为一种格式。受支持的 V1 语法本身保持静默;格式错误的值、不支持的旧字段以及冲突的 V1/V2 值会产生警告,同时无关的有效设置继续加载。

共享

已弃用的 V1 autoshare 布尔值变为显式的 share 策略:

// V1
{ "autoshare": true }

// V2
{ "share": "auto" }

使用 "manual"、"auto" 或 "disabled"。如果 V1 文件已经使用 share,则无需更改。

权限和工具

V1 按工具对权限效果进行分组。V2 使用一个有序的 permissions 数组,使优先级和例外情况变得明确:

// V1
{
  "permission": {
    "bash": {
      "git push *": "ask"
    },
    "edit": "allow"
  },
  "tools": {
    "websearch": false
  }
}

// V2
{
  "permissions": [
    { "action": "shell", "resource": "git push *", "effect": "ask" },
    { "action": "edit", "resource": "*", "effect": "allow" },
    { "action": "websearch", "resource": "*", "effect": "deny" }
  ]
}

权限操作也发生了变化:bash 现在是 shell,task 现在是 subagent,而 write 和 patch 现在是 edit。 有关有序的 V2 规则格式,请参阅 Permissions。

代理与模式

单数的 agent 和已弃用的 mode 映射变为 agents。代理字段与 V2 配置的其余部分变得更加一致:

// V1
{
  "agent": {
    "reviewer": {
      "prompt": "Review for correctness and missing tests.",
      "model": "anthropic/claude-sonnet-4-5",
      "variant": "high",
      "disable": false,
      "permission": {
        "edit": "deny"
      }
    }
  }
}

// V2
{
  "agents": {
    "reviewer": {
      "system": "Review for correctness and missing tests.",
      "model": "anthropic/claude-sonnet-4-5#high",
      "disabled": false,
      "permissions": [
        { "action": "edit", "resource": "*", "effect": "deny" }
      ]
    }
  }
}

prompt 变为 system,disable 变为 disabled,并且一个单独的 variant 在 # 之后加入模型引用。 temperature、top_p 和特定于提供商的 options 移到 request.body 下。maxSteps 变为 steps。来自 旧 mode 映射的条目成为主代理。

快照

将单数的 snapshot 字段重命名为 snapshots。其布尔值不变:

// V1
{ "snapshot": false }

// V2
{ "snapshots": false }

媒体

将单数的 attachment 对象重命名为 media。嵌套的图像设置保持相同的名称:

// V1
{ "attachment": { "image": { "auto_resize": true } } }

// V2
{ "media": { "image": { "auto_resize": true } } }

MCP 服务器

V2 将服务器分组到 mcp.servers 下,用相反的 disabled 替换 enabled,并区分超时用途:

// V1
{
  "mcp": {
    "playwright": {
      "type": "local",
      "command": ["npx", "@playwright/mcp"],
      "enabled": true,
      "timeout": 30000
    }
  }
}

// V2
{
  "mcp": {
    "servers": {
      "playwright": {
        "type": "local",
        "command": ["npx", "@playwright/mcp"],
        "disabled": false,
        "timeout": {
          "catalog": 30000,
          "execution": 30000
        }
      }
    }
  }
}

远程 OAuth 字段使用蛇形命名:clientId 变为 client_id,clientSecret 变为 client_secret, callbackPort 变为 callback_port,而 redirectUri 变为 redirect_uri。V1 的 experimental.mcp_timeout 值 也会成为默认的 mcp.timeout.catalog 和 mcp.timeout.execution 值。请参阅 MCP servers。

压缩

V2 将保留上下文的 token 预算分组到 keep 下,并为预留部分赋予更清晰的名称:

// V1
{
  "compaction": {
    "preserve_recent_tokens": 8000,
    "reserved": 20000
  }
}

// V2
{
  "compaction": {
    "keep": {
      "tokens": 8000
    },
    "buffer": 20000
  }
}

auto 保持其名称。V2 没有原生的 tail_turns 或 prune 字段;这两个旧字段都会被忽略并给出警告。最近的 上下文改为通过 token 预算来保留。请参阅 Compaction。

技能

V1 将额外的技能路径和 URL 分开。V2 将两者合并为一个有序数组:

// V1
{
  "skills": {
    "paths": ["./team-skills"],
    "urls": ["https://example.com/skills/"]
  }
}

// V2
{
  "skills": ["./team-skills", "https://example.com/skills/"]
}

现有的技能文件和自动 .opencode/skills/ 发现不会改变。请参阅 Skills。

命令

将单数的 command 映射重命名为 commands,将 subtask 重命名为 subagent。将单独的模型 variant 加入模型引用:

// V1
{
  "command": {
    "review": {
      "template": "Review the current changes.",
      "model": "anthropic/claude-sonnet-4-5",
      "variant": "high",
      "subtask": true
    }
  }
}

// V2
{
  "commands": {
    "review": {
      "template": "Review the current changes.",
      "model": "anthropic/claude-sonnet-4-5#high",
      "subagent": true
    }
  }
}

template、description 和 agent 保持其名称。旧版 subtask 仍被接受;委托的命令现在会 自动在后台运行,并将其结果报告给父会话。现有的 Markdown 命令定义仍受支持。 请参阅 Commands。

引用

将已弃用的单数 reference 映射重命名为 references:

// V1
{ "reference": { "docs": "../docs" } }

// V2
{ "references": { "docs": "../docs" } }

V1 已经接受 references,因此当文件使用它时无需更改。引用条目保持 相同的结构。请参阅 References。

提供商

将单数的 provider 映射重命名为 providers。V2 将运行时包、端点和请求设置分开:

// V1
{
  "provider": {
    "acme": {
      "npm": "@ai-sdk/openai-compatible",
      "api": "https://llm.example.com/v1",
      "options": {
        "apiKey": "{env:ACME_API_KEY}"
      }
    }
  }
}

// V2
{
  "providers": {
    "acme": {
      "package": "aisdk:@ai-sdk/openai-compatible",
      "settings": {
        "baseURL": "https://llm.example.com/v1",
        "apiKey": "{env:ACME_API_KEY}"
      }
    }
  }
}

V1 的 npm 变为 package,AI SDK 包获得 aisdk: 前缀。api 变为 settings.baseURL。提供商的 options 根据其请求角色被分为 settings、headers 和 body。请参阅 Providers。

V2 合并了两个旧版提供商命名空间:

V1 提供商 ID规范的 V2 提供商 ID
azure-cognitive-servicesazure
google-vertex-anthropicgoogle-vertex

对无歧义的 V1 提供商、代理、命令和提供商过滤字段的迁移使用这些规范 ID。共享的 顶层 model 字段保留其确切的提供商 ID,因为相同的语法在原生的 V2 配置中有效;在迁移旧版内置提供商时,请将该字段 更新为规范 ID。

模型与变体

模型仍嵌套在其提供商下,但若干模型字段变得更加明确:

  • id 变为 modelID。
  • tool_call 和 modalities 变为 capabilities.tools、capabilities.input 和 capabilities.output。
  • "deprecated" 的 status 变为 disabled: true。
  • 缓存成本从 cache_read 和 cache_write 移到 cache.read 和 cache.write。
  • 特定于提供商的 options 变为 settings。
  • V1 的变体对象变为 V2 数组,每个条目上带有一个 id。
// V1
{
  "variants": {
    "high": {
      "reasoningEffort": "high"
    }
  }
}

// V2
{
  "variants": [
    {
      "id": "high",
      "settings": {
        "reasoningEffort": "high"
      }
    }
  ]
}

有关完整的原生模型结构,请参阅 Models。

没有直接原生对应项的受支持字段

大多数保持相同结构的字段,包括 shell、model、default_agent、watcher、formatter、 instructions、enterprise 和 tool_output,无需迁移。

V2 接受并保留 lsp 配置,但它不会运行语言服务器、暴露 LSP 工具或生成 LSP 诊断信息。请将依赖这些能力的工作流替换为项目的 lint、typecheck 或编译器命令。

V1 的 provider 过滤器没有一对一的原生 V2 配置字段,但其行为仍通过 policies 得到支持:

  • enabled_providers 变为一个内部的默认拒绝 provider 策略,随后为列出的 provider 添加允许项。
  • disabled_providers 变为针对所列 provider 的内部拒绝策略。
  • autoupdate 变为 update:false 映射到 "disable","notify" 映射到 "notify",true 映射到 "auto"。
  • small_model 变为内置 title agent 的 model 选择。原生 V2 配置应改用 agents.title.model。

你可以保留这些字段的 V1 语法。OpenCode 会在不发出警告的情况下将其规范化。

已接受但不支持的字段

V1 schema 还接受了一些在 V2 中没有受支持行为的字段。V2 会忽略这些值并发出警告,以免它们被误认为是生效的配置:

  • logLevel:启动 OpenCode 时使用 OPENCODE_LOG_LEVEL。
  • server:使用 V2 服务和显式 server 选项;server API 是有意为之的破坏性变更。
  • 顶层 subagent_depth:改用 experimental.subagent_depth。
  • compaction.tail_turns 和 compaction.prune:V2 改用 compaction.keep.tokens 和基于 checkpoint 的压缩。
  • V1 JSON 配置中的 agent name。
  • 仅启用、没有 type 的 V1 MCP 条目。
  • V1 实验性字段 batch_tool、openTelemetry、primary_tools 和 continue_loop_on_deny。
  • V1 provider 字段 id、whitelist 和 blacklist。
  • V1 provider-model 字段 release_date、attachment、reasoning、temperature、experimental、非 deprecated 的 status,以及布尔值 interleaved。

忽略这些字段是有意为之,并非兼容性回归。如果 V2 未保留本指南其他地方标识为受支持的行为,请遵循 Troubleshooting 中的问题报告指引。

Agent 文件

V1 agent 文件可以使用 agent/、agents/、mode/ 或 modes/。V2 仍会发现全部四个目录。首选的 V2 位置是:

.opencode/agents/<name>.md

V1 mode/ 或 modes/ 目录下的文件代表主 agent。将其移入 agents/ 时,请在其 frontmatter 中添加 mode: primary。agent/ 下的文件可以移到 agents/,而无需更改其由路径派生的 ID。

将 frontmatter 转换为原生 V2 字段时:

  • 保留 Markdown 正文作为 agent 的系统指令。
  • 当 prompt 出现在 JSON 配置中时,将其重命名为 system;文件正文不需要 system 字段。
  • 将 disable 重命名为 disabled,将 permission 重命名为 permissions。
  • 将 model 和 variant 合并为 provider/model#variant。
  • 将 temperature、top_p 和 provider 特定选项移到 request.body 下。

V2 会自动转换旧版 agent frontmatter,因此这些编辑是可选的。参见 Agents。

命令文件

V1 命令文件可以使用 command/ 或 commands/。V2 会发现两者。首选位置是:

.opencode/commands/<name>.md

将文件从 command/ 移到 commands/ 下的相同相对路径,以保留命令名称。Markdown 正文仍是命令模板,description 和 agent frontmatter 保持相同的名称。将 subtask 重命名为 subagent,以使用后台委托的原生名称。如果 frontmatter 有单独的 model 和 variant 字段,请将变体追加到模型并移除 variant:

# V1
model: anthropic/claude-sonnet-4-5
variant: high
subtask: true

# V2
model: anthropic/claude-sonnet-4-5#high
subagent: true

参见 Commands。

Skill 文件

V2 会从 .opencode/skill/ 和 .opencode/skills/ 中发现 skill。首选布局是:

.opencode/skills/<skill-id>/SKILL.md

移动整个 skill 目录,而不仅仅是 SKILL.md,以便相对脚本、引用和其他支持文件仍然可用。保持目录名称稳定,以保留 skill ID。现有的 skill frontmatter 和 Markdown 正文无需为 V2 重写。参见 Skills。

指令文件

现有的 AGENTS.md 文件保持原位。V2 会从当前目录向上到 home 发现全局 ~/.config/opencode/AGENTS.md 和环境 AGENTS.md 文件。对于 home 之外的项目,发现会在项目根目录停止。

如果 V1 设置依赖 CLAUDE.md 回退,请将该指引移入适用的 AGENTS.md。V2 目前仅发现 AGENTS.md;由于非 API 的 V1 行为旨在保持兼容,还请针对受影响的项目详情提交一个兼容性问题。参见说明。

终端客户端配置

V2 用单个全局终端客户端配置文件取代分层的 V1 tui.json(c) 文件:

~/.config/opencode/cli.json

该文件由终端客户端持有;后台服务不会加载它。当 cli.json 不存在时,首次 V2 终端客户端启动会迁移受支持的全局 tui.json 设置和持久化偏好,同时保持 V1 文件不变。项目本地的客户端配置不会被迁移,因为 V2 客户端配置是全局的。当前客户端设置参考参见CLI 设置。

插件

将 plugin 重命名为 plugins。将包与选项元组替换为对象:

// V1
{
  "plugin": ["opencode-example-plugin", ["./plugin/local.ts", { "enabled": true }]]
}

// V2
{
  "plugins": [
    "opencode-example-plugin",
    {
      "package": "./plugin/local.ts",
      "options": { "enabled": true }
    }
  ]
}

V2 会从 .opencode/plugin/ 和 .opencode/plugins/ 中发现本地插件;V2 文件请使用 .opencode/plugins/。

使用专门的插件迁移指南移植入口点、钩子、工具、事件和包导出。

服务器 API 与客户端

OpenCode 2 拥有经过修订、更符合人体工学的服务器 API 以及一组新客户端。调用 V1 服务器 API 的集成必须迁移到 V2 API。

使用 @opencode/client 包访问已发布的 V2 API。其端点、请求类型和响应参见生成的API 参考。

验证你的设置

在依赖 V2 进行日常工作之前,先在项目中验证你的模型、提供商凭据、代理、权限、MCP 服务器和插件。在确认你所需的 V2 行为之前,请保留你的 V1 设置,并且不要将 V1 指向你已转换为原生 V2 形态的配置。

来源:Hacker News · opencode.ai