首页
/ 用 @opencode-ai/sdk 从脚本驱动 opencode:oh-my-openagent 仓库中的 SDK 参考与源码级实践

用 @opencode-ai/sdk 从脚本驱动 opencode:oh-my-openagent 仓库中的 SDK 参考与源码级实践

2026-09-04 19:56:44作者:董斯意

本文基于 oh-my-openagent 仓库 opencode-qa 技能中的 SDK 参考文档(.agents/skills/opencode-qa/references/sdk.md),完整讲清 @opencode-ai/sdk 的包入口、两种连接方式、客户端命名空间、常用方法与核心类型,以及如何从 OpenAPI 规范生成该 SDK;并结合仓库内 packages/omo-opencode 的真实源码用法,给出可运行的最小 QA 脚本和版本核验建议,帮助你在 Bun/TypeScript 脚本中安全地以类型化方式驱动 opencode 服务器。

定位:reference only,优先 CLI/curl 脚本

opencode-qa 技能的核心 QA 面是"经过实测的 CLI/curl 脚本",SDK 在其中被明确标注为 reference only(仅供参考)

A TypeScript/Bun way to drive opencode for QA. Prefer the tested CLI/curl scripts for portability; reach for the SDK when you want typed access from a Bun script.

也就是说,技能的主路由器(见 SKILL.md)把 QA 场景映射到带 --self-test 的 shell 脚本,而当你需要在 Bun 脚本里获得类型化访问(typed access)时才应使用 SDK。原文档特别强调了一条贯穿全文的重要规则:

IMPORTANT: method signatures differ between SDK versions and between the published docs and the generated client. ALWAYS check the installed version's types (node_modules/@opencode-ai/sdk) before relying on a signature, and verify against GET /doc (the OpenAPI spec the SDK is generated from).

方法签名会在不同 SDK 版本之间、以及"已发布的文档"与"生成的客户端"之间产生差异。因此在依赖任何签名之前,必须检查已安装版本的类型定义,并对照 GET /doc(即 SDK 所依据生成的 OpenAPI 规范)核验。仓库根 package.jsonpackages/omo-opencode/package.json 均将依赖锁定为 "@opencode-ai/sdk": "1.18.22",这正是"以已安装版本类型为准"的具体落点。

包入口与导出

@opencode-ai/sdk 提供以下子路径导出(subpath exports):

  • .(src/index.ts)
  • ./client
  • ./server
  • ./v2(src/v2/index.ts)
  • ./v2/client
  • ./v2/server
  • ./v2/gen/client

根入口与 v2 入口都导出三个工厂函数:createOpencode()createOpencodeClient(...)createOpencodeServer(...)

从源码结构看,这三个工厂各自承担不同职责:

  • createOpencodeServer():拉起 opencode serve ... 子进程,并等待启动行(startup line)出现后才返回;
  • createOpencodeClient({ baseUrl }):包装生成的客户端(generated client),重写 directory/workspace 请求头,并安装错误拦截(error interception);
  • createOpencode():opencode 自身的运行时客户端构造入口。

仓库中的实际调用印证了后两者的形态。packages/omo-opencode/src/cli/run/server-connection.ts 在运行时分别调用:

deps.createOpencode({ signal, port, hostname: "127.0.0.1" })          // L78
deps.createOpencodeClient({ baseUrl: attach })                        // L94
deps.createOpencodeClient({ baseUrl: `http://127.0.0.1:${port}` })    // L123/L130/L152

这与文档描述的 createOpencode() / createOpencodeClient({ baseUrl }) 签名一致,也说明"attach 到已有服务器"与"自启服务器"两条路径在同一连接模块内并存。

两种连接方式

原文档给出了两种标准连接模式:

import { createOpencodeClient, createOpencodeServer } from "@opencode-ai/sdk/v2"

// A) embedded server (spawns opencode serve)
const server = await createOpencodeServer()
const client = createOpencodeClient({ baseUrl: server.url })
// ... use client ...
server.close()

// B) connect to an already-running server
const client2 = createOpencodeClient({ baseUrl: "http://127.0.0.1:4096" })
  • 方式 A(内嵌服务器)createOpencodeServer() 自行 spawn opencode serve 并等待其就绪,用完 server.close() 收尾;
  • 方式 B(连接已有服务器):直接传 baseUrl 指向已运行的实例,端口 4096 是默认约定端口。

方式 B 与 server-api.md 中描述的服务器面完全对应:opencode serve --port 4096 --hostname 127.0.0.1,认证凭 OPENCODE_SERVER_PASSWORD 环境变量启用,实例级路由通过 ?directory= 查询参数或 x-opencode-directory 头传递。文档中提到 createOpencodeClient 会"重写 directory/workspace headers",正服务于这套每请求工作区路由协议——仓库源码 packages/omo-opencode/src/shared/live-server-route.ts 中构造客户端时同时传入 baseUrldirectory,即是该能力的直接体现。

客户端命名空间

顶层 OpencodeClient 上的命名空间如下(原文档逐字列出):

auth, app, global, event, config, experimental, tool, worktree, find, file, instance, path, vcs, command, lsp, formatter, mcp, project, pty, question, permission, provider, session, part, sync, v2, tui.

这些命名空间与 server-api.md/doc 返回的路由目录高度对应:session/part 对应 Session 与 Prompting 路由,event 对应 /event SSE 流,pty/tui 对应 PTY 与 TUI control 路由,v2 则承载新版 /api/... 读写面。

常用方法(形状随版本变化)

原文档列出的常用方法清单(完整继承,形状以版本为准):

  • client.global.health()client.global.event()
  • client.app.log(...)client.app.agents(...)client.app.skills(...)
  • client.config.get()client.config.providers()
  • client.event.subscribe() — 订阅 /event 上的 SSE 流;用 for await (const event of events.stream) { event.type, event.properties } 迭代
  • client.session(旧表面,legacy surface):list, create, status, get, update, delete, children, todo, diff, messages, message, deleteMessage, prompt, promptAsync, command, shell, fork, abort, init, share, unshare, summarize, revert, unrevert
  • client.v2.session(新版读写/流表面):list, prompt, compact, wait, context, messages
  • client.part.delete(...)client.part.update(...)

仓库源码对上述方法名提供了大量实锤用法:

这说明 legacy 表面的 session 命名空间是当前代码库的主力使用面;v2 命名空间同时存在(仓库中有 import { OpencodeClient as V2OpencodeClient } from "@opencode-ai/sdk/v2"import type { Client as V2GeneratedClient } from "@opencode-ai/sdk/v2/gen/client" 的导入),印证了"legacy 与 v2 两套表面并存"的描述。

类型导入方面,仓库代码频繁从包根导入 AgentConfigMessagePartSessionAssistantMessageEventProjectTodoSessionPromptAsyncData 等类型,例如 import type { AgentConfig } from "@opencode-ai/sdk",说明类型导出的实际使用面比文档示例更广,可放心作为类型契约引用(仍以安装版类型为准)。

最小 QA 片段

原文档给出了一段最小 QA 脚本,并注明"参数形状可能因版本而异,请视为起点而非契约":

import { createOpencodeClient, createOpencodeServer } from "@opencode-ai/sdk/v2"

const server = await createOpencodeServer()
const client = createOpencodeClient({ baseUrl: server.url })

try {
  const session = await client.session.create({ title: "QA session" })
  await client.session.promptAsync({
    sessionID: session.id,
    parts: [{ type: "text", text: "Say hello in one line." }],
  })

  const sessions = await client.session.list({ limit: 10 })
  console.log(sessions[0]?.title)

  const messages = await client.v2.session.messages({
    sessionID: session.id,
    limit: 20,
  })
  console.log(messages.items.length)
} finally {
  server.close()
}

这段脚本恰好串起了三种典型操作:session.create 建会话、session.promptAsync 发"发后即忘"提示(对应 HTTP 面 POST /session/:id/prompt_async 返回 204 的语义,见 server-api.md)、v2.session.messages 读取消息并取 items.lengthfinallyserver.close() 保证内嵌服务器被回收——这与 opencode-qa 技能"任何会 spawn opencode 的 QA 都必须做隔离与清理"的黄金规则一致(见 SKILL.md 的 Golden rules 一节)。

核心类型

原文档列出三组关键类型(完整继承):

  • Legacy Sessionid, slug, projectID, directory, title, version, time.created/updated,可选 workspaceID, path, parentID, summary, cost, tokens, share, agent, model, metadata, permission, revert
  • Message = UserMessage | AssistantMessage(role 为 "user" | "assistant";assistant 额外携带 time.completed?modelIDproviderIDagenttokensfinish?error?);
  • Part 联合类型TextPart, ReasoningPart, FilePart, ToolPart, StepStartPart, StepFinishPart, SnapshotPart, PatchPart, AgentPart, RetryPart, CompactionPart, SubtaskPart

Part 联合的 12 个成员与 opencode 的事件语义一一对应(工具调用、推理、快照/补丁、压缩、重试等),这也解释了为什么 QA 脚本(如 SKILL.md Case A 中 opencode run --format json)能按 text / tool_use / step_start / step_finish / reasoning / error 等类型对逐行事件做断言——SDK 类型面与 CLI JSON 事件面是同一领域模型的两种表达。

生成机制:从 OpenAPI 到 TypeScript 客户端

@opencode-ai/sdk 是生成物。原文档说明其生成管线:

packages/sdk/js/script/build.ts runs bun dev generate > openapi.json from the opencode repo, feeds it to @hey-api/openapi-ts.createClient, writes output to packages/sdk/js/src/v2/gen, patches an SSE generic, prettifies and typechecks. Regenerate with ./packages/sdk/js/script/build.ts.

即:在 opencode 源仓库执行 bun dev generate 导出 openapi.json,喂给 @hey-api/openapi-tscreateClient,输出写入 packages/sdk/js/src/v2/gen,再修补一个 SSE 泛型、格式化并做类型检查。这条管线解释了文档开头"签名以安装版类型与 GET /doc 为准"的必要性:v2/gen 下的客户端是逐版本再生的,路径与参数形状跟随 OpenAPI 规范演进。注意上述 packages/sdk/js/... 路径位于 opencode 源仓库,不在本仓库内;本仓库只消费其发布产物。

仓库内的真实使用模式:健康探测与会话亲和

除了文档覆盖的用法,仓库源码还展示了一个值得借鉴的 SDK 客户端工程化模式——packages/omo-opencode/src/shared/live-server-route.ts 的"live 路由"机制:

  1. 构造客户端时注入路由与认证(L248-L252):
const client = createOpencodeClientSdk({
  baseUrl: registration.serverUrl.toString(),
  directory: registration.directory,
})
injectServerAuthIntoClient(client)

directory 参数对应文档所述"重写 directory/workspace headers"的行为;injectServerAuthIntoClient 则把 Basic Auth 注入 SDK 客户端,呼应 server-api 文档"认证调用使用 -u opencode:$PASS"的语义。

  1. 健康探测(L103 起):向 {serverUrl}/global/health 发起带 1.5s 超时的 fetch,等价于文档中 client.global.health() 的底层调用;401/403 时判定"认证无法满足,禁用 live 路由"。

  2. 会话亲和探测(L155 起):GET /session/{sessionID},只有明确的 404 才降级到进程内客户端——因为健康的 /global/health 只能证明"某个监听器在应答",不能证明它拥有目标会话。

从源码结构看,这套"先探测再分发"的逻辑正是 SDK createOpencodeClient 在真实系统里被包裹、缓存与降级使用的范例:SDK 客户端不是拿来即用就结束,而是要与探活、TTL 缓存(PROBE_TTL_MS / AFFINITY_TTL_MS 各 60 秒)和失败回退一起设计。

版本锁定与核验清单

综合原文档与仓库现状,落地 SDK 调用前建议按以下清单核验:

  1. 确认安装版本:本仓库根 package.jsonpackages/omo-opencode/package.json 均锁定 @opencode-ai/sdk@1.18.22;你的项目应以自己 node_modules/@opencode-ai/sdk.d.ts 为准,而非任何文档。
  2. 对照 GET /docGET /doc 返回完整 OpenAPI 规范(smoke 测试断言其包含至少 100 条路径,见 SKILL.md 的 Scripts index),是请求/响应 schema 的权威来源。
  3. 区分 legacy 与 v2 表面client.session.*(旧)与 client.v2.session.*(新)并存,读消息、等待完成等在新表面(list, prompt, compact, wait, context, messages),写操作与生命周期管理仍在旧表面;跨版本迁移时优先检查二者是否同时可用。
  4. 认证与隔离:服务器仅在设置 OPENCODE_SERVER_PASSWORD 时强制认证,否则无保护运行;用 SDK 对已有服务器做 QA 时,任何会 spawn opencode 的场景都应置于隔离环境(Docker 或隔离 XDG 沙箱),避免污染真实会话库。
  5. 事件流迭代client.event.subscribe() 返回可读 SSE 流,用 for await (const event of events.stream) 消费 event.type / event.properties;若要证明某个插件钩子/动作事件确实触发,事件流观察(Case B)比 TUI 断言更可靠,事件类型目录见 events-hooks.md

小结

@opencode-ai/sdk 为 opencode 提供了类型化的程序化入口:createOpencodeServer() 内嵌起服、createOpencodeClient({ baseUrl }) 连接现有实例,客户端按 auth/app/global/event/session/part/v2 等命名空间组织,legacy 与 v2 两套 session 表面并存;它由 OpenAPI 规范经 @hey-api/openapi-ts 生成,因此"签名随版本漂移、以安装版类型与 GET /doc 为准"是必须遵守的第一原则。oh-my-openagent 仓库自身的用法——从 server-connection.ts 的连接构造,到 live-server-route.ts 的健康探测与会话亲和,再到各 feature 模块中 session.create / session.messages / event.subscribe 的高频调用——为这份参考文档提供了仓库内的实现级印证。对于版本稳定的 QA,仍建议以技能中经过自测的 curl/CLI 脚本为首选,把 SDK 作为需要类型安全时的补充手段,并对每个 SDK 调用先做 GET /doc 交叉核验。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
903
1.82 K
docsdocs
暂无描述
Markdown
888
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.51 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341