diff --git a/apps/desktop/src/components/assistant-ui/tool/fallback.test.ts b/apps/desktop/src/components/assistant-ui/tool/fallback.test.ts new file mode 100644 index 000000000000..008e701b23cf --- /dev/null +++ b/apps/desktop/src/components/assistant-ui/tool/fallback.test.ts @@ -0,0 +1,13 @@ +import { describe, expect, it } from 'vitest' + +import { shouldBoundToolGroup } from './fallback' + +describe('shouldBoundToolGroup', () => { + it('bounds long runs of ordinary tool calls', () => { + expect(shouldBoundToolGroup(3, false)).toBe(true) + }) + + it('never bounds a run containing clarify', () => { + expect(shouldBoundToolGroup(3, true)).toBe(false) + }) +}) diff --git a/apps/desktop/src/components/assistant-ui/tool/fallback.tsx b/apps/desktop/src/components/assistant-ui/tool/fallback.tsx index a501b7c9ee0e..f40ff7693f50 100644 --- a/apps/desktop/src/components/assistant-ui/tool/fallback.tsx +++ b/apps/desktop/src/components/assistant-ui/tool/fallback.tsx @@ -611,6 +611,10 @@ function ToolEntry({ part }: ToolEntryProps) { // auto-scrolling window; fewer than this stays a plain inline stack. const TOOL_GROUP_SCROLL_THRESHOLD = 3 +export function shouldBoundToolGroup(childCount: number, containsClarify: boolean) { + return childCount >= TOOL_GROUP_SCROLL_THRESHOLD && !containsClarify +} + // Pin-to-bottom + top-fade for the bounded tool window. Pins the newest row on // growth (a call lands or a row expands) unless the user scrolled up, and fades // the top edge once anything sits above it. Mirrors ThinkingDisclosure's live @@ -678,13 +682,21 @@ function useToolWindow(enabled: boolean) { */ export const ToolGroupSlot: FC> = ({ children, + endIndex, startIndex }) => { const messageId = useAuiState(s => s.message.id) const messageRunning = useAuiState(selectMessageRunning) + + const containsClarify = useAuiState(s => + s.message.parts + .slice(Math.max(0, startIndex), endIndex + 1) + .some(part => part.type === 'tool-call' && part.toolName === 'clarify') + ) + const enterRef = useEnterAnimation(messageRunning, `tool-group:${messageId}:${startIndex}`) - const bounded = Children.count(children) >= TOOL_GROUP_SCROLL_THRESHOLD + const bounded = shouldBoundToolGroup(Children.count(children), containsClarify) const { contentRef, faded, onScroll, scrollRef } = useToolWindow(bounded) return (