fix(web): render the subagent expansion below the tool call's own content (#33)

Co-authored-by: Alice <alice@prismshadow.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Yaowei Zheng
2026-07-23 00:43:47 +08:00
committed by GitHub
parent 829ca57a43
commit 9a1257b2be
2 changed files with 30 additions and 13 deletions
+16
View File
@@ -84,6 +84,22 @@ test("subagent card survives a reload; child session title is generated from its
// Under live streaming, the child session card is nested inside the run_subagent tool card.
await openSubagent();
// --- DOM order: the subagent expansion renders BELOW the tool's own content ---
// Expand the run_subagent tool card itself so its arguments block is in the DOM, then assert
// the child-session card comes after it in document order (it used to render between the tool
// header and the expanded arguments/output).
const toolRow = page.locator("button[aria-expanded]").filter({ hasText: "run_subagent" }).first();
await toolRow.click();
await expect(toolRow).toHaveAttribute("aria-expanded", "true");
const argsPre = page.locator("pre", { hasText: '"prompt"' }).first();
await expect(argsPre).toBeVisible();
const subagentBtn = page.getByRole("button", { name: /子会话/ }).first();
const cardFollowsArgs = await argsPre.evaluate(
(pre, card) => Boolean(pre.compareDocumentPosition(card) & Node.DOCUMENT_POSITION_FOLLOWING),
await subagentBtn.elementHandle(),
);
expect(cardFollowsArgs, "subagent expansion renders below the tool arguments/output").toBe(true);
// --- Must still hold after reload (the fix's goal: parent Trace's child session pointer + server-side expansion) ---
await page.reload();
await openSubagent();
@@ -1,7 +1,8 @@
/**
* Tool call card: collapses to a single line by
* default — status icon + tool name + duration (a live-ticking timer while running) + status
* badge; clicking expands full arguments, output, and any nested subagent.
* badge; clicking expands full arguments and output; a nested subagent renders below them
* regardless of collapsed state.
* The pending-approval row is always visible regardless of collapsed state; when a pending
* approval appears anywhere in a nested subagent chain, the card auto-expands once (respecting
* the user's choice if they've manually collapsed it since).
@@ -194,18 +195,6 @@ export function ToolCallCard({ item, ctx }: { item: ToolCallItem; ctx: StreamRen
</div>
)}
{/* Subagent card: always visible (not hidden after completion, only collapsed by default), unaffected by the tool card's collapsed state. */}
{item.subagent && (
<div className="px-3 pb-2">
<SubagentCard
sessionId={item.subagentSessionId ?? ""}
model={item.subagent}
running={!item.outputComplete}
ctx={ctx}
/>
</div>
)}
{/* Expanded details: full arguments / output */}
{open && (
<div className="anim-fade">
@@ -238,6 +227,18 @@ export function ToolCallCard({ item, ctx }: { item: ToolCallItem; ctx: StreamRen
)}
</div>
)}
{/* Subagent card: always visible (not hidden after completion, only collapsed by default), unaffected by the tool card's collapsed state. Rendered below the expanded arguments/output so the nested conversation reads after the tool call's own content, not between the header and its details; pt-2 keeps a gap from the tinted args/output blocks above. */}
{item.subagent && (
<div className="px-3 pb-2 pt-2">
<SubagentCard
sessionId={item.subagentSessionId ?? ""}
model={item.subagent}
running={!item.outputComplete}
ctx={ctx}
/>
</div>
)}
</div>
);
}