feat(web): collapse resolved approval rows
Resolved permission boxes vanish from the transcript instead of lingering as "answered" cards. When a turn has 2+ tools the resolved approval is absorbed into the tool group as a compact italic line; otherwise it is hidden entirely. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
bc0fd6ee60
commit
60e57fde31
+24
-16
@@ -402,13 +402,15 @@ export function createStructuredConnection(
|
||||
return el;
|
||||
}
|
||||
|
||||
/** Group tool rows (and intermediate agent text between them) by turn.
|
||||
* An agent_text/agent_thought row is "intermediate" when a tool row follows
|
||||
* it in the same turn — it gets absorbed into the group so the collapsed
|
||||
* block preserves chronological order. The *last* agent text with no
|
||||
* subsequent tool stays standalone (the prominent final answer).
|
||||
* Returns groups keyed by `turn:<userId>`, each with `toolCount` (for the
|
||||
* header label) and `rows` (tools + intermediate text, in order). */
|
||||
/** Group tool rows (and intermediate agent text / resolved approvals between
|
||||
* them) by turn. An agent_text/agent_thought row is "intermediate" when a
|
||||
* tool row follows it in the same turn — it gets absorbed into the group so
|
||||
* the collapsed block preserves chronological order. Resolved approval rows
|
||||
* (not the currently pending one) are absorbed the same way. The *last*
|
||||
* agent text with no subsequent tool stays standalone (the prominent final
|
||||
* answer). Returns groups keyed by `turn:<userId>`, each with `toolCount`
|
||||
* (for the header label) and `rows` (tools + intermediate text/approvals,
|
||||
* in order). */
|
||||
function activityGroupsByTurn(): Map<string, { toolCount: number; rows: TranscriptRow[] }> {
|
||||
// First: count tools per turn to know which turns qualify for grouping.
|
||||
const toolCounts = new Map<string, number>();
|
||||
@@ -422,33 +424,35 @@ export function createStructuredConnection(
|
||||
// Second: build groups with interleaved text for turns with 2+ tools.
|
||||
const groups = new Map<string, { toolCount: number; rows: TranscriptRow[] }>();
|
||||
turnId = "before-first-message";
|
||||
// Pending text rows that might be intermediate (not yet confirmed by a
|
||||
// Pending rows that might be intermediate (not yet confirmed by a
|
||||
// following tool). If no tool follows, they stay standalone.
|
||||
let pendingText: TranscriptRow[] = [];
|
||||
let pending: TranscriptRow[] = [];
|
||||
let currentGid = `turn:${turnId}`;
|
||||
for (const row of rows) {
|
||||
if (row.kind === "user") {
|
||||
turnId = row.id;
|
||||
currentGid = `turn:${turnId}`;
|
||||
pendingText = [];
|
||||
pending = [];
|
||||
continue;
|
||||
}
|
||||
const count = toolCounts.get(currentGid) ?? 0;
|
||||
if (count < 2) continue;
|
||||
if (row.kind === "agent_text" || row.kind === "agent_thought") {
|
||||
pendingText.push(row);
|
||||
const isIntermediateText = row.kind === "agent_text" || row.kind === "agent_thought";
|
||||
const isResolvedApproval = row.kind === "approval" && row.id !== pendingApprovalRowId;
|
||||
if (isIntermediateText || isResolvedApproval) {
|
||||
pending.push(row);
|
||||
continue;
|
||||
}
|
||||
if (row.kind === "tool_call" || row.kind === "tool_diff") {
|
||||
const group = groups.get(currentGid) ?? { toolCount: count, rows: [] };
|
||||
// Flush any pending text — a tool follows, so it's intermediate.
|
||||
group.rows.push(...pendingText);
|
||||
pendingText = [];
|
||||
// Flush any pending rows — a tool follows, so they're intermediate.
|
||||
group.rows.push(...pending);
|
||||
pending = [];
|
||||
group.rows.push(row);
|
||||
groups.set(currentGid, group);
|
||||
}
|
||||
}
|
||||
// pendingText at end of a turn = final text, stays outside (not flushed).
|
||||
// pending at end of a turn = final text/approvals, stays outside (not flushed).
|
||||
return groups;
|
||||
}
|
||||
|
||||
@@ -500,6 +504,10 @@ export function createStructuredConnection(
|
||||
children.push(groupEl);
|
||||
continue;
|
||||
}
|
||||
// Resolved approvals not absorbed into a tool group are hidden — the
|
||||
// tool row itself already identifies the action, so a standalone
|
||||
// "answered" card adds nothing. Pending approvals always render.
|
||||
if (row.kind === "approval" && row.id !== pendingApprovalRowId) continue;
|
||||
const rowEl = buildRowElement(row);
|
||||
if (!rowEl) continue;
|
||||
rowEls.set(row.id, rowEl);
|
||||
|
||||
Reference in New Issue
Block a user