[Bug] 已完成的子代理会话(subagent_child)泄漏进主会话列表,且可交互续聊
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 22
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
提交前确认 · Pre-submission checklist
- 我已搜索过现有 issue,确认这不是重复 / I searched existing issues and confirmed this isn't a duplicate.
- 我已阅读 CONTRIBUTING.md / I've read CONTRIBUTING.md.
问题类别 · Category
对话 / Agent 交互 · Agent chat
涉及的 Agent 框架 · Agent framework
ZCode Agent(自研)
严重程度 · Severity
影响体验 · Major(功能可用但体验受损:子代理的隔离性/一次性语义被破坏,且容易被误当作普通会话继续对话)
复现频率 · Reproducibility
偶现 · Sometimes(触发条件:子代理转录曾被加载进后端运行时注册表;代码层面看是确定性路径,见下方根因分析)
问题描述 · Summary
主会话通过 Agent 工具派出的子代理(task_type = "subagent_child",parent_id 非空)在任务完成后,出现在左侧主会话列表里,并且可以点开续聊——输入框照常受理消息,子代理以 zcode-agent 人格正常回复。
用户视角的体感是:"我没开过这个会话,它怎么在主会话列表里?而且子代理居然能对话?"
复现步骤 · Steps to reproduce
路径为根据客户端代码根因分析 + 本地取证推断,建议官方按此验证。
- 在任一会话里用 Agent 工具派一个子代理执行任务(如审查类长任务),等待其完成;
- 从父会话的子代理任务视图/转录入口打开该子代理的对话内容(或重启客户端后重新打开父会话,触发子代理转录重新加载);
- 查看左侧主会话列表 → 该
subagent_child会话出现在列表中; - 点开它,输入任意消息 → 正常发送并得到回复。
对照组:仅通过 Agent 工具派发、从未打开过其转录的子代理,不会出现在列表中。
预期行为 · Expected
- 子代理会话不进入主会话列表(仅在其父会话的子代理视图内可见);
- 子代理不可被交互续聊(其一次性任务语义保持完整)。
实际行为 · Actual
- 子代理会话泄漏进主会话列表;
- 该会话可交互续聊:本地
db.sqlite中可见该会话写入了input_history(kind=prompt)、session_input(kind=sendText, delivery=startNow, status=promoted),消息semantics.origin = "real_user"——即客户端输入管道对subagent_child会话完全放行。
根因分析 · Root cause(代码级,来自 resources/glm/zcode.cjs 0.16.5)
① 列表泄漏:协议层 listSessions 由两段拼接——
// 第一段:db 查询,干净
await sessionStore.listSessions({ directory, limit: 50, roots: true })
// 第二段:内存活跃会话合并,漏了 subagent_child
for (let s of e.sessions.values())
s.persistence !== "deferred"
&& s.taskType !== "selection_side_chat" // ← 只排除了这一个类型
&& (… || i.push(fse({app: s.app, workspace: s.workspace})))
db 段有 roots: true、启动索引段有 taskTypes: ["interactive","fork","workflow_parent"] 白名单,唯独内存合并段没有等价过滤。子代理转录一旦经加载/恢复路径进入注册表(e.sessions.set(sessionId, …),该路径对 taskType 无门禁),其条目即被持续合并进列表结果;重启后再次触发加载会复现。
② 可续聊:会话加载/恢复路径同样不检查 taskType,被加载的 subagent_child 会话成为可交互运行时,输入队列正常受理 sendText。
建议修复 · Suggested fix
- 内存合并段补
taskType白名单(对齐启动索引段的["interactive","fork","workflow_parent"]),或等价地排除subagent_child/workflow_child/nested_workflow_child; - 加载/恢复路径对
subagent_child拒绝交互输入,或(若有意保留查看能力)在 UI 醒目标注"子代理会话"并禁用输入框。
版本 & 环境 · Version & environment
- 客户端:ZCode 0.16.5(Electron,Windows x64)
- 系统:Windows 10 19045 x64
- 后端 bundle:
resources/glm/zcode.cjs - 模型:GLM-5.3(coding-plan)
- 取证数据源:
~/.zcode/cli/db/db.sqlite(session / message / session_input / input_history 表)+ bundle 反编译对照
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with resources/glm/zcode.cjs, inspecting the listSessions memory-merge path and the session load/recovery path described in the report; use ~/.zcode/cli/db/db.sqlite to reproduce the affected session state. Done means completed subagent_child sessions stay out of the main list and reject interactive input while remaining available through the parent view.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- electron, javascript
- Domain
- backend, desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100