
【声明】本博客所有内容均为个人业余时间创作所述技术案例均来自公开开源项目如GithubApache基金会不涉及任何企业机密或未公开技术如有侵权请联系删除标题199、【Agent】【OpenCode】TuiThreadCommand handlerworker 到底是什么背景上篇 blog【Agent】【OpenCode】TuiThreadCommand handlertransport 双形态的触发与误区拆了 transport 双形态外部模式由--port/--hostname/--mdns或 config 的server非默认触发worker 真起 HTTP server、fetch/events为undefined内部模式全默认走进程内 RPCcreateWorkerFetch把请求序列化转发、createEventSource订阅 RPC 事件流、伪地址http://opencode.internal并澄清internal/external 不等于内部/外部大模型模型由 worker 按配置调用、与传输通道正交。198 里RPC 转发给 worker反复出现但worker 到底是个什么东西一直没讲透——本篇专门拆worker.ts它的 RPC 方法表、它握着的 Server 核心、它的事件中转OpenCode192 篇只讲了怎么把 worker 拉起来target()三级回退 new Worker本篇回答worker 是什么。一句话先给结论worker 就是 opencode 的后端服务——会话、模型调用、权限、文件、事件全在它里面TUI 只是前端界面壳两者同进程分线程、靠 RPC 通信。架构总览TUI 是壳worker 是核角色所在线程是什么持有什么TUI主线程前端界面渲染、输入、快捷键无核心状态Worker独立线程opencode 后端服务Serversession/provider/权限/MCP、Instance按目录实例、事件总线主线程通过Rpc.clienttypeof rpc(worker)thread.ts:140连上 workertypeof rpc让 TUI 能类型安全地调用 worker 暴露的每一个方法。下面用 worker.ts 源码逐层佐证。佐证 1RPC 方法表——worker 能提供什么服务一目了然worker.ts:101-148 的export const rpc就是 worker 的全部服务清单exportconstrpc{asyncfetch(input){...},// 内部模式执行 TUI 转来的 HTTP 请求asyncserver(input){...},// 外部模式真起 HTTP serverasynccheckUpgrade(input){...},// 版本升级检查asyncreload(){...},// 重置配置 重建实例SIGUSR2 热重载asyncsetWorkspace(input){...},// 切换 workspace 事件流asyncshutdown(){...},// 停事件流 释放实例 停 server}六个方法恰好对应前面文章里所有 RPC 调用的落点RPC 方法主线程调用处用途fetchthread.ts:24-40createWorkerFetch内部模式请求代理serverthread.ts:187 external 分支外部模式起真 servershutdownthread.ts:162stop优雅关闭5s 超时reloadthread.ts:145SIGUSR2热重载checkUpgradethread.ts:198延迟升级检测setWorkspacethread.ts:46createEventSource切换工作区事件流️佐证 2worker 握着 opencode 的核心服务 Serverworker.ts:102-120 的fetch里关键一行是asyncfetch(input){...constresponseawaitServer.Default().fetch(request)// 进程内交给核心 HTTP 服务return{status,headers,body}}Serversrc/server/server.ts是 opencode 的核心 HTTP 服务挂满了业务路由server.ts:244-254/session会话 /provider模型提供方 /question提问 /permission权限 /mcp /config /pty /experimental ...上表是 Server 提供的能力清单而 worker 只是把 TUI 转来的请求转交进这套路由TUI 内部模式的每个请求最终都落到这套路由上——会话、模型调用、权限判断都在这由 worker 持有并执行。所以TUI 用 fetch 请求后端其实是TUI 把请求 RPC 给 workerworker 在进程内喂给同一个核心服务。佐证 3worker 是事件流的中转站worker.ts:37-39 把全局事件转发到 RPCGlobalBus.on(event,(event){Rpc.emit(global.event,event)})worker.ts:47-97 的startEventStream还用 SDK 订阅 opencode 服务的事件流逐条Rpc.emit(event, ...)worker.ts:84-86推给 TUI。这正是内部模式createEventSource的on(handler)收到的数据来源thread.ts:42-49。佐证 4RPC 机制本身——JSON postMessagerpc.ts 定义了整套通信协议// worker 侧rpc.ts:6-14exportfunctionlisten(rpc){onmessageasync(evt){constparsedJSON.parse(evt.data)if(parsed.typerpc.request){constresultawaitrpc[parsed.method](parsed.input)postMessage(JSON.stringify({type:rpc.result,result,id:parsed.id}))}}}worker 侧listen接收请求并回结果emit主动推事件rpc.ts:16-18主线程侧client用call发请求挂 Promise、用on订阅事件频道rpc.ts:20-65。本质就是JSON 序列化走postMessage/onmessage的进程内消息通道。与前面所有文章串起来worker 不是新概念——系列文章里每处RPC 调用都在它身上前面文章的点落到 worker 的什么内部模式createWorkerFetchrpc.fetch→Server.Default().fetch内部模式createEventSourceworker 的Rpc.emit(event)外部模式client.call(server)rpc.server→Server.listen幂等stop的 shutdown RPCrpc.shutdown→ 释放实例 停 serverSIGUSR2热重载rpc.reload→ 重置 config disposeAll延迟升级检测rpc.checkUpgrade总结对比维度TUI主线程Worker独立线程职责界面渲染与输入后端服务Server/Instance/事件核心状态无session / provider / 权限 / MCP对外通道不直接暴露经 RPC 或真 HTTP server生命周期tui()主循环由stop的 shutdown RPC 收尾一句话记忆worker 就是 opencode 的后端服务rpc方法表fetch/server/shutdown/reload…是它的服务清单Server是它的业务核心会话/模型/权限Rpc.emit是它的事件出口。TUI 只是壳一切核心能力都在 worker 里前后端靠 JSONpostMessage 的进程内 RPC 解耦。OK本篇先到这里如有疑问欢迎评论区留言讨论祝各位功力大涨技术更上一层楼更多内容见下篇 blog【Agent】【OpenCode】TuiThreadCommand handlercheckUpgrade 的延迟与 unref