@athenaintel/react 0.26.5 → 0.27.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.
- package/README.md +19 -0
- package/dist/chat/AthenaChat.cjs +1 -1
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.js +1 -1
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/StatewireQueuedMessages.cjs +44 -1
- package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
- package/dist/chat/StatewireQueuedMessages.js +45 -2
- package/dist/chat/StatewireQueuedMessages.js.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.cjs +6 -0
- package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.d.ts +2 -0
- package/dist/chat-ui/mentions/mention-chip.js +6 -0
- package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
- package/dist/diagnostics/athena-diagnostics.cjs.map +1 -1
- package/dist/diagnostics/athena-diagnostics.d.ts +1 -1
- package/dist/diagnostics/athena-diagnostics.js.map +1 -1
- package/dist/diagnostics/errors.cjs +11 -2
- package/dist/diagnostics/errors.cjs.map +1 -1
- package/dist/diagnostics/errors.d.ts +11 -2
- package/dist/diagnostics/errors.js +11 -2
- package/dist/diagnostics/errors.js.map +1 -1
- package/dist/packages/agent-runtime/src/tool-metadata.cjs +15 -0
- package/dist/packages/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/packages/agent-runtime/src/tool-metadata.js +15 -0
- package/dist/packages/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/packages/react/package.json.cjs +1 -1
- package/dist/packages/react/package.json.js +1 -1
- package/dist/provider/AthenaProvider.cjs +3 -0
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.js +3 -0
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/runtime/auth.cjs +219 -104
- package/dist/runtime/auth.cjs.map +1 -1
- package/dist/runtime/auth.d.ts +79 -5
- package/dist/runtime/auth.js +219 -104
- package/dist/runtime/auth.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AthenaChat.js","sources":["../../src/chat/AthenaChat.tsx"],"sourcesContent":["import { isGithubWakeMessage } from '@athenaintel/agent-runtime';\nimport { TiptapText } from './tiptap-text';\nimport { AthenaChatErrorBoundary } from './AthenaChatErrorBoundary';\nimport { StatewireApprovalCard } from './StatewireApprovalCard';\nimport { StatewireQueuedMessages } from './StatewireQueuedMessages';\nimport { StatewireConnectionBanner, StatewireErrorBanner } from './statewire-banners';\nimport { WaitingOnYouBanner } from './WaitingOnYouBanner';\nimport { WakeMarkerMessage } from '../chat-ui/messages/wake-marker';\nimport { ToolFallback, ToolFallbackAppearanceProvider } from '../tools/tool-fallback';\nimport { AppendDocumentToolUI } from '../tools/append-document-tool-ui';\nimport { ReadAssetToolUI } from '../tools/read-asset-tool-ui';\nimport { TOOL_UI_REGISTRY } from '../tools/tool-uis';\nimport { SuperGroupingCard, SuperGroupingFinalText } from './super-grouping/SuperGroupingCard';\nimport {\n NestedPtcComponentsProvider,\n NestedPtcMessages,\n useNestedPtcComponents,\n} from '../tools/NestedPtcMessages';\nimport { TooltipIconButton } from './tooltip-icon-button';\nimport { Button } from '../ui/button';\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../ui/collapsible';\nimport { ChatComposerDock } from '../chat-ui/thread/chat-composer-dock';\nimport { ChatThreadShell } from '../chat-ui/thread/chat-thread-shell';\nimport { StatewireHistoryEdge } from '../chat-ui/thread/statewire-history-edge';\nimport { ThreadLoadingOverlay } from '../chat-ui/thread/thread-loading-overlay';\nimport {\n ComposerSendOrStop,\n type ComposerSendOrStopProps,\n} from '../chat-ui/thread/composer-send-or-stop';\nimport { resolveComposerAction } from '../chat-ui/composer/composer-action';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport { useDictation } from '../dictation/use-dictation';\nimport { DictationStrip } from '../dictation/DictationStrip';\nimport {\n DictationCancelButton,\n DictationMicButton,\n DictationStopButton,\n} from '../dictation/dictation-controls';\nimport { composeDictationDraft, DICTATION_STATUSES } from '../dictation/dictation-state';\nimport type { DictationEngine } from '../dictation/dictation-engine';\nimport { useAthenaDictationEngine } from '../dictation/use-athena-dictation-engine';\nimport {\n TiptapComposer,\n type ComposerFileIntake,\n type TiptapComposerHandle,\n} from '../chat-ui/composer/tiptap-composer';\nimport {\n MentionAuthCtx,\n type MentionAuthContext,\n} from '../chat-ui/mentions/suggestions/data/api-client';\nimport type { MentionRootCategory } from '../chat-ui/mentions/suggestions/data/use-mention-suggestions';\nimport type { MentionTool } from '../chat-ui/mentions/suggestions/data/types';\nimport { ACTION_BAR_REVEAL_CLASS, BranchPicker } from '../chat-ui/messages/message-components';\nimport { useMessageActionsReadOnly } from '../chat-ui/messages/message-actions-config';\nimport { useAthenaRunLive } from './use-athena-run-live';\nimport {\n AthenaChatWelcome,\n AthenaChatWelcomeSuggestions,\n DEFAULT_WELCOME_SUGGESTIONS,\n welcomeComposerDelayMs,\n welcomeEntrance,\n type WelcomeSuggestion,\n} from './athena-chat-welcome';\nimport {\n ATHENA_COMPOSER_COMPONENTS,\n AthenaComposerMentionButton,\n AthenaComposerSendButton,\n} from './athena-composer-controls';\nimport { ComposerKeyboardHint, useComposerKeyboardHint } from './composer-keyboard-hint';\nimport { usePrefersReducedMotion } from '../lib/use-prefers-reduced-motion';\nimport {\n ActionBarMorePrimitive,\n ActionBarPrimitive,\n AuiIf,\n ErrorPrimitive,\n MessagePrimitive,\n ThreadPrimitive,\n useAui,\n useAuiState,\n} from '@assistant-ui/react';\nimport type {\n EmptyMessagePartComponent,\n PartState,\n ReasoningMessagePartProps,\n ReasoningMessagePartComponent,\n TextMessagePartProps,\n TextMessagePartComponent,\n ToolCallMessagePartComponent,\n ToolCallMessagePartProps,\n} from '@assistant-ui/react';\nimport {\n AlertCircleIcon,\n ArrowUpIcon,\n BrainIcon,\n CheckIcon,\n ChevronDownIcon,\n ChevronRightIcon,\n CopyIcon,\n DownloadIcon,\n ExternalLinkIcon,\n LayersIcon,\n MoreHorizontalIcon,\n PencilIcon,\n RefreshCwIcon,\n} from 'lucide-react';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type FC,\n type ReactNode,\n} from 'react';\nimport {\n AthenaStatewireThreadIdContext,\n useAthenaStatewireThreadId,\n useAthenaThreadId,\n} from '../threads/thread-id-context';\nimport { FileUploadButton } from '../composer/FileUploadButton';\nimport { ComposerQuotePreview } from '../composer/ComposerQuotePreview';\nimport { ComposerAttachmentPreview } from '../composer/ComposerAttachmentPreview';\nimport { ComposerDropZone } from '../composer/ComposerDropZone';\nimport { useQuote, QuoteProvider, useQuoteFromPostMessage } from '../composer/QuoteContext';\nimport { AttachmentProvider, useAttachments } from '../composer/AttachmentContext';\nimport { buildComposedMessage } from '../composer/build-composed-message';\nimport { useAttachFiles } from '../composer/useAttachFiles';\nimport { useAthenaConfig } from '../provider/AthenaContext';\nimport { createAthenaSpacesUrl } from '../lib/athena-urls';\nimport { cn, isRecord } from '../lib/utils';\nimport { getToolkitDisplayInfo } from '../toolkits';\nimport {\n RUN_ACTIVITY_COUNTER_SECONDS,\n RUN_ACTIVITY_STALL_SECONDS,\n runActivityKey,\n runActivityLabel,\n runActivityVerb,\n} from './run-activity';\nimport {\n formatDayLabel,\n formatMessageDateTime,\n formatMessageTime,\n isSameCalendarDay,\n parseMessageTime,\n readMessageCreatedAt,\n} from './message-time';\nimport { ThreadScrollToBottom } from './thread-scroll-to-bottom';\n\nfunction QuotePostMessageBridge() {\n useQuoteFromPostMessage();\n return null;\n}\n\nexport type { WelcomeSuggestion } from './athena-chat-welcome';\n\nexport interface AthenaChatProps {\n /** CSS class name for the root element. */\n className?: string;\n /** Welcome heading text. Defaults to \"Hello there!\" */\n welcomeMessage?: string;\n /** Welcome subheading text. */\n welcomeSubtext?: string;\n /**\n * Maximum width of the reading column (messages, welcome, composer).\n * Defaults to \"46rem\" — about 760 px, a comfortable measure for 15 px text.\n */\n maxWidth?: string;\n /**\n * Scroll anchoring for new turns. \"bottom\" (default) keeps the viewport\n * pinned to the end while the assistant streams — classic chat follow.\n * \"top\" pins the just-sent user message to the top of the viewport and\n * intentionally does NOT follow the streaming response (assistant-ui\n * disables autoScroll in that mode), so readers scroll at their own pace.\n */\n turnAnchor?: \"top\" | \"bottom\";\n /**\n * Marks the transcript read-only: Edit and Regenerate hide while Copy stays\n * available. For threads whose server rejects dispatch (e.g. legacy\n * pre-cutover conversations) — the runtime's static capability flags cannot\n * express a per-thread fence, so the host that knows passes it here.\n */\n readOnly?: boolean;\n /** Additional tool UIs to register by name. */\n toolUIs?: Record<string, ToolCallMessagePartComponent>;\n /** Tools / Toolkits offered by the composer's `@` menu beside the asset\n * library. Defaults to the toolkits enabled on the provider. */\n mentionTools?: MentionTool[];\n /** Suggestion cards shown on the welcome screen. Pass `[]` to hide.\n * For workflow launchers outside AthenaChat, use `useSendMessage()`.\n */\n welcomeSuggestions?: WelcomeSuggestion[];\n /** Optional component overrides for message containers and key message parts. */\n components?: AthenaChatComponents;\n /**\n * Fold a turn's tool calls into one collapsible activity group with a\n * count, the answer rendered below it. Defaults to `true`; pass `false` to\n * list every tool card inline in the order it was called.\n */\n groupToolCalls?: boolean;\n /**\n * Extra composer toolbar content and send hooks. `toolbarStart` renders\n * after the attach button, `toolbarEnd` renders before the mic and Send.\n * Slot components render inside the chat's thread scope, so `useAthenaRunLive`\n * and `useAppendToComposer` work in them.\n */\n composer?: AthenaChatComposerSlots;\n /**\n * Built-in microphone dictation in the composer: a mic left of Send that\n * swaps the editor for a live waveform while recording, then puts the words\n * into the draft (Stop) or sends them (Send). Recording is transcribed by\n * Athena (Deepgram) once the user stops; the words land after a short\n * \"Transcribing…\" pause. Defaults to `true`. Pass `false` to remove it, or\n * options to pick the language or a custom speech engine.\n */\n dictation?: boolean | AthenaChatDictationOptions;\n}\n\nexport interface AthenaChatComposerSlots {\n /** Toolbar contents after the attach button. */\n toolbarStart?: ReactNode;\n /** Toolbar contents before the mic and the send/stop control. */\n toolbarEnd?: ReactNode;\n /** Host work to run before a draft submits (also runs for a dictated send). */\n onBeforeSend?: ComposerSendOrStopProps['onBeforeSend'];\n}\n\nexport interface AthenaChatDictationOptions {\n /**\n * Speech engine; defaults to record-then-transcribe through Athena\n * (`createRecordedDictationEngine`). Pass `createWebSpeechDictationEngine()`\n * for the browser's live Web Speech API instead.\n */\n engine?: DictationEngine;\n /** BCP-47 language tag; defaults to the document language. */\n lang?: string;\n}\n\nexport interface AthenaChatMessagePartComponents {\n Text?: TextMessagePartComponent;\n Reasoning?: ReasoningMessagePartComponent;\n Empty?: EmptyMessagePartComponent;\n}\n\nexport interface AthenaChatComponents {\n UserMessage?: FC;\n AssistantMessage?: FC;\n AssistantActionBar?: FC<AthenaAssistantActionBarProps>;\n /**\n * Rendered in a leading column on every assistant turn (a small avatar or\n * mark). Without it there is no leading column: the reply sits flush with\n * the thread column and is told apart from the right-aligned user bubbles by\n * alignment alone.\n */\n AssistantAvatar?: FC;\n messageParts?: AthenaChatMessagePartComponents;\n}\n\nexport interface AthenaUserMessageProps {\n TextComponent?: TextMessagePartComponent;\n}\n\nexport interface AthenaAssistantActionBarProps {\n className?: string;\n}\n\nexport interface AthenaAssistantMessageProps {\n toolUIs: Record<string, ToolCallMessagePartComponent>;\n /** Leading-column content for the turn; no leading column at all when unset. */\n AvatarComponent?: FC;\n TextComponent?: TextMessagePartComponent;\n ReasoningComponent?: ReasoningMessagePartComponent;\n EmptyComponent?: EmptyMessagePartComponent;\n ActionBarComponent?: FC<AthenaAssistantActionBarProps>;\n /** Fold the turn's tool calls into one collapsible activity group. Defaults to `true`. */\n groupToolCalls?: boolean;\n}\n\nexport interface AthenaReasoningPartProps extends ReasoningMessagePartProps {\n TextComponent?: TextMessagePartComponent;\n}\n\ninterface AthenaChatDefaultComponentsContextValue {\n toolUIs: Record<string, ToolCallMessagePartComponent>;\n TextComponent: TextMessagePartComponent;\n ReasoningComponent?: ReasoningMessagePartComponent;\n EmptyComponent: EmptyMessagePartComponent;\n ActionBarComponent: FC<AthenaAssistantActionBarProps>;\n AvatarComponent?: FC;\n groupToolCalls: boolean;\n}\n\nconst AthenaChatDefaultComponentsContext =\n createContext<AthenaChatDefaultComponentsContextValue | null>(null);\n\nconst AthenaReasoningTextComponentContext = createContext<TextMessagePartComponent | null>(null);\n\nconst useAthenaChatDefaultComponents = (): AthenaChatDefaultComponentsContextValue => {\n const value = useContext(AthenaChatDefaultComponentsContext);\n\n if (!value) {\n throw new Error('Athena default chat components must be used within AthenaChat.');\n }\n\n return value;\n};\n\nconst AthenaDefaultAssistantMessage: FC = () => {\n const {\n toolUIs,\n TextComponent,\n ReasoningComponent,\n EmptyComponent,\n ActionBarComponent,\n AvatarComponent,\n groupToolCalls,\n } = useAthenaChatDefaultComponents();\n\n return (\n <AthenaAssistantMessage\n toolUIs={toolUIs}\n AvatarComponent={AvatarComponent}\n TextComponent={TextComponent}\n ReasoningComponent={ReasoningComponent}\n EmptyComponent={EmptyComponent}\n ActionBarComponent={ActionBarComponent}\n groupToolCalls={groupToolCalls}\n />\n );\n};\n\nconst AthenaDefaultUserMessage: FC = () => {\n const { TextComponent } = useAthenaChatDefaultComponents();\n\n return <AthenaUserMessage TextComponent={TextComponent} />;\n};\n\nconst getReasoningTokensFromMetadata = (metadata: unknown): number | undefined => {\n if (!isRecord(metadata)) {\n return undefined;\n }\n\n const customMetadata = metadata.custom;\n if (!isRecord(customMetadata)) {\n return undefined;\n }\n\n const athenaMetadata = customMetadata._athena;\n if (!isRecord(athenaMetadata)) {\n return undefined;\n }\n\n const reasoningTokens = athenaMetadata.reasoningTokens;\n return typeof reasoningTokens === 'number' && Number.isFinite(reasoningTokens)\n ? reasoningTokens\n : undefined;\n};\n\nconst formatReasoningTokens = (reasoningTokens: number) =>\n `${reasoningTokens.toLocaleString('en-US')} ${reasoningTokens === 1 ? 'token' : 'tokens'}`;\n\nconst withNestedPtcMessages = (\n ToolUI: ToolCallMessagePartComponent\n): ToolCallMessagePartComponent => {\n const ToolUIWithNestedPtcMessages: ToolCallMessagePartComponent = (props) => {\n const nestedComponents = useNestedPtcComponents(ToolFallback);\n\n return (\n <>\n <ToolUI {...props} />\n <NestedPtcMessages components={nestedComponents} />\n </>\n );\n };\n\n return ToolUIWithNestedPtcMessages;\n};\n\nexport const AthenaChat: FC<AthenaChatProps> = ({\n className,\n welcomeMessage = \"Hello there!\",\n welcomeSubtext = \"What can I help you with?\",\n maxWidth = \"46rem\",\n turnAnchor = \"bottom\",\n readOnly = false,\n toolUIs,\n mentionTools,\n welcomeSuggestions = DEFAULT_WELCOME_SUGGESTIONS,\n components,\n groupToolCalls = true,\n composer: composerSlots,\n dictation = true,\n}) => {\n const athenaConfig = useAthenaConfig();\n // The chat surface is per thread. `AthenaProvider` keeps the host's\n // children mounted across a thread switch and swaps only the client under\n // them, so what used to reset with the whole tree — the composer draft, the\n // viewport's scroll position, the approval card and banner state, a caught\n // render crash — is reset here instead, keyed on the attached thread (the\n // id the provider publishes together with that thread's client, so the\n // fresh surface never renders against the previous thread's runtime).\n const statewireThreadId = useContext(AthenaStatewireThreadIdContext);\n // The mention menu's GraphQL credentials: the backend and credential the\n // provider resolved. `athenaConfig` keeps its identity across token\n // rotations (its `token` is a getter over a ref — see useAthenaConfigValue),\n // so this object is stable too. The mention store lists `accessToken` among\n // its memo dependencies, so it rebuilds (and refetches its lists) on the\n // composer's next render after a rotation; the getter is what hands the\n // rotated token to any fetch before that render. With neither token nor\n // API key the fetch rides the same-origin session cookie, as the SDK's\n // upload and thread REST calls do.\n const mentionAuth = useMemo<MentionAuthContext>(\n () => ({\n backendUrl: athenaConfig.backendUrl,\n appUrl: athenaConfig.appUrl,\n apiKey: athenaConfig.apiKey,\n credentials: 'include',\n get accessToken() {\n return athenaConfig.token ?? undefined;\n },\n getAccessToken: async () => (await athenaConfig.getToken?.()) ?? undefined,\n renewAccessToken: async () => (await athenaConfig.getToken?.({ force: true })) ?? undefined,\n }),\n [athenaConfig],\n );\n const providerMentionTools = useMemo<MentionTool[]>(() => {\n const uniqueToolkitIds = Array.from(new Set(athenaConfig.enabledToolkits));\n\n return uniqueToolkitIds.map((id) => {\n const toolkit = getToolkitDisplayInfo(id);\n\n return {\n id: toolkit.id,\n name: toolkit.name,\n description: toolkit.description,\n icon: toolkit.icon,\n type: 'toolkit',\n };\n });\n }, [athenaConfig.enabledToolkits]);\n const tools = mentionTools ?? providerMentionTools;\n const mergedToolUIs = useMemo(\n () => ({\n append_markdown_to_athena_document: AppendDocumentToolUI,\n read_full_asset: ReadAssetToolUI,\n read_asset: ReadAssetToolUI,\n ...TOOL_UI_REGISTRY,\n ...toolUIs,\n }),\n [toolUIs],\n );\n\n const textComponent = components?.messageParts?.Text ?? TiptapText;\n const reasoningComponent = components?.messageParts?.Reasoning;\n const emptyComponent = components?.messageParts?.Empty ?? AthenaAssistantMessageEmpty;\n const actionBarComponent = components?.AssistantActionBar ?? AthenaAssistantActionBar;\n const avatarComponent = components?.AssistantAvatar;\n\n const defaultComponentsContextValue = useMemo<AthenaChatDefaultComponentsContextValue>(\n () => ({\n toolUIs: mergedToolUIs,\n TextComponent: textComponent,\n ReasoningComponent: reasoningComponent,\n EmptyComponent: emptyComponent,\n ActionBarComponent: actionBarComponent,\n AvatarComponent: avatarComponent,\n groupToolCalls,\n }),\n [\n actionBarComponent,\n avatarComponent,\n emptyComponent,\n groupToolCalls,\n mergedToolUIs,\n reasoningComponent,\n textComponent,\n ],\n );\n const AssistantMessageComponent = components?.AssistantMessage ?? AthenaDefaultAssistantMessage;\n const UserMessageComponent = components?.UserMessage ?? AthenaDefaultUserMessage;\n const messageComponents = useMemo(\n () => ({\n UserMessage: UserMessageComponent,\n AssistantMessage: AssistantMessageComponent,\n }),\n [AssistantMessageComponent, UserMessageComponent],\n );\n\n return (\n <AthenaChatDefaultComponentsContext.Provider value={defaultComponentsContextValue}>\n {/* Contain render crashes to the chat pane (telemetry + retry) instead of\n unmounting the integrator's subtree. */}\n <AthenaChatErrorBoundary key={statewireThreadId ?? undefined}>\n {/* Every tool call in the thread — generic fallback, dedicated tool\n UI, nested PTC sub-call — renders as the one-line thread row. */}\n <ToolFallbackAppearanceProvider appearance=\"thread\">\n <ChatThreadShell\n overlay={<ThreadLoadingOverlay />}\n panelClassName={cn(\n 'aui-root aui-thread-root @container relative flex h-full flex-col bg-background',\n className,\n )}\n maxWidth={maxWidth}\n turnAnchor={turnAnchor}\n readOnly={readOnly}\n // Persistent \"waiting on you\" strip above the viewport; the approval\n // card it points at stays in the sticky footer below.\n banners={<WaitingOnYouBanner className=\"px-4 pt-3\" />}\n viewportClassName=\"aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth px-4 pt-4\"\n contentClassName=\"flex w-full flex-1 flex-col\"\n viewportOverlay={<ThreadScrollToTop />}\n welcome={\n <AthenaChatWelcome welcomeMessage={welcomeMessage} welcomeSubtext={welcomeSubtext} />\n }\n beforeMessages={<StatewireHistoryEdge className=\"aui-thread-history-edge\" />}\n components={messageComponents}\n runningIndicator={null}\n // The scroll-to-bottom pill is docked on the composer (see\n // AthenaChatComposer) instead of floating over the messages; the\n // footer's top padding is the room it sits in.\n scrollToBottom={null}\n viewportFooterClassName=\"aui-thread-viewport-footer sticky bottom-0 mx-auto mt-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 overflow-visible rounded-t-3xl bg-background pt-4 pb-4 md:pb-6\"\n viewportFooter={\n <>\n {/* Empty state: the suggestion cards sit directly above the\n composer (the greeting stays centred in the viewport). */}\n {welcomeSuggestions.length > 0 && (\n <ThreadPrimitive.Empty>\n <AthenaChatWelcomeSuggestions suggestions={welcomeSuggestions} />\n </ThreadPrimitive.Empty>\n )}\n <StatewireConnectionBanner />\n <StatewireErrorBanner />\n <StatewireApprovalCard />\n <StatewireQueuedMessages />\n <AttachmentProvider>\n <QuoteProvider>\n <QuotePostMessageBridge />\n <MentionAuthCtx.Provider value={mentionAuth}>\n <AthenaChatComposer\n tools={tools}\n slots={composerSlots}\n dictation={dictation}\n welcomeSuggestionCount={welcomeSuggestions.length}\n />\n </MentionAuthCtx.Provider>\n </QuoteProvider>\n </AttachmentProvider>\n </>\n }\n />\n </ToolFallbackAppearanceProvider>\n </AthenaChatErrorBoundary>\n </AthenaChatDefaultComponentsContext.Provider>\n );\n};\n\nconst THREAD_VIEWPORT_ATTR = 'data-aui-thread-viewport';\n\nconst useScrollToTop = () => {\n const [isAtTop, setIsAtTop] = useState(true);\n const [buttonEl, setButtonEl] = useState<HTMLButtonElement | null>(null);\n\n const containerRef = useCallback((node: HTMLButtonElement | null) => {\n setButtonEl(node);\n }, []);\n\n const getViewport = useCallback((): HTMLElement | null => {\n if (!buttonEl) return null;\n return buttonEl.closest(`[${THREAD_VIEWPORT_ATTR}]`) as HTMLElement | null;\n }, [buttonEl]);\n\n useEffect(() => {\n const viewport: HTMLElement | null = getViewport();\n if (!viewport) return;\n\n const handleScroll = () => {\n setIsAtTop(viewport.scrollTop <= 50);\n };\n\n handleScroll();\n viewport.addEventListener('scroll', handleScroll, { passive: true });\n return () => viewport.removeEventListener('scroll', handleScroll);\n }, [getViewport]);\n\n const handleClick = useCallback(() => {\n const viewport: HTMLElement | null = getViewport();\n if (!viewport) return;\n viewport.scrollTo({ top: 0, behavior: 'smooth' });\n }, [getViewport]);\n\n return { isAtTop, containerRef, handleClick };\n};\n\nconst ThreadScrollToTop: FC = () => {\n const { isAtTop, containerRef, handleClick } = useScrollToTop();\n const isEmpty = useAuiState((s) => s.thread.isEmpty);\n\n if (isEmpty) return null;\n\n return (\n <div className=\"sticky top-0 z-10 mx-auto flex h-0 w-full max-w-(--thread-max-width) justify-center\">\n <TooltipIconButton\n ref={containerRef}\n tooltip=\"Scroll to top\"\n variant=\"outline\"\n className={cn('aui-thread-scroll-to-top absolute top-2 rounded-full p-4 dark:bg-background dark:hover:bg-accent', isAtTop && 'invisible')}\n onClick={handleClick}\n >\n <ArrowUpIcon />\n </TooltipIconButton>\n </div>\n );\n};\n\n/**\n * The asset-library categories of AthenaChat's `@` menu. Browse profiles,\n * team and drives are left out: they need browser-side scoping or a workspace\n * id that API-key auth does not carry. The Tools / Toolkits categories are\n * added when the host (or the provider's enabled toolkits) offers any.\n */\nconst ATHENA_CHAT_MENTION_CATEGORIES: readonly MentionRootCategory[] = [\n 'favorites',\n 'assets',\n 'projects',\n 'folders',\n];\n\n/**\n * AthenaChat's composer: the shared chat-ui Tiptap editor and `@` mention menu\n * with AthenaChat's quote and attachment pills composed into the send.\n *\n * A draft with a quote or attachment pills — text or not — is intercepted on\n * submit and dispatched as one composed message through the composer runtime,\n * the path the server-owned queue observes, so a mid-run submit queues like\n * any other send. Pasted images upload into the pills through the same intake\n * as the paperclip and the drop zone, and every submit path (Enter, the send\n * button) waits for an in-flight upload so a send never leaves without its\n * attachment. The send control resolves send / queue / stop through the\n * shared chat-ui logic.\n *\n * The chrome is the shared dock's paper appearance (`data-appearance=\"paper\"`\n * on `.aui-composer-root`): the drop zone reports drag-over into\n * `data-drag-active`, the first focus in a browser shows the Enter /\n * Shift+Enter hint until the first send, and a thread that mounts empty\n * brings the composer in last, after the greeting and the suggestion cards.\n */\nconst AthenaChatComposer: FC<{\n tools: MentionTool[];\n slots?: AthenaChatComposerSlots;\n dictation: boolean | AthenaChatDictationOptions;\n /** How many suggestion cards precede the composer's entrance in the empty state. */\n welcomeSuggestionCount: number;\n}> = ({ tools, slots, dictation, welcomeSuggestionCount }) => {\n const aui = useAui();\n const threadId = useAthenaStatewireThreadId();\n const { appUrl } = useAthenaConfig();\n const { attachments, clearAttachments, isUploading } = useAttachments();\n const { quote, clearQuote } = useQuote();\n const { attachFiles } = useAttachFiles();\n const composerRef = useRef<TiptapComposerHandle>(null);\n const [hasText, setHasText] = useState(false);\n const isRunning = useAuiState((state) => state.optional.thread?.isRunning ?? false);\n const [dragActive, setDragActive] = useState(false);\n const keyboardHint = useComposerKeyboardHint();\n const reducedMotion = usePrefersReducedMotion();\n // The staged entrance belongs to the empty state only: a composer that\n // mounts over an existing transcript is simply there.\n const isEmpty = useAuiState((state) => state.thread.isEmpty);\n const [mountedEmpty] = useState(() => isEmpty);\n const entrance = welcomeEntrance(\n welcomeComposerDelayMs(welcomeSuggestionCount),\n reducedMotion || !mountedEmpty,\n );\n\n // Dictation: the hook is inert until `start()`, so it mounts even when the\n // mic is turned off; `isSupported` hides the control where the engine is\n // missing (Firefox) instead of rendering a button that cannot work.\n const dictationEnabled = dictation !== false;\n const dictationOptions = typeof dictation === 'object' ? dictation : undefined;\n // Words join the draft that existed before recording (manual edits are\n // kept); the composer runtime mirrors `setText` into the Tiptap editor.\n const appendSpokenText = useCallback(\n (spoken: string) => {\n if (!spoken) return;\n aui.composer.setText(composeDictationDraft(aui.composer.getState().text ?? '', spoken));\n },\n [aui],\n );\n const dictationEngine = useAthenaDictationEngine(dictationOptions?.engine);\n const dictationCtl = useDictation({\n engine: dictationEngine,\n lang: dictationOptions?.lang,\n // A recognizer that gives up on its own (silence window) still hands\n // over what it heard instead of dropping the words with the session.\n onAutoEnd: appendSpokenText,\n });\n const recording = dictationEnabled && dictationCtl.isActive;\n const showMic = dictationEnabled && dictationCtl.isSupported;\n // A host that turns dictation off mid-session takes the controls away with\n // it; release the microphone and the recognizer rather than letting them\n // run on with no way to stop them.\n const { isActive: dictationActive, cancel: cancelDictation } = dictationCtl;\n useEffect(() => {\n if (!dictationEnabled && dictationActive) cancelDictation();\n }, [cancelDictation, dictationActive, dictationEnabled]);\n\n const rootCategories = useMemo<readonly MentionRootCategory[]>(() => {\n const categories = [...ATHENA_CHAT_MENTION_CATEGORIES];\n if (tools.some((tool) => tool.type === 'toolkit')) categories.push('toolkits');\n if (tools.some((tool) => tool.type === 'tool')) categories.push('tools');\n return categories;\n }, [tools]);\n\n // The submit paths are captured once by the editor's keybinding, so they\n // read the current draft extras through refs.\n const attachmentsRef = useRef(attachments);\n attachmentsRef.current = attachments;\n const quoteRef = useRef(quote);\n quoteRef.current = quote;\n const hasExtras = attachments.length > 0 || quote !== null;\n\n // A submit during an upload parks until the pills have the asset; the\n // waiters resolve on the render that turns `isUploading` off, by which\n // point `attachmentsRef` holds the uploaded asset.\n const isUploadingRef = useRef(isUploading);\n isUploadingRef.current = isUploading;\n const uploadWaitersRef = useRef<Array<() => void>>([]);\n useEffect(() => {\n if (isUploading) return;\n const waiters = uploadWaitersRef.current;\n uploadWaitersRef.current = [];\n for (const resolve of waiters) resolve();\n }, [isUploading]);\n const waitForHostUploads = useCallback(() => {\n if (!isUploadingRef.current) return;\n return new Promise<void>((resolve) => {\n uploadWaitersRef.current.push(resolve);\n });\n }, []);\n\n const sendComposed = useCallback(\n (userText: string): boolean => {\n const message = buildComposedMessage({\n attachments: attachmentsRef.current,\n quote: quoteRef.current,\n userText,\n appUrl,\n });\n if (!message) return false;\n // steer: false — a mid-run send queues behind the active run instead of\n // interrupting it; idle sends dispatch immediately.\n aui.composer.setText(message);\n aui.composer.send({ steer: false });\n clearAttachments();\n clearQuote();\n return true;\n },\n [appUrl, aui, clearAttachments, clearQuote],\n );\n\n // Consumes the editor's draft (possibly empty) only when there are extras\n // to compose with it.\n const interceptSubmit = useCallback(\n (text: string) =>\n attachmentsRef.current.length > 0 || quoteRef.current !== null\n ? sendComposed(text)\n : false,\n [sendComposed],\n );\n\n // Pasted images go through the pills' intake; drops are left to the\n // enclosing ComposerDropZone.\n const fileIntake = useMemo<ComposerFileIntake>(\n () => ({\n onPaste: (files) => {\n void attachFiles(files, 'paste');\n },\n }),\n [attachFiles],\n );\n\n // Stop: the spoken words join the draft and the editor comes back for review.\n const stopDictation = useCallback(async () => {\n appendSpokenText((await dictationCtl.stop()).text);\n }, [appendSpokenText, dictationCtl]);\n\n // Send: same merge, then dispatched the way the send button would — through\n // the composed-message path when pills are pending, else straight through\n // the composer runtime (a mid-run send queues; see sendComposed).\n const sendDictation = useCallback(async () => {\n const { text: spoken, error } = await dictationCtl.stop();\n const text = composeDictationDraft(aui.composer.getState().text ?? '', spoken);\n // A failed transcription has nothing to send; keep whatever landed in the\n // draft for review next to the error notice rather than dispatching a\n // message that is missing the dictated words.\n if (error) {\n aui.composer.setText(text);\n return;\n }\n const extras = attachmentsRef.current.length > 0 || quoteRef.current !== null;\n if (!text && !extras) return;\n // The merged draft is persisted before any host hook runs, so a hook that\n // rejects leaves the dictated words in the composer instead of losing them.\n aui.composer.setText(text);\n const action = resolveComposerAction({ hasDraft: true, isRunning });\n if (action === 'stop') return;\n try {\n await slots?.onBeforeSend?.({ action });\n } catch (error) {\n athenaDiagnostics.emit('composer.dictation', {\n level: 'warn',\n data: {\n phase: 'before_send_rejected',\n error: error instanceof Error ? error.message : String(error),\n },\n });\n return;\n }\n if (extras) {\n sendComposed(text);\n return;\n }\n aui.composer.send({ steer: false });\n }, [aui, dictationCtl, isRunning, sendComposed, slots]);\n\n return (\n <ComposerDropZone onDragActiveChange={setDragActive}>\n {/* React delivers `onFocus` as focusin, so the editor's focus reaches\n this wrapper; the same element carries the staged entrance. */}\n <div\n className={cn('aui-composer-entrance', entrance.className)}\n style={entrance.style}\n onFocus={keyboardHint.onFocus}\n >\n <ChatComposerDock\n appearance=\"paper\"\n dragActive={dragActive}\n aboveSurface={<ThreadScrollToBottom />}\n beforeEditor={\n <>\n <ComposerQuotePreview />\n <ComposerAttachmentPreview />\n </>\n }\n editor={\n <>\n {/* The editor stays mounted while recording so its draft and\n mention state survive; the waveform takes its place visually. */}\n <div className={cn(recording && 'hidden')}>\n <TiptapComposer\n ref={composerRef}\n threadId={threadId}\n appearance=\"paper\"\n placeholder=\"Type @ to tag an asset\"\n tools={tools}\n rootCategories={rootCategories}\n onDraftStateChange={setHasText}\n waitForHostUploads={waitForHostUploads}\n interceptSubmit={interceptSubmit}\n fileIntake={fileIntake}\n onSubmitted={keyboardHint.onSubmitted}\n />\n </div>\n {recording && (\n <DictationStrip\n status={dictationCtl.status}\n transcript={dictationCtl.transcript}\n stream={dictationCtl.stream}\n stoppingLabel={dictationCtl.engine.stoppingLabel}\n />\n )}\n {dictationEnabled && dictationCtl.status === DICTATION_STATUSES.error && dictationCtl.error && (\n <p className=\"aui-dictation-error px-1.5 pb-1 text-destructive text-xs\" role=\"alert\">\n {dictationCtl.error.message}\n </p>\n )}\n </>\n }\n toolbarStart={\n <div className=\"flex items-center gap-1\">\n {recording ? (\n <DictationCancelButton onClick={dictationCtl.cancel} />\n ) : (\n <>\n <FileUploadButton className=\"aui-composer-attach size-8 rounded-full p-0 disabled:opacity-30\" />\n <AthenaComposerMentionButton\n onClick={() => composerRef.current?.openMentionMenu?.()}\n />\n {slots?.toolbarStart}\n </>\n )}\n </div>\n }\n toolbarEnd={\n <div className=\"flex items-center gap-1\">\n {recording ? (\n <>\n <DictationStopButton\n onClick={() => void stopDictation()}\n disabled={dictationCtl.status === DICTATION_STATUSES.stopping}\n />\n <AthenaComposerSendButton\n action={isRunning ? 'queue' : 'send'}\n onSend={() => void sendDictation()}\n disabled={dictationCtl.status !== DICTATION_STATUSES.listening || isUploading}\n title={isUploading ? 'Upload in progress...' : undefined}\n />\n </>\n ) : (\n <>\n {slots?.toolbarEnd}\n {showMic && (\n <DictationMicButton onClick={dictationCtl.start} disabled={isUploading} />\n )}\n <ComposerSendOrStop\n composerRef={composerRef}\n hasDraft={hasText || hasExtras}\n sendBlockedReason={isUploading ? 'Upload in progress...' : null}\n onBeforeSend={slots?.onBeforeSend}\n components={ATHENA_COMPOSER_COMPONENTS}\n />\n </>\n )}\n </div>\n }\n belowSurface={<ComposerKeyboardHint visible={keyboardHint.visible} />}\n />\n </div>\n </ComposerDropZone>\n );\n};\n\nconst MessageError: FC = () => (\n <MessagePrimitive.Error>\n <ErrorPrimitive.Root className=\"aui-message-error-root mt-2 flex items-start gap-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm dark:bg-destructive/5 dark:text-red-200\">\n <AlertCircleIcon className=\"mt-0.5 size-4 shrink-0\" />\n <ErrorPrimitive.Message className=\"aui-message-error-message grow\" />\n <ActionBarPrimitive.Reload asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-6 shrink-0 text-destructive hover:text-destructive dark:text-red-200 dark:hover:text-red-100\"\n >\n <RefreshCwIcon className=\"size-3.5\" />\n </Button>\n </ActionBarPrimitive.Reload>\n </ErrorPrimitive.Root>\n </MessagePrimitive.Error>\n);\n\n/**\n * The quiet status line under a running turn: one pulsing dot, the verb\n * (\"Thinking…\", or the running tool's activity such as \"Searching the web…\"),\n * the elapsed seconds once the counter is due, and a stall tone once nothing\n * has streamed for a while — so a busy run and a possibly-stuck one stop\n * looking identical. The timer restarts whenever `resetKey` changes.\n */\nconst RunStatusLine: FC<{\n verb: string;\n resetKey: string;\n /** Render nothing until the counter is due (a host header already names the verb). */\n counterOnly?: boolean;\n className?: string;\n}> = ({ verb, resetKey, counterOnly = false, className }) => {\n const [seconds, setSeconds] = useState(0);\n useEffect(() => {\n setSeconds(0);\n const startedAt = Date.now();\n const timer = setInterval(() => {\n setSeconds(Math.floor((Date.now() - startedAt) / 1000));\n }, 1000);\n return () => clearInterval(timer);\n }, [resetKey]);\n const stalled = seconds >= RUN_ACTIVITY_STALL_SECONDS;\n if (counterOnly && seconds < RUN_ACTIVITY_COUNTER_SECONDS) return null;\n return (\n <div\n data-slot=\"run-status-line\"\n data-stalled={stalled ? 'true' : undefined}\n className={cn(\n 'aui-run-activity mt-2 flex items-center gap-2 px-1 text-[12px] text-muted-foreground',\n className,\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n 'size-1.5 shrink-0 rounded-full bg-current opacity-60',\n !stalled && 'animate-pulse motion-reduce:animate-none',\n )}\n />\n <span\n aria-hidden=\"true\"\n className={cn('tabular-nums', stalled && 'text-amber-600 dark:text-amber-400')}\n >\n {runActivityLabel(seconds, verb)}\n </span>\n {/* The visible counter ticks every second; announcing each tick would\n drown a screen reader, so the live region only speaks the two\n meaningful transitions: what the run is doing, and that it looks\n stalled. */}\n <span aria-live=\"polite\" className=\"sr-only\">\n {stalled ? 'Assistant is still working; nothing new for over thirty seconds.' : `${verb}…`}\n </span>\n </div>\n );\n};\n\nconst AthenaAssistantMessageEmpty: EmptyMessagePartComponent = ({ status }) => {\n if (status?.type !== 'running') return null;\n return <RunStatusLine verb=\"Thinking\" resetKey=\"empty\" className=\"mt-0\" />;\n};\n\n/**\n * Renders the empty/loading indicator while a message is running but has no\n * parts yet. `MessagePrimitive.GroupedParts` only renders existing parts, so\n * the indicator can't live inside its switch — it goes here as a sibling.\n */\nconst AthenaMessageEmptyIndicator: FC<{ EmptyComponent: EmptyMessagePartComponent }> = ({\n EmptyComponent,\n}) => {\n const hasParts = useAuiState((s) => s.message.parts.length > 0);\n const isRunning = useAuiState((s) => s.message.status?.type === 'running');\n if (hasParts || !isRunning) return null;\n return <EmptyComponent status={{ type: 'running' }} />;\n};\n\n/**\n * Run-liveness line under a running message whose tail is a tool call: the\n * tool's own verb from the shared registry, an elapsed counter that resets\n * whenever the stream moves the tail part, and the stall tone. Text and\n * reasoning tails animate on their own and render no line.\n */\nconst AthenaMessageActivityIndicator: FC = () => {\n const isRunning = useAuiState((s) => s.message.status?.type === 'running');\n const activityKey = useAuiState((s) => runActivityKey(s.message.parts));\n const verb = useAuiState((s) => runActivityVerb(s.message.parts));\n if (!isRunning || activityKey === null) return null;\n return <RunStatusLine verb={verb ?? 'Working'} resetKey={activityKey} />;\n};\n\n/**\n * The grouped view's running meta: the activity card already names the verb,\n * so this adds only the elapsed counter (after three seconds) and the stall\n * tone, keyed to the stream's tail like the inline indicator.\n */\nconst AthenaGroupedRunMeta: FC = () => {\n const activityKey = useAuiState((s) => runActivityKey(s.message.parts));\n return (\n <RunStatusLine\n verb=\"Working\"\n resetKey={activityKey ?? 'thinking'}\n counterOnly\n className=\"mt-1 px-0\"\n />\n );\n};\nconst renderGroupedRunningMeta = () => <AthenaGroupedRunMeta />;\n\n/**\n * The centered hairline with the date, rendered above the first message of a\n * calendar day that differs from the previous message's. Both messages need\n * the runtime's `_created_at` stamp; without it there is nothing truthful to\n * separate on.\n */\nconst MessageDaySeparator: FC = () => {\n const stamp = useAuiState((s) => readMessageCreatedAt(s.message.metadata?.custom));\n const previousStamp = useAuiState((s) => {\n const index = s.message.index;\n const previous = index > 0 ? s.thread.messages[index - 1] : undefined;\n return readMessageCreatedAt(previous?.metadata?.custom);\n });\n const label = useMemo(() => {\n const date = stamp ? parseMessageTime(stamp) : null;\n const previous = previousStamp ? parseMessageTime(previousStamp) : null;\n if (!date || !previous || isSameCalendarDay(date, previous)) return null;\n return formatDayLabel(date);\n }, [stamp, previousStamp]);\n if (!label) return null;\n return (\n <div\n role=\"separator\"\n aria-label={label}\n data-slot=\"day-separator\"\n className=\"aui-day-separator mb-3 flex w-full items-center gap-3 text-[11px] font-medium text-muted-foreground\"\n >\n <span aria-hidden=\"true\" className=\"h-px flex-1 bg-border\" />\n <span>{label}</span>\n <span aria-hidden=\"true\" className=\"h-px flex-1 bg-border\" />\n </div>\n );\n};\n\n/**\n * The message's clock time, revealed on hover beside the action bar (the\n * full date in its `title`). Reads the runtime's `_created_at` stamp; a\n * message without one shows no time rather than a wrong one.\n */\nconst MessageTimestamp: FC<{ className?: string }> = ({ className }) => {\n const stamp = useAuiState((s) => readMessageCreatedAt(s.message.metadata?.custom));\n const date = useMemo(() => (stamp ? parseMessageTime(stamp) : null), [stamp]);\n if (!date) return null;\n return (\n <time\n dateTime={date.toISOString()}\n title={formatMessageDateTime(date)}\n data-slot=\"message-timestamp\"\n className={cn(\n 'aui-message-timestamp shrink-0 text-[11px] tabular-nums text-muted-foreground',\n ACTION_BAR_REVEAL_CLASS,\n className,\n )}\n >\n {formatMessageTime(date)}\n </time>\n );\n};\n\nexport const AthenaReasoningPart: FC<AthenaReasoningPartProps> = ({\n text,\n status,\n TextComponent,\n}) => {\n const inheritedTextComponent = useContext(AthenaReasoningTextComponentContext);\n const EffectiveTextComponent = TextComponent ?? inheritedTextComponent ?? TiptapText;\n const isMessageRunning = useAuiState((state) => state.message.status?.type === 'running');\n const reasoningTokens = useAuiState((state) =>\n getReasoningTokensFromMetadata(state.message.metadata)\n );\n const isRunning = isMessageRunning || status?.type === 'running';\n const [isCollapsed, setIsCollapsed] = useState(!isRunning);\n const userOverrodeOpenStateRef = useRef(false);\n const hasText = text.trim().length > 0;\n\n const reasoningTextProps: TextMessagePartProps = {\n type: 'text',\n text,\n status: isRunning\n ? ({ type: 'running' } as TextMessagePartProps['status'])\n : (status as TextMessagePartProps['status']),\n };\n\n useEffect(() => {\n if (userOverrodeOpenStateRef.current) {\n return;\n }\n\n setIsCollapsed(!isRunning);\n }, [isRunning]);\n\n if (!hasText && !isRunning) {\n return null;\n }\n\n return (\n <Collapsible\n open={!isCollapsed}\n onOpenChange={(open) => {\n userOverrodeOpenStateRef.current = true;\n setIsCollapsed(!open);\n }}\n className=\"aui-assistant-reasoning-root mb-3 rounded-2xl border border-border/60 bg-muted/30 px-3 py-2\"\n >\n <CollapsibleTrigger asChild>\n <button\n type=\"button\"\n className=\"flex w-full items-center justify-between gap-3 text-left\"\n aria-label={isRunning ? 'Toggle reasoning while streaming' : 'Toggle reasoning'}\n >\n <span className=\"flex min-w-0 items-center gap-2 text-[13px] font-medium text-muted-foreground\">\n <BrainIcon className=\"size-4 shrink-0\" />\n <span>{isRunning ? 'Reasoning...' : 'Reasoning'}</span>\n </span>\n <span className=\"flex shrink-0 items-center gap-2\">\n {reasoningTokens !== undefined && (\n <span className=\"rounded-full border border-border/60 bg-background px-2 py-0.5 text-[11px] font-medium text-muted-foreground\">\n {formatReasoningTokens(reasoningTokens)}\n </span>\n )}\n <span\n className={cn(\n 'flex size-5 items-center justify-center text-muted-foreground transition-transform',\n isCollapsed ? 'rotate-0' : 'rotate-90'\n )}\n aria-hidden=\"true\"\n >\n <ChevronRightIcon className=\"size-4\" />\n </span>\n </span>\n </button>\n </CollapsibleTrigger>\n\n <CollapsibleContent className=\"pt-3\">\n {isRunning && !hasText ? (\n <span className=\"shimmer text-[13px] text-muted-foreground\">Analyzing...</span>\n ) : (\n <div className=\"aui-assistant-reasoning-body text-[13px] leading-relaxed\">\n <EffectiveTextComponent {...reasoningTextProps} />\n </div>\n )}\n </CollapsibleContent>\n </Collapsible>\n );\n};\n\nconst groupAdjacentToolCalls = (part: PartState) =>\n part.type === 'tool-call' ? (['group-tool'] as const) : null;\nconst noToolGrouping = () => null;\n\nexport const AthenaAssistantMessage: FC<AthenaAssistantMessageProps> = ({\n toolUIs,\n AvatarComponent,\n TextComponent = TiptapText,\n ReasoningComponent,\n EmptyComponent = AthenaAssistantMessageEmpty,\n ActionBarComponent = AthenaAssistantActionBar,\n groupToolCalls = true,\n}) => {\n const effectiveReasoningComponent = ReasoningComponent ?? AthenaReasoningPart;\n const toolUIsWithNestedMessages = useMemo(() => {\n const wrappedToolUIs: Record<string, ToolCallMessagePartComponent> = {};\n\n for (const [toolName, ToolUI] of Object.entries(toolUIs)) {\n wrappedToolUIs[toolName] = withNestedPtcMessages(ToolUI);\n }\n\n return wrappedToolUIs;\n }, [toolUIs]);\n\n // NestedPtcComponentsProvider still consumes the legacy parts-config shape\n // (Text / Reasoning / tools.by_name / Empty) to render PTC sub-tool messages\n // inside a tool card. The outer rendering uses GroupedParts, but the inner\n // PTC tree continues to mirror the parent registry.\n const nestedPtcComponents = useMemo(\n () => ({\n Text: TextComponent,\n Reasoning: effectiveReasoningComponent,\n tools: {\n Fallback: ToolFallback,\n by_name: toolUIsWithNestedMessages,\n },\n Empty: EmptyComponent,\n }),\n [EmptyComponent, TextComponent, effectiveReasoningComponent, toolUIsWithNestedMessages],\n );\n\n return (\n <MessagePrimitive.Root\n className=\"aui-assistant-message-root group/aui-assistant-message fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in py-3 duration-150\"\n data-role=\"assistant\"\n >\n <MessageDaySeparator />\n <div className=\"flex gap-3\">\n {/* The leading column exists only when the host supplies an avatar;\n without one the turn is told apart from the right-aligned user\n bubbles by alignment alone, with no rule or gutter of its own. */}\n {AvatarComponent ? (\n <div\n data-slot=\"assistant-lead\"\n className=\"aui-assistant-message-lead flex shrink-0 justify-center\"\n >\n <AvatarComponent />\n </div>\n ) : null}\n <div className=\"min-w-0 flex-1\">\n <AthenaReasoningTextComponentContext.Provider value={TextComponent}>\n <div className=\"aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed\">\n <NestedPtcComponentsProvider components={nestedPtcComponents}>\n {groupToolCalls ? (\n <div className=\"flex flex-col space-y-2\">\n <SuperGroupingCard\n toolUIs={toolUIsWithNestedMessages}\n TextComponent={TextComponent}\n ReasoningComponent={effectiveReasoningComponent}\n renderRunningMeta={renderGroupedRunningMeta}\n />\n <SuperGroupingFinalText TextComponent={TextComponent} />\n </div>\n ) : (\n <>\n <AthenaMessageEmptyIndicator EmptyComponent={EmptyComponent} />\n <MessagePrimitive.GroupedParts groupBy={noToolGrouping}>\n {({ part }) => {\n switch (part.type) {\n case 'tool-call': {\n const ToolUI = toolUIsWithNestedMessages[part.toolName];\n const toolProps = part as unknown as ToolCallMessagePartProps;\n return ToolUI ? <ToolUI {...toolProps} /> : <ToolFallback {...toolProps} />;\n }\n case 'reasoning': {\n const ReasoningRenderer = effectiveReasoningComponent;\n return <ReasoningRenderer {...(part as ReasoningMessagePartProps)} />;\n }\n case 'text': {\n const textPart = part as TextMessagePartProps;\n if (textPart.text === '' && textPart.status?.type === 'running') {\n return <EmptyComponent status={textPart.status} />;\n }\n return <TextComponent {...textPart} />;\n }\n default:\n return null;\n }\n }}\n </MessagePrimitive.GroupedParts>\n <AthenaMessageActivityIndicator />\n </>\n )}\n </NestedPtcComponentsProvider>\n <MessageError />\n </div>\n </AthenaReasoningTextComponentContext.Provider>\n <div className=\"aui-assistant-message-footer mt-1 ml-2 flex items-center gap-1\">\n <BranchPicker />\n <ActionBarComponent />\n <MessageTimestamp className=\"ml-auto group-hover/aui-assistant-message:opacity-100\" />\n </div>\n </div>\n </div>\n </MessagePrimitive.Root>\n );\n};\n\nconst AthenaToolGroup: FC<{ children: React.ReactNode; count: number }> = ({ children, count }) => {\n const [expanded, setExpanded] = useState(false);\n\n return (\n <div className=\"my-3 w-full overflow-hidden rounded-xl border border-border/60 bg-background shadow-sm\">\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n className=\"flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-muted/20\"\n aria-expanded={expanded}\n >\n <div className=\"flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted/60 text-muted-foreground\">\n <LayersIcon className=\"size-4\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <span className=\"text-[13px] font-medium text-foreground\">\n {count} tool {count === 1 ? 'call' : 'calls'}\n </span>\n </div>\n <ChevronDownIcon\n className={cn(\n 'size-4 shrink-0 text-muted-foreground transition-transform duration-200',\n !expanded && '-rotate-90',\n )}\n />\n </button>\n {expanded && (\n <div className=\"border-t border-border/40 bg-muted/5 px-3 pt-1 pb-2 [&>*]:my-2\">\n {children}\n </div>\n )}\n </div>\n );\n};\n\nconst CopyMessageButton: FC = () => (\n <ActionBarPrimitive.Copy asChild>\n <TooltipIconButton tooltip=\"Copy\">\n <AuiIf condition={(s) => s.message.isCopied}>\n <CheckIcon />\n </AuiIf>\n <AuiIf condition={(s) => !s.message.isCopied}>\n <CopyIcon />\n </AuiIf>\n </TooltipIconButton>\n </ActionBarPrimitive.Copy>\n);\n\n/** Regenerate dispatches `run/reload`, so it hides on read-only threads. */\nconst RegenerateMessageButton: FC = () => {\n const readOnly = useMessageActionsReadOnly();\n if (readOnly) return null;\n return (\n <ActionBarPrimitive.Reload asChild>\n <TooltipIconButton tooltip=\"Regenerate\">\n <RefreshCwIcon />\n </TooltipIconButton>\n </ActionBarPrimitive.Reload>\n );\n};\n\n/**\n * The edit primitive does not check the runtime's edit capability itself —\n * clicking it on a runtime without one throws inside onPress — so the button\n * gates on the capability and, to match the rewind semantics of `run/edit`,\n * stays hidden while a run is live or the transcript is read-only.\n */\nconst EditMessageButton: FC = () => {\n const allowEdit = useAuiState((s) => s.thread.capabilities.edit);\n const isRunning = useAthenaRunLive();\n const readOnly = useMessageActionsReadOnly();\n if (!allowEdit || isRunning || readOnly) return null;\n return (\n <ActionBarPrimitive.Edit asChild>\n <TooltipIconButton tooltip=\"Edit\">\n <PencilIcon />\n </TooltipIconButton>\n </ActionBarPrimitive.Edit>\n );\n};\n\n/** Hover-revealed copy / edit row under a user bubble; mirrors the assistant bar. */\nconst AthenaUserActionBar: FC = () => {\n const isThreadRunning = useAuiState((s) => s.thread.isRunning);\n return (\n <ActionBarPrimitive.Root\n autohide=\"never\"\n className={cn(\n 'aui-user-action-bar-root flex min-h-6 gap-1 text-muted-foreground',\n isThreadRunning\n ? 'invisible'\n : [\n ACTION_BAR_REVEAL_CLASS,\n 'group-hover/aui-user-message:pointer-events-auto group-hover/aui-user-message:opacity-100',\n ],\n )}\n >\n <CopyMessageButton />\n <EditMessageButton />\n </ActionBarPrimitive.Root>\n );\n};\n\nexport const AthenaAssistantActionBar: FC<AthenaAssistantActionBarProps> = ({ className }) => {\n const threadId = useAthenaThreadId();\n const { appUrl } = useAthenaConfig();\n // The bar stays mounted so the footer keeps its height: assistant-ui's\n // `autohide` / `hideWhenRunning` unmount it, which shifts the whole message\n // up and down on every hover. Visibility is CSS instead — the latest reply\n // keeps its actions, older replies reveal on hover or keyboard focus, and\n // while the thread runs every bar is `invisible` (layout kept, controls\n // unfocusable — opacity alone would still let Tab reveal them).\n const isLast = useAuiState((s) => s.message.isLast);\n const isThreadRunning = useAuiState((s) => s.thread.isRunning);\n\n return (\n <ActionBarPrimitive.Root\n autohide=\"never\"\n className={cn(\n 'aui-assistant-action-bar-root -ml-1 flex min-h-6 gap-1 text-muted-foreground',\n isThreadRunning && 'invisible',\n !isThreadRunning &&\n !isLast && [\n ACTION_BAR_REVEAL_CLASS,\n 'group-hover/aui-assistant-message:pointer-events-auto group-hover/aui-assistant-message:opacity-100',\n ],\n className,\n )}\n >\n <CopyMessageButton />\n <RegenerateMessageButton />\n <ActionBarMorePrimitive.Root>\n <ActionBarMorePrimitive.Trigger asChild>\n <TooltipIconButton tooltip=\"More\" className=\"data-[state=open]:bg-accent\">\n <MoreHorizontalIcon />\n </TooltipIconButton>\n </ActionBarMorePrimitive.Trigger>\n <ActionBarMorePrimitive.Content\n side=\"bottom\"\n align=\"start\"\n className=\"aui-action-bar-more-content z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md\"\n >\n <ActionBarPrimitive.ExportMarkdown asChild>\n <ActionBarMorePrimitive.Item className=\"aui-action-bar-more-item flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\">\n <DownloadIcon className=\"size-4\" />\n Export as Markdown\n </ActionBarMorePrimitive.Item>\n </ActionBarPrimitive.ExportMarkdown>\n {threadId && (\n <ActionBarMorePrimitive.Item\n className=\"aui-action-bar-more-item flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\"\n onClick={() => {\n window.open(createAthenaSpacesUrl({ appUrl, sessionId: threadId }), '_blank');\n }}\n >\n <ExternalLinkIcon className=\"size-4\" />\n Open in Athena\n </ActionBarMorePrimitive.Item>\n )}\n </ActionBarMorePrimitive.Content>\n </ActionBarMorePrimitive.Root>\n </ActionBarPrimitive.Root>\n );\n};\n\nexport const AthenaUserMessage: FC<AthenaUserMessageProps> = ({\n TextComponent = TiptapText,\n}) => {\n // A GitHub wake turn is an event, not words the user typed: it renders as\n // the compact wake marker instead of a bubble quoting the injected text.\n const isWake = useAuiState((s) => isGithubWakeMessage(s.message.metadata?.custom));\n if (isWake) {\n return (\n <MessagePrimitive.Root\n className=\"aui-user-message-root aui-wake-marker-root mx-auto w-full max-w-(--thread-max-width) px-2 py-1\"\n data-role=\"user\"\n >\n <MessageDaySeparator />\n <WakeMarkerMessage />\n </MessagePrimitive.Root>\n );\n }\n return (\n <MessagePrimitive.Root\n className=\"aui-user-message-root group/aui-user-message fade-in slide-in-from-bottom-1 mx-auto flex w-full max-w-(--thread-max-width) animate-in flex-col items-end px-2 py-3 duration-150\"\n data-role=\"user\"\n >\n <MessageDaySeparator />\n {/* A soft bubble on a 75% measure: the user's words stay a bubble, the\n assistant's reading column stays the page. */}\n <div className=\"flex min-w-0 max-w-[75%] flex-col items-end gap-1\">\n <div className=\"aui-user-message-content wrap-break-word rounded-2xl bg-muted/70 px-4 py-2.5 text-foreground\">\n <MessagePrimitive.Parts components={{ Text: TextComponent }} />\n </div>\n <div className=\"aui-user-message-footer -mr-1 flex items-center gap-1\">\n <MessageTimestamp className=\"mr-1 group-hover/aui-user-message:opacity-100\" />\n <BranchPicker />\n <AthenaUserActionBar />\n </div>\n </div>\n </MessagePrimitive.Root>\n );\n};\n"],"names":["_a","error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AthenaChat.js","sources":["../../src/chat/AthenaChat.tsx"],"sourcesContent":["import { isGithubWakeMessage } from '@athenaintel/agent-runtime';\nimport { TiptapText } from './tiptap-text';\nimport { AthenaChatErrorBoundary } from './AthenaChatErrorBoundary';\nimport { StatewireApprovalCard } from './StatewireApprovalCard';\nimport { StatewireQueuedMessages } from './StatewireQueuedMessages';\nimport { StatewireConnectionBanner, StatewireErrorBanner } from './statewire-banners';\nimport { WaitingOnYouBanner } from './WaitingOnYouBanner';\nimport { WakeMarkerMessage } from '../chat-ui/messages/wake-marker';\nimport { ToolFallback, ToolFallbackAppearanceProvider } from '../tools/tool-fallback';\nimport { AppendDocumentToolUI } from '../tools/append-document-tool-ui';\nimport { ReadAssetToolUI } from '../tools/read-asset-tool-ui';\nimport { TOOL_UI_REGISTRY } from '../tools/tool-uis';\nimport { SuperGroupingCard, SuperGroupingFinalText } from './super-grouping/SuperGroupingCard';\nimport {\n NestedPtcComponentsProvider,\n NestedPtcMessages,\n useNestedPtcComponents,\n} from '../tools/NestedPtcMessages';\nimport { TooltipIconButton } from './tooltip-icon-button';\nimport { Button } from '../ui/button';\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../ui/collapsible';\nimport { ChatComposerDock } from '../chat-ui/thread/chat-composer-dock';\nimport { ChatThreadShell } from '../chat-ui/thread/chat-thread-shell';\nimport { StatewireHistoryEdge } from '../chat-ui/thread/statewire-history-edge';\nimport { ThreadLoadingOverlay } from '../chat-ui/thread/thread-loading-overlay';\nimport {\n ComposerSendOrStop,\n type ComposerSendOrStopProps,\n} from '../chat-ui/thread/composer-send-or-stop';\nimport { resolveComposerAction } from '../chat-ui/composer/composer-action';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport { useDictation } from '../dictation/use-dictation';\nimport { DictationStrip } from '../dictation/DictationStrip';\nimport {\n DictationCancelButton,\n DictationMicButton,\n DictationStopButton,\n} from '../dictation/dictation-controls';\nimport { composeDictationDraft, DICTATION_STATUSES } from '../dictation/dictation-state';\nimport type { DictationEngine } from '../dictation/dictation-engine';\nimport { useAthenaDictationEngine } from '../dictation/use-athena-dictation-engine';\nimport {\n TiptapComposer,\n type ComposerFileIntake,\n type TiptapComposerHandle,\n} from '../chat-ui/composer/tiptap-composer';\nimport {\n MentionAuthCtx,\n type MentionAuthContext,\n} from '../chat-ui/mentions/suggestions/data/api-client';\nimport type { MentionRootCategory } from '../chat-ui/mentions/suggestions/data/use-mention-suggestions';\nimport type { MentionTool } from '../chat-ui/mentions/suggestions/data/types';\nimport { ACTION_BAR_REVEAL_CLASS, BranchPicker } from '../chat-ui/messages/message-components';\nimport { useMessageActionsReadOnly } from '../chat-ui/messages/message-actions-config';\nimport { useAthenaRunLive } from './use-athena-run-live';\nimport {\n AthenaChatWelcome,\n AthenaChatWelcomeSuggestions,\n DEFAULT_WELCOME_SUGGESTIONS,\n welcomeComposerDelayMs,\n welcomeEntrance,\n type WelcomeSuggestion,\n} from './athena-chat-welcome';\nimport {\n ATHENA_COMPOSER_COMPONENTS,\n AthenaComposerMentionButton,\n AthenaComposerSendButton,\n} from './athena-composer-controls';\nimport { ComposerKeyboardHint, useComposerKeyboardHint } from './composer-keyboard-hint';\nimport { usePrefersReducedMotion } from '../lib/use-prefers-reduced-motion';\nimport {\n ActionBarMorePrimitive,\n ActionBarPrimitive,\n AuiIf,\n ErrorPrimitive,\n MessagePrimitive,\n ThreadPrimitive,\n useAui,\n useAuiState,\n} from '@assistant-ui/react';\nimport type {\n EmptyMessagePartComponent,\n PartState,\n ReasoningMessagePartProps,\n ReasoningMessagePartComponent,\n TextMessagePartProps,\n TextMessagePartComponent,\n ToolCallMessagePartComponent,\n ToolCallMessagePartProps,\n} from '@assistant-ui/react';\nimport {\n AlertCircleIcon,\n ArrowUpIcon,\n BrainIcon,\n CheckIcon,\n ChevronDownIcon,\n ChevronRightIcon,\n CopyIcon,\n DownloadIcon,\n ExternalLinkIcon,\n LayersIcon,\n MoreHorizontalIcon,\n PencilIcon,\n RefreshCwIcon,\n} from 'lucide-react';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type FC,\n type ReactNode,\n} from 'react';\nimport {\n AthenaStatewireThreadIdContext,\n useAthenaStatewireThreadId,\n useAthenaThreadId,\n} from '../threads/thread-id-context';\nimport { FileUploadButton } from '../composer/FileUploadButton';\nimport { ComposerQuotePreview } from '../composer/ComposerQuotePreview';\nimport { ComposerAttachmentPreview } from '../composer/ComposerAttachmentPreview';\nimport { ComposerDropZone } from '../composer/ComposerDropZone';\nimport { useQuote, QuoteProvider, useQuoteFromPostMessage } from '../composer/QuoteContext';\nimport { AttachmentProvider, useAttachments } from '../composer/AttachmentContext';\nimport { buildComposedMessage } from '../composer/build-composed-message';\nimport { useAttachFiles } from '../composer/useAttachFiles';\nimport { useAthenaConfig } from '../provider/AthenaContext';\nimport { createAthenaSpacesUrl } from '../lib/athena-urls';\nimport { cn, isRecord } from '../lib/utils';\nimport { getToolkitDisplayInfo } from '../toolkits';\nimport {\n RUN_ACTIVITY_COUNTER_SECONDS,\n RUN_ACTIVITY_STALL_SECONDS,\n runActivityKey,\n runActivityLabel,\n runActivityVerb,\n} from './run-activity';\nimport {\n formatDayLabel,\n formatMessageDateTime,\n formatMessageTime,\n isSameCalendarDay,\n parseMessageTime,\n readMessageCreatedAt,\n} from './message-time';\nimport { ThreadScrollToBottom } from './thread-scroll-to-bottom';\n\nfunction QuotePostMessageBridge() {\n useQuoteFromPostMessage();\n return null;\n}\n\nexport type { WelcomeSuggestion } from './athena-chat-welcome';\n\nexport interface AthenaChatProps {\n /** CSS class name for the root element. */\n className?: string;\n /** Welcome heading text. Defaults to \"Hello there!\" */\n welcomeMessage?: string;\n /** Welcome subheading text. */\n welcomeSubtext?: string;\n /**\n * Maximum width of the reading column (messages, welcome, composer).\n * Defaults to \"46rem\" — about 760 px, a comfortable measure for 15 px text.\n */\n maxWidth?: string;\n /**\n * Scroll anchoring for new turns. \"bottom\" (default) keeps the viewport\n * pinned to the end while the assistant streams — classic chat follow.\n * \"top\" pins the just-sent user message to the top of the viewport and\n * intentionally does NOT follow the streaming response (assistant-ui\n * disables autoScroll in that mode), so readers scroll at their own pace.\n */\n turnAnchor?: \"top\" | \"bottom\";\n /**\n * Marks the transcript read-only: Edit and Regenerate hide while Copy stays\n * available. For threads whose server rejects dispatch (e.g. legacy\n * pre-cutover conversations) — the runtime's static capability flags cannot\n * express a per-thread fence, so the host that knows passes it here.\n */\n readOnly?: boolean;\n /** Additional tool UIs to register by name. */\n toolUIs?: Record<string, ToolCallMessagePartComponent>;\n /** Tools / Toolkits offered by the composer's `@` menu beside the asset\n * library. Defaults to the toolkits enabled on the provider. */\n mentionTools?: MentionTool[];\n /** Suggestion cards shown on the welcome screen. Pass `[]` to hide.\n * For workflow launchers outside AthenaChat, use `useSendMessage()`.\n */\n welcomeSuggestions?: WelcomeSuggestion[];\n /** Optional component overrides for message containers and key message parts. */\n components?: AthenaChatComponents;\n /**\n * Fold a turn's tool calls into one collapsible activity group with a\n * count, the answer rendered below it. Defaults to `true`; pass `false` to\n * list every tool card inline in the order it was called.\n */\n groupToolCalls?: boolean;\n /**\n * Extra composer toolbar content and send hooks. `toolbarStart` renders\n * after the attach button, `toolbarEnd` renders before the mic and Send.\n * Slot components render inside the chat's thread scope, so `useAthenaRunLive`\n * and `useAppendToComposer` work in them.\n */\n composer?: AthenaChatComposerSlots;\n /**\n * Built-in microphone dictation in the composer: a mic left of Send that\n * swaps the editor for a live waveform while recording, then puts the words\n * into the draft (Stop) or sends them (Send). Recording is transcribed by\n * Athena (Deepgram) once the user stops; the words land after a short\n * \"Transcribing…\" pause. Defaults to `true`. Pass `false` to remove it, or\n * options to pick the language or a custom speech engine.\n */\n dictation?: boolean | AthenaChatDictationOptions;\n}\n\nexport interface AthenaChatComposerSlots {\n /** Toolbar contents after the attach button. */\n toolbarStart?: ReactNode;\n /** Toolbar contents before the mic and the send/stop control. */\n toolbarEnd?: ReactNode;\n /** Host work to run before a draft submits (also runs for a dictated send). */\n onBeforeSend?: ComposerSendOrStopProps['onBeforeSend'];\n}\n\nexport interface AthenaChatDictationOptions {\n /**\n * Speech engine; defaults to record-then-transcribe through Athena\n * (`createRecordedDictationEngine`). Pass `createWebSpeechDictationEngine()`\n * for the browser's live Web Speech API instead.\n */\n engine?: DictationEngine;\n /** BCP-47 language tag; defaults to the document language. */\n lang?: string;\n}\n\nexport interface AthenaChatMessagePartComponents {\n Text?: TextMessagePartComponent;\n Reasoning?: ReasoningMessagePartComponent;\n Empty?: EmptyMessagePartComponent;\n}\n\nexport interface AthenaChatComponents {\n UserMessage?: FC;\n AssistantMessage?: FC;\n AssistantActionBar?: FC<AthenaAssistantActionBarProps>;\n /**\n * Rendered in a leading column on every assistant turn (a small avatar or\n * mark). Without it there is no leading column: the reply sits flush with\n * the thread column and is told apart from the right-aligned user bubbles by\n * alignment alone.\n */\n AssistantAvatar?: FC;\n messageParts?: AthenaChatMessagePartComponents;\n}\n\nexport interface AthenaUserMessageProps {\n TextComponent?: TextMessagePartComponent;\n}\n\nexport interface AthenaAssistantActionBarProps {\n className?: string;\n}\n\nexport interface AthenaAssistantMessageProps {\n toolUIs: Record<string, ToolCallMessagePartComponent>;\n /** Leading-column content for the turn; no leading column at all when unset. */\n AvatarComponent?: FC;\n TextComponent?: TextMessagePartComponent;\n ReasoningComponent?: ReasoningMessagePartComponent;\n EmptyComponent?: EmptyMessagePartComponent;\n ActionBarComponent?: FC<AthenaAssistantActionBarProps>;\n /** Fold the turn's tool calls into one collapsible activity group. Defaults to `true`. */\n groupToolCalls?: boolean;\n}\n\nexport interface AthenaReasoningPartProps extends ReasoningMessagePartProps {\n TextComponent?: TextMessagePartComponent;\n}\n\ninterface AthenaChatDefaultComponentsContextValue {\n toolUIs: Record<string, ToolCallMessagePartComponent>;\n TextComponent: TextMessagePartComponent;\n ReasoningComponent?: ReasoningMessagePartComponent;\n EmptyComponent: EmptyMessagePartComponent;\n ActionBarComponent: FC<AthenaAssistantActionBarProps>;\n AvatarComponent?: FC;\n groupToolCalls: boolean;\n}\n\nconst AthenaChatDefaultComponentsContext =\n createContext<AthenaChatDefaultComponentsContextValue | null>(null);\n\nconst AthenaReasoningTextComponentContext = createContext<TextMessagePartComponent | null>(null);\n\nconst useAthenaChatDefaultComponents = (): AthenaChatDefaultComponentsContextValue => {\n const value = useContext(AthenaChatDefaultComponentsContext);\n\n if (!value) {\n throw new Error('Athena default chat components must be used within AthenaChat.');\n }\n\n return value;\n};\n\nconst AthenaDefaultAssistantMessage: FC = () => {\n const {\n toolUIs,\n TextComponent,\n ReasoningComponent,\n EmptyComponent,\n ActionBarComponent,\n AvatarComponent,\n groupToolCalls,\n } = useAthenaChatDefaultComponents();\n\n return (\n <AthenaAssistantMessage\n toolUIs={toolUIs}\n AvatarComponent={AvatarComponent}\n TextComponent={TextComponent}\n ReasoningComponent={ReasoningComponent}\n EmptyComponent={EmptyComponent}\n ActionBarComponent={ActionBarComponent}\n groupToolCalls={groupToolCalls}\n />\n );\n};\n\nconst AthenaDefaultUserMessage: FC = () => {\n const { TextComponent } = useAthenaChatDefaultComponents();\n\n return <AthenaUserMessage TextComponent={TextComponent} />;\n};\n\nconst getReasoningTokensFromMetadata = (metadata: unknown): number | undefined => {\n if (!isRecord(metadata)) {\n return undefined;\n }\n\n const customMetadata = metadata.custom;\n if (!isRecord(customMetadata)) {\n return undefined;\n }\n\n const athenaMetadata = customMetadata._athena;\n if (!isRecord(athenaMetadata)) {\n return undefined;\n }\n\n const reasoningTokens = athenaMetadata.reasoningTokens;\n return typeof reasoningTokens === 'number' && Number.isFinite(reasoningTokens)\n ? reasoningTokens\n : undefined;\n};\n\nconst formatReasoningTokens = (reasoningTokens: number) =>\n `${reasoningTokens.toLocaleString('en-US')} ${reasoningTokens === 1 ? 'token' : 'tokens'}`;\n\nconst withNestedPtcMessages = (\n ToolUI: ToolCallMessagePartComponent\n): ToolCallMessagePartComponent => {\n const ToolUIWithNestedPtcMessages: ToolCallMessagePartComponent = (props) => {\n const nestedComponents = useNestedPtcComponents(ToolFallback);\n\n return (\n <>\n <ToolUI {...props} />\n <NestedPtcMessages components={nestedComponents} />\n </>\n );\n };\n\n return ToolUIWithNestedPtcMessages;\n};\n\nexport const AthenaChat: FC<AthenaChatProps> = ({\n className,\n welcomeMessage = \"Hello there!\",\n welcomeSubtext = \"What can I help you with?\",\n maxWidth = \"46rem\",\n turnAnchor = \"bottom\",\n readOnly = false,\n toolUIs,\n mentionTools,\n welcomeSuggestions = DEFAULT_WELCOME_SUGGESTIONS,\n components,\n groupToolCalls = true,\n composer: composerSlots,\n dictation = true,\n}) => {\n const athenaConfig = useAthenaConfig();\n // The chat surface is per thread. `AthenaProvider` keeps the host's\n // children mounted across a thread switch and swaps only the client under\n // them, so what used to reset with the whole tree — the composer draft, the\n // viewport's scroll position, the approval card and banner state, a caught\n // render crash — is reset here instead, keyed on the attached thread (the\n // id the provider publishes together with that thread's client, so the\n // fresh surface never renders against the previous thread's runtime).\n const statewireThreadId = useContext(AthenaStatewireThreadIdContext);\n // The mention menu's GraphQL credentials: the backend and credential the\n // provider resolved. `athenaConfig` keeps its identity across token\n // rotations (its `token` is a getter over a ref — see useAthenaConfigValue),\n // so this object is stable too. The mention store lists `accessToken` among\n // its memo dependencies, so it rebuilds (and refetches its lists) on the\n // composer's next render after a rotation; the getter is what hands the\n // rotated token to any fetch before that render. With neither token nor\n // API key the fetch rides the same-origin session cookie, as the SDK's\n // upload and thread REST calls do.\n const mentionAuth = useMemo<MentionAuthContext>(\n () => ({\n backendUrl: athenaConfig.backendUrl,\n appUrl: athenaConfig.appUrl,\n apiKey: athenaConfig.apiKey,\n credentials: 'include',\n get accessToken() {\n return athenaConfig.token ?? undefined;\n },\n getAccessToken: async () => (await athenaConfig.getToken?.()) ?? undefined,\n renewAccessToken: async () => (await athenaConfig.getToken?.({ force: true })) ?? undefined,\n }),\n [athenaConfig],\n );\n const providerMentionTools = useMemo<MentionTool[]>(() => {\n const uniqueToolkitIds = Array.from(new Set(athenaConfig.enabledToolkits));\n\n return uniqueToolkitIds.map((id) => {\n const toolkit = getToolkitDisplayInfo(id);\n\n return {\n id: toolkit.id,\n name: toolkit.name,\n description: toolkit.description,\n icon: toolkit.icon,\n type: 'toolkit',\n };\n });\n }, [athenaConfig.enabledToolkits]);\n const tools = mentionTools ?? providerMentionTools;\n const mergedToolUIs = useMemo(\n () => ({\n append_markdown_to_athena_document: AppendDocumentToolUI,\n read_full_asset: ReadAssetToolUI,\n read_asset: ReadAssetToolUI,\n ...TOOL_UI_REGISTRY,\n ...toolUIs,\n }),\n [toolUIs],\n );\n\n const textComponent = components?.messageParts?.Text ?? TiptapText;\n const reasoningComponent = components?.messageParts?.Reasoning;\n const emptyComponent = components?.messageParts?.Empty ?? AthenaAssistantMessageEmpty;\n const actionBarComponent = components?.AssistantActionBar ?? AthenaAssistantActionBar;\n const avatarComponent = components?.AssistantAvatar;\n\n const defaultComponentsContextValue = useMemo<AthenaChatDefaultComponentsContextValue>(\n () => ({\n toolUIs: mergedToolUIs,\n TextComponent: textComponent,\n ReasoningComponent: reasoningComponent,\n EmptyComponent: emptyComponent,\n ActionBarComponent: actionBarComponent,\n AvatarComponent: avatarComponent,\n groupToolCalls,\n }),\n [\n actionBarComponent,\n avatarComponent,\n emptyComponent,\n groupToolCalls,\n mergedToolUIs,\n reasoningComponent,\n textComponent,\n ],\n );\n const AssistantMessageComponent = components?.AssistantMessage ?? AthenaDefaultAssistantMessage;\n const UserMessageComponent = components?.UserMessage ?? AthenaDefaultUserMessage;\n const messageComponents = useMemo(\n () => ({\n UserMessage: UserMessageComponent,\n AssistantMessage: AssistantMessageComponent,\n }),\n [AssistantMessageComponent, UserMessageComponent],\n );\n\n return (\n <AthenaChatDefaultComponentsContext.Provider value={defaultComponentsContextValue}>\n {/* Contain render crashes to the chat pane (telemetry + retry) instead of\n unmounting the integrator's subtree. */}\n <AthenaChatErrorBoundary key={statewireThreadId ?? undefined}>\n {/* Every tool call in the thread — generic fallback, dedicated tool\n UI, nested PTC sub-call — renders as the one-line thread row. */}\n <ToolFallbackAppearanceProvider appearance=\"thread\">\n <ChatThreadShell\n overlay={<ThreadLoadingOverlay />}\n panelClassName={cn(\n 'aui-root aui-thread-root @container relative flex h-full flex-col bg-background',\n className,\n )}\n maxWidth={maxWidth}\n turnAnchor={turnAnchor}\n readOnly={readOnly}\n // Persistent \"waiting on you\" strip above the viewport; the approval\n // card it points at stays in the sticky footer below.\n banners={<WaitingOnYouBanner className=\"px-4 pt-3\" />}\n viewportClassName=\"aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth px-4 pt-4\"\n contentClassName=\"flex w-full flex-1 flex-col\"\n viewportOverlay={<ThreadScrollToTop />}\n welcome={\n <AthenaChatWelcome welcomeMessage={welcomeMessage} welcomeSubtext={welcomeSubtext} />\n }\n beforeMessages={<StatewireHistoryEdge className=\"aui-thread-history-edge\" />}\n components={messageComponents}\n runningIndicator={null}\n // The scroll-to-bottom pill is docked on the composer (see\n // AthenaChatComposer) instead of floating over the messages; the\n // footer's top padding is the room it sits in.\n scrollToBottom={null}\n viewportFooterClassName=\"aui-thread-viewport-footer sticky bottom-0 mx-auto mt-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 overflow-visible rounded-t-3xl bg-background pt-4 pb-4 md:pb-6\"\n viewportFooter={\n <>\n {/* Empty state: the suggestion cards sit directly above the\n composer (the greeting stays centred in the viewport). */}\n {welcomeSuggestions.length > 0 && (\n <ThreadPrimitive.Empty>\n <AthenaChatWelcomeSuggestions suggestions={welcomeSuggestions} />\n </ThreadPrimitive.Empty>\n )}\n <StatewireConnectionBanner />\n <StatewireErrorBanner />\n <StatewireApprovalCard />\n {/* Queued rows render mention chips, which need the app URL\n to link to their asset. */}\n <MentionAuthCtx.Provider value={mentionAuth}>\n <StatewireQueuedMessages />\n </MentionAuthCtx.Provider>\n <AttachmentProvider>\n <QuoteProvider>\n <QuotePostMessageBridge />\n <MentionAuthCtx.Provider value={mentionAuth}>\n <AthenaChatComposer\n tools={tools}\n slots={composerSlots}\n dictation={dictation}\n welcomeSuggestionCount={welcomeSuggestions.length}\n />\n </MentionAuthCtx.Provider>\n </QuoteProvider>\n </AttachmentProvider>\n </>\n }\n />\n </ToolFallbackAppearanceProvider>\n </AthenaChatErrorBoundary>\n </AthenaChatDefaultComponentsContext.Provider>\n );\n};\n\nconst THREAD_VIEWPORT_ATTR = 'data-aui-thread-viewport';\n\nconst useScrollToTop = () => {\n const [isAtTop, setIsAtTop] = useState(true);\n const [buttonEl, setButtonEl] = useState<HTMLButtonElement | null>(null);\n\n const containerRef = useCallback((node: HTMLButtonElement | null) => {\n setButtonEl(node);\n }, []);\n\n const getViewport = useCallback((): HTMLElement | null => {\n if (!buttonEl) return null;\n return buttonEl.closest(`[${THREAD_VIEWPORT_ATTR}]`) as HTMLElement | null;\n }, [buttonEl]);\n\n useEffect(() => {\n const viewport: HTMLElement | null = getViewport();\n if (!viewport) return;\n\n const handleScroll = () => {\n setIsAtTop(viewport.scrollTop <= 50);\n };\n\n handleScroll();\n viewport.addEventListener('scroll', handleScroll, { passive: true });\n return () => viewport.removeEventListener('scroll', handleScroll);\n }, [getViewport]);\n\n const handleClick = useCallback(() => {\n const viewport: HTMLElement | null = getViewport();\n if (!viewport) return;\n viewport.scrollTo({ top: 0, behavior: 'smooth' });\n }, [getViewport]);\n\n return { isAtTop, containerRef, handleClick };\n};\n\nconst ThreadScrollToTop: FC = () => {\n const { isAtTop, containerRef, handleClick } = useScrollToTop();\n const isEmpty = useAuiState((s) => s.thread.isEmpty);\n\n if (isEmpty) return null;\n\n return (\n <div className=\"sticky top-0 z-10 mx-auto flex h-0 w-full max-w-(--thread-max-width) justify-center\">\n <TooltipIconButton\n ref={containerRef}\n tooltip=\"Scroll to top\"\n variant=\"outline\"\n className={cn('aui-thread-scroll-to-top absolute top-2 rounded-full p-4 dark:bg-background dark:hover:bg-accent', isAtTop && 'invisible')}\n onClick={handleClick}\n >\n <ArrowUpIcon />\n </TooltipIconButton>\n </div>\n );\n};\n\n/**\n * The asset-library categories of AthenaChat's `@` menu. Browse profiles,\n * team and drives are left out: they need browser-side scoping or a workspace\n * id that API-key auth does not carry. The Tools / Toolkits categories are\n * added when the host (or the provider's enabled toolkits) offers any.\n */\nconst ATHENA_CHAT_MENTION_CATEGORIES: readonly MentionRootCategory[] = [\n 'favorites',\n 'assets',\n 'projects',\n 'folders',\n];\n\n/**\n * AthenaChat's composer: the shared chat-ui Tiptap editor and `@` mention menu\n * with AthenaChat's quote and attachment pills composed into the send.\n *\n * A draft with a quote or attachment pills — text or not — is intercepted on\n * submit and dispatched as one composed message through the composer runtime,\n * the path the server-owned queue observes, so a mid-run submit queues like\n * any other send. Pasted images upload into the pills through the same intake\n * as the paperclip and the drop zone, and every submit path (Enter, the send\n * button) waits for an in-flight upload so a send never leaves without its\n * attachment. The send control resolves send / queue / stop through the\n * shared chat-ui logic.\n *\n * The chrome is the shared dock's paper appearance (`data-appearance=\"paper\"`\n * on `.aui-composer-root`): the drop zone reports drag-over into\n * `data-drag-active`, the first focus in a browser shows the Enter /\n * Shift+Enter hint until the first send, and a thread that mounts empty\n * brings the composer in last, after the greeting and the suggestion cards.\n */\nconst AthenaChatComposer: FC<{\n tools: MentionTool[];\n slots?: AthenaChatComposerSlots;\n dictation: boolean | AthenaChatDictationOptions;\n /** How many suggestion cards precede the composer's entrance in the empty state. */\n welcomeSuggestionCount: number;\n}> = ({ tools, slots, dictation, welcomeSuggestionCount }) => {\n const aui = useAui();\n const threadId = useAthenaStatewireThreadId();\n const { appUrl } = useAthenaConfig();\n const { attachments, clearAttachments, isUploading } = useAttachments();\n const { quote, clearQuote } = useQuote();\n const { attachFiles } = useAttachFiles();\n const composerRef = useRef<TiptapComposerHandle>(null);\n const [hasText, setHasText] = useState(false);\n const isRunning = useAuiState((state) => state.optional.thread?.isRunning ?? false);\n const [dragActive, setDragActive] = useState(false);\n const keyboardHint = useComposerKeyboardHint();\n const reducedMotion = usePrefersReducedMotion();\n // The staged entrance belongs to the empty state only: a composer that\n // mounts over an existing transcript is simply there.\n const isEmpty = useAuiState((state) => state.thread.isEmpty);\n const [mountedEmpty] = useState(() => isEmpty);\n const entrance = welcomeEntrance(\n welcomeComposerDelayMs(welcomeSuggestionCount),\n reducedMotion || !mountedEmpty,\n );\n\n // Dictation: the hook is inert until `start()`, so it mounts even when the\n // mic is turned off; `isSupported` hides the control where the engine is\n // missing (Firefox) instead of rendering a button that cannot work.\n const dictationEnabled = dictation !== false;\n const dictationOptions = typeof dictation === 'object' ? dictation : undefined;\n // Words join the draft that existed before recording (manual edits are\n // kept); the composer runtime mirrors `setText` into the Tiptap editor.\n const appendSpokenText = useCallback(\n (spoken: string) => {\n if (!spoken) return;\n aui.composer.setText(composeDictationDraft(aui.composer.getState().text ?? '', spoken));\n },\n [aui],\n );\n const dictationEngine = useAthenaDictationEngine(dictationOptions?.engine);\n const dictationCtl = useDictation({\n engine: dictationEngine,\n lang: dictationOptions?.lang,\n // A recognizer that gives up on its own (silence window) still hands\n // over what it heard instead of dropping the words with the session.\n onAutoEnd: appendSpokenText,\n });\n const recording = dictationEnabled && dictationCtl.isActive;\n const showMic = dictationEnabled && dictationCtl.isSupported;\n // A host that turns dictation off mid-session takes the controls away with\n // it; release the microphone and the recognizer rather than letting them\n // run on with no way to stop them.\n const { isActive: dictationActive, cancel: cancelDictation } = dictationCtl;\n useEffect(() => {\n if (!dictationEnabled && dictationActive) cancelDictation();\n }, [cancelDictation, dictationActive, dictationEnabled]);\n\n const rootCategories = useMemo<readonly MentionRootCategory[]>(() => {\n const categories = [...ATHENA_CHAT_MENTION_CATEGORIES];\n if (tools.some((tool) => tool.type === 'toolkit')) categories.push('toolkits');\n if (tools.some((tool) => tool.type === 'tool')) categories.push('tools');\n return categories;\n }, [tools]);\n\n // The submit paths are captured once by the editor's keybinding, so they\n // read the current draft extras through refs.\n const attachmentsRef = useRef(attachments);\n attachmentsRef.current = attachments;\n const quoteRef = useRef(quote);\n quoteRef.current = quote;\n const hasExtras = attachments.length > 0 || quote !== null;\n\n // A submit during an upload parks until the pills have the asset; the\n // waiters resolve on the render that turns `isUploading` off, by which\n // point `attachmentsRef` holds the uploaded asset.\n const isUploadingRef = useRef(isUploading);\n isUploadingRef.current = isUploading;\n const uploadWaitersRef = useRef<Array<() => void>>([]);\n useEffect(() => {\n if (isUploading) return;\n const waiters = uploadWaitersRef.current;\n uploadWaitersRef.current = [];\n for (const resolve of waiters) resolve();\n }, [isUploading]);\n const waitForHostUploads = useCallback(() => {\n if (!isUploadingRef.current) return;\n return new Promise<void>((resolve) => {\n uploadWaitersRef.current.push(resolve);\n });\n }, []);\n\n const sendComposed = useCallback(\n (userText: string): boolean => {\n const message = buildComposedMessage({\n attachments: attachmentsRef.current,\n quote: quoteRef.current,\n userText,\n appUrl,\n });\n if (!message) return false;\n // steer: false — a mid-run send queues behind the active run instead of\n // interrupting it; idle sends dispatch immediately.\n aui.composer.setText(message);\n aui.composer.send({ steer: false });\n clearAttachments();\n clearQuote();\n return true;\n },\n [appUrl, aui, clearAttachments, clearQuote],\n );\n\n // Consumes the editor's draft (possibly empty) only when there are extras\n // to compose with it.\n const interceptSubmit = useCallback(\n (text: string) =>\n attachmentsRef.current.length > 0 || quoteRef.current !== null\n ? sendComposed(text)\n : false,\n [sendComposed],\n );\n\n // Pasted images go through the pills' intake; drops are left to the\n // enclosing ComposerDropZone.\n const fileIntake = useMemo<ComposerFileIntake>(\n () => ({\n onPaste: (files) => {\n void attachFiles(files, 'paste');\n },\n }),\n [attachFiles],\n );\n\n // Stop: the spoken words join the draft and the editor comes back for review.\n const stopDictation = useCallback(async () => {\n appendSpokenText((await dictationCtl.stop()).text);\n }, [appendSpokenText, dictationCtl]);\n\n // Send: same merge, then dispatched the way the send button would — through\n // the composed-message path when pills are pending, else straight through\n // the composer runtime (a mid-run send queues; see sendComposed).\n const sendDictation = useCallback(async () => {\n const { text: spoken, error } = await dictationCtl.stop();\n const text = composeDictationDraft(aui.composer.getState().text ?? '', spoken);\n // A failed transcription has nothing to send; keep whatever landed in the\n // draft for review next to the error notice rather than dispatching a\n // message that is missing the dictated words.\n if (error) {\n aui.composer.setText(text);\n return;\n }\n const extras = attachmentsRef.current.length > 0 || quoteRef.current !== null;\n if (!text && !extras) return;\n // The merged draft is persisted before any host hook runs, so a hook that\n // rejects leaves the dictated words in the composer instead of losing them.\n aui.composer.setText(text);\n const action = resolveComposerAction({ hasDraft: true, isRunning });\n if (action === 'stop') return;\n try {\n await slots?.onBeforeSend?.({ action });\n } catch (error) {\n athenaDiagnostics.emit('composer.dictation', {\n level: 'warn',\n data: {\n phase: 'before_send_rejected',\n error: error instanceof Error ? error.message : String(error),\n },\n });\n return;\n }\n if (extras) {\n sendComposed(text);\n return;\n }\n aui.composer.send({ steer: false });\n }, [aui, dictationCtl, isRunning, sendComposed, slots]);\n\n return (\n <ComposerDropZone onDragActiveChange={setDragActive}>\n {/* React delivers `onFocus` as focusin, so the editor's focus reaches\n this wrapper; the same element carries the staged entrance. */}\n <div\n className={cn('aui-composer-entrance', entrance.className)}\n style={entrance.style}\n onFocus={keyboardHint.onFocus}\n >\n <ChatComposerDock\n appearance=\"paper\"\n dragActive={dragActive}\n aboveSurface={<ThreadScrollToBottom />}\n beforeEditor={\n <>\n <ComposerQuotePreview />\n <ComposerAttachmentPreview />\n </>\n }\n editor={\n <>\n {/* The editor stays mounted while recording so its draft and\n mention state survive; the waveform takes its place visually. */}\n <div className={cn(recording && 'hidden')}>\n <TiptapComposer\n ref={composerRef}\n threadId={threadId}\n appearance=\"paper\"\n placeholder=\"Type @ to tag an asset\"\n tools={tools}\n rootCategories={rootCategories}\n onDraftStateChange={setHasText}\n waitForHostUploads={waitForHostUploads}\n interceptSubmit={interceptSubmit}\n fileIntake={fileIntake}\n onSubmitted={keyboardHint.onSubmitted}\n />\n </div>\n {recording && (\n <DictationStrip\n status={dictationCtl.status}\n transcript={dictationCtl.transcript}\n stream={dictationCtl.stream}\n stoppingLabel={dictationCtl.engine.stoppingLabel}\n />\n )}\n {dictationEnabled && dictationCtl.status === DICTATION_STATUSES.error && dictationCtl.error && (\n <p className=\"aui-dictation-error px-1.5 pb-1 text-destructive text-xs\" role=\"alert\">\n {dictationCtl.error.message}\n </p>\n )}\n </>\n }\n toolbarStart={\n <div className=\"flex items-center gap-1\">\n {recording ? (\n <DictationCancelButton onClick={dictationCtl.cancel} />\n ) : (\n <>\n <FileUploadButton className=\"aui-composer-attach size-8 rounded-full p-0 disabled:opacity-30\" />\n <AthenaComposerMentionButton\n onClick={() => composerRef.current?.openMentionMenu?.()}\n />\n {slots?.toolbarStart}\n </>\n )}\n </div>\n }\n toolbarEnd={\n <div className=\"flex items-center gap-1\">\n {recording ? (\n <>\n <DictationStopButton\n onClick={() => void stopDictation()}\n disabled={dictationCtl.status === DICTATION_STATUSES.stopping}\n />\n <AthenaComposerSendButton\n action={isRunning ? 'queue' : 'send'}\n onSend={() => void sendDictation()}\n disabled={dictationCtl.status !== DICTATION_STATUSES.listening || isUploading}\n title={isUploading ? 'Upload in progress...' : undefined}\n />\n </>\n ) : (\n <>\n {slots?.toolbarEnd}\n {showMic && (\n <DictationMicButton onClick={dictationCtl.start} disabled={isUploading} />\n )}\n <ComposerSendOrStop\n composerRef={composerRef}\n hasDraft={hasText || hasExtras}\n sendBlockedReason={isUploading ? 'Upload in progress...' : null}\n onBeforeSend={slots?.onBeforeSend}\n components={ATHENA_COMPOSER_COMPONENTS}\n />\n </>\n )}\n </div>\n }\n belowSurface={<ComposerKeyboardHint visible={keyboardHint.visible} />}\n />\n </div>\n </ComposerDropZone>\n );\n};\n\nconst MessageError: FC = () => (\n <MessagePrimitive.Error>\n <ErrorPrimitive.Root className=\"aui-message-error-root mt-2 flex items-start gap-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm dark:bg-destructive/5 dark:text-red-200\">\n <AlertCircleIcon className=\"mt-0.5 size-4 shrink-0\" />\n <ErrorPrimitive.Message className=\"aui-message-error-message grow\" />\n <ActionBarPrimitive.Reload asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-6 shrink-0 text-destructive hover:text-destructive dark:text-red-200 dark:hover:text-red-100\"\n >\n <RefreshCwIcon className=\"size-3.5\" />\n </Button>\n </ActionBarPrimitive.Reload>\n </ErrorPrimitive.Root>\n </MessagePrimitive.Error>\n);\n\n/**\n * The quiet status line under a running turn: one pulsing dot, the verb\n * (\"Thinking…\", or the running tool's activity such as \"Searching the web…\"),\n * the elapsed seconds once the counter is due, and a stall tone once nothing\n * has streamed for a while — so a busy run and a possibly-stuck one stop\n * looking identical. The timer restarts whenever `resetKey` changes.\n */\nconst RunStatusLine: FC<{\n verb: string;\n resetKey: string;\n /** Render nothing until the counter is due (a host header already names the verb). */\n counterOnly?: boolean;\n className?: string;\n}> = ({ verb, resetKey, counterOnly = false, className }) => {\n const [seconds, setSeconds] = useState(0);\n useEffect(() => {\n setSeconds(0);\n const startedAt = Date.now();\n const timer = setInterval(() => {\n setSeconds(Math.floor((Date.now() - startedAt) / 1000));\n }, 1000);\n return () => clearInterval(timer);\n }, [resetKey]);\n const stalled = seconds >= RUN_ACTIVITY_STALL_SECONDS;\n if (counterOnly && seconds < RUN_ACTIVITY_COUNTER_SECONDS) return null;\n return (\n <div\n data-slot=\"run-status-line\"\n data-stalled={stalled ? 'true' : undefined}\n className={cn(\n 'aui-run-activity mt-2 flex items-center gap-2 px-1 text-[12px] text-muted-foreground',\n className,\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n 'size-1.5 shrink-0 rounded-full bg-current opacity-60',\n !stalled && 'animate-pulse motion-reduce:animate-none',\n )}\n />\n <span\n aria-hidden=\"true\"\n className={cn('tabular-nums', stalled && 'text-amber-600 dark:text-amber-400')}\n >\n {runActivityLabel(seconds, verb)}\n </span>\n {/* The visible counter ticks every second; announcing each tick would\n drown a screen reader, so the live region only speaks the two\n meaningful transitions: what the run is doing, and that it looks\n stalled. */}\n <span aria-live=\"polite\" className=\"sr-only\">\n {stalled ? 'Assistant is still working; nothing new for over thirty seconds.' : `${verb}…`}\n </span>\n </div>\n );\n};\n\nconst AthenaAssistantMessageEmpty: EmptyMessagePartComponent = ({ status }) => {\n if (status?.type !== 'running') return null;\n return <RunStatusLine verb=\"Thinking\" resetKey=\"empty\" className=\"mt-0\" />;\n};\n\n/**\n * Renders the empty/loading indicator while a message is running but has no\n * parts yet. `MessagePrimitive.GroupedParts` only renders existing parts, so\n * the indicator can't live inside its switch — it goes here as a sibling.\n */\nconst AthenaMessageEmptyIndicator: FC<{ EmptyComponent: EmptyMessagePartComponent }> = ({\n EmptyComponent,\n}) => {\n const hasParts = useAuiState((s) => s.message.parts.length > 0);\n const isRunning = useAuiState((s) => s.message.status?.type === 'running');\n if (hasParts || !isRunning) return null;\n return <EmptyComponent status={{ type: 'running' }} />;\n};\n\n/**\n * Run-liveness line under a running message whose tail is a tool call: the\n * tool's own verb from the shared registry, an elapsed counter that resets\n * whenever the stream moves the tail part, and the stall tone. Text and\n * reasoning tails animate on their own and render no line.\n */\nconst AthenaMessageActivityIndicator: FC = () => {\n const isRunning = useAuiState((s) => s.message.status?.type === 'running');\n const activityKey = useAuiState((s) => runActivityKey(s.message.parts));\n const verb = useAuiState((s) => runActivityVerb(s.message.parts));\n if (!isRunning || activityKey === null) return null;\n return <RunStatusLine verb={verb ?? 'Working'} resetKey={activityKey} />;\n};\n\n/**\n * The grouped view's running meta: the activity card already names the verb,\n * so this adds only the elapsed counter (after three seconds) and the stall\n * tone, keyed to the stream's tail like the inline indicator.\n */\nconst AthenaGroupedRunMeta: FC = () => {\n const activityKey = useAuiState((s) => runActivityKey(s.message.parts));\n return (\n <RunStatusLine\n verb=\"Working\"\n resetKey={activityKey ?? 'thinking'}\n counterOnly\n className=\"mt-1 px-0\"\n />\n );\n};\nconst renderGroupedRunningMeta = () => <AthenaGroupedRunMeta />;\n\n/**\n * The centered hairline with the date, rendered above the first message of a\n * calendar day that differs from the previous message's. Both messages need\n * the runtime's `_created_at` stamp; without it there is nothing truthful to\n * separate on.\n */\nconst MessageDaySeparator: FC = () => {\n const stamp = useAuiState((s) => readMessageCreatedAt(s.message.metadata?.custom));\n const previousStamp = useAuiState((s) => {\n const index = s.message.index;\n const previous = index > 0 ? s.thread.messages[index - 1] : undefined;\n return readMessageCreatedAt(previous?.metadata?.custom);\n });\n const label = useMemo(() => {\n const date = stamp ? parseMessageTime(stamp) : null;\n const previous = previousStamp ? parseMessageTime(previousStamp) : null;\n if (!date || !previous || isSameCalendarDay(date, previous)) return null;\n return formatDayLabel(date);\n }, [stamp, previousStamp]);\n if (!label) return null;\n return (\n <div\n role=\"separator\"\n aria-label={label}\n data-slot=\"day-separator\"\n className=\"aui-day-separator mb-3 flex w-full items-center gap-3 text-[11px] font-medium text-muted-foreground\"\n >\n <span aria-hidden=\"true\" className=\"h-px flex-1 bg-border\" />\n <span>{label}</span>\n <span aria-hidden=\"true\" className=\"h-px flex-1 bg-border\" />\n </div>\n );\n};\n\n/**\n * The message's clock time, revealed on hover beside the action bar (the\n * full date in its `title`). Reads the runtime's `_created_at` stamp; a\n * message without one shows no time rather than a wrong one.\n */\nconst MessageTimestamp: FC<{ className?: string }> = ({ className }) => {\n const stamp = useAuiState((s) => readMessageCreatedAt(s.message.metadata?.custom));\n const date = useMemo(() => (stamp ? parseMessageTime(stamp) : null), [stamp]);\n if (!date) return null;\n return (\n <time\n dateTime={date.toISOString()}\n title={formatMessageDateTime(date)}\n data-slot=\"message-timestamp\"\n className={cn(\n 'aui-message-timestamp shrink-0 text-[11px] tabular-nums text-muted-foreground',\n ACTION_BAR_REVEAL_CLASS,\n className,\n )}\n >\n {formatMessageTime(date)}\n </time>\n );\n};\n\nexport const AthenaReasoningPart: FC<AthenaReasoningPartProps> = ({\n text,\n status,\n TextComponent,\n}) => {\n const inheritedTextComponent = useContext(AthenaReasoningTextComponentContext);\n const EffectiveTextComponent = TextComponent ?? inheritedTextComponent ?? TiptapText;\n const isMessageRunning = useAuiState((state) => state.message.status?.type === 'running');\n const reasoningTokens = useAuiState((state) =>\n getReasoningTokensFromMetadata(state.message.metadata)\n );\n const isRunning = isMessageRunning || status?.type === 'running';\n const [isCollapsed, setIsCollapsed] = useState(!isRunning);\n const userOverrodeOpenStateRef = useRef(false);\n const hasText = text.trim().length > 0;\n\n const reasoningTextProps: TextMessagePartProps = {\n type: 'text',\n text,\n status: isRunning\n ? ({ type: 'running' } as TextMessagePartProps['status'])\n : (status as TextMessagePartProps['status']),\n };\n\n useEffect(() => {\n if (userOverrodeOpenStateRef.current) {\n return;\n }\n\n setIsCollapsed(!isRunning);\n }, [isRunning]);\n\n if (!hasText && !isRunning) {\n return null;\n }\n\n return (\n <Collapsible\n open={!isCollapsed}\n onOpenChange={(open) => {\n userOverrodeOpenStateRef.current = true;\n setIsCollapsed(!open);\n }}\n className=\"aui-assistant-reasoning-root mb-3 rounded-2xl border border-border/60 bg-muted/30 px-3 py-2\"\n >\n <CollapsibleTrigger asChild>\n <button\n type=\"button\"\n className=\"flex w-full items-center justify-between gap-3 text-left\"\n aria-label={isRunning ? 'Toggle reasoning while streaming' : 'Toggle reasoning'}\n >\n <span className=\"flex min-w-0 items-center gap-2 text-[13px] font-medium text-muted-foreground\">\n <BrainIcon className=\"size-4 shrink-0\" />\n <span>{isRunning ? 'Reasoning...' : 'Reasoning'}</span>\n </span>\n <span className=\"flex shrink-0 items-center gap-2\">\n {reasoningTokens !== undefined && (\n <span className=\"rounded-full border border-border/60 bg-background px-2 py-0.5 text-[11px] font-medium text-muted-foreground\">\n {formatReasoningTokens(reasoningTokens)}\n </span>\n )}\n <span\n className={cn(\n 'flex size-5 items-center justify-center text-muted-foreground transition-transform',\n isCollapsed ? 'rotate-0' : 'rotate-90'\n )}\n aria-hidden=\"true\"\n >\n <ChevronRightIcon className=\"size-4\" />\n </span>\n </span>\n </button>\n </CollapsibleTrigger>\n\n <CollapsibleContent className=\"pt-3\">\n {isRunning && !hasText ? (\n <span className=\"shimmer text-[13px] text-muted-foreground\">Analyzing...</span>\n ) : (\n <div className=\"aui-assistant-reasoning-body text-[13px] leading-relaxed\">\n <EffectiveTextComponent {...reasoningTextProps} />\n </div>\n )}\n </CollapsibleContent>\n </Collapsible>\n );\n};\n\nconst groupAdjacentToolCalls = (part: PartState) =>\n part.type === 'tool-call' ? (['group-tool'] as const) : null;\nconst noToolGrouping = () => null;\n\nexport const AthenaAssistantMessage: FC<AthenaAssistantMessageProps> = ({\n toolUIs,\n AvatarComponent,\n TextComponent = TiptapText,\n ReasoningComponent,\n EmptyComponent = AthenaAssistantMessageEmpty,\n ActionBarComponent = AthenaAssistantActionBar,\n groupToolCalls = true,\n}) => {\n const effectiveReasoningComponent = ReasoningComponent ?? AthenaReasoningPart;\n const toolUIsWithNestedMessages = useMemo(() => {\n const wrappedToolUIs: Record<string, ToolCallMessagePartComponent> = {};\n\n for (const [toolName, ToolUI] of Object.entries(toolUIs)) {\n wrappedToolUIs[toolName] = withNestedPtcMessages(ToolUI);\n }\n\n return wrappedToolUIs;\n }, [toolUIs]);\n\n // NestedPtcComponentsProvider still consumes the legacy parts-config shape\n // (Text / Reasoning / tools.by_name / Empty) to render PTC sub-tool messages\n // inside a tool card. The outer rendering uses GroupedParts, but the inner\n // PTC tree continues to mirror the parent registry.\n const nestedPtcComponents = useMemo(\n () => ({\n Text: TextComponent,\n Reasoning: effectiveReasoningComponent,\n tools: {\n Fallback: ToolFallback,\n by_name: toolUIsWithNestedMessages,\n },\n Empty: EmptyComponent,\n }),\n [EmptyComponent, TextComponent, effectiveReasoningComponent, toolUIsWithNestedMessages],\n );\n\n return (\n <MessagePrimitive.Root\n className=\"aui-assistant-message-root group/aui-assistant-message fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in py-3 duration-150\"\n data-role=\"assistant\"\n >\n <MessageDaySeparator />\n <div className=\"flex gap-3\">\n {/* The leading column exists only when the host supplies an avatar;\n without one the turn is told apart from the right-aligned user\n bubbles by alignment alone, with no rule or gutter of its own. */}\n {AvatarComponent ? (\n <div\n data-slot=\"assistant-lead\"\n className=\"aui-assistant-message-lead flex shrink-0 justify-center\"\n >\n <AvatarComponent />\n </div>\n ) : null}\n <div className=\"min-w-0 flex-1\">\n <AthenaReasoningTextComponentContext.Provider value={TextComponent}>\n <div className=\"aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed\">\n <NestedPtcComponentsProvider components={nestedPtcComponents}>\n {groupToolCalls ? (\n <div className=\"flex flex-col space-y-2\">\n <SuperGroupingCard\n toolUIs={toolUIsWithNestedMessages}\n TextComponent={TextComponent}\n ReasoningComponent={effectiveReasoningComponent}\n renderRunningMeta={renderGroupedRunningMeta}\n />\n <SuperGroupingFinalText TextComponent={TextComponent} />\n </div>\n ) : (\n <>\n <AthenaMessageEmptyIndicator EmptyComponent={EmptyComponent} />\n <MessagePrimitive.GroupedParts groupBy={noToolGrouping}>\n {({ part }) => {\n switch (part.type) {\n case 'tool-call': {\n const ToolUI = toolUIsWithNestedMessages[part.toolName];\n const toolProps = part as unknown as ToolCallMessagePartProps;\n return ToolUI ? <ToolUI {...toolProps} /> : <ToolFallback {...toolProps} />;\n }\n case 'reasoning': {\n const ReasoningRenderer = effectiveReasoningComponent;\n return <ReasoningRenderer {...(part as ReasoningMessagePartProps)} />;\n }\n case 'text': {\n const textPart = part as TextMessagePartProps;\n if (textPart.text === '' && textPart.status?.type === 'running') {\n return <EmptyComponent status={textPart.status} />;\n }\n return <TextComponent {...textPart} />;\n }\n default:\n return null;\n }\n }}\n </MessagePrimitive.GroupedParts>\n <AthenaMessageActivityIndicator />\n </>\n )}\n </NestedPtcComponentsProvider>\n <MessageError />\n </div>\n </AthenaReasoningTextComponentContext.Provider>\n <div className=\"aui-assistant-message-footer mt-1 ml-2 flex items-center gap-1\">\n <BranchPicker />\n <ActionBarComponent />\n <MessageTimestamp className=\"ml-auto group-hover/aui-assistant-message:opacity-100\" />\n </div>\n </div>\n </div>\n </MessagePrimitive.Root>\n );\n};\n\nconst AthenaToolGroup: FC<{ children: React.ReactNode; count: number }> = ({ children, count }) => {\n const [expanded, setExpanded] = useState(false);\n\n return (\n <div className=\"my-3 w-full overflow-hidden rounded-xl border border-border/60 bg-background shadow-sm\">\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n className=\"flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-muted/20\"\n aria-expanded={expanded}\n >\n <div className=\"flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted/60 text-muted-foreground\">\n <LayersIcon className=\"size-4\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <span className=\"text-[13px] font-medium text-foreground\">\n {count} tool {count === 1 ? 'call' : 'calls'}\n </span>\n </div>\n <ChevronDownIcon\n className={cn(\n 'size-4 shrink-0 text-muted-foreground transition-transform duration-200',\n !expanded && '-rotate-90',\n )}\n />\n </button>\n {expanded && (\n <div className=\"border-t border-border/40 bg-muted/5 px-3 pt-1 pb-2 [&>*]:my-2\">\n {children}\n </div>\n )}\n </div>\n );\n};\n\nconst CopyMessageButton: FC = () => (\n <ActionBarPrimitive.Copy asChild>\n <TooltipIconButton tooltip=\"Copy\">\n <AuiIf condition={(s) => s.message.isCopied}>\n <CheckIcon />\n </AuiIf>\n <AuiIf condition={(s) => !s.message.isCopied}>\n <CopyIcon />\n </AuiIf>\n </TooltipIconButton>\n </ActionBarPrimitive.Copy>\n);\n\n/** Regenerate dispatches `run/reload`, so it hides on read-only threads. */\nconst RegenerateMessageButton: FC = () => {\n const readOnly = useMessageActionsReadOnly();\n if (readOnly) return null;\n return (\n <ActionBarPrimitive.Reload asChild>\n <TooltipIconButton tooltip=\"Regenerate\">\n <RefreshCwIcon />\n </TooltipIconButton>\n </ActionBarPrimitive.Reload>\n );\n};\n\n/**\n * The edit primitive does not check the runtime's edit capability itself —\n * clicking it on a runtime without one throws inside onPress — so the button\n * gates on the capability and, to match the rewind semantics of `run/edit`,\n * stays hidden while a run is live or the transcript is read-only.\n */\nconst EditMessageButton: FC = () => {\n const allowEdit = useAuiState((s) => s.thread.capabilities.edit);\n const isRunning = useAthenaRunLive();\n const readOnly = useMessageActionsReadOnly();\n if (!allowEdit || isRunning || readOnly) return null;\n return (\n <ActionBarPrimitive.Edit asChild>\n <TooltipIconButton tooltip=\"Edit\">\n <PencilIcon />\n </TooltipIconButton>\n </ActionBarPrimitive.Edit>\n );\n};\n\n/** Hover-revealed copy / edit row under a user bubble; mirrors the assistant bar. */\nconst AthenaUserActionBar: FC = () => {\n const isThreadRunning = useAuiState((s) => s.thread.isRunning);\n return (\n <ActionBarPrimitive.Root\n autohide=\"never\"\n className={cn(\n 'aui-user-action-bar-root flex min-h-6 gap-1 text-muted-foreground',\n isThreadRunning\n ? 'invisible'\n : [\n ACTION_BAR_REVEAL_CLASS,\n 'group-hover/aui-user-message:pointer-events-auto group-hover/aui-user-message:opacity-100',\n ],\n )}\n >\n <CopyMessageButton />\n <EditMessageButton />\n </ActionBarPrimitive.Root>\n );\n};\n\nexport const AthenaAssistantActionBar: FC<AthenaAssistantActionBarProps> = ({ className }) => {\n const threadId = useAthenaThreadId();\n const { appUrl } = useAthenaConfig();\n // The bar stays mounted so the footer keeps its height: assistant-ui's\n // `autohide` / `hideWhenRunning` unmount it, which shifts the whole message\n // up and down on every hover. Visibility is CSS instead — the latest reply\n // keeps its actions, older replies reveal on hover or keyboard focus, and\n // while the thread runs every bar is `invisible` (layout kept, controls\n // unfocusable — opacity alone would still let Tab reveal them).\n const isLast = useAuiState((s) => s.message.isLast);\n const isThreadRunning = useAuiState((s) => s.thread.isRunning);\n\n return (\n <ActionBarPrimitive.Root\n autohide=\"never\"\n className={cn(\n 'aui-assistant-action-bar-root -ml-1 flex min-h-6 gap-1 text-muted-foreground',\n isThreadRunning && 'invisible',\n !isThreadRunning &&\n !isLast && [\n ACTION_BAR_REVEAL_CLASS,\n 'group-hover/aui-assistant-message:pointer-events-auto group-hover/aui-assistant-message:opacity-100',\n ],\n className,\n )}\n >\n <CopyMessageButton />\n <RegenerateMessageButton />\n <ActionBarMorePrimitive.Root>\n <ActionBarMorePrimitive.Trigger asChild>\n <TooltipIconButton tooltip=\"More\" className=\"data-[state=open]:bg-accent\">\n <MoreHorizontalIcon />\n </TooltipIconButton>\n </ActionBarMorePrimitive.Trigger>\n <ActionBarMorePrimitive.Content\n side=\"bottom\"\n align=\"start\"\n className=\"aui-action-bar-more-content z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md\"\n >\n <ActionBarPrimitive.ExportMarkdown asChild>\n <ActionBarMorePrimitive.Item className=\"aui-action-bar-more-item flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\">\n <DownloadIcon className=\"size-4\" />\n Export as Markdown\n </ActionBarMorePrimitive.Item>\n </ActionBarPrimitive.ExportMarkdown>\n {threadId && (\n <ActionBarMorePrimitive.Item\n className=\"aui-action-bar-more-item flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\"\n onClick={() => {\n window.open(createAthenaSpacesUrl({ appUrl, sessionId: threadId }), '_blank');\n }}\n >\n <ExternalLinkIcon className=\"size-4\" />\n Open in Athena\n </ActionBarMorePrimitive.Item>\n )}\n </ActionBarMorePrimitive.Content>\n </ActionBarMorePrimitive.Root>\n </ActionBarPrimitive.Root>\n );\n};\n\nexport const AthenaUserMessage: FC<AthenaUserMessageProps> = ({\n TextComponent = TiptapText,\n}) => {\n // A GitHub wake turn is an event, not words the user typed: it renders as\n // the compact wake marker instead of a bubble quoting the injected text.\n const isWake = useAuiState((s) => isGithubWakeMessage(s.message.metadata?.custom));\n if (isWake) {\n return (\n <MessagePrimitive.Root\n className=\"aui-user-message-root aui-wake-marker-root mx-auto w-full max-w-(--thread-max-width) px-2 py-1\"\n data-role=\"user\"\n >\n <MessageDaySeparator />\n <WakeMarkerMessage />\n </MessagePrimitive.Root>\n );\n }\n return (\n <MessagePrimitive.Root\n className=\"aui-user-message-root group/aui-user-message fade-in slide-in-from-bottom-1 mx-auto flex w-full max-w-(--thread-max-width) animate-in flex-col items-end px-2 py-3 duration-150\"\n data-role=\"user\"\n >\n <MessageDaySeparator />\n {/* A soft bubble on a 75% measure: the user's words stay a bubble, the\n assistant's reading column stays the page. */}\n <div className=\"flex min-w-0 max-w-[75%] flex-col items-end gap-1\">\n <div className=\"aui-user-message-content wrap-break-word rounded-2xl bg-muted/70 px-4 py-2.5 text-foreground\">\n <MessagePrimitive.Parts components={{ Text: TextComponent }} />\n </div>\n <div className=\"aui-user-message-footer -mr-1 flex items-center gap-1\">\n <MessageTimestamp className=\"mr-1 group-hover/aui-user-message:opacity-100\" />\n <BranchPicker />\n <AthenaUserActionBar />\n </div>\n </div>\n </MessagePrimitive.Root>\n );\n};\n"],"names":["_a","error"],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ const reactStatewire = require("@assistant-ui/react-statewire");
|
|
|
6
6
|
const lucideReact = require("lucide-react");
|
|
7
7
|
const react$1 = require("react");
|
|
8
8
|
const continuePill = require("../chat-ui/messages/continue-pill.cjs");
|
|
9
|
+
const mentionChip = require("../chat-ui/mentions/mention-chip.cjs");
|
|
9
10
|
const threadExtras = require("../packages/agent-runtime/src/thread-extras.cjs");
|
|
10
11
|
const statewireState = require("../packages/agent-runtime/src/statewire-state.cjs");
|
|
11
12
|
const queue = require("../packages/agent-runtime/src/queue.cjs");
|
|
@@ -77,7 +78,7 @@ const StatewireQueuedMessagesInner = ({
|
|
|
77
78
|
}
|
|
78
79
|
};
|
|
79
80
|
if (rows.length === 0 && failed.length === 0) return null;
|
|
80
|
-
const renderRowContent = (context) => renderContent ? renderContent(context) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
81
|
+
const renderRowContent = (context) => renderContent ? renderContent(context) : /* @__PURE__ */ jsxRuntime.jsx(QueueRowText, { text: context.text });
|
|
81
82
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
82
83
|
"section",
|
|
83
84
|
{
|
|
@@ -364,6 +365,48 @@ const QueueAutoContinue = ({
|
|
|
364
365
|
]);
|
|
365
366
|
return null;
|
|
366
367
|
};
|
|
368
|
+
const QueueRowText = ({ text }) => {
|
|
369
|
+
const bodyRef = react$1.useRef(null);
|
|
370
|
+
const [expanded, setExpanded] = react$1.useState(false);
|
|
371
|
+
const [overflows, setOverflows] = react$1.useState(false);
|
|
372
|
+
react$1.useLayoutEffect(() => {
|
|
373
|
+
const body = bodyRef.current;
|
|
374
|
+
if (!body || expanded) return;
|
|
375
|
+
const measure = () => setOverflows(body.scrollHeight > body.clientHeight + 1);
|
|
376
|
+
measure();
|
|
377
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
378
|
+
const observer = new ResizeObserver(measure);
|
|
379
|
+
observer.observe(body);
|
|
380
|
+
return () => observer.disconnect();
|
|
381
|
+
}, [text, expanded]);
|
|
382
|
+
if (!text) {
|
|
383
|
+
return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "min-w-0 flex-1 text-foreground text-xs", children: "Queued attachment" });
|
|
384
|
+
}
|
|
385
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
386
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
387
|
+
"p",
|
|
388
|
+
{
|
|
389
|
+
ref: bodyRef,
|
|
390
|
+
className: cnfast.cn(
|
|
391
|
+
"whitespace-pre-wrap break-words text-foreground text-xs leading-relaxed",
|
|
392
|
+
!expanded && "line-clamp-2"
|
|
393
|
+
),
|
|
394
|
+
title: overflows && !expanded ? mentionChip.mentionsToPlainText(text) : void 0,
|
|
395
|
+
children: mentionChip.parseMentionsInText(text)
|
|
396
|
+
}
|
|
397
|
+
),
|
|
398
|
+
overflows || expanded ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
399
|
+
"button",
|
|
400
|
+
{
|
|
401
|
+
type: "button",
|
|
402
|
+
"aria-expanded": expanded,
|
|
403
|
+
onClick: () => setExpanded((value) => !value),
|
|
404
|
+
className: "mt-0.5 font-medium text-[10px] text-muted-foreground hover:text-foreground",
|
|
405
|
+
children: expanded ? "Show less" : "Show more"
|
|
406
|
+
}
|
|
407
|
+
) : null
|
|
408
|
+
] });
|
|
409
|
+
};
|
|
367
410
|
const DefaultQueueEditor = ({
|
|
368
411
|
value,
|
|
369
412
|
onChange,
|