feat(desktop): harden Windows packaging foundation and bundled sidecar runtime#488
Conversation
Introduce the desktop build entrypoints and Tauri bundle configuration needed to emit NSIS and MSI installers while packaging the Go local-service as an external binary.
Start the Go sidecar from the desktop host, grant the required shell capability, and allow the packaged runtime to route workspace and database paths through an explicit app data directory.
…g-foundation # Conflicts: # apps/desktop/src-tauri/gen/schemas/capabilities.json
Wait for the bundled service pipe before the renderer issues RPCs, cross-build the Go sidecar explicitly for Windows, and remove unnecessary webview shell spawn access now that Rust owns sidecar startup.
Teach the desktop Windows workflow to react to local-service changes, install Go, compile the Windows sidecar first, and then run the existing no-bundle Tauri build against the real packaging layout.
Refactor the server entrypoint into testable helpers and add focused CLI/startup tests so the packaging branch no longer drops Go coverage in the cmd/server package.
Timeout named-pipe bridge waits in the Tauri host and fail over packaged renderer requests to the local HTTP JSON-RPC endpoint so dashboard and control-panel loads no longer hang when the pipe session stops returning responses.
Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: gdemonc <146809967+gdemonc@users.noreply.github.com>
Accept Tauri loopback-style origins on the debug RPC endpoint so packaged builds can recover from stalled named-pipe requests without being blocked by CORS.
Open a fresh pipe stream for each desktop RPC and keep the local-service stream handler responsive so one stalled packaged window no longer blocks later dashboard or control-panel reads.
Keep a shared named-pipe session alive for the desktop host so subscribed windows continue receiving task and delivery notifications while packaged RPC requests still wait for sidecar readiness.
…m/gdemonc/CialloClaw into feat/desktop-packaging-foundation
Remove the leftover merge markers from the Tauri bundle config and keep the packaged sidecar path aligned with the current desktop packaging flow.
Remove the leftover merge markers from the desktop Windows workflow, keep the cached Go setup, preserve the stable desktop checks, and use the current sidecar build command.
Keep cross-task named-pipe reads concurrent but serialize requests that target the same task so shared notification drains cannot race and drop replayed task updates or deliveries.
…sk deduper fix: Deduplicate terminal shell-ball task bubbles and add terminal task deduper
fix: Handle invalid JSON in loadStoredValue and add contract test
Keep the default named pipe when the bundled sidecar is unavailable so debug and manual local-service sessions still connect. Serialize task-starting shared-stream RPCs to prevent runtime-notification cross-talk under concurrent requests, and cover the startup entrypoint with targeted tests.
Register the existing Windows icon assets in the Tauri bundle config so NSIS builds stop failing during installer generation. This keeps the desktop packaging path aligned with the packaged app assets already shipped in src-tauri/icons.
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
|
@xgopilot 你提的 #488 (review) 这个问题确实存在,也属于这个分支负责的范围:隔离 named-pipe 请求一旦超时,当前实现会继续把后续悬浮球 bubble submit 走 isolated 路径,等于在“已知可疑”的通道上反复重试,存在持续堆积失控后台 worker 的风险。它不一定每次都永久泄漏线程,但确实缺少降级保护。现在重新review一下 |
ReviewNo new findings in the re-review scope. The prior concern about isolated named-pipe timeouts repeatedly sending later shell-ball bubble submits down the same suspect path appears resolved in this branch:
Residual gap: I did not find a transport-level test that forces a real isolated timeout end-to-end; the new coverage is unit-level around the latch. I was able to run |
|
@MeteorsLiu 好,#488 (comment) 和 #488 (comment) 已经改了,不过对于 https://github.com/1024XEngineer/CialloClaw/pull/488#discussion_r3212819830,ai跟我说的是这里的前提其实不是“RPC server 只会跟着整个进程启动一次、退出一次”,而是把 Server 作为一个可显式 Start/Shutdown 的生命周期组件来设计。当前这层抽象除了服务真实运行,也承载了测试里的几个约束:并发 Start 要拒绝、干净 Shutdown 后允许再次 Start、如果 shutdown 超时则后续要 fence reuse。单靠 context.Done() 只能表达“这个 context 被取消了”,但表达不了这些 server 自身状态,所以这里还是保留了显式状态位。另外这里也不是想靠 context 传递业务错误;terminalErr 主要是为了区分“正常停机后可复用”和“停机不完整、后续不应继续复用”这两类状态。因为 ctx.Err() 最终只有 Canceled/DeadlineExceeded,不足以保留这层 server 生命周期语义。然后测试貌似已经把这个契约写死了,要改还要改这几处地方,主要是在server_transport_test.go下的 |
ai胡说八道,ctx.Cause 让他看这个,生命周期这一块你去想清楚,验证一下 |
好,学长,学到了,已经改好了,具体变更见cf2270a |
没见到相关更改,是不是回复错了 |
这里现在不用 WithCancelCause,ai判断是这层 context 已经不承担“传递 terminal error / lifecycle cause”的职责了。然后现在服务已经收窄成 one-shot,对这个 context 来说只需要支持父级取消传播和 Shutdown 主动 cancel,所以普通的 WithCancel(ctx) 就够了。上面那个提交是收束的一个,不过他没收干净,我再补了一个a70f959 |
这是在干啥?
|
嗯,这个可能是我的决策问题吧,一开始我是想着都改的,不过ai说明WithCancelCause是只有在需要给取消附带一个可读取的额外原因才需要,所以我最后选择了保留,然后现在是改了的,最新提交:874d5ea |
|
bf98f64 这个是哪个main,为啥会产生一堆文件变更 |
这个是思凯那边在优化代码,然后不解决的话会有冲突 |
我意思是你是不是merge错了,merge对的话是不会产生这些变更的,我不管谁推commit了 |
耶?我看看 |
还真是,这最新的commit怎么有不相干的东西 |
背景
这个分支主要补齐并加固了桌面端在 Windows 打包场景下的运行基础设施,使 CialloClaw 从“开发态可运行”进一步走向“打包后可启动、可通信、可更新”。
相较于
upstream/main,本分支重点解决的是 packaged desktop 在真实安装包环境中的一组问题,而不只是单点修复:这个分支解决了什么问题
1. 补齐 Windows 打包基础能力
分支为桌面端补齐了 Windows 打包所需的基础配置和产物约束,包括:
这部分改动让桌面端不再依赖开发态的本地环境假设,而是具备了完整的“随包分发 + 随包启动”的基础能力。
2. 让 bundled local-service 在打包环境中稳定启动
分支把 bundled local-service 的启动流程做成了真正可用于安装包环境的方案,并补齐了失败处理与可观测性,包括:
这部分的目标是解决“包打出来了,但本地服务起不来 / 起了连不上 / 出错难定位”的问题。
3. 加固 packaged 场景下的 named-pipe RPC 传输
这是这条分支最核心的一部分。围绕 packaged desktop 与 local-service 的通信链路,分支做了多项稳定性增强:
这部分主要解决的是:
4. 对 shell-ball / 桌面交互做 packaged 对齐
在打包通信链路稳定之后,分支也同步收敛了 shell-ball 与 runtime 的交互行为,使其更符合 packaged 场景的真实执行链路,包括:
这部分的重点不是做新功能,而是让悬浮球、任务流和本地服务在打包环境中的行为与预期一致,减少“开发态正常、打包后异常”的断层。
5. 修复安装/升级时未停进程的问题
分支还补上了安装器层面的最后一环:
cialloclaw-desktop.execialloclaw-service.exe这部分解决的是安装包覆盖升级时桌面进程仍在运行导致的文件占用、替换失败和升级不完整问题。
总结
整体上,这个分支解决的不是“如何把桌面程序打成一个安装包”这么简单的问题,而是:
让 CialloClaw 的 Windows 安装包在真实用户环境中具备完整、稳定、可升级的运行基础。
它主要完成了三件事:
验证
本分支已经围绕打包链路做了针对性验证,包括:
影响范围
主要涉及以下模块:
apps/desktop/src-tauri/apps/desktop/src/features/shell-ball/apps/desktop/src/rpc/services/local-service/cmd/server/services/local-service/internal/rpc/services/local-service/internal/orchestrator/