Replies: 3 comments
评论 B 草稿 → #916(UX 面:boot 失败 → 空白新会话 → 用户误判数据丢失)补充 #916 的一个更严重的变体:不是"运行中后端退出",而是"启动即失败"。 现象当 profile 因插件问题(如 #917 的残留条目,或插件产物缺失)根本起不来时,Web UI 渲染成空白新会话——连 #916 描述的"界面看起来正常但无响应"都不如:用户看到的是一个全新的空页面,第一反应是"我的全部对话和设置都丢了"。 关键事实:数据其实没丢JSONL 会话日志( 实际报错长这样(终端侧)终端有诊断,浏览器什么都没有。对双击启动或开机自启的普通用户,终端甚至一闪而过——诊断与用户彻底隔绝。 建议Web UI 需要两类失败态:
两者共用同一个目标:任何后端故障都不能让用户以为数据没了。 社区止损工具(--check 预检 + 启动包装,附恢复指引与数据安全说明):https://github.com/ICCuse/dsh-web-safe |
|
I published an installable external plugin as an immediate workaround for this exact visible-disconnect gap: https://github.com/yinren112/dsh-plugin-connection-banner/releases/tag/v0.1.0 Install: I verified the tagged GitHub install from a fresh profile: after a successful connection, stopping the Host shows the existing reconnecting banner without a page reload, and restarting removes it. If you try it, feedback with your DSH version and install method would be very helpful. |
|
感谢 @yinren112 把"后端退出无 UI 提醒"做成了可安装的 workaround 插件,以及 @ICCuse 补充的"启动即失败 → 空白新会话"更严重变体。前者是立即可用的过渡方案,后者提醒我们:无可见反馈的问题面不止"运行中退出",还有"从未成功启动",未来修复时值得一并覆盖。 |
Uh oh!
There was an error while loading. Please reload this page.
摘要
后端退出/被杀后,Web UI 全程没有任何可见反馈:不弹横幅、不显示"重连中"、界面看起来一切正常,只有浏览器控制台里一行
[web-runtime] connection lost, retry #N。根因是重连状态机与现成 UI 组件之间存在断线:客户端连接层在断线时确实发出了reconnecting状态事件,运行时也收到了,但该事件只被用于清理内部待处理交互状态(不可见),而 UI 库中已实现好的ConnectionBanner("连接已断开,正在重连…")从未被前端 shell 挂载渲染——状态存在、组件存在,唯独中间没有接线。复现步骤
dsh并打开 Web UI(127.0.0.1:端口)。Get-Process | Where-Object {...} | Stop-Process,或直接 kill 掉 dsh 宿主进程)。[web-runtime] connection lost, retry #N(N 随退避重试递增),无任何 UI 层日志。根因(源码定位,rc.6)
断线检测层只发状态事件 + console.warn —
@deepseek-ai/dsh-client-connection/lib/client.js:this.emitState("reconnecting")(L122-126 去重后回调sinks.onStateChange);console.warn("[web-runtime] connection lost, retry #N");运行时收到事件后只做不可见的内部清理 —
@deepseek-ai/dsh-client-runtime/lib/client.js:onStateChange: (state) => { if (state === "reconnecting") sessions.handleDisconnected(); };handleDisconnected():仅清空pendingInteractions、从pendingBuffers中过滤掉approval/requested与question/requested帧——没有任何 UI 副作用。UI 组件其实早已实现 —
@deepseek-ai/dsh-client-ui-primitives/lib/index.js:function ConnectionBanner({ reconnecting, label = "连接已断开,正在重连…" }) { ... },L5855 导出;前端 bundle(dsh-web-frontend/dist/assets/index-Dqw48FrP.js)的导出表中也能找到ConnectionBanner。但该组件在前端是死代码 — 整个 web 前端 bundle 中:
连接已断开与reconnecting关键字在 bundle 中零命中——说明前端 shell 既没有挂载横幅,也没有订阅连接状态;hostDescription有完整的 getSnapshot/subscribe 通道(client.js L10168-10176),而连接状态(connected/reconnecting)没有任何 UI 订阅通道。结论:
reconnecting状态机与ConnectionBanner组件都已存在,缺的只是中间接线——前端 shell 从未把连接状态接到任何可见 UI 上。建议修复
方案 A(推荐)· 在 web shell 挂载 ConnectionBanner 并订阅连接状态:仿照现有
hostDescription的 getSnapshot/subscribe 模式(dsh-client-connectionL10168-10176),在 connection handle 上暴露connectionStatestore;dsh-client-runtimeL10497 处把onStateChange一并写入该 store(保留现有handleDisconnected()调用);web shell 读取该状态,reconnecting时渲染 primitives 库中现成的ConnectionBanner。改动小、复用既有组件与既有状态事件,断线/重连对用户完全可见。方案 B · runtime 全局事件 + 横幅:runtime 在 reconnecting 时
ctx.emit连接事件,由 UI 层 toast/banner 组件消费。与 A 等效,但多一层事件协议,不如直接复用 A 的 store。方案 C · 最小改动:仅在前端 shell 内建一个 reconnecting 状态订阅并渲染横幅,不经过 runtime。改动最少,但状态来源绕开了运行时层,后续(如重连成功通知、断线时长展示)扩展性差。
影响
环境
验证材料
[web-runtime] connection lost, retry #N(递增重试号)——唯一反馈。index-Dqw48FrP.js中ConnectionBanner仅存在于导出表,无渲染调用、无默认文案。First analysis of discussion #216. Happy to open a PR with fix option A.
All reactions