feat(web): group consecutive tool-use cards#604
feat(web): group consecutive tool-use cards#604junxin367 wants to merge 7 commits intotiann:mainfrom
Conversation
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.
There was a problem hiding this comment.
Review mode: initial
Findings
- [Major]
needsOlderHistoryis only set when the grouped run starts at index 0, so a tool group that is the oldest visible group but follows a text/event block never auto-loads older pages when expanded. That breaks the promised oldest-incomplete-group hydration on pages that begin with non-tool content.web/src/chat/toolGroups.ts:254-265
Suggested fix:let sawGroup = false for (let index = 0; index < blocks.length; index += 1) { ... const needsOlderHistory = options.hasMoreMessages && !sawGroup sawGroup = true ... }
Summary
- Review mode: initial. One blocking behavior gap found; no other issues confirmed in the diff.
Testing
- Not run (bun is unavailable in this environment).
HAPI Bot
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.
There was a problem hiding this comment.
Review mode: follow-up after new commits
Findings
- [Major] Incomplete tool groups can stop hydrating after the first older-page request.
ToolGroupCardstarts a load, but the same effect depends onctx.isLoadingMoreMessages; when the shared loader flips that flag, React runs the cleanup and marks the in-flight request as cancelled. The eventual promise resolution then cannot clearisHydratingHistory, and the next effect pass returns early onisHydratingHistory, so a multi-page incomplete group can stay stuck instead of loading until its boundary is complete. Evidence:web/src/components/ToolCard/ToolGroupCard.tsx:174.
Suggested fix:useEffect(() => { if (!open || !props.block.needsOlderHistory || historyExhausted) return if (!ctx.hasMoreMessages) { setHistoryExhausted(true) return } let cancelled = false setIsHydratingHistory(true) void ctx.loadOlderMessagesPreservingScroll() .then((loaded) => { if (cancelled) return setIsHydratingHistory(false) if (!loaded) setHistoryExhausted(true) }) .catch(() => { if (cancelled) return setIsHydratingHistory(false) setHistoryExhausted(true) }) return () => { cancelled = true } }, [ open, props.block, ctx.hasMoreMessages, ctx.loadOlderMessagesPreservingScroll, historyExhausted, ])
Summary
- Review mode: follow-up after new commits. The prior bot finding about marking the oldest visible group appears addressed, but grouped expansion still has a remaining hydration regression for incomplete history.
Testing
- Not run (automation;
bunis unavailable in this environment:/bin/bash: bun: command not found).
HAPI Bot
Decouple ToolGroupCard older-history chaining from the shared loading flag, invalidate stale hydration runs safely, and add regression coverage for multi-page hydration.
…uping # Conflicts: # web/src/components/ToolCard/ToolCard.tsx
There was a problem hiding this comment.
Review mode: follow-up after new commits
Findings
- [Major]
ToolGroupCardtreats anyfalsefromloadOlderMessagesPreservingScroll()as exhausted history. That includes transientisLoadingMoreMessages/ initial-settling returns, so if a user expands an incomplete group while the thread is already paginating elsewhere, the card can mark itself exhausted and stop retrying after the in-flight load completes. Evidenceweb/src/components/ToolCard/ToolGroupCard.tsx:192. - [Major]
isInteractiveToolBlock()excludes every tool that carries apermissionobject, not just pending approval prompts. Approved or denied execution tools therefore never enter a group, which defeats the new collapsing behavior for common permissioned shell/edit calls. Evidenceweb/src/chat/toolGroups.ts:188.
Summary
Review mode: follow-up after new commits. The prior hydration-stall issue appears addressed, but the new grouping still has two regressions: a transient-load race in incomplete-group auto-hydration and an overly broad permission exclusion that keeps approved execution tools out of groups.
Testing
Not run (automation; bun unavailable in this environment).
- 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
There was a problem hiding this comment.
Review mode: follow-up after new commits
Findings
- [Major] Completed Codex permission cards can be collapsed into execution groups, so approval/denial milestones stop acting as standalone timeline boundaries.
CodexPermissionis emitted for Codex approval prompts (cli/src/codex/codexRemoteLauncher.ts:376) and has a dedicated permission presentation (web/src/components/ToolCard/knownTools.tsx:178), but the new grouping predicate only excludes pending permissions plus AskUserQuestion/request_user_input. Once the permission completes,block.tool.permission?.statusis no longerpending,CodexPermissionfalls throughisEligibleForToolGrouping, and consecutive permission + command cards can be hidden inside a collapsed group by default. Evidence:web/src/chat/toolGroups.ts:198.
Suggested fix:const INTERACTIVE_TOOL_NAMES = new Set([ 'CodexPermission', ]) function isInteractiveToolBlock(block: ToolCallBlock): boolean { return INTERACTIVE_TOOL_NAMES.has(block.tool.name) || block.tool.permission?.status === 'pending' || isAskUserQuestionToolName(block.tool.name) || isRequestUserInputToolName(block.tool.name) }
Summary
Review mode: follow-up after new commits. The previous hydration issue appears addressed, but the latest grouping predicate still lets completed Codex permission cards lose their standalone boundary.
Testing
Not run (automation; review only, and bun is not installed in this environment).
HAPI Bot
- 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
There was a problem hiding this comment.
Findings
- [Major] Only groups that start at the oldest visible boundary should be marked incomplete. The current
!sawVisibleGroupcheck also marks the first grouped run after visible text, user messages, permissions, or a single standalone tool asneedsOlderHistory; expanding that complete group then callsloadOlderMessagesPreservingScroll()and may keep pulling unrelated older pages until some earlier group appears or history is exhausted. Evidenceweb/src/chat/toolGroups.ts:260.
Suggested fix:const startsAtOldestVisibleBoundary = visibleBlocks.length === 0 const needsOlderHistory = options.hasMoreMessages && startsAtOldestVisibleBoundary
Summary
Review mode: follow-up after new commits. The prior Codex permission grouping issue is fixed, but the incomplete-history marker is still too broad and can trigger unnecessary auto-pagination from complete groups.
Testing
Not run (automation; review only, and PR code was not executed).
HAPI Bot
- 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
There was a problem hiding this comment.
Findings
No issues found.
Summary
Review mode: follow-up after new commits. The prior incomplete-history marker finding is addressed in web/src/chat/toolGroups.ts, and I did not find any new correctness, security, data-loss, performance, or maintainability issue in the latest diff. Residual risk: UI behavior was reviewed statically only; grouped-card browser smoke coverage is still dependent on CI/manual validation.
Testing
Not run (automation; bun is not installed in this runner).
HAPI Bot
Summary
Reason
Scope
Test
cd web && bun run test -- src/chat/toolGroups.test.ts src/components/ToolCard/ToolGroupCard.test.tsx src/components/AssistantChat/HappyThread.test.tsxcd web && bun run typecheckRisk / Rollback
Links
Reviewer Notes
web/src/chat/toolGroups.tsToolGroupCardandHappyThread