You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
摘要
workspace-write沙箱只限制文件写(WRITE_RESTRICTED),不限制进程操作——沙箱内的 agent 可以用taskkill /T /F之类命令杀死自己的宿主进程树(同用户进程,令牌有 PROCESS_TERMINATE)。宿主在 turn 中途死亡时,会话日志干净地结束在step/start/tool/start之后(没有 torn frame):没有tool/result、没有step/end、没有turn/end。重启后:① 持久化层的崩溃修复只处理"撕裂的尾部"(dsh-session-persistence-jsonl的 truncation repair),对这种干净 EOF 的悬空 turn 不做任何闭合;② 客户端状态投影从事件日志派生——dsh-client-ui-conversation中settled === undefined → "running",于是该会话在界面上永远显示运行中、浏览器一直转圈;③ 服务端"会话活跃度"来自活体 agent 注册表(冷启动未恢复 agent → inactive),两个来源互相矛盾,没有一处做冷启动协调。这正是 #387 的现象与根因。根因(源码定位,rc.6)
dsh-sandbox-windows-acl的 WRITE_RESTRICTED 只拦截写访问(包文档明示 "writes are restricted; reads, network, and process visibility are NOT");
沙箱内 bash 的
taskkill /F /T /PID <宿主>可正常执行 → 宿主树整体消失。dsh-agent-loop的turn()已 appendturn/start(/step/start/tool/start)但来不及 appendturn/end(L591-595 的finally 没有机会执行)——日志合法但语义悬空。
dsh-session-persistence-jsonl只在帧撕裂时修复尾部(L1027-1034),对干净 EOF 的悬空 turn 无任何 closeout 逻辑;
dsh-session/lib/types/repair.js的中断修复词汇只用于 resume 时的消息推导,不会改写日志、也不参与状态投影。
dsh-client-ui-conversation/lib/client.jsL7386status = settled === undefined ? "running" : ...——没有 settle 节点的最后一个 step 被渲染为永久运行中。
dsh-host-apiproxy的会话活跃度取自活体 agent 注册表(L2969),冷启动后该会话无 agent → inactive,与客户端投影的"running"互相矛盾,
且没有 boot-time reconciliation 来统一。
复现步骤
dsh web,任意会话让 agent 执行任务。taskkill /F /T /PID <dsh 宿主 PID>——模拟 agent "为了配置生效而重启 DSH"。dsh web,打开该会话。无 step/end;无法自然继续([Bug] Agent 重启 DSH 时会杀死自身宿主,导致会话永久停留在“运行中” #387 原现象)。
建议修复
方案 A(推荐)· 冷启动协调闭合:加载会话时检测日志是否结束在未闭合的
turn/step/tool 内;若是,以中断语义补写 closeout 事件(
tool/result中断标记 +step/end+turn/endreason=aborted/interrupted,复用dsh-sessionrepair 词汇),使所有状态投影统一落到 "interrupted"。用户看到的是"上轮被中断、
可继续",而不是永久转圈。改动集中在 session 加载路径,一处解决 #387 及同类
宿主死亡场景(崩溃、断电、OOM、用户杀进程)。
方案 B(纵深防御)· 防止沙箱内进程杀死宿主:把宿主放入沙箱进程无法终止的
job object / 更高完整性级别,或由 runner 持有宿主 handle 拒绝 PROCESS_TERMINATE。
实现复杂,且只能防"故意/意外自杀",不能防崩溃与断电——需与 A 配合。
方案 C(UI 缓解):客户端检测到"无活体 agent 却投影为 running"的会话时,
提供"中断并继续"按钮(触发一次服务端闭合)。
影响
无 step/end,浏览器永远转圈)
日志干净地停在未闭合 turn 内,会话就"死"在界面上
环境
验证材料
First analysis of discussion #387. Happy to open a PR with fix option A.
All reactions