Stage 302: PR #1725 — fix: simplify compact activity summaries by @Michaelyklam

This commit is contained in:
test
2026-05-06 06:27:14 +00:00
6 changed files with 27 additions and 21 deletions

View File

@@ -140,7 +140,7 @@ Use almost no shadows in the transcript. Shadows are reserved for popovers, drop
### Tool/thinking activity group
Collapsed by default in settled history and during live runs. Summary line uses one disclosure for internals, e.g. `Activity: thinking + 4 tools · read_file, patch, terminal`. Expanding reveals thinking and individual tool cards together. Thinking and tools should not create separate transcript rows unless there is an error or approval state that needs attention.
Collapsed by default in settled history and during live runs. Summary line uses one disclosure for internals and stays intentionally terse, e.g. `Activity: 4 tools`. It should not repeat the always-present thinking area, list individual tool names, or add a second trailing count badge. Expanding reveals thinking and individual tool cards together. Thinking and tools should not create separate transcript rows unless there is an error or approval state that needs attention.
### Tool card

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -1753,9 +1753,7 @@ body.resizing{user-select:none;cursor:col-resize;}
.tool-call-group-summary{width:100%;display:flex;align-items:center;gap:var(--space-2);padding:var(--space-1) var(--space-3);border:0;background:transparent;color:var(--muted);cursor:pointer;text-align:left;font:inherit;font-size:var(--font-size-xs);line-height:1.4;border-radius:var(--radius-card);}
.tool-call-group-summary:hover{background:var(--surface-subtle-hover);color:var(--text);}
.tool-call-group-label{font-weight:600;color:var(--muted);}
.tool-call-group-list{opacity:.72;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.tool-call-group-duration{margin-left:auto;opacity:.62;font-variant-numeric:tabular-nums;white-space:nowrap;}
.tool-call-group-count{opacity:.56;font-variant-numeric:tabular-nums;}
.tool-call-group-chevron{opacity:.45;display:inline-flex;transition:transform .16s ease;}
.tool-call-group:not(.tool-call-group-collapsed) .tool-call-group-chevron{transform:rotate(90deg);}
.tool-call-group-body{display:block;padding-left:var(--space-3);}

View File

@@ -3805,7 +3805,7 @@ function ensureActivityGroup(inner, opts){
group.setAttribute('data-tool-call-group','1');
group.setAttribute('data-agent-activity-group','1');
if(live) group.setAttribute('data-live-tool-call-group','1');
group.innerHTML=`<button type="button" class="tool-call-group-summary" aria-expanded="${collapsed?'false':'true'}" onclick="const g=this.closest('.tool-call-group');const c=g.classList.toggle('tool-call-group-collapsed');this.setAttribute('aria-expanded',String(!c));if(typeof _onLiveActivityToggle==='function')_onLiveActivityToggle(g);"><span class="tool-call-group-chevron">${li('chevron-right',12)}</span><span class="tool-call-group-label">Activity</span><span class="tool-call-group-list">tools / thinking</span><span class="tool-call-group-duration"></span><span class="tool-call-group-count">0</span></button><div class="tool-call-group-body"></div>`;
group.innerHTML=`<button type="button" class="tool-call-group-summary" aria-expanded="${collapsed?'false':'true'}" onclick="const g=this.closest('.tool-call-group');const c=g.classList.toggle('tool-call-group-collapsed');this.setAttribute('aria-expanded',String(!c));if(typeof _onLiveActivityToggle==='function')_onLiveActivityToggle(g);"><span class="tool-call-group-chevron">${li('chevron-right',12)}</span><span class="tool-call-group-label">Activity</span><span class="tool-call-group-duration"></span></button><div class="tool-call-group-body"></div>`;
const anchor=opts.anchor||null;
if(anchor&&anchor.parentElement===inner) anchor.insertAdjacentElement('afterend', group);
else inner.appendChild(group);
@@ -4890,27 +4890,12 @@ function _syncToolCallGroupSummary(group){
if(!group) return;
const cards=Array.from(group.querySelectorAll('.tool-card-row .tool-card'));
const toolCount=cards.length;
const thinkingCount=group.querySelectorAll('.agent-activity-thinking .thinking-card').length;
const names=cards.map(card=>{
const el=card.querySelector('.tool-card-name');
return el?String(el.textContent||'').trim():'';
}).filter(Boolean);
const uniqueNames=[...new Set(names)];
const label=group.querySelector('.tool-call-group-label');
const list=group.querySelector('.tool-call-group-list');
const badge=group.querySelector('.tool-call-group-count');
const durationEl=group.querySelector('.tool-call-group-duration');
const parts=[];
if(thinkingCount) parts.push('thinking');
if(uniqueNames.length) parts.push(uniqueNames.slice(0,5).join(', ')+(uniqueNames.length>5?'…':''));
const total=toolCount+thinkingCount;
if(label){
if(thinkingCount&&toolCount) label.textContent=`Activity: thinking + ${toolCount} tool${toolCount===1?'':'s'}`;
else if(thinkingCount) label.textContent='Activity: thinking';
else if(toolCount) label.textContent=`Activity: ${toolCount} tool${toolCount===1?'':'s'}`;
if(toolCount) label.textContent=`Activity: ${toolCount} tool${toolCount===1?'':'s'}`;
else label.textContent='Activity';
}
if(list) list.textContent=parts.join(' · ')||'tools / thinking';
if(durationEl){
if(group.getAttribute('data-live-tool-call-group')==='1'){
const activeText=_activityElapsedLabel(group);
@@ -4924,7 +4909,6 @@ function _syncToolCallGroupSummary(group){
durationEl.style.display=durationText?'':'none';
}
}
if(badge) badge.textContent=String(total);
}
// ── Live tool card helpers (called during SSE streaming) ──

View File

@@ -128,6 +128,30 @@ class TestToolCallGroupingStatic:
"The expand/collapse control must expose aria-expanded."
)
def test_activity_summary_omits_redundant_trailing_count_badge(self):
helper = _function_body(UI_JS, "ensureActivityGroup")
sync_fn = _function_body(UI_JS, "_syncToolCallGroupSummary")
assert "tool-call-group-count" not in helper, (
"Compact Activity summaries already state tool counts in the label; "
"do not render a second trailing count badge."
)
assert "tool-call-group-count" not in sync_fn, (
"The summary sync path should not update a hidden/removed trailing count badge."
)
def test_activity_summary_keeps_header_compact_without_tool_names_or_thinking_prefix(self):
helper = _function_body(UI_JS, "ensureActivityGroup")
sync_fn = _function_body(UI_JS, "_syncToolCallGroupSummary")
assert "tool-call-group-list" not in helper, (
"The compact Activity row should not allocate a secondary tool-name/thinking summary span."
)
assert "tool-call-group-list" not in sync_fn, (
"The summary sync path should not populate a redundant tool-name/thinking list."
)
assert "Activity: thinking +" not in sync_fn, (
"When tools are present, thinking is expected and should not be repeated in the label."
)
def test_live_tool_cards_use_grouping_only_when_simplified(self):
live_fn = _function_body(UI_JS, "appendLiveToolCard")
settled_fn = _function_body(UI_JS, "renderMessages")