5.10c SDK V2:下一代 API
一句话总结:V2 是 OpenCode SDK 的下一代入口,引入
client.v2.*命名空间、独立的 Permission/Question 模块,以及 Session3 的 interrupt/wait/compact 等增强方法。
⚠️ 实验性功能
V2 入口(@opencode-ai/sdk/v2)当前标记为实验性,API 签名可能随版本变化。生产环境建议继续用 V1(@opencode-ai/sdk)。本章基于源码 packages/sdk/js/src/v2/,版本 1.17.14,以源码为准。
学完你能做什么
- 区分 V1 和 V2,知道什么时候用哪个
- 用
@opencode-ai/sdk/v2创建客户端 - 理解
client.*和client.v2.*两层访问路径 - 使用 Permission、Question 独立模块
- 调用 Session3 的增强方法(interrupt、wait、compact 等)
- 从 V1 迁移到 V2
V2 是什么
V1 和 V2 的定位
OpenCode SDK 包(@opencode-ai/sdk)通过 package.json 的 exports 暴露两个入口:
| 入口路径 | 版本 | 状态 | 适合谁 |
|---|---|---|---|
@opencode-ai/sdk | V1 | 稳定 | 大多数用户、生产环境 |
@opencode-ai/sdk/v2 | V2 | 实验性 | 需要新能力、愿意跟随变化的进阶用户 |
V2 重新设计了 API 结构,和 V1 不完全兼容。在 V2 稳定前,两个入口并存。
V2 的两层客户端结构(重要)
V2 客户端最大的特点是两层访问路径,理解这个就理解了 V2 的核心:
client OpencodeClient(27 个模块)
├── session → Session2 旧路由 /session/*(基础方法)
├── permission → Permission /permission/*(跨 session 权限)
├── question → Question /question/*(跨 session 提问)
├── part → Part 消息部件 CRUD
├── sync → Sync workspace 同步
├── worktree → Worktree git worktree
├── experimental → Experimental 实验功能集合
├── ...
└── v2 → V2 新路由 /api/* 命名空间(17 个子模块)
├── session → Session3 /api/session/*(增强方法)
├── permission → Permission3 /api/session/{}/permission
├── question → Question3 /api/session/{}/question
├── health → Health /api/health
├── agent → Agent /api/agent
├── model → Model /api/model
├── fs → Fs /api/fs/*
└── ...关键区分:
| 访问路径 | 类 | 路由 | 用途 |
|---|---|---|---|
client.session | Session2 | /session/* | 基础方法(list/create/prompt) |
client.v2.session | Session3 | /api/session/* | 增强方法(interrupt/wait/compact/switchModel) |
client.permission | Permission | /permission/* | 跨 session 权限管理 |
client.v2.permission | Permission3 | /api/session/{}/permission | session 级权限 |
来源:
sdk.gen.ts:6990-7075(V2 类定义)、sdk.gen.ts:7077-7219(OpencodeClient 定义)
一句话记忆
增强的 session 方法在 client.v2.session,不是 client.session。client.session 是兼容旧路由的基础方法。
参数风格:平铺(不是嵌套)
V2 所有方法的参数都是平铺的,不再用 V1 的 { path: {...}, body: {...} } 嵌套结构。框架内部用 buildClientParams 自动把字段分发到 path/query/body。
// ❌ V1 风格(V2 中不适用)
client.permission.reply({
path: { requestID: "req-1" },
body: { response: "always" },
})
// ✅ V2 风格(平铺)
client.permission.reply({
requestID: "req-1",
reply: "always",
})来源:
sdk.gen.ts:3121-3144(buildClientParams自动分发)
开始使用 V2
安装
V2 和 V1 在同一个 npm 包里,不需要额外安装:
npm install @opencode-ai/sdk创建客户端
import { createOpencodeClient } from "@opencode-ai/sdk/v2"
const client = createOpencodeClient({
baseUrl: "http://localhost:4096",
directory: "/path/to/my-project", // 项目目录
experimental_workspaceID: "ws-123", // 可选:workspace 标识
})客户端配置参数:
| 参数 | 类型 | 说明 |
|---|---|---|
baseUrl | string | 服务器 URL,默认 http://localhost:4096 |
directory | string | 项目目录,通过 X-Opencode-Directory header 传递 |
experimental_workspaceID | string | workspace 标识,通过 X-Opencode-Workspace header 传递 |
fetch | function | 自定义 fetch 实现 |
headers | object | 自定义请求头 |
directory 和 workspaceID 怎么传递的?
directory 被编码后放入 X-Opencode-Directory header,experimental_workspaceID 放入 X-Opencode-Workspace header。客户端拦截器还会把它们改写进 query string(/api/* 路由用 location[directory] 参数),确保多项目隔离。
OpencodeClient 27 个模块总览
V2 的 OpencodeClient 暴露 27 个模块属性。
兼容 V1 的模块(19 个)
global project pty config tool instance path vcs command provider find file app mcp lsp formatter tui auth event
这些模块和 V1 基本一致,用法参考 5.10b API 参考。
V2 新增/增强的模块(8 个)
| 模块 | 访问路径 | 说明 |
|---|---|---|
| session | client.session / client.v2.session | 两层:Session2 基础 + Session3 增强 |
| permission | client.permission | 跨 session 权限管理 |
| question | client.question | 跨 session 提问管理 |
| part | client.part | 消息部件 CRUD |
| sync | client.sync | workspace 同步 |
| worktree | client.worktree | git worktree 管理 |
| experimental | client.experimental | 实验功能集合 |
| v2 | client.v2 | /api/* 新路由命名空间(17 个子模块) |
下面逐一详解。
V2 核心新能力详解
1. Permission 独立模块
V1 响应权限请求要用超长的 postSessionIdPermissionsPermissionId(),且只能响应特定 session 的请求。V2 把权限管理提升为独立模块,支持跨 session 查询和响应。
| 方法 | 路由 | 说明 |
|---|---|---|
permission.list() | GET /permission | 列出所有 session 的待处理权限请求 |
permission.reply() | POST /permission/{requestID}/reply | 响应权限请求 |
permission.respond() | POST /session/{sessionID}/permissions/{permissionID} | ⚠️ 已废弃,用 reply 代替 |
// 列出所有待处理的权限请求(跨 session)
const pending = await client.permission.list()
for (const request of pending.data ?? []) {
console.log(`[${request.sessionID}] ${request.permission}: ${request.patterns.join(", ")}`)
}
// 响应某个权限请求(注意:字段名是 reply,不是 response)
await client.permission.reply({
requestID: "req-123",
reply: "always", // "once" | "always" | "reject"
})字段名注意
reply() 方法的 body 字段名是 reply(不是 response)。response 是已废弃的 respond() 方法的字段名。
和 V1 的对比:
| 操作 | V1 | V2 |
|---|---|---|
| 列出权限请求 | ❌ 不支持 | ✅ permission.list() |
| 响应权限 | postSessionIdPermissionsPermissionId({path:{id,permissionID},body:{response}}) | permission.reply({requestID, reply}) |
| 跨 session 查询 | ❌ | ✅ |
2. Question 独立模块
Agent 可以通过 question 工具向你提问。V1 没有统一管理接口,V2 新增独立模块。
| 方法 | 路由 | 说明 |
|---|---|---|
question.list() | GET /question | 列出所有待回答的提问 |
question.reply() | POST /question/{requestID}/reply | 回答提问 |
question.reject() | POST /question/{requestID}/reject | 拒绝提问 |
// 查看所有待回答的提问
const questions = await client.question.list()
for (const q of questions.data ?? []) {
console.log(`[${q.sessionID}] ${q.questions[0]?.header ?? "(no question)"}`)
}
// 回答某个提问
await client.question.reply({
requestID: "q-456",
answers: [["选项 A"]],
})
// 拒绝提问
await client.question.reject({ requestID: "q-456" })权限和提问的区别
- Permission:Agent 要执行某个操作(如运行命令、编辑文件),请求你授权。
- Question:Agent 需要信息(如选择方案、确认偏好),向你提问。
3. Session 增强(client.v2.session)
这是 V2 最容易踩坑的地方。增强的 session 方法在 client.v2.session(Session3 类),不是 client.session(Session2 类)。
Session2(client.session):兼容旧路由 /session/*,有 list/create/prompt/messages 等基础方法。
Session3(client.v2.session):新路由 /api/session/*,新增一组控制方法。
来源:
sdk.gen.ts:5426-5875(Session3 类)
Session3 新增方法:
| 方法 | 路由 | 说明 |
|---|---|---|
interrupt() | POST /api/session/{sessionID}/interrupt | 中断当前执行 |
wait() | POST /api/session/{sessionID}/wait | 等待 session 空闲 |
compact() | POST /api/session/{sessionID}/compact | 触发上下文压缩 |
context() | GET /api/session/{sessionID}/context | 获取当前上下文 |
history() | GET /api/session/{sessionID}/history | 获取历史记录 |
switchModel() | POST /api/session/{sessionID}/model | 切换模型 |
switchAgent() | POST /api/session/{sessionID}/agent | 切换 agent |
events() | GET /api/session/{sessionID}/event | session 级事件流 |
const sessionID = "sess-abc"
// 注意:这些方法都在 client.v2.session(Session3)
await client.v2.session.interrupt({ sessionID })
await client.v2.session.wait({ sessionID })
await client.v2.session.compact({ sessionID })
// 切换模型
await client.v2.session.switchModel({
sessionID,
model: { providerID: "anthropic", id: "claude-sonnet-4-20250514" },
})
// 切换 agent
await client.v2.session.switchAgent({ sessionID, agent: "plan" })
// 获取上下文
const ctx = await client.v2.session.context({ sessionID })最常见的坑
把增强方法写在 client.session 上会报错。记住:
client.session.prompt()✅(基础方法在 Session2)client.v2.session.interrupt()✅(增强方法在 Session3)client.session.interrupt()❌(Session2 没有这个方法)
4. Part 模块(消息部件 CRUD)
V2 新增了对消息部件(Part)的细粒度操作。一条消息由多个 Part 组成,V2 支持删除和更新单个 Part。
| 方法 | 路由 | 说明 |
|---|---|---|
part.delete() | DELETE /session/{sessionID}/message/{messageID}/part/{partID} | 删除部件 |
part.update() | PATCH /session/{sessionID}/message/{messageID}/part/{partID} | 更新部件 |
// 更新某个文本部件
await client.part.update({
sessionID: "sess-abc",
messageID: "msg-1",
partID: "part-3",
part: { type: "text", text: "修改后的内容" },
})
// 删除某个部件
await client.part.delete({
sessionID: "sess-abc",
messageID: "msg-1",
partID: "part-3",
})5. Sync 模块(workspace 同步)
Sync 是 V2 的多 workspace 事件同步机制。
| 方法 | 路由 | 说明 |
|---|---|---|
sync.start() | POST /sync/start | 启动同步循环 |
sync.replay() | POST /sync/replay | 回放同步事件 |
sync.steal() | POST /sync/steal | 将 session 转移到当前 workspace |
sync.history.list() | POST /sync/history | 列出同步事件历史 |
来源:
sdk.gen.ts:4448-4576(Sync 类)、4413-4447(History 类)
注意
sync.history 是一个 getter 属性(返回 History 类实例),不是方法。要调用 sync.history.list()。
// 启动同步
await client.sync.start()
// 查看同步事件历史(history 是 getter,再调 list)
const history = await client.sync.history.list({
body: { "sess-abc": 10 }, // 返回 seq > 10 的事件
})Sync 是什么场景用的?
当你同时在多个 workspace 运行 OpenCode,session 可能需要在不同 workspace 间迁移。Sync 提供事件日志机制,确保迁移可追溯、可回放。这是为未来的分布式/集群场景设计的,单机用户一般用不到。
6. Worktree 模块(git worktree 管理)
V2 新增了 git worktree 的完整管理接口。
| 方法 | 路由 | 说明 |
|---|---|---|
worktree.list() | GET /experimental/worktree | 列出所有 worktree |
worktree.create() | POST /experimental/worktree | 创建 worktree |
worktree.remove() | DELETE /experimental/worktree | 删除 worktree 及分支 |
worktree.reset() | POST /experimental/worktree/reset | 重置到默认分支 |
// 列出所有 worktree
const worktrees = await client.worktree.list()
// 创建新 worktree
await client.worktree.create({
worktreeCreateInput: { branch: "feature-experiment" },
})
// 删除
await client.worktree.remove({
worktreeRemoveInput: { branch: "feature-experiment" },
})和 5.25 Git Worktree 课程的关系
本节是 SDK 编程接口。手动使用 worktree 请参考 5.25 Git Worktree 工作流。
7. Experimental 模块集合
client.experimental 是聚合模块,包含 workspace、resource、capabilities、console、control-plane 等前沿功能。
| 子功能 | 路由前缀 | 说明 |
|---|---|---|
| workspace | /experimental/workspace | 多工作空间管理 |
| resource | /experimental/resource | MCP 资源查询 |
| capabilities | /experimental/capabilities | 能力声明 |
| console | /experimental/console | 控制台(组织切换) |
| controlPlane | /experimental/control-plane | 控制平面(session 迁移) |
| session | /experimental/session | 实验性会话(background 子代理) |
实验性 session 的 background 方法可以把阻塞的子代理转为后台执行:
// 把阻塞的子代理转到后台继续运行
await client.experimental.session.background({ sessionID: "sess-abc" })完整示例:用 V2 构建自动化助手
import { createOpencodeClient } from "@opencode-ai/sdk/v2"
const client = createOpencodeClient({
baseUrl: "http://localhost:4096",
directory: "/path/to/my-project",
})
async function runTask(task: string) {
// 1. 创建 session(client.session 是 Session2,基础方法)
const session = await client.session.create({
title: task.slice(0, 50),
agent: "build",
})
const sessionID = session.data!.id
// 2. 异步发送任务(平铺参数)
await client.session.promptAsync({
sessionID,
parts: [{ type: "text", text: task }],
model: { providerID: "anthropic", modelID: "claude-sonnet-4-20250514" },
})
// 3. 轮询权限请求,自动允许只读操作
const poll = setInterval(async () => {
const pending = await client.permission.list()
for (const req of pending.data ?? []) {
// permission 是操作类型(如 "read"、"grep"),patterns 是匹配模式
if (req.permission === "read" || req.permission === "grep") {
await client.permission.reply({
requestID: req.id,
reply: "always", // 注意字段名是 reply
})
}
}
}, 1000)
// 4. 等待 session 完成(增强方法在 client.v2.session)
await client.v2.session.wait({ sessionID })
clearInterval(poll)
// 5. 获取结果(基础方法回到 client.session)
const messages = await client.session.messages({ sessionID })
const last = messages.data?.at(-1)
// 6. 读取 Token 消耗和费用(V1/V2 都支持)
if (last?.info.role === "assistant") {
console.log(`费用: $${last.info.cost}`)
console.log(`Token: 输入 ${last.info.tokens.input} / 输出 ${last.info.tokens.output}`)
}
return last
}
const result = await runTask("分析项目结构并生成 README")
console.log(result)核心要点:基础方法(create/promptAsync/messages)在
client.session,增强方法(wait/interrupt/compact)在client.v2.session。混用时注意切换路径。
V1 → V2 迁移指南
导入路径
// V1
import { createOpencodeClient } from "@opencode-ai/sdk"
// V2
import { createOpencodeClient } from "@opencode-ai/sdk/v2"参数结构
// V1:嵌套结构
await client.session.create({ body: { title: "xxx" } })
await client.session.prompt({ path: { id: "sess-1" }, body: { parts: [...] } })
// V2:平铺结构
await client.session.create({ title: "xxx" })
await client.session.prompt({ sessionID: "sess-1", parts: [...] })权限响应
// V1:超长方法名 + 嵌套参数
await client.postSessionIdPermissionsPermissionId({
path: { id: sessionID, permissionID: "perm-1" },
body: { response: "always" },
})
// V2:独立模块 + 平铺参数
await client.permission.reply({
requestID: "req-1",
reply: "always", // 字段名变了:response → reply
})会话控制
// V1:没有 interrupt/wait/compact
// V2:增强方法在 client.v2.session
await client.v2.session.interrupt({ sessionID })
await client.v2.session.wait({ sessionID })
await client.v2.session.compact({ sessionID })
await client.v2.session.switchModel({ sessionID, model: { ... } })
await client.v2.session.switchAgent({ sessionID, agent: "plan" })能力对照表
| 功能 | V1 | V2 |
|---|---|---|
| 权限响应 | postSessionIdPermissionsPermissionId | permission.reply |
| 权限列表 | ❌ | permission.list |
| 提问管理 | ❌ | question.list/reply/reject |
| 中断会话 | ❌ | v2.session.interrupt |
| 等待完成 | ❌(自己轮询) | v2.session.wait |
| 触发压缩 | ❌ | v2.session.compact |
| 切换模型 | ❌ | v2.session.switchModel |
| 切换 agent | ❌ | v2.session.switchAgent |
| 消息部件 CRUD | ❌ | part.update/delete |
| worktree | ❌ | worktree.list/create/remove/reset |
| workspace 同步 | ❌ | sync.start/replay/steal/history.list |
踩坑提醒
| 现象 | 原因 | 解决 |
|---|---|---|
createOpencodeClient is not exported | 导入路径错了 | V2 用 @opencode-ai/sdk/v2 |
client.session.interrupt is not a function | 用错了访问路径 | 增强方法在 client.v2.session |
| 参数报类型错误 | 用了 V1 的 {path, body} 嵌套 | V2 参数全部平铺 |
permission.reply 报字段错误 | 字段名写成了 response | V2 字段名是 reply |
sync.history is not a function | history 是 getter 不是方法 | 调用 sync.history.list() |
| 请求返回 HTML | 连的是 V1 服务器,不支持 /api/* | 确认服务器版本支持 V2 |
| V2 方法签名和文档不一致 | V2 是实验性,API 会变 | 以源码 sdk.gen.ts 为准 |
v2.session.wait 一直阻塞 | session 一直在运行 | 先 v2.session.interrupt 或设超时 |
本课小结
你学会了:
- V2 定位:实验性下一代 API,和 V1 并存于同一个 npm 包
- 两层结构:
client.*(基础 + 新概念)和client.v2.*(/api/* 新路由) - 参数风格:全部平铺,不是 V1 的嵌套
- 核心新能力:Permission/Question 独立模块、Session3 增强方法(在
client.v2.session)、Part CRUD、Sync、Worktree - 迁移要点:导入路径、参数结构、权限字段名、session 访问路径的差异
相关资源
- 5.10a SDK 基础 - V1 SDK 入门
- 5.10b API 参考 - V1 完整 API 文档
- V2 类型定义源码
- V2 SDK 生成源码
附录:源码参考
点击展开查看源码位置
更新时间:2026-07-07
| 功能 | 文件路径 | 行号 |
|---|---|---|
| V2 入口(exports 配置) | packages/sdk/js/package.json | 12-21 |
| V2 index(createOpencode) | packages/sdk/js/src/v2/index.ts | 1-23 |
| V2 客户端(createOpencodeClient) | packages/sdk/js/src/v2/client.ts | 50-92 |
| V2 服务器(ServerOptions) | packages/sdk/js/src/v2/server.ts | 5-30 |
| OpencodeClient 27 模块 | sdk.gen.ts | 7077-7219 |
| V2 命名空间(17 子模块) | sdk.gen.ts | 6990-7075 |
| Permission 模块 | sdk.gen.ts | 3085-3193 |
| Question 模块 | sdk.gen.ts | 2982-3084 |
| Session3 模块(增强方法) | sdk.gen.ts | 5426-5875 |
| Session2 模块(基础方法) | sdk.gen.ts | 3362-4329 |
| Part 模块(update/delete) | sdk.gen.ts | 4330-4406 |
| Sync 模块 + History 类 | sdk.gen.ts | 4413-4576 |
| Worktree 模块 | sdk.gen.ts | 1582-1724 |
| Workspace 模块(experimental) | sdk.gen.ts | 1006-1242 |
| Experimental 模块(聚合) | sdk.gen.ts | 1243-1317 |
关键类:
OpencodeClient:V2 客户端主类,27 个模块属性V2:client.v2命名空间,17 个 /api/* 子模块Session2(client.session):旧路由基础方法Session3(client.v2.session):新路由增强方法(interrupt/wait/compact/switchModel/switchAgent)Permission(client.permission):跨 session 权限管理Question(client.question):跨 session 提问管理
注意:packages/client/(@opencode-ai/client)是私有包,基于 Effect HttpApi 生成,非公开 SDK,不在本章范围。

