Repository navigation
[Bug] 回归:0.2.0-rc.2 起,删除子代理会话目录不再从 UI 清除该条目 #9552
Replies: 1 comment 1 reply
The record layer is append-only, and that is why nothing else in the product can clear itYour layer analysis matches the source. The parent-side record is a projection over an append-only fold — apply: (state, event: SessionEvent) => {
if (event.type !== 'subagent/catalog' || event.seq < state.inheritedEventCount) return state
return { ...state, head: appendChunkedList(state.head, eventDataSchema.parse(event.data)) }
},and the wire view maps every collected entry to a row: function subagentCatalogEntries(state) {
for (const data of iterateChunkedList(state.head)) { ... entries.push({ id: childId, createdAt: childCreatedAt, ...descriptor }) }
}There is no counterpart to Deleting the child's session directory therefore cannot work any more, and the reason is upstream of the UI: the row is derived from the parent's log, and the child directory is not an input to it. Two consequences worth naming:
So the request is right and it is a small one in shape: one version bump of the catalog payload with a terminal flag (or a sibling |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
EN TL;DR: After
0.2.0-rc.2, deleting a subagent's session directory no longer removes it from the Web UI — the record now lives as asubagent/catalogevent in the parent session log, and there is no retire/removal path in the event, projection, query, or tool layer. The same release added a full archive lifecycle for sessions (unarchiveSession). Request: give subagent records a symmetric "retire" capability.摘要
#1202 记录过"子代理条目无法从 UI 清除",并指出当时唯一的办法是手工删除磁盘上的会话目录——该办法有效。
0.2.0-rc.2(2026-09-30 升级)之后,这个办法失效了:删除子代理的会话目录不再影响 UI 显示,帖子会一直留在子代理列表里("一次性 · 当前未运行"),刷新与重启均无效。原因:子代理记录现在是父会话日志里的
subagent/catalog事件,而事件层、投影层、查询层、工具层四层都没有移除或退役路径。也就是说,从"有手工变通办法但没有一等公民入口",退化成了"完全没有任何办法"。而同一次升级为会话补齐了
unarchiveSession(完整归档生命周期:归档 → 视图筛选 → 取消归档 → 撤销)——这正好回应了 #1202 评论区当时提出的"归档会不可逆、得按不可逆动作设计"的顾虑。因此本贴请求的是为子代理记录补上对称的那一半,而不是从零发明某个能力。既有报告(本贴的增量在哪)
相邻讨论已有两条,但它们定位在状态层,本贴定位在记录层——互补,不是重复。
#476(已关闭 · resolved)
[bug] Subagent sessions that did not terminate normally are shown as green (ready/archived state indistinguishable from completed)诊断的是状态显示:约 39 个子代理会话处于
ready状态(仅存在于存储、可send_message续接、非终态),却在 UI 中被渲染成绿色done,与真正完成的无法区分。它给出了最底层的成因(注意这句直接支持我们的论点):
以及 GUI 侧的取色分支(
ui-subagent/.../SubagentCatalogAction.tsx:348):#1202(仍然开启 · 1 条评论)
[Bug][Web GUI] Failed subagents stay visible in the UI as if still running — non-terminal ready state, no way to clear them from the UI环境
0.1.0-rc.6/ Linux。诊断的是状态机:后台子代理已失败,UI 却仍显示为运行中;list_agents报ready(非终态)。它的第二条诉求是"提供一个 dismiss 动作",且正文明确记录了当时的变通办法:
—— 这就是本贴的切入点:那个唯一办法,在 0.2.0-rc.2 上不再生效。
#1202 的评论(weijiafufu14, Aug 27)—— 与本贴最有关系的两点
(a) 它把三帖归纳为"一个缺失字段的三种表现":同一个
ready在 #476/#478 被渲染成绿色"已完成",在 #1202 被渲染成"仍在活动",而list_agents报的ready才是真实语义(但只有工具能看到)。建议把诉求从"请把失败的标成失败"提到"activity需要能表达终态结局"。(b) 它列了一张 DSH 公开 API 表,回答"能否提供清除动作":
workspaceRegistry.archiveSession(sessionId)unarchiveSession(sessionId)SessionPersistence无delete/forget并给出警告:"它只是只增操作:归档了就没有官方的取消归档路径。所以如果做成用户可点的按钮,得当一个不可逆动作来设计(至少要有确认)"。
—— 0.2.0-rc.2 恰恰为会话解决了这个"不可逆"顾虑(取消归档 + 三态筛选 + 归档提示的撤销动作)。这就是本贴"对称性"论据的来源:同样的顾虑,官方已经为会话解了一次,子代理这一次还没有。
本贴与它们的区别
activity无法表达终态结局subagent/catalog事件成为父会话日志中的不可变事实一句话:#476 / #1202 解决的是"为什么它看起来还活着";本贴解决的是"为什么它明明结束了却删不掉"。
本贴的三点增量
subagent/catalog事件 +subagentCatalog投影,并给出四层(事件 / 投影 / 查询 / 工具)各自缺什么、该在哪一层补建议:本贴独立提交(根因层面与触发条件都与它们不同,并入会让讨论失焦),正文已引用 #476 / #1202;同时在 #1202 下留一条简短的跟进评论,指出其"唯一办法"已失效并链接本贴——因为那句话现在已经是错的。
环境
@deepseek-ai/dsh0.2.0-rc.2(Windows)@deepseek-ai/dsh-subagent(包内文件时间戳2026-09-30 15:56:18)session.v4.jsonl.zstd)复现步骤
subagent工具,或workflow内的agent())。实际结果:条目仍在,计数不变。
期望结果:条目消失,或至少提供一个显式的退役/隐藏入口。
根因
1. 数据源从"磁盘扫描"改成了"父会话日志投影"
subagent/catalog事件。UI 改为读取父会话的subagentCatalog投影 → 删目录不影响该事件,记录永久保留。2. 四层都没有移除语义
dsh-subagentsubagent/catalog一种事件,无"退役/删除"变体subagentCatalogProjectionDefinitionapply只做appendChunkedList;view遍历全部、无存活过滤listChildren()dsh-tool-subagent-controlsend_message与interrupt_agent(代码摘录见下方折叠块。)
关键代码摘录
投影定义 —— 只有 append,没有移除分支(
dsh-subagent/lib/types/catalog.js):UI 数据源(
dsh-subagent/lib/types/list-children.js):工具层(
dsh-tool-subagent-control/lib/index.js):父会话日志中的实际记录:
{ "type": "subagent/catalog", "seq": 6517, "time": 1791739054872, "data": { "version": 0, "childId": "7334292e-0892-44eb-81a9-4d305ca51fa6", "childCreatedAt": 1791739054844, "mode": "one-shot", "label": "Casual subagent probe" } }证据链
①
subagent/catalog只出现在 v4 格式文件中session-fad4189f-64f2-423f-9bf3-34224ea101a0workflow子代理调用)session-1550a353-006e-4ee7-8153-4fa761599637workflow子代理调用)两者同属 projectKey
--F-deepseek~0020~0020harness--。② 同一会话、同一工具,相隔 52 天行为不同(关键对照)
会话
session-1550a353-006e-4ee7-8153-4fa761599637:subagent/catalogworkflowworkflowworkflowworkflowworkflow(catalog 事件与对应
tool/call相隔 0.3–0.4 秒,确认为同一次 spawn 产生。)③ 清理记录对撞
8e452f5a-d80e-4758-b17b-61178db41adf、f1d55623-59d9-4017-826b-0d35fe2b9900、86e92bfd-eaf9-4892-b0ce-e9ed9cea2d32d761831b-f416-4d28-87ed-84fa36d41d5c、207cba51-c581-4825-a5e4-ef521abfbf3370daeb5d-bfa9-495b-a871-f94f05fa85ae、fbce292e-4db3-4e03-b6e3-a99b83c378b80063bb9c-3b60-429d-bc60-309c323e41e22a8a7860-3c57-41a7-b8cd-25256ad18e58、b9f17d8c-567c-4d41-80ed-45bf8c0d921ed14b24e8-43af-486a-b69e-f73b3d11ca5b、1dea3837-09cb-4540-acb3-cb5d302e661b、d37a3d83-626b-44ef-81e8-ec076fd28e62、29556e75-05d2-407d-a8c8-5fc23a682c397334292e-0892-44eb-81a9-4d305ca51fa6关键对撞:10-11 17:09 删除的 4 个 UUID,与 ② 中同日 17:00–17:04 产生的 4 条 catalog 事件的
childId完全一致;而 8 月那 5 次清理(当时无 catalog 事件)全部有效。即:同一批 UUID,删掉后 8 月有效、10 月无效。④ 包文件时间戳
修复建议
方案 A(推荐,符合现有 append-only 架构)
为 catalog 引入追加式退役语义:新增
subagent/retire事件(记录childId、原因、时间),subagentCatalogProjectionDefinition折叠时将其标记为 retired,subagentCatalogEntries过滤掉 retired 条目。日志仍完整留痕,UI 可清理。方案 B(最小改动,但语义较弱)
subagentCatalogEntries/ UI 层过滤掉"子会话已不存在于 session store"的条目。缺点是把"记录是否显示"重新绑定到磁盘存在性,与 9/30 那次改进的方向(不依赖磁盘扫描)相悖。方案 C(补入口)
增加
forget_subagent工具(配合方案 A 的事件),让用户或 agent 显式退役子代理记录。无论采用哪种,建议在文档中明确"子代理记录的生命周期",避免用户继续按"删目录"的旧习惯操作。
一致性论据(本贴的核心)
0.2.0-rc.2已经为会话补齐了完整的归档生命周期:dsh-workspace暴露unarchiveSession(sessionId): Promise<void>而同一次升级(引入 v4 日志格式与
subagent/catalog)让子代理记录只有"登记"没有"退役"。因此本问题不宜被归类为"DSH 不做破坏性入口"的设计取舍——更准确的定性是生命周期不完整的一致性缺口:会话有"归档 ↔ 取消归档",子代理只有 catalog 登记。既然官方愿意为会话提供减法入口,子代理缺的对应一半也应当补齐。
影响
~/.dsh/storages/session_projcache/sessions/<childUuid>.json在删除子代理目录后不会清理,实测已堆积多个已删子代理的缓存文件(纯缓存,不影响 UI)。相关讨论
相邻层面(子代理条目的状态与清除)—— 本贴的直接上下文:
Failed subagents stay visible in the UI as if still running — non-terminal ready state, no way to clear them from the UISubagent sessions that did not terminate normally are shown as green (ready/archived state indistinguishable from completed)list-children.ts:49-55)ready状态被渲染为绿色 "completed"(以上定位"状态层";本贴定位"记录层",区别见「既有报告」节。)
同一类(缺少减法入口):
unarchiveSession已内建,见「一致性论据」节)同版本 / 同 UI 区域:
指引与背景:
附注
~/.dsh/sessions/与session.v4.jsonl.zstd直接核验;事件seq与毫秒时间戳同样为原始值。--F-deepseek~0020~0020harness--中的~0020~是空格转义(本地工作区路径含空格),仅用于定位,不含敏感信息。All reactions