@athenaintel/react 0.39.0 → 0.40.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -3
- package/dist/agent-runtime/src/errors.cjs +8 -0
- package/dist/agent-runtime/src/errors.cjs.map +1 -1
- package/dist/agent-runtime/src/errors.js +8 -0
- package/dist/agent-runtime/src/errors.js.map +1 -1
- package/dist/agent-runtime/src/messages.cjs +76 -16
- package/dist/agent-runtime/src/messages.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.js +76 -16
- package/dist/agent-runtime/src/messages.js.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.cjs +15 -0
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.js +15 -0
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/assets/use-asset-content.cjs +127 -0
- package/dist/assets/use-asset-content.cjs.map +1 -0
- package/dist/assets/use-asset-content.d.ts +60 -0
- package/dist/assets/use-asset-content.js +127 -0
- package/dist/assets/use-asset-content.js.map +1 -0
- package/dist/chat/AthenaChat.cjs +24 -10
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.js +25 -11
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/run-activity.cjs +29 -10
- package/dist/chat/run-activity.cjs.map +1 -1
- package/dist/chat/run-activity.d.ts +30 -4
- package/dist/chat/run-activity.js +29 -10
- package/dist/chat/run-activity.js.map +1 -1
- package/dist/chat/super-grouping/CollapsibleGroup.cjs +16 -8
- package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
- package/dist/chat/super-grouping/CollapsibleGroup.d.ts +26 -1
- package/dist/chat/super-grouping/CollapsibleGroup.js +16 -8
- package/dist/chat/super-grouping/CollapsibleGroup.js.map +1 -1
- package/dist/chat/super-grouping/GroupedMessageParts.cjs +59 -0
- package/dist/chat/super-grouping/GroupedMessageParts.cjs.map +1 -0
- package/dist/chat/super-grouping/GroupedMessageParts.d.ts +25 -0
- package/dist/chat/super-grouping/GroupedMessageParts.js +59 -0
- package/dist/chat/super-grouping/GroupedMessageParts.js.map +1 -0
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +9 -5
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +2 -1
- package/dist/chat/super-grouping/SuperGroupingCard.js +13 -9
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +10 -6
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.js +14 -10
- package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
- package/dist/chat/super-grouping/grouped-part-keys.cjs +104 -0
- package/dist/chat/super-grouping/grouped-part-keys.cjs.map +1 -0
- package/dist/chat/super-grouping/grouped-part-keys.d.ts +37 -0
- package/dist/chat/super-grouping/grouped-part-keys.js +104 -0
- package/dist/chat/super-grouping/grouped-part-keys.js.map +1 -0
- package/dist/chat/super-grouping/index.cjs +2 -0
- package/dist/chat/super-grouping/index.cjs.map +1 -1
- package/dist/chat/super-grouping/index.d.ts +3 -1
- package/dist/chat/super-grouping/index.js +2 -0
- package/dist/chat/super-grouping/index.js.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.cjs +25 -19
- package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.d.ts +5 -0
- package/dist/chat-ui/composer/tiptap-composer.js +26 -20
- package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
- package/dist/composer/clipboard.cjs +16 -0
- package/dist/composer/clipboard.cjs.map +1 -1
- package/dist/composer/clipboard.d.ts +9 -0
- package/dist/composer/clipboard.js +17 -1
- package/dist/composer/clipboard.js.map +1 -1
- package/dist/diagnostics/errors.cjs +6 -0
- package/dist/diagnostics/errors.cjs.map +1 -1
- package/dist/diagnostics/errors.d.ts +6 -0
- package/dist/diagnostics/errors.js +6 -0
- package/dist/diagnostics/errors.js.map +1 -1
- package/dist/index.cjs +23 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/use-document-active.cjs +40 -0
- package/dist/lib/use-document-active.cjs.map +1 -0
- package/dist/lib/use-document-active.d.ts +9 -0
- package/dist/lib/use-document-active.js +40 -0
- package/dist/lib/use-document-active.js.map +1 -0
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/runtime/statewire-lifecycle.cjs +8 -0
- package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
- package/dist/runtime/statewire-lifecycle.js +9 -1
- package/dist/runtime/statewire-lifecycle.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/threads/Inbox.cjs +6 -2
- package/dist/threads/Inbox.cjs.map +1 -1
- package/dist/threads/Inbox.js +6 -2
- package/dist/threads/Inbox.js.map +1 -1
- package/dist/threads/mark-viewed-thread-read.cjs +97 -0
- package/dist/threads/mark-viewed-thread-read.cjs.map +1 -0
- package/dist/threads/mark-viewed-thread-read.d.ts +7 -0
- package/dist/threads/mark-viewed-thread-read.js +97 -0
- package/dist/threads/mark-viewed-thread-read.js.map +1 -0
- package/dist/tools/index.cjs +7 -0
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.js +7 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/inline-tools.cjs +10 -0
- package/dist/tools/inline-tools.cjs.map +1 -0
- package/dist/tools/inline-tools.d.ts +2 -0
- package/dist/tools/inline-tools.js +10 -0
- package/dist/tools/inline-tools.js.map +1 -0
- package/dist/tools/test-recording-report.cjs +175 -0
- package/dist/tools/test-recording-report.cjs.map +1 -0
- package/dist/tools/test-recording-report.d.ts +82 -0
- package/dist/tools/test-recording-report.js +175 -0
- package/dist/tools/test-recording-report.js.map +1 -0
- package/dist/tools/test-recording-tool-uis.cjs +498 -0
- package/dist/tools/test-recording-tool-uis.cjs.map +1 -0
- package/dist/tools/test-recording-tool-uis.d.ts +32 -0
- package/dist/tools/test-recording-tool-uis.js +498 -0
- package/dist/tools/test-recording-tool-uis.js.map +1 -0
- package/dist/tools/tool-summary.cjs +49 -1
- package/dist/tools/tool-summary.cjs.map +1 -1
- package/dist/tools/tool-summary.js +49 -1
- package/dist/tools/tool-summary.js.map +1 -1
- package/dist/tools/tool-uis.cjs +6 -1
- package/dist/tools/tool-uis.cjs.map +1 -1
- package/dist/tools/tool-uis.js +6 -1
- package/dist/tools/tool-uis.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SuperGroupingTranscript.cjs","sources":["../../../src/chat/super-grouping/SuperGroupingTranscript.tsx"],"sourcesContent":["'use client';\n\nimport { isInlineTool as isRegistryInlineTool } from '@athenaintel/agent-runtime';\nimport {\n getExternalStoreMessages,\n MessagePrimitive,\n type TextMessagePartComponent,\n type ThreadAssistantMessagePart,\n useAuiState,\n} from '@assistant-ui/react';\nimport { AlertCircle, Check, ChevronRight, Circle, LoaderCircle } from 'lucide-react';\nimport { memo, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { cn } from '../../lib/utils';\nimport { StepText } from '../../tools/step-text';\nimport { ToolFallback } from '../../tools/tool-fallback';\nimport { collectAssetTitles } from '../../tools/tool-summary';\nimport { readMessageCreatedAt } from '../message-time';\nimport {\n type ActivityPhase,\n buildActivityTimeline,\n countActivityTools,\n excludePartsFromGroups,\n getActivitySummary,\n resolveActivityPhase,\n} from './activity-timeline';\nimport { CollapsibleGroup, SuperGroupingProvider } from './CollapsibleGroup';\nimport { createToolBasedGroupingFunction, type GroupingFunction } from './grouping-function';\nimport { type SuperGroupingCardProps, useActivityExpansion } from './SuperGroupingCard';\nimport { ToolTimeline } from './ToolTimeline';\nimport { type TimelineStep, toTimelineStep } from './timeline-step';\nimport { defaultGetToolGroupKey } from './toolkit-map';\nimport {\n scopeGroupingToSegment,\n splitTurnSegments,\n summarizeSegment,\n type TurnSegment,\n} from './turn-segments';\nimport {\n firstSeenMs,\n formatWorkDuration,\n observedTurnEndMs,\n readTurnTiming,\n recordObservedTurnEnd,\n type TurnTiming,\n workedDurationMs,\n workingLabel,\n} from './turn-timing';\n\nconst DEFAULT_MAX_VISIBLE_STEPS = 6;\nconst EMPTY_CONTENT: readonly ThreadAssistantMessagePart[] = [];\nconst EMPTY_STEPS: readonly TimelineStep[] = [];\n\nexport interface SuperGroupingTranscriptProps\n extends Pick<\n SuperGroupingCardProps,\n | 'toolUIs'\n | 'ToolFallback'\n | 'TextComponent'\n | 'ReasoningComponent'\n | 'GroupComponent'\n | 'getToolGroupKey'\n | 'groupingFunction'\n | 'isInlineTool'\n | 'waitingTools'\n | 'passThroughTools'\n | 'waitingForInput'\n | 'resolveToolDisplayName'\n | 'expansionKey'\n | 'expandWhileWaiting'\n | 'mountDetails'\n | 'summaryDetails'\n | 'renderHeaderActions'\n | 'renderRunningMeta'\n | 'className'\n > {\n /** Steps an opened segment lists before older ones fold away; unresolved calls always show. */\n maxVisibleSteps?: number;\n classNames?: {\n root?: string;\n header?: string;\n body?: string;\n details?: string;\n /** The flex column a segment's parts render in; override its gap here. */\n detailsParts?: string;\n };\n}\n\n// ─── Turn timing ───────────────────────────────────────────────────────\n\n/**\n * The turn's stamps: the prompt it answers, its joined metadata, and the raw\n * messages behind it. Reads the whole message (the bound raw messages hang off\n * it), so only the small header status subscribes here, never the transcript.\n */\nfunction useTurnTimingSources(): { timing: TurnTiming; clockKey: string } {\n const message = useAuiState((s) => s.message);\n const promptCreatedAt = useAuiState((s) => {\n const previous = s.thread.messages[s.message.index - 1];\n return previous?.role === 'user' ? readMessageCreatedAt(previous.metadata?.custom) : null;\n });\n const promptId = useAuiState((s) => {\n const previous = s.thread.messages[s.message.index - 1];\n return previous?.role === 'user' ? previous.id : '';\n });\n const timing = useMemo(\n () =>\n readTurnTiming({\n promptCreatedAt,\n custom: message.metadata?.custom,\n sourceMessages: getExternalStoreMessages<unknown>(message),\n }),\n [message, promptCreatedAt],\n );\n return { timing, clockKey: `${promptId}:${message.id}` };\n}\n\n/** \"Working for 1m 12s\", re-rendered once a second by itself so the transcript does not. */\nfunction WorkingFor({ startMs, clockKey }: { startMs: number | null; clockKey: string }) {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(timer);\n }, []);\n const anchor = startMs ?? firstSeenMs(clockKey, now);\n return <>{workingLabel(Math.max(0, now - anchor))}</>;\n}\n\n/**\n * The header's words: \"Working for 1m 12s\" while the turn runs, \"Worked for\n * 2m 30s · Used 7 tools\" once done, \"Waiting for you\", or how it ended.\n */\nfunction TurnStatus({\n phase,\n cancelled,\n activitySummary,\n toolCount,\n summaryDetails,\n}: {\n phase: ActivityPhase;\n cancelled: boolean;\n activitySummary: string;\n toolCount: number;\n summaryDetails: readonly string[] | undefined;\n}) {\n const { timing, clockKey } = useTurnTimingSources();\n const [observedEndMs, setObservedEndMs] = useState(() => observedTurnEndMs(clockKey));\n const wasActive = useRef(phase === 'running' || phase === 'waiting');\n useEffect(() => {\n const active = phase === 'running' || phase === 'waiting';\n if (wasActive.current && !active) setObservedEndMs(recordObservedTurnEnd(clockKey));\n wasActive.current = active;\n }, [phase, clockKey]);\n if (phase === 'running') return <WorkingFor startMs={timing.startMs} clockKey={clockKey} />;\n if (phase === 'waiting') return <>Waiting for you</>;\n const workedMs = workedDurationMs(timing, observedEndMs);\n if (phase === 'error') {\n if (!cancelled) return <>Something went wrong</>;\n return <>{workedMs !== null ? `Run stopped after ${formatWorkDuration(workedMs)}` : 'Run stopped'}</>;\n }\n const label = [\n ...(workedMs !== null ? [`Worked for ${formatWorkDuration(workedMs)}`] : []),\n ...(workedMs === null || toolCount > 0 || activitySummary !== 'Reasoning complete' ? [activitySummary] : []),\n ...(summaryDetails ?? []),\n ].join(' · ');\n return <>{label}</>;\n}\n\nfunction TurnGlyph({ phase }: { phase: ActivityPhase }) {\n const className = 'size-3.5 shrink-0';\n if (phase === 'running') {\n return <LoaderCircle aria-hidden=\"true\" className={cn(className, 'motion-safe:animate-spin')} />;\n }\n if (phase === 'waiting') {\n return <Circle aria-hidden=\"true\" className={cn(className, 'text-amber-600 dark:text-amber-400')} />;\n }\n if (phase === 'error') {\n return <AlertCircle aria-hidden=\"true\" className={cn(className, 'text-destructive')} />;\n }\n return <Check aria-hidden=\"true\" className={cn(className, 'opacity-70')} />;\n}\n\n// ─── Segments ──────────────────────────────────────────────────────────\n\nconst ProseSegment = memo(function ProseSegment({\n text,\n TextComponent,\n}: {\n text: string;\n TextComponent: TextMessagePartComponent;\n}) {\n return (\n <div data-slot=\"transcript-prose\" className=\"min-w-0\">\n <TextComponent type=\"text\" text={text} status={{ type: 'complete' }} />\n </div>\n );\n});\n\ninterface ActivitySegmentProps {\n segment: Extract<TurnSegment, { kind: 'activity' }>;\n steps: readonly TimelineStep[];\n turnPhase: ActivityPhase;\n expansionKey: string;\n expandWhileWaiting: boolean;\n mountDetails: boolean;\n maxVisibleSteps: number;\n grouping: GroupingFunction;\n /** This segment's inline tool calls (an editable draft), rendered outside its disclosures. */\n inlineParts: readonly { index: number; key: string }[];\n /** False when every step's UI renders inline, so there is nothing behind \"Show tool details\". */\n hasDetails: boolean;\n components: Parameters<typeof MessagePrimitive.Unstable_PartsGrouped>[0]['components'];\n classNames: SuperGroupingTranscriptProps['classNames'];\n}\n\n/**\n * One collapsed run of work between two of the agent's sentences: the step in\n * progress (or the last one taken) on one line, the segment's steps when\n * opened, and the tool UIs of just this segment behind \"Show tool details\".\n * The tool UIs stay mounted (hidden) while the turn is live so their effects\n * run, as in `SuperGroupingCard`.\n */\nfunction ActivitySegment({\n segment,\n steps,\n turnPhase,\n expansionKey,\n expandWhileWaiting,\n mountDetails,\n maxVisibleSteps,\n grouping,\n inlineParts,\n hasDetails,\n components,\n classNames,\n}: ActivitySegmentProps) {\n const summary = summarizeSegment(steps);\n const phase = summary.phase;\n const { expanded, toggleExpanded } = useActivityExpansion({\n expansionKey: `${expansionKey}:${segment.key}`,\n phase,\n expandWhileWaiting,\n });\n const { expanded: detailsExpanded, toggleExpanded: toggleDetails } = useActivityExpansion({\n expansionKey: `${expansionKey}:${segment.key}:details`,\n phase,\n expandWhileWaiting,\n });\n const indicesKey = segment.partIndices.join(',');\n const scopedGrouping = useMemo(\n () => scopeGroupingToSegment(grouping, indicesKey.split(',').map(Number)),\n [grouping, indicesKey],\n );\n const groupingContext = useMemo(() => ({ groupingFunction: scopedGrouping }), [scopedGrouping]);\n const detailsPanelId = `aui-sg-segment-${useId().replace(/[^A-Za-z0-9_-]/g, '')}`;\n\n const isTurnActive = turnPhase === 'running' || turnPhase === 'waiting';\n const detailsMounted = isTurnActive || mountDetails || (expanded && detailsExpanded);\n const hasToolSteps = steps.some((step) => step.kind === 'tool');\n const meta = [summary.step?.chip, summary.meta].filter(Boolean).join(' · ');\n\n // Parts with no step of their own (an image the agent produced) are content, not work.\n if (steps.length === 0) {\n return (\n <div data-slot=\"transcript-parts\" className={cn('flex min-w-0 flex-col gap-2', classNames?.detailsParts)}>\n <SuperGroupingProvider value={groupingContext}>\n <MessagePrimitive.Unstable_PartsGrouped groupingFunction={scopedGrouping} components={components} />\n </SuperGroupingProvider>\n </div>\n );\n }\n\n return (\n <div data-slot=\"activity-segment\" data-phase={phase} data-segment-key={segment.key} className=\"min-w-0\">\n <ToolTimeline\n steps={steps}\n open={expanded}\n onOpenChange={toggleExpanded}\n label={<StepText text={summary.label} code={summary.step?.code} />}\n labelTitle={summary.step?.detail}\n phase={phase}\n maxVisibleSteps={maxVisibleSteps}\n keepMounted={isTurnActive || mountDetails}\n meta={meta ? <span data-slot=\"activity-segment-meta\">{meta}</span> : null}\n >\n {hasDetails ? (\n <div className=\"min-w-0 pl-5\">\n <button\n type=\"button\"\n onClick={toggleDetails}\n aria-expanded={detailsExpanded}\n aria-controls={detailsPanelId}\n className=\"flex items-center gap-1.5 rounded py-1 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronRight\n aria-hidden=\"true\"\n className={cn(\n 'size-3 transition-transform motion-reduce:transition-none',\n detailsExpanded && 'rotate-90',\n )}\n />\n {detailsExpanded\n ? hasToolSteps\n ? 'Hide tool details'\n : 'Hide thinking'\n : hasToolSteps\n ? 'Show tool details'\n : 'Show thinking'}\n </button>\n {detailsMounted ? (\n <section\n id={detailsPanelId}\n aria-label=\"Step details\"\n hidden={!expanded || !detailsExpanded}\n className={cn(\n 'min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3',\n classNames?.details,\n )}\n >\n <div className={cn('flex flex-col gap-2', classNames?.detailsParts)}>\n <SuperGroupingProvider value={groupingContext}>\n <MessagePrimitive.Unstable_PartsGrouped groupingFunction={scopedGrouping} components={components} />\n </SuperGroupingProvider>\n </div>\n </section>\n ) : null}\n </div>\n ) : null}\n </ToolTimeline>\n {inlineParts.length > 0 ? (\n <div data-slot=\"activity-segment-inline-tools\" className=\"mt-2 flex min-w-0 flex-col gap-2\">\n {inlineParts.map(({ index, key }) => (\n <MessagePrimitive.PartByIndex key={key} index={index} components={components} />\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n\n// ─── Transcript ────────────────────────────────────────────────────────\n\n/**\n * The collapsed view (previously called the conversational view) of an\n * assistant turn as a transcript: a header that says how long the turn has\n * been working (\"Working for 1m 12s\", then \"Worked for 2m 30s\"), then the\n * agent's own sentences in the order it wrote them, each run of work between\n * them folded into one collapsed activity segment that names its step (\"Ran\n * `git log -1`\", \"Read `config.ts`\"). The answer — the text after the last\n * tool call — renders below it through `SuperGroupingFinalText`, exactly as\n * under `SuperGroupingCard`, so no text renders twice.\n *\n * Takes the same renderer and host slots as `SuperGroupingCard`;\n * `renderRunningMeta` and `renderHeaderActions` sit on the header row.\n *\n * Selector discipline: raw reads only (`message`, `message.content`,\n * `message.status`, the previous message's stamp and id); every derivation\n * runs in `useMemo`.\n */\nexport const SuperGroupingTranscript = memo(function SuperGroupingTranscript({\n toolUIs,\n ToolFallback: ToolFallbackComponent = ToolFallback,\n TextComponent,\n ReasoningComponent,\n GroupComponent = CollapsibleGroup,\n getToolGroupKey = defaultGetToolGroupKey,\n groupingFunction,\n isInlineTool = isRegistryInlineTool,\n waitingTools,\n passThroughTools,\n waitingForInput = false,\n resolveToolDisplayName,\n expansionKey: expansionKeyProp,\n expandWhileWaiting = false,\n mountDetails = false,\n maxVisibleSteps = DEFAULT_MAX_VISIBLE_STEPS,\n summaryDetails,\n renderHeaderActions,\n renderRunningMeta,\n className,\n classNames,\n}: SuperGroupingTranscriptProps) {\n const messageId = useAuiState((s) => s.message.id);\n const messageContent = useAuiState((s) =>\n s.message.role === 'assistant' ? s.message.content : EMPTY_CONTENT,\n );\n const messageStatus = useAuiState((s) => s.message.status);\n\n const timeline = useMemo(\n () => buildActivityTimeline(messageContent, messageStatus, { waitingTools, passThroughTools }),\n [messageContent, messageStatus, waitingTools, passThroughTools],\n );\n const phase = useMemo(\n () => resolveActivityPhase(messageStatus, timeline, { waitingForInput }),\n [messageStatus, timeline, waitingForInput],\n );\n const assetTitles = useMemo(() => collectAssetTitles(messageContent), [messageContent]);\n const stepsByPart = useMemo(() => {\n const byPart = new Map<number, TimelineStep>();\n timeline.forEach((item, index) => {\n if (item.partIndex === undefined) return;\n byPart.set(item.partIndex, toTimelineStep({ item, index, resolveToolDisplayName, assetTitles }));\n });\n return byPart;\n }, [timeline, resolveToolDisplayName, assetTitles]);\n const segments = useMemo(() => splitTurnSegments(messageContent), [messageContent]);\n const grouping = useMemo(\n () =>\n excludePartsFromGroups(\n groupingFunction ?? createToolBasedGroupingFunction(getToolGroupKey),\n (part) => part.type === 'tool-call' && part.toolName !== undefined && isInlineTool(part.toolName),\n ),\n [groupingFunction, getToolGroupKey, isInlineTool],\n );\n const inlineKeys = useMemo(() => {\n const keys = new Map<number, string>();\n messageContent.forEach((part, index) => {\n if (part.type === 'tool-call' && isInlineTool(part.toolName)) keys.set(index, part.toolCallId);\n });\n return keys;\n }, [messageContent, isInlineTool]);\n const components = useMemo(\n () => ({\n tools: {\n ...(toolUIs ? { by_name: toolUIs } : {}),\n Fallback: ToolFallbackComponent,\n },\n Text: TextComponent,\n ...(ReasoningComponent ? { Reasoning: ReasoningComponent } : {}),\n Group: GroupComponent,\n }),\n [toolUIs, ToolFallbackComponent, TextComponent, ReasoningComponent, GroupComponent],\n );\n const statusId = `aui-sg-turn-${useId().replace(/[^A-Za-z0-9_-]/g, '')}`;\n\n const hasText = messageContent.some((part) => part.type === 'text' && part.text.trim() !== '');\n const isVisible =\n timeline.length > 0 || phase === 'waiting' || phase === 'error' || (phase === 'running' && !hasText);\n if (!isVisible) return null;\n\n const expansionKey = expansionKeyProp ?? messageId;\n const toolCount = countActivityTools(timeline);\n const runningStep = [...stepsByPart.values()].filter((step) => step.state === 'running').at(-1);\n const cancelled = messageStatus?.type === 'incomplete' && messageStatus.reason === 'cancelled';\n const activitySummary = getActivitySummary(timeline);\n // The live region speaks what changed, never the ticking clock.\n const announcement =\n phase === 'running'\n ? (runningStep?.verb ?? 'Working')\n : phase === 'waiting'\n ? 'Waiting for your input'\n : phase === 'error'\n ? cancelled\n ? 'Run stopped'\n : 'Something went wrong'\n : activitySummary;\n const actions = renderHeaderActions?.({ phase, messageContent });\n const meta = phase === 'running' ? renderRunningMeta?.({ phase }) : null;\n\n return (\n <section\n data-slot=\"super-grouping-transcript\"\n data-phase={phase}\n data-tool-count={toolCount}\n className={cn('my-3 flex min-w-0 flex-col gap-1', className, classNames?.root)}\n aria-busy={phase === 'running' ? 'true' : 'false'}\n aria-describedby={statusId}\n >\n <div\n data-slot=\"turn-header\"\n className={cn(\n 'flex min-w-0 items-center gap-2 py-1 text-[13px] text-muted-foreground',\n classNames?.header,\n )}\n >\n <TurnGlyph phase={phase} />\n <span\n data-slot=\"turn-status\"\n className={cn(\n 'min-w-0 flex-1 truncate tabular-nums leading-5',\n phase === 'error' && !cancelled && 'text-destructive',\n )}\n >\n <TurnStatus\n phase={phase}\n cancelled={cancelled}\n activitySummary={activitySummary}\n toolCount={toolCount}\n summaryDetails={summaryDetails}\n />\n </span>\n {meta ? (\n <div data-slot=\"turn-meta\" className=\"flex shrink-0 items-center text-xs tabular-nums\">\n {meta}\n </div>\n ) : null}\n {actions ? <div className=\"flex shrink-0 items-center gap-1\">{actions}</div> : null}\n </div>\n {segments.length > 0 ? (\n <div\n data-slot=\"super-grouping-transcript-body\"\n className={cn('flex min-w-0 flex-col gap-1.5', classNames?.body)}\n >\n {segments.map((segment) =>\n segment.kind === 'prose' ? (\n <ProseSegment key={segment.key} text={segment.text} TextComponent={TextComponent} />\n ) : (\n <ActivitySegment\n key={segment.key}\n segment={segment}\n steps={segmentSteps(segment, stepsByPart)}\n turnPhase={phase}\n expansionKey={expansionKey}\n expandWhileWaiting={expandWhileWaiting}\n mountDetails={mountDetails}\n maxVisibleSteps={maxVisibleSteps}\n grouping={grouping}\n inlineParts={segment.partIndices.flatMap((index) => {\n const key = inlineKeys.get(index);\n return key === undefined ? [] : [{ index, key }];\n })}\n hasDetails={segment.partIndices.some(\n (index) => !inlineKeys.has(index) && messageContent[index]?.type !== 'text',\n )}\n components={components}\n classNames={classNames}\n />\n ),\n )}\n </div>\n ) : null}\n <output id={statusId} aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {announcement}\n </output>\n </section>\n );\n});\n\nfunction segmentSteps(\n segment: Extract<TurnSegment, { kind: 'activity' }>,\n stepsByPart: ReadonlyMap<number, TimelineStep>,\n): readonly TimelineStep[] {\n const steps = segment.partIndices\n .map((index) => stepsByPart.get(index))\n .filter((step): step is TimelineStep => step !== undefined);\n return steps.length > 0 ? steps : EMPTY_STEPS;\n}\n"],"names":["useAuiState","readMessageCreatedAt","useMemo","readTurnTiming","getExternalStoreMessages","useState","useEffect","firstSeenMs","jsx","Fragment","observedTurnEndMs","useRef","recordObservedTurnEnd","workedDurationMs","formatWorkDuration","LoaderCircle","cn","Circle","AlertCircle","Check","memo","ProseSegment","summarizeSegment","useActivityExpansion","scopeGroupingToSegment","useId","SuperGroupingProvider","MessagePrimitive","jsxs","ToolTimeline","StepText","ChevronRight","SuperGroupingTranscript","ToolFallback","CollapsibleGroup","defaultGetToolGroupKey","groupingFunction","isRegistryInlineTool","buildActivityTimeline","resolveActivityPhase","collectAssetTitles","toTimelineStep","splitTurnSegments","excludePartsFromGroups","createToolBasedGroupingFunction","countActivityTools","getActivitySummary"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SuperGroupingTranscript.cjs","sources":["../../../src/chat/super-grouping/SuperGroupingTranscript.tsx"],"sourcesContent":["'use client';\n\nimport {\n getExternalStoreMessages,\n MessagePrimitive,\n type TextMessagePartComponent,\n type ThreadAssistantMessagePart,\n useAuiState,\n} from '@assistant-ui/react';\nimport { AlertCircle, Check, ChevronRight, Circle, LoaderCircle } from 'lucide-react';\nimport { memo, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { cn } from '../../lib/utils';\nimport { StepText } from '../../tools/step-text';\nimport { isSdkInlineTool } from '../../tools/inline-tools';\nimport { ToolFallback } from '../../tools/tool-fallback';\nimport { collectAssetTitles } from '../../tools/tool-summary';\nimport { readMessageCreatedAt } from '../message-time';\nimport {\n type ActivityPhase,\n buildActivityTimeline,\n countActivityTools,\n excludePartsFromGroups,\n getActivitySummary,\n resolveActivityPhase,\n} from './activity-timeline';\nimport { CollapsibleGroup, SuperGroupingProvider } from './CollapsibleGroup';\nimport { GroupedMessageParts, type GroupedMessagePartsProps } from './GroupedMessageParts';\nimport { createToolBasedGroupingFunction, type GroupingFunction } from './grouping-function';\nimport { type SuperGroupingCardProps, useActivityExpansion } from './SuperGroupingCard';\nimport { ToolTimeline } from './ToolTimeline';\nimport { type TimelineStep, toTimelineStep } from './timeline-step';\nimport { defaultGetToolGroupKey } from './toolkit-map';\nimport {\n scopeGroupingToSegment,\n splitTurnSegments,\n summarizeSegment,\n type TurnSegment,\n} from './turn-segments';\nimport {\n firstSeenMs,\n formatWorkDuration,\n observedTurnEndMs,\n readTurnTiming,\n recordObservedTurnEnd,\n type TurnTiming,\n workedDurationMs,\n workingLabel,\n} from './turn-timing';\n\nconst DEFAULT_MAX_VISIBLE_STEPS = 6;\nconst EMPTY_CONTENT: readonly ThreadAssistantMessagePart[] = [];\nconst EMPTY_STEPS: readonly TimelineStep[] = [];\n\nexport interface SuperGroupingTranscriptProps\n extends Pick<\n SuperGroupingCardProps,\n | 'toolUIs'\n | 'ToolFallback'\n | 'TextComponent'\n | 'ReasoningComponent'\n | 'GroupComponent'\n | 'getToolGroupKey'\n | 'groupingFunction'\n | 'isInlineTool'\n | 'waitingTools'\n | 'passThroughTools'\n | 'waitingForInput'\n | 'resolveToolDisplayName'\n | 'expansionKey'\n | 'expandWhileWaiting'\n | 'mountDetails'\n | 'summaryDetails'\n | 'renderHeaderActions'\n | 'renderRunningMeta'\n | 'className'\n > {\n /** Steps an opened segment lists before older ones fold away; unresolved calls always show. */\n maxVisibleSteps?: number;\n classNames?: {\n root?: string;\n header?: string;\n body?: string;\n details?: string;\n /** The flex column a segment's parts render in; override its gap here. */\n detailsParts?: string;\n };\n}\n\n// ─── Turn timing ───────────────────────────────────────────────────────\n\n/**\n * The turn's stamps: the prompt it answers, its joined metadata, and the raw\n * messages behind it. Reads the whole message (the bound raw messages hang off\n * it), so only the small header status subscribes here, never the transcript.\n */\nfunction useTurnTimingSources(): { timing: TurnTiming; clockKey: string } {\n const message = useAuiState((s) => s.message);\n const promptCreatedAt = useAuiState((s) => {\n const previous = s.thread.messages[s.message.index - 1];\n return previous?.role === 'user' ? readMessageCreatedAt(previous.metadata?.custom) : null;\n });\n const promptId = useAuiState((s) => {\n const previous = s.thread.messages[s.message.index - 1];\n return previous?.role === 'user' ? previous.id : '';\n });\n const timing = useMemo(\n () =>\n readTurnTiming({\n promptCreatedAt,\n custom: message.metadata?.custom,\n sourceMessages: getExternalStoreMessages<unknown>(message),\n }),\n [message, promptCreatedAt],\n );\n return { timing, clockKey: `${promptId}:${message.id}` };\n}\n\n/** \"Working for 1m 12s\", re-rendered once a second by itself so the transcript does not. */\nfunction WorkingFor({ startMs, clockKey }: { startMs: number | null; clockKey: string }) {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(timer);\n }, []);\n const anchor = startMs ?? firstSeenMs(clockKey, now);\n return <>{workingLabel(Math.max(0, now - anchor))}</>;\n}\n\n/**\n * The header's words: \"Working for 1m 12s\" while the turn runs, \"Worked for\n * 2m 30s · Used 7 tools\" once done, \"Waiting for you\", or how it ended.\n */\nfunction TurnStatus({\n phase,\n cancelled,\n activitySummary,\n toolCount,\n summaryDetails,\n}: {\n phase: ActivityPhase;\n cancelled: boolean;\n activitySummary: string;\n toolCount: number;\n summaryDetails: readonly string[] | undefined;\n}) {\n const { timing, clockKey } = useTurnTimingSources();\n const [observedEndMs, setObservedEndMs] = useState(() => observedTurnEndMs(clockKey));\n const wasActive = useRef(phase === 'running' || phase === 'waiting');\n useEffect(() => {\n const active = phase === 'running' || phase === 'waiting';\n if (wasActive.current && !active) setObservedEndMs(recordObservedTurnEnd(clockKey));\n wasActive.current = active;\n }, [phase, clockKey]);\n if (phase === 'running') return <WorkingFor startMs={timing.startMs} clockKey={clockKey} />;\n if (phase === 'waiting') return <>Waiting for you</>;\n const workedMs = workedDurationMs(timing, observedEndMs);\n if (phase === 'error') {\n if (!cancelled) return <>Something went wrong</>;\n return <>{workedMs !== null ? `Run stopped after ${formatWorkDuration(workedMs)}` : 'Run stopped'}</>;\n }\n const label = [\n ...(workedMs !== null ? [`Worked for ${formatWorkDuration(workedMs)}`] : []),\n ...(workedMs === null || toolCount > 0 || activitySummary !== 'Reasoning complete' ? [activitySummary] : []),\n ...(summaryDetails ?? []),\n ].join(' · ');\n return <>{label}</>;\n}\n\nfunction TurnGlyph({ phase }: { phase: ActivityPhase }) {\n const className = 'size-3.5 shrink-0';\n if (phase === 'running') {\n return <LoaderCircle aria-hidden=\"true\" className={cn(className, 'motion-safe:animate-spin')} />;\n }\n if (phase === 'waiting') {\n return <Circle aria-hidden=\"true\" className={cn(className, 'text-amber-600 dark:text-amber-400')} />;\n }\n if (phase === 'error') {\n return <AlertCircle aria-hidden=\"true\" className={cn(className, 'text-destructive')} />;\n }\n return <Check aria-hidden=\"true\" className={cn(className, 'opacity-70')} />;\n}\n\n// ─── Segments ──────────────────────────────────────────────────────────\n\nconst ProseSegment = memo(function ProseSegment({\n text,\n TextComponent,\n}: {\n text: string;\n TextComponent: TextMessagePartComponent;\n}) {\n return (\n <div data-slot=\"transcript-prose\" className=\"min-w-0\">\n <TextComponent type=\"text\" text={text} status={{ type: 'complete' }} />\n </div>\n );\n});\n\ninterface ActivitySegmentProps {\n segment: Extract<TurnSegment, { kind: 'activity' }>;\n steps: readonly TimelineStep[];\n turnPhase: ActivityPhase;\n expansionKey: string;\n expandWhileWaiting: boolean;\n mountDetails: boolean;\n maxVisibleSteps: number;\n grouping: GroupingFunction;\n /** This segment's inline tool calls (an editable draft), rendered outside its disclosures. */\n inlineParts: readonly { index: number; key: string }[];\n /** False when every step's UI renders inline, so there is nothing behind \"Show tool details\". */\n hasDetails: boolean;\n components: GroupedMessagePartsProps['components'];\n classNames: SuperGroupingTranscriptProps['classNames'];\n}\n\n/**\n * One collapsed run of work between two of the agent's sentences: the step in\n * progress (or the last one taken) on one line, the segment's steps when\n * opened, and the tool UIs of just this segment behind \"Show tool details\".\n * The tool UIs stay mounted (hidden) while the turn is live so their effects\n * run, as in `SuperGroupingCard`.\n */\nfunction ActivitySegment({\n segment,\n steps,\n turnPhase,\n expansionKey,\n expandWhileWaiting,\n mountDetails,\n maxVisibleSteps,\n grouping,\n inlineParts,\n hasDetails,\n components,\n classNames,\n}: ActivitySegmentProps) {\n const summary = summarizeSegment(steps);\n const phase = summary.phase;\n const { expanded, toggleExpanded } = useActivityExpansion({\n expansionKey: `${expansionKey}:${segment.key}`,\n phase,\n expandWhileWaiting,\n });\n const { expanded: detailsExpanded, toggleExpanded: toggleDetails } = useActivityExpansion({\n expansionKey: `${expansionKey}:${segment.key}:details`,\n phase,\n expandWhileWaiting,\n });\n const indicesKey = segment.partIndices.join(',');\n const scopedGrouping = useMemo(\n () => scopeGroupingToSegment(grouping, indicesKey.split(',').map(Number)),\n [grouping, indicesKey],\n );\n const isTurnActive = turnPhase === 'running' || turnPhase === 'waiting';\n // The toolkit groups inside keep their tool UIs mounted when the details do.\n const groupingContext = useMemo(\n () => ({ groupingFunction: scopedGrouping, mountHidden: isTurnActive || mountDetails }),\n [scopedGrouping, isTurnActive, mountDetails],\n );\n const detailsPanelId = `aui-sg-segment-${useId().replace(/[^A-Za-z0-9_-]/g, '')}`;\n\n const detailsMounted = isTurnActive || mountDetails || (expanded && detailsExpanded);\n const hasToolSteps = steps.some((step) => step.kind === 'tool');\n const meta = [summary.step?.chip, summary.meta].filter(Boolean).join(' · ');\n\n // Parts with no step of their own (an image the agent produced) are content, not work.\n if (steps.length === 0) {\n return (\n <div data-slot=\"transcript-parts\" className={cn('flex min-w-0 flex-col gap-2', classNames?.detailsParts)}>\n <SuperGroupingProvider value={groupingContext}>\n <GroupedMessageParts groupingFunction={scopedGrouping} components={components} />\n </SuperGroupingProvider>\n </div>\n );\n }\n\n return (\n <div data-slot=\"activity-segment\" data-phase={phase} data-segment-key={segment.key} className=\"min-w-0\">\n <ToolTimeline\n steps={steps}\n open={expanded}\n onOpenChange={toggleExpanded}\n label={<StepText text={summary.label} code={summary.step?.code} />}\n labelTitle={summary.step?.detail}\n phase={phase}\n maxVisibleSteps={maxVisibleSteps}\n keepMounted={isTurnActive || mountDetails}\n meta={meta ? <span data-slot=\"activity-segment-meta\">{meta}</span> : null}\n >\n {hasDetails ? (\n <div className=\"min-w-0 pl-5\">\n <button\n type=\"button\"\n onClick={toggleDetails}\n aria-expanded={detailsExpanded}\n aria-controls={detailsPanelId}\n className=\"flex items-center gap-1.5 rounded py-1 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronRight\n aria-hidden=\"true\"\n className={cn(\n 'size-3 transition-transform motion-reduce:transition-none',\n detailsExpanded && 'rotate-90',\n )}\n />\n {detailsExpanded\n ? hasToolSteps\n ? 'Hide tool details'\n : 'Hide thinking'\n : hasToolSteps\n ? 'Show tool details'\n : 'Show thinking'}\n </button>\n {detailsMounted ? (\n <section\n id={detailsPanelId}\n aria-label=\"Step details\"\n hidden={!expanded || !detailsExpanded}\n className={cn(\n 'min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3',\n classNames?.details,\n )}\n >\n <div className={cn('flex flex-col gap-2', classNames?.detailsParts)}>\n <SuperGroupingProvider value={groupingContext}>\n <GroupedMessageParts groupingFunction={scopedGrouping} components={components} />\n </SuperGroupingProvider>\n </div>\n </section>\n ) : null}\n </div>\n ) : null}\n </ToolTimeline>\n {inlineParts.length > 0 ? (\n <div data-slot=\"activity-segment-inline-tools\" className=\"mt-2 flex min-w-0 flex-col gap-2\">\n {inlineParts.map(({ index, key }) => (\n <MessagePrimitive.PartByIndex key={key} index={index} components={components} />\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n\n// ─── Transcript ────────────────────────────────────────────────────────\n\n/**\n * The collapsed view (previously called the conversational view) of an\n * assistant turn as a transcript: a header that says how long the turn has\n * been working (\"Working for 1m 12s\", then \"Worked for 2m 30s\"), then the\n * agent's own sentences in the order it wrote them, each run of work between\n * them folded into one collapsed activity segment that names its step (\"Ran\n * `git log -1`\", \"Read `config.ts`\"). The answer — the text after the last\n * tool call — renders below it through `SuperGroupingFinalText`, exactly as\n * under `SuperGroupingCard`, so no text renders twice.\n *\n * Takes the same renderer and host slots as `SuperGroupingCard`;\n * `renderRunningMeta` and `renderHeaderActions` sit on the header row.\n *\n * Selector discipline: raw reads only (`message`, `message.content`,\n * `message.status`, the previous message's stamp and id); every derivation\n * runs in `useMemo`.\n */\nexport const SuperGroupingTranscript = memo(function SuperGroupingTranscript({\n toolUIs,\n ToolFallback: ToolFallbackComponent = ToolFallback,\n TextComponent,\n ReasoningComponent,\n GroupComponent = CollapsibleGroup,\n getToolGroupKey = defaultGetToolGroupKey,\n groupingFunction,\n isInlineTool = isSdkInlineTool,\n waitingTools,\n passThroughTools,\n waitingForInput = false,\n resolveToolDisplayName,\n expansionKey: expansionKeyProp,\n expandWhileWaiting = false,\n mountDetails = false,\n maxVisibleSteps = DEFAULT_MAX_VISIBLE_STEPS,\n summaryDetails,\n renderHeaderActions,\n renderRunningMeta,\n className,\n classNames,\n}: SuperGroupingTranscriptProps) {\n const messageId = useAuiState((s) => s.message.id);\n const messageContent = useAuiState((s) =>\n s.message.role === 'assistant' ? s.message.content : EMPTY_CONTENT,\n );\n const messageStatus = useAuiState((s) => s.message.status);\n\n const timeline = useMemo(\n () => buildActivityTimeline(messageContent, messageStatus, { waitingTools, passThroughTools }),\n [messageContent, messageStatus, waitingTools, passThroughTools],\n );\n const phase = useMemo(\n () => resolveActivityPhase(messageStatus, timeline, { waitingForInput }),\n [messageStatus, timeline, waitingForInput],\n );\n const assetTitles = useMemo(() => collectAssetTitles(messageContent), [messageContent]);\n const stepsByPart = useMemo(() => {\n const byPart = new Map<number, TimelineStep>();\n timeline.forEach((item, index) => {\n if (item.partIndex === undefined) return;\n byPart.set(item.partIndex, toTimelineStep({ item, index, resolveToolDisplayName, assetTitles }));\n });\n return byPart;\n }, [timeline, resolveToolDisplayName, assetTitles]);\n const segments = useMemo(() => splitTurnSegments(messageContent), [messageContent]);\n const grouping = useMemo(\n () =>\n excludePartsFromGroups(\n groupingFunction ?? createToolBasedGroupingFunction(getToolGroupKey),\n (part) => part.type === 'tool-call' && part.toolName !== undefined && isInlineTool(part.toolName),\n ),\n [groupingFunction, getToolGroupKey, isInlineTool],\n );\n const inlineKeys = useMemo(() => {\n const keys = new Map<number, string>();\n messageContent.forEach((part, index) => {\n if (part.type === 'tool-call' && isInlineTool(part.toolName)) keys.set(index, part.toolCallId);\n });\n return keys;\n }, [messageContent, isInlineTool]);\n const components = useMemo(\n () => ({\n tools: {\n ...(toolUIs ? { by_name: toolUIs } : {}),\n Fallback: ToolFallbackComponent,\n },\n Text: TextComponent,\n ...(ReasoningComponent ? { Reasoning: ReasoningComponent } : {}),\n Group: GroupComponent,\n }),\n [toolUIs, ToolFallbackComponent, TextComponent, ReasoningComponent, GroupComponent],\n );\n const statusId = `aui-sg-turn-${useId().replace(/[^A-Za-z0-9_-]/g, '')}`;\n\n const hasText = messageContent.some((part) => part.type === 'text' && part.text.trim() !== '');\n const isVisible =\n timeline.length > 0 || phase === 'waiting' || phase === 'error' || (phase === 'running' && !hasText);\n if (!isVisible) return null;\n\n const expansionKey = expansionKeyProp ?? messageId;\n const toolCount = countActivityTools(timeline);\n const runningStep = [...stepsByPart.values()].filter((step) => step.state === 'running').at(-1);\n const cancelled = messageStatus?.type === 'incomplete' && messageStatus.reason === 'cancelled';\n const activitySummary = getActivitySummary(timeline);\n // The live region speaks what changed, never the ticking clock.\n const announcement =\n phase === 'running'\n ? (runningStep?.verb ?? 'Working')\n : phase === 'waiting'\n ? 'Waiting for your input'\n : phase === 'error'\n ? cancelled\n ? 'Run stopped'\n : 'Something went wrong'\n : activitySummary;\n const actions = renderHeaderActions?.({ phase, messageContent });\n const meta = phase === 'running' ? renderRunningMeta?.({ phase }) : null;\n\n return (\n <section\n data-slot=\"super-grouping-transcript\"\n data-phase={phase}\n data-tool-count={toolCount}\n className={cn('my-3 flex min-w-0 flex-col gap-1', className, classNames?.root)}\n aria-busy={phase === 'running' ? 'true' : 'false'}\n aria-describedby={statusId}\n >\n <div\n data-slot=\"turn-header\"\n className={cn(\n 'flex min-w-0 items-center gap-2 py-1 text-[13px] text-muted-foreground',\n classNames?.header,\n )}\n >\n <TurnGlyph phase={phase} />\n <span\n data-slot=\"turn-status\"\n className={cn(\n 'min-w-0 flex-1 truncate tabular-nums leading-5',\n phase === 'error' && !cancelled && 'text-destructive',\n )}\n >\n <TurnStatus\n phase={phase}\n cancelled={cancelled}\n activitySummary={activitySummary}\n toolCount={toolCount}\n summaryDetails={summaryDetails}\n />\n </span>\n {meta ? (\n <div data-slot=\"turn-meta\" className=\"flex shrink-0 items-center text-xs tabular-nums\">\n {meta}\n </div>\n ) : null}\n {actions ? <div className=\"flex shrink-0 items-center gap-1\">{actions}</div> : null}\n </div>\n {segments.length > 0 ? (\n <div\n data-slot=\"super-grouping-transcript-body\"\n className={cn('flex min-w-0 flex-col gap-1.5', classNames?.body)}\n >\n {segments.map((segment) =>\n segment.kind === 'prose' ? (\n <ProseSegment key={segment.key} text={segment.text} TextComponent={TextComponent} />\n ) : (\n <ActivitySegment\n key={segment.key}\n segment={segment}\n steps={segmentSteps(segment, stepsByPart)}\n turnPhase={phase}\n expansionKey={expansionKey}\n expandWhileWaiting={expandWhileWaiting}\n mountDetails={mountDetails}\n maxVisibleSteps={maxVisibleSteps}\n grouping={grouping}\n inlineParts={segment.partIndices.flatMap((index) => {\n const key = inlineKeys.get(index);\n return key === undefined ? [] : [{ index, key }];\n })}\n hasDetails={segment.partIndices.some(\n (index) => !inlineKeys.has(index) && messageContent[index]?.type !== 'text',\n )}\n components={components}\n classNames={classNames}\n />\n ),\n )}\n </div>\n ) : null}\n <output id={statusId} aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {announcement}\n </output>\n </section>\n );\n});\n\nfunction segmentSteps(\n segment: Extract<TurnSegment, { kind: 'activity' }>,\n stepsByPart: ReadonlyMap<number, TimelineStep>,\n): readonly TimelineStep[] {\n const steps = segment.partIndices\n .map((index) => stepsByPart.get(index))\n .filter((step): step is TimelineStep => step !== undefined);\n return steps.length > 0 ? steps : EMPTY_STEPS;\n}\n"],"names":["useAuiState","readMessageCreatedAt","useMemo","readTurnTiming","getExternalStoreMessages","useState","useEffect","firstSeenMs","jsx","Fragment","observedTurnEndMs","useRef","recordObservedTurnEnd","workedDurationMs","formatWorkDuration","LoaderCircle","cn","Circle","AlertCircle","Check","memo","ProseSegment","summarizeSegment","useActivityExpansion","scopeGroupingToSegment","useId","SuperGroupingProvider","GroupedMessageParts","jsxs","ToolTimeline","StepText","ChevronRight","MessagePrimitive","SuperGroupingTranscript","ToolFallback","CollapsibleGroup","defaultGetToolGroupKey","groupingFunction","isSdkInlineTool","buildActivityTimeline","resolveActivityPhase","collectAssetTitles","toTimelineStep","splitTurnSegments","excludePartsFromGroups","createToolBasedGroupingFunction","countActivityTools","getActivitySummary"],"mappings":"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"}
|
|
@@ -3,11 +3,13 @@ import { useAuiState, MessagePrimitive, getExternalStoreMessages } from "@assist
|
|
|
3
3
|
import { LoaderCircle, Circle, AlertCircle, Check, ChevronRight } from "lucide-react";
|
|
4
4
|
import { memo, useMemo, useId, useState, useRef, useEffect } from "react";
|
|
5
5
|
import { StepText } from "../../tools/step-text.js";
|
|
6
|
+
import { isSdkInlineTool } from "../../tools/inline-tools.js";
|
|
6
7
|
import { ToolFallback } from "../../tools/tool-fallback.js";
|
|
7
8
|
import { collectAssetTitles } from "../../tools/tool-summary.js";
|
|
8
9
|
import { readMessageCreatedAt } from "../message-time.js";
|
|
9
10
|
import { buildActivityTimeline, resolveActivityPhase, excludePartsFromGroups, countActivityTools, getActivitySummary } from "./activity-timeline.js";
|
|
10
11
|
import { CollapsibleGroup, SuperGroupingProvider } from "./CollapsibleGroup.js";
|
|
12
|
+
import { GroupedMessageParts } from "./GroupedMessageParts.js";
|
|
11
13
|
import { createToolBasedGroupingFunction } from "./grouping-function.js";
|
|
12
14
|
import { useActivityExpansion } from "./SuperGroupingCard.js";
|
|
13
15
|
import { ToolTimeline } from "./ToolTimeline.js";
|
|
@@ -15,7 +17,6 @@ import { toTimelineStep } from "./timeline-step.js";
|
|
|
15
17
|
import { defaultGetToolGroupKey } from "./toolkit-map.js";
|
|
16
18
|
import { splitTurnSegments, summarizeSegment, scopeGroupingToSegment } from "./turn-segments.js";
|
|
17
19
|
import { observedTurnEndMs, recordObservedTurnEnd, workedDurationMs, formatWorkDuration, readTurnTiming, firstSeenMs, workingLabel } from "./turn-timing.js";
|
|
18
|
-
import { isInlineTool } from "../../agent-runtime/src/tool-metadata.js";
|
|
19
20
|
import { cn } from "cnfast";
|
|
20
21
|
const DEFAULT_MAX_VISIBLE_STEPS = 6;
|
|
21
22
|
const EMPTY_CONTENT = [];
|
|
@@ -133,14 +134,17 @@ function ActivitySegment({
|
|
|
133
134
|
() => scopeGroupingToSegment(grouping, indicesKey.split(",").map(Number)),
|
|
134
135
|
[grouping, indicesKey]
|
|
135
136
|
);
|
|
136
|
-
const groupingContext = useMemo(() => ({ groupingFunction: scopedGrouping }), [scopedGrouping]);
|
|
137
|
-
const detailsPanelId = `aui-sg-segment-${useId().replace(/[^A-Za-z0-9_-]/g, "")}`;
|
|
138
137
|
const isTurnActive = turnPhase === "running" || turnPhase === "waiting";
|
|
138
|
+
const groupingContext = useMemo(
|
|
139
|
+
() => ({ groupingFunction: scopedGrouping, mountHidden: isTurnActive || mountDetails }),
|
|
140
|
+
[scopedGrouping, isTurnActive, mountDetails]
|
|
141
|
+
);
|
|
142
|
+
const detailsPanelId = `aui-sg-segment-${useId().replace(/[^A-Za-z0-9_-]/g, "")}`;
|
|
139
143
|
const detailsMounted = isTurnActive || mountDetails || expanded && detailsExpanded;
|
|
140
144
|
const hasToolSteps = steps.some((step) => step.kind === "tool");
|
|
141
145
|
const meta = [(_a = summary.step) == null ? void 0 : _a.chip, summary.meta].filter(Boolean).join(" · ");
|
|
142
146
|
if (steps.length === 0) {
|
|
143
|
-
return /* @__PURE__ */ jsx("div", { "data-slot": "transcript-parts", className: cn("flex min-w-0 flex-col gap-2", classNames == null ? void 0 : classNames.detailsParts), children: /* @__PURE__ */ jsx(SuperGroupingProvider, { value: groupingContext, children: /* @__PURE__ */ jsx(
|
|
147
|
+
return /* @__PURE__ */ jsx("div", { "data-slot": "transcript-parts", className: cn("flex min-w-0 flex-col gap-2", classNames == null ? void 0 : classNames.detailsParts), children: /* @__PURE__ */ jsx(SuperGroupingProvider, { value: groupingContext, children: /* @__PURE__ */ jsx(GroupedMessageParts, { groupingFunction: scopedGrouping, components }) }) });
|
|
144
148
|
}
|
|
145
149
|
return /* @__PURE__ */ jsxs("div", { "data-slot": "activity-segment", "data-phase": phase, "data-segment-key": segment.key, className: "min-w-0", children: [
|
|
146
150
|
/* @__PURE__ */ jsx(
|
|
@@ -189,7 +193,7 @@ function ActivitySegment({
|
|
|
189
193
|
"min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3",
|
|
190
194
|
classNames == null ? void 0 : classNames.details
|
|
191
195
|
),
|
|
192
|
-
children: /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-2", classNames == null ? void 0 : classNames.detailsParts), children: /* @__PURE__ */ jsx(SuperGroupingProvider, { value: groupingContext, children: /* @__PURE__ */ jsx(
|
|
196
|
+
children: /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-2", classNames == null ? void 0 : classNames.detailsParts), children: /* @__PURE__ */ jsx(SuperGroupingProvider, { value: groupingContext, children: /* @__PURE__ */ jsx(GroupedMessageParts, { groupingFunction: scopedGrouping, components }) }) })
|
|
193
197
|
}
|
|
194
198
|
) : null
|
|
195
199
|
] }) : null
|
|
@@ -206,7 +210,7 @@ const SuperGroupingTranscript = memo(function SuperGroupingTranscript2({
|
|
|
206
210
|
GroupComponent = CollapsibleGroup,
|
|
207
211
|
getToolGroupKey = defaultGetToolGroupKey,
|
|
208
212
|
groupingFunction,
|
|
209
|
-
isInlineTool
|
|
213
|
+
isInlineTool = isSdkInlineTool,
|
|
210
214
|
waitingTools,
|
|
211
215
|
passThroughTools,
|
|
212
216
|
waitingForInput = false,
|
|
@@ -247,17 +251,17 @@ const SuperGroupingTranscript = memo(function SuperGroupingTranscript2({
|
|
|
247
251
|
const grouping = useMemo(
|
|
248
252
|
() => excludePartsFromGroups(
|
|
249
253
|
groupingFunction ?? createToolBasedGroupingFunction(getToolGroupKey),
|
|
250
|
-
(part) => part.type === "tool-call" && part.toolName !== void 0 && isInlineTool
|
|
254
|
+
(part) => part.type === "tool-call" && part.toolName !== void 0 && isInlineTool(part.toolName)
|
|
251
255
|
),
|
|
252
|
-
[groupingFunction, getToolGroupKey, isInlineTool
|
|
256
|
+
[groupingFunction, getToolGroupKey, isInlineTool]
|
|
253
257
|
);
|
|
254
258
|
const inlineKeys = useMemo(() => {
|
|
255
259
|
const keys = /* @__PURE__ */ new Map();
|
|
256
260
|
messageContent.forEach((part, index) => {
|
|
257
|
-
if (part.type === "tool-call" && isInlineTool
|
|
261
|
+
if (part.type === "tool-call" && isInlineTool(part.toolName)) keys.set(index, part.toolCallId);
|
|
258
262
|
});
|
|
259
263
|
return keys;
|
|
260
|
-
}, [messageContent, isInlineTool
|
|
264
|
+
}, [messageContent, isInlineTool]);
|
|
261
265
|
const components = useMemo(
|
|
262
266
|
() => ({
|
|
263
267
|
tools: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SuperGroupingTranscript.js","sources":["../../../src/chat/super-grouping/SuperGroupingTranscript.tsx"],"sourcesContent":["'use client';\n\nimport { isInlineTool as isRegistryInlineTool } from '@athenaintel/agent-runtime';\nimport {\n getExternalStoreMessages,\n MessagePrimitive,\n type TextMessagePartComponent,\n type ThreadAssistantMessagePart,\n useAuiState,\n} from '@assistant-ui/react';\nimport { AlertCircle, Check, ChevronRight, Circle, LoaderCircle } from 'lucide-react';\nimport { memo, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { cn } from '../../lib/utils';\nimport { StepText } from '../../tools/step-text';\nimport { ToolFallback } from '../../tools/tool-fallback';\nimport { collectAssetTitles } from '../../tools/tool-summary';\nimport { readMessageCreatedAt } from '../message-time';\nimport {\n type ActivityPhase,\n buildActivityTimeline,\n countActivityTools,\n excludePartsFromGroups,\n getActivitySummary,\n resolveActivityPhase,\n} from './activity-timeline';\nimport { CollapsibleGroup, SuperGroupingProvider } from './CollapsibleGroup';\nimport { createToolBasedGroupingFunction, type GroupingFunction } from './grouping-function';\nimport { type SuperGroupingCardProps, useActivityExpansion } from './SuperGroupingCard';\nimport { ToolTimeline } from './ToolTimeline';\nimport { type TimelineStep, toTimelineStep } from './timeline-step';\nimport { defaultGetToolGroupKey } from './toolkit-map';\nimport {\n scopeGroupingToSegment,\n splitTurnSegments,\n summarizeSegment,\n type TurnSegment,\n} from './turn-segments';\nimport {\n firstSeenMs,\n formatWorkDuration,\n observedTurnEndMs,\n readTurnTiming,\n recordObservedTurnEnd,\n type TurnTiming,\n workedDurationMs,\n workingLabel,\n} from './turn-timing';\n\nconst DEFAULT_MAX_VISIBLE_STEPS = 6;\nconst EMPTY_CONTENT: readonly ThreadAssistantMessagePart[] = [];\nconst EMPTY_STEPS: readonly TimelineStep[] = [];\n\nexport interface SuperGroupingTranscriptProps\n extends Pick<\n SuperGroupingCardProps,\n | 'toolUIs'\n | 'ToolFallback'\n | 'TextComponent'\n | 'ReasoningComponent'\n | 'GroupComponent'\n | 'getToolGroupKey'\n | 'groupingFunction'\n | 'isInlineTool'\n | 'waitingTools'\n | 'passThroughTools'\n | 'waitingForInput'\n | 'resolveToolDisplayName'\n | 'expansionKey'\n | 'expandWhileWaiting'\n | 'mountDetails'\n | 'summaryDetails'\n | 'renderHeaderActions'\n | 'renderRunningMeta'\n | 'className'\n > {\n /** Steps an opened segment lists before older ones fold away; unresolved calls always show. */\n maxVisibleSteps?: number;\n classNames?: {\n root?: string;\n header?: string;\n body?: string;\n details?: string;\n /** The flex column a segment's parts render in; override its gap here. */\n detailsParts?: string;\n };\n}\n\n// ─── Turn timing ───────────────────────────────────────────────────────\n\n/**\n * The turn's stamps: the prompt it answers, its joined metadata, and the raw\n * messages behind it. Reads the whole message (the bound raw messages hang off\n * it), so only the small header status subscribes here, never the transcript.\n */\nfunction useTurnTimingSources(): { timing: TurnTiming; clockKey: string } {\n const message = useAuiState((s) => s.message);\n const promptCreatedAt = useAuiState((s) => {\n const previous = s.thread.messages[s.message.index - 1];\n return previous?.role === 'user' ? readMessageCreatedAt(previous.metadata?.custom) : null;\n });\n const promptId = useAuiState((s) => {\n const previous = s.thread.messages[s.message.index - 1];\n return previous?.role === 'user' ? previous.id : '';\n });\n const timing = useMemo(\n () =>\n readTurnTiming({\n promptCreatedAt,\n custom: message.metadata?.custom,\n sourceMessages: getExternalStoreMessages<unknown>(message),\n }),\n [message, promptCreatedAt],\n );\n return { timing, clockKey: `${promptId}:${message.id}` };\n}\n\n/** \"Working for 1m 12s\", re-rendered once a second by itself so the transcript does not. */\nfunction WorkingFor({ startMs, clockKey }: { startMs: number | null; clockKey: string }) {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(timer);\n }, []);\n const anchor = startMs ?? firstSeenMs(clockKey, now);\n return <>{workingLabel(Math.max(0, now - anchor))}</>;\n}\n\n/**\n * The header's words: \"Working for 1m 12s\" while the turn runs, \"Worked for\n * 2m 30s · Used 7 tools\" once done, \"Waiting for you\", or how it ended.\n */\nfunction TurnStatus({\n phase,\n cancelled,\n activitySummary,\n toolCount,\n summaryDetails,\n}: {\n phase: ActivityPhase;\n cancelled: boolean;\n activitySummary: string;\n toolCount: number;\n summaryDetails: readonly string[] | undefined;\n}) {\n const { timing, clockKey } = useTurnTimingSources();\n const [observedEndMs, setObservedEndMs] = useState(() => observedTurnEndMs(clockKey));\n const wasActive = useRef(phase === 'running' || phase === 'waiting');\n useEffect(() => {\n const active = phase === 'running' || phase === 'waiting';\n if (wasActive.current && !active) setObservedEndMs(recordObservedTurnEnd(clockKey));\n wasActive.current = active;\n }, [phase, clockKey]);\n if (phase === 'running') return <WorkingFor startMs={timing.startMs} clockKey={clockKey} />;\n if (phase === 'waiting') return <>Waiting for you</>;\n const workedMs = workedDurationMs(timing, observedEndMs);\n if (phase === 'error') {\n if (!cancelled) return <>Something went wrong</>;\n return <>{workedMs !== null ? `Run stopped after ${formatWorkDuration(workedMs)}` : 'Run stopped'}</>;\n }\n const label = [\n ...(workedMs !== null ? [`Worked for ${formatWorkDuration(workedMs)}`] : []),\n ...(workedMs === null || toolCount > 0 || activitySummary !== 'Reasoning complete' ? [activitySummary] : []),\n ...(summaryDetails ?? []),\n ].join(' · ');\n return <>{label}</>;\n}\n\nfunction TurnGlyph({ phase }: { phase: ActivityPhase }) {\n const className = 'size-3.5 shrink-0';\n if (phase === 'running') {\n return <LoaderCircle aria-hidden=\"true\" className={cn(className, 'motion-safe:animate-spin')} />;\n }\n if (phase === 'waiting') {\n return <Circle aria-hidden=\"true\" className={cn(className, 'text-amber-600 dark:text-amber-400')} />;\n }\n if (phase === 'error') {\n return <AlertCircle aria-hidden=\"true\" className={cn(className, 'text-destructive')} />;\n }\n return <Check aria-hidden=\"true\" className={cn(className, 'opacity-70')} />;\n}\n\n// ─── Segments ──────────────────────────────────────────────────────────\n\nconst ProseSegment = memo(function ProseSegment({\n text,\n TextComponent,\n}: {\n text: string;\n TextComponent: TextMessagePartComponent;\n}) {\n return (\n <div data-slot=\"transcript-prose\" className=\"min-w-0\">\n <TextComponent type=\"text\" text={text} status={{ type: 'complete' }} />\n </div>\n );\n});\n\ninterface ActivitySegmentProps {\n segment: Extract<TurnSegment, { kind: 'activity' }>;\n steps: readonly TimelineStep[];\n turnPhase: ActivityPhase;\n expansionKey: string;\n expandWhileWaiting: boolean;\n mountDetails: boolean;\n maxVisibleSteps: number;\n grouping: GroupingFunction;\n /** This segment's inline tool calls (an editable draft), rendered outside its disclosures. */\n inlineParts: readonly { index: number; key: string }[];\n /** False when every step's UI renders inline, so there is nothing behind \"Show tool details\". */\n hasDetails: boolean;\n components: Parameters<typeof MessagePrimitive.Unstable_PartsGrouped>[0]['components'];\n classNames: SuperGroupingTranscriptProps['classNames'];\n}\n\n/**\n * One collapsed run of work between two of the agent's sentences: the step in\n * progress (or the last one taken) on one line, the segment's steps when\n * opened, and the tool UIs of just this segment behind \"Show tool details\".\n * The tool UIs stay mounted (hidden) while the turn is live so their effects\n * run, as in `SuperGroupingCard`.\n */\nfunction ActivitySegment({\n segment,\n steps,\n turnPhase,\n expansionKey,\n expandWhileWaiting,\n mountDetails,\n maxVisibleSteps,\n grouping,\n inlineParts,\n hasDetails,\n components,\n classNames,\n}: ActivitySegmentProps) {\n const summary = summarizeSegment(steps);\n const phase = summary.phase;\n const { expanded, toggleExpanded } = useActivityExpansion({\n expansionKey: `${expansionKey}:${segment.key}`,\n phase,\n expandWhileWaiting,\n });\n const { expanded: detailsExpanded, toggleExpanded: toggleDetails } = useActivityExpansion({\n expansionKey: `${expansionKey}:${segment.key}:details`,\n phase,\n expandWhileWaiting,\n });\n const indicesKey = segment.partIndices.join(',');\n const scopedGrouping = useMemo(\n () => scopeGroupingToSegment(grouping, indicesKey.split(',').map(Number)),\n [grouping, indicesKey],\n );\n const groupingContext = useMemo(() => ({ groupingFunction: scopedGrouping }), [scopedGrouping]);\n const detailsPanelId = `aui-sg-segment-${useId().replace(/[^A-Za-z0-9_-]/g, '')}`;\n\n const isTurnActive = turnPhase === 'running' || turnPhase === 'waiting';\n const detailsMounted = isTurnActive || mountDetails || (expanded && detailsExpanded);\n const hasToolSteps = steps.some((step) => step.kind === 'tool');\n const meta = [summary.step?.chip, summary.meta].filter(Boolean).join(' · ');\n\n // Parts with no step of their own (an image the agent produced) are content, not work.\n if (steps.length === 0) {\n return (\n <div data-slot=\"transcript-parts\" className={cn('flex min-w-0 flex-col gap-2', classNames?.detailsParts)}>\n <SuperGroupingProvider value={groupingContext}>\n <MessagePrimitive.Unstable_PartsGrouped groupingFunction={scopedGrouping} components={components} />\n </SuperGroupingProvider>\n </div>\n );\n }\n\n return (\n <div data-slot=\"activity-segment\" data-phase={phase} data-segment-key={segment.key} className=\"min-w-0\">\n <ToolTimeline\n steps={steps}\n open={expanded}\n onOpenChange={toggleExpanded}\n label={<StepText text={summary.label} code={summary.step?.code} />}\n labelTitle={summary.step?.detail}\n phase={phase}\n maxVisibleSteps={maxVisibleSteps}\n keepMounted={isTurnActive || mountDetails}\n meta={meta ? <span data-slot=\"activity-segment-meta\">{meta}</span> : null}\n >\n {hasDetails ? (\n <div className=\"min-w-0 pl-5\">\n <button\n type=\"button\"\n onClick={toggleDetails}\n aria-expanded={detailsExpanded}\n aria-controls={detailsPanelId}\n className=\"flex items-center gap-1.5 rounded py-1 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronRight\n aria-hidden=\"true\"\n className={cn(\n 'size-3 transition-transform motion-reduce:transition-none',\n detailsExpanded && 'rotate-90',\n )}\n />\n {detailsExpanded\n ? hasToolSteps\n ? 'Hide tool details'\n : 'Hide thinking'\n : hasToolSteps\n ? 'Show tool details'\n : 'Show thinking'}\n </button>\n {detailsMounted ? (\n <section\n id={detailsPanelId}\n aria-label=\"Step details\"\n hidden={!expanded || !detailsExpanded}\n className={cn(\n 'min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3',\n classNames?.details,\n )}\n >\n <div className={cn('flex flex-col gap-2', classNames?.detailsParts)}>\n <SuperGroupingProvider value={groupingContext}>\n <MessagePrimitive.Unstable_PartsGrouped groupingFunction={scopedGrouping} components={components} />\n </SuperGroupingProvider>\n </div>\n </section>\n ) : null}\n </div>\n ) : null}\n </ToolTimeline>\n {inlineParts.length > 0 ? (\n <div data-slot=\"activity-segment-inline-tools\" className=\"mt-2 flex min-w-0 flex-col gap-2\">\n {inlineParts.map(({ index, key }) => (\n <MessagePrimitive.PartByIndex key={key} index={index} components={components} />\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n\n// ─── Transcript ────────────────────────────────────────────────────────\n\n/**\n * The collapsed view (previously called the conversational view) of an\n * assistant turn as a transcript: a header that says how long the turn has\n * been working (\"Working for 1m 12s\", then \"Worked for 2m 30s\"), then the\n * agent's own sentences in the order it wrote them, each run of work between\n * them folded into one collapsed activity segment that names its step (\"Ran\n * `git log -1`\", \"Read `config.ts`\"). The answer — the text after the last\n * tool call — renders below it through `SuperGroupingFinalText`, exactly as\n * under `SuperGroupingCard`, so no text renders twice.\n *\n * Takes the same renderer and host slots as `SuperGroupingCard`;\n * `renderRunningMeta` and `renderHeaderActions` sit on the header row.\n *\n * Selector discipline: raw reads only (`message`, `message.content`,\n * `message.status`, the previous message's stamp and id); every derivation\n * runs in `useMemo`.\n */\nexport const SuperGroupingTranscript = memo(function SuperGroupingTranscript({\n toolUIs,\n ToolFallback: ToolFallbackComponent = ToolFallback,\n TextComponent,\n ReasoningComponent,\n GroupComponent = CollapsibleGroup,\n getToolGroupKey = defaultGetToolGroupKey,\n groupingFunction,\n isInlineTool = isRegistryInlineTool,\n waitingTools,\n passThroughTools,\n waitingForInput = false,\n resolveToolDisplayName,\n expansionKey: expansionKeyProp,\n expandWhileWaiting = false,\n mountDetails = false,\n maxVisibleSteps = DEFAULT_MAX_VISIBLE_STEPS,\n summaryDetails,\n renderHeaderActions,\n renderRunningMeta,\n className,\n classNames,\n}: SuperGroupingTranscriptProps) {\n const messageId = useAuiState((s) => s.message.id);\n const messageContent = useAuiState((s) =>\n s.message.role === 'assistant' ? s.message.content : EMPTY_CONTENT,\n );\n const messageStatus = useAuiState((s) => s.message.status);\n\n const timeline = useMemo(\n () => buildActivityTimeline(messageContent, messageStatus, { waitingTools, passThroughTools }),\n [messageContent, messageStatus, waitingTools, passThroughTools],\n );\n const phase = useMemo(\n () => resolveActivityPhase(messageStatus, timeline, { waitingForInput }),\n [messageStatus, timeline, waitingForInput],\n );\n const assetTitles = useMemo(() => collectAssetTitles(messageContent), [messageContent]);\n const stepsByPart = useMemo(() => {\n const byPart = new Map<number, TimelineStep>();\n timeline.forEach((item, index) => {\n if (item.partIndex === undefined) return;\n byPart.set(item.partIndex, toTimelineStep({ item, index, resolveToolDisplayName, assetTitles }));\n });\n return byPart;\n }, [timeline, resolveToolDisplayName, assetTitles]);\n const segments = useMemo(() => splitTurnSegments(messageContent), [messageContent]);\n const grouping = useMemo(\n () =>\n excludePartsFromGroups(\n groupingFunction ?? createToolBasedGroupingFunction(getToolGroupKey),\n (part) => part.type === 'tool-call' && part.toolName !== undefined && isInlineTool(part.toolName),\n ),\n [groupingFunction, getToolGroupKey, isInlineTool],\n );\n const inlineKeys = useMemo(() => {\n const keys = new Map<number, string>();\n messageContent.forEach((part, index) => {\n if (part.type === 'tool-call' && isInlineTool(part.toolName)) keys.set(index, part.toolCallId);\n });\n return keys;\n }, [messageContent, isInlineTool]);\n const components = useMemo(\n () => ({\n tools: {\n ...(toolUIs ? { by_name: toolUIs } : {}),\n Fallback: ToolFallbackComponent,\n },\n Text: TextComponent,\n ...(ReasoningComponent ? { Reasoning: ReasoningComponent } : {}),\n Group: GroupComponent,\n }),\n [toolUIs, ToolFallbackComponent, TextComponent, ReasoningComponent, GroupComponent],\n );\n const statusId = `aui-sg-turn-${useId().replace(/[^A-Za-z0-9_-]/g, '')}`;\n\n const hasText = messageContent.some((part) => part.type === 'text' && part.text.trim() !== '');\n const isVisible =\n timeline.length > 0 || phase === 'waiting' || phase === 'error' || (phase === 'running' && !hasText);\n if (!isVisible) return null;\n\n const expansionKey = expansionKeyProp ?? messageId;\n const toolCount = countActivityTools(timeline);\n const runningStep = [...stepsByPart.values()].filter((step) => step.state === 'running').at(-1);\n const cancelled = messageStatus?.type === 'incomplete' && messageStatus.reason === 'cancelled';\n const activitySummary = getActivitySummary(timeline);\n // The live region speaks what changed, never the ticking clock.\n const announcement =\n phase === 'running'\n ? (runningStep?.verb ?? 'Working')\n : phase === 'waiting'\n ? 'Waiting for your input'\n : phase === 'error'\n ? cancelled\n ? 'Run stopped'\n : 'Something went wrong'\n : activitySummary;\n const actions = renderHeaderActions?.({ phase, messageContent });\n const meta = phase === 'running' ? renderRunningMeta?.({ phase }) : null;\n\n return (\n <section\n data-slot=\"super-grouping-transcript\"\n data-phase={phase}\n data-tool-count={toolCount}\n className={cn('my-3 flex min-w-0 flex-col gap-1', className, classNames?.root)}\n aria-busy={phase === 'running' ? 'true' : 'false'}\n aria-describedby={statusId}\n >\n <div\n data-slot=\"turn-header\"\n className={cn(\n 'flex min-w-0 items-center gap-2 py-1 text-[13px] text-muted-foreground',\n classNames?.header,\n )}\n >\n <TurnGlyph phase={phase} />\n <span\n data-slot=\"turn-status\"\n className={cn(\n 'min-w-0 flex-1 truncate tabular-nums leading-5',\n phase === 'error' && !cancelled && 'text-destructive',\n )}\n >\n <TurnStatus\n phase={phase}\n cancelled={cancelled}\n activitySummary={activitySummary}\n toolCount={toolCount}\n summaryDetails={summaryDetails}\n />\n </span>\n {meta ? (\n <div data-slot=\"turn-meta\" className=\"flex shrink-0 items-center text-xs tabular-nums\">\n {meta}\n </div>\n ) : null}\n {actions ? <div className=\"flex shrink-0 items-center gap-1\">{actions}</div> : null}\n </div>\n {segments.length > 0 ? (\n <div\n data-slot=\"super-grouping-transcript-body\"\n className={cn('flex min-w-0 flex-col gap-1.5', classNames?.body)}\n >\n {segments.map((segment) =>\n segment.kind === 'prose' ? (\n <ProseSegment key={segment.key} text={segment.text} TextComponent={TextComponent} />\n ) : (\n <ActivitySegment\n key={segment.key}\n segment={segment}\n steps={segmentSteps(segment, stepsByPart)}\n turnPhase={phase}\n expansionKey={expansionKey}\n expandWhileWaiting={expandWhileWaiting}\n mountDetails={mountDetails}\n maxVisibleSteps={maxVisibleSteps}\n grouping={grouping}\n inlineParts={segment.partIndices.flatMap((index) => {\n const key = inlineKeys.get(index);\n return key === undefined ? [] : [{ index, key }];\n })}\n hasDetails={segment.partIndices.some(\n (index) => !inlineKeys.has(index) && messageContent[index]?.type !== 'text',\n )}\n components={components}\n classNames={classNames}\n />\n ),\n )}\n </div>\n ) : null}\n <output id={statusId} aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {announcement}\n </output>\n </section>\n );\n});\n\nfunction segmentSteps(\n segment: Extract<TurnSegment, { kind: 'activity' }>,\n stepsByPart: ReadonlyMap<number, TimelineStep>,\n): readonly TimelineStep[] {\n const steps = segment.partIndices\n .map((index) => stepsByPart.get(index))\n .filter((step): step is TimelineStep => step !== undefined);\n return steps.length > 0 ? steps : EMPTY_STEPS;\n}\n"],"names":["ProseSegment","SuperGroupingTranscript","isInlineTool","isRegistryInlineTool"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SuperGroupingTranscript.js","sources":["../../../src/chat/super-grouping/SuperGroupingTranscript.tsx"],"sourcesContent":["'use client';\n\nimport {\n getExternalStoreMessages,\n MessagePrimitive,\n type TextMessagePartComponent,\n type ThreadAssistantMessagePart,\n useAuiState,\n} from '@assistant-ui/react';\nimport { AlertCircle, Check, ChevronRight, Circle, LoaderCircle } from 'lucide-react';\nimport { memo, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { cn } from '../../lib/utils';\nimport { StepText } from '../../tools/step-text';\nimport { isSdkInlineTool } from '../../tools/inline-tools';\nimport { ToolFallback } from '../../tools/tool-fallback';\nimport { collectAssetTitles } from '../../tools/tool-summary';\nimport { readMessageCreatedAt } from '../message-time';\nimport {\n type ActivityPhase,\n buildActivityTimeline,\n countActivityTools,\n excludePartsFromGroups,\n getActivitySummary,\n resolveActivityPhase,\n} from './activity-timeline';\nimport { CollapsibleGroup, SuperGroupingProvider } from './CollapsibleGroup';\nimport { GroupedMessageParts, type GroupedMessagePartsProps } from './GroupedMessageParts';\nimport { createToolBasedGroupingFunction, type GroupingFunction } from './grouping-function';\nimport { type SuperGroupingCardProps, useActivityExpansion } from './SuperGroupingCard';\nimport { ToolTimeline } from './ToolTimeline';\nimport { type TimelineStep, toTimelineStep } from './timeline-step';\nimport { defaultGetToolGroupKey } from './toolkit-map';\nimport {\n scopeGroupingToSegment,\n splitTurnSegments,\n summarizeSegment,\n type TurnSegment,\n} from './turn-segments';\nimport {\n firstSeenMs,\n formatWorkDuration,\n observedTurnEndMs,\n readTurnTiming,\n recordObservedTurnEnd,\n type TurnTiming,\n workedDurationMs,\n workingLabel,\n} from './turn-timing';\n\nconst DEFAULT_MAX_VISIBLE_STEPS = 6;\nconst EMPTY_CONTENT: readonly ThreadAssistantMessagePart[] = [];\nconst EMPTY_STEPS: readonly TimelineStep[] = [];\n\nexport interface SuperGroupingTranscriptProps\n extends Pick<\n SuperGroupingCardProps,\n | 'toolUIs'\n | 'ToolFallback'\n | 'TextComponent'\n | 'ReasoningComponent'\n | 'GroupComponent'\n | 'getToolGroupKey'\n | 'groupingFunction'\n | 'isInlineTool'\n | 'waitingTools'\n | 'passThroughTools'\n | 'waitingForInput'\n | 'resolveToolDisplayName'\n | 'expansionKey'\n | 'expandWhileWaiting'\n | 'mountDetails'\n | 'summaryDetails'\n | 'renderHeaderActions'\n | 'renderRunningMeta'\n | 'className'\n > {\n /** Steps an opened segment lists before older ones fold away; unresolved calls always show. */\n maxVisibleSteps?: number;\n classNames?: {\n root?: string;\n header?: string;\n body?: string;\n details?: string;\n /** The flex column a segment's parts render in; override its gap here. */\n detailsParts?: string;\n };\n}\n\n// ─── Turn timing ───────────────────────────────────────────────────────\n\n/**\n * The turn's stamps: the prompt it answers, its joined metadata, and the raw\n * messages behind it. Reads the whole message (the bound raw messages hang off\n * it), so only the small header status subscribes here, never the transcript.\n */\nfunction useTurnTimingSources(): { timing: TurnTiming; clockKey: string } {\n const message = useAuiState((s) => s.message);\n const promptCreatedAt = useAuiState((s) => {\n const previous = s.thread.messages[s.message.index - 1];\n return previous?.role === 'user' ? readMessageCreatedAt(previous.metadata?.custom) : null;\n });\n const promptId = useAuiState((s) => {\n const previous = s.thread.messages[s.message.index - 1];\n return previous?.role === 'user' ? previous.id : '';\n });\n const timing = useMemo(\n () =>\n readTurnTiming({\n promptCreatedAt,\n custom: message.metadata?.custom,\n sourceMessages: getExternalStoreMessages<unknown>(message),\n }),\n [message, promptCreatedAt],\n );\n return { timing, clockKey: `${promptId}:${message.id}` };\n}\n\n/** \"Working for 1m 12s\", re-rendered once a second by itself so the transcript does not. */\nfunction WorkingFor({ startMs, clockKey }: { startMs: number | null; clockKey: string }) {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(timer);\n }, []);\n const anchor = startMs ?? firstSeenMs(clockKey, now);\n return <>{workingLabel(Math.max(0, now - anchor))}</>;\n}\n\n/**\n * The header's words: \"Working for 1m 12s\" while the turn runs, \"Worked for\n * 2m 30s · Used 7 tools\" once done, \"Waiting for you\", or how it ended.\n */\nfunction TurnStatus({\n phase,\n cancelled,\n activitySummary,\n toolCount,\n summaryDetails,\n}: {\n phase: ActivityPhase;\n cancelled: boolean;\n activitySummary: string;\n toolCount: number;\n summaryDetails: readonly string[] | undefined;\n}) {\n const { timing, clockKey } = useTurnTimingSources();\n const [observedEndMs, setObservedEndMs] = useState(() => observedTurnEndMs(clockKey));\n const wasActive = useRef(phase === 'running' || phase === 'waiting');\n useEffect(() => {\n const active = phase === 'running' || phase === 'waiting';\n if (wasActive.current && !active) setObservedEndMs(recordObservedTurnEnd(clockKey));\n wasActive.current = active;\n }, [phase, clockKey]);\n if (phase === 'running') return <WorkingFor startMs={timing.startMs} clockKey={clockKey} />;\n if (phase === 'waiting') return <>Waiting for you</>;\n const workedMs = workedDurationMs(timing, observedEndMs);\n if (phase === 'error') {\n if (!cancelled) return <>Something went wrong</>;\n return <>{workedMs !== null ? `Run stopped after ${formatWorkDuration(workedMs)}` : 'Run stopped'}</>;\n }\n const label = [\n ...(workedMs !== null ? [`Worked for ${formatWorkDuration(workedMs)}`] : []),\n ...(workedMs === null || toolCount > 0 || activitySummary !== 'Reasoning complete' ? [activitySummary] : []),\n ...(summaryDetails ?? []),\n ].join(' · ');\n return <>{label}</>;\n}\n\nfunction TurnGlyph({ phase }: { phase: ActivityPhase }) {\n const className = 'size-3.5 shrink-0';\n if (phase === 'running') {\n return <LoaderCircle aria-hidden=\"true\" className={cn(className, 'motion-safe:animate-spin')} />;\n }\n if (phase === 'waiting') {\n return <Circle aria-hidden=\"true\" className={cn(className, 'text-amber-600 dark:text-amber-400')} />;\n }\n if (phase === 'error') {\n return <AlertCircle aria-hidden=\"true\" className={cn(className, 'text-destructive')} />;\n }\n return <Check aria-hidden=\"true\" className={cn(className, 'opacity-70')} />;\n}\n\n// ─── Segments ──────────────────────────────────────────────────────────\n\nconst ProseSegment = memo(function ProseSegment({\n text,\n TextComponent,\n}: {\n text: string;\n TextComponent: TextMessagePartComponent;\n}) {\n return (\n <div data-slot=\"transcript-prose\" className=\"min-w-0\">\n <TextComponent type=\"text\" text={text} status={{ type: 'complete' }} />\n </div>\n );\n});\n\ninterface ActivitySegmentProps {\n segment: Extract<TurnSegment, { kind: 'activity' }>;\n steps: readonly TimelineStep[];\n turnPhase: ActivityPhase;\n expansionKey: string;\n expandWhileWaiting: boolean;\n mountDetails: boolean;\n maxVisibleSteps: number;\n grouping: GroupingFunction;\n /** This segment's inline tool calls (an editable draft), rendered outside its disclosures. */\n inlineParts: readonly { index: number; key: string }[];\n /** False when every step's UI renders inline, so there is nothing behind \"Show tool details\". */\n hasDetails: boolean;\n components: GroupedMessagePartsProps['components'];\n classNames: SuperGroupingTranscriptProps['classNames'];\n}\n\n/**\n * One collapsed run of work between two of the agent's sentences: the step in\n * progress (or the last one taken) on one line, the segment's steps when\n * opened, and the tool UIs of just this segment behind \"Show tool details\".\n * The tool UIs stay mounted (hidden) while the turn is live so their effects\n * run, as in `SuperGroupingCard`.\n */\nfunction ActivitySegment({\n segment,\n steps,\n turnPhase,\n expansionKey,\n expandWhileWaiting,\n mountDetails,\n maxVisibleSteps,\n grouping,\n inlineParts,\n hasDetails,\n components,\n classNames,\n}: ActivitySegmentProps) {\n const summary = summarizeSegment(steps);\n const phase = summary.phase;\n const { expanded, toggleExpanded } = useActivityExpansion({\n expansionKey: `${expansionKey}:${segment.key}`,\n phase,\n expandWhileWaiting,\n });\n const { expanded: detailsExpanded, toggleExpanded: toggleDetails } = useActivityExpansion({\n expansionKey: `${expansionKey}:${segment.key}:details`,\n phase,\n expandWhileWaiting,\n });\n const indicesKey = segment.partIndices.join(',');\n const scopedGrouping = useMemo(\n () => scopeGroupingToSegment(grouping, indicesKey.split(',').map(Number)),\n [grouping, indicesKey],\n );\n const isTurnActive = turnPhase === 'running' || turnPhase === 'waiting';\n // The toolkit groups inside keep their tool UIs mounted when the details do.\n const groupingContext = useMemo(\n () => ({ groupingFunction: scopedGrouping, mountHidden: isTurnActive || mountDetails }),\n [scopedGrouping, isTurnActive, mountDetails],\n );\n const detailsPanelId = `aui-sg-segment-${useId().replace(/[^A-Za-z0-9_-]/g, '')}`;\n\n const detailsMounted = isTurnActive || mountDetails || (expanded && detailsExpanded);\n const hasToolSteps = steps.some((step) => step.kind === 'tool');\n const meta = [summary.step?.chip, summary.meta].filter(Boolean).join(' · ');\n\n // Parts with no step of their own (an image the agent produced) are content, not work.\n if (steps.length === 0) {\n return (\n <div data-slot=\"transcript-parts\" className={cn('flex min-w-0 flex-col gap-2', classNames?.detailsParts)}>\n <SuperGroupingProvider value={groupingContext}>\n <GroupedMessageParts groupingFunction={scopedGrouping} components={components} />\n </SuperGroupingProvider>\n </div>\n );\n }\n\n return (\n <div data-slot=\"activity-segment\" data-phase={phase} data-segment-key={segment.key} className=\"min-w-0\">\n <ToolTimeline\n steps={steps}\n open={expanded}\n onOpenChange={toggleExpanded}\n label={<StepText text={summary.label} code={summary.step?.code} />}\n labelTitle={summary.step?.detail}\n phase={phase}\n maxVisibleSteps={maxVisibleSteps}\n keepMounted={isTurnActive || mountDetails}\n meta={meta ? <span data-slot=\"activity-segment-meta\">{meta}</span> : null}\n >\n {hasDetails ? (\n <div className=\"min-w-0 pl-5\">\n <button\n type=\"button\"\n onClick={toggleDetails}\n aria-expanded={detailsExpanded}\n aria-controls={detailsPanelId}\n className=\"flex items-center gap-1.5 rounded py-1 text-xs text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChevronRight\n aria-hidden=\"true\"\n className={cn(\n 'size-3 transition-transform motion-reduce:transition-none',\n detailsExpanded && 'rotate-90',\n )}\n />\n {detailsExpanded\n ? hasToolSteps\n ? 'Hide tool details'\n : 'Hide thinking'\n : hasToolSteps\n ? 'Show tool details'\n : 'Show thinking'}\n </button>\n {detailsMounted ? (\n <section\n id={detailsPanelId}\n aria-label=\"Step details\"\n hidden={!expanded || !detailsExpanded}\n className={cn(\n 'min-w-0 overflow-hidden border-l border-border/60 py-2 pl-3',\n classNames?.details,\n )}\n >\n <div className={cn('flex flex-col gap-2', classNames?.detailsParts)}>\n <SuperGroupingProvider value={groupingContext}>\n <GroupedMessageParts groupingFunction={scopedGrouping} components={components} />\n </SuperGroupingProvider>\n </div>\n </section>\n ) : null}\n </div>\n ) : null}\n </ToolTimeline>\n {inlineParts.length > 0 ? (\n <div data-slot=\"activity-segment-inline-tools\" className=\"mt-2 flex min-w-0 flex-col gap-2\">\n {inlineParts.map(({ index, key }) => (\n <MessagePrimitive.PartByIndex key={key} index={index} components={components} />\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n\n// ─── Transcript ────────────────────────────────────────────────────────\n\n/**\n * The collapsed view (previously called the conversational view) of an\n * assistant turn as a transcript: a header that says how long the turn has\n * been working (\"Working for 1m 12s\", then \"Worked for 2m 30s\"), then the\n * agent's own sentences in the order it wrote them, each run of work between\n * them folded into one collapsed activity segment that names its step (\"Ran\n * `git log -1`\", \"Read `config.ts`\"). The answer — the text after the last\n * tool call — renders below it through `SuperGroupingFinalText`, exactly as\n * under `SuperGroupingCard`, so no text renders twice.\n *\n * Takes the same renderer and host slots as `SuperGroupingCard`;\n * `renderRunningMeta` and `renderHeaderActions` sit on the header row.\n *\n * Selector discipline: raw reads only (`message`, `message.content`,\n * `message.status`, the previous message's stamp and id); every derivation\n * runs in `useMemo`.\n */\nexport const SuperGroupingTranscript = memo(function SuperGroupingTranscript({\n toolUIs,\n ToolFallback: ToolFallbackComponent = ToolFallback,\n TextComponent,\n ReasoningComponent,\n GroupComponent = CollapsibleGroup,\n getToolGroupKey = defaultGetToolGroupKey,\n groupingFunction,\n isInlineTool = isSdkInlineTool,\n waitingTools,\n passThroughTools,\n waitingForInput = false,\n resolveToolDisplayName,\n expansionKey: expansionKeyProp,\n expandWhileWaiting = false,\n mountDetails = false,\n maxVisibleSteps = DEFAULT_MAX_VISIBLE_STEPS,\n summaryDetails,\n renderHeaderActions,\n renderRunningMeta,\n className,\n classNames,\n}: SuperGroupingTranscriptProps) {\n const messageId = useAuiState((s) => s.message.id);\n const messageContent = useAuiState((s) =>\n s.message.role === 'assistant' ? s.message.content : EMPTY_CONTENT,\n );\n const messageStatus = useAuiState((s) => s.message.status);\n\n const timeline = useMemo(\n () => buildActivityTimeline(messageContent, messageStatus, { waitingTools, passThroughTools }),\n [messageContent, messageStatus, waitingTools, passThroughTools],\n );\n const phase = useMemo(\n () => resolveActivityPhase(messageStatus, timeline, { waitingForInput }),\n [messageStatus, timeline, waitingForInput],\n );\n const assetTitles = useMemo(() => collectAssetTitles(messageContent), [messageContent]);\n const stepsByPart = useMemo(() => {\n const byPart = new Map<number, TimelineStep>();\n timeline.forEach((item, index) => {\n if (item.partIndex === undefined) return;\n byPart.set(item.partIndex, toTimelineStep({ item, index, resolveToolDisplayName, assetTitles }));\n });\n return byPart;\n }, [timeline, resolveToolDisplayName, assetTitles]);\n const segments = useMemo(() => splitTurnSegments(messageContent), [messageContent]);\n const grouping = useMemo(\n () =>\n excludePartsFromGroups(\n groupingFunction ?? createToolBasedGroupingFunction(getToolGroupKey),\n (part) => part.type === 'tool-call' && part.toolName !== undefined && isInlineTool(part.toolName),\n ),\n [groupingFunction, getToolGroupKey, isInlineTool],\n );\n const inlineKeys = useMemo(() => {\n const keys = new Map<number, string>();\n messageContent.forEach((part, index) => {\n if (part.type === 'tool-call' && isInlineTool(part.toolName)) keys.set(index, part.toolCallId);\n });\n return keys;\n }, [messageContent, isInlineTool]);\n const components = useMemo(\n () => ({\n tools: {\n ...(toolUIs ? { by_name: toolUIs } : {}),\n Fallback: ToolFallbackComponent,\n },\n Text: TextComponent,\n ...(ReasoningComponent ? { Reasoning: ReasoningComponent } : {}),\n Group: GroupComponent,\n }),\n [toolUIs, ToolFallbackComponent, TextComponent, ReasoningComponent, GroupComponent],\n );\n const statusId = `aui-sg-turn-${useId().replace(/[^A-Za-z0-9_-]/g, '')}`;\n\n const hasText = messageContent.some((part) => part.type === 'text' && part.text.trim() !== '');\n const isVisible =\n timeline.length > 0 || phase === 'waiting' || phase === 'error' || (phase === 'running' && !hasText);\n if (!isVisible) return null;\n\n const expansionKey = expansionKeyProp ?? messageId;\n const toolCount = countActivityTools(timeline);\n const runningStep = [...stepsByPart.values()].filter((step) => step.state === 'running').at(-1);\n const cancelled = messageStatus?.type === 'incomplete' && messageStatus.reason === 'cancelled';\n const activitySummary = getActivitySummary(timeline);\n // The live region speaks what changed, never the ticking clock.\n const announcement =\n phase === 'running'\n ? (runningStep?.verb ?? 'Working')\n : phase === 'waiting'\n ? 'Waiting for your input'\n : phase === 'error'\n ? cancelled\n ? 'Run stopped'\n : 'Something went wrong'\n : activitySummary;\n const actions = renderHeaderActions?.({ phase, messageContent });\n const meta = phase === 'running' ? renderRunningMeta?.({ phase }) : null;\n\n return (\n <section\n data-slot=\"super-grouping-transcript\"\n data-phase={phase}\n data-tool-count={toolCount}\n className={cn('my-3 flex min-w-0 flex-col gap-1', className, classNames?.root)}\n aria-busy={phase === 'running' ? 'true' : 'false'}\n aria-describedby={statusId}\n >\n <div\n data-slot=\"turn-header\"\n className={cn(\n 'flex min-w-0 items-center gap-2 py-1 text-[13px] text-muted-foreground',\n classNames?.header,\n )}\n >\n <TurnGlyph phase={phase} />\n <span\n data-slot=\"turn-status\"\n className={cn(\n 'min-w-0 flex-1 truncate tabular-nums leading-5',\n phase === 'error' && !cancelled && 'text-destructive',\n )}\n >\n <TurnStatus\n phase={phase}\n cancelled={cancelled}\n activitySummary={activitySummary}\n toolCount={toolCount}\n summaryDetails={summaryDetails}\n />\n </span>\n {meta ? (\n <div data-slot=\"turn-meta\" className=\"flex shrink-0 items-center text-xs tabular-nums\">\n {meta}\n </div>\n ) : null}\n {actions ? <div className=\"flex shrink-0 items-center gap-1\">{actions}</div> : null}\n </div>\n {segments.length > 0 ? (\n <div\n data-slot=\"super-grouping-transcript-body\"\n className={cn('flex min-w-0 flex-col gap-1.5', classNames?.body)}\n >\n {segments.map((segment) =>\n segment.kind === 'prose' ? (\n <ProseSegment key={segment.key} text={segment.text} TextComponent={TextComponent} />\n ) : (\n <ActivitySegment\n key={segment.key}\n segment={segment}\n steps={segmentSteps(segment, stepsByPart)}\n turnPhase={phase}\n expansionKey={expansionKey}\n expandWhileWaiting={expandWhileWaiting}\n mountDetails={mountDetails}\n maxVisibleSteps={maxVisibleSteps}\n grouping={grouping}\n inlineParts={segment.partIndices.flatMap((index) => {\n const key = inlineKeys.get(index);\n return key === undefined ? [] : [{ index, key }];\n })}\n hasDetails={segment.partIndices.some(\n (index) => !inlineKeys.has(index) && messageContent[index]?.type !== 'text',\n )}\n components={components}\n classNames={classNames}\n />\n ),\n )}\n </div>\n ) : null}\n <output id={statusId} aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {announcement}\n </output>\n </section>\n );\n});\n\nfunction segmentSteps(\n segment: Extract<TurnSegment, { kind: 'activity' }>,\n stepsByPart: ReadonlyMap<number, TimelineStep>,\n): readonly TimelineStep[] {\n const steps = segment.partIndices\n .map((index) => stepsByPart.get(index))\n .filter((step): step is TimelineStep => step !== undefined);\n return steps.length > 0 ? steps : EMPTY_STEPS;\n}\n"],"names":["ProseSegment","SuperGroupingTranscript"],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
function identityOf(part) {
|
|
4
|
+
const identity = part.type === "tool-call" ? part.toolCallId : part.id;
|
|
5
|
+
return identity ? `${part.type}:${identity}` : void 0;
|
|
6
|
+
}
|
|
7
|
+
function claim({ base, used }) {
|
|
8
|
+
let key = base;
|
|
9
|
+
for (let suffix = 1; used.has(key); suffix += 1) key = `${base}#${suffix}`;
|
|
10
|
+
used.add(key);
|
|
11
|
+
return key;
|
|
12
|
+
}
|
|
13
|
+
function sharedPartShift({
|
|
14
|
+
previous,
|
|
15
|
+
parts,
|
|
16
|
+
identities
|
|
17
|
+
}) {
|
|
18
|
+
const previousIndexByPart = new Map(previous.parts.map((part, index) => [part, index]));
|
|
19
|
+
const previousIndexByKey = new Map(previous.partKeys.map((key, index) => [key, index]));
|
|
20
|
+
for (let index = 0; index < parts.length; index += 1) {
|
|
21
|
+
const identity = identities[index];
|
|
22
|
+
const previousIndex = previousIndexByPart.get(parts[index]) ?? (identity === void 0 ? void 0 : previousIndexByKey.get(identity));
|
|
23
|
+
if (previousIndex !== void 0) return index - previousIndex;
|
|
24
|
+
}
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
function carryGroupedPartKeys({
|
|
28
|
+
previous,
|
|
29
|
+
parts,
|
|
30
|
+
groups
|
|
31
|
+
}) {
|
|
32
|
+
const identities = parts.map(identityOf);
|
|
33
|
+
const identityCounts = /* @__PURE__ */ new Map();
|
|
34
|
+
for (const identity of identities) {
|
|
35
|
+
if (identity !== void 0) identityCounts.set(identity, (identityCounts.get(identity) ?? 0) + 1);
|
|
36
|
+
}
|
|
37
|
+
const usedPartKeys = /* @__PURE__ */ new Set();
|
|
38
|
+
const partKeys = identities.map((identity) => {
|
|
39
|
+
if (identity === void 0 || identityCounts.get(identity) !== 1) return void 0;
|
|
40
|
+
usedPartKeys.add(identity);
|
|
41
|
+
return identity;
|
|
42
|
+
});
|
|
43
|
+
if (previous !== null) {
|
|
44
|
+
const previousIndexByPart = new Map(previous.parts.map((part, index) => [part, index]));
|
|
45
|
+
const carry = (index, previousIndex) => {
|
|
46
|
+
const key = previousIndex === void 0 ? void 0 : previous.partKeys[previousIndex];
|
|
47
|
+
if (key === void 0 || usedPartKeys.has(key)) return;
|
|
48
|
+
partKeys[index] = key;
|
|
49
|
+
usedPartKeys.add(key);
|
|
50
|
+
};
|
|
51
|
+
parts.forEach((part, index) => {
|
|
52
|
+
if (partKeys[index] === void 0) carry(index, previousIndexByPart.get(part));
|
|
53
|
+
});
|
|
54
|
+
const shift = sharedPartShift({ previous, parts, identities });
|
|
55
|
+
parts.forEach((part, index) => {
|
|
56
|
+
var _a;
|
|
57
|
+
if (partKeys[index] !== void 0) return;
|
|
58
|
+
const previousIndex = index - shift;
|
|
59
|
+
if (((_a = previous.parts[previousIndex]) == null ? void 0 : _a.type) === part.type) carry(index, previousIndex);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
const keys = partKeys.map(
|
|
63
|
+
(key, index) => {
|
|
64
|
+
var _a;
|
|
65
|
+
return key ?? claim({ base: `${(_a = parts[index]) == null ? void 0 : _a.type}@${index}`, used: usedPartKeys });
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
const previousGroupByPartKey = /* @__PURE__ */ new Map();
|
|
69
|
+
previous == null ? void 0 : previous.groups.forEach((group, groupIndex) => {
|
|
70
|
+
const key = previous.groupKeys[groupIndex];
|
|
71
|
+
if (key === void 0) return;
|
|
72
|
+
for (const index of group.indices) {
|
|
73
|
+
const partKey = previous.partKeys[index];
|
|
74
|
+
if (partKey !== void 0) previousGroupByPartKey.set(partKey, { key, groupKey: group.groupKey });
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
const usedGroupKeys = /* @__PURE__ */ new Set();
|
|
78
|
+
const carriedGroupKeys = groups.map((group) => {
|
|
79
|
+
for (const index of group.indices) {
|
|
80
|
+
const previousGroup = previousGroupByPartKey.get(keys[index] ?? "");
|
|
81
|
+
if (previousGroup !== void 0 && previousGroup.groupKey === group.groupKey && !usedGroupKeys.has(previousGroup.key)) {
|
|
82
|
+
usedGroupKeys.add(previousGroup.key);
|
|
83
|
+
return previousGroup.key;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return void 0;
|
|
87
|
+
});
|
|
88
|
+
const groupKeys = carriedGroupKeys.map(
|
|
89
|
+
(key, groupIndex) => {
|
|
90
|
+
var _a, _b;
|
|
91
|
+
return key ?? claim({
|
|
92
|
+
base: JSON.stringify([
|
|
93
|
+
"group",
|
|
94
|
+
((_a = groups[groupIndex]) == null ? void 0 : _a.groupKey) ?? null,
|
|
95
|
+
keys[((_b = groups[groupIndex]) == null ? void 0 : _b.indices[0]) ?? -1] ?? groupIndex
|
|
96
|
+
]),
|
|
97
|
+
used: usedGroupKeys
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
return { parts, groups, partKeys: keys, groupKeys };
|
|
102
|
+
}
|
|
103
|
+
exports.carryGroupedPartKeys = carryGroupedPartKeys;
|
|
104
|
+
//# sourceMappingURL=grouped-part-keys.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grouped-part-keys.cjs","sources":["../../../src/chat/super-grouping/grouped-part-keys.ts"],"sourcesContent":["import type { MessagePartGroup } from './grouping-function';\n\n/** The part shape keying needs; assistant-ui's message parts satisfy it. */\nexport type KeyablePart = {\n readonly type: string;\n readonly toolCallId?: string;\n readonly id?: string;\n};\n\n/** The React keys of one render of a message's grouped parts, and what they were computed for. */\nexport interface GroupedPartKeys {\n readonly parts: readonly KeyablePart[];\n readonly groups: readonly MessagePartGroup[];\n /** Each part's key, by part index. */\n readonly partKeys: readonly string[];\n /** Each group's key, by group index. */\n readonly groupKeys: readonly string[];\n}\n\n/** A tool call's id, or the identity a host gave the part, as assistant-ui keys parts. */\nfunction identityOf(part: KeyablePart): string | undefined {\n const identity = part.type === 'tool-call' ? part.toolCallId : part.id;\n return identity ? `${part.type}:${identity}` : undefined;\n}\n\n/** `base`, or `base` with the first free suffix, claimed in `used`. */\nfunction claim({ base, used }: { base: string; used: Set<string> }): string {\n let key = base;\n for (let suffix = 1; used.has(key); suffix += 1) key = `${base}#${suffix}`;\n used.add(key);\n return key;\n}\n\n/**\n * How far the parts the previous render shares with this one moved: a page of\n * older steps folding in at the head of a turn shifts every part it already\n * had by the page's length; a streamed token or a part appended at the tail\n * shifts none.\n */\nfunction sharedPartShift({\n previous,\n parts,\n identities,\n}: {\n previous: GroupedPartKeys;\n parts: readonly KeyablePart[];\n identities: readonly (string | undefined)[];\n}): number {\n const previousIndexByPart = new Map(previous.parts.map((part, index) => [part, index]));\n const previousIndexByKey = new Map(previous.partKeys.map((key, index) => [key, index]));\n for (let index = 0; index < parts.length; index += 1) {\n const identity = identities[index];\n const previousIndex =\n previousIndexByPart.get(parts[index]) ??\n (identity === undefined ? undefined : previousIndexByKey.get(identity));\n if (previousIndex !== undefined) return index - previousIndex;\n }\n return 0;\n}\n\n/**\n * The React keys a message's grouped parts render under, carried over from\n * the previous render so that what is already mounted stays mounted when the\n * message grows at its head as well as at its tail.\n *\n * assistant-ui keys a part by its tool call id (or a host-given id) and any\n * other part by its type and index, and a group by its first part. A page of\n * older steps that folds into the first loaded turn therefore gives the\n * turn's first toolkit group a new key whenever the folded steps join it (the\n * group and every card in it remount), and every text part a new index. Here\n * a tool call keeps its id key; any other part keeps the key it had, found as\n * the same part object or as the part at the same place relative to the parts\n * both renders share; and a group keeps the key of the previous group of the\n * same toolkit that held one of its parts. New parts and groups get\n * assistant-ui's keys, made unique.\n */\nexport function carryGroupedPartKeys({\n previous,\n parts,\n groups,\n}: {\n previous: GroupedPartKeys | null;\n parts: readonly KeyablePart[];\n groups: readonly MessagePartGroup[];\n}): GroupedPartKeys {\n const identities = parts.map(identityOf);\n const identityCounts = new Map<string, number>();\n for (const identity of identities) {\n if (identity !== undefined) identityCounts.set(identity, (identityCounts.get(identity) ?? 0) + 1);\n }\n const usedPartKeys = new Set<string>();\n const partKeys: (string | undefined)[] = identities.map((identity) => {\n if (identity === undefined || identityCounts.get(identity) !== 1) return undefined;\n usedPartKeys.add(identity);\n return identity;\n });\n\n if (previous !== null) {\n const previousIndexByPart = new Map(previous.parts.map((part, index) => [part, index]));\n const carry = (index: number, previousIndex: number | undefined): void => {\n const key = previousIndex === undefined ? undefined : previous.partKeys[previousIndex];\n if (key === undefined || usedPartKeys.has(key)) return;\n partKeys[index] = key;\n usedPartKeys.add(key);\n };\n // The same part object first, so a place-based match never takes a key its own part still holds.\n parts.forEach((part, index) => {\n if (partKeys[index] === undefined) carry(index, previousIndexByPart.get(part));\n });\n const shift = sharedPartShift({ previous, parts, identities });\n parts.forEach((part, index) => {\n if (partKeys[index] !== undefined) return;\n const previousIndex = index - shift;\n if (previous.parts[previousIndex]?.type === part.type) carry(index, previousIndex);\n });\n }\n const keys = partKeys.map(\n (key, index) => key ?? claim({ base: `${parts[index]?.type}@${index}`, used: usedPartKeys }),\n );\n\n const previousGroupByPartKey = new Map<string, { key: string; groupKey: string | undefined }>();\n previous?.groups.forEach((group, groupIndex) => {\n const key = previous.groupKeys[groupIndex];\n if (key === undefined) return;\n for (const index of group.indices) {\n const partKey = previous.partKeys[index];\n if (partKey !== undefined) previousGroupByPartKey.set(partKey, { key, groupKey: group.groupKey });\n }\n });\n const usedGroupKeys = new Set<string>();\n const carriedGroupKeys = groups.map((group) => {\n for (const index of group.indices) {\n const previousGroup = previousGroupByPartKey.get(keys[index] ?? '');\n if (\n previousGroup !== undefined &&\n previousGroup.groupKey === group.groupKey &&\n !usedGroupKeys.has(previousGroup.key)\n ) {\n usedGroupKeys.add(previousGroup.key);\n return previousGroup.key;\n }\n }\n return undefined;\n });\n const groupKeys = carriedGroupKeys.map(\n (key, groupIndex) =>\n key ??\n claim({\n base: JSON.stringify([\n 'group',\n groups[groupIndex]?.groupKey ?? null,\n keys[groups[groupIndex]?.indices[0] ?? -1] ?? groupIndex,\n ]),\n used: usedGroupKeys,\n }),\n );\n\n return { parts, groups, partKeys: keys, groupKeys };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { MessagePartGroup } from './grouping-function';
|
|
2
|
+
/** The part shape keying needs; assistant-ui's message parts satisfy it. */
|
|
3
|
+
export type KeyablePart = {
|
|
4
|
+
readonly type: string;
|
|
5
|
+
readonly toolCallId?: string;
|
|
6
|
+
readonly id?: string;
|
|
7
|
+
};
|
|
8
|
+
/** The React keys of one render of a message's grouped parts, and what they were computed for. */
|
|
9
|
+
export interface GroupedPartKeys {
|
|
10
|
+
readonly parts: readonly KeyablePart[];
|
|
11
|
+
readonly groups: readonly MessagePartGroup[];
|
|
12
|
+
/** Each part's key, by part index. */
|
|
13
|
+
readonly partKeys: readonly string[];
|
|
14
|
+
/** Each group's key, by group index. */
|
|
15
|
+
readonly groupKeys: readonly string[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The React keys a message's grouped parts render under, carried over from
|
|
19
|
+
* the previous render so that what is already mounted stays mounted when the
|
|
20
|
+
* message grows at its head as well as at its tail.
|
|
21
|
+
*
|
|
22
|
+
* assistant-ui keys a part by its tool call id (or a host-given id) and any
|
|
23
|
+
* other part by its type and index, and a group by its first part. A page of
|
|
24
|
+
* older steps that folds into the first loaded turn therefore gives the
|
|
25
|
+
* turn's first toolkit group a new key whenever the folded steps join it (the
|
|
26
|
+
* group and every card in it remount), and every text part a new index. Here
|
|
27
|
+
* a tool call keeps its id key; any other part keeps the key it had, found as
|
|
28
|
+
* the same part object or as the part at the same place relative to the parts
|
|
29
|
+
* both renders share; and a group keeps the key of the previous group of the
|
|
30
|
+
* same toolkit that held one of its parts. New parts and groups get
|
|
31
|
+
* assistant-ui's keys, made unique.
|
|
32
|
+
*/
|
|
33
|
+
export declare function carryGroupedPartKeys({ previous, parts, groups, }: {
|
|
34
|
+
previous: GroupedPartKeys | null;
|
|
35
|
+
parts: readonly KeyablePart[];
|
|
36
|
+
groups: readonly MessagePartGroup[];
|
|
37
|
+
}): GroupedPartKeys;
|