☰
199、【Agent】【OpenCode】TuiThreadCommand handler:worker 到底是什么
2026/10/7 10:47:47 网站建设 项目流程

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除

标题

199、【Agent】【OpenCode】TuiThreadCommand handler:worker 到底是什么

背景

上篇 blog
【Agent】【OpenCode】TuiThreadCommand handler:transport 双形态的触发与误区
拆了 transport 双形态:外部模式由--port/--hostname/--mdns或 config 的server非默认触发(worker 真起 HTTP server、fetch/events为undefined),内部模式全默认走进程内 RPC(createWorkerFetch把请求序列化转发、createEventSource订阅 RPC 事件流、伪地址http://opencode.internal);并澄清internal/external 不等于"内部/外部大模型",模型由 worker 按配置调用、与传输通道正交。198 里"RPC 转发给 worker"反复出现,但worker 到底是个什么东西一直没讲透——本篇专门拆worker.ts:它的 RPC 方法表、它握着的 Server 核心、它的事件中转

OpenCode

192 篇只讲了"怎么把 worker 拉起来"(target()三级回退 +new Worker),本篇回答"worker 是什么"。一句话先给结论:worker 就是 opencode 的后端服务——会话、模型调用、权限、文件、事件全在它里面,TUI 只是前端界面壳,两者同进程分线程、靠 RPC 通信。


🧩架构总览:TUI 是壳,worker 是核

角色所在线程是什么持有什么
TUI主线程前端界面渲染、输入、快捷键,无核心状态
Worker独立线程opencode 后端服务Server(session/provider/权限/MCP)、Instance(按目录实例)、事件总线

主线程通过Rpc.client<typeof rpc>(worker)(thread.ts:140)连上 worker,typeof rpc让 TUI 能类型安全地调用 worker 暴露的每一个方法。下面用 worker.ts 源码逐层佐证。


📋佐证 1:RPC 方法表——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 分支外部模式起真 server
shutdownthread.ts:162stop优雅关闭(5s 超时)
reloadthread.ts:145SIGUSR2热重载
checkUpgradethread.ts:198延迟升级检测
setWorkspacethread.ts:46createEventSource切换工作区事件流

🏛️佐证 2:worker 握着 opencode 的核心服务 Server

worker.ts:102-120 的fetch里,关键一行是:

asyncfetch(input){...constresponse=awaitServer.Default().fetch(request)// 进程内交给核心 HTTP 服务return{status,headers,body}}

Server(src/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 给 worker,worker 在进程内喂给同一个核心服务"。


📡佐证 3:worker 是事件流的中转站

worker.ts:37-39 把全局事件转发到 RPC:

GlobalBus.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)。


🔌佐证 4:RPC 机制本身——JSON + postMessage

rpc.ts 定义了整套通信协议:

// worker 侧(rpc.ts:6-14)exportfunctionlisten(rpc){onmessage=async(evt)=>{constparsed=JSON.parse(evt.data)if(parsed.type==="rpc.request"){constresult=awaitrpc[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→ 释放实例 + 停 server
SIGUSR2热重载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 里,前后端靠 JSON+postMessage 的进程内 RPC 解耦。


OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog
【Agent】【OpenCode】TuiThreadCommand handler:checkUpgrade 的延迟与 unref

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询