zai-org / zai-org/feedback

[Bug] 已完成的子代理会话(subagent_child)泄漏进主会话列表,且可交互续聊

Open
#637 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

priority: P2
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

路径为根据客户端代码根因分析 + 本地取证推断,建议官方按此验证。

  1. 在任一会话里用 Agent 工具派一个子代理执行任务(如审查类长任务),等待其完成;
  2. 从父会话的子代理任务视图/转录入口打开该子代理的对话内容(或重启客户端后重新打开父会话,触发子代理转录重新加载);
  3. 查看左侧主会话列表 → 该 subagent_child 会话出现在列表中;
  4. 点开它,输入任意消息 → 正常发送并得到回复。

对照组:仅通过 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.