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:
2 files changed
+30
-13
No files matched your search
@@ -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.
|
// Under live streaming, the child session card is nested inside the run_subagent tool card.
|
||||||
await openSubagent();
|
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) ---
|
// --- Must still hold after reload (the fix's goal: parent Trace's child session pointer + server-side expansion) ---
|
||||||
await page.reload();
|
await page.reload();
|
||||||
await openSubagent();
|
await openSubagent();
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* Tool call card: collapses to a single line by
|
* Tool call card: collapses to a single line by
|
||||||
* default — status icon + tool name + duration (a live-ticking timer while running) + status
|
* 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
|
* 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
|
* 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).
|
* 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>
|
</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 */}
|
{/* Expanded details: full arguments / output */}
|
||||||
{open && (
|
{open && (
|
||||||
<div className="anim-fade">
|
<div className="anim-fade">
|
||||||
@@ -238,6 +227,18 @@ export function ToolCallCard({ item, ctx }: { item: ToolCallItem; ctx: StreamRen
|
|||||||
)}
|
)}
|
||||||
</div>
|
</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>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user