You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// GET /session/{id}/message → MessageWithParts[]{info: Message,parts: Part[]}// Part 联合(12 种)typePart=|TextPart|ReasoningPart|ToolPart|FilePart|AgentPart|StepStartPart|StepFinishPart|SnapshotPart|PatchPart|SubtaskPart|RetryPart|CompactionPart
Activity
lehhair commentedon Sep 28, 2026
是该支持了,工作太忙,我还在用oc v1
AAEE86 commentedon Sep 29, 2026
工作量有点大,还是大佬来做吧
OpenCode V2 迁移计划
目录
1. 背景与结论
1.1 为什么要做
本机 opencode 已升级到 v2.0.16,而 OpenCodeUI 仍对接 V1 API。V2 是一次有意为之的破坏性升级,官方文档明确说明:
也就是说:配置文件、agent、命令、skill 都还能用,唯独「界面程序怎么跟 opencode 说话」这套协议被换掉了 —— 而这恰好是本项目的核心依赖。
1.2 结论
属于中等偏大的重构,主要难点有二:
/api前缀,十余个端点改名或删除)src/api/约 20 个文件{info, parts}两层 → 扁平联合 + 游标分页)有利条件:
auth.json/cli.json/opencode.json文件本体 → 这部分零改动src/types/api/下 16 个文件是 SDK 类型的转发,SDK 换包后自动跟随401 + www-authenticate: Basic realm="Secure Area")→ 鉴权层基本不动2. 现状:项目如何接入 OpenCode
2.1 架构
2.2 关键事实
@opencode-ai/sdk,package.json声明^1.16.0,实际安装 1.4.1(不一致)src/types/api/*共 17 个文件,16 个是 SDK 类型 re-export;项目内无任何 codegen 配置useSyncExternalStore(无 zustand/redux)opencode serve、健康检查、SSE/WS 透明代理、WSL 管理ServerHealth.version仅用于 UI 展示,无能力分支)2.3⚠️ 已存在的隐患(与本次迁移无关,但应先修)
package.json声明^1.16.0,package-lock.json锁 1.16.0,但node_modules实装 1.4.1src/api/pty.ts:50调用sdk.pty.shells(),该方法在 1.4.1 中不存在docker/Dockerfile.backend:102和docker/backend-entrypoint.sh:34拉取releases/latest,很可能已经装成 V2,处于风险中3. V2 五个层面的变更
3.1 客户端包更换
@opencode-ai/sdk@opencode/client^1.16.0(实装 1.4.1)2.0.19createOpencodeClient()OpenCode.make({ baseUrl, headers, fetch }){ data, error, request, response }需unwrap()client.event.subscribe()→ async iterableplugin-http可继续注入)3.2 接口路径全部加
/api前缀详见 §4 完整端点对照表。
3.3 目录/位置参数传递方式变化
?directory=/path?directory=,部分改为?location[directory]=(deepObject)x-opencode-directorylocation对象directory: stringlocation: { directory: string }Session.directorySession.location(Session.Info含location/subpath)3.4 配置字段格式大改(影响可视化配置编辑器)
配置文件本身 V2 能读 V1 格式并自动归一化(不重写源文件),所以用户配置不用改。
但项目的配置编辑器(
src/features/settings/components/configEditor*)是按 V1 字段渲染的,需要适配:permission: { bash: {...}, edit: "allow" }permissions: [{ action, resource, effect }]有序数组bash/task/write/patchshell/subagent/editagent: { ... }agents: { ... }prompt/disable/variantsystem/disabled/model#variant(variant 拼进模型串)command/plugin/provider/reference/snapshot/attachmentcommands/plugins/providers/references/snapshots/mediamcp: { name: {...} }mcp: { servers: { name: {...} } },enabled→ 反转为disabledskills: { paths, urls }skills: ["...", "..."]一个有序数组provider.npm/api/optionspackage(加aisdk:前缀)/settings.baseURL/ 拆成settings/headers/bodymodel.id/tool_call/cache_readmodelID/capabilities.*/cache.readautoshare: trueshare: "auto"3.5 启动与环境变量(待验证)
Rust 侧当前使用(
src-tauri/src/app/commands/opencode.rs、wsl_commands.rs):4. 完整端点对照表
4.1 服务与事件
GET /global/health(Rust 先试/api/health)GET /api/info{version, pid, urls[], paths:{tmp}},无healthy字段GET /global/eventGET /api/eventPOST /global/dispose、POST /instance/disposeDELETE /api/debug/location替代(驱逐 location)GET /pathGET /api/locationPOST /api/location/reload4.2 会话
GET /sessionGET /api/sessioncursor游标分页、search/project/subpathPOST /sessionPOST /api/sessionGET /session/{id}GET /api/session/{id}PATCH /session/{id}PATCH /api/session/{id}DELETE /session/{id}DELETE /api/session/{id}GET /session/statusGET /api/session/activeSessionActiveGET /session/{id}/messageGET /api/session/{id}/messagePOST /session/{id}/messagePOST /api/session/{id}/prompt{text, files, agents, skills, metadata, delivery, resume}POST /session/{id}/prompt_async/background(后台化阻塞中的工具)POST /session/{id}/abortPOST /api/session/{id}/interruptPOST /session/{id}/forkPOST /api/session/{id}/forkForkBoundaryPOST /session/{id}/revertPOST .../revert/stage→POST .../revert/commit→DELETE .../revert(清除暂存)POST /session/{id}/unrevertPOST/DELETE /session/{id}/shareshare: "auto"策略,但无 APIPOST /session/{id}/summarizePOST /api/session/{id}/compactGET /session/{id}/childrenGET /api/session?parentID=<id>GET /session/{id}/todotodo.updatedGET /session/{id}/diffGET /api/session/{id}/diffPOST /api/session/{id}/agentPOST /api/session/{id}/modelPOST /api/session/{id}/movePOST /api/session/{id}/viewGET /api/session/{id}/contextGET/PATCH/DELETE /api/session/{id}/inbox[/{inboxID}]4.3 权限与提问
GET /permissionGET /api/permission/requestGET /api/permission/saved(已保存规则)POST /session/{id}/permissions/{pid}POST /api/session/{id}/permission/{rid}/reply{ decision: "once"|"always"|"reject" }DELETE /api/permission/saved/{id}GET /question、POST /question/{id}/reply、POST /question/{id}/rejectGET /api/session/{id}/form、POST .../form、POST .../form/{formID}/reply、DELETE .../form/{formID}GET /api/form(location 级)4.4 模型、配置、项目
GET /configGET /api/configlocation[directory]deepObjectPATCH /configPATCH /global/configPATCH /api/experimental/configGET /global/configGET /api/configGET /config/providersGET /api/model+GET /api/model/defaultGET /api/provider+GET /api/provider/{id}GET /pty/shellsGET /api/config/shellGET /agentGET /api/agent+GET /api/agent/{agentID}GET /skillGET /api/skillGET /commandGET /api/commandPOST /session/{id}/commandPOST /api/session/{id}/commandGET /projectGET /api/projectGET /project/currentGET /api/location)POST /project/git/initPATCH /project/{id}PATCH /api/project/{id}GET /lspGET /formatter4.5 文件与搜索
GET /fileGET /api/fs/listGET /file/contentGET /api/fs/read/*GET /file/statusGET /api/vcs/statusPOST /api/experimental/fs/writeGET /findGET /api/fs/findGET /find/file/api/fs/find)GET /find/symbol4.6 终端 PTY
GET /ptyGET /api/ptyPOST /ptyPOST /api/ptyGET /pty/{id}GET /api/pty/{id}PATCH /pty/{id}PUT /api/pty/{id}DELETE /pty/{id}DELETE /api/pty/{id}WS /pty/{id}/connect(带 auth)POST /api/pty/{id}/connect-token换令牌 → 再连GET /api/pty/{id}/connectGET /pty/shellsGET /api/config/shellPOST /api/experimental/persistent-pty/*4.7 MCP、VCS、Worktree
GET /mcpGET /api/mcpPOST /mcp、DELETE /mcp/{name}PUT/DELETE /api/experimental/mcp/{server}POST /mcp/{name}/connect、/disconnectPOST /api/experimental/mcp/{server}/connect、/disconnectPOST /mcp/{name}/auth*(4 个端点)/api/integration/*全新体系GET /api/integration、connect/key、connect/oauth[/{attemptID}][/complete]、connect/commandGET /experimental/resourceGET /api/mcp/resourceGET /vcsGET /api/vcsGET /vcs/diffGET /api/vcs/diffGET /api/vcs/status/file/statusGET /api/vcs/branchGET /api/vcs/baseGET /experimental/worktreeGET /api/worktreePOST、DELETE /experimental/worktreePOST、DELETE /api/worktreePOST /api/worktree/refreshPOST /experimental/worktree/reset4.8 工具、插件、调试
GET /experimental/tool、/experimental/tool/idsGET /api/plugin(含Features)GET /api/plugin、POST /api/plugin/check、POST /api/plugin/updateGET /api/debug/location、DELETE /api/debug/location/{loc}GET /api/experimental/migration/v1GET /api/websearch/provider、POST /api/websearchGET/POST/DELETE /api/shell、GET /api/shell/{id}/outputPOST /api/rpc/{rpcID}/{method}5. 消息模型变更(最大改动)
5.1 结构对比
V1 —— 两层结构
V2 —— 扁平联合 + 游标分页
5.2 关键字段变化
parts[].type === 'text'User.text(直接字段)parts[].type === 'file'User.filesparts[].type === 'agent'User.agentsparts[].type === 'text'Assistant.content[].type === 'text'+textparts[].type === 'reasoning'Assistant.content[].type === 'reasoning'parts[].type === 'tool'(内嵌state)Assistant.content[].type === 'tool'(内嵌state)step-start/step-finishIdle消息)subtaskpartparentID会话树)snapshot/patchpartretrypartAssistant.retry字段compactionpartCompaction(Running/Completed/Failed)Assistant.cost、Assistant.tokens、Assistant.finish、Assistant.rawFinishMessage.errorAssistant.error+Session.StructuredError5.3 新增的消息类型(需要新写渲染分支)
systemskillshellsyntheticPOST .../synthetic可写入)idleagentSelectedmodelSelectedlocationSwitched5.4 影响的代码
src/types/api/message.tssrc/api/message.tsbuildPromptParams()重写(text/files/agents/skills)src/utils/messageConversion.tstoUIMessage/toUIPart整体重写src/types/message.tssrc/store/messageStore.tssrc/features/message/**src/api/types.tsSendMessageParams等兼容别名5.5 分页
V1 一次性返回全量;V2 返回
{data, cursor}。需要新增:
cursor.previous向前加载fc6ce8e6 fix: preserve scroll position after loading history)协同messageStore的MAX_CACHED_SESSIONS = 10LRU 策略需重新评估6. 事件流变更
6.1 协议
GET /global/eventGET /api/event{ directory, payload: { type, properties } }data字段为V2EventEncoded(JSON 编码字符串),另有id/event字段6.2⚠️ 官方明确的限制
对本项目的冲击(
src/api/events.ts有 1060 行精巧实现):coalesceEvents) → V2 无message.part.delta事件,需按新事件类型重新设计RECONNECT_DELAYS) → 连接管理逻辑保留,但恢复动作要改成"重订阅 + 重拉数据"@opencode/client自带订阅:client.event.subscribe()返回 async iterable,内部共享一条懒连接,最后一个订阅者退出才关闭 → 可以大幅简化手写连接管理6.3 事件类型
V1 的
EventTypes常量表(src/types/api/event.ts,40 余种)整体需要按 V2 重做,该表被约束为:V2 实际处理的事件集合必须抓真实流量确认(见 §10.3)。
确定已消失的事件:
message.part.updated/message.part.delta/message.part.removed、todo.updated、question.*7. 文件改动清单
🔴 P0 —— 主流程打通
package.json@opencode-ai/sdk→@opencode/client;先修依赖不一致src/api/sdk.tssrc/api/*.ts(约 20 个)directory→location)src/api/events.tssrc/types/api/message.tssrc/utils/messageConversion.tssrc/store/messageStore.tssrc/utils/directoryUtils.tsformatPathForApi适配新参数形态🟠 P1 —— 功能对齐
src/features/message/**src/hooks/useGlobalEvents.tssrc/api/pty.ts+ptyBridge.tsPATCH→PUTsrc-tauri/src/app/commands/opencode.rs/api/info;启动参数验证src-tauri/src/app/commands/wsl_commands.rssrc/store/serverStore.tshealthy字段(checkHealth+ 3 处 UI 展示)src/api/session.ts🟡 P2 —— 周边能力
src/api/config.ts+features/settings/configEditor*src/api/permission.ts+ 权限 UIdecision字段;question → Form 表单渲染器(新 UI)src/api/mcp.ts/api/integration/*体系src/api/file.ts+ 搜索 UIfile/status→vcs/statussrc/api/vcs.ts、worktree.tssrc/api/client.ts/config/providers→/api/model+/api/provider⚪ P3 —— 清理
openapi_doc.json、openapi_formatted.jsonsrc-tauri/src/app/commands/git.rsmod.rs未声明、未注册、未编译),删除core.filemode权限位噪音.gitattributes或文档说明8. 分阶段实施计划
阶段 0:环境与依赖修复 🟢 小
package.json/node_modules版本不一致(1.16.0 vs 1.4.1)sdk.pty.shells()缺失导致的当前故障状态opencode v2.0.16+opencode servedocs/fixtures/作为回归依据产出:能跑起来,拿到真实数据形状。
阶段 1:换 SDK + 迁移端点 🟡 中
@opencode-ai/sdk→@opencode/clientsrc/api/sdk.ts(OpenCode.make,保留 Tauri fetch + Basic Auth)directory→location参数src/types/api/*适配新 SDK 类型导出GET /api/info(含 Rust 侧 +serverStore+ 3 处 UI)产出:会话列表、模型列表、配置读取可用。
阶段 2:消息模型 + 事件流 🔴 大(最难)
src/types/api/message.ts(Session.Message.Info 联合)src/utils/messageConversion.tssrc/api/events.ts订阅层(改用client.event.subscribe()或手写改造)EventTypes常量表与handleEventForSubscribermessageStore数据结构与合并逻辑重写POST .../prompt(含附件/agent/skill 参数)产出:聊天主流程可用(发消息、流式回复、工具卡片、历史加载)。
阶段 3:功能补齐与裁撤 🟠 中大
abort→interruptstage/commit/clear三段式/api/permission/request+{decision}回复 + saved 规则管理PATCH→PUT、/api/config/shell/api/integration/*file/status→vcs/statuspermissions数组、agents、mcp.servers、providers…)产出:功能与 V2 对齐。
阶段 4:收尾 🟡 中
git.rs、openapi_doc.json)latest)产出:可发布。
工作量参考
9. 决策记录
9.1 只支持 V2,直接切换 ✅
决定:迁移后只支持 opencode V2,不做 V1/V2 双栈兼容。
理由:
代价:用户必须把 opencode 升级到 v2,否则无法使用。→ 在 README 明确标注版本要求。
9.2 不做的事
/global/health、/global/event等 V1 端点的双端点兜底9.3 要删除的历史兼容 shim
src/api/events.ts:578properties.info ?? properties.messagesrc/api/events.tsnormalizeSessionError(){name,data}与{error:{name,data}}src/api/pty.ts:27 normalizePty()running: boolean→statussrc/components/SessionChangesPanel.tsx:982/1086、src/hooks/useFileExplorer.ts:486before/aftersrc-tauri/src/app/commands/opencode.rs:52/66/api/health再试/global/healthGET /api/info9.4 要移除的功能(V2 已删除)
LSP 状态 · 格式化器状态 · 符号搜索 · 会话分享 · 手动摘要 · 子会话列表 · 待办事项 ·
prompt_async·unrevert· worktree reset ·file/status(改用vcs/status)·project/git/init·find/symbol10. 开工前必须验证的事项
10.1 依赖
node_modules与package.json不一致(1.4.1 / 1.16.0)sdk.pty.shells()缺失造成的当前故障@opencode/client在浏览器与 Tauriplugin-http下的流式表现10.2 启动参数与环境变量
opencode serve --hostname --port是否仍有效--print-logs --log-level是否仍有效OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER是否仍被识别OPENCODE_CLIENT=desktop是否仍被识别OPENCODE_SERVER_USERNAME/OPENCODE_SERVER_PASSWORD是否仍生效http://...(parse_listening_url()依赖)10.3 事件 payload 真实形状
V2EventEncoded是「JSON 字符串」—— 确认是否双层编码(JSON.parse一次还是两次)event:字段取值集合EventTypes)message.part.delta,V2 需确认)10.4 接口细节
directoryvslocation[directory]逐端点核对GET /global/config是否有替代端点(配置编辑器依赖)PATCH /api/config是否存在GET /project/current的替代GET /find/file(文件名搜索)是否并入/api/fs/find@opencode/client示例用 Bearer)10.5 部署
releases/latest,可能已是 V2)附录 A:主要参考
附录 B:本机实测环境
v2.0.16(/home/coder/.opencode/bin/opencode)0.6.46@opencode/client@2.0.19@opencode-ai/sdk声明^1.16.0/ 实装1.4.1401+www-authenticate: Basic realm="Secure Area"(Basic 仍可用)lehhair commentedon Sep 29, 2026
我也看了下,简直是要完全重写
AAEE86 commentedon Sep 29, 2026
是的 改动太多了😂😂😂 不然我就提PR了
AAEE86 commentedon Sep 29, 2026
我先用官方Web过渡了 等大佬更新😁
AAEE86 commentedon Sep 30, 2026
#173 提了个PR 测试不充分 估计还有bug
lehhair commentedon Oct 6, 2026
已更新,可能还有部分我没检查到的问题,确实是个大工程,期待你的反馈
lehhair commentedon Oct 6, 2026
安装0.7.3即可,有问题再开issue