@athenaintel/react 0.38.1 → 0.40.0

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.
Files changed (137) hide show
  1. package/README.md +23 -3
  2. package/dist/agent-runtime/src/errors.cjs +8 -0
  3. package/dist/agent-runtime/src/errors.cjs.map +1 -1
  4. package/dist/agent-runtime/src/errors.js +8 -0
  5. package/dist/agent-runtime/src/errors.js.map +1 -1
  6. package/dist/agent-runtime/src/messages.cjs +76 -16
  7. package/dist/agent-runtime/src/messages.cjs.map +1 -1
  8. package/dist/agent-runtime/src/messages.js +76 -16
  9. package/dist/agent-runtime/src/messages.js.map +1 -1
  10. package/dist/agent-runtime/src/tool-metadata.cjs +15 -0
  11. package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
  12. package/dist/agent-runtime/src/tool-metadata.js +15 -0
  13. package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
  14. package/dist/assets/use-asset-content.cjs +127 -0
  15. package/dist/assets/use-asset-content.cjs.map +1 -0
  16. package/dist/assets/use-asset-content.d.ts +60 -0
  17. package/dist/assets/use-asset-content.js +127 -0
  18. package/dist/assets/use-asset-content.js.map +1 -0
  19. package/dist/chat/super-grouping/CollapsibleGroup.cjs +16 -8
  20. package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
  21. package/dist/chat/super-grouping/CollapsibleGroup.d.ts +26 -1
  22. package/dist/chat/super-grouping/CollapsibleGroup.js +16 -8
  23. package/dist/chat/super-grouping/CollapsibleGroup.js.map +1 -1
  24. package/dist/chat/super-grouping/GroupedMessageParts.cjs +59 -0
  25. package/dist/chat/super-grouping/GroupedMessageParts.cjs.map +1 -0
  26. package/dist/chat/super-grouping/GroupedMessageParts.d.ts +25 -0
  27. package/dist/chat/super-grouping/GroupedMessageParts.js +59 -0
  28. package/dist/chat/super-grouping/GroupedMessageParts.js.map +1 -0
  29. package/dist/chat/super-grouping/SuperGroupingCard.cjs +9 -5
  30. package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
  31. package/dist/chat/super-grouping/SuperGroupingCard.d.ts +2 -1
  32. package/dist/chat/super-grouping/SuperGroupingCard.js +13 -9
  33. package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
  34. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +10 -6
  35. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
  36. package/dist/chat/super-grouping/SuperGroupingTranscript.js +14 -10
  37. package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
  38. package/dist/chat/super-grouping/grouped-part-keys.cjs +104 -0
  39. package/dist/chat/super-grouping/grouped-part-keys.cjs.map +1 -0
  40. package/dist/chat/super-grouping/grouped-part-keys.d.ts +37 -0
  41. package/dist/chat/super-grouping/grouped-part-keys.js +104 -0
  42. package/dist/chat/super-grouping/grouped-part-keys.js.map +1 -0
  43. package/dist/chat/super-grouping/index.cjs +2 -0
  44. package/dist/chat/super-grouping/index.cjs.map +1 -1
  45. package/dist/chat/super-grouping/index.d.ts +3 -1
  46. package/dist/chat/super-grouping/index.js +2 -0
  47. package/dist/chat/super-grouping/index.js.map +1 -1
  48. package/dist/chat-ui/composer/tiptap-composer.cjs +25 -19
  49. package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
  50. package/dist/chat-ui/composer/tiptap-composer.d.ts +5 -0
  51. package/dist/chat-ui/composer/tiptap-composer.js +26 -20
  52. package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
  53. package/dist/chat-ui/thread/statewire-history-edge.cjs +13 -0
  54. package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
  55. package/dist/chat-ui/thread/statewire-history-edge.js +13 -0
  56. package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
  57. package/dist/composer/clipboard.cjs +16 -0
  58. package/dist/composer/clipboard.cjs.map +1 -1
  59. package/dist/composer/clipboard.d.ts +9 -0
  60. package/dist/composer/clipboard.js +17 -1
  61. package/dist/composer/clipboard.js.map +1 -1
  62. package/dist/diagnostics/errors.cjs +11 -0
  63. package/dist/diagnostics/errors.cjs.map +1 -1
  64. package/dist/diagnostics/errors.d.ts +11 -0
  65. package/dist/diagnostics/errors.js +11 -0
  66. package/dist/diagnostics/errors.js.map +1 -1
  67. package/dist/index.cjs +37 -0
  68. package/dist/index.cjs.map +1 -1
  69. package/dist/index.d.ts +14 -1
  70. package/dist/index.js +37 -0
  71. package/dist/index.js.map +1 -1
  72. package/dist/provider/AthenaProvider.cjs +5 -2
  73. package/dist/provider/AthenaProvider.cjs.map +1 -1
  74. package/dist/provider/AthenaProvider.js +5 -2
  75. package/dist/provider/AthenaProvider.js.map +1 -1
  76. package/dist/provider/statewire-history-context.cjs +48 -0
  77. package/dist/provider/statewire-history-context.cjs.map +1 -0
  78. package/dist/provider/statewire-history-context.d.ts +36 -0
  79. package/dist/provider/statewire-history-context.js +48 -0
  80. package/dist/provider/statewire-history-context.js.map +1 -0
  81. package/dist/react/package.json.cjs +1 -1
  82. package/dist/react/package.json.js +1 -1
  83. package/dist/runtime/statewire-lifecycle.cjs +8 -0
  84. package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
  85. package/dist/runtime/statewire-lifecycle.js +9 -1
  86. package/dist/runtime/statewire-lifecycle.js.map +1 -1
  87. package/dist/styles.css +1 -1
  88. package/dist/tools/index.cjs +7 -0
  89. package/dist/tools/index.cjs.map +1 -1
  90. package/dist/tools/index.d.ts +2 -0
  91. package/dist/tools/index.js +7 -0
  92. package/dist/tools/index.js.map +1 -1
  93. package/dist/tools/inline-tools.cjs +10 -0
  94. package/dist/tools/inline-tools.cjs.map +1 -0
  95. package/dist/tools/inline-tools.d.ts +2 -0
  96. package/dist/tools/inline-tools.js +10 -0
  97. package/dist/tools/inline-tools.js.map +1 -0
  98. package/dist/tools/test-recording-report.cjs +175 -0
  99. package/dist/tools/test-recording-report.cjs.map +1 -0
  100. package/dist/tools/test-recording-report.d.ts +82 -0
  101. package/dist/tools/test-recording-report.js +175 -0
  102. package/dist/tools/test-recording-report.js.map +1 -0
  103. package/dist/tools/test-recording-tool-uis.cjs +498 -0
  104. package/dist/tools/test-recording-tool-uis.cjs.map +1 -0
  105. package/dist/tools/test-recording-tool-uis.d.ts +32 -0
  106. package/dist/tools/test-recording-tool-uis.js +498 -0
  107. package/dist/tools/test-recording-tool-uis.js.map +1 -0
  108. package/dist/tools/tool-summary.cjs +49 -1
  109. package/dist/tools/tool-summary.cjs.map +1 -1
  110. package/dist/tools/tool-summary.js +49 -1
  111. package/dist/tools/tool-summary.js.map +1 -1
  112. package/dist/tools/tool-uis.cjs +6 -1
  113. package/dist/tools/tool-uis.cjs.map +1 -1
  114. package/dist/tools/tool-uis.js +6 -1
  115. package/dist/tools/tool-uis.js.map +1 -1
  116. package/dist/workbench/ComputerLiveDesktop.cjs +287 -0
  117. package/dist/workbench/ComputerLiveDesktop.cjs.map +1 -0
  118. package/dist/workbench/ComputerLiveDesktop.d.ts +27 -0
  119. package/dist/workbench/ComputerLiveDesktop.js +287 -0
  120. package/dist/workbench/ComputerLiveDesktop.js.map +1 -0
  121. package/dist/workbench/SessionWorkbench.cjs +2 -2
  122. package/dist/workbench/SessionWorkbench.cjs.map +1 -1
  123. package/dist/workbench/SessionWorkbench.js +2 -2
  124. package/dist/workbench/SessionWorkbench.js.map +1 -1
  125. package/dist/workbench/live-desktop-api.cjs +139 -0
  126. package/dist/workbench/live-desktop-api.cjs.map +1 -0
  127. package/dist/workbench/live-desktop-api.d.ts +69 -0
  128. package/dist/workbench/live-desktop-api.js +139 -0
  129. package/dist/workbench/live-desktop-api.js.map +1 -0
  130. package/dist/workbench/session-workbench-context.cjs.map +1 -1
  131. package/dist/workbench/session-workbench-context.d.ts +7 -0
  132. package/dist/workbench/session-workbench-context.js.map +1 -1
  133. package/dist/workbench/session-workbench-panes.cjs +38 -2
  134. package/dist/workbench/session-workbench-panes.cjs.map +1 -1
  135. package/dist/workbench/session-workbench-panes.js +38 -2
  136. package/dist/workbench/session-workbench-panes.js.map +1 -1
  137. package/package.json +1 -1
@@ -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;
@@ -0,0 +1,104 @@
1
+ function identityOf(part) {
2
+ const identity = part.type === "tool-call" ? part.toolCallId : part.id;
3
+ return identity ? `${part.type}:${identity}` : void 0;
4
+ }
5
+ function claim({ base, used }) {
6
+ let key = base;
7
+ for (let suffix = 1; used.has(key); suffix += 1) key = `${base}#${suffix}`;
8
+ used.add(key);
9
+ return key;
10
+ }
11
+ function sharedPartShift({
12
+ previous,
13
+ parts,
14
+ identities
15
+ }) {
16
+ const previousIndexByPart = new Map(previous.parts.map((part, index) => [part, index]));
17
+ const previousIndexByKey = new Map(previous.partKeys.map((key, index) => [key, index]));
18
+ for (let index = 0; index < parts.length; index += 1) {
19
+ const identity = identities[index];
20
+ const previousIndex = previousIndexByPart.get(parts[index]) ?? (identity === void 0 ? void 0 : previousIndexByKey.get(identity));
21
+ if (previousIndex !== void 0) return index - previousIndex;
22
+ }
23
+ return 0;
24
+ }
25
+ function carryGroupedPartKeys({
26
+ previous,
27
+ parts,
28
+ groups
29
+ }) {
30
+ const identities = parts.map(identityOf);
31
+ const identityCounts = /* @__PURE__ */ new Map();
32
+ for (const identity of identities) {
33
+ if (identity !== void 0) identityCounts.set(identity, (identityCounts.get(identity) ?? 0) + 1);
34
+ }
35
+ const usedPartKeys = /* @__PURE__ */ new Set();
36
+ const partKeys = identities.map((identity) => {
37
+ if (identity === void 0 || identityCounts.get(identity) !== 1) return void 0;
38
+ usedPartKeys.add(identity);
39
+ return identity;
40
+ });
41
+ if (previous !== null) {
42
+ const previousIndexByPart = new Map(previous.parts.map((part, index) => [part, index]));
43
+ const carry = (index, previousIndex) => {
44
+ const key = previousIndex === void 0 ? void 0 : previous.partKeys[previousIndex];
45
+ if (key === void 0 || usedPartKeys.has(key)) return;
46
+ partKeys[index] = key;
47
+ usedPartKeys.add(key);
48
+ };
49
+ parts.forEach((part, index) => {
50
+ if (partKeys[index] === void 0) carry(index, previousIndexByPart.get(part));
51
+ });
52
+ const shift = sharedPartShift({ previous, parts, identities });
53
+ parts.forEach((part, index) => {
54
+ var _a;
55
+ if (partKeys[index] !== void 0) return;
56
+ const previousIndex = index - shift;
57
+ if (((_a = previous.parts[previousIndex]) == null ? void 0 : _a.type) === part.type) carry(index, previousIndex);
58
+ });
59
+ }
60
+ const keys = partKeys.map(
61
+ (key, index) => {
62
+ var _a;
63
+ return key ?? claim({ base: `${(_a = parts[index]) == null ? void 0 : _a.type}@${index}`, used: usedPartKeys });
64
+ }
65
+ );
66
+ const previousGroupByPartKey = /* @__PURE__ */ new Map();
67
+ previous == null ? void 0 : previous.groups.forEach((group, groupIndex) => {
68
+ const key = previous.groupKeys[groupIndex];
69
+ if (key === void 0) return;
70
+ for (const index of group.indices) {
71
+ const partKey = previous.partKeys[index];
72
+ if (partKey !== void 0) previousGroupByPartKey.set(partKey, { key, groupKey: group.groupKey });
73
+ }
74
+ });
75
+ const usedGroupKeys = /* @__PURE__ */ new Set();
76
+ const carriedGroupKeys = groups.map((group) => {
77
+ for (const index of group.indices) {
78
+ const previousGroup = previousGroupByPartKey.get(keys[index] ?? "");
79
+ if (previousGroup !== void 0 && previousGroup.groupKey === group.groupKey && !usedGroupKeys.has(previousGroup.key)) {
80
+ usedGroupKeys.add(previousGroup.key);
81
+ return previousGroup.key;
82
+ }
83
+ }
84
+ return void 0;
85
+ });
86
+ const groupKeys = carriedGroupKeys.map(
87
+ (key, groupIndex) => {
88
+ var _a, _b;
89
+ return key ?? claim({
90
+ base: JSON.stringify([
91
+ "group",
92
+ ((_a = groups[groupIndex]) == null ? void 0 : _a.groupKey) ?? null,
93
+ keys[((_b = groups[groupIndex]) == null ? void 0 : _b.indices[0]) ?? -1] ?? groupIndex
94
+ ]),
95
+ used: usedGroupKeys
96
+ });
97
+ }
98
+ );
99
+ return { parts, groups, partKeys: keys, groupKeys };
100
+ }
101
+ export {
102
+ carryGroupedPartKeys
103
+ };
104
+ //# sourceMappingURL=grouped-part-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grouped-part-keys.js","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":"AAoBA,SAAS,WAAW,MAAuC;AACzD,QAAM,WAAW,KAAK,SAAS,cAAc,KAAK,aAAa,KAAK;AACpE,SAAO,WAAW,GAAG,KAAK,IAAI,IAAI,QAAQ,KAAK;AACjD;AAGA,SAAS,MAAM,EAAE,MAAM,QAAqD;AAC1E,MAAI,MAAM;AACV,WAAS,SAAS,GAAG,KAAK,IAAI,GAAG,GAAG,UAAU,EAAG,OAAM,GAAG,IAAI,IAAI,MAAM;AACxE,OAAK,IAAI,GAAG;AACZ,SAAO;AACT;AAQA,SAAS,gBAAgB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AACF,GAIW;AACT,QAAM,sBAAsB,IAAI,IAAI,SAAS,MAAM,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC;AACtF,QAAM,qBAAqB,IAAI,IAAI,SAAS,SAAS,IAAI,CAAC,KAAK,UAAU,CAAC,KAAK,KAAK,CAAC,CAAC;AACtF,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,WAAW,WAAW,KAAK;AACjC,UAAM,gBACJ,oBAAoB,IAAI,MAAM,KAAK,CAAC,MACnC,aAAa,SAAY,SAAY,mBAAmB,IAAI,QAAQ;AACvE,QAAI,kBAAkB,OAAW,QAAO,QAAQ;AAAA,EAClD;AACA,SAAO;AACT;AAkBO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF,GAIoB;AAClB,QAAM,aAAa,MAAM,IAAI,UAAU;AACvC,QAAM,qCAAqB,IAAA;AAC3B,aAAW,YAAY,YAAY;AACjC,QAAI,aAAa,OAAW,gBAAe,IAAI,WAAW,eAAe,IAAI,QAAQ,KAAK,KAAK,CAAC;AAAA,EAClG;AACA,QAAM,mCAAmB,IAAA;AACzB,QAAM,WAAmC,WAAW,IAAI,CAAC,aAAa;AACpE,QAAI,aAAa,UAAa,eAAe,IAAI,QAAQ,MAAM,EAAG,QAAO;AACzE,iBAAa,IAAI,QAAQ;AACzB,WAAO;AAAA,EACT,CAAC;AAED,MAAI,aAAa,MAAM;AACrB,UAAM,sBAAsB,IAAI,IAAI,SAAS,MAAM,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC;AACtF,UAAM,QAAQ,CAAC,OAAe,kBAA4C;AACxE,YAAM,MAAM,kBAAkB,SAAY,SAAY,SAAS,SAAS,aAAa;AACrF,UAAI,QAAQ,UAAa,aAAa,IAAI,GAAG,EAAG;AAChD,eAAS,KAAK,IAAI;AAClB,mBAAa,IAAI,GAAG;AAAA,IACtB;AAEA,UAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,UAAI,SAAS,KAAK,MAAM,cAAiB,OAAO,oBAAoB,IAAI,IAAI,CAAC;AAAA,IAC/E,CAAC;AACD,UAAM,QAAQ,gBAAgB,EAAE,UAAU,OAAO,YAAY;AAC7D,UAAM,QAAQ,CAAC,MAAM,UAAU;AA1FnC;AA2FM,UAAI,SAAS,KAAK,MAAM,OAAW;AACnC,YAAM,gBAAgB,QAAQ;AAC9B,YAAI,cAAS,MAAM,aAAa,MAA5B,mBAA+B,UAAS,KAAK,KAAM,OAAM,OAAO,aAAa;AAAA,IACnF,CAAC;AAAA,EACH;AACA,QAAM,OAAO,SAAS;AAAA,IACpB,CAAC,KAAK,UAAA;AAjGV;AAiGoB,oBAAO,MAAM,EAAE,MAAM,IAAG,WAAM,KAAK,MAAX,mBAAc,IAAI,IAAI,KAAK,IAAI,MAAM,cAAc;AAAA;AAAA,EAAA;AAG7F,QAAM,6CAA6B,IAAA;AACnC,uCAAU,OAAO,QAAQ,CAAC,OAAO,eAAe;AAC9C,UAAM,MAAM,SAAS,UAAU,UAAU;AACzC,QAAI,QAAQ,OAAW;AACvB,eAAW,SAAS,MAAM,SAAS;AACjC,YAAM,UAAU,SAAS,SAAS,KAAK;AACvC,UAAI,YAAY,OAAW,wBAAuB,IAAI,SAAS,EAAE,KAAK,UAAU,MAAM,UAAU;AAAA,IAClG;AAAA,EACF;AACA,QAAM,oCAAoB,IAAA;AAC1B,QAAM,mBAAmB,OAAO,IAAI,CAAC,UAAU;AAC7C,eAAW,SAAS,MAAM,SAAS;AACjC,YAAM,gBAAgB,uBAAuB,IAAI,KAAK,KAAK,KAAK,EAAE;AAClE,UACE,kBAAkB,UAClB,cAAc,aAAa,MAAM,YACjC,CAAC,cAAc,IAAI,cAAc,GAAG,GACpC;AACA,sBAAc,IAAI,cAAc,GAAG;AACnC,eAAO,cAAc;AAAA,MACvB;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACD,QAAM,YAAY,iBAAiB;AAAA,IACjC,CAAC,KAAK;AA7HV;AA8HM,oBACA,MAAM;AAAA,QACJ,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,YACA,YAAO,UAAU,MAAjB,mBAAoB,aAAY;AAAA,UAChC,OAAK,YAAO,UAAU,MAAjB,mBAAoB,QAAQ,OAAM,EAAE,KAAK;AAAA,QAAA,CAC/C;AAAA,QACD,MAAM;AAAA,MAAA,CACP;AAAA;AAAA,EAAA;AAGL,SAAO,EAAE,OAAO,QAAQ,UAAU,MAAM,UAAA;AAC1C;"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const activityTimeline = require("./activity-timeline.cjs");
4
4
  const CollapsibleGroup = require("./CollapsibleGroup.cjs");
5
+ const GroupedMessageParts = require("./GroupedMessageParts.cjs");
5
6
  const groupingFunction = require("./grouping-function.cjs");
6
7
  const SuperGroupingCard = require("./SuperGroupingCard.cjs");
7
8
  const SuperGroupingTranscript = require("./SuperGroupingTranscript.cjs");
@@ -24,6 +25,7 @@ exports.CollapsibleGroup = CollapsibleGroup.CollapsibleGroup;
24
25
  exports.DEFAULT_TOOLKIT_THEME = CollapsibleGroup.DEFAULT_TOOLKIT_THEME;
25
26
  exports.SuperGroupingProvider = CollapsibleGroup.SuperGroupingProvider;
26
27
  exports.TOOLKIT_THEMES = CollapsibleGroup.TOOLKIT_THEMES;
28
+ exports.GroupedMessageParts = GroupedMessageParts.GroupedMessageParts;
27
29
  exports.createToolBasedGroupingFunction = groupingFunction.createToolBasedGroupingFunction;
28
30
  exports.SuperGroupingCard = SuperGroupingCard.SuperGroupingCard;
29
31
  exports.SuperGroupingFinalText = SuperGroupingCard.SuperGroupingFinalText;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * `@athenaintel/react/super-grouping` — the collapsed view (previously called
3
3
  * the conversational view) of an assistant turn: the activity card, its
4
- * per-toolkit collapsible blocks, the timeline derivation behind them, the
4
+ * per-toolkit collapsible blocks and the grouped-parts renderer that keeps
5
+ * them mounted as the turn grows, the timeline derivation behind them, the
5
6
  * tool-based grouping function, and the transcript layout (the agent's
6
7
  * sentences in order with the work between them folded, under a "Working
7
8
  * for …" header).
@@ -10,6 +11,7 @@
10
11
  */
11
12
  export { type ActivityItem, type ActivityPhase, type ActivityTimelineOptions, type ActivityToolState, buildActivityTimeline, countActivityTools, excludeFinalTextFromGroups, excludePartsFromGroups, type FinalTextPart, type FinalTextSegment, getActivityItemLabel, getActivitySummary, getReasoningLabel, getActivityToolState, isStreamingToolPlaceholder, getFinalText, getFinalTextParts, resolveActivityPhase, } from './activity-timeline';
12
13
  export { CollapsibleGroup, type CollapsibleGroupProps, DEFAULT_TOOLKIT_THEME, SuperGroupingProvider, TOOLKIT_THEMES, type ToolkitTheme, } from './CollapsibleGroup';
14
+ export { GroupedMessageParts, type GroupedMessagePartsProps } from './GroupedMessageParts';
13
15
  export { createToolBasedGroupingFunction, type GroupablePart, type GroupingFunction, type MessagePartGroup, } from './grouping-function';
14
16
  export { resetRememberedExpansionsForTests, SuperGroupingCard, type SuperGroupingCardProps, SuperGroupingFinalText, useActivityExpansion, } from './SuperGroupingCard';
15
17
  export { SuperGroupingTranscript, type SuperGroupingTranscriptProps } from './SuperGroupingTranscript';
@@ -1,5 +1,6 @@
1
1
  import { buildActivityTimeline, countActivityTools, excludeFinalTextFromGroups, excludePartsFromGroups, getActivityItemLabel, getActivitySummary, getActivityToolState, getFinalText, getFinalTextParts, getReasoningLabel, isStreamingToolPlaceholder, resolveActivityPhase } from "./activity-timeline.js";
2
2
  import { CollapsibleGroup, DEFAULT_TOOLKIT_THEME, SuperGroupingProvider, TOOLKIT_THEMES } from "./CollapsibleGroup.js";
3
+ import { GroupedMessageParts } from "./GroupedMessageParts.js";
3
4
  import { createToolBasedGroupingFunction } from "./grouping-function.js";
4
5
  import { SuperGroupingCard, SuperGroupingFinalText, resetRememberedExpansionsForTests, useActivityExpansion } from "./SuperGroupingCard.js";
5
6
  import { SuperGroupingTranscript } from "./SuperGroupingTranscript.js";
@@ -9,6 +10,7 @@ import { defaultGetToolGroupKey } from "./toolkit-map.js";
9
10
  export {
10
11
  CollapsibleGroup,
11
12
  DEFAULT_TOOLKIT_THEME,
13
+ GroupedMessageParts,
12
14
  SuperGroupingCard,
13
15
  SuperGroupingFinalText,
14
16
  SuperGroupingProvider,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
@@ -158,6 +158,7 @@ const TiptapComposer = react.forwardRef(
158
158
  rootCategories,
159
159
  onDraftStateChange,
160
160
  showImagePreviews = false,
161
+ attachAnyFile = false,
161
162
  onAttachmentError,
162
163
  fileIntake,
163
164
  waitForHostUploads,
@@ -304,59 +305,64 @@ const TiptapComposer = react.forwardRef(
304
305
  const clipboardData = event.clipboardData;
305
306
  if (!clipboardData) return false;
306
307
  const images = clipboard.extractPastedImages({ clipboardData });
307
- if (images.length === 0) return false;
308
- if (clipboard.clipboardHasMeaningfulText({
308
+ const otherFiles = attachAnyFile ? clipboard.extractPastedNonImageFiles({ clipboardData }) : [];
309
+ if (images.length === 0 && otherFiles.length === 0) return false;
310
+ if (otherFiles.length === 0 && clipboard.clipboardHasMeaningfulText({
309
311
  clipboardData,
310
312
  pastedFileNames: images.map((image) => image.originalName)
311
313
  })) {
312
314
  return false;
313
315
  }
314
316
  event.preventDefault();
315
- const files = images.map((image) => image.file);
317
+ const files = [...images.map((image) => image.file), ...otherFiles];
316
318
  if (fileIntake) {
317
319
  fileIntake.onPaste(files);
318
320
  return true;
319
321
  }
320
322
  for (const file of files) {
321
323
  void addAttachment(file).catch((error) => {
322
- onAttachmentError == null ? void 0 : onAttachmentError("Couldn’t paste that image.");
324
+ onAttachmentError == null ? void 0 : onAttachmentError(
325
+ clipboard.isImageFile(file) ? "Couldn’t paste that image." : "Couldn’t paste that file."
326
+ );
323
327
  athenaDiagnostics.athenaDiagnostics.error(
324
328
  "composer.attachment.error",
325
329
  error,
326
- { code: "attachment_failed", message: "Pasted image upload failed" },
330
+ { code: "attachment_failed", message: "Pasted file upload failed" },
327
331
  { source: "paste", type: file.type }
328
332
  );
329
333
  });
330
334
  }
331
335
  return true;
332
336
  },
333
- [addAttachment, fileIntake, onAttachmentError]
337
+ [addAttachment, attachAnyFile, fileIntake, onAttachmentError]
334
338
  );
335
- const addDroppedImages = react.useCallback(
339
+ const addDroppedFiles = react.useCallback(
336
340
  (files) => {
337
- const images = Array.from(files).filter(
338
- (file) => file.type.startsWith("image/")
341
+ const attachable = Array.from(files).filter(
342
+ (file) => attachAnyFile || clipboard.isImageFile(file)
339
343
  );
340
- if (images.length === 0) return false;
344
+ if (attachable.length === 0) return false;
341
345
  if (fileIntake) {
342
346
  if (!fileIntake.onDrop) return false;
343
- fileIntake.onDrop(images);
347
+ fileIntake.onDrop(attachable);
344
348
  return true;
345
349
  }
346
- for (const file of images) {
350
+ for (const file of attachable) {
347
351
  void addAttachment(file).catch((error) => {
348
- onAttachmentError == null ? void 0 : onAttachmentError("Couldn’t attach that dropped image.");
352
+ onAttachmentError == null ? void 0 : onAttachmentError(
353
+ clipboard.isImageFile(file) ? "Couldn’t attach that dropped image." : "Couldn’t attach that dropped file."
354
+ );
349
355
  athenaDiagnostics.athenaDiagnostics.error(
350
356
  "composer.attachment.error",
351
357
  error,
352
- { code: "attachment_failed", message: "Dropped image upload failed" },
358
+ { code: "attachment_failed", message: "Dropped file upload failed" },
353
359
  { source: "drop", type: file.type }
354
360
  );
355
361
  });
356
362
  }
357
363
  return true;
358
364
  },
359
- [addAttachment, fileIntake, onAttachmentError]
365
+ [addAttachment, attachAnyFile, fileIntake, onAttachmentError]
360
366
  );
361
367
  const disabledRef = react.useRef(disabled);
362
368
  disabledRef.current = disabled;
@@ -394,20 +400,20 @@ const TiptapComposer = react.forwardRef(
394
400
  if (handleAssetDrop(event, view)) return true;
395
401
  const files = (_a = event.dataTransfer) == null ? void 0 : _a.files;
396
402
  if (!(files == null ? void 0 : files.length)) return false;
397
- const handled = addDroppedImages(files);
403
+ const handled = addDroppedFiles(files);
398
404
  if (handled) event.preventDefault();
399
405
  return handled;
400
406
  },
401
- [addDroppedImages, handleAssetDrop]
407
+ [addDroppedFiles, handleAssetDrop]
402
408
  );
403
409
  const handleComposerDrop = react.useCallback(
404
410
  (event) => {
405
411
  var _a;
406
412
  if (event.defaultPrevented) return;
407
413
  if (handleAssetDrop(event.nativeEvent, (_a = editorRef.current) == null ? void 0 : _a.view)) return;
408
- if (addDroppedImages(event.dataTransfer.files)) event.preventDefault();
414
+ if (addDroppedFiles(event.dataTransfer.files)) event.preventDefault();
409
415
  },
410
- [addDroppedImages, handleAssetDrop]
416
+ [addDroppedFiles, handleAssetDrop]
411
417
  );
412
418
  const placeholderRef = react.useRef(placeholder);
413
419
  placeholderRef.current = placeholder;