@x12i/ai 1.0.0 → 1.1.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 +515 -24
- package/dist/chunk-RP5SPJKM.js +1179 -0
- package/dist/chunk-RP5SPJKM.js.map +1 -0
- package/dist/index.d.ts +273 -72
- package/dist/index.js +510 -9
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +906 -0
- package/dist/react.js +3067 -0
- package/dist/react.js.map +1 -0
- package/dist/stream-C2tzoSII.d.ts +482 -0
- package/dist/styles.css +1225 -0
- package/package.json +48 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react/chat-thread.tsx","../src/react/conversation.tsx","../src/react/internal/cx.ts","../src/react/internal/glyphs.tsx","../src/react/messages-context.tsx","../src/react/messages.ts","../src/react/use-stick-to-bottom.ts","../src/react/internal/hooks.ts","../src/react/empty-thread.tsx","../src/react/error-banner.tsx","../src/react/message.tsx","../src/react/attachments.tsx","../src/react/internal/json-view.tsx","../src/react/internal/copy-button.tsx","../src/react/internal/clipboard.ts","../src/react/internal/use-autosize.ts","../src/react/markdown.tsx","../src/react/code-block.tsx","../src/react/sources.tsx","../src/react/internal/disclosure.ts","../src/react/reasoning.tsx","../src/react/streaming-indicator.tsx","../src/react/tool-call.tsx","../src/react/approval-prompt.tsx","../src/react/message-actions.tsx","../src/react/prompt-input.tsx","../src/react/suggestions.tsx","../src/react/use-thread.ts"],"sourcesContent":["import { VisuallyHidden } from \"@x12i/ui\";\nimport {\n memo,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithRef,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { markdownToPlainText, splitCompletedSentences } from \"../format\";\nimport { lastMessageWithRole, messageText, threadPendingApprovals } from \"../messages\";\nimport type { BranchInfo, ThreadStatus } from \"../thread-state\";\nimport type { Message as ThreadMessage, ThreadError } from \"../types\";\nimport { Conversation, type ConversationHandle } from \"./conversation\";\nimport { EmptyThread } from \"./empty-thread\";\nimport { ErrorBanner } from \"./error-banner\";\nimport { cx } from \"./internal/cx\";\nimport { useEventCallback } from \"./internal/hooks\";\nimport { Message, type PartRenderers } from \"./message\";\nimport { MessageActions, type Feedback } from \"./message-actions\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { AiMessagesProvider, useAiMessages } from \"./messages-context\";\nimport { PromptInput, type PromptAttachment, type PromptInputProps } from \"./prompt-input\";\nimport { StreamingIndicator } from \"./streaming-indicator\";\nimport { Suggestions, type Suggestion } from \"./suggestions\";\n\n/** How much of a finished reply is spoken, at most. The full text stays in the message. */\nconst ANNOUNCE_MAX_CHARS = 600;\n\n/**\n * When the thread speaks a reply to a screen reader:\n * - `complete`: once, when the reply is finished (default).\n * - `sentences`: each finished sentence while it streams, then the rest.\n * - `off`: never. The messages are still in the `role=\"log\"`.\n */\nexport type AnnounceMode = \"complete\" | \"sentences\" | \"off\";\n\nexport interface ChatThreadProps extends Omit<ComponentPropsWithRef<\"section\">, \"children\" | \"onSubmit\"> {\n messages: readonly ThreadMessage[];\n /** The conversation's state. Defaults to `streaming` if the last message is streaming, otherwise `idle`. */\n status?: ThreadStatus | undefined;\n /** A failure that is not tied to a message. */\n error?: ThreadError | null | undefined;\n /** Called with the text and attachments when the user sends. */\n onSend: (text: string, attachments?: readonly PromptAttachment[]) => void;\n onStop?: (() => void) | undefined;\n /** Shows a regenerate button on the last reply, and the retry button of an error. */\n onRegenerate?: (() => void) | undefined;\n /** Called when the user approves or denies a tool call. Without it the approval buttons are not shown. */\n onToolDecision?: ((callId: string, decision: \"approve\" | \"deny\", reason?: string) => void) | undefined;\n /** Shows an edit button on user messages. */\n onEdit?: ((messageId: string, text: string) => void) | undefined;\n /** Version navigation for edited messages, from `useThread().chatProps.branches`. */\n branches?: Record<string, BranchInfo> | undefined;\n onSwitchBranch?: ((parentId: string, index: number) => void) | undefined;\n onDismissError?: (() => void) | undefined;\n /** Shows thumbs buttons on replies. */\n onFeedback?: ((messageId: string, feedback: Feedback | null) => void) | undefined;\n /** Current ratings by message id. Omit to let the thread remember them. */\n feedback?: Record<string, Feedback | null | undefined> | undefined;\n /** Starter prompts, shown while the thread is empty. */\n suggestions?: readonly Suggestion[] | undefined;\n /** Follow-up prompts, shown under the last reply when nothing is running. */\n followUps?: readonly Suggestion[] | undefined;\n /** Replaces how parts render, for example to draw a chart for `data:chart`. Memoize it. */\n renderPart?: PartRenderers | undefined;\n /** Replaces the empty state. */\n emptyState?: ReactNode;\n /** Content above the conversation, such as a title bar. */\n header?: ReactNode;\n /** Text under the prompt. Defaults to the AI-generated notice. Pass `false` to hide it. */\n disclaimer?: ReactNode | false | undefined;\n /** Avatars by role (decorative). */\n avatars?: { user?: ReactNode; assistant?: ReactNode } | undefined;\n /** Display names by role. Defaults to `strings.roles`. */\n names?: { user?: string; assistant?: string } | undefined;\n showTimestamps?: boolean | undefined;\n showUsage?: boolean | undefined;\n /** How images in replies are shown. Default `\"link\"`. See `Markdown`. */\n images?: \"inline\" | \"link\" | \"none\" | undefined;\n announce?: AnnounceMode | undefined;\n /** Disables the prompt. */\n disabled?: boolean | undefined;\n /** More props for the prompt box: `maxLength`, `slashCommands`, `onFiles`, `accept`, `placeholder`... */\n promptProps?: Partial<Omit<PromptInputProps, \"onSubmit\" | \"status\" | \"onStop\" | \"disabled\">> | undefined;\n locale?: string | undefined;\n /** The words the thread shows. A partial catalog, merged over `defaultMessages`. (Named `strings` because `messages` is the list.) */\n strings?: AiMessagesOverride | undefined;\n /** Imperative handle of the conversation: `scrollToBottom()`. */\n conversationRef?: Ref<ConversationHandle> | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Live announcements\n// ---------------------------------------------------------------------------\n\ninterface AnnouncerOptions {\n messages: readonly ThreadMessage[];\n busy: boolean;\n mode: AnnounceMode;\n approvalsEnabled: boolean;\n}\n\nfunction truncate(text: string): string {\n return text.length > ANNOUNCE_MAX_CHARS ? `${text.slice(0, ANNOUNCE_MAX_CHARS).trimEnd()}…` : text;\n}\n\n/**\n * Decides what to speak. A finished reply is spoken once; tokens never are.\n * Existing history and branch switches are not spoken: only a reply that\n * this thread watched being written, a stop, and a new approval request.\n */\nfunction useAnnouncement({ messages, busy, mode, approvalsEnabled }: AnnouncerOptions): string {\n const strings = useAiMessages();\n const [announcement, setAnnouncement] = useState(\"\");\n const wasBusy = useRef(busy);\n const spoken = useRef(new Map<string, number>());\n const approvals = useRef<Set<string> | null>(null);\n if (approvals.current === null) {\n approvals.current = new Set(threadPendingApprovals(messages).map((part) => part.id));\n }\n\n useEffect(() => {\n if (mode === \"off\") {\n wasBusy.current = busy;\n return;\n }\n const lines: string[] = [];\n\n if (mode === \"sentences\" && busy) {\n for (const message of messages) {\n if (message.role !== \"assistant\" || message.status !== \"streaming\") continue;\n const { complete } = splitCompletedSentences(messageText(message));\n const done = spoken.current.get(message.id) ?? 0;\n if (complete.length > done) {\n const chunk = markdownToPlainText(complete.slice(done));\n spoken.current.set(message.id, complete.length);\n if (chunk !== \"\") lines.push(chunk);\n }\n }\n }\n\n // The run just ended: speak how.\n if (wasBusy.current && !busy) {\n const last = lastMessageWithRole(messages, \"assistant\");\n if (last) {\n const text = messageText(last);\n const alreadySpoken = spoken.current.get(last.id) ?? 0;\n spoken.current.delete(last.id);\n if (last.status === \"stopped\") {\n lines.push(strings.announceStopped);\n } else if (last.status === \"complete\" || last.status === undefined) {\n if (mode === \"sentences\") {\n const rest = markdownToPlainText(text.slice(alreadySpoken));\n if (rest !== \"\") lines.push(rest);\n } else {\n const plain = markdownToPlainText(text);\n if (plain !== \"\") lines.push(strings.announceReply(truncate(plain)));\n }\n }\n // A failed reply announces itself through the error banner (`role=\"alert\"`).\n }\n }\n wasBusy.current = busy;\n\n if (approvalsEnabled) {\n for (const part of threadPendingApprovals(messages)) {\n if (!approvals.current?.has(part.id)) {\n approvals.current?.add(part.id);\n lines.push(strings.announceApproval(part.name));\n }\n }\n }\n\n if (lines.length > 0) setAnnouncement(lines.join(\" \"));\n }, [messages, busy, mode, approvalsEnabled, strings]);\n\n return announcement;\n}\n\n// ---------------------------------------------------------------------------\n// One message in the thread\n// ---------------------------------------------------------------------------\n\ninterface ThreadMessageItemProps {\n message: ThreadMessage;\n streaming: boolean;\n busy: boolean;\n isLastAssistant: boolean;\n branch: BranchInfo | undefined;\n editing: boolean;\n feedback: Feedback | null;\n canFeedback: boolean;\n canEdit: boolean;\n canRegenerate: boolean;\n canDecide: boolean;\n avatar: ReactNode;\n name: string | undefined;\n locale: string | undefined;\n images: \"inline\" | \"link\" | \"none\" | undefined;\n showTimestamp: boolean;\n showUsage: boolean;\n renderPart: PartRenderers | undefined;\n onToolDecision: (callId: string, decision: \"approve\" | \"deny\", reason?: string) => void;\n onRegenerate: () => void;\n onStartEdit: (messageId: string) => void;\n onEditSubmit: (messageId: string, text: string) => void;\n onEditCancel: () => void;\n onFeedback: (messageId: string, feedback: Feedback | null) => void;\n onSwitchBranch: (parentId: string, index: number) => void;\n}\n\n/** `memo` skips every message whose data did not change while the last one streams. */\nconst ThreadMessageItem = memo(function ThreadMessageItem(props: ThreadMessageItemProps) {\n const { message, streaming, busy } = props;\n const text = messageText(message);\n const role = message.role;\n const interactive = (role === \"assistant\" || role === \"user\") && !streaming && !props.editing;\n\n const regenerate = interactive && role === \"assistant\" && props.isLastAssistant && props.canRegenerate;\n const edit = interactive && role === \"user\" && props.canEdit;\n const rate = interactive && role === \"assistant\" && props.canFeedback;\n const branch = interactive ? props.branch : undefined;\n const hasActions = text !== \"\" || regenerate || edit || rate || (branch !== undefined && branch.count > 1);\n\n const actions =\n interactive && hasActions ? (\n <MessageActions\n text={text === \"\" ? undefined : text}\n onRegenerate={regenerate ? props.onRegenerate : undefined}\n onEdit={edit ? () => props.onStartEdit(message.id) : undefined}\n feedback={props.feedback}\n onFeedback={rate ? (value) => props.onFeedback(message.id, value) : undefined}\n branch={\n branch\n ? { index: branch.index, count: branch.count, onSelect: (index) => props.onSwitchBranch(branch.parentId, index) }\n : undefined\n }\n disabled={busy}\n />\n ) : undefined;\n\n return (\n <Message\n message={message}\n streaming={streaming}\n avatar={props.avatar}\n name={props.name}\n locale={props.locale}\n images={props.images}\n showTimestamp={props.showTimestamp}\n showUsage={props.showUsage}\n renderPart={props.renderPart}\n onToolDecision={props.canDecide ? props.onToolDecision : undefined}\n onRetry={props.canRegenerate ? props.onRegenerate : undefined}\n editing={props.editing}\n onEditSubmit={(value) => props.onEditSubmit(message.id, value)}\n onEditCancel={props.onEditCancel}\n actions={actions}\n />\n );\n});\n\n// ---------------------------------------------------------------------------\n// ChatThread\n// ---------------------------------------------------------------------------\n\n/**\n * The whole chat: message list, composer, errors, suggestions and live\n * announcements, driven by props. Pair it with `useThread`:\n *\n * ```tsx\n * const thread = useThread({ onSend });\n * return <ChatThread {...thread.chatProps} suggestions={[\"Hello\"]} />;\n * ```\n *\n * It owns no conversation state: pass `messages` and `status` from anywhere.\n */\nexport function ChatThread({\n messages: threadMessages,\n status: statusProp,\n error = null,\n onSend,\n onStop,\n onRegenerate,\n onToolDecision,\n onEdit,\n branches,\n onSwitchBranch,\n onDismissError,\n onFeedback,\n feedback: feedbackProp,\n suggestions,\n followUps,\n renderPart,\n emptyState,\n header,\n disclaimer,\n avatars,\n names,\n showTimestamps = false,\n showUsage = false,\n images,\n announce = \"complete\",\n disabled = false,\n promptProps,\n locale,\n strings,\n conversationRef,\n className,\n ref,\n ...props\n}: ChatThreadProps) {\n return (\n <AiMessagesProvider messages={strings}>\n <ChatThreadInner\n {...props}\n ref={ref}\n className={className}\n messages={threadMessages}\n status={statusProp}\n error={error}\n onSend={onSend}\n onStop={onStop}\n onRegenerate={onRegenerate}\n onToolDecision={onToolDecision}\n onEdit={onEdit}\n branches={branches}\n onSwitchBranch={onSwitchBranch}\n onDismissError={onDismissError}\n onFeedback={onFeedback}\n feedback={feedbackProp}\n suggestions={suggestions}\n followUps={followUps}\n renderPart={renderPart}\n emptyState={emptyState}\n header={header}\n disclaimer={disclaimer}\n avatars={avatars}\n names={names}\n showTimestamps={showTimestamps}\n showUsage={showUsage}\n images={images}\n announce={announce}\n disabled={disabled}\n promptProps={promptProps}\n locale={locale}\n conversationRef={conversationRef}\n />\n </AiMessagesProvider>\n );\n}\n\ntype ChatThreadInnerProps = Omit<ChatThreadProps, \"strings\">;\n\n// The provider is above, so everything below reads the right strings from context.\nfunction ChatThreadInner({\n messages: threadMessages,\n status: statusProp,\n error,\n onSend,\n onStop,\n onRegenerate,\n onToolDecision,\n onEdit,\n branches,\n onSwitchBranch,\n onDismissError,\n onFeedback,\n feedback: feedbackProp,\n suggestions,\n followUps,\n renderPart,\n emptyState,\n header,\n disclaimer,\n avatars,\n names,\n showTimestamps = false,\n showUsage = false,\n images,\n announce = \"complete\",\n disabled = false,\n promptProps,\n locale,\n conversationRef,\n className,\n ref,\n ...props\n}: ChatThreadInnerProps) {\n const messages = useAiMessages();\n const last = threadMessages[threadMessages.length - 1];\n const status: ThreadStatus = statusProp ?? (last?.status === \"streaming\" ? \"streaming\" : \"idle\");\n const busy = status === \"submitted\" || status === \"streaming\";\n const [editingId, setEditingId] = useState<string | null>(null);\n const [ownFeedback, setOwnFeedback] = useState<Record<string, Feedback | null | undefined>>({});\n const feedbackMap = feedbackProp ?? ownFeedback;\n\n const pending = useMemo(() => threadPendingApprovals(threadMessages), [threadMessages]);\n const announcement = useAnnouncement({\n messages: threadMessages,\n busy,\n mode: announce,\n approvalsEnabled: onToolDecision !== undefined,\n });\n\n // Stable handlers, so memoized messages are not re-rendered by new closures.\n const handleToolDecision = useEventCallback((callId: string, decision: \"approve\" | \"deny\", reason?: string) =>\n onToolDecision?.(callId, decision, reason),\n );\n const handleRegenerate = useEventCallback(() => onRegenerate?.());\n const handleStartEdit = useEventCallback((id: string) => setEditingId(id));\n const handleEditSubmit = useEventCallback((id: string, text: string) => {\n setEditingId(null);\n onEdit?.(id, text);\n });\n const handleEditCancel = useEventCallback(() => setEditingId(null));\n const handleFeedback = useEventCallback((id: string, value: Feedback | null) => {\n if (feedbackProp === undefined) setOwnFeedback((current) => ({ ...current, [id]: value }));\n onFeedback?.(id, value);\n });\n const handleSwitchBranch = useEventCallback((parentId: string, index: number) => onSwitchBranch?.(parentId, index));\n\n const lastAssistantId = useMemo(() => {\n for (let index = threadMessages.length - 1; index >= 0; index -= 1) {\n const message = threadMessages[index];\n if (message?.role === \"assistant\") return message.id;\n }\n return undefined;\n }, [threadMessages]);\n\n // An error that is not already shown on the last reply gets its own banner.\n const errorOnMessage = last?.status === \"error\" && last.error !== undefined;\n const threadError = error ?? (status === \"error\" ? { message: \"\", kind: \"unknown\" as const } : null);\n const showThreadError = threadError !== null && !errorOnMessage;\n const lastUser = useMemo(() => {\n for (let index = threadMessages.length - 1; index >= 0; index -= 1) {\n const message = threadMessages[index];\n if (message?.role === \"user\") return message;\n }\n return undefined;\n }, [threadMessages]);\n\n const empty = threadMessages.length === 0 && status === \"idle\";\n const waitingForReply = status === \"submitted\" || (status === \"streaming\" && last?.role !== \"assistant\");\n const showFollowUps =\n followUps !== undefined && followUps.length > 0 && !busy && last?.role === \"assistant\" && pending.length === 0;\n\n const pickSuggestion = (prompt: string) => onSend(prompt);\n\n return (\n <section {...props} ref={ref} aria-label={props[\"aria-label\"] ?? messages.chat} data-kit=\"ai-chat-thread\" data-status={status} className={cx(className)}>\n {header}\n <Conversation handleRef={conversationRef}>\n {empty ? (\n (emptyState ?? (\n <EmptyThread>\n {suggestions && suggestions.length > 0 ? <Suggestions suggestions={suggestions} onSelect={pickSuggestion} disabled={disabled} /> : null}\n </EmptyThread>\n ))\n ) : (\n <div data-kit=\"ai-message-list\">\n {threadMessages.map((message) => {\n const role = message.role;\n const streaming = message.status === \"streaming\" && busy;\n const avatar = role === \"user\" ? avatars?.user : role === \"assistant\" ? avatars?.assistant : undefined;\n const name = role === \"user\" ? names?.user : role === \"assistant\" ? names?.assistant : undefined;\n return (\n <ThreadMessageItem\n key={message.id}\n message={message}\n streaming={streaming}\n busy={busy}\n isLastAssistant={message.id === lastAssistantId}\n branch={branches?.[message.id]}\n editing={editingId === message.id}\n feedback={feedbackMap[message.id] ?? null}\n canFeedback={onFeedback !== undefined}\n canEdit={onEdit !== undefined}\n canRegenerate={onRegenerate !== undefined}\n canDecide={onToolDecision !== undefined}\n avatar={avatar}\n name={name}\n locale={locale}\n images={images}\n showTimestamp={showTimestamps}\n showUsage={showUsage}\n renderPart={renderPart}\n onToolDecision={handleToolDecision}\n onRegenerate={handleRegenerate}\n onStartEdit={handleStartEdit}\n onEditSubmit={handleEditSubmit}\n onEditCancel={handleEditCancel}\n onFeedback={handleFeedback}\n onSwitchBranch={handleSwitchBranch}\n />\n );\n })}\n </div>\n )}\n {waitingForReply ? (\n <div data-kit=\"ai-pending\" aria-busy=\"true\">\n <StreamingIndicator label={messages.responding} />\n </div>\n ) : null}\n {showThreadError && threadError ? (\n <ErrorBanner\n error={threadError}\n showDetail={threadError.message !== \"\"}\n onRetry={onRegenerate && !empty ? handleRegenerate : undefined}\n onDismiss={onDismissError}\n onEdit={lastUser && onEdit ? () => setEditingId(lastUser.id) : undefined}\n />\n ) : null}\n {showFollowUps && followUps ? <Suggestions suggestions={followUps} onSelect={pickSuggestion} disabled={disabled} /> : null}\n </Conversation>\n\n <div data-kit=\"ai-chat-composer\">\n <PromptInput\n {...promptProps}\n status={status}\n onStop={onStop}\n disabled={disabled}\n onSubmit={(text, attachments) => onSend(text, attachments)}\n />\n {disclaimer === false ? null : (\n <p data-kit=\"ai-disclaimer\" dir=\"auto\">\n {disclaimer ?? messages.disclaimer}\n </p>\n )}\n </div>\n\n <VisuallyHidden role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {announcement}\n </VisuallyHidden>\n </section>\n );\n}\n","import { Button } from \"@x12i/ui\";\nimport { useImperativeHandle, type ComponentPropsWithRef, type ReactNode, type Ref } from \"react\";\nimport { cx } from \"./internal/cx\";\nimport { ArrowDownGlyph } from \"./internal/glyphs\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\nimport { useStickToBottom } from \"./use-stick-to-bottom\";\n\nexport interface ConversationHandle {\n /** Scrolls to the newest message and resumes following. */\n scrollToBottom: (behavior?: ScrollBehavior) => void;\n}\n\nexport interface ConversationProps extends Omit<ComponentPropsWithRef<\"div\">, \"children\"> {\n children?: ReactNode;\n /** Pixels from the end that still count as \"at the bottom\". Default 48. */\n stickThreshold?: number | undefined;\n /** Called when the user scrolls away from, or back to, the end. */\n onAtBottomChange?: ((atBottom: boolean) => void) | undefined;\n /** Accessible name of the log. Defaults to `messages.conversation`. */\n label?: string | undefined;\n /** Imperative handle: `scrollToBottom()`. */\n handleRef?: Ref<ConversationHandle> | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\n/**\n * The scrolling list of messages.\n *\n * - It follows new content (a streaming reply) while you are at the bottom,\n * and lets go the moment you scroll up. A \"Jump to latest\" button appears\n * while you are away from the end.\n * - The scroller is `role=\"log\"` with polite, additions-only live updates, and is\n * focusable so the keyboard can scroll it. A streaming message turns its\n * own text off (`aria-live=\"off\"`), so a screen reader hears messages, not tokens.\n */\nexport function Conversation({\n children,\n stickThreshold,\n onAtBottomChange,\n label,\n handleRef,\n messages: override,\n className,\n ref,\n ...props\n}: ConversationProps) {\n const messages = useAiMessages(override);\n const { scrollerRef, contentRef, atBottom, scrollToBottom } = useStickToBottom({\n threshold: stickThreshold,\n onAtBottomChange,\n });\n\n useImperativeHandle(handleRef, () => ({ scrollToBottom }), [scrollToBottom]);\n\n return (\n <div {...props} ref={ref} data-kit=\"ai-conversation\" className={cx(className)}>\n <div\n ref={scrollerRef}\n data-kit=\"ai-conversation-scroller\"\n role=\"log\"\n aria-live=\"polite\"\n aria-relevant=\"additions\"\n aria-label={label ?? messages.conversation}\n tabIndex={0}\n >\n <div ref={contentRef} data-kit=\"ai-conversation-content\">\n {children}\n </div>\n </div>\n {atBottom ? null : (\n <div data-kit=\"ai-jump-to-latest\">\n <Button\n variant=\"outline\"\n tone=\"neutral\"\n size=\"sm\"\n onClick={() => {\n scrollToBottom(\"smooth\");\n // The button disappears when the view is at the bottom; keep keyboard focus in the conversation.\n scrollerRef.current?.focus({ preventScroll: true });\n }}\n >\n <ArrowDownGlyph size=\"sm\" />\n {messages.jumpToLatest}\n </Button>\n </div>\n )}\n </div>\n );\n}\n","/** Joins class names, skipping falsy values. */\nexport function cx(...values: Array<string | false | null | undefined>): string | undefined {\n const joined = values.filter(Boolean).join(\" \");\n return joined === \"\" ? undefined : joined;\n}\n","import type { ComponentPropsWithoutRef, ReactNode } from \"react\";\n\n/**\n * Small inline icons for the actions `@x12i/icons` does not have yet (send,\n * stop, attach, thumbs, refresh). They follow the same rules as the kit's\n * `Icon`: decorative, `currentColor`, stroke width from the token (set in\n * CSS), size from the icon size tokens (set in CSS through `data-size`).\n */\n\ntype GlyphSize = \"xs\" | \"sm\" | \"md\" | \"lg\";\n\ninterface GlyphProps extends Omit<ComponentPropsWithoutRef<\"svg\">, \"children\"> {\n size?: GlyphSize;\n}\n\nfunction Glyph({ size = \"sm\", children, ...props }: GlyphProps & { children: ReactNode }) {\n return (\n <svg\n data-kit=\"ai-glyph\"\n data-size={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n {...props}\n >\n {children}\n </svg>\n );\n}\n\nexport function SendGlyph(props: GlyphProps) {\n return (\n <Glyph {...props}>\n <path d=\"M12 19V5\" />\n <path d=\"m5 12 7-7 7 7\" />\n </Glyph>\n );\n}\n\nexport function ArrowDownGlyph(props: GlyphProps) {\n return (\n <Glyph {...props}>\n <path d=\"M12 5v14\" />\n <path d=\"m19 12-7 7-7-7\" />\n </Glyph>\n );\n}\n\nexport function StopGlyph(props: GlyphProps) {\n return (\n <Glyph {...props}>\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" fill=\"currentColor\" stroke=\"none\" />\n </Glyph>\n );\n}\n\nexport function PaperclipGlyph(props: GlyphProps) {\n return (\n <Glyph {...props}>\n <path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </Glyph>\n );\n}\n\nexport function ThumbsUpGlyph({ filled, ...props }: GlyphProps & { filled?: boolean }) {\n return (\n <Glyph {...props} fill={filled ? \"currentColor\" : \"none\"}>\n <path d=\"M7 10v12\" />\n <path d=\"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z\" />\n </Glyph>\n );\n}\n\nexport function ThumbsDownGlyph({ filled, ...props }: GlyphProps & { filled?: boolean }) {\n return (\n <Glyph {...props} fill={filled ? \"currentColor\" : \"none\"}>\n <path d=\"M17 14V2\" />\n <path d=\"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z\" />\n </Glyph>\n );\n}\n\nexport function RefreshGlyph(props: GlyphProps) {\n return (\n <Glyph {...props}>\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n </Glyph>\n );\n}\n\nexport function SparklesGlyph(props: GlyphProps) {\n return (\n <Glyph {...props}>\n <path d=\"M12 3l1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9L12 3z\" />\n <path d=\"M19 15l.8 2.2L22 18l-2.2.8L19 21l-.8-2.2L16 18l2.2-.8L19 15z\" />\n </Glyph>\n );\n}\n\nexport function WrenchGlyph(props: GlyphProps) {\n return (\n <Glyph {...props}>\n <path d=\"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z\" />\n </Glyph>\n );\n}\n\nexport function FileGlyph(props: GlyphProps) {\n return (\n <Glyph {...props}>\n <path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\" />\n <path d=\"M14 2v6h6\" />\n </Glyph>\n );\n}\n\nexport function BranchPrevGlyph(props: GlyphProps) {\n return (\n <Glyph {...props}>\n <path d=\"m15 18-6-6 6-6\" />\n </Glyph>\n );\n}\n\nexport function BranchNextGlyph(props: GlyphProps) {\n return (\n <Glyph {...props}>\n <path d=\"m9 18 6-6-6-6\" />\n </Glyph>\n );\n}\n","import { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport { defaultMessages, mergeMessages, type AiMessages, type AiMessagesOverride } from \"./messages\";\n\nconst MessagesContext = createContext<AiMessages>(defaultMessages);\n\nexport interface AiMessagesProviderProps {\n /** A partial catalog, merged over `defaultMessages` (or over a parent provider). */\n messages?: AiMessagesOverride;\n children?: ReactNode;\n}\n\n/**\n * Sets the strings for every chat component below it, so you translate once\n * instead of passing `messages` to each component. A component's own\n * `messages` prop still wins.\n */\nexport function AiMessagesProvider({ messages, children }: AiMessagesProviderProps) {\n const parent = useContext(MessagesContext);\n const value = useMemo(() => mergeMessages(parent, messages), [parent, messages]);\n return <MessagesContext.Provider value={value}>{children}</MessagesContext.Provider>;\n}\n\n/**\n * The strings a component should use: the nearest provider's catalog (or the\n * English default) with the component's own override on top.\n */\nexport function useAiMessages(override?: AiMessagesOverride): AiMessages {\n const context = useContext(MessagesContext);\n return useMemo(() => (override ? mergeMessages(context, override) : context), [context, override]);\n}\n","import type { ErrorKind, MessageRole, ToolState } from \"../types\";\n\n/**\n * Every word the chat components show. The kit's components contain no\n * user-facing text of their own: they read it from this catalog. English ships\n * as `defaultMessages`. To translate, pass a partial override as the\n * `messages` prop of a component (`strings` on `ChatThread`), or provide one\n * for a whole subtree with `AiMessagesProvider`.\n *\n * Values that are functions take the dynamic parts (a tool name, a count, a\n * duration) so a translation can put them anywhere in the sentence. Counts\n * should use `Intl.PluralRules` in your translation when the language needs it.\n * Values that are data, such as a tool name or a source title, are shown as\n * they are.\n */\nexport interface AiMessages {\n // ChatThread and Conversation\n /** Accessible name of the whole chat region. */\n chat: string;\n /** Accessible name of the scrolling message log. */\n conversation: string;\n jumpToLatest: string;\n emptyTitle: string;\n emptyDescription: string;\n /** Shown under the prompt: never hide that content is AI-generated. */\n disclaimer: string;\n /** Accessible name of the follow-up suggestions list. */\n suggestions: string;\n\n // Message\n roles: Record<MessageRole, string>;\n /** The visible badge on assistant messages. */\n aiGenerated: string;\n /** The badge's accessible name. */\n aiGeneratedLabel: string;\n edited: string;\n stopped: string;\n failed: string;\n /** Visually hidden while a message is being written. */\n responding: string;\n /** For example `1.2K tokens`. */\n tokens: (count: string) => string;\n /** `Message from {role}` for the message's accessible name. */\n messageFrom: (role: string) => string;\n\n // PromptInput\n promptLabel: string;\n promptPlaceholder: string;\n send: string;\n stop: string;\n attach: string;\n attachments: string;\n removeAttachment: (name: string) => string;\n attachmentUploading: string;\n attachmentFailed: string;\n dropFiles: string;\n /** For example `12 / 500`. */\n characterCount: (count: number, max: number) => string;\n characterLimitReached: string;\n commands: string;\n commandsAvailable: (count: number) => string;\n\n // Reasoning\n reasoning: string;\n thinking: string;\n thought: string;\n /** `duration` is already formatted, for example `4s`. */\n thoughtFor: (duration: string) => string;\n\n // ToolCall\n toolStates: Record<ToolState, string>;\n toolCall: (name: string) => string;\n toolInput: string;\n toolOutput: string;\n toolError: string;\n /** Shown when the user stopped the run before the tool finished. */\n toolAborted: string;\n noInput: string;\n noOutput: string;\n\n // ApprovalPrompt\n approvalTitle: (toolName: string) => string;\n approvalDescription: string;\n approvalAction: string;\n approve: string;\n deny: string;\n approveLabel: (toolName: string) => string;\n denyLabel: (toolName: string) => string;\n reasonLabel: string;\n reasonPlaceholder: string;\n\n // Sources and citations\n sources: string;\n sourcesCount: (count: number) => string;\n /** The accessible name of an inline citation chip. */\n citationLabel: (number: number, title: string) => string;\n opensInNewTab: string;\n noLink: string;\n\n // MessageActions\n actions: string;\n copy: string;\n copied: string;\n copyFailed: string;\n regenerate: string;\n edit: string;\n goodResponse: string;\n badResponse: string;\n /** `Version 2 of 3`. */\n versionLabel: (index: number, count: number) => string;\n previousVersion: string;\n nextVersion: string;\n saveEdit: string;\n cancelEdit: string;\n editLabel: string;\n\n // Attachments\n attachmentsList: string;\n download: (name: string) => string;\n\n // StreamingIndicator\n thinkingIndicator: string;\n\n // ErrorBanner\n errorKinds: Record<ErrorKind, { title: string; description: string }>;\n retry: string;\n dismiss: string;\n editInstead: string;\n\n // Live announcements (spoken, not shown)\n announceReply: (text: string) => string;\n announceStopped: string;\n announceApproval: (toolName: string) => string;\n\n // Markdown\n copyCode: string;\n codeCopied: string;\n /** Accessible name of a code block. `language` is empty when unknown. */\n codeBlock: (language: string) => string;\n plainText: string;\n table: string;\n taskDone: string;\n taskTodo: string;\n footnotes: string;\n footnoteBack: string;\n /** Shown instead of an image that is blocked. */\n imageBlocked: string;\n\n // JSON viewer\n copyJson: string;\n showMore: (hidden: number) => string;\n showLess: string;\n}\n\n/** A partial catalog. The nested records may be partial too. */\nexport interface AiMessagesOverride\n extends Partial<Omit<AiMessages, \"roles\" | \"toolStates\" | \"errorKinds\">> {\n roles?: Partial<AiMessages[\"roles\"]>;\n toolStates?: Partial<AiMessages[\"toolStates\"]>;\n errorKinds?: { [K in ErrorKind]?: Partial<AiMessages[\"errorKinds\"][K]> };\n}\n\nexport const defaultMessages: AiMessages = {\n chat: \"Chat\",\n conversation: \"Conversation\",\n jumpToLatest: \"Jump to latest\",\n emptyTitle: \"How can I help?\",\n emptyDescription: \"Ask a question or pick a suggestion to start.\",\n disclaimer: \"AI-generated content can be wrong. Check important information.\",\n suggestions: \"Suggested follow-ups\",\n\n roles: { user: \"You\", assistant: \"Assistant\", system: \"System\", tool: \"Tool\" },\n aiGenerated: \"AI\",\n aiGeneratedLabel: \"AI-generated\",\n edited: \"Edited\",\n stopped: \"Response stopped\",\n failed: \"Response failed\",\n responding: \"Responding\",\n tokens: (count) => `${count} tokens`,\n messageFrom: (role) => `Message from ${role}`,\n\n promptLabel: \"Message\",\n promptPlaceholder: \"Type a message\",\n send: \"Send message\",\n stop: \"Stop generating\",\n attach: \"Attach files\",\n attachments: \"Attachments\",\n removeAttachment: (name) => `Remove ${name}`,\n attachmentUploading: \"Uploading\",\n attachmentFailed: \"Upload failed\",\n dropFiles: \"Drop files to attach\",\n characterCount: (count, max) => `${count} / ${max}`,\n characterLimitReached: \"Character limit reached\",\n commands: \"Commands\",\n commandsAvailable: (count) => `${count} commands available`,\n\n reasoning: \"Reasoning\",\n thinking: \"Thinking…\",\n thought: \"Thought\",\n thoughtFor: (duration) => `Thought for ${duration}`,\n\n toolStates: {\n queued: \"Queued\",\n running: \"Running\",\n \"needs-approval\": \"Needs approval\",\n approved: \"Approved\",\n denied: \"Denied\",\n succeeded: \"Done\",\n failed: \"Failed\",\n },\n toolCall: (name) => `Tool call: ${name}`,\n toolInput: \"Input\",\n toolOutput: \"Output\",\n toolError: \"Error\",\n toolAborted: \"Stopped before it finished\",\n noInput: \"No input\",\n noOutput: \"No output\",\n\n approvalTitle: (toolName) => `Approve “${toolName}”?`,\n approvalDescription: \"The assistant wants to run this action. Review it, then approve or deny.\",\n approvalAction: \"Action\",\n approve: \"Approve\",\n deny: \"Deny\",\n approveLabel: (toolName) => `Approve ${toolName}`,\n denyLabel: (toolName) => `Deny ${toolName}`,\n reasonLabel: \"Reason (optional)\",\n reasonPlaceholder: \"Why?\",\n\n sources: \"Sources\",\n sourcesCount: (count) => (count === 1 ? \"1 source\" : `${count} sources`),\n citationLabel: (number, title) => `Source ${number}: ${title}`,\n opensInNewTab: \"opens in a new tab\",\n noLink: \"No link available\",\n\n actions: \"Message actions\",\n copy: \"Copy\",\n copied: \"Copied\",\n copyFailed: \"Copy failed\",\n regenerate: \"Regenerate response\",\n edit: \"Edit message\",\n goodResponse: \"Good response\",\n badResponse: \"Bad response\",\n versionLabel: (index, count) => `Version ${index} of ${count}`,\n previousVersion: \"Previous version\",\n nextVersion: \"Next version\",\n saveEdit: \"Save and resend\",\n cancelEdit: \"Cancel\",\n editLabel: \"Edit your message\",\n\n attachmentsList: \"Attachments\",\n download: (name) => `Download ${name}`,\n\n thinkingIndicator: \"Assistant is thinking\",\n\n errorKinds: {\n network: {\n title: \"Connection problem\",\n description: \"The request did not complete. Check your connection and try again.\",\n },\n \"rate-limit\": {\n title: \"Too many requests\",\n description: \"The service asked us to slow down. Wait a moment, then try again.\",\n },\n moderation: {\n title: \"Response blocked\",\n description: \"The service declined to answer this message. Edit it and try again.\",\n },\n auth: {\n title: \"Not signed in\",\n description: \"The service rejected the credentials. Sign in again, then retry.\",\n },\n unknown: {\n title: \"Something went wrong\",\n description: \"The response could not be completed.\",\n },\n },\n retry: \"Retry\",\n dismiss: \"Dismiss\",\n editInstead: \"Edit message\",\n\n announceReply: (text) => `Assistant replied: ${text}`,\n announceStopped: \"Response stopped\",\n announceApproval: (toolName) => `Approval needed for ${toolName}`,\n\n copyCode: \"Copy code\",\n codeCopied: \"Code copied\",\n codeBlock: (language) => (language === \"\" ? \"Code\" : `Code, ${language}`),\n plainText: \"Text\",\n table: \"Table\",\n taskDone: \"Completed\",\n taskTodo: \"Not completed\",\n footnotes: \"Footnotes\",\n footnoteBack: \"Back to reference\",\n imageBlocked: \"Image not shown\",\n\n copyJson: \"Copy\",\n showMore: (hidden) => `Show ${hidden} more characters`,\n showLess: \"Show less\",\n};\n\ntype RecordKey = \"roles\" | \"toolStates\" | \"errorKinds\";\n\n/**\n * Merges catalogs, later ones winning. The record-valued entries (`roles`,\n * `toolStates`, `errorKinds`) merge key by key, so you can translate a single\n * tool state or error title.\n */\nexport function mergeMessages(\n base: AiMessages,\n ...overrides: Array<AiMessagesOverride | undefined>\n): AiMessages {\n let result: AiMessages = base;\n for (const override of overrides) {\n if (!override) continue;\n const next: Record<string, unknown> = { ...result };\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) continue;\n if (key === \"roles\" || key === \"toolStates\") {\n next[key] = { ...(result[key as RecordKey] as object), ...(value as object) };\n } else if (key === \"errorKinds\") {\n const merged: Record<string, unknown> = { ...result.errorKinds };\n for (const [kind, entry] of Object.entries(value as Record<string, object>)) {\n merged[kind] = { ...(result.errorKinds[kind as ErrorKind] as object), ...entry };\n }\n next[key] = merged;\n } else {\n next[key] = value;\n }\n }\n result = next as unknown as AiMessages;\n }\n return result;\n}\n","import { useCallback, useEffect, useLayoutEffect, useRef, useState, type RefObject } from \"react\";\nimport { useEventCallback, usePrefersReducedMotion } from \"./internal/hooks\";\n\nexport interface UseStickToBottomOptions {\n /** How close to the end (in pixels) still counts as \"at the bottom\". Default 48. */\n threshold?: number | undefined;\n /** Called when the user moves away from, or returns to, the bottom. */\n onAtBottomChange?: ((atBottom: boolean) => void) | undefined;\n}\n\nexport interface StickToBottom {\n /** Put on the scrolling element. */\n scrollerRef: RefObject<HTMLDivElement | null>;\n /** Put on the element that holds the content, so growth is noticed. */\n contentRef: RefObject<HTMLDivElement | null>;\n /** True while the view is at (or near) the end, or following it. */\n atBottom: boolean;\n /** Scrolls to the end and resumes following. */\n scrollToBottom: (behavior?: ScrollBehavior) => void;\n}\n\n/** Time during which a scroll event is taken to be ours, not the user's. */\nconst INSTANT_SETTLE_MS = 120;\nconst SMOOTH_SETTLE_MS = 800;\n\n/**\n * Keeps a scroller pinned to its end while content grows (a streaming reply),\n * and stops as soon as the user scrolls up, so they can read in peace. It\n * resumes when they scroll back to the bottom, or call `scrollToBottom`.\n *\n * A scroll the hook caused itself is told apart from the user's, so a long\n * smooth scroll or a growing reply does not make it let go by mistake.\n */\nexport function useStickToBottom({ threshold = 48, onAtBottomChange }: UseStickToBottomOptions = {}): StickToBottom {\n const scrollerRef = useRef<HTMLDivElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n const following = useRef(true);\n const ours = useRef(false);\n const settleTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const lastAtBottom = useRef(true);\n const [atBottom, setAtBottomState] = useState(true);\n const reducedMotion = usePrefersReducedMotion();\n const notify = useEventCallback((value: boolean) => onAtBottomChange?.(value));\n\n const setAtBottom = useCallback(\n (value: boolean) => {\n if (lastAtBottom.current === value) return;\n lastAtBottom.current = value;\n setAtBottomState(value);\n notify(value);\n },\n [notify],\n );\n\n const isNearBottom = useCallback(\n (element: HTMLElement) => element.scrollHeight - element.scrollTop - element.clientHeight <= threshold,\n [threshold],\n );\n\n const scrollToBottom = useCallback(\n (behavior: ScrollBehavior = \"auto\") => {\n const element = scrollerRef.current;\n if (!element) return;\n const effective: ScrollBehavior = reducedMotion ? \"auto\" : behavior;\n following.current = true;\n ours.current = true;\n clearTimeout(settleTimer.current);\n settleTimer.current = setTimeout(\n () => {\n ours.current = false;\n },\n effective === \"smooth\" ? SMOOTH_SETTLE_MS : INSTANT_SETTLE_MS,\n );\n element.scrollTo({ top: element.scrollHeight, behavior: effective });\n setAtBottom(true);\n },\n [reducedMotion, setAtBottom],\n );\n\n // Start at the end.\n useLayoutEffect(() => {\n scrollToBottom(\"auto\");\n // Only on mount.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n const scroller = scrollerRef.current;\n if (!scroller) return;\n\n const release = () => {\n ours.current = false;\n clearTimeout(settleTimer.current);\n };\n\n const handleScroll = () => {\n const near = isNearBottom(scroller);\n if (ours.current) {\n // Our own scroll: only the arrival at the end matters.\n if (near) {\n ours.current = false;\n clearTimeout(settleTimer.current);\n following.current = true;\n setAtBottom(true);\n }\n return;\n }\n following.current = near;\n setAtBottom(near);\n };\n\n // Wheel up, or a key that scrolls up, is a clear sign the user wants to read: let go at once.\n const handleWheel = (event: WheelEvent) => {\n if (event.deltaY < 0) {\n release();\n if (scroller.scrollHeight > scroller.clientHeight) following.current = false;\n }\n };\n const handleKey = (event: KeyboardEvent) => {\n if (event.target !== scroller) return;\n if (event.key === \"PageUp\" || event.key === \"ArrowUp\" || event.key === \"Home\") {\n release();\n if (scroller.scrollHeight > scroller.clientHeight) following.current = false;\n }\n };\n\n scroller.addEventListener(\"scroll\", handleScroll, { passive: true });\n scroller.addEventListener(\"wheel\", handleWheel, { passive: true });\n scroller.addEventListener(\"touchmove\", release, { passive: true });\n scroller.addEventListener(\"keydown\", handleKey);\n\n let observer: ResizeObserver | undefined;\n if (typeof ResizeObserver !== \"undefined\") {\n observer = new ResizeObserver(() => {\n if (following.current) scrollToBottom(\"auto\");\n });\n observer.observe(scroller);\n if (contentRef.current) observer.observe(contentRef.current);\n }\n\n return () => {\n scroller.removeEventListener(\"scroll\", handleScroll);\n scroller.removeEventListener(\"wheel\", handleWheel);\n scroller.removeEventListener(\"touchmove\", release);\n scroller.removeEventListener(\"keydown\", handleKey);\n observer?.disconnect();\n clearTimeout(settleTimer.current);\n };\n }, [isNearBottom, scrollToBottom, setAtBottom]);\n\n return { scrollerRef, contentRef, atBottom, scrollToBottom };\n}\n","import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n useSyncExternalStore,\n type RefObject,\n} from \"react\";\n\n/** A stable function that always calls the latest `fn`, so it can be a dependency without churn. */\nexport function useEventCallback<A extends unknown[], R>(fn: (...args: A) => R): (...args: A) => R {\n const ref = useRef(fn);\n useLayoutEffect(() => {\n ref.current = fn;\n });\n return useCallback((...args: A) => ref.current(...args), []);\n}\n\n/** Controlled or uncontrolled state: pass `value` to control it. */\nexport function useControllableState<T>(options: {\n value: T | undefined;\n defaultValue: T;\n onChange?: ((value: T) => void) | undefined;\n}): [T, (next: T) => void] {\n const { value, defaultValue, onChange } = options;\n const [inner, setInner] = useState<T>(defaultValue);\n const controlled = value !== undefined;\n const current = controlled ? value : inner;\n const notify = useEventCallback((next: T) => onChange?.(next));\n\n const set = useCallback(\n (next: T) => {\n if (!controlled) setInner(next);\n notify(next);\n },\n [controlled, notify],\n );\n return [current, set];\n}\n\nconst REDUCED_MOTION_QUERY = \"(prefers-reduced-motion: reduce)\";\n\nfunction subscribeReducedMotion(onChange: () => void): () => void {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return () => {};\n const query = window.matchMedia(REDUCED_MOTION_QUERY);\n query.addEventListener?.(\"change\", onChange);\n return () => query.removeEventListener?.(\"change\", onChange);\n}\n\nfunction getReducedMotion(): boolean {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return false;\n return window.matchMedia(REDUCED_MOTION_QUERY).matches;\n}\n\n/** True when the user asked the system for less motion. False on the server. */\nexport function usePrefersReducedMotion(): boolean {\n return useSyncExternalStore(subscribeReducedMotion, getReducedMotion, () => false);\n}\n\n/**\n * True while an element's content is wider than its box, so a scroll region\n * can become focusable. Pass `content` (any value that changes when the content\n * does) to measure again when text streams in without the box changing size.\n */\nexport function useHorizontalOverflow(ref: RefObject<HTMLElement | null>, content?: unknown): boolean {\n const [overflowing, setOverflowing] = useState(false);\n\n useLayoutEffect(() => {\n const element = ref.current;\n if (!element) return;\n const measure = () => setOverflowing(element.scrollWidth > element.clientWidth);\n measure();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n return () => observer.disconnect();\n }, [ref, content]);\n\n return overflowing;\n}\n\n/** State that falls back to `resting` after `delay` ms, for transient states such as \"Copied\". The timer is cleared on unmount. */\nexport function useTransientState<T>(resting: T, delay = 2000): [T, (value: T) => void] {\n const [value, setValue] = useState<T>(resting);\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n const set = useCallback(\n (next: T) => {\n setValue(next);\n clearTimeout(timer.current);\n if (next !== resting) {\n timer.current = setTimeout(() => setValue(resting), delay);\n }\n },\n [resting, delay],\n );\n\n useEffect(() => () => clearTimeout(timer.current), []);\n return [value, set];\n}\n","import type { ComponentPropsWithRef, ReactNode } from \"react\";\nimport { cx } from \"./internal/cx\";\nimport { SparklesGlyph } from \"./internal/glyphs\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\n\nexport interface EmptyThreadProps extends Omit<ComponentPropsWithRef<\"div\">, \"title\"> {\n /** Defaults to `messages.emptyTitle`. */\n title?: ReactNode;\n /** Defaults to `messages.emptyDescription`. */\n description?: ReactNode;\n /** An icon or logo. Defaults to a sparkles glyph. */\n icon?: ReactNode;\n /** Usually `Suggestions`. */\n children?: ReactNode;\n messages?: AiMessagesOverride | undefined;\n}\n\n/** What an empty conversation shows: a title, a line of help and, as children, starter suggestions. */\nexport function EmptyThread({ title, description, icon, children, messages: override, className, ref, ...props }: EmptyThreadProps) {\n const messages = useAiMessages(override);\n return (\n <div {...props} ref={ref} data-kit=\"ai-empty-thread\" className={cx(className)}>\n <span data-kit=\"ai-empty-icon\" aria-hidden=\"true\">\n {icon ?? <SparklesGlyph size=\"lg\" />}\n </span>\n <p data-kit=\"ai-empty-title\" dir=\"auto\">\n {title ?? messages.emptyTitle}\n </p>\n <p data-kit=\"ai-empty-description\" dir=\"auto\">\n {description ?? messages.emptyDescription}\n </p>\n {children}\n </div>\n );\n}\n","import { Icon } from \"@x12i/icons\";\nimport { Button, IconButton } from \"@x12i/ui\";\nimport type { ComponentPropsWithRef } from \"react\";\nimport type { ThreadError } from \"../types\";\nimport { cx } from \"./internal/cx\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\n\nexport interface ErrorBannerProps extends Omit<ComponentPropsWithRef<\"div\">, \"children\"> {\n error: ThreadError;\n /** Shows a retry button, unless the error says it is not retryable. */\n onRetry?: (() => void) | undefined;\n /** Shows a dismiss button. */\n onDismiss?: (() => void) | undefined;\n /** For a moderation error: lets the user go back and rephrase. */\n onEdit?: (() => void) | undefined;\n /** Show the provider's own message under the explanation. Default true. */\n showDetail?: boolean | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\n/**\n * Explains a failed reply in plain words that depend on the kind of failure\n * (network, rate limit, moderation, auth, unknown), with a retry where\n * retrying can help. It is `role=\"alert\"`, so it is announced when it appears.\n */\nexport function ErrorBanner({\n error,\n onRetry,\n onDismiss,\n onEdit,\n showDetail = true,\n messages: override,\n className,\n ref,\n ...props\n}: ErrorBannerProps) {\n const messages = useAiMessages(override);\n const kind = error.kind ?? \"unknown\";\n const copy = messages.errorKinds[kind];\n const canRetry = onRetry !== undefined && error.retryable !== false;\n const canEdit = onEdit !== undefined && kind === \"moderation\";\n\n return (\n <div {...props} ref={ref} role=\"alert\" data-kit=\"ai-error-banner\" data-kind={kind} className={cx(className)}>\n <span data-kit=\"ai-error-icon\">\n <Icon name=\"alert-circle\" size={20} />\n </span>\n <div data-kit=\"ai-error-body\">\n <p data-kit=\"ai-error-title\">{copy.title}</p>\n <p data-kit=\"ai-error-description\">{copy.description}</p>\n {showDetail && error.message !== \"\" ? (\n <p data-kit=\"ai-error-detail\" dir=\"auto\">\n {error.message}\n </p>\n ) : null}\n {canRetry || canEdit ? (\n <div data-kit=\"ai-error-actions\">\n {canRetry ? (\n <Button variant=\"outline\" tone=\"neutral\" size=\"sm\" onClick={onRetry}>\n {messages.retry}\n </Button>\n ) : null}\n {canEdit ? (\n <Button variant=\"outline\" tone=\"neutral\" size=\"sm\" onClick={onEdit}>\n {messages.editInstead}\n </Button>\n ) : null}\n </div>\n ) : null}\n </div>\n {onDismiss ? (\n <IconButton variant=\"ghost\" tone=\"neutral\" size=\"sm\" label={messages.dismiss} onClick={onDismiss}>\n <Icon name=\"close\" size={16} />\n </IconButton>\n ) : null}\n </div>\n );\n}\n","import { Badge, Button, VisuallyHidden } from \"@x12i/ui\";\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithRef,\n type KeyboardEvent,\n type ReactNode,\n} from \"react\";\nimport { formatTokenCount, totalTokens } from \"../format\";\nimport { messageText } from \"../messages\";\nimport type {\n DataPart,\n FilePart,\n Message as ThreadMessage,\n MessagePart,\n ReasoningPart,\n SourcePart,\n TextPart,\n ToolPart,\n} from \"../types\";\nimport { Attachments } from \"./attachments\";\nimport { ErrorBanner } from \"./error-banner\";\nimport { cx } from \"./internal/cx\";\nimport { JsonView } from \"./internal/json-view\";\nimport { useAutosize } from \"./internal/use-autosize\";\nimport { Markdown } from \"./markdown\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\nimport { Reasoning } from \"./reasoning\";\nimport { Sources, SourcesProvider } from \"./sources\";\nimport { StreamingIndicator } from \"./streaming-indicator\";\nimport { ToolCall } from \"./tool-call\";\n\nexport interface PartRenderContext {\n message: ThreadMessage;\n /** The part's position in `message.parts` (the first one, for grouped parts). */\n index: number;\n /** True while the message is still being written. */\n streaming: boolean;\n /** Renders the built-in view, so a custom renderer can wrap it. */\n defaultRender: () => ReactNode;\n}\n\n/**\n * Renders one part (or, for `sources` and `files`, all of them at once).\n * Return `undefined` to use the built-in view and `null` to show nothing.\n */\nexport type PartRenderer<P> = (part: P, context: PartRenderContext) => ReactNode | undefined;\n\n/**\n * Overrides how parts render. Keys: `text`, `reasoning`, `tool`, `sources`,\n * `files`, `data` (every data part) and `data:<kind>` for one kind, such as\n * `data:chart`. A `data:<kind>` renderer wins over `data`.\n */\nexport interface PartRenderers {\n text?: PartRenderer<TextPart>;\n reasoning?: PartRenderer<ReasoningPart>;\n tool?: PartRenderer<ToolPart>;\n sources?: PartRenderer<SourcePart[]>;\n files?: PartRenderer<FilePart[]>;\n data?: PartRenderer<DataPart>;\n [key: `data:${string}`]: PartRenderer<DataPart> | undefined;\n}\n\nexport interface MessageProps extends Omit<ComponentPropsWithRef<\"article\">, \"children\"> {\n message: ThreadMessage;\n /** Defaults to `message.status === \"streaming\"`. */\n streaming?: boolean | undefined;\n /** A decorative avatar. Give it `aria-hidden` if it has no text alternative. */\n avatar?: ReactNode;\n /** Display name. Defaults to the role's name from `messages.roles`. */\n name?: string | undefined;\n /** Show `createdAt` as a time. Default false. */\n showTimestamp?: boolean | undefined;\n /** Formats `createdAt`. Defaults to a short localized time. */\n formatTimestamp?: ((iso: string, locale: string | undefined) => string) | undefined;\n /** Show the token count of a finished reply. Default false. */\n showUsage?: boolean | undefined;\n locale?: string | undefined;\n renderPart?: PartRenderers | undefined;\n /** Called when the user decides on a tool call that needs approval. */\n onToolDecision?: ((callId: string, decision: \"approve\" | \"deny\", reason?: string) => void) | undefined;\n /** Retry button of the error banner, for a failed reply. */\n onRetry?: (() => void) | undefined;\n /** Edit mode for a user message: shows a text box with Save and Cancel. */\n editing?: boolean | undefined;\n onEditSubmit?: ((text: string) => void) | undefined;\n onEditCancel?: (() => void) | undefined;\n /** Rendered under the content, usually `MessageActions`. */\n actions?: ReactNode;\n /** Passed to `Markdown`: how images in replies are shown. */\n images?: \"inline\" | \"link\" | \"none\" | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\nfunction defaultTimestamp(iso: string, locale: string | undefined): string {\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) return iso;\n return new Intl.DateTimeFormat(locale, { timeStyle: \"short\" }).format(date);\n}\n\ninterface MessageEditorProps {\n initialText: string;\n onSubmit: (text: string) => void;\n onCancel: () => void;\n messages?: AiMessagesOverride | undefined;\n}\n\n/** Inline editor for a user message. Escape cancels, Ctrl or Cmd+Enter saves, and focus returns to where it was. */\nfunction MessageEditor({ initialText, onSubmit, onCancel, messages: override }: MessageEditorProps) {\n const messages = useAiMessages(override);\n const [text, setText] = useState(initialText);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n useAutosize(textareaRef, text);\n\n useEffect(() => {\n const previous = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n const textarea = textareaRef.current;\n textarea?.focus();\n textarea?.setSelectionRange(textarea.value.length, textarea.value.length);\n return () => {\n if (previous?.isConnected) previous.focus();\n };\n }, []);\n\n const save = () => {\n const next = text.trim();\n if (next !== \"\") onSubmit(next);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.nativeEvent.isComposing || event.keyCode === 229) return;\n if (event.key === \"Escape\") {\n event.preventDefault();\n onCancel();\n } else if (event.key === \"Enter\" && (event.ctrlKey || event.metaKey)) {\n event.preventDefault();\n save();\n }\n };\n\n return (\n <div data-kit=\"ai-message-editor\">\n <textarea\n ref={textareaRef}\n dir=\"auto\"\n rows={1}\n value={text}\n aria-label={messages.editLabel}\n onChange={(event) => setText(event.target.value)}\n onKeyDown={handleKeyDown}\n />\n <div data-kit=\"ai-message-editor-actions\">\n <Button variant=\"solid\" tone=\"accent\" size=\"sm\" disabled={text.trim() === \"\"} onClick={save}>\n {messages.saveEdit}\n </Button>\n <Button variant=\"ghost\" tone=\"neutral\" size=\"sm\" onClick={onCancel}>\n {messages.cancelEdit}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * One message: author, an \"AI\" label on assistant messages, an optional\n * time, and its parts.\n *\n * - Assistant text is rendered as safe Markdown; user and system text stays plain.\n * - Source parts become the numbered source list; `[1]` in the text links to it.\n * - While streaming, the content is `aria-live=\"off\"` and the article is\n * `aria-busy`, so assistive technology reads the finished reply once.\n * - `renderPart` replaces any part's view, for example to draw a chart for a `data:chart` part.\n */\nexport function Message({\n message,\n streaming: streamingProp,\n avatar,\n name,\n showTimestamp = false,\n formatTimestamp = defaultTimestamp,\n showUsage = false,\n locale,\n renderPart,\n onToolDecision,\n onRetry,\n editing = false,\n onEditSubmit,\n onEditCancel,\n actions,\n images,\n messages: override,\n className,\n ref,\n ...props\n}: MessageProps) {\n const messages = useAiMessages(override);\n const streaming = streamingProp ?? message.status === \"streaming\";\n const role = message.role;\n const assistant = role === \"assistant\";\n const author = name ?? messages.roles[role];\n const sourceParts = useMemo(\n () => message.parts.filter((part): part is SourcePart => part.type === \"source\"),\n [message.parts],\n );\n const edited = message.metadata?.[\"edited\"] === true;\n const tokens = showUsage && message.usage ? totalTokens(message.usage) : undefined;\n\n const context = (index: number): Omit<PartRenderContext, \"defaultRender\"> => ({ message, index, streaming });\n\n const renderTextPart = (part: TextPart, index: number): ReactNode => {\n const isLast = index === message.parts.length - 1;\n const view = () =>\n assistant ? (\n <Markdown streaming={streaming && isLast} images={images} messages={override}>\n {part.text}\n </Markdown>\n ) : (\n <p data-kit=\"ai-message-text\" dir=\"auto\">\n {part.text}\n </p>\n );\n const custom = renderPart?.text?.(part, { ...context(index), defaultRender: view });\n return custom === undefined ? view() : custom;\n };\n\n const renderReasoningPart = (part: ReasoningPart, index: number): ReactNode => {\n const isLast = index === message.parts.length - 1;\n const view = () => (\n <Reasoning\n text={part.text}\n durationMs={part.durationMs}\n streaming={streaming && isLast}\n locale={locale}\n messages={override}\n />\n );\n const custom = renderPart?.reasoning?.(part, { ...context(index), defaultRender: view });\n return custom === undefined ? view() : custom;\n };\n\n const renderToolPart = (part: ToolPart, index: number): ReactNode => {\n const view = () => (\n <ToolCall part={part} onDecision={onToolDecision} locale={locale} messages={override} />\n );\n const custom = renderPart?.tool?.(part, { ...context(index), defaultRender: view });\n return custom === undefined ? view() : custom;\n };\n\n const renderDataPart = (part: DataPart, index: number): ReactNode => {\n const view = () => <JsonView value={part.data} label={part.kind} messages={override} />;\n const renderer = renderPart?.[`data:${part.kind}`] ?? renderPart?.data;\n const custom = renderer?.(part, { ...context(index), defaultRender: view });\n return custom === undefined ? view() : custom;\n };\n\n const renderFiles = (files: FilePart[], index: number): ReactNode => {\n const view = () => <Attachments files={files} locale={locale} messages={override} />;\n const custom = renderPart?.files?.(files, { ...context(index), defaultRender: view });\n return custom === undefined ? view() : custom;\n };\n\n const renderSources = (): ReactNode => {\n if (sourceParts.length === 0) return null;\n const index = message.parts.findIndex((part) => part.type === \"source\");\n const view = () => <Sources messages={override} />;\n const custom = renderPart?.sources?.(sourceParts, { ...context(index), defaultRender: view });\n return custom === undefined ? view() : custom;\n };\n\n const renderParts = (): ReactNode[] => {\n const nodes: ReactNode[] = [];\n const files = message.parts.filter((part): part is FilePart => part.type === \"file\");\n let filesDone = false;\n\n message.parts.forEach((part: MessagePart, index) => {\n switch (part.type) {\n case \"text\": {\n if (part.text === \"\") return;\n nodes.push(<div key={`text-${index}`} data-kit=\"ai-message-part\" data-part=\"text\">{renderTextPart(part, index)}</div>);\n return;\n }\n case \"reasoning\":\n nodes.push(<div key={`reasoning-${index}`} data-kit=\"ai-message-part\" data-part=\"reasoning\">{renderReasoningPart(part, index)}</div>);\n return;\n case \"tool\":\n nodes.push(<div key={`tool-${part.id}`} data-kit=\"ai-message-part\" data-part=\"tool\">{renderToolPart(part, index)}</div>);\n return;\n case \"data\":\n nodes.push(<div key={`data-${index}`} data-kit=\"ai-message-part\" data-part=\"data\">{renderDataPart(part, index)}</div>);\n return;\n case \"file\":\n if (!filesDone) {\n filesDone = true;\n nodes.push(<div key={`files-${index}`} data-kit=\"ai-message-part\" data-part=\"files\">{renderFiles(files, index)}</div>);\n }\n return;\n case \"source\":\n // Sources are shown together at the end of the message.\n return;\n }\n });\n return nodes;\n };\n\n const editingUserText = editing && role === \"user\";\n const hasVisibleParts = message.parts.some((part) => part.type !== \"text\" || part.text !== \"\");\n const timestamp = showTimestamp && message.createdAt ? message.createdAt : null;\n\n return (\n <article\n {...props}\n ref={ref}\n tabIndex={props.tabIndex ?? -1}\n aria-label={messages.messageFrom(author)}\n aria-busy={streaming ? true : undefined}\n data-kit=\"ai-message\"\n data-role={role}\n data-status={message.status}\n data-streaming={streaming ? \"\" : undefined}\n className={cx(className)}\n >\n {avatar ? <div data-kit=\"ai-message-avatar\">{avatar}</div> : null}\n <div data-kit=\"ai-message-main\">\n <div data-kit=\"ai-message-header\">\n <span data-kit=\"ai-message-author\" dir=\"auto\">\n {author}\n </span>\n {assistant ? (\n <span data-kit=\"ai-message-label\">\n <Badge size=\"sm\" variant=\"outline\" tone=\"neutral\">\n <span aria-hidden=\"true\">{messages.aiGenerated}</span>\n <VisuallyHidden>{messages.aiGeneratedLabel}</VisuallyHidden>\n </Badge>\n </span>\n ) : null}\n {timestamp ? (\n <time data-kit=\"ai-message-time\" dateTime={timestamp} suppressHydrationWarning>\n {formatTimestamp(timestamp, locale)}\n </time>\n ) : null}\n {edited ? <span data-kit=\"ai-message-edited\">{messages.edited}</span> : null}\n </div>\n\n <SourcesProvider sources={sourceParts}>\n <div data-kit=\"ai-message-content\" aria-live={streaming ? \"off\" : undefined}>\n {editingUserText ? (\n <MessageEditor\n initialText={messageText(message)}\n onSubmit={(text) => onEditSubmit?.(text)}\n onCancel={() => onEditCancel?.()}\n messages={override}\n />\n ) : (\n renderParts()\n )}\n {streaming && !hasVisibleParts ? <StreamingIndicator messages={override} /> : null}\n </div>\n {renderSources()}\n </SourcesProvider>\n\n {message.status === \"stopped\" ? (\n <p data-kit=\"ai-message-status\" data-status=\"stopped\">\n {messages.stopped}\n </p>\n ) : null}\n {message.status === \"error\" && message.error ? (\n <ErrorBanner error={message.error} onRetry={onRetry} messages={override} />\n ) : null}\n {tokens !== undefined && !streaming ? (\n <p data-kit=\"ai-message-usage\">{messages.tokens(formatTokenCount(tokens, locale))}</p>\n ) : null}\n {actions}\n </div>\n </article>\n );\n}\n\n/** Alias of `Message`, for code that also imports the `Message` data type from `@x12i/ai`. */\nexport const ChatMessage = Message;\nexport type ChatMessageProps = MessageProps;\n","import { VisuallyHidden } from \"@x12i/ui\";\nimport type { ComponentPropsWithRef } from \"react\";\nimport { formatBytes } from \"../format\";\nimport { sanitizeImageUrl, sanitizeUrl } from \"../markdown-safety\";\nimport type { FilePart } from \"../types\";\nimport { cx } from \"./internal/cx\";\nimport { FileGlyph } from \"./internal/glyphs\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\n\nexport interface AttachmentsProps extends Omit<ComponentPropsWithRef<\"ul\">, \"children\"> {\n files: readonly FilePart[];\n locale?: string | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\nfunction isImage(file: FilePart): boolean {\n return file.mediaType.toLowerCase().startsWith(\"image/\") && file.mediaType.toLowerCase() !== \"image/svg+xml\";\n}\n\n/**\n * The files of a message. Images show as thumbnails that open the full image;\n * other files show as a chip with name and size that downloads. A file whose\n * URL is not safe (`javascript:` and the like) is shown as a name only. SVG is\n * never shown inline, because it can carry script.\n */\nexport function Attachments({ files, locale, messages: override, className, ref, ...props }: AttachmentsProps) {\n const messages = useAiMessages(override);\n if (files.length === 0) return null;\n\n return (\n <ul {...props} ref={ref} role=\"list\" aria-label={messages.attachmentsList} data-kit=\"ai-attachments\" className={cx(className)}>\n {files.map((file, position) => {\n const image = isImage(file);\n const url = image\n ? sanitizeImageUrl(file.url, { allowDataImages: true, allowBlob: true })\n : sanitizeUrl(file.url, { protocols: [\"http:\", \"https:\", \"blob:\"] });\n const size = file.size === undefined ? \"\" : formatBytes(file.size, locale);\n\n return (\n <li key={file.id ?? `${file.url}-${position}`} data-kit=\"ai-attachment\" data-kind={image ? \"image\" : \"file\"}>\n {image && url ? (\n <a href={url} target=\"_blank\" rel=\"noopener noreferrer\">\n <img src={url} alt={file.name} loading=\"lazy\" decoding=\"async\" referrerPolicy=\"no-referrer\" />\n <VisuallyHidden> ({messages.opensInNewTab})</VisuallyHidden>\n </a>\n ) : (\n <>\n {url ? (\n <a href={url} download={file.name} aria-label={messages.download(file.name)} data-kit=\"ai-attachment-link\">\n <FileGlyph size=\"sm\" />\n <span data-kit=\"ai-attachment-name\" dir=\"auto\">\n {file.name}\n </span>\n {size === \"\" ? null : <span data-kit=\"ai-attachment-size\">{size}</span>}\n </a>\n ) : (\n <span data-kit=\"ai-attachment-link\" data-inert=\"\">\n <FileGlyph size=\"sm\" />\n <span data-kit=\"ai-attachment-name\" dir=\"auto\">\n {file.name}\n </span>\n {size === \"\" ? null : <span data-kit=\"ai-attachment-size\">{size}</span>}\n </span>\n )}\n </>\n )}\n </li>\n );\n })}\n </ul>\n );\n}\n","import { Button } from \"@x12i/ui\";\nimport { useRef, useState } from \"react\";\nimport { useAiMessages } from \"../messages-context\";\nimport type { AiMessagesOverride } from \"../messages\";\nimport { CopyButton } from \"./copy-button\";\nimport { useHorizontalOverflow } from \"./hooks\";\n\n/**\n * Turns any value into pretty JSON without throwing: circular references\n * become `\"[Circular]\"`, `BigInt` becomes a string, functions and symbols\n * become their string form, and `undefined` becomes `null` at the top level.\n */\nexport function safeStringify(value: unknown, space = 2): string {\n if (typeof value === \"string\") return value;\n const seen = new WeakSet<object>();\n try {\n const json = JSON.stringify(\n value,\n (_key, entry: unknown) => {\n if (typeof entry === \"bigint\") return `${entry.toString()}n`;\n if (typeof entry === \"function\" || typeof entry === \"symbol\") return String(entry);\n if (typeof entry === \"object\" && entry !== null) {\n if (seen.has(entry)) return \"[Circular]\";\n seen.add(entry);\n }\n return entry;\n },\n space,\n );\n return json ?? \"null\";\n } catch {\n return String(value);\n }\n}\n\nexport interface JsonViewProps {\n value: unknown;\n /** Accessible name of the block, for example \"Input\". */\n label: string;\n /** Characters shown before the rest is folded behind a button. Default 4000. */\n maxChars?: number;\n messages?: AiMessagesOverride;\n}\n\n/**\n * A read-only, copyable view of a value, always left-to-right. Large values\n * are folded so a tool that returns a megabyte does not freeze the page.\n */\nexport function JsonView({ value, label, maxChars = 4000, messages: override }: JsonViewProps) {\n const messages = useAiMessages(override);\n const [expanded, setExpanded] = useState(false);\n const preRef = useRef<HTMLPreElement>(null);\n const text = safeStringify(value);\n const folded = !expanded && text.length > maxChars;\n const shown = folded ? text.slice(0, maxChars) : text;\n const overflowing = useHorizontalOverflow(preRef, shown);\n\n return (\n <div data-kit=\"ai-json-view\" dir=\"ltr\" role=\"group\" aria-label={label}>\n <div data-kit=\"ai-json-view-header\">\n <span data-kit=\"ai-json-view-label\" aria-hidden=\"true\">\n {label}\n </span>\n <CopyButton\n text={text}\n label={messages.copyJson}\n copiedLabel={messages.copied}\n failedLabel={messages.copyFailed}\n />\n </div>\n <pre ref={preRef} tabIndex={overflowing ? 0 : undefined}>\n <code>{shown}</code>\n </pre>\n {text.length > maxChars ? (\n <Button\n variant=\"ghost\"\n tone=\"neutral\"\n size=\"xs\"\n aria-expanded={!folded}\n onClick={() => setExpanded((open) => !open)}\n >\n {folded ? messages.showMore(text.length - maxChars) : messages.showLess}\n </Button>\n ) : null}\n </div>\n );\n}\n","import { Icon } from \"@x12i/icons\";\nimport { IconButton, VisuallyHidden, type IconButtonProps } from \"@x12i/ui\";\nimport { useCallback, useId } from \"react\";\nimport { writeToClipboard } from \"./clipboard\";\nimport { useTransientState } from \"./hooks\";\n\nexport interface CopyButtonProps extends Omit<IconButtonProps, \"label\" | \"children\" | \"onClick\"> {\n /** What to copy: a string, or a function that returns it when the button is pressed. */\n text: string | (() => string);\n /** Accessible name of the button, for example \"Copy code\". */\n label: string;\n /** Spoken after a successful copy. */\n copiedLabel: string;\n /** Spoken when the copy failed. */\n failedLabel: string;\n /** Called with the copied text after a successful copy. */\n onCopied?: ((text: string) => void) | undefined;\n}\n\n/**\n * An icon button that copies text. The button's name never changes, so a\n * screen reader does not re-read it; the result is spoken through a separate\n * polite status region, and shown as a check mark.\n */\nexport function CopyButton({ text, label, copiedLabel, failedLabel, onCopied, ...props }: CopyButtonProps) {\n const [status, setStatus] = useTransientState<\"idle\" | \"copied\" | \"failed\">(\"idle\");\n const statusId = useId();\n\n const handleClick = useCallback(async () => {\n const value = typeof text === \"function\" ? text() : text;\n const ok = await writeToClipboard(value);\n setStatus(ok ? \"copied\" : \"failed\");\n if (ok) onCopied?.(value);\n }, [text, onCopied, setStatus]);\n\n return (\n <span data-kit=\"ai-copy\" data-state={status}>\n <IconButton\n variant=\"ghost\"\n tone=\"neutral\"\n size=\"sm\"\n {...props}\n label={label}\n aria-describedby={statusId}\n onClick={() => {\n void handleClick();\n }}\n >\n <Icon name={status === \"copied\" ? \"check\" : \"copy\"} size={16} />\n </IconButton>\n <VisuallyHidden id={statusId} role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {status === \"copied\" ? copiedLabel : status === \"failed\" ? failedLabel : \"\"}\n </VisuallyHidden>\n </span>\n );\n}\n","/**\n * Copies text to the clipboard. Uses the async Clipboard API, and falls back to\n * a hidden textarea and `execCommand(\"copy\")` where it is missing (older\n * browsers, or an insecure context). Returns whether the copy worked.\n */\nexport async function writeToClipboard(text: string): Promise<boolean> {\n try {\n if (typeof navigator !== \"undefined\" && navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(text);\n return true;\n }\n } catch {\n // Fall through to the legacy path: the API can reject without permission.\n }\n\n if (typeof document === \"undefined\") return false;\n const previous = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n const textarea = document.createElement(\"textarea\");\n try {\n textarea.value = text;\n textarea.setAttribute(\"readonly\", \"\");\n textarea.setAttribute(\"aria-hidden\", \"true\");\n textarea.style.position = \"fixed\";\n textarea.style.opacity = \"0\";\n textarea.style.pointerEvents = \"none\";\n document.body.appendChild(textarea);\n textarea.select();\n return typeof document.execCommand === \"function\" ? document.execCommand(\"copy\") : false;\n } catch {\n return false;\n } finally {\n textarea.remove();\n previous?.focus();\n }\n}\n","import { useLayoutEffect, type RefObject } from \"react\";\n\n/**\n * Grows a textarea to fit its content. It writes the measured height to the\n * `--_ai-height` custom property; the stylesheet turns that into `block-size`\n * and caps it with `max-block-size`, so rows beyond the cap scroll.\n */\nexport function useAutosize(ref: RefObject<HTMLTextAreaElement | null>, value: string): void {\n useLayoutEffect(() => {\n const element = ref.current;\n if (!element) return;\n\n const fit = () => {\n element.style.setProperty(\"--_ai-height\", \"auto\");\n const chrome = element.offsetHeight - element.clientHeight;\n const next = element.scrollHeight + Math.max(0, chrome);\n element.style.setProperty(\"--_ai-height\", next > 0 ? `${next}px` : \"auto\");\n };\n fit();\n\n // Wrapping changes when the width does, so measure again then.\n if (typeof ResizeObserver === \"undefined\") return;\n let lastWidth = element.clientWidth;\n const observer = new ResizeObserver(() => {\n if (element.clientWidth !== lastWidth) {\n lastWidth = element.clientWidth;\n fit();\n }\n });\n observer.observe(element);\n return () => observer.disconnect();\n }, [ref, value]);\n}\n","import { VisuallyHidden } from \"@x12i/ui\";\nimport {\n createContext,\n createElement,\n memo,\n useContext,\n useId,\n useMemo,\n useRef,\n type ComponentPropsWithoutRef,\n type ComponentPropsWithRef,\n type JSX,\n type MouseEvent,\n type ReactNode,\n} from \"react\";\nimport ReactMarkdown, { type Components, type ExtraProps, type Options } from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport { parseCitations } from \"../citations\";\nimport { isExternalUrl, sanitizeImageUrl, sanitizeUrl, splitMarkdownBlocks } from \"../markdown-safety\";\nimport type { SourcePart } from \"../types\";\nimport { CodeBlock } from \"./code-block\";\nimport { cx } from \"./internal/cx\";\nimport { useHorizontalOverflow } from \"./internal/hooks\";\nimport type { AiMessages, AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\nimport { Citation, useSourcesContext } from \"./sources\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype HastElement = NonNullable<ExtraProps[\"node\"]>;\ntype HastChild = HastElement[\"children\"][number];\n\n/** How `` is shown. */\nexport type MarkdownImageMode = \"inline\" | \"link\" | \"none\";\n\nexport interface MarkdownProps extends Omit<ComponentPropsWithRef<\"div\">, \"children\"> {\n /** The Markdown text. Raw HTML in it is dropped, never rendered. */\n children: string;\n /** True while the text is still arriving. Sets `data-streaming`; finished blocks are not re-rendered either way. */\n streaming?: boolean | undefined;\n /**\n * Added to heading levels so a `#` in a reply does not compete with the\n * page's own headings: with the default 2, `#` renders as `<h3>`. Capped at `<h6>`.\n */\n headingOffset?: number | undefined;\n /**\n * What to do with images. `\"link\"` (default) shows a link to the image, `\"inline\"`\n * renders it, `\"none\"` shows only the alt text. A model can leak data in an\n * image URL, so inline images are opt-in. Unsafe URLs are never rendered.\n */\n images?: MarkdownImageMode | undefined;\n /** Allow raster `data:image/...;base64` images when `images=\"inline\"`. Default false. */\n allowDataImages?: boolean | undefined;\n /**\n * Rewrites an image URL before it is rendered, for example to send it through\n * your own proxy. Return `null` to block the image. The result is checked again.\n */\n transformImageUrl?: ((url: string) => string | null | undefined) | undefined;\n /**\n * Turn `[1]`, `[1, 2]` and `[1-3]` into citation chips. Defaults to true when\n * `sources` is given or a surrounding `SourcesProvider` has sources. A number\n * with no matching source stays as plain text.\n */\n citations?: boolean | undefined;\n /** The sources the citations point at. Defaults to the surrounding `SourcesProvider`'s. */\n sources?: readonly SourcePart[] | undefined;\n /** Called when a link is clicked. Call `preventDefault` to handle navigation yourself. */\n onLinkClick?: ((event: MouseEvent<HTMLAnchorElement>, url: string) => void) | undefined;\n /** Called after a code block was copied. */\n onCopyCode?: ((code: string, language: string) => void) | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\ninterface MarkdownConfig {\n messages: AiMessages;\n /** The component's own override, passed on to nested components such as `CodeBlock`. */\n override: AiMessagesOverride | undefined;\n images: MarkdownImageMode;\n allowDataImages: boolean;\n transformImageUrl: ((url: string) => string | null | undefined) | undefined;\n headingOffset: number;\n idPrefix: string;\n onLinkClick: ((event: MouseEvent<HTMLAnchorElement>, url: string) => void) | undefined;\n onCopyCode: ((code: string, language: string) => void) | undefined;\n /** Sources given through the `sources` prop. Citations then link straight to them. */\n sources: readonly SourcePart[] | undefined;\n}\n\nconst ConfigContext = createContext<MarkdownConfig | null>(null);\n\nfunction useConfig(): MarkdownConfig {\n const config = useContext(ConfigContext);\n if (!config) throw new Error(\"@x12i/ai: Markdown elements must render inside <Markdown>.\");\n return config;\n}\n\n// ---------------------------------------------------------------------------\n// Citation plugin\n// ---------------------------------------------------------------------------\n\ninterface MdNode {\n type: string;\n value?: string;\n label?: string | null;\n identifier?: string;\n referenceType?: string;\n children?: MdNode[];\n data?: Record<string, unknown>;\n}\n\nconst SKIP_CITATIONS_IN = new Set([\"link\", \"linkReference\", \"code\", \"inlineCode\", \"definition\", \"html\", \"image\", \"imageReference\"]);\n\nfunction citationNode(n: number): MdNode {\n return {\n type: \"citation\",\n data: { hName: \"span\", hProperties: { dataCitation: String(n) } },\n children: [{ type: \"text\", value: String(n) }],\n };\n}\n\nfunction collectDefinitions(node: MdNode, into: Set<string>): void {\n if (node.type === \"definition\" && node.identifier) into.add(node.identifier.toLowerCase());\n node.children?.forEach((child) => collectDefinitions(child, into));\n}\n\n/** Replaces `[n]` markers with citation nodes. Markdown parses an unresolved `[1]` as a shortcut link reference, so that is handled too. */\nfunction createCitationTransform(maxIndex: number) {\n return () => (tree: MdNode) => {\n const definitions = new Set<string>();\n collectDefinitions(tree, definitions);\n\n const visit = (node: MdNode) => {\n if (!node.children) return;\n const next: MdNode[] = [];\n for (const child of node.children) {\n let raw: string | null = null;\n if (child.type === \"text\" && typeof child.value === \"string\" && child.value.includes(\"[\")) {\n raw = child.value;\n } else if (\n child.type === \"linkReference\" &&\n child.referenceType === \"shortcut\" &&\n !definitions.has((child.identifier ?? \"\").toLowerCase()) &&\n typeof child.label === \"string\"\n ) {\n raw = `[${child.label}]`;\n }\n\n if (raw !== null) {\n const segments = parseCitations(raw, { maxIndex });\n if (segments.some((segment) => segment.type === \"citation\")) {\n for (const segment of segments) {\n if (segment.type === \"text\") next.push({ type: \"text\", value: segment.text });\n else for (const n of segment.numbers) next.push(citationNode(n));\n }\n continue;\n }\n }\n\n if (!SKIP_CITATIONS_IN.has(child.type)) visit(child);\n next.push(child);\n }\n node.children = next;\n };\n visit(tree);\n };\n}\n\ntype PluginList = NonNullable<Options[\"remarkPlugins\"]>;\n\nconst BASE_PLUGINS: PluginList = [remarkGfm];\nconst citationPlugins = new Map<number, PluginList>();\n\nfunction pluginsFor(maxIndex: number): PluginList {\n if (maxIndex <= 0) return BASE_PLUGINS;\n let plugins = citationPlugins.get(maxIndex);\n if (!plugins) {\n plugins = [remarkGfm, createCitationTransform(maxIndex)];\n citationPlugins.set(maxIndex, plugins);\n }\n return plugins;\n}\n\n// ---------------------------------------------------------------------------\n// URL handling\n// ---------------------------------------------------------------------------\n\n/**\n * The first line of defence, run by react-markdown on every `href` and `src`\n * before it reaches a component. It is a pure, stable function, so it never\n * invalidates the block cache. Components then apply the per-instance policy.\n */\nfunction urlTransform(url: string, key: string): string {\n if (key === \"src\") return sanitizeImageUrl(url, { allowDataImages: true }) ?? \"\";\n return sanitizeUrl(url) ?? \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Element components (module-level, so their identity never changes)\n// ---------------------------------------------------------------------------\n\ntype WithNode<T extends keyof JSX.IntrinsicElements> = ComponentPropsWithoutRef<T> & ExtraProps;\n\n/** Removes the `node` prop react-markdown adds, so it never reaches the DOM. */\nfunction withoutNode<T extends { node?: unknown }>(props: T): Omit<T, \"node\"> {\n const rest = { ...props };\n delete rest.node;\n return rest;\n}\n\nfunction textOf(node: HastChild | undefined): string {\n if (!node) return \"\";\n if (node.type === \"text\") return node.value;\n if (node.type === \"element\") return node.children.map(textOf).join(\"\");\n return \"\";\n}\n\nfunction Link(raw: WithNode<\"a\">) {\n const { href, children, onClick, ...props } = withoutNode(raw);\n const config = useConfig();\n const url = sanitizeUrl(href);\n\n if (!url) {\n return (\n <span data-kit=\"ai-markdown-link\" data-blocked=\"\">\n {children}\n </span>\n );\n }\n\n const isFragment = url.startsWith(\"#\");\n const isContact = /^(?:mailto|tel):/i.test(url);\n const opensNewTab = !isFragment && !isContact;\n const anchorProps: ComponentPropsWithoutRef<\"a\"> = { ...props, href: url };\n\n // Footnote references use a fixed id for `aria-describedby`; scope it so two messages can both have footnotes.\n if (anchorProps[\"aria-describedby\"] === \"footnote-label\") {\n anchorProps[\"aria-describedby\"] = `${config.idPrefix}footnote-label`;\n }\n\n return (\n <a\n {...anchorProps}\n data-kit=\"ai-markdown-link\"\n data-external={opensNewTab && isExternalUrl(url) ? \"\" : undefined}\n target={opensNewTab ? \"_blank\" : undefined}\n rel={isFragment ? undefined : \"noopener noreferrer\"}\n onClick={(event) => {\n onClick?.(event);\n config.onLinkClick?.(event, url);\n }}\n >\n {children}\n {opensNewTab ? <VisuallyHidden> ({config.messages.opensInNewTab})</VisuallyHidden> : null}\n </a>\n );\n}\n\nfunction Image({ src, alt, title }: WithNode<\"img\">) {\n const config = useConfig();\n const altText = alt ?? \"\";\n let url = typeof src === \"string\" ? src : null;\n if (url !== null && config.transformImageUrl) url = config.transformImageUrl(url) ?? null;\n const safe = url === null ? null : sanitizeImageUrl(url, { allowDataImages: config.allowDataImages });\n\n // A data URL cannot be opened as a link in most browsers, so only inline mode shows it.\n const blocked = config.images === \"none\" || safe === null || (safe.startsWith(\"data:\") && config.images !== \"inline\");\n if (blocked || safe === null) {\n return (\n <span data-kit=\"ai-markdown-image\" data-blocked=\"\" dir=\"auto\">\n {altText === \"\" ? config.messages.imageBlocked : altText}\n </span>\n );\n }\n\n if (config.images === \"link\") {\n return (\n <a data-kit=\"ai-markdown-link\" href={safe} target=\"_blank\" rel=\"noopener noreferrer\" dir=\"auto\">\n {altText === \"\" ? safe : altText}\n <VisuallyHidden> ({config.messages.opensInNewTab})</VisuallyHidden>\n </a>\n );\n }\n\n return (\n <img\n data-kit=\"ai-markdown-image\"\n src={safe}\n alt={altText}\n title={title}\n loading=\"lazy\"\n decoding=\"async\"\n referrerPolicy=\"no-referrer\"\n />\n );\n}\n\nfunction Pre({ node, children }: WithNode<\"pre\">) {\n const config = useConfig();\n const codeElement = node?.children.find(\n (child): child is HastElement => child.type === \"element\" && child.tagName === \"code\",\n );\n if (!codeElement) return <pre>{children}</pre>;\n\n const classNames = codeElement.properties?.className;\n const classList = Array.isArray(classNames) ? classNames.map(String) : [];\n const language = classList.find((name) => name.startsWith(\"language-\"))?.slice(\"language-\".length) ?? \"\";\n // The parser adds a final newline to fenced code; it is not part of the code.\n const code = textOf(codeElement).replace(/\\n$/, \"\");\n\n return (\n <CodeBlock\n code={code}\n language={language}\n messages={config.override}\n onCopied={config.onCopyCode ? (copied) => config.onCopyCode?.(copied, language) : undefined}\n />\n );\n}\n\nfunction Table(raw: WithNode<\"table\">) {\n const { children, ...props } = withoutNode(raw);\n const { messages } = useConfig();\n const ref = useRef<HTMLDivElement>(null);\n const overflowing = useHorizontalOverflow(ref, children);\n return (\n <div\n ref={ref}\n data-kit=\"ai-markdown-table\"\n role={overflowing ? \"group\" : undefined}\n aria-label={overflowing ? messages.table : undefined}\n tabIndex={overflowing ? 0 : undefined}\n >\n <table {...props}>{children}</table>\n </div>\n );\n}\n\nfunction Input(raw: WithNode<\"input\">) {\n const { checked, ...props } = withoutNode(raw);\n const { messages } = useConfig();\n if (props.type !== \"checkbox\") return null;\n // Task-list boxes are display only: a reply cannot be edited by ticking them.\n return (\n <input\n {...props}\n type=\"checkbox\"\n checked={Boolean(checked)}\n disabled\n readOnly\n aria-label={checked ? messages.taskDone : messages.taskTodo}\n />\n );\n}\n\nfunction Span(raw: WithNode<\"span\">) {\n const { children, ...props } = withoutNode(raw);\n const config = useConfig();\n const citation = (props as Record<string, unknown>)[\"data-citation\"];\n if (typeof citation === \"string\") {\n const index = Number(citation);\n if (Number.isInteger(index) && index > 0) {\n return <Citation index={index} source={config.sources?.[index - 1]} messages={config.override} />;\n }\n }\n return <span {...props}>{children}</span>;\n}\n\nfunction makeHeading(level: 1 | 2 | 3 | 4 | 5 | 6) {\n function Heading(raw: WithNode<\"h1\">) {\n const { children, ...props } = withoutNode(raw);\n const config = useConfig();\n const tag = `h${Math.min(6, level + Math.max(0, config.headingOffset))}`;\n const isFootnoteLabel = props.id === \"footnote-label\";\n return createElement(\n tag,\n {\n ...props,\n id: isFootnoteLabel ? `${config.idPrefix}footnote-label` : props.id,\n dir: \"auto\",\n \"data-footnote-label\": isFootnoteLabel ? \"\" : undefined,\n },\n children,\n );\n }\n Heading.displayName = `MarkdownHeading${level}`;\n return Heading;\n}\n\nfunction Paragraph(props: WithNode<\"p\">) {\n return <p {...withoutNode(props)} dir=\"auto\" />;\n}\n\nfunction ListItem(props: WithNode<\"li\">) {\n return <li {...withoutNode(props)} dir=\"auto\" />;\n}\n\nfunction UnorderedList(props: WithNode<\"ul\">) {\n return <ul {...withoutNode(props)} dir=\"auto\" />;\n}\n\nfunction OrderedList(props: WithNode<\"ol\">) {\n return <ol {...withoutNode(props)} dir=\"auto\" />;\n}\n\nfunction Blockquote(props: WithNode<\"blockquote\">) {\n return <blockquote {...withoutNode(props)} dir=\"auto\" />;\n}\n\nfunction TableCell(props: WithNode<\"td\">) {\n return <td {...withoutNode(props)} dir=\"auto\" />;\n}\n\nfunction TableHeaderCell(props: WithNode<\"th\">) {\n return <th {...withoutNode(props)} dir=\"auto\" />;\n}\n\nconst COMPONENTS: Components = {\n a: Link,\n img: Image,\n pre: Pre,\n table: Table,\n input: Input,\n span: Span,\n h1: makeHeading(1),\n h2: makeHeading(2),\n h3: makeHeading(3),\n h4: makeHeading(4),\n h5: makeHeading(5),\n h6: makeHeading(6),\n p: Paragraph,\n li: ListItem,\n ul: UnorderedList,\n ol: OrderedList,\n blockquote: Blockquote,\n td: TableCell,\n th: TableHeaderCell,\n};\n\n// ---------------------------------------------------------------------------\n// Block rendering\n// ---------------------------------------------------------------------------\n\ninterface MarkdownBlockProps {\n markdown: string;\n maxIndex: number;\n footnoteLabel: string;\n footnoteBackLabel: string;\n clobberPrefix: string;\n}\n\n/**\n * One top-level block. Every prop is a primitive, so `memo` skips a block\n * whose text did not change: while a reply streams, only the last block is\n * parsed again.\n */\nconst MarkdownBlock = memo(function MarkdownBlock({\n markdown,\n maxIndex,\n footnoteLabel,\n footnoteBackLabel,\n clobberPrefix,\n}: MarkdownBlockProps) {\n const remarkRehypeOptions = useMemo(\n () => ({ footnoteLabel, footnoteBackLabel, clobberPrefix, footnoteLabelProperties: {} }),\n [footnoteLabel, footnoteBackLabel, clobberPrefix],\n );\n\n return (\n <ReactMarkdown\n skipHtml\n remarkPlugins={pluginsFor(maxIndex)}\n components={COMPONENTS}\n urlTransform={urlTransform}\n remarkRehypeOptions={remarkRehypeOptions}\n >\n {markdown}\n </ReactMarkdown>\n );\n});\n\n// ---------------------------------------------------------------------------\n// Public component\n// ---------------------------------------------------------------------------\n\n/**\n * Renders Markdown from a model safely.\n *\n * - Raw HTML is dropped. Links keep only `http:`, `https:`, `mailto:`, `tel:`\n * and relative URLs; external links open in a new tab with\n * `rel=\"noopener noreferrer\"` and a spoken \"opens in a new tab\".\n * - GitHub Flavored Markdown: tables (in a scroll wrapper), task lists\n * (display only), strikethrough, autolinks and footnotes.\n * - Fenced code becomes a `CodeBlock`: language label and copy button, no highlighting.\n * - Text blocks are `dir=\"auto\"`, so Hebrew or Arabic paragraphs align correctly.\n * - Finished blocks are cached while text streams in.\n */\nexport function Markdown({\n children,\n streaming = false,\n headingOffset = 2,\n images = \"link\",\n allowDataImages = false,\n transformImageUrl,\n citations,\n sources,\n onLinkClick,\n onCopyCode,\n messages: override,\n className,\n ref,\n ...props\n}: MarkdownProps) {\n const messages = useAiMessages(override);\n const sourcesContext = useSourcesContext();\n const instanceId = useId();\n const sourceCount = (sources ?? sourcesContext?.sources)?.length ?? 0;\n const maxIndex = (citations ?? sourceCount > 0) ? sourceCount : 0;\n const idPrefix = `${instanceId}-`;\n\n const config = useMemo<MarkdownConfig>(\n () => ({\n messages,\n override,\n images,\n allowDataImages,\n transformImageUrl,\n headingOffset,\n idPrefix,\n onLinkClick,\n onCopyCode,\n sources,\n }),\n [messages, override, images, allowDataImages, transformImageUrl, headingOffset, idPrefix, onLinkClick, onCopyCode, sources],\n );\n const blocks = useMemo(() => splitMarkdownBlocks(children), [children]);\n\n let content: ReactNode = null;\n if (blocks.length > 0) {\n content = blocks.map((block, position) => (\n <MarkdownBlock\n // Block order is stable while text is appended, so the index is the right key.\n key={position}\n markdown={block}\n maxIndex={maxIndex}\n footnoteLabel={messages.footnotes}\n footnoteBackLabel={messages.footnoteBack}\n clobberPrefix={idPrefix}\n />\n ));\n }\n\n return (\n <div\n {...props}\n ref={ref}\n data-kit=\"ai-markdown\"\n data-streaming={streaming ? \"\" : undefined}\n className={cx(className)}\n >\n <ConfigContext.Provider value={config}>{content}</ConfigContext.Provider>\n </div>\n );\n}\n","import { useRef, type ComponentPropsWithRef } from \"react\";\nimport { CopyButton } from \"./internal/copy-button\";\nimport { cx } from \"./internal/cx\";\nimport { useHorizontalOverflow } from \"./internal/hooks\";\nimport { useAiMessages } from \"./messages-context\";\nimport type { AiMessagesOverride } from \"./messages\";\n\nexport interface CodeBlockProps extends Omit<ComponentPropsWithRef<\"div\">, \"children\"> {\n /** The code, exactly as it should be copied. */\n code: string;\n /** The language label, such as `ts`. Empty or omitted shows a generic label. */\n language?: string | undefined;\n onCopied?: ((code: string) => void) | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\n/**\n * A code block with a language label and a copy button. It is always\n * left-to-right, whatever the page direction, and is never highlighted or\n * run: code from a model is shown as text only. When a line is wider than the\n * block, the block becomes keyboard-focusable so it can be scrolled.\n */\nexport function CodeBlock({ code, language = \"\", onCopied, messages: override, className, ref, ...props }: CodeBlockProps) {\n const messages = useAiMessages(override);\n const preRef = useRef<HTMLPreElement>(null);\n const overflowing = useHorizontalOverflow(preRef, code);\n\n return (\n <div\n {...props}\n ref={ref}\n data-kit=\"ai-code-block\"\n data-language={language === \"\" ? undefined : language}\n dir=\"ltr\"\n role=\"group\"\n aria-label={messages.codeBlock(language)}\n className={cx(className)}\n >\n <div data-kit=\"ai-code-block-header\">\n <span data-kit=\"ai-code-block-language\" aria-hidden=\"true\">\n {language === \"\" ? messages.plainText : language}\n </span>\n <CopyButton\n text={code}\n label={messages.copyCode}\n copiedLabel={messages.codeCopied}\n failedLabel={messages.copyFailed}\n onCopied={onCopied}\n />\n </div>\n <pre ref={preRef} tabIndex={overflowing ? 0 : undefined}>\n <code className={language === \"\" ? undefined : `language-${language}`}>{code}</code>\n </pre>\n </div>\n );\n}\n","import { Icon } from \"@x12i/icons\";\nimport { Badge, VisuallyHidden } from \"@x12i/ui\";\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithRef,\n type MouseEvent,\n type ReactNode,\n} from \"react\";\nimport { getUrlHostname, sanitizeUrl } from \"../markdown-safety\";\nimport type { SourcePart } from \"../types\";\nimport { useDisclosure } from \"./internal/disclosure\";\nimport { cx } from \"./internal/cx\";\nimport { useAiMessages } from \"./messages-context\";\nimport type { AiMessagesOverride } from \"./messages\";\n\ninterface SourcesContextValue {\n /** Prefix of the DOM ids of the source items. */\n baseId: string;\n sources: readonly SourcePart[];\n /** Opens the source list and moves focus to the n-th source. False when no list is mounted. */\n reveal: (index: number) => boolean;\n register: (handler: (index: number) => void) => () => void;\n}\n\nconst SourcesContext = createContext<SourcesContextValue | null>(null);\n\nexport function useSourcesContext(): SourcesContextValue | null {\n return useContext(SourcesContext);\n}\n\n/** The DOM id of the n-th source item (1-based), so a citation can link to it. */\nexport function sourceDomId(baseId: string, index: number): string {\n return `${baseId}-source-${index}`;\n}\n\nexport interface SourcesProviderProps {\n sources: readonly SourcePart[];\n children?: ReactNode;\n}\n\n/**\n * Connects inline citations to the source list. `Message` provides it; use it\n * yourself when you render `Markdown` and `Sources` separately.\n */\nexport function SourcesProvider({ sources, children }: SourcesProviderProps) {\n const baseId = useId();\n const handlers = useRef(new Set<(index: number) => void>());\n\n const register = useCallback((handler: (index: number) => void) => {\n handlers.current.add(handler);\n return () => {\n handlers.current.delete(handler);\n };\n }, []);\n\n const reveal = useCallback((index: number) => {\n if (handlers.current.size === 0) return false;\n handlers.current.forEach((handler) => handler(index));\n return true;\n }, []);\n\n const value = useMemo(() => ({ baseId, sources, reveal, register }), [baseId, sources, reveal, register]);\n return <SourcesContext.Provider value={value}>{children}</SourcesContext.Provider>;\n}\n\nexport interface CitationProps extends Omit<ComponentPropsWithRef<\"a\">, \"children\" | \"href\"> {\n /** The source number, from 1. */\n index: number;\n /**\n * The source. Defaults to the n-th source of the surrounding\n * `SourcesProvider`. Passing one makes the chip stand alone: it links to the\n * source's URL instead of jumping to the provider's list.\n */\n source?: SourcePart | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\n/**\n * An inline numbered chip for a citation. Inside a `SourcesProvider` it jumps\n * to the matching item of the source list (opening the list if it is\n * folded); on its own it links to the source's URL. A source without a safe\n * URL renders as a plain, non-interactive chip.\n */\nexport function Citation({ index, source: sourceProp, messages: override, className, onClick, ref, ...props }: CitationProps) {\n const messages = useAiMessages(override);\n const ambient = useSourcesContext();\n // An explicit `source` makes the chip stand alone: it links to that source's\n // URL rather than to an item of a list that may hold different sources.\n const context = sourceProp ? null : ambient;\n const source = sourceProp ?? context?.sources[index - 1];\n const title = source?.title ?? \"\";\n const label = messages.citationLabel(index, title);\n\n const handleClick = (event: MouseEvent<HTMLAnchorElement>) => {\n onClick?.(event);\n if (event.defaultPrevented || !context) return;\n // Keep the page's own URL and scroll position: the source list takes focus instead.\n if (context.reveal(index)) event.preventDefault();\n };\n\n if (context && source) {\n return (\n <a\n {...props}\n ref={ref}\n data-kit=\"ai-citation\"\n className={cx(className)}\n href={`#${sourceDomId(context.baseId, index)}`}\n aria-label={label}\n onClick={handleClick}\n >\n {index}\n </a>\n );\n }\n\n const url = source ? sanitizeUrl(source.url, { allowRelative: false }) : null;\n if (url) {\n return (\n <a\n {...props}\n ref={ref}\n data-kit=\"ai-citation\"\n className={cx(className)}\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`${label} (${messages.opensInNewTab})`}\n onClick={onClick}\n >\n {index}\n </a>\n );\n }\n\n return (\n <span data-kit=\"ai-citation\" data-inert=\"\" className={cx(className)} aria-label={source ? label : undefined}>\n {index}\n </span>\n );\n}\n\nexport interface SourceCardProps extends Omit<ComponentPropsWithRef<\"li\">, \"children\" | \"id\"> {\n source: SourcePart;\n /** The number shown and cited, from 1. */\n index: number;\n /** The DOM id, so citations can link here. */\n id?: string;\n messages?: AiMessagesOverride | undefined;\n}\n\n/**\n * One source: number, title as a link, domain and snippet. No favicon is\n * fetched, so listing sources never makes a request to the source's site.\n */\nexport function SourceCard({ source, index, id, messages: override, className, ref, ...props }: SourceCardProps) {\n const messages = useAiMessages(override);\n const url = sanitizeUrl(source.url, { allowRelative: false });\n const host = url ? getUrlHostname(url) : null;\n\n return (\n <li\n {...props}\n ref={ref}\n id={id}\n tabIndex={-1}\n data-kit=\"ai-source\"\n className={cx(className)}\n >\n <span data-kit=\"ai-source-index\" aria-hidden=\"true\">\n {index}\n </span>\n <div data-kit=\"ai-source-body\">\n {url ? (\n <a data-kit=\"ai-source-link\" href={url} target=\"_blank\" rel=\"noopener noreferrer\" dir=\"auto\">\n {source.title}\n <Icon name=\"external-link\" size={12} />\n <VisuallyHidden> ({messages.opensInNewTab})</VisuallyHidden>\n </a>\n ) : (\n <span data-kit=\"ai-source-link\" data-inert=\"\" dir=\"auto\">\n {source.title}\n <VisuallyHidden> ({messages.noLink})</VisuallyHidden>\n </span>\n )}\n {host ? (\n <span data-kit=\"ai-source-host\" dir=\"ltr\">\n {host}\n </span>\n ) : null}\n {source.snippet ? (\n <p data-kit=\"ai-source-snippet\" dir=\"auto\">\n {source.snippet}\n </p>\n ) : null}\n </div>\n </li>\n );\n}\n\nexport interface SourcesProps extends Omit<ComponentPropsWithRef<\"div\">, \"children\"> {\n /** Defaults to the sources of the surrounding `SourcesProvider`. */\n sources?: readonly SourcePart[] | undefined;\n open?: boolean | undefined;\n defaultOpen?: boolean | undefined;\n onOpenChange?: ((open: boolean) => void) | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\n/**\n * A collapsible, numbered list of sources. Citations in the message jump here:\n * the list opens and the cited source takes focus.\n */\nexport function Sources({ sources: sourcesProp, open, defaultOpen = false, onOpenChange, messages: override, className, ref, ...props }: SourcesProps) {\n const messages = useAiMessages(override);\n const context = useSourcesContext();\n const sources = sourcesProp ?? context?.sources ?? [];\n const ownId = useId();\n const baseId = context?.baseId ?? ownId;\n const disclosure = useDisclosure({ open, defaultOpen, onOpenChange });\n const [target, setTarget] = useState<{ index: number; nonce: number } | null>(null);\n const { setOpen } = disclosure;\n\n useEffect(() => {\n if (!context) return;\n return context.register((index) => {\n setOpen(true);\n setTarget((previous) => ({ index, nonce: (previous?.nonce ?? 0) + 1 }));\n });\n }, [context, setOpen]);\n\n // Once the list is open and rendered, move focus to the cited source.\n useEffect(() => {\n if (!target || !disclosure.open) return;\n const element = document.getElementById(sourceDomId(baseId, target.index));\n element?.focus();\n element?.scrollIntoView?.({ block: \"nearest\" });\n }, [target, disclosure.open, baseId]);\n\n if (sources.length === 0) return null;\n\n return (\n <div {...props} ref={ref} data-kit=\"ai-sources\" data-state={disclosure.open ? \"open\" : \"closed\"} className={cx(className)}>\n <button {...disclosure.triggerProps} data-kit=\"ai-sources-trigger\">\n <span>{messages.sources}</span>\n <Badge size=\"sm\" title={messages.sourcesCount(sources.length)}>\n {sources.length}\n </Badge>\n <Icon name={disclosure.open ? \"chevron-up\" : \"chevron-down\"} size={16} />\n </button>\n <div {...disclosure.panelProps} data-kit=\"ai-sources-panel\">\n {disclosure.open ? (\n <ol role=\"list\" data-kit=\"ai-sources-list\">\n {sources.map((source, position) => (\n <SourceCard\n key={source.id}\n source={source}\n index={position + 1}\n id={sourceDomId(baseId, position + 1)}\n messages={override}\n />\n ))}\n </ol>\n ) : null}\n </div>\n </div>\n );\n}\n","import { useId, type ButtonHTMLAttributes, type HTMLAttributes } from \"react\";\nimport { useControllableState } from \"./hooks\";\n\nexport interface UseDisclosureOptions {\n open?: boolean | undefined;\n defaultOpen?: boolean | undefined;\n onOpenChange?: ((open: boolean) => void) | undefined;\n}\n\nexport interface Disclosure {\n open: boolean;\n setOpen: (open: boolean) => void;\n toggle: () => void;\n /** Spread on the button that shows or hides the panel. */\n triggerProps: ButtonHTMLAttributes<HTMLButtonElement> & { \"data-state\": \"open\" | \"closed\" };\n /** Spread on the panel. It stays in the DOM when closed, so `aria-controls` is always valid. */\n panelProps: HTMLAttributes<HTMLDivElement> & { \"data-state\": \"open\" | \"closed\" };\n}\n\n/**\n * The WAI-ARIA disclosure pattern: a button with `aria-expanded` and\n * `aria-controls` that shows or hides a panel. Enter and Space (native button\n * behaviour) toggle it; there is no focus trap and no roving focus. Controlled\n * with `open`, or uncontrolled with `defaultOpen`.\n */\nexport function useDisclosure({ open, defaultOpen = false, onOpenChange }: UseDisclosureOptions = {}): Disclosure {\n const [current, setOpen] = useControllableState<boolean>({ value: open, defaultValue: defaultOpen, onChange: onOpenChange });\n const base = useId();\n const triggerId = `${base}-trigger`;\n const panelId = `${base}-panel`;\n const state = current ? \"open\" : \"closed\";\n\n return {\n open: current,\n setOpen,\n toggle: () => setOpen(!current),\n triggerProps: {\n id: triggerId,\n type: \"button\",\n \"aria-expanded\": current,\n \"aria-controls\": panelId,\n \"data-state\": state,\n onClick: () => setOpen(!current),\n },\n panelProps: {\n id: panelId,\n hidden: !current,\n \"data-state\": state,\n },\n };\n}\n","import { Icon } from \"@x12i/icons\";\nimport { Spinner } from \"@x12i/ui\";\nimport { useEffect, useRef, type ComponentPropsWithRef } from \"react\";\nimport { formatDuration } from \"../format\";\nimport { useDisclosure } from \"./internal/disclosure\";\nimport { cx } from \"./internal/cx\";\nimport { useControllableState } from \"./internal/hooks\";\nimport { SparklesGlyph } from \"./internal/glyphs\";\nimport { Markdown } from \"./markdown\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\n\nexport interface ReasoningProps extends Omit<ComponentPropsWithRef<\"div\">, \"children\"> {\n /** The model's reasoning text. Rendered as safe Markdown. */\n text: string;\n /** True while the reasoning is still arriving. The panel is open then, and collapses when it ends. */\n streaming?: boolean | undefined;\n /** How long the model thought, in milliseconds. Shown once it has finished. */\n durationMs?: number | undefined;\n open?: boolean | undefined;\n defaultOpen?: boolean | undefined;\n onOpenChange?: ((open: boolean) => void) | undefined;\n /** Locale used to format the duration. */\n locale?: string | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\n/**\n * A collapsible view of the model's reasoning. Open while it streams, then it\n * folds itself away (unless you opened or closed it yourself) so the answer\n * is what you see. The header reads \"Thinking…\" and then \"Thought for 4s\".\n */\nexport function Reasoning({\n text,\n streaming = false,\n durationMs,\n open: openProp,\n defaultOpen,\n onOpenChange,\n locale,\n messages: override,\n className,\n ref,\n ...props\n}: ReasoningProps) {\n const messages = useAiMessages(override);\n const [open, setOpen] = useControllableState<boolean>({\n value: openProp,\n defaultValue: defaultOpen ?? streaming,\n onChange: onOpenChange,\n });\n const userChoice = useRef(false);\n const wasStreaming = useRef(streaming);\n\n // Fold away when the reasoning ends, unless the user chose a state themselves.\n useEffect(() => {\n if (wasStreaming.current && !streaming && !userChoice.current) setOpen(false);\n if (!wasStreaming.current && streaming && !userChoice.current) setOpen(true);\n wasStreaming.current = streaming;\n }, [streaming, setOpen]);\n\n const disclosure = useDisclosure({\n open,\n onOpenChange: (next) => {\n userChoice.current = true;\n setOpen(next);\n },\n });\n\n const title = streaming\n ? messages.thinking\n : durationMs !== undefined\n ? messages.thoughtFor(formatDuration(durationMs, locale))\n : messages.thought;\n\n return (\n <div\n {...props}\n ref={ref}\n data-kit=\"ai-reasoning\"\n data-state={disclosure.open ? \"open\" : \"closed\"}\n data-streaming={streaming ? \"\" : undefined}\n className={cx(className)}\n >\n <button {...disclosure.triggerProps} data-kit=\"ai-reasoning-trigger\">\n {streaming ? <Spinner size=\"sm\" /> : <SparklesGlyph size=\"sm\" />}\n <span data-kit=\"ai-reasoning-title\">{title}</span>\n <Icon name={disclosure.open ? \"chevron-up\" : \"chevron-down\"} size={16} />\n </button>\n <div {...disclosure.panelProps} data-kit=\"ai-reasoning-panel\" aria-live=\"off\">\n {disclosure.open ? (\n <Markdown streaming={streaming} headingOffset={3} messages={override} images=\"none\" citations={false}>\n {text}\n </Markdown>\n ) : null}\n </div>\n </div>\n );\n}\n","import { VisuallyHidden } from \"@x12i/ui\";\nimport type { ComponentPropsWithRef } from \"react\";\nimport { cx } from \"./internal/cx\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\n\nexport interface StreamingIndicatorProps extends Omit<ComponentPropsWithRef<\"span\">, \"children\"> {\n /** Replaces the spoken label. Defaults to `messages.thinkingIndicator`. */\n label?: string | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\n/**\n * Three pulsing dots that show the assistant is working. The motion is CSS\n * and stops under `prefers-reduced-motion`, leaving three still dots. The\n * label is visually hidden and not live: the thread announces progress itself.\n */\nexport function StreamingIndicator({ label, messages: override, className, ref, ...props }: StreamingIndicatorProps) {\n const messages = useAiMessages(override);\n return (\n <span {...props} ref={ref} data-kit=\"ai-streaming-indicator\" className={cx(className)}>\n <span data-kit=\"ai-streaming-dot\" aria-hidden=\"true\" />\n <span data-kit=\"ai-streaming-dot\" aria-hidden=\"true\" />\n <span data-kit=\"ai-streaming-dot\" aria-hidden=\"true\" />\n <VisuallyHidden>{label ?? messages.thinkingIndicator}</VisuallyHidden>\n </span>\n );\n}\n","import { Icon } from \"@x12i/icons\";\nimport { Badge, Spinner, VisuallyHidden, type BadgeTone } from \"@x12i/ui\";\nimport type { ComponentPropsWithRef, ReactNode } from \"react\";\nimport { formatDuration } from \"../format\";\nimport type { ToolPart, ToolState } from \"../types\";\nimport { ApprovalPrompt } from \"./approval-prompt\";\nimport { useDisclosure } from \"./internal/disclosure\";\nimport { cx } from \"./internal/cx\";\nimport { WrenchGlyph } from \"./internal/glyphs\";\nimport { JsonView } from \"./internal/json-view\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\n\nconst STATE_TONE: Record<ToolState, BadgeTone> = {\n queued: \"neutral\",\n running: \"info\",\n \"needs-approval\": \"warning\",\n approved: \"accent\",\n denied: \"danger\",\n succeeded: \"success\",\n failed: \"danger\",\n};\n\nexport interface ToolCallProps extends Omit<ComponentPropsWithRef<\"div\">, \"children\" | \"part\"> {\n /** The tool part to show. (Shadows the unrelated HTML `part` attribute.) */\n part: ToolPart;\n open?: boolean | undefined;\n defaultOpen?: boolean | undefined;\n onOpenChange?: ((open: boolean) => void) | undefined;\n /**\n * Called when the user decides on a call that needs approval. Without it, the\n * approval buttons are not shown: the call is only displayed.\n */\n onDecision?: ((callId: string, decision: \"approve\" | \"deny\", reason?: string) => void) | undefined;\n /** Replaces the JSON view of the input, for example with a table or a chart. */\n renderInput?: ((input: unknown, part: ToolPart) => ReactNode) | undefined;\n /** Replaces the JSON view of the output. */\n renderOutput?: ((output: unknown, part: ToolPart) => ReactNode) | undefined;\n locale?: string | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\n/**\n * Shows what the assistant is doing: the tool's name, its state as a badge,\n * how long it took, and (collapsed by default) its input and output as JSON.\n * A call that needs approval shows an `ApprovalPrompt` that stays visible even\n * when the details are folded, so a decision can never be hidden.\n */\nexport function ToolCall({\n part,\n open,\n defaultOpen = false,\n onOpenChange,\n onDecision,\n renderInput,\n renderOutput,\n locale,\n messages: override,\n className,\n ref,\n ...props\n}: ToolCallProps) {\n const messages = useAiMessages(override);\n const disclosure = useDisclosure({ open, defaultOpen, onOpenChange });\n const aborted = part.state === \"failed\" && part.errorCode === \"aborted\";\n const hasInput = part.input !== undefined;\n const hasOutput = part.output !== undefined;\n const failedMessage = part.state === \"failed\" ? (aborted ? messages.toolAborted : part.error) : undefined;\n const live = part.state === \"running\" || part.state === \"queued\";\n const needsDecision = part.state === \"needs-approval\" && onDecision !== undefined;\n\n return (\n <div\n {...props}\n ref={ref}\n role=\"group\"\n aria-label={messages.toolCall(part.name)}\n data-kit=\"ai-tool-call\"\n data-state={part.state}\n data-open={disclosure.open ? \"\" : undefined}\n className={cx(className)}\n >\n <button {...disclosure.triggerProps} data-kit=\"ai-tool-call-trigger\">\n <WrenchGlyph size=\"sm\" />\n <span data-kit=\"ai-tool-call-name\" dir=\"ltr\">\n {part.name}\n </span>\n <Badge tone={STATE_TONE[part.state]} size=\"sm\">\n {live ? <Spinner size=\"xs\" /> : null}\n {messages.toolStates[part.state]}\n </Badge>\n {part.durationMs !== undefined ? (\n <span data-kit=\"ai-tool-call-duration\">{formatDuration(part.durationMs, locale)}</span>\n ) : null}\n <Icon name={disclosure.open ? \"chevron-up\" : \"chevron-down\"} size={16} />\n </button>\n\n {failedMessage ? (\n <p data-kit=\"ai-tool-call-error\" data-aborted={aborted ? \"\" : undefined} dir=\"auto\">\n <VisuallyHidden>{messages.toolError}: </VisuallyHidden>\n {failedMessage}\n </p>\n ) : null}\n\n {needsDecision ? (\n <ApprovalPrompt\n toolName={part.name}\n input={part.input}\n prompt={part.approval?.prompt}\n renderInput={renderInput ? (input) => renderInput(input, part) : undefined}\n messages={override}\n onApprove={(reason) => onDecision?.(part.id, \"approve\", reason)}\n onDeny={(reason) => onDecision?.(part.id, \"deny\", reason)}\n />\n ) : null}\n\n {part.state === \"denied\" && part.approval?.reason ? (\n <p data-kit=\"ai-tool-call-note\" dir=\"auto\">\n {part.approval.reason}\n </p>\n ) : null}\n\n <div {...disclosure.panelProps} data-kit=\"ai-tool-call-panel\">\n {disclosure.open ? (\n <>\n {hasInput ? (\n renderInput ? (\n renderInput(part.input, part)\n ) : (\n <JsonView value={part.input} label={messages.toolInput} messages={override} />\n )\n ) : (\n <p data-kit=\"ai-tool-call-empty\">{messages.noInput}</p>\n )}\n {hasOutput ? (\n renderOutput ? (\n renderOutput(part.output, part)\n ) : (\n <JsonView value={part.output} label={messages.toolOutput} messages={override} />\n )\n ) : part.state === \"succeeded\" ? (\n <p data-kit=\"ai-tool-call-empty\">{messages.noOutput}</p>\n ) : null}\n </>\n ) : null}\n </div>\n </div>\n );\n}\n","import { Button } from \"@x12i/ui\";\nimport {\n useId,\n useLayoutEffect,\n useRef,\n type ComponentPropsWithRef,\n type ReactNode,\n type RefObject,\n} from \"react\";\nimport { cx } from \"./internal/cx\";\nimport { JsonView } from \"./internal/json-view\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\n\nexport interface ApprovalPromptProps\n extends Omit<ComponentPropsWithRef<\"div\">, \"children\" | \"title\" | \"prompt\"> {\n /** The tool that wants to run. Shown as it is. */\n toolName: string;\n /** The exact arguments the tool will run with. Shown in full so the decision is informed. */\n input?: unknown;\n /** Why approval is needed, from the model or your policy. Falls back to a generic sentence. */\n prompt?: string | undefined;\n /** Called when the user approves. `reason` is the optional note they typed. */\n onApprove: (reason?: string) => void;\n /** Called when the user denies. `reason` is the optional note they typed. */\n onDeny: (reason?: string) => void;\n /**\n * Move focus to the prompt when it appears, so a keyboard or screen-reader\n * user notices it. It never focuses a button, so Enter cannot approve by\n * accident. Skipped when focus is somewhere else on the page. Default true.\n */\n autoFocus?: boolean | undefined;\n /** Where focus goes after a decision. Defaults to what was focused before, then the chat's prompt box. */\n returnFocusTo?: RefObject<HTMLElement | null> | (() => HTMLElement | null | undefined) | undefined;\n /** Show the optional \"reason\" field. Default true. */\n allowReason?: boolean | undefined;\n /** Replaces the JSON view of the input, for example with a form-like summary. */\n renderInput?: ((input: unknown) => ReactNode) | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\nconst THREAD_SELECTOR = '[data-kit=\"ai-chat-thread\"]';\nconst CONVERSATION_SELECTOR = '[data-kit=\"ai-conversation\"]';\n\n/** The widest chat container around `element`: the whole thread (prompt box included), else just the message list. */\nfunction findScope(element: HTMLElement): Element | null {\n return element.closest(THREAD_SELECTOR) ?? element.closest(CONVERSATION_SELECTOR);\n}\n\n/**\n * Asks the user to allow or refuse an action. It is a non-modal group, not a\n * dialog: nothing is blocked and there is no focus trap. It never decides on\n * its own, and the buttons are the only way to answer.\n *\n * When it appears, focus moves to the prompt itself (not to a button). After\n * a decision, focus returns to where it was.\n */\nexport function ApprovalPrompt({\n toolName,\n input,\n prompt,\n onApprove,\n onDeny,\n autoFocus = true,\n returnFocusTo,\n allowReason = true,\n renderInput,\n messages: override,\n className,\n ref,\n ...props\n}: ApprovalPromptProps) {\n const messages = useAiMessages(override);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const reasonRef = useRef<HTMLInputElement>(null);\n const previousFocus = useRef<HTMLElement | null>(null);\n const titleId = useId();\n const descriptionId = useId();\n const reasonId = useId();\n\n useLayoutEffect(() => {\n const root = rootRef.current;\n if (!root || !autoFocus) return;\n const active = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n const scope = findScope(root);\n // Do not pull focus away from an unrelated part of the page.\n const unrelated = active !== null && active !== document.body && scope !== null && !scope.contains(active);\n if (unrelated) return;\n previousFocus.current = active !== null && active !== document.body && !root.contains(active) ? active : null;\n root.focus();\n // Only on first render: the prompt keeps focus management out of later updates.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const restoreFocus = () => {\n const root = rootRef.current;\n const explicit = typeof returnFocusTo === \"function\" ? returnFocusTo() : returnFocusTo?.current;\n const fallback = root?.closest(THREAD_SELECTOR)?.querySelector<HTMLElement>('[data-kit=\"ai-prompt-textarea\"]') ?? null;\n const target = [explicit, previousFocus.current, fallback].find(\n (element): element is HTMLElement => element instanceof HTMLElement && element.isConnected && !root?.contains(element),\n );\n target?.focus();\n };\n\n const decide = (decision: \"approve\" | \"deny\") => {\n const reason = reasonRef.current?.value.trim();\n const value = reason === \"\" ? undefined : reason;\n if (decision === \"approve\") onApprove(value);\n else onDeny(value);\n restoreFocus();\n };\n\n return (\n <div\n {...props}\n ref={(node) => {\n rootRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }}\n role=\"group\"\n tabIndex={-1}\n aria-labelledby={titleId}\n aria-describedby={descriptionId}\n data-kit=\"ai-approval-prompt\"\n className={cx(className)}\n >\n <p data-kit=\"ai-approval-title\" id={titleId} dir=\"auto\">\n {messages.approvalTitle(toolName)}\n </p>\n <p data-kit=\"ai-approval-description\" id={descriptionId} dir=\"auto\">\n {prompt ?? messages.approvalDescription}\n </p>\n\n <div data-kit=\"ai-approval-action\">\n {renderInput ? (\n renderInput(input)\n ) : input === undefined ? (\n <p data-kit=\"ai-approval-no-input\">{messages.noInput}</p>\n ) : (\n <JsonView value={input} label={messages.approvalAction} messages={override} />\n )}\n </div>\n\n {allowReason ? (\n <div data-kit=\"ai-approval-reason\">\n <label htmlFor={reasonId}>{messages.reasonLabel}</label>\n <input\n ref={reasonRef}\n id={reasonId}\n type=\"text\"\n dir=\"auto\"\n autoComplete=\"off\"\n placeholder={messages.reasonPlaceholder}\n />\n </div>\n ) : null}\n\n <div data-kit=\"ai-approval-buttons\">\n <Button variant=\"solid\" tone=\"accent\" size=\"sm\" aria-label={messages.approveLabel(toolName)} onClick={() => decide(\"approve\")}>\n {messages.approve}\n </Button>\n <Button variant=\"outline\" tone=\"neutral\" size=\"sm\" aria-label={messages.denyLabel(toolName)} onClick={() => decide(\"deny\")}>\n {messages.deny}\n </Button>\n </div>\n </div>\n );\n}\n","import { Icon } from \"@x12i/icons\";\nimport { IconButton, Inline, VisuallyHidden } from \"@x12i/ui\";\nimport type { ComponentPropsWithRef, ReactNode } from \"react\";\nimport { cx } from \"./internal/cx\";\nimport { CopyButton } from \"./internal/copy-button\";\nimport {\n BranchNextGlyph,\n BranchPrevGlyph,\n RefreshGlyph,\n ThumbsDownGlyph,\n ThumbsUpGlyph,\n} from \"./internal/glyphs\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\n\nexport type Feedback = \"up\" | \"down\";\n\nexport interface MessageBranchControl {\n /** The shown version, from 0. */\n index: number;\n /** How many versions exist. The control is hidden when there is only one. */\n count: number;\n onSelect: (index: number) => void;\n}\n\nexport interface MessageActionsProps extends Omit<ComponentPropsWithRef<\"div\">, \"children\"> {\n /** The text the copy button copies. Without it there is no copy button. */\n text?: string | undefined;\n onCopied?: ((text: string) => void) | undefined;\n /** Shows a regenerate button. */\n onRegenerate?: (() => void) | undefined;\n /** Shows an edit button (for user messages). */\n onEdit?: (() => void) | undefined;\n /** The current rating. `null` or omitted means none. */\n feedback?: Feedback | null | undefined;\n /** Shows thumbs buttons. Called with the new rating, or `null` when it is withdrawn. */\n onFeedback?: ((feedback: Feedback | null) => void) | undefined;\n /** Previous / next version controls for an edited or regenerated message. */\n branch?: MessageBranchControl | undefined;\n /** Disables regenerate, edit and branch changes, for example while a reply is streaming. */\n disabled?: boolean | undefined;\n /** Your own actions, after the built-in ones. */\n children?: ReactNode;\n messages?: AiMessagesOverride | undefined;\n}\n\n/**\n * The actions under a message: copy, regenerate, edit, thumbs up and down,\n * and version navigation. Every control is a labelled button; the thumbs are\n * toggle buttons (`aria-pressed`). The copy result is announced politely.\n */\nexport function MessageActions({\n text,\n onCopied,\n onRegenerate,\n onEdit,\n feedback = null,\n onFeedback,\n branch,\n disabled = false,\n children,\n messages: override,\n className,\n ref,\n ...props\n}: MessageActionsProps) {\n const messages = useAiMessages(override);\n\n return (\n <div\n {...props}\n ref={ref}\n role=\"group\"\n aria-label={messages.actions}\n data-kit=\"ai-message-actions\"\n className={cx(className)}\n >\n <Inline gap=\"1\" align=\"center\">\n {branch && branch.count > 1 ? (\n <span data-kit=\"ai-branch-nav\">\n <IconButton\n variant=\"ghost\"\n tone=\"neutral\"\n size=\"sm\"\n label={messages.previousVersion}\n disabled={disabled || branch.index <= 0}\n onClick={() => branch.onSelect(branch.index - 1)}\n >\n <BranchPrevGlyph size=\"sm\" data-flip=\"\" />\n </IconButton>\n <span data-kit=\"ai-branch-position\" dir=\"ltr\">\n <VisuallyHidden>{messages.versionLabel(branch.index + 1, branch.count)}</VisuallyHidden>\n <span aria-hidden=\"true\">\n {branch.index + 1}/{branch.count}\n </span>\n </span>\n <IconButton\n variant=\"ghost\"\n tone=\"neutral\"\n size=\"sm\"\n label={messages.nextVersion}\n disabled={disabled || branch.index >= branch.count - 1}\n onClick={() => branch.onSelect(branch.index + 1)}\n >\n <BranchNextGlyph size=\"sm\" data-flip=\"\" />\n </IconButton>\n </span>\n ) : null}\n\n {text !== undefined ? (\n <CopyButton\n text={text}\n label={messages.copy}\n copiedLabel={messages.copied}\n failedLabel={messages.copyFailed}\n onCopied={onCopied}\n />\n ) : null}\n\n {onEdit ? (\n <IconButton variant=\"ghost\" tone=\"neutral\" size=\"sm\" label={messages.edit} disabled={disabled} onClick={onEdit}>\n <Icon name=\"edit\" size={16} />\n </IconButton>\n ) : null}\n\n {onRegenerate ? (\n <IconButton variant=\"ghost\" tone=\"neutral\" size=\"sm\" label={messages.regenerate} disabled={disabled} onClick={onRegenerate}>\n <RefreshGlyph size=\"sm\" />\n </IconButton>\n ) : null}\n\n {onFeedback ? (\n <>\n <IconButton\n variant=\"ghost\"\n tone=\"neutral\"\n size=\"sm\"\n label={messages.goodResponse}\n aria-pressed={feedback === \"up\"}\n onClick={() => onFeedback(feedback === \"up\" ? null : \"up\")}\n >\n <ThumbsUpGlyph size=\"sm\" filled={feedback === \"up\"} />\n </IconButton>\n <IconButton\n variant=\"ghost\"\n tone=\"neutral\"\n size=\"sm\"\n label={messages.badResponse}\n aria-pressed={feedback === \"down\"}\n onClick={() => onFeedback(feedback === \"down\" ? null : \"down\")}\n >\n <ThumbsDownGlyph size=\"sm\" filled={feedback === \"down\"} />\n </IconButton>\n </>\n ) : null}\n\n {children}\n </Inline>\n </div>\n );\n}\n","import { Icon } from \"@x12i/icons\";\nimport { IconButton, Spinner, VisuallyHidden } from \"@x12i/ui\";\nimport {\n useCallback,\n useId,\n useRef,\n useState,\n type ChangeEvent,\n type ClipboardEvent,\n type ComponentPropsWithRef,\n type CSSProperties,\n type DragEvent,\n type FormEvent,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { formatBytes } from \"../format\";\nimport type { ThreadStatus } from \"../thread-state\";\nimport { cx } from \"./internal/cx\";\nimport { FileGlyph, PaperclipGlyph, SendGlyph, StopGlyph } from \"./internal/glyphs\";\nimport { useControllableState } from \"./internal/hooks\";\nimport { useAutosize } from \"./internal/use-autosize\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\n\n/** A file waiting to be sent with the next message. */\nexport interface PromptAttachment {\n id: string;\n name: string;\n size?: number | undefined;\n mediaType?: string | undefined;\n /** `uploading` blocks sending; `error` shows a failure on the chip. Default `ready`. */\n status?: \"ready\" | \"uploading\" | \"error\" | undefined;\n /** The file itself, set when `PromptInput` collected it (uncontrolled attachments). */\n file?: File | undefined;\n}\n\n/** A command the user can pick by typing `/` in the prompt. */\nexport interface SlashCommand {\n id?: string;\n /** The text after the slash, such as `summarize` for `/summarize`. */\n name: string;\n description?: string | undefined;\n}\n\nexport interface PromptInputProps extends Omit<ComponentPropsWithRef<\"form\">, \"onSubmit\" | \"children\" | \"onChange\"> {\n /** Called with the trimmed text and the attachments when the user sends. */\n onSubmit: (text: string, attachments: readonly PromptAttachment[]) => void;\n /** Controlled text. Clear it yourself in `onSubmit`. */\n value?: string | undefined;\n defaultValue?: string | undefined;\n onValueChange?: ((value: string) => void) | undefined;\n /**\n * The conversation's state. While `submitted` or `streaming` the send button\n * becomes a stop button and Enter does nothing.\n */\n status?: ThreadStatus | undefined;\n /** Called by the stop button, and by Escape when `stopOnEscape` is true. */\n onStop?: (() => void) | undefined;\n disabled?: boolean | undefined;\n placeholder?: string | undefined;\n /** Hard limit; the counter shows `n / max`. */\n maxLength?: number | undefined;\n /** Smallest height in lines. Default 1. */\n minRows?: number | undefined;\n /** The height at which the box stops growing and scrolls. Default 8 lines. */\n maxRows?: number | undefined;\n /** Enter sends and Shift+Enter adds a line. When false, Ctrl or Cmd+Enter sends. Default true. */\n submitOnEnter?: boolean | undefined;\n /** Escape stops a running reply. Default true. */\n stopOnEscape?: boolean | undefined;\n autoFocus?: boolean | undefined;\n /** Attachments, controlled. Leave it out and `PromptInput` keeps the files itself. */\n attachments?: readonly PromptAttachment[] | undefined;\n onRemoveAttachment?: ((id: string) => void) | undefined;\n /** Called with files from the attach button, a paste or a drop. Providing it turns on all three. */\n onFiles?: ((files: File[]) => void) | undefined;\n /**\n * Show the attach button and accept pasted and dropped files. Defaults to true\n * when `onFiles` or `attachments` is given. With `allowFiles` alone, `PromptInput`\n * keeps the chosen files itself and hands them to `onSubmit` as `attachments[].file`.\n */\n allowFiles?: boolean | undefined;\n /** The `accept` list of the file picker, for example `image/*,.pdf`. */\n accept?: string | undefined;\n /** Most files per message. */\n maxFiles?: number | undefined;\n /** Commands offered after typing `/` at the start. */\n slashCommands?: readonly SlashCommand[] | undefined;\n /** Called when a command is picked. By default, it inserts `/name ` into the text. */\n onCommandSelect?: ((command: SlashCommand) => void) | undefined;\n /** Content under the box, such as a disclaimer. */\n footer?: ReactNode;\n /** A ref to the textarea. */\n textareaRef?: Ref<HTMLTextAreaElement> | undefined;\n locale?: string | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\nlet attachmentCounter = 0;\n\nfunction matchCommands(commands: readonly SlashCommand[], query: string): SlashCommand[] {\n const needle = query.toLowerCase();\n const starts: SlashCommand[] = [];\n const contains: SlashCommand[] = [];\n for (const command of commands) {\n const name = command.name.toLowerCase();\n if (name.startsWith(needle)) starts.push(command);\n else if (needle !== \"\" && (name.includes(needle) || (command.description ?? \"\").toLowerCase().includes(needle))) contains.push(command);\n }\n return [...starts, ...contains];\n}\n\n/**\n * The message box. It grows with the text up to `maxRows`, sends on Enter\n * (Shift+Enter adds a line, and Enter during IME composition never sends),\n * turns the send button into a stop button while a reply runs, and supports\n * attachments (button, paste, drop), a character counter and `/` commands.\n *\n * Accessibility: the textarea has an accessible name; the button's name says\n * what it does now (\"Send message\" or \"Stop generating\"); nothing steals focus;\n * the command list is announced and navigated with the arrow keys, with focus\n * staying in the textarea.\n */\nexport function PromptInput({\n onSubmit,\n value: valueProp,\n defaultValue = \"\",\n onValueChange,\n status = \"idle\",\n onStop,\n disabled = false,\n placeholder,\n maxLength,\n minRows = 1,\n maxRows = 8,\n submitOnEnter = true,\n stopOnEscape = true,\n autoFocus,\n attachments: attachmentsProp,\n onRemoveAttachment,\n onFiles,\n allowFiles,\n accept,\n maxFiles,\n slashCommands,\n onCommandSelect,\n footer,\n textareaRef: textareaRefProp,\n locale,\n messages: override,\n className,\n style,\n ref,\n ...props\n}: PromptInputProps) {\n const messages = useAiMessages(override);\n const [value, setValue] = useControllableState<string>({ value: valueProp, defaultValue, onChange: onValueChange });\n const [ownAttachments, setOwnAttachments] = useState<PromptAttachment[]>([]);\n const attachments: readonly PromptAttachment[] = attachmentsProp ?? ownAttachments;\n const [dragging, setDragging] = useState(false);\n const [commandIndex, setCommandIndex] = useState(0);\n const [dismissedFor, setDismissedFor] = useState<string | null>(null);\n\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const composing = useRef(false);\n const dragDepth = useRef(0);\n const counterId = useId();\n const listId = useId();\n const optionIdBase = useId();\n\n const busy = status === \"submitted\" || status === \"streaming\";\n const filesEnabled = allowFiles ?? (onFiles !== undefined || attachmentsProp !== undefined);\n const filesFull = maxFiles !== undefined && attachments.length >= maxFiles;\n const uploading = attachments.some((attachment) => attachment.status === \"uploading\");\n const trimmed = value.trim();\n const canSend = !disabled && !busy && !uploading && (trimmed !== \"\" || attachments.length > 0);\n\n useAutosize(textareaRef, value);\n\n const setTextareaRef = useCallback(\n (node: HTMLTextAreaElement | null) => {\n textareaRef.current = node;\n if (typeof textareaRefProp === \"function\") textareaRefProp(node);\n else if (textareaRefProp) textareaRefProp.current = node;\n },\n [textareaRefProp],\n );\n\n // ----- Slash commands -----\n const slashMatch = /^\\/([^\\s]*)$/.exec(value);\n const matches = slashCommands && slashMatch ? matchCommands(slashCommands, slashMatch[1] ?? \"\") : [];\n const commandsOpen = !disabled && matches.length > 0 && dismissedFor !== value;\n const activeIndex = Math.min(commandIndex, Math.max(0, matches.length - 1));\n const activeCommand = commandsOpen ? matches[activeIndex] : undefined;\n const optionId = (index: number) => `${optionIdBase}-option-${index}`;\n\n const pickCommand = (command: SlashCommand) => {\n if (onCommandSelect) onCommandSelect(command);\n else {\n setValue(`/${command.name} `);\n }\n setCommandIndex(0);\n textareaRef.current?.focus();\n };\n\n // ----- Files -----\n const addFiles = (incoming: readonly File[]) => {\n if (!filesEnabled || incoming.length === 0 || disabled) return;\n const room = maxFiles === undefined ? incoming.length : Math.max(0, maxFiles - attachments.length);\n const accepted = incoming.slice(0, room);\n if (accepted.length === 0) return;\n if (attachmentsProp === undefined) {\n setOwnAttachments((current) => [\n ...current,\n ...accepted.map((file): PromptAttachment => {\n attachmentCounter += 1;\n return { id: `file-${attachmentCounter}`, name: file.name, size: file.size, mediaType: file.type, status: \"ready\", file };\n }),\n ]);\n }\n onFiles?.([...accepted]);\n };\n\n const removeAttachment = (id: string) => {\n if (attachmentsProp === undefined) setOwnAttachments((current) => current.filter((attachment) => attachment.id !== id));\n onRemoveAttachment?.(id);\n // The removed chip took focus with it; hand it back to the text box.\n textareaRef.current?.focus();\n };\n\n // ----- Sending -----\n const submit = () => {\n if (!canSend) return;\n onSubmit(trimmed, attachments);\n if (valueProp === undefined) setValue(\"\");\n if (attachmentsProp === undefined) setOwnAttachments([]);\n };\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (busy) onStop?.();\n else submit();\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n const imeActive = composing.current || event.nativeEvent.isComposing || event.keyCode === 229;\n\n if (commandsOpen && !imeActive) {\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n setCommandIndex((activeIndex + 1) % matches.length);\n return;\n }\n if (event.key === \"ArrowUp\") {\n event.preventDefault();\n setCommandIndex((activeIndex - 1 + matches.length) % matches.length);\n return;\n }\n if (!event.shiftKey && (event.key === \"Enter\" || event.key === \"Tab\")) {\n const command = matches[activeIndex];\n if (command) {\n event.preventDefault();\n pickCommand(command);\n return;\n }\n }\n if (event.key === \"Escape\") {\n event.preventDefault();\n setDismissedFor(value);\n return;\n }\n }\n\n if (event.key === \"Escape\" && stopOnEscape && busy && onStop && !imeActive) {\n event.preventDefault();\n onStop();\n return;\n }\n\n if (event.key !== \"Enter\" || imeActive) return;\n const modifier = event.ctrlKey || event.metaKey;\n const wantsSend = submitOnEnter ? !event.shiftKey : modifier;\n if (!wantsSend) return;\n event.preventDefault();\n submit();\n };\n\n const handlePaste = (event: ClipboardEvent<HTMLTextAreaElement>) => {\n if (!filesEnabled) return;\n const files = Array.from(event.clipboardData.files);\n if (files.length === 0) return;\n // Text wins: a spreadsheet cell copies as both text and an image of itself.\n if (event.clipboardData.getData(\"text\") !== \"\") return;\n event.preventDefault();\n addFiles(files);\n };\n\n const hasFiles = (event: DragEvent) => Array.from(event.dataTransfer.types).includes(\"Files\");\n\n const handleDragEnter = (event: DragEvent<HTMLFormElement>) => {\n if (!filesEnabled || !hasFiles(event)) return;\n event.preventDefault();\n dragDepth.current += 1;\n setDragging(true);\n };\n\n const handleDragOver = (event: DragEvent<HTMLFormElement>) => {\n if (!filesEnabled || !hasFiles(event)) return;\n event.preventDefault();\n };\n\n const handleDragLeave = (event: DragEvent<HTMLFormElement>) => {\n if (!filesEnabled || !hasFiles(event)) return;\n dragDepth.current = Math.max(0, dragDepth.current - 1);\n if (dragDepth.current === 0) setDragging(false);\n };\n\n const handleDrop = (event: DragEvent<HTMLFormElement>) => {\n if (!filesEnabled || !hasFiles(event)) return;\n event.preventDefault();\n dragDepth.current = 0;\n setDragging(false);\n addFiles(Array.from(event.dataTransfer.files));\n };\n\n const handleFileInput = (event: ChangeEvent<HTMLInputElement>) => {\n addFiles(Array.from(event.target.files ?? []));\n event.target.value = \"\";\n textareaRef.current?.focus();\n };\n\n const atLimit = maxLength !== undefined && value.length >= maxLength;\n const announcement = commandsOpen\n ? messages.commandsAvailable(matches.length)\n : atLimit\n ? messages.characterLimitReached\n : \"\";\n\n const rowStyle = { ...style, \"--_ai-max-rows\": maxRows } as CSSProperties;\n\n return (\n <form\n {...props}\n ref={ref}\n noValidate\n data-kit=\"ai-prompt-input\"\n data-busy={busy ? \"\" : undefined}\n data-disabled={disabled ? \"\" : undefined}\n data-dragging={dragging ? \"\" : undefined}\n className={cx(className)}\n style={rowStyle}\n onSubmit={handleSubmit}\n onDragEnter={handleDragEnter}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {attachments.length > 0 ? (\n <ul role=\"list\" aria-label={messages.attachments} data-kit=\"ai-prompt-attachments\">\n {attachments.map((attachment) => (\n <li key={attachment.id} data-kit=\"ai-prompt-attachment\" data-status={attachment.status ?? \"ready\"}>\n <FileGlyph size=\"sm\" />\n <span data-kit=\"ai-prompt-attachment-name\" dir=\"auto\">\n {attachment.name}\n </span>\n {attachment.size !== undefined ? (\n <span data-kit=\"ai-prompt-attachment-size\">{formatBytes(attachment.size, locale)}</span>\n ) : null}\n {attachment.status === \"uploading\" ? (\n <span data-kit=\"ai-prompt-attachment-status\">\n <Spinner size=\"xs\" />\n <VisuallyHidden>{messages.attachmentUploading}</VisuallyHidden>\n </span>\n ) : null}\n {attachment.status === \"error\" ? (\n <span data-kit=\"ai-prompt-attachment-status\">{messages.attachmentFailed}</span>\n ) : null}\n <IconButton\n variant=\"ghost\"\n tone=\"neutral\"\n size=\"xs\"\n label={messages.removeAttachment(attachment.name)}\n onClick={() => removeAttachment(attachment.id)}\n >\n <Icon name=\"close\" size={12} />\n </IconButton>\n </li>\n ))}\n </ul>\n ) : null}\n\n <div data-kit=\"ai-prompt-row\">\n {filesEnabled ? (\n <>\n <IconButton\n variant=\"ghost\"\n tone=\"neutral\"\n size=\"md\"\n label={messages.attach}\n disabled={disabled || filesFull}\n onClick={() => fileInputRef.current?.click()}\n >\n <PaperclipGlyph size=\"md\" />\n </IconButton>\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n hidden\n tabIndex={-1}\n aria-hidden=\"true\"\n accept={accept}\n onChange={handleFileInput}\n />\n </>\n ) : null}\n\n <textarea\n ref={setTextareaRef}\n data-kit=\"ai-prompt-textarea\"\n dir=\"auto\"\n rows={minRows}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n autoFocus={autoFocus}\n placeholder={placeholder ?? messages.promptPlaceholder}\n aria-label={messages.promptLabel}\n aria-describedby={maxLength !== undefined ? counterId : undefined}\n aria-autocomplete={slashCommands ? \"list\" : undefined}\n aria-controls={commandsOpen ? listId : undefined}\n aria-activedescendant={activeCommand ? optionId(activeIndex) : undefined}\n onChange={(event) => {\n setValue(event.target.value);\n setCommandIndex(0);\n }}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n onCompositionStart={() => {\n composing.current = true;\n }}\n onCompositionEnd={() => {\n composing.current = false;\n }}\n />\n\n <IconButton\n variant=\"solid\"\n tone={busy ? \"neutral\" : \"accent\"}\n size=\"md\"\n // The same button is send and stop, so focus never jumps when a reply starts.\n type={busy ? \"button\" : \"submit\"}\n label={busy ? messages.stop : messages.send}\n data-mode={busy ? \"stop\" : \"send\"}\n disabled={busy ? onStop === undefined : !canSend}\n onClick={busy ? onStop : undefined}\n >\n {busy ? <StopGlyph size=\"md\" /> : <SendGlyph size=\"md\" />}\n </IconButton>\n </div>\n\n {commandsOpen ? (\n <ul role=\"listbox\" id={listId} aria-label={messages.commands} data-kit=\"ai-prompt-commands\">\n {matches.map((command, index) => (\n <li\n key={command.id ?? command.name}\n id={optionId(index)}\n role=\"option\"\n aria-selected={index === activeIndex}\n data-active={index === activeIndex ? \"\" : undefined}\n onMouseDown={(event) => {\n // Keep focus in the textarea.\n event.preventDefault();\n }}\n onClick={() => pickCommand(command)}\n >\n <span data-kit=\"ai-prompt-command-name\" dir=\"ltr\">\n /{command.name}\n </span>\n {command.description ? (\n <span data-kit=\"ai-prompt-command-description\" dir=\"auto\">\n {command.description}\n </span>\n ) : null}\n </li>\n ))}\n </ul>\n ) : null}\n\n {maxLength !== undefined || footer ? (\n <div data-kit=\"ai-prompt-meta\">\n {footer ? <div data-kit=\"ai-prompt-footer\">{footer}</div> : null}\n {maxLength !== undefined ? (\n <span id={counterId} data-kit=\"ai-prompt-counter\" data-limit={atLimit ? \"\" : undefined} dir=\"ltr\">\n {messages.characterCount(value.length, maxLength)}\n </span>\n ) : null}\n </div>\n ) : null}\n\n <VisuallyHidden role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {announcement}\n </VisuallyHidden>\n\n {dragging ? (\n <div data-kit=\"ai-prompt-drop\" aria-hidden=\"true\">\n {messages.dropFiles}\n </div>\n ) : null}\n </form>\n );\n}\n","import { Button } from \"@x12i/ui\";\nimport type { ComponentPropsWithRef } from \"react\";\nimport { cx } from \"./internal/cx\";\nimport type { AiMessagesOverride } from \"./messages\";\nimport { useAiMessages } from \"./messages-context\";\n\n/** A suggestion is a string (shown and sent as it is), or a short label with a longer prompt behind it. */\nexport type Suggestion = string | { id?: string; label: string; prompt?: string };\n\nexport interface SuggestionsProps extends Omit<ComponentPropsWithRef<\"div\">, \"children\" | \"onSelect\"> {\n suggestions: readonly Suggestion[];\n /** Called with the text to send (the suggestion's `prompt`, or its label). */\n onSelect: (prompt: string, suggestion: Suggestion) => void;\n disabled?: boolean | undefined;\n messages?: AiMessagesOverride | undefined;\n}\n\nfunction labelOf(suggestion: Suggestion): string {\n return typeof suggestion === \"string\" ? suggestion : suggestion.label;\n}\n\n/** A row of follow-up or starter prompts. Each is a button; picking one is the same as sending that text. */\nexport function Suggestions({ suggestions, onSelect, disabled = false, messages: override, className, ref, ...props }: SuggestionsProps) {\n const messages = useAiMessages(override);\n if (suggestions.length === 0) return null;\n\n return (\n <div {...props} ref={ref} data-kit=\"ai-suggestions\" className={cx(className)}>\n <ul role=\"list\" aria-label={messages.suggestions}>\n {suggestions.map((suggestion, position) => {\n const label = labelOf(suggestion);\n const prompt = typeof suggestion === \"string\" ? suggestion : (suggestion.prompt ?? suggestion.label);\n const key = typeof suggestion === \"string\" ? `${position}-${suggestion}` : (suggestion.id ?? `${position}-${suggestion.label}`);\n return (\n <li key={key}>\n <Button\n variant=\"outline\"\n tone=\"neutral\"\n size=\"sm\"\n disabled={disabled}\n onClick={() => onSelect(prompt, suggestion)}\n dir=\"auto\"\n >\n {label}\n </Button>\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { toThreadError } from \"../errors\";\nimport { findToolCall, lastMessageWithRole, messageText, threadPendingApprovals } from \"../messages\";\nimport {\n createAbortableStream,\n isTerminalStreamEvent,\n applyStreamEvent,\n type StreamEvent,\n} from \"../stream\";\nimport {\n createThreadState,\n getBranchInfoMap,\n isBusy,\n lastUserMessage,\n threadReducer,\n type BranchInfo,\n type ThreadAction,\n type ThreadState,\n type ThreadStatus,\n} from \"../thread-state\";\nimport type { FilePart, Message, ThreadError } from \"../types\";\nimport { useEventCallback } from \"./internal/hooks\";\n\ntype Awaitable<T> = T | Promise<T>;\n\n/** What a handler returns to stream a reply: any async iterable of stream events, such as an async generator. Return nothing to stream nothing. */\nexport type ThreadStreamResult = AsyncIterable<StreamEvent> | void | undefined;\n\n/** A file to send with a message. `PromptInput`'s attachments fit this shape. */\nexport interface SendAttachment {\n id?: string | undefined;\n name: string;\n mediaType?: string | undefined;\n size?: number | undefined;\n /** Where the file can be read. Without it, a `file` is shown through a `blob:` URL. */\n url?: string | undefined;\n file?: File | undefined;\n}\n\nexport type ThreadTrigger = \"send\" | \"regenerate\" | \"edit\";\n\nexport interface ThreadRequest {\n trigger: ThreadTrigger;\n /** The user message this turn answers (the newest one). */\n message: Message | undefined;\n /** Its text. */\n text: string;\n /** Its files. */\n attachments: FilePart[];\n /** Every message of the thread, including the new user message. A snapshot: it does not change. */\n messages: readonly Message[];\n /** Aborted by `stop()`. Pass it to `fetch` so the request is cancelled too. */\n signal: AbortSignal;\n}\n\nexport interface ToolDecisionRequest {\n callId: string;\n toolName: string;\n decision: \"approve\" | \"deny\";\n reason: string | undefined;\n /** Tool calls still waiting for a decision after this one. Resume the model only when it is 0. */\n pending: number;\n messages: readonly Message[];\n signal: AbortSignal;\n}\n\nexport interface UseThreadOptions {\n /** Messages to start with, for example loaded from your store. Read once. */\n initialMessages?: readonly Message[] | undefined;\n /** Called to answer a new user message. Return (or yield) stream events to write the reply. */\n onSend?: ((request: ThreadRequest) => Awaitable<ThreadStreamResult>) | undefined;\n /** Called to answer the last user message again. Defaults to `onSend` with `trigger: \"regenerate\"`. */\n onRegenerate?: ((request: ThreadRequest) => Awaitable<ThreadStreamResult>) | undefined;\n /**\n * Called after the user approves or denies a tool call. Return a stream to\n * continue the reply (it is written into the same message), or nothing.\n * If the stream of the original reply is still open (because it is waiting\n * for this decision), it is left running and not aborted.\n */\n onToolDecision?: ((request: ToolDecisionRequest) => Awaitable<ThreadStreamResult>) | undefined;\n /** Called after the user stops a reply. The run's `signal` has already been aborted. */\n onStop?: ((info: { messages: readonly Message[] }) => void) | undefined;\n /** Called when a reply finishes normally. */\n onFinish?: ((message: Message | undefined) => void) | undefined;\n /** Called when a reply fails. */\n onError?: ((error: ThreadError) => void) | undefined;\n /**\n * Group stream events into one render per animation frame, so a fast stream\n * does not render once per token. Default true. Turn it off in tests.\n */\n batch?: boolean | undefined;\n /** Makes ids for user messages. Defaults to `crypto.randomUUID`. */\n generateId?: (() => string) | undefined;\n /** The clock, in epoch milliseconds. For tests. */\n now?: (() => number) | undefined;\n}\n\nexport interface EditOptions {\n /** `truncate` (default) replaces the message and drops what followed; `branch` keeps the old version. */\n mode?: \"truncate\" | \"branch\" | undefined;\n}\n\n/** Props that `ChatThread` understands, so `<ChatThread {...thread.chatProps} />` just works. */\nexport interface ThreadChatProps {\n messages: Message[];\n status: ThreadStatus;\n error: ThreadError | null;\n branches: Record<string, BranchInfo>;\n onSend: (text: string, attachments?: readonly SendAttachment[]) => void;\n onStop: () => void;\n onRegenerate: () => void;\n onToolDecision: (callId: string, decision: \"approve\" | \"deny\", reason?: string) => void;\n onEdit: (messageId: string, text: string) => void;\n onSwitchBranch: (parentId: string, index: number) => void;\n onDismissError: () => void;\n}\n\nexport interface UseThreadResult {\n messages: Message[];\n status: ThreadStatus;\n error: ThreadError | null;\n /** The whole state, including branches. */\n state: ThreadState;\n /** Adds a user message and asks `onSend` for the reply. Ignored while a reply is running. */\n send: (text: string, attachments?: readonly SendAttachment[]) => Promise<void>;\n /** Stops the running reply and keeps what was written. */\n stop: () => void;\n /** Answers the last user message again. */\n regenerate: () => Promise<void>;\n /** Approves a tool call that needs approval. */\n approve: (callId: string, reason?: string) => Promise<void>;\n /** Denies a tool call that needs approval. */\n deny: (callId: string, reason?: string) => Promise<void>;\n decide: (callId: string, decision: \"approve\" | \"deny\", reason?: string) => Promise<void>;\n /** Edits a user message and asks for a new reply. */\n edit: (messageId: string, text: string, options?: EditOptions) => Promise<void>;\n /** Shows another version of an edited message. */\n switchBranch: (parentId: string, index: number) => void;\n dismissError: () => void;\n /** Empties the thread and stops any reply. */\n clear: () => void;\n /** Replaces the thread. Stops any reply. */\n setMessages: (messages: readonly Message[]) => void;\n /** Applies a reducer action, for example to add a system note. */\n dispatch: (action: ThreadAction) => void;\n /** Applies one stream event yourself, for events that arrive outside `onSend`, such as from a WebSocket. */\n applyEvent: (event: StreamEvent) => void;\n /** Spread into `ChatThread`. */\n chatProps: ThreadChatProps;\n}\n\ninterface Run {\n controller: AbortController;\n done: Promise<void>;\n}\n\nlet idCounter = 0;\n\nfunction defaultGenerateId(): string {\n idCounter += 1;\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") return crypto.randomUUID();\n return `msg-${Date.now().toString(36)}-${idCounter}`;\n}\n\nfunction isBusyRef(ref: { current: ThreadState | null }): boolean {\n return ref.current ? isBusy(ref.current) : false;\n}\n\nfunction buildRequest(state: ThreadState | null, trigger: ThreadTrigger, signal: AbortSignal): ThreadRequest {\n const messages = state?.messages ?? [];\n const user = lastUserMessage({ messages });\n return {\n trigger,\n message: user,\n text: user ? messageText(user) : \"\",\n attachments: user ? user.parts.filter((part): part is FilePart => part.type === \"file\") : [],\n messages,\n signal,\n };\n}\n\nfunction toFileParts(attachments: readonly SendAttachment[]): FilePart[] {\n return attachments.map((attachment, index): FilePart => {\n let url = attachment.url ?? \"\";\n if (url === \"\" && attachment.file && typeof URL !== \"undefined\" && typeof URL.createObjectURL === \"function\") {\n url = URL.createObjectURL(attachment.file);\n }\n return {\n type: \"file\",\n id: attachment.id ?? `file-${idCounter}-${index}`,\n name: attachment.name,\n mediaType: attachment.mediaType ?? attachment.file?.type ?? \"application/octet-stream\",\n url,\n ...(attachment.size === undefined && attachment.file === undefined\n ? {}\n : { size: attachment.size ?? attachment.file?.size ?? 0 }),\n };\n });\n}\n\n/**\n * Chat state for any provider. It keeps the thread with `threadReducer`, runs\n * your `onSend` (an async generator of stream events works), and gives you\n * `send`, `stop`, `regenerate`, `approve` and `deny`.\n *\n * - Events are applied to the thread as they arrive but rendered once per\n * animation frame (`batch: false` to render each one).\n * - `stop()` aborts the signal your handler received, ends the stream, and\n * keeps the text written so far.\n * - A failure becomes `status: \"error\"` with a typed `error`; `regenerate()` retries.\n * - Nothing is ever approved on its own: a tool call that needs approval waits\n * until `approve` or `deny` is called.\n */\nexport function useThread(options: UseThreadOptions = {}): UseThreadResult {\n const { batch = true, initialMessages } = options;\n\n const stateRef = useRef<ThreadState | null>(null);\n if (stateRef.current === null) stateRef.current = createThreadState(initialMessages ?? []);\n const [state, setState] = useState<ThreadState>(stateRef.current);\n\n const runRef = useRef<Run | null>(null);\n const frameRef = useRef<{ kind: \"raf\" | \"timeout\"; id: number } | null>(null);\n const decisionChain = useRef<Promise<void>>(Promise.resolve());\n const mounted = useRef(true);\n\n const onSend = useEventCallback((request: ThreadRequest) => options.onSend?.(request));\n const onRegenerate = useEventCallback((request: ThreadRequest) => options.onRegenerate?.(request));\n const onToolDecision = useEventCallback((request: ToolDecisionRequest) => options.onToolDecision?.(request));\n const onStop = useEventCallback((info: { messages: readonly Message[] }) => options.onStop?.(info));\n const onFinish = useEventCallback((message: Message | undefined) => options.onFinish?.(message));\n const onError = useEventCallback((error: ThreadError) => options.onError?.(error));\n const hasOnRegenerate = options.onRegenerate !== undefined;\n const hasOnToolDecision = options.onToolDecision !== undefined;\n const generateId = useEventCallback(() => (options.generateId ?? defaultGenerateId)());\n const now = useEventCallback(() => (options.now ?? Date.now)());\n\n const cancelFrame = useCallback(() => {\n const frame = frameRef.current;\n if (!frame) return;\n if (frame.kind === \"raf\" && typeof cancelAnimationFrame === \"function\") cancelAnimationFrame(frame.id);\n else clearTimeout(frame.id);\n frameRef.current = null;\n }, []);\n\n const flush = useCallback(() => {\n cancelFrame();\n if (mounted.current && stateRef.current) setState(stateRef.current);\n }, [cancelFrame]);\n\n const scheduleRender = useCallback(() => {\n if (!batch) {\n flush();\n return;\n }\n if (frameRef.current) return;\n const run = () => {\n frameRef.current = null;\n if (mounted.current && stateRef.current) setState(stateRef.current);\n };\n if (typeof requestAnimationFrame === \"function\") {\n frameRef.current = { kind: \"raf\", id: requestAnimationFrame(run) };\n } else {\n frameRef.current = { kind: \"timeout\", id: window.setTimeout(run, 16) };\n }\n }, [batch, flush]);\n\n const dispatch = useCallback(\n (action: ThreadAction) => {\n if (!stateRef.current) return;\n stateRef.current = threadReducer(stateRef.current, action);\n flush();\n },\n [flush],\n );\n\n const applyEvent = useCallback(\n (event: StreamEvent) => {\n if (!stateRef.current) return;\n const stamped: StreamEvent =\n event.type === \"start\" && event.createdAt === undefined\n ? { ...event, createdAt: new Date(now()).toISOString() }\n : event;\n stateRef.current = applyStreamEvent(stateRef.current, stamped, { at: now() });\n if (isTerminalStreamEvent(stamped)) flush();\n else scheduleRender();\n },\n [flush, now, scheduleRender],\n );\n\n const failRun = useCallback(\n (error: unknown) => {\n const threadError = toThreadError(error);\n dispatch({ type: \"error\", error: threadError });\n onError(threadError);\n },\n [dispatch, onError],\n );\n\n /** Runs one producer to completion, replacing any run still in flight. */\n const runProducer = useCallback(\n async (producer: (signal: AbortSignal) => Awaitable<ThreadStreamResult>): Promise<void> => {\n runRef.current?.controller.abort();\n\n let finishRun!: () => void;\n const run: Run = {\n controller: new AbortController(),\n done: new Promise<void>((resolve) => {\n finishRun = resolve;\n }),\n };\n runRef.current = run;\n const { signal } = run.controller;\n\n try {\n let source: ThreadStreamResult;\n try {\n source = await producer(signal);\n } catch (error) {\n if (!signal.aborted && runRef.current === run) failRun(error);\n return;\n }\n if (runRef.current !== run || signal.aborted) return;\n\n if (!source) {\n // The handler chose not to stream: the turn is over.\n dispatch({ type: \"finish\" });\n return;\n }\n\n let finished = false;\n try {\n for await (const event of createAbortableStream(source, signal)) {\n if (runRef.current !== run) break;\n applyEvent(event);\n if (event.type === \"finish\") finished = true;\n if (isTerminalStreamEvent(event)) break;\n }\n } catch (error) {\n if (!signal.aborted && runRef.current === run) failRun(error);\n return;\n }\n\n // The stream ended. If it never said so, finish the message.\n if (runRef.current === run && stateRef.current) {\n if (isBusy(stateRef.current)) {\n dispatch({ type: \"finish\" });\n finished = true;\n }\n if (finished) onFinish(lastMessageWithRole(stateRef.current.messages, \"assistant\"));\n }\n } finally {\n if (runRef.current === run) runRef.current = null;\n finishRun();\n }\n },\n [applyEvent, dispatch, failRun, onFinish],\n );\n\n const send = useCallback(\n async (text: string, attachments: readonly SendAttachment[] = []) => {\n const trimmed = text.trim();\n if (trimmed === \"\" && attachments.length === 0) return;\n if (isBusyRef(stateRef)) return;\n dispatch({\n type: \"add-user-message\",\n id: generateId(),\n text: trimmed,\n attachments: toFileParts(attachments),\n createdAt: new Date(now()).toISOString(),\n });\n await runProducer((signal) => onSend(buildRequest(stateRef.current, \"send\", signal)));\n },\n [dispatch, generateId, now, onSend, runProducer],\n );\n\n const stop = useCallback(() => {\n const run = runRef.current;\n if (run) {\n runRef.current = null;\n run.controller.abort();\n }\n if (stateRef.current && isBusy(stateRef.current)) {\n dispatch({ type: \"abort\", at: now() });\n onStop({ messages: stateRef.current.messages });\n }\n }, [dispatch, now, onStop]);\n\n const regenerate = useCallback(async () => {\n if (isBusyRef(stateRef)) return;\n dispatch({ type: \"regenerate\" });\n if (stateRef.current?.status !== \"submitted\") return;\n const handler = hasOnRegenerate ? onRegenerate : onSend;\n await runProducer((signal) => handler(buildRequest(stateRef.current, \"regenerate\", signal)));\n }, [dispatch, hasOnRegenerate, onRegenerate, onSend, runProducer]);\n\n const edit = useCallback(\n async (messageId: string, text: string, editOptions: EditOptions = {}) => {\n if (isBusyRef(stateRef) || text.trim() === \"\") return;\n dispatch({\n type: \"edit-message\",\n messageId,\n text: text.trim(),\n mode: editOptions.mode ?? \"truncate\",\n createdAt: new Date(now()).toISOString(),\n });\n if (stateRef.current?.status !== \"submitted\") return;\n await runProducer((signal) => onSend(buildRequest(stateRef.current, \"edit\", signal)));\n },\n [dispatch, now, onSend, runProducer],\n );\n\n const decide = useCallback(\n (callId: string, decision: \"approve\" | \"deny\", reason?: string): Promise<void> => {\n const current = stateRef.current;\n const found = current ? findToolCall(current.messages, callId) : undefined;\n // Only a call that is waiting for a decision can be decided, and only once.\n if (!current || !found || found.part.state !== \"needs-approval\") return Promise.resolve();\n\n dispatch({\n type: \"tool-decision\",\n callId,\n decision: decision === \"approve\" ? \"approved\" : \"denied\",\n ...(reason === undefined ? {} : { reason }),\n });\n if (!hasOnToolDecision) return Promise.resolve();\n\n const messageId = found.message.id;\n const toolName = found.part.name;\n // Counted now, right after this decision, so two quick clicks are told 1 and then 0\n // (and the model is resumed once, after the last), however the handlers get scheduled.\n const pending = threadPendingApprovals(stateRef.current?.messages ?? []).length;\n\n // Decisions are handled one after another, so two quick clicks do not start two runs at once.\n const task = decisionChain.current.then(async () => {\n if (!mounted.current) return;\n\n const active = runRef.current;\n if (active) {\n // The original stream is still open, and may be waiting for this very decision.\n // Tell the handler, but leave that stream running; anything the handler streams\n // back is written into the same message alongside it.\n const { signal } = active.controller;\n try {\n const result = await onToolDecision({\n callId,\n toolName,\n decision,\n reason,\n pending,\n messages: stateRef.current?.messages ?? [],\n signal,\n });\n if (result && runRef.current === active) {\n for await (const event of createAbortableStream(result, signal)) {\n if (runRef.current !== active) break;\n applyEvent(event);\n if (isTerminalStreamEvent(event)) break;\n }\n }\n } catch (error) {\n if (!signal.aborted && runRef.current === active) failRun(error);\n }\n return;\n }\n\n await runProducer(async (signal) => {\n const result = await onToolDecision({\n callId,\n toolName,\n decision,\n reason,\n pending,\n messages: stateRef.current?.messages ?? [],\n signal,\n });\n // Continue writing into the message the tool call belongs to.\n if (result) dispatch({ type: \"begin-assistant-message\", id: messageId });\n return result;\n });\n });\n decisionChain.current = task.catch(() => {});\n return task;\n },\n [applyEvent, dispatch, failRun, hasOnToolDecision, onToolDecision, runProducer],\n );\n\n const approve = useCallback((callId: string, reason?: string) => decide(callId, \"approve\", reason), [decide]);\n const deny = useCallback((callId: string, reason?: string) => decide(callId, \"deny\", reason), [decide]);\n\n const switchBranch = useCallback(\n (parentId: string, index: number) => dispatch({ type: \"switch-branch\", parentId, index }),\n [dispatch],\n );\n const dismissError = useCallback(() => dispatch({ type: \"dismiss-error\" }), [dispatch]);\n\n const clear = useCallback(() => {\n runRef.current?.controller.abort();\n runRef.current = null;\n dispatch({ type: \"clear\" });\n }, [dispatch]);\n\n const setMessages = useCallback(\n (messages: readonly Message[]) => {\n runRef.current?.controller.abort();\n runRef.current = null;\n dispatch({ type: \"set-messages\", messages: [...messages] });\n },\n [dispatch],\n );\n\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n cancelFrame();\n runRef.current?.controller.abort();\n runRef.current = null;\n };\n }, [cancelFrame]);\n\n const branches = useMemo(() => getBranchInfoMap(state), [state]);\n\n const chatProps = useMemo<ThreadChatProps>(\n () => ({\n messages: state.messages,\n status: state.status,\n error: state.error,\n branches,\n onSend: (text, attachments) => {\n void send(text, attachments);\n },\n onStop: stop,\n onRegenerate: () => {\n void regenerate();\n },\n onToolDecision: (callId, decision, reason) => {\n void decide(callId, decision, reason);\n },\n onEdit: (messageId, text) => {\n void edit(messageId, text);\n },\n onSwitchBranch: switchBranch,\n onDismissError: dismissError,\n }),\n [state.messages, state.status, state.error, branches, send, stop, regenerate, decide, edit, switchBranch, dismissError],\n );\n\n return {\n messages: state.messages,\n status: state.status,\n error: state.error,\n state,\n send,\n stop,\n regenerate,\n approve,\n deny,\n decide,\n edit,\n switchBranch,\n dismissError,\n clear,\n setMessages,\n dispatch,\n applyEvent,\n chatProps,\n };\n}\n"],"mappings":"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","names":["VisuallyHidden","memo","useEffect","useMemo","useRef","useState","jsx","useCallback","useEffect","useLayoutEffect","useRef","useState","useRef","useState","useCallback","useLayoutEffect","useEffect","jsx","jsxs","jsx","jsxs","Button","jsx","jsxs","Button","Badge","Button","VisuallyHidden","useEffect","useMemo","useRef","useState","jsx","jsxs","Button","useRef","useState","Icon","IconButton","VisuallyHidden","useCallback","jsx","jsxs","useCallback","IconButton","Icon","VisuallyHidden","jsx","jsxs","useState","useRef","Button","useLayoutEffect","VisuallyHidden","createContext","useContext","useId","useMemo","useRef","useRef","jsx","jsxs","useRef","Icon","VisuallyHidden","createContext","useCallback","useContext","useEffect","useId","useMemo","useRef","useState","useId","useId","jsx","jsxs","createContext","useContext","useId","useRef","useCallback","useMemo","Icon","VisuallyHidden","useState","useEffect","jsx","jsxs","createContext","useContext","VisuallyHidden","useRef","MarkdownBlock","useMemo","useId","Icon","useEffect","useRef","jsx","jsxs","useRef","useEffect","Icon","VisuallyHidden","jsx","jsxs","VisuallyHidden","Icon","Badge","Spinner","VisuallyHidden","Button","useId","useLayoutEffect","useRef","jsx","jsxs","useRef","useId","useLayoutEffect","Button","Fragment","jsx","jsxs","Badge","Spinner","Icon","VisuallyHidden","jsx","jsxs","useState","useRef","useEffect","Button","useMemo","Badge","VisuallyHidden","Icon","IconButton","VisuallyHidden","Fragment","jsx","jsxs","IconButton","VisuallyHidden","Icon","Icon","IconButton","Spinner","VisuallyHidden","useCallback","useId","useRef","useState","Fragment","jsx","jsxs","useState","useRef","useId","useCallback","Spinner","VisuallyHidden","IconButton","Icon","Button","jsx","Button","jsx","jsxs","useState","useRef","useEffect","memo","ThreadMessageItem","useMemo","VisuallyHidden","useCallback","useEffect","useMemo","useRef","useState","useRef","useState","useCallback","useEffect","useMemo"]}
|