feat(web): group consecutive tool-use cards (#604)

* feat(web): group consecutive tool-use cards

Add a web-only visible projection that groups consecutive root-level execution tools into expandable cards.
Keep approval and question tools standalone, reuse older-history loading on expand, and add regression coverage for grouping and UI behavior.

* fix(web): hydrate oldest visible tool group

Mark needsOlderHistory on the first visible grouped tool run even when earlier visible blocks are non-tool content, and add regression coverage for the boundary.

* fix(web): continue grouped history hydration

Decouple ToolGroupCard older-history chaining from the shared loading flag, invalidate stale hydration runs safely, and add regression coverage for multi-page hydration.

* fix(web): harden grouped tool hydration

- retry incomplete group hydration after transient pagination contention\n- keep approved and denied permissioned tool cards eligible for grouping\n- cover both regressions with targeted web tests

* fix(web): keep Codex permission cards standalone

- treat CodexPermission as a semantic grouping boundary even after approval\n- keep permissioned execution tools groupable while preserving permission milestones\n- add regression coverage for Codex permission eligibility and boundary behavior

* fix(web): narrow incomplete tool-group hydration

- only mark groups at the oldest visible boundary as needing older history\n- avoid auto-paginating complete groups behind text, standalone tools, or permission milestones\n- add regression coverage for the adjacent boundary cases
This commit is contained in:
junes
2026-05-11 09:25:49 +08:00
committed by GitHub
parent 77f6aae169
commit af3491e046
13 changed files with 1575 additions and 39 deletions
+22
View File
@@ -272,6 +272,28 @@ export default {
'tool.requestUserInput.textPlaceholder': 'Type your answer…',
'tool.requestUserInput.noteLabel': 'Additional note (optional)',
'tool.requestUserInput.notePlaceholder': 'Add a note…',
'toolGroup.title': 'Tool activity',
'toolGroup.primary.fileTargets': '{target} +{n}',
'toolGroup.primary.commandTargets': '{target} +{n}',
'toolGroup.primary.searchTargets': '{target} +{n}',
'toolGroup.primary.urlTargets': '{target} +{n}',
'toolGroup.primary.otherTargets': '{target} +{n}',
'toolGroup.summary.read': 'Read {n}',
'toolGroup.summary.mutation': 'Edit {n}',
'toolGroup.summary.command': 'Run {n}',
'toolGroup.summary.search': 'Search {n}',
'toolGroup.summary.web': 'Web {n}',
'toolGroup.summary.other': 'Tool {n}',
'toolGroup.badge.running': '{n} running',
'toolGroup.badge.pending': '{n} pending',
'toolGroup.badge.error': '{n} error',
'toolGroup.badge.fileTargets': '{n} files',
'toolGroup.toolCount': '{n} tool calls',
'toolGroup.loadingOlderHistory': 'Loading earlier tool activity…',
'toolGroup.historyUnavailable': 'Earlier tool activity is unavailable.',
'toolGroup.rowStatus.running': 'Running',
'toolGroup.rowStatus.pending': 'Pending',
'toolGroup.rowStatus.error': 'Error',
// Composer buttons
'composer.settings': 'Settings',