READMESource: main@be2baa0f
dsh-unlag(解除卡顿)
一个按钮,把「必须重启才生效」的更新变成点一下。除了第一次装它本身,之后不用再重启 DSH。
窗口右上角那个按钮做两件事:把改过的插件代码原地换掉,以及把老旧/卡顿的界面重建一次。 两件事都不动进程,所以会话、正在跑的轮次、排队的消息、没发出去的输入都还在。
有几个会话正在跑的时候点也可以:马上换,不等空闲。正在跑的轮次不会被打断,也不丢东西——换的是插件代码,轮次自己的上下文、消息和草稿都在;极端情况下某一步正好调用到被换掉的插件,那一步会报错重来,会话继续。
什么时候不用再重启
| 更新了什么 | 以前 | 现在 |
|---|---|---|
插件源码 .js 改了(工具、接口、行为) |
重启 App | 点一下换代码,页面都不需要重建 |
| 客户端 bundle / 界面文案、按钮、组件变了 | 重启 App + 刷新页面 | 点一下重建页面 |
~/.dsh/profiles/*/cordis.patch.yml 或插件配置改了 |
重启 App | 点一下重读并重挂受影响的条目 |
第一次装一个 bundle(plugin_manager install_bundle) |
重启 App | 点一下让它激活 |
| 界面用久了变卡 | 重启 App | 点一下重建页面 |
什么时候仍然要重启(这个插件管不到)
这些不是 Cordis 插件,或者是进程级的东西,热重载的入口碰不到:
- 宠物窗口的
~/.dsh/dsh-pet/main-config.jsonc(display之类的参数)——它是独立的 Electron 进程,配置在它自己启动时读一次。 - 其它进程自己的缓存,例如某次给 tesseract 装语言包后
--list-langs要重开进程。 - 别的宿主,例如 Claude Code / Codex 的
.mcp.json。 - DSH 自身升级(
@deepseek-ai/dsh-*版本变更)、原生/编译依赖变化。
设置里的两行
- 按下刷新时换掉插件代码(默认开)
- 按下刷新时重建界面(默认开)
两个都勾:一次点击按需执行——先换需要换的代码,再重建页面;某一项没有可做的事就空跑过去,没有副作用。 只勾一个:另一个完全不动(只换代码时页面不刷新,渲染状态和滚动位置都保留;只重建界面时插件代码不动)。 两个都不勾:点击无反应。
点一下具体按什么顺序发生
- 读设置,决定这一次要不要做插件、要不要做页面。
- 需要插件时:先看有没有轮次在跑,有就不动手(等下一次点击,或等它跑完自动换); 没有才让宿主重读并替换改过的模块。
- 需要页面时:先校验启动项在 bundle 里真的存在(缺一个就放弃重建并提示,避免启动失败把整个 App 带下去), 再提交输入框里最后敲的那几个字,然后在新文档里重进界面。
不会丢什么
- 正在跑的轮次、子代理、终端里的进程:宿主侧,不受影响(只有 App 进程重启才会断)。
- 排队的消息、引导队列、没发送的输入草稿和附件:重建页面之前会先提交焦点里的内容。
- 打开的窗口有未保存改动、或还有弹窗时:重建会被拦下并给出提示,不硬刷。
这个插件在任何路径上都不会自己重启或退出 App;重启只由你发起。
第一次装:只有这一次需要重启
这一次重启是为了让四样东西进到正在跑的进程里:hmr 条目、文件 watcher、/dsh-unlag/state、/dsh-unlag/reload。
之后所有更新都走按钮,不再重启。
出问题时看哪里
- 日志:
~/.dsh/unlag-reload.log(每次换代码、跳过、失败各一行,含原因)。 - 状态:
GET /dsh-unlag/state回{"plugins":true,"page":true}就是两个开关的当前值。 - 换代码失败时旧代码继续跑,不会出现半换状态;错误只进日志。
测试
node test/button.test.mjs # 开关、两个接口、忙时立刻换、无宿主时不崩
node test/safety.test.mjs # 15 条崩坏路径,含未处理拒绝
No comments yet. Be the first to write one.