feat(wsl): manage opencode servers inside WSL distros (Windows desktop) - #164
Open
rayn1314 wants to merge 9 commits into
Open
feat(wsl): manage opencode servers inside WSL distros (Windows desktop)#164rayn1314 wants to merge 9 commits into
rayn1314 wants to merge 9 commits into
Conversation
- WSL runtime probe, distro enumeration (local + online), per-distro probes and opencode version checks with UAC-elevated installers - server lifecycle jobs (start/install/remove) with generation-guarded state, UTF-16 console decoding, full state push via wsl-state event - deterministic server ids (wsl:<distro>), startup warm-up - opencode command surface extended for WSL sidecar lifecycle
- wslStore syncs runtime into serverStore: ready servers register with auth and auto-subscribe to the multi-server sidebar (WSL badge) - connections list renders one card per WSL server combining connection and lifecycle management (switch, health, default, install/update opencode, retry, remove); add dialog with detection progress state and terminal entry - default-server preference persisted (boot auto-switch, death- rebirth restore after sidecar restart); WSL ids excluded from localStorage persistence; SSE resubscribes on same-id runtime change
- upsertServer broadcasts server-runtime-updated on any endpoint change (first registration included), decoupled from the active server - SidePanel subscribed filter tracks the serverStore snapshot so the WSL group appears the moment the server registers, no manual re-subscribe - per-server SSE rebuilds the single affected connection on runtime change: the boot-window fallback connection (WSL not yet registered) stays healthy on the wrong address and never self-heals via auto-reconnect
Owner
|
感谢pr,最近工作太忙,更新比较慢,抽空我会看看的 |
- initialize_wsl 瘦身为仅恢复配置+拉起已有服务器,删启动全量 opencode 检查与预热块 - 新增 prewarm_wsl 命令,设置页打开时按需补齐 runtime/发行版列表/opencode 检查 - 在线目录 stale-while-revalidate 缓存(wsl-online-cache.json, TTL 24h):联网目录持久化,过期先展示后后台刷新 - 对话框「重新检测」按钮走 force=true 绕过缓存,autoProbePlan 走缓存 - 未添加过 WSL 服务器的机器启动路径零开销
- collectActiveServerIds 过滤未注册服务器,消灭 WSL 就绪前请求回退 local 的数据串服 - 注册事件订阅 serverStore,WSL 就绪时自动入集触发接入 - upsertServer 无变更短路,wsl-state 全量推送不再触发 localStorage 写入与全体重渲染 - 订阅集合改增量 diff(Map 按 serverId),集合变化不再全量拆建 SSE 与全量重拉 - useModels 按 reason 门控,非 active 服务器端点变化不再触发模型重拉 - 补增量接入与定向重建订阅的契约测试
- useSessions 重试改为显式循环,loading 生命周期=循环生命周期,重试等待期不落地 - 重试耗尽才落 error 终态,空态文案不再伪装成「没有对话」的加载失败 - FolderRecentList 空态前增加 error 分支,加载失败显示可点击重试 - 新增 locale 键 sidebar.loadFailed - 补重试期保持 loading 与耗尽落 error 的契约测试
- 后台 revalidate 加在途标志,避免每次 ServeStale 并发拉起会挂住的 wsl --list --online - prewarm 只补未就绪发行版的 opencode 检查,就绪服务器由 Ready 挂钩刷新,不再重复 spawn - 单元测试去掉冗余 target_os 门控(模块本身已按 Windows 编译)
- collectActiveServerIds 过滤后为空时兜底回退 active server,避免 SSE 全灭(补回归测试) - useSessions 重试等待期检查 enabledRef,懒加载闸门关闭时中断在途重试 - 重试终态改为 return 而非 throw 到空 catch,消除空 catch 块
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
起因
我在 Windows 上主力用 WSL 跑 opencode(Linux 环境确实更顺手),但 OpenCodeUI 桌面端想连上 WSL 里的服务只能手动「添加服务器」填地址——而 opencode serve 每次启动端口和密码都会变,等于每次都要去 WSL 里查一遍再手填一遍,没法日常用(也就是 #161 描述的痛点)。
官方 OpenCode 桌面端已经有完整的一套 WSL 服务器管理,所以我对着它的实现(packages/desktop/src/main/wsl 和 packages/app/src/wsl)逐项对照,给 OpenCodeUI 补上了这块能力。这个功能的目标是让 opencode 真正跑在 WSL 里、像管理本地服务一样管理它的完整生命周期,而不是从 Windows 侧拼个地址远程连过去的包装。
这是 Windows 桌面端(Tauri)专属功能,Web / Docker 部署完全不受影响(WSL 命令只在 Windows 编译分支注册)。
现在能做到什么
设置 → 服务器里:
实现方式挑重点
截图
后续改进(启动性能与加载体验)
功能做完真机用了一阵,发现初始启动的加载明显变慢(侧边栏会话列表、模型选择栏都要等更久),用 DevTools Network 看了一遍请求时序,定位到三组问题,挨个修掉了:
1. WSL 探测全部改为按需触发
原来的实现是应用一启动就在后台无条件跑一轮 WSL 探测:runtime 探测、发行版列表、联网拉微软在线目录、逐个发行版查 opencode——哪怕你从没添加过 WSL 服务器也照跑,等于为用不到的功能在启动路径上付成本。现在启动只做「恢复上次状态」(读配置 + 拉起已添加的服务器),所有探测改到打开设置页时按需触发;联网的在线目录加了 24 小时缓存,先展示后刷新,点「重新检测」才强制联网。
2. 启动级联:全量拆建改增量接入
WSL 服务器就绪注册时,原实现会把所有服务器的 SSE 连接全拆全建、所有会话数据全量重拉一遍,同一份数据在启动窗口期要加载 2~3 次;另外未注册的 WSL 服务器 id 会静默回退到本地端点,把本地数据写到 WSL 的键下(数据串服)。现在未注册服务器不订阅(注册即自动接入),订阅集合按服务器增量 diff——加入只连新的,移出只拆旧的;wsl-state 全量推送的重复同步也加了短路,无变更零副作用。
3. 会话列表的加载态与错误态
网络抖动时每个文件夹的重试间隙会闪现「此文件夹中没有对话」,重试耗尽后失败还会被永久伪装成空数据。现在重试期间保持加载态,「此文件夹中没有对话」只在真的确认没有会话时出现,加载失败如实显示「加载失败,点击重试」。
提交前对这批改动做了一轮独立审查,顺手修了几个边界问题:pane 里还开着已失效服务器时 SSE 集合可能被清空(现在兜底回退 active server)、离线机器上后台刷新会反复拉起挂住的联网进程(加了在途去重)等。
踩过的坑(挑几个印象深的)
#[serde(rename_all = "camelCase")],命名有机械保证。wsl --list --online要联网:网络慢时超时会把已经成功的本地列表一起丢掉,还伪装成「没有发行版」。现在本地列表和在线目录解耦容错,谁失败只报谁。Stdio::piped():子进程输出全拿空串,探测「成功」但数据全空,上层误判成没数据就无限自动刷新,整个弹窗卡死。已补回归测试防再犯。invoke_handler注册 WSL 命令——Tauri 的 invoke_handler 是整体替换语义,第二次调用会把第一次注册的全部命令覆盖掉,安装包表现为「进程在但窗口永远不出来」。现在 WSL 命令合并进同一个generate_handler!列表。wsl.exe的管道输出是 UTF-16LE(可能带 BOM)和 UTF-8 混杂,不解码就是乱码。验证
提交组织
为方便审计拆成九个提交:
chore: exclude local opencode reference dir from git, eslint and vitest—— 排除我做官方源码对照用的本地目录feat(wsl): backend server management commands for Windows desktop—— src-tauri 全部(7 文件)feat(wsl): frontend server sync, settings UI and connections integration—— src 全部 + package.json(21 文件)fix(wsl): sidebar group and SSE follow WSL server registered after boot—— WSL 服务器启动后就绪后自动注册进侧边栏并接通事件流perf(wsl): 按需预热——启动零探测、设置页意图驱动、在线目录 TTL 缓存—— 启动路径只恢复状态,探测按需perf(sessions): 修复启动级联——未注册服务器过滤、upsert 短路、订阅集合增量管理—— 消灭启动窗口期的重复加载与数据串服fix(sidebar): 会话列表加载态与错误态——重试间隙不再闪现空态文案fix(wsl): 评审修正——在线目录 revalidate 去重、prewarm 跳过就绪服务器、测试门控简化fix(sessions): 评审修正——过滤后兜底 active server、enabled 关闭中断重试、去除空 catch前后端拆开但没拆更细的原因:wslStore 和 serverStore 互相引用对方本次新增的方法,行级拆分会产生无法通过 typecheck 的中间提交;性能与体验修复(5-9)按主题拆分,每个提交都能独立通过校验。
Closes #161
关于 AI 辅助
这次的排查和实现过程使用了 AI 辅助(对照官方源码做差距清单、定位跨���言序列化问题等),但上面每一个功能点都是我在真机上逐一实测验收过的。