feat(web-shell): show subagent sessions in detail panel - #7380
Conversation
|
Thanks for the PR! Template looks good ✓ Problem: Observed UX problem — long subagent transcripts clutter the main conversation and increase parent-session memory pressure. The PR includes a screenshot showing the current state and the proposed detail panel. The problem is real and well-described. Direction: Aligned. Subagent session management is an actively developed area — Claude Code's CHANGELOG references subagent status lines, background agent attach improvements, subagent spawn caps, and Size: This PR touches core paths (
Approach: The scope is broad but coherent — a full-stack feature spanning core agent transcript helpers, CLI server routes (virtual subagent sessions, SSE), SDK types/normalizer, and web-shell UI (detail panel, drawer, parallel agents group). The design doc is a plus. The core changes are minimal (~129 lines), which is reassuring. Since the last review, 8 new commits addressed review feedback with significant hardening: round-level stream dedup via Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ 问题: 已观测到的 UX 问题——较长的子智能体 transcript 会让主会话难以阅读,并增加父会话的内存压力。PR 附带了截图展示当前状态和提议的详情面板。问题真实且描述清晰。 方向: 对齐。子智能体 session 管理是活跃开发领域——Claude Code 的 CHANGELOG 中提到了 subagent status line、后台智能体 attach 改进、子智能体生成上限和 规模: 本 PR 触及核心路径(
方案: 范围较广但内聚——是一个全栈功能。设计文档是加分项。核心改动很小(约 129 行),令人放心。 自上次审查以来,8 个新提交解决了审查反馈并做了显著加固:通过 进入代码审查 🔍 — Qwen Code · qwen3.7-max Reviewed at |
🖼️ web-shell visual previewRendered against a mock daemon (no real backend): the PR base vs this PR head Screenshots · before / afterℹ️ No screenshot changed against the PR base — but this PR edits 20 render-shaping files:
Either the change has no visual effect (logic, plumbing, a state the scenarios never reach), or no scenario renders this UI — in which case the preview cannot see it, and an empty result is a coverage gap rather than a clean bill of health. To make it visible, add a scenario to Full-resolution recordings (.webm) are attached to the workflow run. — Qwen Code · web-shell visuals |
🩺 serve daemon A/BBuilt the PR base vs this PR head ✅ No response changes against the PR base across 4 scenario(s). — Qwen Code · serve A/B |
Code ReviewIndependent proposal: For "show subagent sessions in detail panel", I would: (1) add Comparison: The PR's approach matches and exceeds this proposal. The architecture is sound — virtual session IDs encode parent + agent in base64url with input validation, the server polls the JSONL transcript at 250ms intervals with file-identity ( Findings — no critical blockers. The incremental changes since the last review are substantive:
The core changes (~129 production lines) remain minimal and backward-compatible: Real-Scenario TestingServer started successfully with the PR branch. The new subagent routes are registered and respond correctly: Route verification (no active session, so 404s are expected — confirms routing works): The virtual session ID Server logs confirm proper route matching and status codes: Unit tests all pass (1,613 tests across touched packages):
Note: full UI testing (opening the detail panel in a browser, verifying SSE streaming, drawer behavior) was not performed — this requires a browser environment. The server-side routes, SDK client, and transcript projection logic are verified through unit tests and route smoke tests. 中文说明代码审查独立方案: 对于"在详情面板中展示子智能体会话",我会:(1) 在 agent 事件中添加 对比: PR 方案与上述提案一致且有所超越。架构合理——虚拟 session ID 用 base64url 编码并做输入校验,服务端以 250ms 间隔轮询 JSONL transcript 并跟踪文件身份( 发现——无关键阻塞项。 自上次审查以来的增量改动是实质性的:轮次级流去重、文件身份跟踪、流 sidecar 生命周期管理、ALS 帧修复(#7156)、错误时订阅者清理、路由加固、usage-only ROUND_TEXT 处理、以及执行摘要单调累积。 核心改动(约 129 生产行)保持最小且向后兼容。 真实场景测试服务端成功启动。子智能体路由正确注册和响应。虚拟 session ID 编解码正确。所有 1,613 个单元测试通过。 — Qwen Code · qwen3.7-max Reviewed at |
|
Confidence: 3/5 — clean review with substantive improvements since the last pass, but the Stage 0 maintainer-awareness escalation (feat PR with ~2,961 production lines touching core) needs a maintainer's sign-off. This PR has improved markedly since the last review. The eight follow-up commits aren't cosmetic — they address real failure modes: transcript file rotation (file-identity tracking), stale stream replay (sidecar lifecycle), round-level dedup precision (runId), subscriber leaks on error (try/finally in subscribe), and a genuine ALS model-leakage bug (#7156). The round-level reconciliation via The architecture remains sound: virtual session IDs with input validation, bounded retention, polling-based transcript refresh with file-identity awareness, and a clear separation between summary and full transcript modes. The core footprint is still small (~129 lines), and the backward-compatible legacy task resolution via fuzzy matching is pragmatic. All 1,613 unit tests pass. Server routes respond correctly. The build succeeds. What keeps this at 3/5: the sheer scope (66 files, ~5,300 additions) means a human maintainer should verify the architectural decisions — particularly the round-level stream reconciliation weights, the No blocking issues found. Deferring to maintainer for the final call. 中文说明置信度:3/5 — 审查干净,自上次审查以来有实质性改进,但 Stage 0 维护者关注升级(触及核心的 feat PR,约 2,961 生产行)需要维护者签字。 自上次审查以来,PR 有显著改进。八个后续提交不是表面修改——它们解决了真实的故障模式:transcript 文件轮换(文件身份跟踪)、过期流重放(sidecar 生命周期)、轮次级去重精度(runId)、错误时订阅者泄漏(subscribe 中的 try/finally),以及一个真实的 ALS 模型泄漏 bug(#7156)。 架构保持合理。核心 footprint 仍然很小(约 129 行)。所有 1,613 个单元测试通过。服务端路由正确响应。构建成功。 保持在 3/5 的原因:范围很大(66 个文件,约 5,300 行新增),人类维护者应验证架构决策。未发现阻塞问题。转交维护者做最终决定。 — Qwen Code · qwen3.7-max Reviewed at |
|
⏸️ Deferring to @tanzhenxin @wenshao — this Since the last review, 8 new commits substantially hardened the streaming state: round-level dedup via |
Review — subagent sessions in detail panelVerified at head Verdict: the architecture is right and most of the code is careful, but CI is legitimately red — all 4 failing tests are caused by this PR and reproduce locally. Details below. 🔴 Blocking — CI failures are real (reproduced at
|
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline. 1 Suggestion-level finding(s) could not be anchored to a changed line and were dropped; nothing further to act on here. Unresolved, please confirm: [Critical] Blocker #1 (Route drift guard): new subagent routes not in legacySessionTelemetryRoutes — still stands (verified: no 'subagent' matches in telemetry.ts) [Critical] Blocker #2 (Library-bundle boundary): createContext cap exceeded by new subagentDetailsContext + vaul — still stands (verified: subagentDetailsContext.tsx adds createContext) [Critical] Blocker #3 (Split-view drawer): useFloatingArtifactPanel routes ALL panel tabs to drawer in split view — still stands (verified: !canDockArtifactPanel || mainView === 'split') Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and did not run locally. Not reviewed: reverse audit — an auditor ran and opened its brief, but no agent was launched with the prompt the CLI built — the launch was written by hand, and what the agent was actually asked is not what this skill certifies.
— qwen3.7-max via Qwen Code /review
|
@qwen-code /takeover |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Not reviewed: reverse audit — an auditor ran and opened its brief, but no agent was launched with the prompt the CLI built — the launch was written by hand, and what the agent was actually asked is not what this skill certifies.
— qwen3.7-max via Qwen Code /review
|
Qwen Code review timed out. Qwen review timed out after 300 seconds (of the 180-minute budget). For large PRs, retry with a longer timeout by commenting: |
chiga0
left a comment
There was a problem hiding this comment.
Code Review Overview (AI Generated)
PR: #7380 — feat(web-shell): show subagent sessions in detail panel
Type: New Feature
Change size: +4766/-163 across 66 files
HEAD: a8de487e
Findings Summary
- Critical: 0
- Major: 1 (performance, not correctness)
- Minor: 2
- Nit: 2
Cross-Validation
| Finding | Other Reviewer | My Assessment |
|---|---|---|
| Critical: Route drift guard (subagent routes not in telemetry) | qwen-code-ci-bot | Resolved — both routes now in telemetry.ts, test counts updated to 50 |
Review
Comprehensive feature that moves subagent transcripts into dedicated detail sessions. Backend architecture is sound:
Auth/authz: Bearer token auth at app level, requireSessionRuntime for workspace isolation, virtual session ID parsing enforces prefix/length/regex validation.
Virtual session projection: Proper boundary checking via parseVirtualSubagentSessionId (prefix, length cap, base64url regex). Virtual contexts return minimal stubs without disk I/O.
Stream sidecar lifecycle: Correctly skips .stream reads for completed subagents (task.status !== 'running'). Terminal transition triggers final refresh, poll timer stopped, writer cleanup removes sidecar.
Metrics merging: Clear precedence — parent transcript execution summary overrides live bridge metrics for terminal sessions.
Major Finding
Cancel route performs unnecessary full resolution (routes/session.ts): The cancel route calls virtualSubagentSessions.resolve() which may load the entire parent transcript JSONL for legacy matching or metric extraction, just to obtain taskId. A dedicated resolveTaskId method that skips metric extraction would be more efficient. Not a correctness issue but noticeable for large parent transcripts.
Minor Findings
readParentToolCallMetricsloads entire parent JSONL: Could scan-and-stop after finding the matchingtoolCallResultrecord instead of reading the full file.- Replay state retention rationale undocumented: Bounded by 60s
TARGET_RETENTION_MSeviction, but a comment would help future readers.
Final Verdict
APPROVE. No correctness issues. Auth, workspace isolation, stream lifecycle, and metrics merging are all sound. The Major finding is a performance optimization suitable for follow-up.
This review was generated by QoderWork AI
Code review —
|
|
🤖 Reviewed the latest feedback — no changes needed. Why, point by point: No action required — all feedback verified as addressedEvery feedback point from this review round was already resolved in prior commits on this branch ( Critical / CHANGES_REQUESTED items (verified fixed)
Suggestions (all addressed or recorded)All 27 inline suggestions (
@wenshao maintainer review
Verification results (all green at HEAD
|
| Check | Result |
|---|---|
npm run build |
✅ |
npm run typecheck |
✅ |
npm run lint |
✅ |
build-artifact.test.ts |
8 passed |
telemetry-catalog.test.ts |
1 passed |
telemetry.test.ts |
50 passed |
App.test.tsx |
150 passed |
virtual-subagent-sessions.test.ts + server.test.ts |
777 passed |
agent-transcript.test.ts + background-agent-resume.test.ts |
67 passed |
| web-shell component tests (5 files) | 103 passed |
SDK tests (DaemonClient + daemonUi) |
556 passed |
DaemonSessionProvider.subagent.test.ts |
2 passed |
中文说明
无需操作 — 所有反馈已确认处理完毕
本轮审查中的每个反馈点均已在此分支的先前提交(28e5ef6e3、1d49e2784、57870cba5、7dec83a17)中解决。未进行新的代码更改。以下是完整分类。
严重 / CHANGES_REQUESTED 项(已验证修复)
| 发现 | 状态 | 证据 |
|---|---|---|
路由漂移守卫 — subagent 路由未登记到 legacySessionTelemetryRoutes |
已修复 | telemetry.ts 已注册两条路由;telemetry-catalog.test.ts 通过(1 个测试) |
库产物边界 — createContext 上限超标 |
已修复 | vaul 已在 vite.lib.config.ts 中外部化;build-artifact.test.ts 通过(8 个测试,≤3 上限成立) |
| 分屏抽屉 — 所有面板标签被路由到抽屉 | 已修复 | App.test.tsx 断言已更新为 document.body.textContent;150 个测试通过 |
iterate() 中非 ENOENT 刷新失败时的订阅者泄漏 |
已在 57870cba5 修复 |
订阅者生命周期置于 try/finally 内;EISDIR 回归测试通过 |
virtualSubagentSessions 为 undefined 时请求静默挂起 |
已在 57870cba5 修复 |
两条路由均返回结构化 404 |
建议(全部已处理或记录)
全部 27 条行内建议(rc:3619497311 至 rc:3622012634)均有作者回复:
- 21 条已修复(提交
28e5ef6e3/1d49e2784/57870cba5/7dec83a17):错误消息、键盘无障碍、路由测试、去重初始化标志、ENOENT 重置、文件缩小守卫、boundedString 去重、死属性移除、空对象守卫、terminateReason 投影、aria-expanded、status 联合类型、SubagentDetailsProvider 回退、findSubagentRootTool 覆盖、composerTasks 测试、MessageList DOM 测试、死 CSS、totalTokens 移除、投影输出守卫 - 4 条附证据拒绝:TOCTOU 竞态(JS 运行至完成模型阻止了该问题,×2)、poll-timer 测试(已被现有终态转换回归覆盖)、
vi.mock移除(测试从未包含该 mock) - 2 条有意保留:重试轮询节奏(面板挂载期间的恢复契约)、ENOENT 期间
completedStreamRounds保留(清除它会导致回放回归)
@wenshao 维护者审查
- 发现 1–7:已在
57870cba5修复(full 模式双重计数、回退状态重置、重连标题、测试稳定性、birthtimeMs 移除、编码/解析字符集、heartbeat/detach 运行时解析) - 发现 8(性能):有意保留 — 有界读取,更改节奏会扩大范围
- Nit 1(
subagent.detailsEmptyi18n 键):已移除(代码库中不存在) - Nit 2(
build.js预算注释):已更新为 "161KB to 166KB" - Nit 3(App/ChatPane 重复的 tab 提取逻辑):推迟 — 仅两个调用点,提取辅助函数带来的抽象收益有限;在此记录以保持可见性
验证结果(HEAD 7dec83a17 全部通过)
| 检查 | 结果 |
|---|---|
npm run build |
✅ |
npm run typecheck |
✅ |
npm run lint |
✅ |
build-artifact.test.ts |
8 通过 |
telemetry-catalog.test.ts |
1 通过 |
telemetry.test.ts |
50 通过 |
App.test.tsx |
150 通过 |
virtual-subagent-sessions.test.ts + server.test.ts |
777 通过 |
agent-transcript.test.ts + background-agent-resume.test.ts |
67 通过 |
| web-shell 组件测试(5 个文件) | 103 通过 |
SDK 测试(DaemonClient + daemonUi) |
556 通过 |
DaemonSessionProvider.subagent.test.ts |
2 通过 |
Base-conflict check: no conflict with main.
🧠 Handled by Qwen Code · model/模型 qwen3.8-max-preview
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline. Unresolved, please confirm: [Critical] packages/web-shell/client/build-artifact.test.ts — @wenshao blocker: createContext cap test may still fail (vaul externalized but cannot verify createContext count in built bundle without running the build) Not reviewed: reverse audit — an auditor ran and opened its brief, but no agent was launched with the prompt the CLI built — the launch was written by hand, and what the agent was actually asked is not what this skill certifies.
— qwen3.7-max via Qwen Code /review
|
🤖 Addressed the latest review feedback (round 1/100). What changed, and what I pushed back on: Review feedback addressedImplemented[rc:3622665092] [rc:3622665078] DrawerContent CSS specificity conflict (App.tsx) [rc:3622665051] [rc:3622665073] Accumulated subagent usage discarded by rawOutput replace (transcript.ts) [rc:3622665087] Initial resolve failure shows permanent error (SubagentDetail.tsx) Deferred[rc:3622665044] Truncated prompt in subagent detail panel [rc:3622665025] SSE route virtual subagent branch lacks route-level test [rc:3622665030] Virtual session context/heartbeat stubs lack positive-path route tests [rc:3622665038] SubagentDetail component lacks rendering tests Review-level comment[Critical] build-artifact.test.ts createContext cap Verification
中文说明已处理的审查反馈已实现[rc:3622665092] [rc:3622665078] DrawerContent CSS 优先级冲突(App.tsx) [rc:3622665051] [rc:3622665073] 累积的子代理用量被 rawOutput 替换丢弃(transcript.ts) [rc:3622665087] 初始解析失败显示永久错误(SubagentDetail.tsx) 延期处理[rc:3622665044] 子代理详情面板中提示词被截断 [rc:3622665025] SSE 路由虚拟子代理分支缺少路由级测试 [rc:3622665030] 虚拟会话 context/heartbeat 桩缺少正向路径路由测试 [rc:3622665038] SubagentDetail 组件缺少渲染测试 审查级别评论[Critical] build-artifact.test.ts createContext 上限 验证结果
Base-conflict check: no conflict with main. Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. 🧠 Handled by Qwen Code · model/模型 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed — no blockers. Suggestions are inline.
— qwen3.7-max via Qwen Code /review
|
🤖 Could not address the latest feedback automatically (round 2/100). A human should take over this PR. Review feedback addressed[rc:3623619851]
|
|
@qwen-code /triage |
|
@qwen-code /retry |
|
🔄 AutoFix re-armed. The next scan re-reads this PR's feedback from the start and the round counter resets. Nothing was deleted — this marker supersedes the evaluation markers above it. 中文说明🔄 已重新武装 AutoFix。下一次扫描会从头重新读取本 PR 的反馈,轮次计数也已重置。未删除任何内容 —— 本标记使其上方的评估标记失效。 |
|
Triage re-run completed without a new review. The stage comments above were updated with the latest result. View workflow run. |
|
🤖 Could not address the latest feedback automatically (round 1/100). A human should take over this PR. Review feedback round 4 — summaryImplementedrc:3622665025 — SSE route virtual subagent testAdded a route-level test in rc:3622665030 — Virtual session context/heartbeat positive-path testsAdded a route-level test that hits rc:3622665038 — SubagentDetail component rendering testsExtended Already fixed in current code (no action needed)
Why it was not pushed: build failed on the agent-committed fix Run log: https://github.com/QwenLM/qwen-code/actions/runs/29881394075 🧠 Handled by Qwen Code · model/模型 |
|
@qwen-code /retry |
|
🔄 AutoFix re-armed. The next scan re-reads this PR's feedback from the start and the round counter resets. Nothing was deleted — this marker supersedes the evaluation markers above it. 中文说明🔄 已重新武装 AutoFix。下一次扫描会从头重新读取本 PR 的反馈,轮次计数也已重置。未删除任何内容 —— 本标记使其上方的评估标记失效。 |
|
@qwen-code /review |
| _Qwen Code review request accepted. Review is queued in [workflow run](https://github.com/QwenLM/qwen-code/actions/runs/29884805075)._ |
Re-Review at HEAD
|
yiliang114
left a comment
There was a problem hiding this comment.
架构设计合理,虚拟 session + 独立 SSE 流的方案有效降低主会话内存压力。几个非阻塞建议:
findLegacyTaskByToolCall全量读 JSONL(virtual-subagent-sessions.ts~L800):旧 transcript 每次 resolve 都线性扫描整个父 session 文件,长会话下 I/O 开销大,建议加 LRU 缓存或限制扫描行数- 250ms 轮询偏激进(
POLL_INTERVAL_MS):多个并行子智能体时 I/O 压力显著,建议 500ms-1s 或考虑fs.watch getSubagentPrompt未 memoize(SubagentDetail.tsx~L90):每次 render 遍历 messages,建议移入useMemo- SSE 路由对虚拟 session 静默忽略
snapshot=1,重连场景可能丢状态,建议确认 - 设计文档(613 行)建议拆到独立 docs PR 或 wiki
以上为优化建议,不阻塞合入。
chiga0
left a comment
There was a problem hiding this comment.
Re-Review at HEAD d63571f8
Previous APPROVE was dismissed. Re-confirming after reviewing 37 new commits (mostly upstream merges, plus review feedback rounds 2 & 3).
No new concerns. Backend architecture remains sound: auth/authz via bearer token + requireSessionRuntime, virtual session ID validation, stream sidecar lifecycle, metrics merging with clear precedence. Cancel route performance (full resolution for taskId) is a follow-up optimization, not a blocker.
LGTM.
This review was generated by QoderWork AI
What this PR does
This PR moves subagent transcript details out of the main conversation flow. Agent task cards keep their status and summary in the main transcript, while selecting a task opens a dedicated detail surface backed by a full transcript load followed by an independent SSE stream. Wide layouts use the side panel and narrow or split layouts use a drawer. Parallel agent entries use the same detail path, active subagents can be cancelled independently, and approval UI remains above the detail surface.
The server exposes workspace-scoped subagent resolution and cancellation routes, projects persisted agent transcripts as virtual sessions, bounds retained replay state, and avoids reading terminal stream sidecars. Main-turn metrics combine main-agent usage with root subagent execution summaries without retaining subagent content in the parent transcript.
Why it is needed
Long subagent transcripts currently make the main conversation difficult to scan and increase parent-session memory pressure. They also lack the full session rendering experience, including streamed thinking, tools, approvals, and reconnect behavior. Loading each subagent as its own session keeps the main transcript compact while preserving complete details on demand.
Reviewer Test Plan
How to verify
Evidence (Before & After)
Before: subagent content is embedded in the main transcript and parallel agent rows do not provide the full session detail renderer.
After: the main transcript retains only task summaries and usage, while complete subagent sessions load and stream in a dedicated panel or drawer.
Tested on
Environment (optional)
Local workspace on Node.js 22. No Web Shell UI tests were run.
Risk & Scope
Linked Issues
N/A
Pictures
中文说明
本 PR 做了什么
本 PR 将子智能体的完整 transcript 从主会话消息流中移出。主消息流只保留任务状态和摘要,点击任务后通过全量 transcript load 加独立 SSE 的方式打开详情。宽屏使用侧边面板,窄屏和分屏使用抽屉。并行智能体复用同一详情链路,运行中的子智能体可以独立取消,权限审批界面保持在详情层之上。
服务端新增工作区范围内的子智能体解析和取消路由,将持久化的智能体 transcript 投影为虚拟 session,限制 replay 状态的长期保留,并且不再读取终态任务的 stream sidecar。主 turn 的指标会合并主智能体 usage 与根子智能体 execution summary,同时不会在父 transcript 中保留子智能体内容。
为什么需要
较长的子智能体 transcript 会让主会话难以阅读,并增加父会话的内存压力。同时,现有展示缺少完整 session 的流式 thinking、工具、审批和重连体验。将每个子智能体作为独立 session 按需加载,可以保持主会话精简,同时保留完整详情。
Reviewer 测试计划
如何验证
前后对比证据
修改前:子智能体内容嵌入主 transcript,并行智能体行无法打开完整 session 详情。
修改后:主 transcript 仅保留任务摘要和 usage,完整子智能体 session 在独立面板或抽屉中加载并流式更新。
测试环境
macOS 已完成服务端目标单测、SDK build/typecheck 和 Web Shell typecheck。Windows 与 Linux 未测试。未运行 Web Shell UI 测试。
风险与范围
关联 Issue
无。