quassel 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChatMessages.d.ts +3 -1
- package/index.js +19 -10
- package/index.js.map +2 -2
- package/package.json +1 -1
package/ChatMessages.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { type ChatAppearance, type TimestampOptions, type CodeBlockOptions, type
|
|
|
7
7
|
* The transcript: its own scroll container with autoscroll while you are at the bottom, and a
|
|
8
8
|
* jump-to-end button as soon as you are reading. Usable read-only without a composer.
|
|
9
9
|
*/
|
|
10
|
-
export declare function ChatMessages({ messages, owner, detailMode, running, working, stepsExpandable, texts, toolArgumentsText, renderTool, renderAction, onDismissAction, onLinkClick, emptyState, className, scrollerClassName, showTimestamps, announce, scrollerRef, maxWidth, horizontalPadding, jumpToEndThreshold, appearance, timestampOptions, codeBlockOptions, bubbleOptions, messageActions, toolElapsedThreshold, }: {
|
|
10
|
+
export declare function ChatMessages({ messages, owner, detailMode, running, working, stepsExpandable, groupsExpandable, texts, toolArgumentsText, renderTool, renderAction, onDismissAction, onLinkClick, emptyState, className, scrollerClassName, showTimestamps, announce, scrollerRef, maxWidth, horizontalPadding, jumpToEndThreshold, appearance, timestampOptions, codeBlockOptions, bubbleOptions, messageActions, toolElapsedThreshold, }: {
|
|
11
11
|
messages: Message[];
|
|
12
12
|
/** Contributions with this Message.sender appear without a speech bubble; null keeps the message defaults. */
|
|
13
13
|
owner?: string | null;
|
|
@@ -16,6 +16,8 @@ export declare function ChatMessages({ messages, owner, detailMode, running, wor
|
|
|
16
16
|
working?: ReactNode;
|
|
17
17
|
/** false = thinking and tool steps cannot be expanded (no popover). */
|
|
18
18
|
stepsExpandable?: boolean;
|
|
19
|
+
/** false = step groups in grouped mode stay collapsed (header without toggle). */
|
|
20
|
+
groupsExpandable?: boolean;
|
|
19
21
|
texts?: Partial<ChatTexts>;
|
|
20
22
|
toolArgumentsText?: (tool: ToolInfo) => string;
|
|
21
23
|
/** Custom rendering for single tools; undefined = default rendering. */
|
package/index.js
CHANGED
|
@@ -1100,6 +1100,7 @@ function ChatMessages({
|
|
|
1100
1100
|
running: running2 = false,
|
|
1101
1101
|
working,
|
|
1102
1102
|
stepsExpandable = true,
|
|
1103
|
+
groupsExpandable = true,
|
|
1103
1104
|
texts,
|
|
1104
1105
|
toolArgumentsText = defaultArgumentsText,
|
|
1105
1106
|
renderTool,
|
|
@@ -1244,6 +1245,7 @@ function ChatMessages({
|
|
|
1244
1245
|
{
|
|
1245
1246
|
elapsedAfter,
|
|
1246
1247
|
expandable: stepsExpandable,
|
|
1248
|
+
groupExpandable: groupsExpandable,
|
|
1247
1249
|
runningStep,
|
|
1248
1250
|
messages: group,
|
|
1249
1251
|
texts: allTexts,
|
|
@@ -1456,6 +1458,7 @@ function StepGroup({
|
|
|
1456
1458
|
runningStep,
|
|
1457
1459
|
elapsedAfter,
|
|
1458
1460
|
expandable,
|
|
1461
|
+
groupExpandable,
|
|
1459
1462
|
texts,
|
|
1460
1463
|
toolArgumentsText
|
|
1461
1464
|
}) {
|
|
@@ -1472,6 +1475,21 @@ function StepGroup({
|
|
|
1472
1475
|
const failed = messages.some((message) => message.tool?.isError);
|
|
1473
1476
|
const count = messages.length === 1 ? texts.stepGroupOne : texts.stepGroupMany.replace("{count}", String(messages.length));
|
|
1474
1477
|
const runningLabel = runningStep && (runningStep.role === "thinking" ? texts.thinkingChip : runningStep.tool?.name || runningStep.text || texts.toolChip);
|
|
1478
|
+
const summary = /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1479
|
+
/* @__PURE__ */ jsx13(LayersIcon, { className: failed ? traceErrorIconClasses : traceIconClasses, size: 12 }),
|
|
1480
|
+
/* @__PURE__ */ jsxs6("span", { className: cn(traceLineClasses, "qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap"), children: [
|
|
1481
|
+
count,
|
|
1482
|
+
runningLabel && /* @__PURE__ */ jsxs6("span", { className: traceRunningClasses, children: [
|
|
1483
|
+
runningLabel,
|
|
1484
|
+
" ",
|
|
1485
|
+
texts.toolRunning
|
|
1486
|
+
] }),
|
|
1487
|
+
runningStep && /* @__PURE__ */ jsx13(ToolElapsed, { after: elapsedAfter, message: runningStep, texts })
|
|
1488
|
+
] })
|
|
1489
|
+
] });
|
|
1490
|
+
if (!groupExpandable) {
|
|
1491
|
+
return /* @__PURE__ */ jsx13("div", { className: stepClasses, "data-step": "group", children: /* @__PURE__ */ jsx13("div", { className: cn(traceClasses, "qsl:items-center qsl:py-1 qsl:pr-2 qsl:pl-1", active && "qsl:animate-fade-pulse qsl:motion-reduce:animate-none"), children: summary }) });
|
|
1492
|
+
}
|
|
1475
1493
|
return /* @__PURE__ */ jsxs6("div", { className: stepClasses, "data-step": "group", children: [
|
|
1476
1494
|
/* @__PURE__ */ jsxs6(
|
|
1477
1495
|
"button",
|
|
@@ -1483,16 +1501,7 @@ function StepGroup({
|
|
|
1483
1501
|
type: "button",
|
|
1484
1502
|
children: [
|
|
1485
1503
|
/* @__PURE__ */ jsx13(ChevronRightIcon, { className: cn("qsl:flex-none qsl:opacity-60 qsl:transition-transform", open && "qsl:rotate-90"), size: 12 }),
|
|
1486
|
-
|
|
1487
|
-
/* @__PURE__ */ jsxs6("span", { className: cn(traceLineClasses, "qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap"), children: [
|
|
1488
|
-
count,
|
|
1489
|
-
runningLabel && /* @__PURE__ */ jsxs6("span", { className: traceRunningClasses, children: [
|
|
1490
|
-
runningLabel,
|
|
1491
|
-
" ",
|
|
1492
|
-
texts.toolRunning
|
|
1493
|
-
] }),
|
|
1494
|
-
runningStep && /* @__PURE__ */ jsx13(ToolElapsed, { after: elapsedAfter, message: runningStep, texts })
|
|
1495
|
-
] })
|
|
1504
|
+
summary
|
|
1496
1505
|
]
|
|
1497
1506
|
}
|
|
1498
1507
|
),
|
package/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/types.ts", "../src/texts.ts", "../src/ui/cn.ts", "../src/ChatMessages.tsx", "../src/chat-scroll.ts", "../src/Markdown.tsx", "../src/QuasselProvider.tsx", "../src/ui/button.tsx", "../src/ui/card.tsx", "../src/ui/popover.tsx", "../src/ui/stop-button.tsx", "../src/ui/spinner.tsx", "../src/ui/toggle.tsx", "../src/useChatAction.ts", "../src/StepPopover.tsx", "../src/PendingActionCard.tsx", "../src/WorkingScenes.tsx", "../src/attachments.ts", "../src/options.ts", "../src/timestamps.ts", "../src/elapsed.ts", "../src/MessageActions.tsx", "../src/ChatSendContext.ts", "../src/ChatActionDock.ts", "../src/announce.ts", "../src/ChatPanel.tsx", "../src/ChatInputToolbar.tsx", "../src/ui/useFileInput.ts", "../src/DetailModeSwitch.tsx", "../src/TimestampSwitch.tsx"],
|
|
4
|
-
"sourcesContent": ["import type { Message } from \"./events\";\n\nexport type { Role, ToolInfo, PendingAction, Message, ChatEvent, ChatTextCursor, ChatJournalCursor, ChatAttachment, ChatAttachmentInput, ChatAttachmentCapabilities, ChatStartupStatus } from \"./events\";\nexport { applyEvent, prettyJson, compactToolLine } from \"./events\";\n\n/**\n * current = only the running step, off = answers only, icons = steps as plain icons side by side,\n * chips = steps as icon + short text side by side (wrapping),\n * grouped = consecutive steps as one expandable line, single line each inside,\n * compact = thinking and tools on a single line, full = everything expanded.\n */\nexport type DetailMode = \"off\" | \"current\" | \"icons\" | \"chips\" | \"grouped\" | \"compact\" | \"full\";\n\n/** running = call still open, thinking = thought block still open, done = finished, error = failed. */\nexport type StepState = \"running\" | \"thinking\" | \"done\" | \"error\";\n\n/** The single derivation of a step state, so chips, hosts and tests read the same signal. */\nexport function stepState(message: Message): StepState {\n if (message.tool?.isError) {\n return \"error\";\n }\n if (message.role === \"thinking\") {\n return message.closed ? \"done\" : \"thinking\";\n }\n return message.tool !== undefined && message.tool.result === undefined ? \"running\" : \"done\";\n}\n\n/** A moment worth one screen reader announcement: a finished reply or a new pending action. */\nexport type ChatAnnouncement =\n | { kind: \"reply\"; message: Message }\n | { kind: \"action\"; message: Message };\n", "export interface ChatTexts {\n working: string;\n toolRunning: string;\n toolStillRunning: string;\n toolElapsedSeconds: string;\n currentTool: string;\n thinkingChip: string;\n toolChip: string;\n stepGroupOne: string;\n stepGroupMany: string;\n stepGroupCollapse: string;\n thinkingTitle: string;\n toolTitle: string;\n argumentsLabel: string;\n resultLabel: string;\n close: string;\n jumpToEnd: string;\n send: string;\n sendIntoRun: string;\n stop: string;\n placeholder: string;\n steeringPlaceholder: string;\n steered: string;\n detailModeTitle: string;\n detailModeOff: string;\n detailModeCurrent: string;\n detailModeIcons: string;\n detailModeChips: string;\n detailModeGrouped: string;\n detailModeCompact: string;\n detailModeFull: string;\n showTimestamps: string;\n hideTimestamps: string;\n copyMessage: string;\n editMessage: string;\n retryMessage: string;\n copyCode: string;\n copied: string;\n pendingAction: string;\n dismissAction: string;\n actionDismissed: string;\n actionFailed: string;\n clipboardUnavailable: string;\n transcript: string;\n attachments: string;\n attachFiles: string;\n attachFilesHint: string;\n removeAttachment: string;\n attachmentPreparing: string;\n attachmentsPreparing: string;\n attachmentReadFailed: string;\n attachmentsWhileBusy: string;\n tooManyAttachments: string;\n attachmentsTooLarge: string;\n attachmentUnsupported: string;\n attachmentUnsupportedByModel: string;\n attachmentKindImage: string;\n attachmentKindVideo: string;\n attachmentKindPdf: string;\n notSent: string;\n notSentAttachments: string;\n insertUnsent: string;\n}\n\n\nexport const fillText = (text: string, values: Record<string, string | number>): string =>\n text.replace(/\\{(\\w+)\\}/g, (match, name: string) => name in values ? String(values[name]) : match);\n\nexport const defaultTexts: ChatTexts = {\n working: \"Working ...\",\n toolRunning: \"running ...\",\n toolStillRunning: \"Tool running ...\",\n toolElapsedSeconds: \"{seconds} s\",\n currentTool: \"Tool running\",\n thinkingChip: \"Thinking\",\n toolChip: \"Tool\",\n stepGroupOne: \"1 step\",\n stepGroupMany: \"{count} steps\",\n stepGroupCollapse: \"Collapse\",\n thinkingTitle: \"Thinking trace\",\n toolTitle: \"Tool call\",\n argumentsLabel: \"Arguments\",\n resultLabel: \"Result\",\n close: \"Close\",\n jumpToEnd: \"Jump to end\",\n send: \"Send\",\n sendIntoRun: \"Feed into the running turn\",\n stop: \"Stop work\",\n placeholder: \"Write a message ...\",\n steeringPlaceholder: \"Interject ...\",\n steered: \"Fed into the running turn\",\n detailModeTitle: \"Step detail level\",\n detailModeOff: \"answers only\",\n detailModeCurrent: \"current\",\n detailModeIcons: \"icons\",\n detailModeChips: \"compact\",\n detailModeGrouped: \"grouped\",\n detailModeCompact: \"single line\",\n detailModeFull: \"everything\",\n showTimestamps: \"Show timestamps\",\n hideTimestamps: \"Hide timestamps\",\n copyMessage: \"Copy message\",\n editMessage: \"Edit message\",\n retryMessage: \"Request answer again\",\n copyCode: \"Copy code\",\n copied: \"Copied\",\n pendingAction: \"waiting for input\",\n dismissAction: \"Dismiss\",\n actionDismissed: \"dismissed\",\n actionFailed: \"Action failed\",\n clipboardUnavailable: \"The clipboard is not available\",\n transcript: \"Chat history\",\n attachments: \"Attachments\",\n attachFiles: \"Attach files\",\n attachFilesHint: \"Attach files (up to {count} files, {size} in total)\",\n removeAttachment: \"Remove {name}\",\n attachmentPreparing: \"Preparing ...\",\n attachmentsPreparing: \"Preparing attachments ...\",\n attachmentReadFailed: \"The file could not be read. Remove it and add it again.\",\n attachmentsWhileBusy: \"Wait until the input is ready again, then add the files again.\",\n tooManyAttachments: \"At most {count} attachments per message. Remove an attachment first.\",\n attachmentsTooLarge: \"Attachments may be at most {size} in total. Choose smaller files.\",\n attachmentUnsupported: \"This chat does not support {name} as {kind}. Remove the attachment.\",\n attachmentUnsupportedByModel: \"The model {model} does not support {name} as {kind}. Choose a suitable model or remove the attachment.\",\n attachmentKindImage: \"image\",\n attachmentKindVideo: \"video\",\n attachmentKindPdf: \"PDF\",\n notSent: \"Not sent:\",\n notSentAttachments: \"({count} attachments)\",\n insertUnsent: \"Insert unsent input\",\n};\n", "import type { CnFunction } from \"cn\";\nimport { createCn } from \"cn/config\";\n\nexport const cn: CnFunction = createCn({ prefix: \"qsl\", extend: { theme: { text: [\"meta\", \"trace\", \"label\"] } } });\n", "import { cn } from \"./ui/cn\";\nimport { type CSSProperties, ReactNode, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { createChatScroll } from \"./chat-scroll\";\nimport { ChatAnnouncement, DetailMode, Message, PendingAction, prettyJson, stepState, ToolInfo } from \"./types\";\nimport { ChatTexts, defaultTexts } from \"./texts\";\nimport { Markdown, MarkdownCodeBlocks, MarkdownLinks, markdownPlainText, type LinkClickHandler } from \"./Markdown\";\nimport { StepPopover } from \"./StepPopover\";\nimport { PendingActionCard } from \"./PendingActionCard\";\nimport { WorkingScenes } from \"./WorkingScenes\";\nimport { attachmentDownloadUrl, formatAttachmentSize } from \"./attachments\";\nimport { CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, LayersIcon, SparklesIcon, WrenchIcon } from \"lucide-react\";\nimport { appearanceStyle, type ChatAppearance, type TimestampOptions, type CodeBlockOptions, type BubbleOptions, type MessageActionsOptions } from \"./options\";\nimport { messageDate, timestampDay, timestampLabel } from \"./timestamps\";\nimport { formatElapsed, useElapsed } from \"./elapsed\";\nimport { MessageActions } from \"./MessageActions\";\nimport { ChatSendContext } from \"./ChatSendContext\";\nimport { ChatActionDock } from \"./ChatActionDock\";\nimport { announce as announceText } from \"./announce\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\n\nconst stepClasses = \"qsl:mt-[var(--qsl-chat-message-gap,16px)]\";\nconst denseStepClasses = \"qsl:mt-[var(--qsl-chat-dense-message-gap,8px)]\";\n\nconst traceClasses = \"qsl:flex qsl:w-full qsl:gap-2 qsl:pl-6 qsl:text-left qsl:text-trace qsl:leading-[1.375] qsl:text-muted-foreground\";\nconst traceButtonClasses = \"qsl:cursor-pointer qsl:rounded-md qsl:py-1 qsl:pr-2 qsl:transition-colors qsl:hover:bg-secondary qsl:hover:text-foreground qsl:focus-visible:bg-secondary qsl:focus-visible:text-foreground qsl:focus-visible:outline-none\";\nconst traceIconClasses = \"qsl:mt-0.5 qsl:flex-none qsl:opacity-60\";\nconst traceErrorIconClasses = \"qsl:mt-0.5 qsl:flex-none qsl:text-destructive qsl:opacity-100\";\nconst traceLineClasses = \"qsl:min-w-0 qsl:self-baseline qsl:font-mono qsl:[overflow-wrap:anywhere]\";\nconst traceRunningClasses = \"qsl:ml-1.5 qsl:opacity-60\";\n\nconst chipClasses = cn(\n \"qsl:inline-flex qsl:max-w-[220px] qsl:items-center qsl:gap-[5px] qsl:rounded-full qsl:border qsl:border-border-soft qsl:px-2.5 qsl:py-0.5\",\n \"qsl:font-mono qsl:text-meta qsl:leading-[1.6] qsl:text-muted-foreground qsl:transition-colors\",\n \"qsl:data-[state=running]:border-[color-mix(in_srgb,var(--qsl-primary)_40%,var(--qsl-border-soft))]\",\n \"qsl:data-[state=thinking]:border-[color-mix(in_srgb,var(--qsl-primary)_40%,var(--qsl-border-soft))]\",\n \"qsl:data-[state=error]:border-[color-mix(in_srgb,var(--qsl-destructive)_45%,var(--qsl-border-soft))]\",\n \"qsl:data-[state=done]:opacity-85\",\n);\nconst chipInteractiveClasses = \"qsl:cursor-pointer qsl:hover:border-border qsl:hover:bg-secondary qsl:hover:text-foreground qsl:focus-visible:border-border qsl:focus-visible:bg-secondary qsl:focus-visible:text-foreground qsl:focus-visible:outline-none qsl:data-[state=done]:hover:opacity-100 qsl:data-[state=done]:focus-visible:opacity-100\";\n\nconst collapseAtBottomFrom = 11;\n\nconst maxAnnouncementsAtOnce = 2;\n\nconst bubbleBodyClasses = \"qsl:relative qsl:max-w-[86%] qsl:px-3 qsl:py-2 qsl:leading-[var(--qsl-chat-line-height,1.625)] qsl:[overflow-wrap:anywhere] qsl:@max-[620px]/chat:max-w-full\";\n\nfunction isStep(message?: Message): boolean {\n return !!message && (message.role === \"thinking\" || message.role === \"tool\");\n}\n\nfunction isOpenAction(message: Message): message is Message & { action: PendingAction } {\n return message.role === \"action\" && message.action !== undefined && message.action.status === undefined;\n}\n\nfunction defaultArgumentsText(tool: ToolInfo): string {\n return prettyJson(tool.arguments);\n}\n\n/**\n * The transcript: its own scroll container with autoscroll while you are at the bottom, and a\n * jump-to-end button as soon as you are reading. Usable read-only without a composer.\n */\nexport function ChatMessages({\n messages,\n owner,\n detailMode = \"current\",\n running = false,\n working,\n stepsExpandable = true,\n texts,\n toolArgumentsText = defaultArgumentsText,\n renderTool,\n renderAction,\n onDismissAction,\n onLinkClick,\n emptyState,\n className,\n scrollerClassName,\n showTimestamps = false,\n announce,\n scrollerRef,\n maxWidth,\n horizontalPadding,\n jumpToEndThreshold = 120,\n appearance,\n timestampOptions,\n codeBlockOptions,\n bubbleOptions,\n messageActions,\n toolElapsedThreshold = 3000,\n}: {\n messages: Message[];\n /** Contributions with this Message.sender appear without a speech bubble; null keeps the message defaults. */\n owner?: string | null;\n detailMode?: DetailMode;\n running?: boolean;\n working?: ReactNode;\n /** false = thinking and tool steps cannot be expanded (no popover). */\n stepsExpandable?: boolean;\n texts?: Partial<ChatTexts>;\n toolArgumentsText?: (tool: ToolInfo) => string;\n /** Custom rendering for single tools; undefined = default rendering. */\n renderTool?: (tool: ToolInfo) => ReactNode | undefined;\n /** Rendering of a pending action by its owner; undefined = generic card. */\n renderAction?: (action: PendingAction, text: string) => ReactNode | undefined;\n onDismissAction?: (actionId: string) => void;\n /** Intercepts clicks on Markdown links; true = handled, the browser does not follow. */\n onLinkClick?: LinkClickHandler;\n emptyState?: ReactNode;\n className?: string;\n /** Host classes for the scroll container (data-quassel-transcript). */\n scrollerClassName?: string;\n /** true = subtle HH:MM column to the left of each block (Message.at). */\n showTimestamps?: boolean;\n /** Screen reader announcement of finished answers and new actions; false = the host announces itself. */\n announce?: false | ((announcement: ChatAnnouncement) => string | undefined);\n /** Exposes the scroll container so hosts can scroll without querying the DOM. */\n scrollerRef?: (element: HTMLDivElement | null) => void;\n maxWidth?: CSSProperties[\"maxWidth\"];\n horizontalPadding?: CSSProperties[\"paddingInline\"];\n jumpToEndThreshold?: number;\n appearance?: ChatAppearance;\n timestampOptions?: TimestampOptions;\n codeBlockOptions?: CodeBlockOptions;\n bubbleOptions?: BubbleOptions;\n messageActions?: MessageActionsOptions;\n /** Milliseconds before a running tool call shows its elapsed time (from Message.at) while running; false = never. */\n toolElapsedThreshold?: number | false;\n}) {\n const allTexts = { ...defaultTexts, ...texts };\n const { Button } = useQuasselComponents();\n const scrollArea = useRef<HTMLDivElement>(null);\n const threadRef = useRef<HTMLDivElement>(null);\n const scrollbarDragging = useRef(false);\n const touchY = useRef<number | undefined>(undefined);\n const [showJumpToEnd, setShowJumpToEnd] = useState(false);\n const [scroll] = useState(() => createChatScroll());\n const sendScope = useContext(ChatSendContext);\n const dock = useContext(ChatActionDock);\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n if (!showTimestamps || timestampOptions?.format !== \"relative\") return;\n setNow(Date.now());\n const timer = window.setInterval(() => setNow(Date.now()), 15_000);\n return () => window.clearInterval(timer);\n }, [showTimestamps, timestampOptions?.format]);\n\n // The transcript at mount time and whole batches (reset with replay) count as known, not as new.\n const announced = useRef<ReadonlySet<string>>(new Set(messages.map((message) => message.key)));\n useEffect(() => {\n const due = messages.filter((message, index) => !announced.current.has(message.key) && (\n message.role === \"action\"\n ? isOpenAction(message)\n : message.role === \"assistant\" && message.text.trim() !== \"\" && (message.closed === true || (!running && index === messages.length - 1))\n ));\n if (due.length === 0) {\n return;\n }\n announced.current = new Set([...announced.current, ...due.map((message) => message.key)]);\n if (announce === false || due.length > maxAnnouncementsAtOnce) {\n return;\n }\n due\n .map((message) => announce\n ? announce({ kind: message.role === \"action\" ? \"action\" : \"reply\", message })\n : markdownPlainText(message.text))\n .forEach((text) => text && announceText(text));\n }, [messages, running, announce]);\n const updateJumpVisibility = useCallback((viewport: HTMLDivElement) => {\n if (viewport.clientHeight > 0) setShowJumpToEnd(viewport.scrollHeight - viewport.clientHeight - viewport.scrollTop > jumpToEndThreshold);\n }, [jumpToEndThreshold]);\n useLayoutEffect(() => sendScope?.subscribe(() => {\n const viewport = scrollArea.current;\n if (!viewport) return;\n scroll.jump(viewport);\n updateJumpVisibility(viewport);\n }), [sendScope, scroll, updateJumpVisibility]);\n\n const pauseUp = (viewport: HTMLDivElement, target: EventTarget) => {\n let element = target instanceof Element ? target : null;\n while (element && element !== viewport) {\n if (element.scrollTop > 0 && /auto|scroll/.test(getComputedStyle(element).overflowY)) return;\n element = element.parentElement;\n }\n scroll.pause(viewport);\n };\n\n const checkEnd = useCallback(() => {\n const area = scrollArea.current;\n if (area) {\n scroll.scroll(area, scrollbarDragging.current);\n updateJumpVisibility(area);\n }\n }, [scroll, updateJumpVisibility]);\n\n useEffect(() => {\n const finishDrag = () => {\n if (scrollbarDragging.current && scrollArea.current) scroll.scroll(scrollArea.current, true);\n scrollbarDragging.current = false;\n };\n window.addEventListener(\"pointerup\", finishDrag);\n window.addEventListener(\"pointercancel\", finishDrag);\n return () => {\n window.removeEventListener(\"pointerup\", finishDrag);\n window.removeEventListener(\"pointercancel\", finishDrag);\n };\n }, [scroll]);\n\n // Content growth does not change the follow mode; lazily loaded media and the composer count too.\n useLayoutEffect(() => {\n const area = scrollArea.current;\n if (!area) return;\n const align = () => {\n scroll.layout(area, scrollbarDragging.current);\n updateJumpVisibility(area);\n };\n align();\n const observer = new ResizeObserver(align);\n observer.observe(area);\n if (threadRef.current) observer.observe(threadRef.current, { box: \"border-box\" });\n return () => observer.disconnect();\n });\n\n const visible = useMemo(\n () => {\n // Your own inputs after the running step do not end it; any other message does.\n const lastNonUser = messages.reduce((last, message, index) => message.role === \"user\" ? last : index, -1);\n return messages.filter((message, index) => {\n if (dock !== undefined && isOpenAction(message)) {\n return false;\n }\n if (detailMode === \"current\" && isStep(message)) {\n return running && index === lastNonUser\n && (message.role === \"thinking\" ? !message.closed : stepState(message) === \"running\");\n }\n if ((message.role === \"thinking\" || message.role === \"assistant\") && message.text.trim() === \"\" && !message.attachments?.length) {\n return false;\n }\n if (message.role === \"thinking\" || message.role === \"tool\") {\n return detailMode !== \"off\";\n }\n return true;\n });\n },\n [messages, detailMode, running, dock],\n );\n const openActions = dock ? messages.filter(isOpenAction) : [];\n\n const withTime = (content: ReactNode, key: string, at: string | undefined, dense = false): ReactNode =>\n showTimestamps\n ? (\n <div className={cn(\"qsl:flex qsl:items-baseline qsl:gap-2\", dense ? denseStepClasses : stepClasses)} key={`time-${key}`}>\n <time dateTime={messageDate(at)?.toISOString()} className={cn(\"qsl:flex-none qsl:text-meta qsl:tabular-nums qsl:text-muted-foreground qsl:opacity-85\",\n timestampOptions?.format && timestampOptions.format !== \"time\" ? \"qsl:w-[clamp(60px,20%,120px)]\" : \"qsl:w-[34px]\")}>\n {messageDate(at) ? timestampLabel(messageDate(at)!, timestampOptions, now) : \"\"}\n </time>\n <div className=\"qsl:min-w-0 qsl:flex-1 qsl:[&>*:first-child]:mt-0\">{content}</div>\n </div>\n )\n : content;\n\n // In the chip modes consecutive steps move together into one wrapping line, in grouped mode into one expandable line.\n const chipMode = detailMode === \"current\" || detailMode === \"chips\" || detailMode === \"icons\";\n const elapsedAfter = running && toolElapsedThreshold !== false ? toolElapsedThreshold : undefined;\n const groupMode = detailMode === \"grouped\";\n const blocks: ReactNode[] = [];\n let lastDay: string | undefined;\n let group: Message[] = [];\n const closeGroup = () => {\n if (group.length > 0) {\n const runningStep = running ? [...group].reverse().find((message) => [\"running\", \"thinking\"].includes(stepState(message))) : undefined;\n blocks.push(withTime(\n groupMode ? (\n <StepGroup\n elapsedAfter={elapsedAfter}\n expandable={stepsExpandable}\n runningStep={runningStep}\n key={group[0].key}\n messages={group}\n texts={allTexts}\n toolArgumentsText={toolArgumentsText}\n />\n ) : (\n <StepRow\n elapsedAfter={elapsedAfter}\n expandable={stepsExpandable}\n key={group[0].key}\n messages={group}\n withText={detailMode !== \"icons\"}\n texts={allTexts}\n toolArgumentsText={toolArgumentsText}\n toolLabel={detailMode === \"current\" && !stepsExpandable ? allTexts.currentTool : undefined}\n />\n ),\n group[0].key,\n group[0].at,\n ));\n group = [];\n }\n };\n visible.forEach((message, index) => {\n const date = timestampOptions?.showDaySeparators ? messageDate(message.at) : undefined;\n if (date) {\n const day = timestampDay(date, timestampOptions);\n if (day.key !== lastDay) {\n closeGroup();\n blocks.push(<div className={cn(stepClasses, \"qsl:text-center qsl:text-xs qsl:text-muted-foreground\")} data-chat=\"day-separator\" data-day={day.key} key={`day-${message.key}`}>{day.label}</div>);\n lastDay = day.key;\n }\n }\n const customRendering = message.role === \"tool\" && message.tool && detailMode !== \"current\" ? renderTool?.(message.tool) : undefined;\n if (customRendering !== undefined) {\n closeGroup();\n blocks.push(withTime(\n <div className={stepClasses} key={message.key}>\n {customRendering}\n </div>,\n message.key,\n message.at,\n ));\n return;\n }\n if ((chipMode || groupMode) && isStep(message)) {\n group = [...group, message];\n return;\n }\n closeGroup();\n const dense = isStep(message) && isStep(visible[index - 1]);\n blocks.push(withTime(\n <Bubble\n detailMode={detailMode}\n dense={dense}\n elapsedAfter={elapsedAfter}\n expandable={stepsExpandable}\n key={message.key}\n message={message}\n plain={owner != null && message.sender === owner}\n texts={allTexts}\n toolArgumentsText={toolArgumentsText}\n renderAction={renderAction}\n onDismissAction={onDismissAction}\n bubbleOptions={bubbleOptions}\n messageActions={messageActions}\n />,\n message.key,\n message.at,\n dense,\n ));\n });\n closeGroup();\n\n const transcript = (\n <div className={cn(\"qsl:@container/chat qsl:relative qsl:flex qsl:min-h-0 qsl:flex-1 qsl:flex-col\", className)} data-quassel=\"\" style={{\n ...appearanceStyle(appearance),\n \"--qsl-chat-content-max-width\": typeof maxWidth === \"number\" ? `${maxWidth}px` : maxWidth,\n \"--qsl-chat-horizontal-padding\": typeof horizontalPadding === \"number\" ? `${horizontalPadding}px` : horizontalPadding,\n } as CSSProperties}>\n <div\n aria-label={allTexts.transcript}\n className={cn(\n \"qsl:min-h-0 qsl:flex-1 qsl:cursor-default qsl:overflow-y-auto qsl:text-[length:var(--qsl-chat-font-size,13px)] qsl:text-foreground\",\n \"qsl:[--qsl-fade-edge:calc(100%_-_var(--qsl-composer-height,0px))]\",\n \"qsl:[-webkit-mask-image:linear-gradient(to_bottom,#000_calc(var(--qsl-fade-edge)_-_40px),transparent_calc(var(--qsl-fade-edge)_+_16px))]\",\n \"qsl:[mask-image:linear-gradient(to_bottom,#000_calc(var(--qsl-fade-edge)_-_40px),transparent_calc(var(--qsl-fade-edge)_+_16px))]\",\n \"qsl:in-data-[tone=material]:p-0\",\n scrollerClassName,\n )}\n data-quassel-transcript=\"\"\n onScroll={checkEnd}\n onWheel={(event) => { if (!event.ctrlKey && event.deltaY < 0) pauseUp(event.currentTarget, event.target); }}\n onKeyDown={(event) => {\n const editable = event.target instanceof Element && event.target.closest(\"input, textarea, select, [contenteditable=true]\");\n if (!editable && ([\"ArrowUp\", \"PageUp\", \"Home\"].includes(event.key) || event.target === event.currentTarget && event.key === \" \" && event.shiftKey)) pauseUp(event.currentTarget, event.target);\n }}\n onPointerDown={(event) => {\n const viewport = event.currentTarget;\n scrollbarDragging.current = event.clientX >= viewport.getBoundingClientRect().right - Math.max(16, viewport.offsetWidth - viewport.clientWidth);\n }}\n onTouchStart={(event) => { touchY.current = event.touches[0]?.clientY; }}\n onTouchMove={(event) => {\n const next = event.touches[0]?.clientY;\n if (next !== undefined && touchY.current !== undefined && next > touchY.current) pauseUp(event.currentTarget, event.target);\n touchY.current = next;\n }}\n role=\"region\"\n tabIndex={0}\n ref={(element) => {\n scrollArea.current = element;\n scrollerRef?.(element);\n }}\n >\n {visible.length === 0 && !running ? (\n emptyState ?? null\n ) : (\n <div\n aria-busy={running || undefined}\n className={cn(\n \"qsl:mx-auto qsl:w-[calc(100%_-_2_*_var(--qsl-chat-horizontal-padding,24px))] qsl:max-w-[var(--qsl-chat-content-max-width,none)] qsl:pt-2\",\n \"qsl:pb-[calc(var(--qsl-composer-height,0px)_+_max(3.25em,40px))]\",\n \"qsl:in-data-[tone=material]:[&>*:first-child]:mt-0\",\n )}\n ref={threadRef}\n >\n {blocks}\n {running && (working ?? <WorkingScenes label={allTexts.working} />)}\n </div>\n )}\n </div>\n {showJumpToEnd && (\n <div className=\"qsl:pointer-events-none qsl:absolute qsl:inset-x-0 qsl:bottom-[calc(var(--qsl-composer-height,0px)_+_12px)] qsl:z-10 qsl:flex qsl:justify-center\">\n <Button aria-label={allTexts.jumpToEnd} className=\"qsl:pointer-events-auto qsl:rounded-full qsl:border qsl:border-primary-foreground/20 qsl:shadow-md\" size=\"icon\" title={allTexts.jumpToEnd} variant=\"default\" onClick={() => {\n if (scrollArea.current) {\n scroll.jump(scrollArea.current);\n updateJumpVisibility(scrollArea.current);\n }\n }}>\n <ChevronDownIcon />\n </Button>\n </div>\n )}\n {dock && openActions.length > 0 && createPortal(\n <div className=\"qsl:flex qsl:flex-col qsl:gap-[var(--qsl-chat-dense-message-gap,8px)] qsl:text-[length:var(--qsl-chat-font-size,13px)] qsl:text-foreground\" style={appearanceStyle(appearance)}>\n {openActions.map((message) => (\n <div key={message.key}>\n <ActionContent action={message.action} onDismissAction={onDismissAction} renderAction={renderAction} text={message.text} texts={allTexts} />\n </div>\n ))}\n </div>,\n dock,\n )}\n </div>\n );\n\n return <MarkdownLinks onLinkClick={onLinkClick}><MarkdownCodeBlocks options={codeBlockOptions} texts={allTexts}>{transcript}</MarkdownCodeBlocks></MarkdownLinks>;\n}\n\n/** Consecutive steps as chips side by side; the line wraps when space runs out. */\nfunction StepRow({\n messages,\n withText,\n expandable,\n elapsedAfter,\n texts,\n toolArgumentsText,\n toolLabel,\n}: {\n messages: Message[];\n withText: boolean;\n expandable: boolean;\n elapsedAfter: number | undefined;\n texts: ChatTexts;\n toolArgumentsText: (tool: ToolInfo) => string;\n toolLabel?: string;\n}) {\n const [detail, setDetail] = useState<{ key: string; position: { x: number; y: number } }>();\n const open = expandable && detail && messages.find((message) => message.key === detail.key);\n\n return (\n <div className={cn(stepClasses, \"qsl:flex qsl:flex-wrap qsl:items-center qsl:gap-x-1.5 qsl:gap-y-1 qsl:pl-6\")} data-step=\"row\">\n {messages.map((message) => {\n const thinking = message.role === \"thinking\";\n const tool = message.tool;\n const state = stepState(message);\n const running = state === \"running\" || state === \"thinking\";\n const label = thinking ? texts.thinkingChip : toolLabel ?? (tool?.name || message.text || texts.toolChip);\n const content = (\n <>\n {thinking ? (\n <SparklesIcon size={11} />\n ) : (\n <WrenchIcon className={tool?.isError ? \"qsl:text-destructive\" : undefined} size={11} />\n )}\n {withText && <span className=\"qsl:min-w-0 qsl:self-baseline qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap\">{label}</span>}\n {withText && <ToolElapsed after={elapsedAfter} className=\"qsl:flex-none qsl:self-baseline\" message={message} texts={texts} />}\n {withText && <span className=\"qsl:inline-flex qsl:w-2.5 qsl:flex-none qsl:items-center qsl:justify-center qsl:text-success\">{state === \"done\" && <CheckIcon size={10} />}</span>}\n </>\n );\n const classes = cn(chipClasses, !withText && \"qsl:p-1\", running && \"qsl:animate-fade-pulse qsl:motion-reduce:animate-none\");\n if (!expandable) {\n return (\n <span className={classes} data-kind={thinking ? \"thinking\" : \"tool\"} data-state={state} data-step=\"chip\" key={message.key} title={label}>\n {content}\n </span>\n );\n }\n return (\n <button\n aria-haspopup=\"dialog\"\n className={cn(classes, chipInteractiveClasses)}\n data-kind={thinking ? \"thinking\" : \"tool\"}\n data-state={state}\n data-step=\"chip\"\n key={message.key}\n onClick={(event) => setDetail({ key: message.key, position: { x: event.clientX, y: event.clientY } })}\n title={label}\n type=\"button\"\n >\n {content}\n </button>\n );\n })}\n {open && detail && (\n <StepPopover\n message={open}\n position={detail.position}\n texts={texts}\n toolArgumentsText={toolArgumentsText}\n onClose={() => setDetail(undefined)}\n />\n )}\n </div>\n );\n}\n\n/** Consecutive steps behind a header line; expanded, they stand below it as single-line rows. */\nfunction StepGroup({\n messages,\n runningStep,\n elapsedAfter,\n expandable,\n texts,\n toolArgumentsText,\n}: {\n messages: Message[];\n /** The step the collapsed header names while the chat runs; undefined = nothing running. */\n runningStep: Message | undefined;\n elapsedAfter: number | undefined;\n expandable: boolean;\n texts: ChatTexts;\n toolArgumentsText: (tool: ToolInfo) => string;\n}) {\n const [open, setOpen] = useState(false);\n const header = useRef<HTMLButtonElement>(null);\n const collapsedFromBottom = useRef(false);\n useLayoutEffect(() => {\n if (!open && collapsedFromBottom.current) {\n collapsedFromBottom.current = false;\n header.current?.scrollIntoView({ block: \"nearest\" });\n }\n }, [open]);\n const active = runningStep !== undefined;\n const failed = messages.some((message) => message.tool?.isError);\n const count = messages.length === 1 ? texts.stepGroupOne : texts.stepGroupMany.replace(\"{count}\", String(messages.length));\n const runningLabel = runningStep && (runningStep.role === \"thinking\" ? texts.thinkingChip : runningStep.tool?.name || runningStep.text || texts.toolChip);\n\n return (\n <div className={stepClasses} data-step=\"group\">\n <button\n aria-expanded={open}\n className={cn(traceClasses, traceButtonClasses, \"qsl:items-center qsl:pl-1\", active && \"qsl:animate-fade-pulse qsl:motion-reduce:animate-none\")}\n onClick={() => setOpen((value) => !value)}\n ref={header}\n type=\"button\"\n >\n <ChevronRightIcon className={cn(\"qsl:flex-none qsl:opacity-60 qsl:transition-transform\", open && \"qsl:rotate-90\")} size={12} />\n <LayersIcon className={failed ? traceErrorIconClasses : traceIconClasses} size={12} />\n <span className={cn(traceLineClasses, \"qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap\")}>\n {count}\n {runningLabel && <span className={traceRunningClasses}>{runningLabel} {texts.toolRunning}</span>}\n {runningStep && <ToolElapsed after={elapsedAfter} message={runningStep} texts={texts} />}\n </span>\n </button>\n {open && (\n <div className=\"qsl:mt-0.5 qsl:flex qsl:flex-col qsl:gap-0.5 qsl:pl-3\">\n {messages.map((message) => (\n <TraceLine className=\"qsl:pl-3\" elapsedAfter={elapsedAfter} expandable={expandable} key={message.key} message={message} texts={texts} toolArgumentsText={toolArgumentsText} />\n ))}\n </div>\n )}\n {open && messages.length >= collapseAtBottomFrom && (\n <button\n className={cn(traceClasses, traceButtonClasses, \"qsl:mt-0.5 qsl:items-center qsl:pl-1\")}\n data-step=\"group-collapse\"\n onClick={() => {\n collapsedFromBottom.current = true;\n setOpen(false);\n }}\n type=\"button\"\n >\n <ChevronUpIcon className=\"qsl:flex-none qsl:opacity-60\" size={12} />\n <span className={traceLineClasses}>{texts.stepGroupCollapse}</span>\n </button>\n )}\n </div>\n );\n}\n\n/** One step as one line; when enabled, a click opens the details in the popover. */\nfunction TraceLine({\n message,\n className,\n elapsedAfter,\n expandable,\n texts,\n toolArgumentsText,\n}: {\n message: Message;\n className: string;\n elapsedAfter: number | undefined;\n expandable: boolean;\n texts: ChatTexts;\n toolArgumentsText: (tool: ToolInfo) => string;\n}) {\n const [detailPosition, setDetailPosition] = useState<{ x: number; y: number }>();\n const thinking = message.role === \"thinking\";\n const tool = message.tool;\n const classes = cn(traceClasses, className);\n const line = cn(traceLineClasses, thinking && \"qsl:font-sans qsl:italic qsl:whitespace-pre-wrap\", \"qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap\");\n const content = (\n <>\n {thinking ? (\n <SparklesIcon className={traceIconClasses} size={12} />\n ) : (\n <WrenchIcon className={tool?.isError ? traceErrorIconClasses : traceIconClasses} size={12} />\n )}\n <span className={line}>\n {message.text}\n {tool && tool.result === undefined && <span className={traceRunningClasses}>{texts.toolRunning}</span>}\n <ToolElapsed after={elapsedAfter} message={message} texts={texts} />\n </span>\n </>\n );\n const marks = { \"data-compact\": \"true\", \"data-kind\": thinking ? \"thinking\" : \"tool\", \"data-step\": \"line\" } as const;\n if (!expandable) {\n return <div className={classes} {...marks}>{content}</div>;\n }\n return (\n <>\n <button\n aria-expanded={detailPosition !== undefined}\n aria-haspopup=\"dialog\"\n className={cn(classes, traceButtonClasses)}\n {...marks}\n onClick={(event) => setDetailPosition({ x: event.clientX, y: event.clientY })}\n type=\"button\"\n >\n {content}\n </button>\n {detailPosition && (\n <StepPopover\n message={message}\n position={detailPosition}\n texts={texts}\n toolArgumentsText={toolArgumentsText}\n onClose={() => setDetailPosition(undefined)}\n />\n )}\n </>\n );\n}\n\n/** Elapsed time of a running tool call since Message.at; aria-hidden, so the ticking number never reaches screen readers. */\nfunction ToolElapsed({ message, after, texts, className = traceRunningClasses }: { message: Message; after: number | undefined; texts: ChatTexts; className?: string }) {\n const start = stepState(message) === \"running\" ? messageDate(message.at)?.getTime() : undefined;\n return after === undefined || start === undefined ? null : <Elapsed after={after} className={className} start={start} texts={texts} />;\n}\n\nfunction Elapsed({ start, after, className, texts }: { start: number; after: number; className: string; texts: ChatTexts }) {\n const elapsed = useElapsed(start);\n if (elapsed === undefined || elapsed < after) return null;\n return <span aria-hidden=\"true\" className={cn(className, \"qsl:tabular-nums\")} data-step=\"elapsed\">{formatElapsed(elapsed, texts)}</span>;\n}\n\nfunction Bubble({\n message,\n plain,\n detailMode,\n dense,\n elapsedAfter,\n expandable,\n texts,\n toolArgumentsText,\n renderAction,\n onDismissAction,\n bubbleOptions,\n messageActions,\n}: {\n message: Message;\n plain: boolean;\n detailMode: DetailMode;\n dense: boolean;\n elapsedAfter: number | undefined;\n expandable: boolean;\n texts: ChatTexts;\n toolArgumentsText: (tool: ToolInfo) => string;\n renderAction?: (action: PendingAction, text: string) => ReactNode | undefined;\n onDismissAction?: (actionId: string) => void;\n bubbleOptions?: BubbleOptions;\n messageActions?: MessageActionsOptions;\n}) {\n const stepSpacing = dense ? denseStepClasses : stepClasses;\n\n if (message.role === \"thinking\" || (message.role === \"tool\" && message.tool)) {\n if (detailMode === \"compact\") {\n return <TraceLine className={stepSpacing} elapsedAfter={elapsedAfter} expandable={expandable} message={message} texts={texts} toolArgumentsText={toolArgumentsText} />;\n }\n const thinking = message.role === \"thinking\";\n const tool = message.tool;\n const icon = thinking ? (\n <SparklesIcon className={traceIconClasses} size={12} />\n ) : (\n <WrenchIcon className={tool?.isError ? traceErrorIconClasses : traceIconClasses} size={12} />\n );\n const line = (\n <>\n {message.text}\n {tool && tool.result === undefined && <span className={traceRunningClasses}>{texts.toolRunning}</span>}\n <ToolElapsed after={elapsedAfter} message={message} texts={texts} />\n </>\n );\n return (\n <div className={cn(traceClasses, stepSpacing)} data-kind={thinking ? \"thinking\" : \"tool\"} data-step=\"detail\">\n {icon}\n <div className=\"qsl:min-w-0 qsl:flex-1\">\n <div className={cn(traceLineClasses, thinking && \"qsl:font-sans qsl:italic qsl:whitespace-pre-wrap\")}>{line}</div>\n {tool && (\n <div className=\"qsl:mt-0.5 qsl:border-l-2 qsl:border-border-soft qsl:pl-2\">\n <pre className=\"qsl:mb-0.5 qsl:max-h-[208px] qsl:overflow-auto qsl:font-mono qsl:text-meta qsl:leading-[1.375] qsl:break-all qsl:whitespace-pre-wrap qsl:opacity-80\">{toolArgumentsText(tool)}</pre>\n {tool.result !== undefined && (\n <pre className={cn(\"qsl:mb-0.5 qsl:max-h-[208px] qsl:overflow-auto qsl:font-mono qsl:text-meta qsl:leading-[1.375] qsl:break-all qsl:whitespace-pre-wrap qsl:opacity-80\",\n tool.isError && \"qsl:text-destructive qsl:opacity-100\")}>{prettyJson(tool.result)}</pre>\n )}\n </div>\n )}\n </div>\n </div>\n );\n }\n\n if (message.role === \"action\" && message.action) {\n return (\n <div className={stepSpacing}>\n <ActionContent action={message.action} onDismissAction={onDismissAction} renderAction={renderAction} text={message.text} texts={texts} />\n </div>\n );\n }\n\n if (message.role === \"system\") {\n return (\n <div className={cn(stepSpacing, \"qsl:border-l-2 qsl:border-destructive/50 qsl:pl-3 qsl:text-sm qsl:text-muted-foreground\")} data-message=\"system\">\n <Markdown text={message.text} />\n <MessageAttachments label={texts.attachments} message={message} />\n </div>\n );\n }\n\n if (!message.text.trim() && !message.attachments?.length) return null;\n\n const variant = bubbleOptions?.variant ?? \"default\";\n const useBubble = !plain && variant !== \"plain\" && (variant === \"bubbles\" || message.role === \"user\" || !!message.bubble);\n const side = (message.role === \"user\" ? bubbleOptions?.userSide : bubbleOptions?.assistantSide)\n ?? message.bubble?.side ?? (message.role === \"user\" ? \"end\" : \"start\");\n const sender = bubbleOptions?.senderLabel?.(message) ?? message.bubble?.label ?? message.sender;\n const showSender = bubbleOptions?.showSender ?? (!!message.bubble?.label && !plain);\n const content = <>\n {showSender && sender && <span className={cn(\"qsl:mb-[5px] qsl:table qsl:text-label qsl:leading-[1.45] qsl:font-semibold\",\n useBubble && message.bubble && \"qsl:rounded-full qsl:border qsl:border-white/30 qsl:bg-black/15 qsl:px-[7px] qsl:py-px qsl:tracking-[0.02em]\")} data-chat=\"sender\">{sender}</span>}\n <Markdown text={message.text} streaming={message.role === \"assistant\" && !message.closed} />\n <MessageAttachments label={texts.attachments} message={message} />\n {message.steered && <small className=\"qsl:mt-1 qsl:block qsl:text-label qsl:leading-[1.45] qsl:opacity-70\" data-chat=\"steered\">{texts.steered}</small>}\n <MessageActions message={message} options={messageActions} texts={texts} />\n </>;\n const cursor = message.role === \"assistant\" && message.textCursor ? JSON.stringify(message.textCursor) : undefined;\n if (!useBubble) return (\n <div data-chat-text-cursor={cursor} className={cn(stepSpacing, \"qsl:group qsl:relative qsl:w-full qsl:leading-[var(--qsl-chat-line-height,1.625)] qsl:text-foreground\")} data-message=\"answer\">\n {content}\n </div>\n );\n return (\n <div data-chat-text-cursor={cursor} className={cn(stepSpacing, \"qsl:flex\", side === \"end\" ? \"qsl:justify-end\" : \"qsl:justify-start\")}\n data-message={message.role === \"user\" && !message.bubble && variant === \"default\" ? \"user\" : \"bubble\"} data-side={side}>\n <div className={cn(bubbleBodyClasses, \"qsl:group\", message.bubble\n ? \"qsl:rounded-lg qsl:text-white qsl:[--qsl-scroll-cover:var(--qsl-primary)]\"\n : \"qsl:rounded-[var(--qsl-bubble-radius,10px_10px_4px_10px)] qsl:border qsl:border-border qsl:bg-secondary qsl:text-foreground qsl:[--qsl-scroll-cover:var(--qsl-secondary)] qsl:in-data-[tone=material]:rounded-[var(--qsl-bubble-radius,9px)] qsl:in-data-[tone=material]:border-glass-edge/20 qsl:in-data-[tone=material]:bg-primary/15 qsl:in-data-[tone=material]:text-foreground\")}\n data-tone={message.bubble ? \"on-color\" : undefined}\n style={{ background: message.bubble?.color, maxWidth: bubbleOptions?.maxWidth }}>\n {content}\n </div>\n </div>\n );\n}\n\nfunction ActionContent({\n action,\n text,\n texts,\n renderAction,\n onDismissAction,\n}: {\n action: PendingAction;\n text: string;\n texts: ChatTexts;\n renderAction?: (action: PendingAction, text: string) => ReactNode | undefined;\n onDismissAction?: (actionId: string) => void;\n}) {\n return renderAction?.(action, text) ?? (\n <PendingActionCard\n action={action}\n dismissedLabel={texts.actionDismissed}\n dismissLabel={texts.dismissAction}\n onDismiss={onDismissAction ? () => onDismissAction(action.actionId) : undefined}\n text={text}\n waitingLabel={texts.pendingAction}\n />\n );\n}\n\nfunction MessageAttachments({ message, label }: { message: Message; label: string }) {\n if (!message.attachments?.length) return null;\n return (\n <ul className=\"qsl:mt-2.5 qsl:flex qsl:flex-wrap qsl:gap-2\" aria-label={label}>\n {message.attachments.map((attachment, index) => (\n <li className=\"qsl:relative qsl:flex qsl:w-[190px] qsl:max-w-full qsl:min-w-0 qsl:flex-col qsl:overflow-hidden qsl:rounded-lg qsl:border qsl:border-border qsl:text-sm\" key={`${attachment.url}-${index}`}>\n {attachment.mediaType.startsWith(\"image/\") && <a href={attachmentDownloadUrl(attachment.url)} download={attachment.name}><img className=\"qsl:block qsl:h-[112px] qsl:w-full qsl:bg-secondary qsl:object-contain\" src={attachment.url} alt={attachment.name} loading=\"lazy\" /></a>}\n {attachment.mediaType.startsWith(\"video/\") && <video className=\"qsl:block qsl:h-[112px] qsl:w-full qsl:bg-secondary qsl:object-contain\" src={attachment.url} controls preload=\"metadata\" aria-label={attachment.name} />}\n <div className=\"qsl:flex qsl:flex-col qsl:gap-1 qsl:p-2 qsl:[overflow-wrap:anywhere]\">\n <a className=\"qsl:font-medium\" href={attachmentDownloadUrl(attachment.url)} download={attachment.name}>{attachment.name}</a>\n <small>{formatAttachmentSize(attachment.size)}</small>\n </div>\n </li>\n ))}\n </ul>\n );\n}\n", "interface ScrollViewport {\n scrollTop: number;\n readonly scrollHeight: number;\n readonly clientHeight: number;\n}\n\nconst atEnd = (viewport: ScrollViewport) => viewport.scrollHeight - viewport.clientHeight - viewport.scrollTop <= 24;\n\nexport function createChatScroll(onFollowChange: (following: boolean) => void = () => {}) {\n let following = true;\n let lastTop = 0;\n\n const follow = (value: boolean) => {\n if (following === value) return;\n following = value;\n onFollowChange(value);\n };\n const layout = (viewport: ScrollViewport, dragging = false) => {\n if (viewport.clientHeight <= 0) return;\n if (dragging && viewport.scrollTop < lastTop && !atEnd(viewport)) follow(false);\n if (following) viewport.scrollTop = Math.max(0, viewport.scrollHeight - viewport.clientHeight);\n else if (viewport.scrollHeight <= viewport.clientHeight) follow(true);\n lastTop = viewport.scrollTop;\n };\n return {\n layout,\n pause(viewport: ScrollViewport) {\n if (viewport.scrollTop > 0) follow(false);\n },\n scroll(viewport: ScrollViewport, dragging = false) {\n if (viewport.clientHeight <= 0) return;\n if (atEnd(viewport)) follow(true);\n else if (dragging && viewport.scrollTop < lastTop) follow(false);\n lastTop = viewport.scrollTop;\n },\n jump(viewport: ScrollViewport) {\n follow(true);\n layout(viewport);\n },\n };\n}\n", "import { createContext, ReactNode, useCallback, useContext, useRef } from \"react\";\nimport { Streamdown, type Components } from \"streamdown\";\nimport { CheckIcon, CopyIcon } from \"lucide-react\";\nimport { cn } from \"./ui/cn\";\nimport { useAllowUrl, useQuasselComponents } from \"./QuasselProvider\";\nimport type { CodeBlockOptions } from \"./options\";\nimport { type ChatTexts, defaultTexts } from \"./texts\";\nimport { copyChatText, useChatAction } from \"./useChatAction\";\n\nexport type LinkClickHandler = (href: string, label: string) => boolean;\n\nconst LinkClickContext = createContext<LinkClickHandler | undefined>(undefined);\nconst CodeBlockContext = createContext<{ options?: CodeBlockOptions; texts: ChatTexts }>({ texts: defaultTexts });\n\nexport function MarkdownCodeBlocks({ children, options, texts }: { children: ReactNode; options?: CodeBlockOptions; texts: ChatTexts }) {\n return <CodeBlockContext.Provider value={{ options, texts }}>{children}</CodeBlockContext.Provider>;\n}\n\nfunction CodeBlock({ children }: { children?: ReactNode }) {\n const { options, texts } = useContext(CodeBlockContext);\n const { Button } = useQuasselComponents();\n const code = useRef<HTMLPreElement>(null);\n const action = useChatAction();\n const label = action.status === \"done\" ? texts.copied : texts.copyCode;\n const block = <pre ref={code} data-chat=\"code-block\"\n className={cn(scrollbar, \"qsl:my-2 qsl:overflow-auto qsl:rounded-lg qsl:bg-secondary qsl:px-3 qsl:py-2 qsl:font-mono qsl:text-sm qsl:leading-relaxed qsl:in-data-[tone=on-color]:bg-black/30 qsl:in-data-[tone=on-color]:text-inherit\")}\n style={{ maxHeight: options?.maxHeight, whiteSpace: options?.wrap ? \"pre-wrap\" : undefined, overflowWrap: options?.wrap ? \"anywhere\" : undefined }}>{children}</pre>;\n if (!options?.showCopyButton) return block;\n return <div className=\"qsl:relative\">\n {block}\n <Button aria-label={label} className=\"qsl:absolute qsl:top-1 qsl:right-1 qsl:bg-secondary\" disabled={action.status === \"pending\"} size=\"icon-sm\" title={label} variant=\"ghost\"\n onClick={() => { void action.invoke(() => copyChatText(code.current?.textContent ?? \"\", texts.clipboardUnavailable), texts.actionFailed); }}>\n {action.status === \"done\" ? <CheckIcon /> : <CopyIcon />}\n </Button>\n {action.error && <p className=\"qsl:text-sm qsl:text-destructive\" role=\"alert\">{action.error}</p>}\n </div>;\n}\n\nexport function MarkdownLinks({ children, onLinkClick }: { children: ReactNode; onLinkClick?: LinkClickHandler }) {\n return <LinkClickContext.Provider value={onLinkClick}>{children}</LinkClickContext.Provider>;\n}\n\nfunction MarkdownLink({ href, children }: { href?: string; children?: ReactNode }) {\n const onLinkClick = useContext(LinkClickContext);\n if (!href || href === \"streamdown:incomplete-link\") {\n return <span>{children}</span>;\n }\n return (\n <a\n className=\"qsl:text-primary qsl:[text-underline-offset:2px] qsl:in-data-[tone=on-color]:text-inherit qsl:in-data-[tone=on-color]:underline\"\n href={href}\n onClick={(event) => {\n if (href && onLinkClick?.(href, event.currentTarget.textContent ?? \"\")) {\n event.preventDefault();\n }\n }}\n rel=\"noreferrer\"\n target=\"_blank\"\n >\n {children}\n </a>\n );\n}\n\n// Horizontal scrollbars stay visible - otherwise the overflow cannot be found.\nconst scrollbar = \"qsl:[scrollbar-width:thin] qsl:[&::-webkit-scrollbar]:block qsl:[&::-webkit-scrollbar]:h-2 qsl:[&::-webkit-scrollbar-thumb]:rounded-full qsl:[&::-webkit-scrollbar-thumb]:bg-border\";\n\n// The cover strips hide the cut at the edge; --qsl-scroll-cover comes from the surrounding bubble.\nconst scrollCover = \"qsl:bg-[linear-gradient(to_right,var(--qsl-scroll-cover,var(--qsl-background))_50%,transparent)_left/20px_100%_no-repeat_local,linear-gradient(to_left,var(--qsl-scroll-cover,var(--qsl-background))_50%,transparent)_right/20px_100%_no-repeat_local,linear-gradient(to_right,#00000047,transparent)_left/14px_100%_no-repeat_scroll,linear-gradient(to_left,#00000047,transparent)_right/14px_100%_no-repeat_scroll]\";\n\nconst headingClasses = \"qsl:mt-3 qsl:mb-1 qsl:text-[15px] qsl:font-medium\";\nconst cellClasses = \"qsl:max-w-[44ch] qsl:border qsl:border-border qsl:px-2 qsl:py-1 qsl:text-left qsl:align-top qsl:in-data-[tone=on-color]:border-white/35\";\n\nconst components: Components = {\n h1: ({ children }) => <h1 className=\"qsl:mt-3 qsl:mb-1 qsl:text-lg qsl:font-semibold\">{children}</h1>,\n h2: ({ children }) => <h2 className={headingClasses}>{children}</h2>,\n h3: ({ children }) => <h3 className={headingClasses}>{children}</h3>,\n h4: ({ children }) => <h4 className=\"qsl:mt-2 qsl:mb-1 qsl:text-base qsl:font-medium\">{children}</h4>,\n h5: ({ children }) => <h5 className=\"qsl:mt-2 qsl:mb-1 qsl:text-base qsl:font-medium\">{children}</h5>,\n h6: ({ children }) => <h6 className=\"qsl:mt-2 qsl:mb-1 qsl:text-base qsl:font-medium\">{children}</h6>,\n p: ({ children }) => <p className=\"qsl:[p+&]:mt-2\">{children}</p>,\n ul: ({ children }) => <ul className=\"qsl:my-2 qsl:list-disc qsl:pl-6 qsl:[li>&]:my-0\">{children}</ul>,\n ol: ({ children }) => <ol className=\"qsl:my-2 qsl:list-decimal qsl:pl-6 qsl:[li>&]:my-0\">{children}</ol>,\n li: ({ children }) => <li className=\"qsl:marker:text-muted-foreground qsl:in-data-[tone=on-color]:marker:text-inherit\">{children}</li>,\n hr: () => <hr className=\"qsl:my-3 qsl:border-t qsl:border-border\" />,\n img: ({ src, alt }) => <img alt={alt} className=\"qsl:h-auto qsl:max-w-full\" src={typeof src === \"string\" ? src : undefined} />,\n blockquote: ({ children }) => (\n <blockquote className=\"qsl:my-1 qsl:border-l-2 qsl:border-border qsl:pl-3 qsl:text-muted-foreground qsl:in-data-[tone=on-color]:border-white/50 qsl:in-data-[tone=on-color]:text-inherit\">{children}</blockquote>\n ),\n strong: ({ children }) => <strong className=\"qsl:font-medium\">{children}</strong>,\n em: ({ children }) => <em>{children}</em>,\n a: ({ href, children }) => <MarkdownLink href={href}>{children}</MarkdownLink>,\n pre: ({ children }) => <CodeBlock>{children}</CodeBlock>,\n code: ({ children, className }) => (\n <code className={cn(className, \"qsl:rounded-sm qsl:bg-secondary qsl:px-1 qsl:py-0.5 qsl:font-mono qsl:text-sm qsl:[overflow-wrap:anywhere] qsl:in-data-[tone=on-color]:bg-white/20 qsl:in-data-[tone=on-color]:text-inherit\", \"qsl:[pre>&]:bg-transparent qsl:[pre>&]:p-0\")}>{children}</code>\n ),\n // Without max-content the table shrinks to the container and stacks letters.\n table: ({ children }) => (\n <div className={cn(scrollbar, scrollCover, \"qsl:my-2 qsl:overflow-x-auto\")}>\n <table className=\"qsl:w-max qsl:min-w-full qsl:border-collapse qsl:text-sm\">{children}</table>\n </div>\n ),\n thead: ({ children }) => <thead>{children}</thead>,\n tbody: ({ children }) => <tbody>{children}</tbody>,\n tr: ({ children }) => <tr>{children}</tr>,\n th: ({ children }) => <th className={cn(cellClasses, \"qsl:bg-secondary qsl:font-medium qsl:in-data-[tone=on-color]:bg-white/15 qsl:in-data-[tone=on-color]:text-inherit\")}>{children}</th>,\n td: ({ children }) => <td className={cellClasses}>{children}</td>,\n};\n\nfunction transformUrl(url: string, allowUrl?: (url: string) => boolean) {\n if (allowUrl?.(url)) return url;\n const scheme = /^[^/?#]*:/.exec(url);\n return !scheme || /^(https?|mailto|tel|ftp|irc|ircs|xmpp):$/i.test(scheme[0]) ? url : \"\";\n}\n\nexport function Markdown({ text, streaming = false }: { text: string; streaming?: boolean }) {\n const allowUrl = useAllowUrl();\n const urlTransform = useCallback((url: string) => transformUrl(url, allowUrl), [allowUrl]);\n return (\n <Streamdown\n className=\"space-y-0 text-inherit\"\n prefix=\"qsl\"\n mode={streaming ? \"streaming\" : \"static\"}\n isAnimating={streaming}\n parseIncompleteMarkdown={streaming}\n components={components}\n controls={false}\n rehypePlugins={[]}\n urlTransform={urlTransform}\n skipHtml\n >\n {text}\n </Streamdown>\n );\n}\n\n/** The same syntax as the renderer, as plain text without markup, e.g. for screen reader announcements. */\nexport function markdownPlainText(text: string): string {\n return text\n .split(\"\\n\")\n .filter((line) => !/^\\s*```\\w*\\s*$/.test(line) && !isTableDivider(line))\n .map((line) => (line.trim().startsWith(\"|\") ? splitTableRow(line).join(\", \") : line)\n .replace(/^(#{1,6})\\s+/, \"\")\n .replace(/^\\s*>\\s?/, \"\")\n .replace(/^\\s*([-*+]|\\d+[.)])\\s+/, \"\")\n .replace(/!?\\[([^\\]]*)\\]\\(([^)]+)\\)|\\*\\*([^*]+)\\*\\*|__([^_]+)__|\\*([^*]+)\\*|`([^`]+)`/g, (_, link, _href, bold, boldUnderscore, italic, code) => link ?? bold ?? boldUnderscore ?? italic ?? code)\n .trim())\n .filter((line) => line !== \"\")\n .join(\"\\n\");\n}\n\nfunction splitTableRow(line: string): string[] {\n let row = line.trim();\n if (row.startsWith(\"|\")) {\n row = row.slice(1);\n }\n if (row.endsWith(\"|\")) {\n row = row.slice(0, -1);\n }\n return row.split(\"|\").map((cell) => cell.trim());\n}\n\nfunction isTableDivider(line: string): boolean {\n return /^\\s*\\|?\\s*:?-{1,}:?\\s*(\\|\\s*:?-{1,}:?\\s*)*\\|?\\s*$/.test(line) && line.includes(\"-\");\n}\n", "import { createContext, useContext, useMemo, type ComponentType, type ReactNode, type RefObject } from \"react\";\nimport { Button } from \"./ui/button\";\nimport { Card } from \"./ui/card\";\nimport { Popover, PopoverContent } from \"./ui/popover\";\nimport { StopButton } from \"./ui/stop-button\";\nimport { Toggle } from \"./ui/toggle\";\n\nexport type QuasselButtonVariant = \"default\" | \"outline\" | \"secondary\" | \"ghost\" | \"destructive\" | \"link\";\nexport type QuasselButtonSize = \"default\" | \"xs\" | \"sm\" | \"lg\" | \"icon\" | \"icon-xs\" | \"icon-sm\" | \"icon-lg\";\n\nexport interface QuasselButtonProps {\n variant?: QuasselButtonVariant;\n size?: QuasselButtonSize;\n className?: string;\n disabled?: boolean;\n title?: string;\n \"aria-label\"?: string;\n \"aria-pressed\"?: boolean;\n onClick?: () => void;\n children?: ReactNode;\n}\n\nexport interface QuasselToggleProps {\n variant?: \"default\" | \"outline\";\n size?: \"default\" | \"sm\" | \"lg\";\n className?: string;\n disabled?: boolean;\n title?: string;\n pressed?: boolean;\n onPressedChange?: (pressed: boolean) => void;\n children?: ReactNode;\n}\n\nexport interface QuasselCardProps {\n size?: \"default\" | \"sm\";\n className?: string;\n children?: ReactNode;\n}\n\nexport interface QuasselStopButtonProps {\n label: string;\n busy?: boolean;\n size?: QuasselButtonSize;\n className?: string;\n disabled?: boolean;\n title?: string;\n onClick?: () => void;\n}\n\nexport interface QuasselPopoverProps {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n children?: ReactNode;\n}\n\nexport interface QuasselPopoverAnchor {\n getBoundingClientRect: () => DOMRect;\n contextElement?: Element;\n}\n\n/** Where popovers mount: an element, a ref or a getter; resolved when the popover opens. */\nexport type QuasselPortalTarget = HTMLElement | ShadowRoot;\nexport type QuasselPortalContainer = QuasselPortalTarget | RefObject<QuasselPortalTarget | null> | (() => QuasselPortalTarget | null | undefined);\n\nexport interface QuasselPopoverContentProps {\n anchor?: QuasselPopoverAnchor;\n align?: \"start\" | \"center\" | \"end\";\n side?: \"top\" | \"bottom\" | \"left\" | \"right\" | \"inline-start\" | \"inline-end\";\n sideOffset?: number;\n collisionPadding?: number;\n className?: string;\n \"aria-label\"?: string;\n /** The resolved portalContainer of QuasselProvider; undefined = document.body. */\n portalContainer?: QuasselPortalTarget;\n children?: ReactNode;\n}\n\n/** The primitives quassel renders; a host replaces any of them through QuasselProvider. */\nexport interface QuasselComponents {\n Button: ComponentType<QuasselButtonProps>;\n Toggle: ComponentType<QuasselToggleProps>;\n Card: ComponentType<QuasselCardProps>;\n StopButton: ComponentType<QuasselStopButtonProps>;\n Popover: ComponentType<QuasselPopoverProps>;\n PopoverContent: ComponentType<QuasselPopoverContentProps>;\n}\n\nexport const defaultComponents: QuasselComponents = { Button, Toggle, Card, StopButton, Popover, PopoverContent };\n\ninterface QuasselSettings {\n components: QuasselComponents;\n allowUrl?: (url: string) => boolean;\n portalContainer?: QuasselPortalContainer;\n}\n\nconst QuasselContext = createContext<QuasselSettings>({ components: defaultComponents });\n\nexport function QuasselProvider({ components, allowUrl, portalContainer, children }: {\n /** Replaces single primitives; the rest stay the built-in ones or those of an outer provider. */\n components?: Partial<QuasselComponents>;\n /** Keeps Markdown link and image URLs that the default policy (http, https, mailto, tel, ftp, irc, xmpp, relative) would drop. */\n allowUrl?: (url: string) => boolean;\n /** Mounts quassel's popovers inside this element instead of document.body, e.g. within the host's theme wrapper. */\n portalContainer?: QuasselPortalContainer;\n children: ReactNode;\n}) {\n const outer = useContext(QuasselContext);\n const value = useMemo(() => ({\n components: { ...outer.components, ...components },\n allowUrl: allowUrl ?? outer.allowUrl,\n portalContainer: portalContainer ?? outer.portalContainer,\n }), [outer, components, allowUrl, portalContainer]);\n return <QuasselContext.Provider value={value}>{children}</QuasselContext.Provider>;\n}\n\nexport const useQuasselComponents = (): QuasselComponents => useContext(QuasselContext).components;\n\nexport const useAllowUrl = (): ((url: string) => boolean) | undefined => useContext(QuasselContext).allowUrl;\n\nexport function useQuasselPortalContainer(): QuasselPortalTarget | undefined {\n const container = useContext(QuasselContext).portalContainer;\n const target = typeof container === \"function\" ? container() : container && \"current\" in container ? container.current : container;\n return target ?? undefined;\n}\n", "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"./cn\"\n\nconst buttonVariants = cva(\n \"qsl:group/button qsl:inline-flex qsl:shrink-0 qsl:items-center qsl:justify-center qsl:rounded-lg qsl:border qsl:border-transparent qsl:bg-clip-padding qsl:text-sm qsl:font-medium qsl:whitespace-nowrap qsl:transition-all qsl:outline-none qsl:select-none qsl:focus-visible:border-ring qsl:focus-visible:ring-3 qsl:focus-visible:ring-ring/50 qsl:active:not-aria-[haspopup]:translate-y-px qsl:disabled:pointer-events-none qsl:disabled:opacity-50 qsl:aria-invalid:border-destructive qsl:aria-invalid:ring-3 qsl:aria-invalid:ring-destructive/20 qsl:dark:aria-invalid:border-destructive/50 qsl:dark:aria-invalid:ring-destructive/40 qsl:[&_svg]:pointer-events-none qsl:[&_svg]:shrink-0 qsl:[&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"qsl:bg-primary qsl:text-primary-foreground qsl:hover:bg-primary/80\",\n outline:\n \"qsl:border-border qsl:bg-background qsl:hover:bg-muted qsl:hover:text-foreground qsl:aria-expanded:bg-muted qsl:aria-expanded:text-foreground qsl:dark:border-input qsl:dark:bg-input/30 qsl:dark:hover:bg-input/50\",\n secondary:\n \"qsl:bg-secondary qsl:text-secondary-foreground qsl:hover:bg-[color-mix(in_oklch,var(--qsl-secondary),var(--qsl-foreground)_5%)] qsl:aria-expanded:bg-secondary qsl:aria-expanded:text-secondary-foreground\",\n ghost:\n \"qsl:hover:bg-muted qsl:hover:text-foreground qsl:aria-expanded:bg-muted qsl:aria-expanded:text-foreground qsl:dark:hover:bg-muted/50\",\n destructive:\n \"qsl:bg-destructive/10 qsl:text-destructive qsl:hover:bg-destructive/20 qsl:focus-visible:border-destructive/40 qsl:focus-visible:ring-destructive/20 qsl:dark:bg-destructive/20 qsl:dark:hover:bg-destructive/30 qsl:dark:focus-visible:ring-destructive/40\",\n link: \"qsl:text-primary qsl:underline-offset-4 qsl:hover:underline\",\n },\n size: {\n default:\n \"qsl:h-8 qsl:gap-1.5 qsl:px-2.5 qsl:has-data-[icon=inline-end]:pr-2 qsl:has-data-[icon=inline-start]:pl-2\",\n xs: \"qsl:h-6 qsl:gap-1 qsl:rounded-[min(--theme(--radius-md),10px)] qsl:px-2 qsl:text-xs qsl:in-data-[slot=button-group]:rounded-lg qsl:has-data-[icon=inline-end]:pr-1.5 qsl:has-data-[icon=inline-start]:pl-1.5 qsl:[&_svg:not([class*='size-'])]:size-3\",\n sm: \"qsl:h-7 qsl:gap-1 qsl:rounded-[min(--theme(--radius-md),12px)] qsl:px-2.5 qsl:text-[0.8rem] qsl:in-data-[slot=button-group]:rounded-lg qsl:has-data-[icon=inline-end]:pr-1.5 qsl:has-data-[icon=inline-start]:pl-1.5 qsl:[&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"qsl:h-9 qsl:gap-1.5 qsl:px-2.5 qsl:has-data-[icon=inline-end]:pr-2 qsl:has-data-[icon=inline-start]:pl-2\",\n icon: \"qsl:size-8\",\n \"icon-xs\":\n \"qsl:size-6 qsl:rounded-[min(--theme(--radius-md),10px)] qsl:in-data-[slot=button-group]:rounded-lg qsl:[&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"qsl:size-7 qsl:rounded-[min(--theme(--radius-md),12px)] qsl:in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"qsl:size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-quassel=\"\"\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n", "import * as React from \"react\"\nimport { cn } from \"./cn\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-quassel=\"\"\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"qsl:group/card qsl:flex qsl:flex-col qsl:gap-(--qsl-card-spacing) qsl:overflow-hidden qsl:rounded-panel qsl:border qsl:border-border qsl:bg-card qsl:py-(--qsl-card-spacing) qsl:text-sm qsl:text-card-foreground qsl:shadow-bar qsl:[--qsl-card-spacing:--spacing(4)] qsl:has-data-[slot=card-footer]:pb-0 qsl:has-[>img:first-child]:pt-0 qsl:data-[size=sm]:[--qsl-card-spacing:--spacing(3)] qsl:data-[size=sm]:has-data-[slot=card-footer]:pb-0 qsl:*:[img:first-child]:rounded-t-xl qsl:*:[img:last-child]:rounded-b-xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Card }\n", "import { Popover as PopoverPrimitive } from \"@base-ui/react/popover\"\nimport { cn } from \"./cn\"\n\nfunction Popover({ ...props }: PopoverPrimitive.Root.Props) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\n}\n\nfunction PopoverContent({\n className,\n align = \"center\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 8,\n anchor,\n collisionPadding,\n keepMounted,\n portalContainer,\n ...props\n}: PopoverPrimitive.Popup.Props &\n Pick<\n PopoverPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\" | \"anchor\" | \"collisionPadding\"\n > & Pick<PopoverPrimitive.Portal.Props, \"keepMounted\"> & { portalContainer?: HTMLElement | ShadowRoot }) {\n return (\n <PopoverPrimitive.Portal container={portalContainer} keepMounted={keepMounted}>\n <PopoverPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n anchor={anchor}\n collisionPadding={collisionPadding}\n side={side}\n sideOffset={sideOffset}\n className=\"qsl:isolate qsl:z-[110]\"\n >\n <PopoverPrimitive.Popup\n data-quassel=\"\"\n data-quassel-popover=\"\"\n data-slot=\"popover-content\"\n className={cn(\n \"qsl:z-[110] qsl:flex qsl:w-72 qsl:origin-(--transform-origin) qsl:flex-col qsl:gap-2.5 qsl:rounded-lg qsl:bg-popover qsl:p-2.5 qsl:text-sm qsl:text-popover-foreground qsl:shadow-md qsl:ring-1 qsl:ring-foreground/10 qsl:outline-hidden qsl:duration-100 qsl:data-[side=bottom]:slide-in-from-top-2 qsl:data-[side=inline-end]:slide-in-from-left-2 qsl:data-[side=inline-start]:slide-in-from-right-2 qsl:data-[side=left]:slide-in-from-right-2 qsl:data-[side=right]:slide-in-from-left-2 qsl:data-[side=top]:slide-in-from-bottom-2 qsl:data-open:animate-in qsl:data-open:fade-in-0 qsl:data-open:zoom-in-95 qsl:data-closed:animate-out qsl:data-closed:fade-out-0 qsl:data-closed:zoom-out-95\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Positioner>\n </PopoverPrimitive.Portal>\n )\n}\n\nexport { Popover, PopoverContent }\n", "import { SquareIcon } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"./cn\";\nimport { Button } from \"./button\";\nimport { Spinner } from \"./spinner\";\n\n/** The one stop glyph: a filled red square; never used as a state icon. */\nexport function StopGlyph({ className, ...props }: Omit<ComponentProps<typeof SquareIcon>, \"fill\">) {\n return <SquareIcon aria-hidden className={cn(\"qsl:text-destructive\", className)} fill=\"currentColor\" {...props} />;\n}\n\nconst stopButtonClass = \"qsl:text-destructive qsl:hover:bg-destructive/10 qsl:hover:text-destructive qsl:dark:hover:bg-destructive/20\";\n\n/** Every stop button looks the same: the glyph as icon, the word in the tooltip, red at rest and on hover. */\nexport function StopButton({ label, busy = false, className, title, ...props }: Omit<ComponentProps<typeof Button>, \"children\" | \"variant\"> & {\n label: string;\n busy?: boolean;\n}) {\n return <Button aria-busy={busy || undefined} aria-label={label} className={cn(stopButtonClass, className)} title={title ?? label} variant=\"ghost\" {...props}>\n {busy ? <Spinner /> : <StopGlyph />}\n </Button>;\n}\n", "import { cn } from \"./cn\"\nimport { Loader2Icon } from \"lucide-react\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <Loader2Icon data-slot=\"spinner\" role=\"status\" aria-label=\"Loading\" className={cn(\"qsl:size-4 qsl:animate-spin\", className)} {...props} />\n )\n}\n\nexport { Spinner }\n", "import { Toggle as TogglePrimitive } from \"@base-ui/react/toggle\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"./cn\"\n\nconst toggleVariants = cva(\n \"qsl:group/toggle qsl:inline-flex qsl:items-center qsl:justify-center qsl:gap-1 qsl:rounded-lg qsl:text-sm qsl:font-medium qsl:whitespace-nowrap qsl:transition-all qsl:outline-none qsl:hover:bg-muted qsl:hover:text-foreground qsl:focus-visible:border-ring qsl:focus-visible:ring-[3px] qsl:focus-visible:ring-ring/50 qsl:disabled:pointer-events-none qsl:disabled:opacity-50 qsl:aria-invalid:border-destructive qsl:aria-invalid:ring-destructive/20 qsl:aria-pressed:bg-muted qsl:data-[state=on]:bg-muted qsl:dark:aria-invalid:ring-destructive/40 qsl:[&_svg]:pointer-events-none qsl:[&_svg]:shrink-0 qsl:[&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"qsl:bg-transparent\",\n outline: \"qsl:border qsl:border-input qsl:bg-transparent qsl:hover:bg-muted\",\n },\n size: {\n default:\n \"qsl:h-8 qsl:min-w-8 qsl:px-2.5 qsl:has-data-[icon=inline-end]:pr-2 qsl:has-data-[icon=inline-start]:pl-2\",\n sm: \"qsl:h-7 qsl:min-w-7 qsl:rounded-[min(--theme(--radius-md),12px)] qsl:px-2.5 qsl:text-[0.8rem] qsl:has-data-[icon=inline-end]:pr-1.5 qsl:has-data-[icon=inline-start]:pl-1.5 qsl:[&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"qsl:h-9 qsl:min-w-9 qsl:px-2.5 qsl:has-data-[icon=inline-end]:pr-2 qsl:has-data-[icon=inline-start]:pl-2\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Toggle({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {\n return (\n <TogglePrimitive\n data-quassel=\"\"\n data-slot=\"toggle\"\n className={cn(toggleVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Toggle, toggleVariants }\n", "import { useEffect, useRef, useState } from \"react\";\n\nexport function useChatAction() {\n const pending = useRef(false);\n const [status, setStatus] = useState<\"idle\" | \"pending\" | \"done\">(\"idle\");\n const [error, setError] = useState<string>();\n useEffect(() => {\n if (status !== \"done\") return;\n const timer = window.setTimeout(() => setStatus(\"idle\"), 1800);\n return () => window.clearTimeout(timer);\n }, [status]);\n const invoke = async (action: () => void | Promise<void>, failureLabel: string) => {\n if (pending.current) return;\n pending.current = true;\n setError(undefined);\n setStatus(\"pending\");\n try {\n await action();\n setStatus(\"done\");\n } catch (failure) {\n const detail = failure instanceof Error ? failure.message : String(failure);\n setError(`${failureLabel}: ${detail}`);\n setStatus(\"idle\");\n } finally {\n pending.current = false;\n }\n };\n return { status, error, invoke };\n}\n\nexport async function copyChatText(text: string, unavailable: string) {\n if (!navigator.clipboard) throw new Error(unavailable);\n await navigator.clipboard.writeText(text);\n}\n", "import { useMemo } from \"react\";\nimport { SparklesIcon, WrenchIcon, XIcon } from \"lucide-react\";\nimport { cn } from \"./ui/cn\";\nimport { useQuasselComponents, useQuasselPortalContainer } from \"./QuasselProvider\";\nimport { Message, prettyJson } from \"./types\";\nimport { ChatTexts } from \"./texts\";\n\nconst preClasses = \"qsl:rounded-lg qsl:bg-secondary qsl:p-3 qsl:font-mono qsl:text-trace qsl:leading-[1.625] qsl:break-all qsl:whitespace-pre-wrap\";\n\nexport function StepPopover({\n message,\n position,\n texts,\n toolArgumentsText,\n onClose,\n}: {\n message: Message;\n position: { x: number; y: number };\n texts: ChatTexts;\n toolArgumentsText: (tool: NonNullable<Message[\"tool\"]>) => string;\n onClose: () => void;\n}) {\n const anchor = useMemo(() => ({\n getBoundingClientRect: () => new DOMRect(position.x, position.y, 0, 0),\n contextElement: document.documentElement,\n }), [position]);\n const { Button, Popover, PopoverContent } = useQuasselComponents();\n const portalContainer = useQuasselPortalContainer();\n const tool = message.tool;\n const thinking = message.role === \"thinking\";\n const title = thinking ? texts.thinkingTitle : texts.toolTitle;\n\n return (\n <Popover open onOpenChange={(open) => { if (!open) onClose(); }}>\n <PopoverContent\n align=\"start\"\n anchor={anchor}\n aria-label={title}\n className={cn(\n \"qsl:w-[min(680px,calc(100vw-32px))] qsl:gap-0 qsl:overflow-hidden qsl:p-0 qsl:text-[13px] qsl:leading-normal qsl:shadow-pop\",\n thinking ? \"qsl:max-h-none\" : \"qsl:max-h-[min(70vh,620px)]\",\n )}\n collisionPadding={16}\n portalContainer={portalContainer}\n side=\"bottom\"\n sideOffset={10}\n >\n <div className=\"qsl:flex qsl:flex-none qsl:items-center qsl:gap-2 qsl:border-b qsl:border-border-soft qsl:px-4 qsl:py-2.5\">\n {thinking ? (\n <SparklesIcon className=\"qsl:text-muted-foreground\" size={14} />\n ) : (\n <WrenchIcon className={tool?.isError ? \"qsl:text-destructive\" : \"qsl:text-muted-foreground\"} size={14} />\n )}\n <span className=\"qsl:min-w-0 qsl:flex-1 qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap qsl:font-medium\">{title}</span>\n <Button aria-label={texts.close} className=\"qsl:flex-none\" onClick={onClose} size=\"icon-sm\" title={texts.close} variant=\"ghost\">\n <XIcon />\n </Button>\n </div>\n <div className={cn(\"qsl:min-h-0 qsl:p-4\", thinking ? \"qsl:overflow-visible\" : \"qsl:overflow-auto\")}>\n {thinking ? (\n <div className=\"qsl:text-sm qsl:leading-[1.625] qsl:whitespace-pre-wrap\">{message.text}</div>\n ) : tool ? (\n <div className=\"qsl:flex qsl:flex-col qsl:gap-4\">\n <div className=\"qsl:font-mono qsl:text-sm\">{message.text}</div>\n <PopoverSection label={texts.argumentsLabel} value={toolArgumentsText(tool)} />\n {tool.result === undefined ? (\n <div className=\"qsl:text-sm qsl:text-muted-foreground\">{texts.toolStillRunning}</div>\n ) : (\n <PopoverSection error={tool.isError} label={texts.resultLabel} value={prettyJson(tool.result)} />\n )}\n </div>\n ) : null}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction PopoverSection({ label, value, error = false }: { label: string; value: string; error?: boolean }) {\n return (\n <section>\n <h3 className=\"qsl:mb-1.5 qsl:text-trace qsl:font-semibold qsl:tracking-[0.04em] qsl:text-muted-foreground qsl:uppercase\">{label}</h3>\n <pre className={cn(preClasses, error && \"qsl:text-destructive\")}>{value}</pre>\n </section>\n );\n}\n", "import { CheckIcon, XIcon } from \"lucide-react\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\nimport type { PendingAction } from \"./types\";\n\nconst cardClasses = \"qsl:gap-2.5 qsl:bg-background qsl:px-3.5 qsl:text-sm\";\n\nconst resultText = (result: unknown): string =>\n typeof result === \"string\" ? result : result === null || result === undefined ? \"\" : JSON.stringify(result);\n\n/**\n * The rendering of a pending action without a contribution from its owner: title, the hint\n * that input is expected, and dismissing. Only the plugin knows the form.\n */\nexport function PendingActionCard({\n text,\n action,\n waitingLabel,\n dismissLabel,\n dismissedLabel,\n onDismiss,\n}: {\n text: string;\n action: PendingAction;\n waitingLabel: string;\n dismissLabel: string;\n dismissedLabel: string;\n onDismiss?: () => void;\n}) {\n const { Button, Card } = useQuasselComponents();\n if (action.status !== undefined) {\n return (\n <Card className={cardClasses} size=\"sm\">\n <div className=\"qsl:leading-normal\">{text}</div>\n <div className=\"qsl:flex qsl:items-center qsl:gap-1.5 qsl:text-sm qsl:text-muted-foreground\" data-action=\"resolved\">\n {action.status === \"approved\" ? <CheckIcon className=\"qsl:text-success\" size={12} /> : <XIcon size={12} />}\n {action.status === \"approved\" ? resultText(action.result) : dismissedLabel}\n </div>\n </Card>\n );\n }\n\n return (\n <Card className={cardClasses} size=\"sm\">\n <div className=\"qsl:leading-normal\">{text}</div>\n <div className=\"qsl:flex qsl:items-center qsl:justify-between qsl:gap-2\">\n <span className=\"qsl:text-sm qsl:text-muted-foreground\" data-action=\"waiting\">{waitingLabel}</span>\n {onDismiss && (\n <Button onClick={onDismiss} size=\"sm\" variant=\"outline\">{dismissLabel}</Button>\n )}\n </div>\n </Card>\n );\n}\n", "import { useEffect, useState } from \"react\";\nimport { cn } from \"./ui/cn\";\n\nconst TRACK = 13;\nconst BASE_TICK_MS = 90;\nconst SCENE_CHANGE_MS = 2600;\n\n/** One cell per figure: emoji and punctuation share no grid, shifted text judders. */\nfunction track(figures: Record<number, string>, width = TRACK): string[] {\n return Array.from({ length: width }, (_, x) => figures[x] ?? \" \");\n}\n\ninterface Scene {\n id: string;\n tick: number;\n moving?: true;\n compact?: true;\n draw: (step: number) => string | string[];\n}\n\n/**\n * Small scenes in which something recognizable happens - the state changes visibly instead\n * of a figure just walking past. Scenes with movement return their track as cells, all others\n * as plain text.\n */\nconst SCENES: Scene[] = [\n {\n id: \"thinking\",\n tick: 2,\n draw: (step) => {\n const tick = step % 10;\n if (tick >= 8) return \"\\u{1F929}\\u{1F4A1}\";\n return \"\\u{1F914}\" + \"\\u{1F4AD}\".repeat(Math.min(tick, 3));\n },\n },\n {\n // Flies to the right, dragging its tail behind.\n id: \"rocket\",\n tick: 2,\n moving: true,\n draw: (step) => {\n const x = step % TRACK;\n return track({ [x - 2]: \"\u00B7\", [x - 1]: \"\\u{1F4A8}\", [x]: \"\\u{1F680}\" });\n },\n },\n {\n // The dots stay put and are eaten one by one.\n id: \"pacman\",\n tick: 2,\n moving: true,\n draw: (step) => {\n const x = step % TRACK;\n const figures: Record<number, string> = {};\n for (let i = x + 1; i < TRACK; i++) {\n figures[i] = \"\u00B7\";\n }\n figures[x] = step % 2 === 0 ? \"\\u{1F7E1}\" : \"\\u{1F315}\";\n return track(figures);\n },\n },\n {\n // A seed becomes a tree, then start over.\n id: \"growing\",\n compact: true,\n tick: 2,\n draw: (step) => {\n const stages = [\"\\u{1F331}\", \"\\u{1F331}\", \"\\u{1F33F}\", \"\\u{1F33F}\", \"\\u{1F343}\", \"\\u{1F333}\", \"\\u{1F333}\", \"\\u{1F333}\"];\n return stages[step % stages.length];\n },\n },\n {\n // The egg cracks, the chick hatches.\n id: \"hatching\",\n compact: true,\n tick: 2,\n draw: (step) => {\n const tick = step % 12;\n if (tick < 4) return \"\\u{1F95A}\";\n if (tick < 6) return \"\\u{1F95A}*\";\n if (tick < 9) return \"\\u{1F423}\";\n return \"\\u{1F425}\";\n },\n },\n {\n // Morse-like signal that resolves into an OK.\n id: \"signal\",\n tick: 2,\n draw: (step) => {\n const tick = step % 14;\n if (tick >= 11) return \"\\u{1F4E1} OK\";\n const pattern = [\"\u00B7\", \"\u00B7\u00B7\", \"\u00B7-\", \"-\u00B7\", \"\u00B7\u00B7-\", \"-\u00B7\u00B7\"];\n return \"\\u{1F4E1} \" + pattern[tick % pattern.length];\n },\n },\n {\n // Hourglass: the sand runs through, then it is flipped.\n id: \"hourglass\",\n tick: 2,\n draw: (step) => {\n const tick = step % 12;\n const grains = \"\u00B7\".repeat(Math.max(0, 5 - Math.floor(tick / 2)));\n return (tick < 10 ? \"\u23F3\" : \"\u231B\") + \" \" + grains;\n },\n },\n {\n // Egg, chick, hen - and she lays the next egg.\n id: \"chicken-cycle\",\n compact: true,\n tick: 3,\n draw: (step) => {\n const tick = step % 16;\n if (tick < 3) return \"\\u{1F95A}\";\n if (tick < 5) return \"\\u{1F95A}*\";\n if (tick < 8) return \"\\u{1F423}\";\n if (tick < 11) return \"\\u{1F424}\";\n if (tick < 14) return \"\\u{1F414}\";\n return \"\\u{1F414}\\u{1F95A}\";\n },\n },\n {\n // Hat, sparks - and the rabbit bolts.\n id: \"magic-hat\",\n compact: true,\n tick: 3,\n draw: (step) => {\n const tick = step % 14;\n if (tick < 4) return \"\\u{1F3A9}\";\n if (tick < 7) return \"\\u{1F3A9}*\";\n if (tick < 11) return \"\\u{1F3A9}\\u{1F407}\";\n return \"\\u{1F407}\\u{1F4A8}\";\n },\n },\n {\n // Red, yellow, green - and off.\n id: \"traffic-light\",\n compact: true,\n tick: 3,\n draw: (step) => {\n const tick = step % 12;\n if (tick < 4) return \"\\u{1F534}\";\n if (tick < 6) return \"\\u{1F7E1}\";\n if (tick < 8) return \"\\u{1F7E2}\";\n return \"\\u{1F697}\\u{1F4A8}\";\n },\n },\n {\n // Ringing, oversleeping, running off.\n id: \"alarm-clock\",\n compact: true,\n tick: 2,\n draw: (step) => {\n const tick = step % 14;\n if (tick < 5) return tick % 2 === 0 ? \"\u23F0\" : \"\\u{1F514}\";\n if (tick < 8) return \"\\u{1F634}\";\n if (tick < 10) return \"\\u{1F633}\";\n return \"\\u{1F3C3}\\u{1F4A8}\";\n },\n },\n {\n // A snail crawls to the flag - and celebrates.\n id: \"snail\",\n tick: 4,\n draw: (step) => {\n const tick = step % 8;\n if (tick < 5) return track({ [tick]: \"\\u{1F40C}\", 4: \"\\u{1F3C1}\" }, 5);\n return track({ 4: \"\\u{1F389}\" }, 5);\n },\n },\n];\n\nconst COMPACT_SCENES = SCENES.filter((scene) => scene.compact);\n\nexport interface WorkingScenesProps {\n /** Limits scenes to one or two visible characters for small status fields. */\n compact?: boolean;\n /** Text for screen readers, default \"Working ...\". */\n label?: string;\n}\n\n/**\n * The default working indicator: randomly rotating mini scenes. Random order and start phase,\n * so the same scenes never feel like a loop. The working prop of ChatMessages replaces it\n * completely.\n */\nexport function WorkingScenes({ label = \"Working ...\", compact = false }: WorkingScenesProps) {\n const scenes = compact ? COMPACT_SCENES : SCENES;\n const [sceneIndex, setSceneIndex] = useState(() => Math.floor(Math.random() * scenes.length));\n const [offset, setOffset] = useState(() => Math.floor(Math.random() * 20));\n const [frameTick, setFrameTick] = useState(0);\n const [reducedMotion, setReducedMotion] = useState(() => typeof window !== \"undefined\"\n && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches);\n const scene = scenes[sceneIndex % scenes.length];\n\n useEffect(() => {\n const preference = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const update = () => setReducedMotion(preference.matches);\n preference.addEventListener(\"change\", update);\n update();\n return () => preference.removeEventListener(\"change\", update);\n }, []);\n\n useEffect(() => {\n if (reducedMotion) return;\n const timer = window.setInterval(() => {\n setSceneIndex((previous) => (previous + 1 + Math.floor(Math.random() * (scenes.length - 1))) % scenes.length);\n setOffset(Math.floor(Math.random() * 20));\n setFrameTick(0);\n }, SCENE_CHANGE_MS);\n return () => window.clearInterval(timer);\n }, [reducedMotion, scenes]);\n\n useEffect(() => {\n if (reducedMotion) return;\n const timer = window.setInterval(() => setFrameTick((value) => value + 1), BASE_TICK_MS);\n return () => window.clearInterval(timer);\n }, [reducedMotion]);\n\n const frame = scene.draw(Math.floor(frameTick / scene.tick) + (scene.moving ? offset : 0));\n return (\n <span aria-label={label} className={cn(\"qsl:flex qsl:items-center qsl:gap-2.5 qsl:text-[13px]\", compact ? \"qsl:text-inherit\" : \"qsl:mt-4 qsl:text-foreground\")} data-chat=\"working\" role=\"status\">\n {!compact && <span aria-hidden=\"true\" className=\"qsl:text-muted-foreground qsl:opacity-70\">></span>}\n <span aria-hidden=\"true\" className={cn(\"qsl:inline-block qsl:flex-none qsl:font-mono qsl:[font-variant-ligatures:none]\", compact ? \"qsl:w-[2.4em] qsl:text-center\" : \"qsl:w-[15rem]\")} key={scene.id}>\n <span className=\"qsl:tracking-[0.02em] qsl:whitespace-pre qsl:motion-reduce:opacity-60\">\n {typeof frame === \"string\"\n ? frame\n : frame.map((cell, index) => (\n <span className=\"qsl:inline-block qsl:w-[1.35em] qsl:text-center\" key={index}>\n {cell}\n </span>\n ))}\n </span>\n </span>\n </span>\n );\n}\n", "import type { ChatAttachmentInput } from \"./events\";\n\nimport { chatAttachmentMediaType, MAX_CHAT_ATTACHMENTS, MAX_CHAT_ATTACHMENT_BYTES } from \"./chat-attachments\";\nimport { defaultTexts, fillText, type ChatTexts } from \"./texts\";\n\nexport { MAX_CHAT_ATTACHMENTS, MAX_CHAT_ATTACHMENT_BYTES };\n\nexport const maxAttachmentSizeLabel = `${MAX_CHAT_ATTACHMENT_BYTES / (1024 * 1024)} MiB`;\n\nexport function attachmentMediaType(file: { name: string; type: string }): string {\n return chatAttachmentMediaType(file.name, file.type);\n}\n\nexport function attachmentCapabilityError(\n files: readonly { name: string; mediaType: string }[],\n capabilities: { input: readonly string[]; model: string },\n texts: ChatTexts = defaultTexts,\n): string | undefined {\n for (const file of files) {\n const required = file.mediaType.startsWith(\"image/\") ? \"image\"\n : file.mediaType.startsWith(\"video/\") ? \"video\" : file.mediaType === \"application/pdf\" ? \"file\" : undefined;\n if (required && !capabilities.input.includes(required)) {\n const kind = required === \"image\" ? texts.attachmentKindImage : required === \"video\" ? texts.attachmentKindVideo : texts.attachmentKindPdf;\n if (!capabilities.model) return fillText(texts.attachmentUnsupported, { name: file.name, kind });\n return fillText(texts.attachmentUnsupportedByModel, { model: capabilities.model, name: file.name, kind });\n }\n }\n}\n\nexport function validateAttachmentSelection(existing: readonly { size: number }[], incoming: readonly { size: number }[], texts: ChatTexts = defaultTexts): void {\n if (existing.length + incoming.length > MAX_CHAT_ATTACHMENTS) {\n throw new Error(fillText(texts.tooManyAttachments, { count: MAX_CHAT_ATTACHMENTS }));\n }\n if ([...existing, ...incoming].reduce((total, file) => total + file.size, 0) > MAX_CHAT_ATTACHMENT_BYTES) {\n throw new Error(fillText(texts.attachmentsTooLarge, { size: maxAttachmentSizeLabel }));\n }\n}\n\nexport async function encodeAttachment(file: File): Promise<ChatAttachmentInput> {\n const bytes = new Uint8Array(await file.arrayBuffer());\n const chunks: string[] = [];\n for (let offset = 0; offset < bytes.length; offset += 8192) {\n chunks.push(String.fromCharCode(...bytes.subarray(offset, offset + 8192)));\n }\n return { name: file.name, mediaType: attachmentMediaType(file), data: btoa(chunks.join(\"\")) };\n}\n\nexport function formatAttachmentSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;\n}\n\nexport function attachmentDownloadUrl(url: string): string {\n if (/^(data|blob):/i.test(url)) return url;\n const [resource, fragment] = url.split(/#(.*)/s);\n return `${resource}${resource.includes(\"?\") ? \"&\" : \"?\"}download=1${fragment === undefined ? \"\" : `#${fragment}`}`;\n}\n", "import type { CSSProperties, ReactNode } from \"react\";\nimport type { Message } from \"./types\";\n\nexport interface ChatAppearance {\n fontSize?: CSSProperties[\"fontSize\"];\n lineHeight?: CSSProperties[\"lineHeight\"];\n messageGap?: CSSProperties[\"marginTop\"];\n denseMessageGap?: CSSProperties[\"marginTop\"];\n}\n\nexport interface TimestampOptions {\n format?: \"time\" | \"date-time\" | \"relative\";\n locale?: string;\n timeZone?: string;\n showDaySeparators?: boolean;\n}\n\nexport interface CodeBlockOptions {\n wrap?: boolean;\n maxHeight?: CSSProperties[\"maxHeight\"];\n showCopyButton?: boolean;\n}\n\nexport interface BubbleOptions {\n variant?: \"default\" | \"plain\" | \"bubbles\";\n maxWidth?: CSSProperties[\"maxWidth\"];\n userSide?: \"start\" | \"end\";\n assistantSide?: \"start\" | \"end\";\n showSender?: boolean;\n senderLabel?: (message: Message) => string | undefined;\n}\n\nexport interface MessageAction {\n id: string;\n label: string;\n icon?: ReactNode;\n disabled?: boolean;\n onClick: (message: Message) => void | Promise<void>;\n}\n\nexport interface MessageActionsOptions {\n copy?: boolean | ((message: Message) => boolean);\n edit?: (message: Message) => void | Promise<void>;\n retry?: (message: Message) => void | Promise<void>;\n custom?: (message: Message) => readonly MessageAction[];\n}\n\nexport type SendShortcut = \"enter\" | \"mod-enter\";\n\nconst cssLength = (value: string | number | undefined) => typeof value === \"number\" ? `${value}px` : value;\n\nexport const appearanceStyle = (appearance?: ChatAppearance): CSSProperties => ({\n \"--qsl-chat-font-size\": cssLength(appearance?.fontSize),\n \"--qsl-chat-line-height\": appearance?.lineHeight,\n \"--qsl-chat-message-gap\": cssLength(appearance?.messageGap),\n \"--qsl-chat-dense-message-gap\": cssLength(appearance?.denseMessageGap),\n} as CSSProperties);\n", "import type { TimestampOptions } from \"./options\";\n\nexport function messageDate(at: string | undefined): Date | undefined {\n if (!at) return undefined;\n const date = new Date(at);\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n\nexport function timestampLabel(date: Date, options: TimestampOptions = {}, now = Date.now()): string {\n if ((!options.format || options.format === \"time\") && !options.locale && !options.timeZone) {\n return `${String(date.getHours()).padStart(2, \"0\")}:${String(date.getMinutes()).padStart(2, \"0\")}`;\n }\n if (options.format === \"relative\") {\n const seconds = (date.getTime() - now) / 1000;\n const units: readonly [Intl.RelativeTimeFormatUnit, number][] = [\n [\"year\", 365 * 86400], [\"month\", 30 * 86400], [\"day\", 86400], [\"hour\", 3600], [\"minute\", 60],\n ];\n const [unit, divisor] = units.find(([, value]) => Math.abs(seconds) >= value) ?? [\"second\", 1];\n return new Intl.RelativeTimeFormat(options.locale, { numeric: \"auto\" }).format(Math.round(seconds / divisor), unit);\n }\n return new Intl.DateTimeFormat(options.locale, {\n timeZone: options.timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hourCycle: \"h23\",\n ...(options.format === \"date-time\" ? { year: \"numeric\", month: \"2-digit\", day: \"2-digit\" } as const : {}),\n }).format(date);\n}\n\nexport function timestampDay(date: Date, options: TimestampOptions = {}): { key: string; label: string } {\n const key = new Intl.DateTimeFormat(\"en-CA\", {\n timeZone: options.timeZone, year: \"numeric\", month: \"2-digit\", day: \"2-digit\",\n }).format(date);\n const label = new Intl.DateTimeFormat(options.locale, {\n timeZone: options.timeZone, dateStyle: \"long\",\n }).format(date);\n return { key, label };\n}\n", "import { useSyncExternalStore } from \"react\";\nimport { type ChatTexts, fillText } from \"./texts\";\n\nconst tickMs = 500;\n\n/** Under a minute \"{seconds} s\" from texts, then m:ss, from an hour on h:mm:ss. */\nexport function formatElapsed(ms: number, texts: Pick<ChatTexts, \"toolElapsedSeconds\">): string {\n const total = Math.max(0, Math.floor(ms / 1000));\n if (total < 60) return fillText(texts.toolElapsedSeconds, { seconds: total });\n const hours = Math.floor(total / 3600);\n const minutes = Math.floor(total / 60) % 60;\n const seconds = String(total % 60).padStart(2, \"0\");\n return hours > 0 ? `${hours}:${String(minutes).padStart(2, \"0\")}:${seconds}` : `${minutes}:${seconds}`;\n}\n\n/** One interval for every subscriber; it runs only while someone listens. */\nexport function createTicker(intervalMs = tickMs) {\n const listeners = new Set<() => void>();\n let now = Date.now();\n let timer: ReturnType<typeof setInterval> | undefined;\n return {\n subscribe(listener: () => void): () => void {\n listeners.add(listener);\n if (timer === undefined) {\n now = Date.now();\n timer = setInterval(() => {\n now = Date.now();\n listeners.forEach((notify) => notify());\n }, intervalMs);\n }\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0 && timer !== undefined) {\n clearInterval(timer);\n timer = undefined;\n }\n };\n },\n now(): number {\n const current = Date.now();\n if (timer === undefined && (current - now >= intervalMs || current < now)) now = current;\n return now;\n },\n active: (): boolean => timer !== undefined,\n };\n}\n\nexport const elapsedTicker = createTicker();\n\nconst nothingOnServer = () => undefined;\n\n/** Milliseconds since start in whole seconds, so a row renders only when its display changes; undefined on the server. */\nexport function useElapsed(start: number): number | undefined {\n return useSyncExternalStore(elapsedTicker.subscribe, () => Math.floor((elapsedTicker.now() - start) / 1000) * 1000, nothingOnServer);\n}\n", "import { CheckIcon, CopyIcon, PencilIcon, RotateCcwIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { cn } from \"./ui/cn\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\nimport type { MessageActionsOptions, MessageAction } from \"./options\";\nimport type { ChatTexts } from \"./texts\";\nimport type { Message } from \"./types\";\nimport { copyChatText, useChatAction } from \"./useChatAction\";\n\nconst actionClasses = cn(\n \"qsl:absolute qsl:top-1 qsl:right-1 qsl:z-[1] qsl:flex qsl:flex-wrap qsl:rounded-sm qsl:bg-secondary qsl:opacity-0\",\n \"qsl:shadow-[0_2px_6px_color-mix(in_srgb,var(--qsl-foreground)_15%,transparent)]\",\n \"qsl:pointer-events-none qsl:group-hover:pointer-events-auto qsl:group-hover:opacity-100 qsl:focus-within:pointer-events-auto qsl:focus-within:opacity-100\",\n \"qsl:[@media(hover:none)]:pointer-events-auto qsl:[@media(hover:none)]:opacity-100\",\n);\n\nexport function MessageActions({ message, options, texts }: { message: Message; options?: MessageActionsOptions; texts: ChatTexts }) {\n const action = useChatAction();\n const { Button } = useQuasselComponents();\n const [lastAction, setLastAction] = useState<string>();\n const copy = typeof options?.copy === \"function\" ? options.copy(message) : options?.copy ?? message.role === \"user\";\n const actions: MessageAction[] = [\n ...(copy && message.text.trim() ? [{ id: \"copy\", label: texts.copyMessage, icon: <CopyIcon />, onClick: () => copyChatText(message.text, texts.clipboardUnavailable) }] : []),\n ...(options?.edit && message.role === \"user\" ? [{ id: \"edit\", label: texts.editMessage, icon: <PencilIcon />, onClick: options.edit }] : []),\n ...(options?.retry && message.role === \"assistant\" ? [{ id: \"retry\", label: texts.retryMessage, icon: <RotateCcwIcon />, onClick: options.retry }] : []),\n ...options?.custom?.(message) ?? [],\n ];\n return <>\n {actions.length > 0 && <div className={actionClasses}>\n {actions.map((item) => {\n const copied = item.id === \"copy\" && lastAction === item.id && action.status === \"done\";\n const label = copied ? texts.copied : item.label;\n return <Button aria-label={label} className=\"qsl:text-inherit\" disabled={item.disabled || action.status === \"pending\"}\n key={item.id} size={item.icon ? \"icon-sm\" : \"sm\"} title={label} variant=\"ghost\"\n onClick={() => {\n setLastAction(item.id);\n void action.invoke(() => item.onClick(message), texts.actionFailed);\n }}>{copied ? <CheckIcon /> : item.icon ?? item.label}</Button>;\n })}\n </div>}\n {action.error && <p className=\"qsl:mt-2 qsl:text-sm qsl:text-destructive\" role=\"alert\">{action.error}</p>}\n </>;\n}\n", "import { createContext, type RefObject } from \"react\";\n\nexport interface ChatSendScope {\n notify: () => void;\n subscribe: (listener: () => void) => () => void;\n}\n\nexport const ChatSendContext = createContext<ChatSendScope | undefined>(undefined);\n\nexport function createChatSendScope(enabled: RefObject<boolean>): ChatSendScope {\n const listeners = new Set<() => void>();\n return {\n notify: () => { if (enabled.current) listeners.forEach((listener) => listener()); },\n subscribe: (listener) => {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n },\n };\n}\n", "import { createContext } from \"react\";\n\n/** Target of open actions: undefined = in the transcript, null = the dock above the input is not mounted yet. */\nexport const ChatActionDock = createContext<HTMLElement | null | undefined>(undefined);\n", "const intervalMs = 400;\nconst maxQueued = 5;\n\nlet region: HTMLElement | undefined;\nlet queued: readonly string[] = [];\nlet running = false;\n\nfunction liveRegion(): HTMLElement {\n if (region?.isConnected) {\n return region;\n }\n const element = document.createElement(\"div\");\n element.setAttribute(\"role\", \"status\");\n element.setAttribute(\"aria-live\", \"polite\");\n element.setAttribute(\"aria-atomic\", \"true\");\n Object.assign(element.style, {\n position: \"absolute\",\n width: \"1px\",\n height: \"1px\",\n margin: \"-1px\",\n padding: \"0\",\n border: \"0\",\n overflow: \"hidden\",\n clipPath: \"inset(50%)\",\n whiteSpace: \"nowrap\",\n });\n document.body.append(element);\n region = element;\n return element;\n}\n\nfunction next(): void {\n if (queued.length === 0) {\n running = false;\n return;\n }\n if (document.visibilityState === \"hidden\") {\n document.addEventListener(\"visibilitychange\", next, { once: true });\n return;\n }\n const [text, ...rest] = queued;\n queued = rest;\n const target = liveRegion();\n target.textContent = target.textContent === text ? `${text}\\u00a0` : text;\n window.setTimeout(next, intervalMs);\n}\n\n/** Announces text through a shared, hidden live region: throttled, and paused while the tab is hidden. */\nexport function announce(text: string): void {\n const content = text.trim();\n if (!content || typeof document === \"undefined\") {\n return;\n }\n queued = [...queued, content].slice(-maxQueued);\n if (running) {\n return;\n }\n running = true;\n liveRegion();\n window.setTimeout(next, intervalMs);\n}\n", "import { useEffect, useLayoutEffect, useRef, useState, type CSSProperties, type ReactNode, type Ref } from \"react\";\nimport { cn } from \"./ui/cn\";\nimport { ChatSendContext, createChatSendScope } from \"./ChatSendContext\";\nimport { ChatActionDock } from \"./ChatActionDock\";\nimport { appearanceStyle, type ChatAppearance } from \"./options\";\n\n/**\n * Transcript with an overlaid composer. The frame measures the composer itself and gives the\n * transcript the footer space it needs, so no host has to set inner dimensions.\n */\nexport function ChatPanel({\n children,\n composer,\n className,\n nodeRef,\n maxWidth,\n horizontalPadding,\n appearance,\n scrollOnSend = false,\n}: {\n children: ReactNode;\n /** The composer; it lies over the transcript, not below it. */\n composer?: ReactNode;\n className?: string;\n nodeRef?: Ref<HTMLDivElement>;\n maxWidth?: CSSProperties[\"maxWidth\"];\n horizontalPadding?: CSSProperties[\"paddingInline\"];\n appearance?: ChatAppearance;\n scrollOnSend?: boolean;\n}) {\n const root = useRef<HTMLDivElement>(null);\n const composerRef = useRef<HTMLDivElement>(null);\n const [dock, setDock] = useState<HTMLDivElement | null>(null);\n const hasComposer = composer !== undefined;\n const scrollOnSendRef = useRef(scrollOnSend);\n const [sendScope] = useState(() => createChatSendScope(scrollOnSendRef));\n useLayoutEffect(() => { scrollOnSendRef.current = scrollOnSend; }, [scrollOnSend]);\n\n useEffect(() => {\n const element = composerRef.current;\n const frame = root.current;\n if (!element || !frame) {\n return;\n }\n const measure = () => {\n frame.style.setProperty(\"--qsl-composer-height\", `${element.offsetHeight}px`);\n frame.style.setProperty(\"--qsl-panel-height\", `${frame.offsetHeight}px`);\n };\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n observer.observe(frame);\n measure();\n return () => {\n observer.disconnect();\n frame.style.removeProperty(\"--qsl-composer-height\");\n frame.style.removeProperty(\"--qsl-panel-height\");\n };\n }, [hasComposer]);\n\n return (\n <ChatSendContext.Provider value={sendScope}>\n <ChatActionDock.Provider value={hasComposer ? dock : undefined}>\n <div\n className={cn(\"qsl:relative qsl:flex qsl:min-h-0 qsl:min-w-0 qsl:flex-col qsl:overflow-hidden\", className)}\n data-chat=\"panel\"\n data-quassel=\"\"\n style={{\n ...appearanceStyle(appearance),\n \"--qsl-chat-content-max-width\": typeof maxWidth === \"number\" ? `${maxWidth}px` : maxWidth,\n \"--qsl-chat-horizontal-padding\": typeof horizontalPadding === \"number\" ? `${horizontalPadding}px` : horizontalPadding,\n } as CSSProperties}\n ref={(element) => {\n root.current = element;\n if (typeof nodeRef === \"function\") {\n nodeRef(element);\n } else if (nodeRef) {\n nodeRef.current = element;\n }\n }}\n >\n {children}\n {hasComposer && (\n <div className=\"qsl:absolute qsl:inset-x-0 qsl:bottom-0 qsl:z-[5] qsl:px-[var(--qsl-chat-horizontal-padding,24px)] qsl:pb-3.5 qsl:*:mx-auto qsl:*:max-w-[var(--qsl-chat-content-max-width,none)]\" data-chat=\"composer\" ref={composerRef}>\n <div>\n <div\n className=\"qsl:-mx-[16px] qsl:max-h-[calc(var(--qsl-panel-height,100dvh)_/_2)] qsl:overflow-y-auto qsl:px-[16px] qsl:pb-[var(--qsl-chat-message-gap,16px)] qsl:[-webkit-mask-image:linear-gradient(to_bottom,#000_calc(100%_-_var(--qsl-chat-message-gap,16px)),transparent)] qsl:[mask-image:linear-gradient(to_bottom,#000_calc(100%_-_var(--qsl-chat-message-gap,16px)),transparent)] qsl:empty:hidden\"\n data-chat=\"actions\"\n ref={setDock}\n />\n </div>\n {composer}\n </div>\n )}\n </div>\n </ChatActionDock.Provider>\n </ChatSendContext.Provider>\n );\n}\n", "import { PaperclipIcon, SendIcon, XIcon } from \"lucide-react\";\nimport { cn } from \"./ui/cn\";\nimport { useFileInput } from \"./ui/useFileInput\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\nimport { KeyboardEvent, ReactNode, Ref, useCallback, useContext, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { ChatTexts, defaultTexts, fillText } from \"./texts\";\nimport type { ChatAttachmentInput } from \"./events\";\nimport { attachmentCapabilityError, attachmentMediaType, encodeAttachment, formatAttachmentSize, MAX_CHAT_ATTACHMENTS, maxAttachmentSizeLabel, validateAttachmentSelection } from \"./attachments\";\nimport { ChatSendContext } from \"./ChatSendContext\";\nimport type { SendShortcut } from \"./options\";\n\ntype DraftAttachment = { id: number; file: File } & (\n | { status: \"reading\" }\n | { status: \"ready\"; input: ChatAttachmentInput }\n | { status: \"error\"; error: string }\n);\n\n// Below this panel width, accompanying labels collapse to their icons.\nconst COMPACT_WIDTH_PX = 480;\n\nconst errorClasses = \"qsl:px-3 qsl:py-2 qsl:text-sm qsl:text-destructive\";\nconst attachmentItemClasses = \"qsl:relative qsl:flex qsl:w-[190px] qsl:max-w-full qsl:min-w-0 qsl:flex-col qsl:overflow-hidden qsl:rounded-lg qsl:border qsl:border-border qsl:text-sm\";\nconst attachmentMediaClasses = \"qsl:block qsl:h-[112px] qsl:w-full qsl:bg-secondary qsl:object-contain\";\n\n/** A toolbar button, declarative: icon, text or both - plus click handler. */\nexport interface ToolbarAction {\n icon?: ReactNode;\n label?: string;\n title?: string;\n disabled?: boolean;\n active?: boolean;\n onClick: () => void;\n}\n\n/** Hosts control the draft from outside, e.g. to insert a template for editing. */\nexport interface ChatInputHandle {\n /** Replaces the draft, focuses the input and puts the caret at the end. */\n insert: (text: string) => void;\n focus: () => void;\n reset: () => void;\n submit: (onSubmit?: (text: string, attachments?: ChatAttachmentInput[]) => void | Promise<void>, options?: { allowEmpty?: boolean }) => Promise<void>;\n}\n\n/**\n * The input card: borderless textarea on top, toolbar below a hairline. Custom buttons come\n * declaratively through `actions` or freely through the left/right slots; while work is running\n * the stop button stays visible, and typing shows the send button next to it, which then\n * interjects. `rows` sets the initial height; with `maxRows` the textarea grows with its content\n * up to that number of rows and scrolls after that.\n */\nexport function ChatInputToolbar({\n onSend,\n onStop,\n running = false,\n disabled = false,\n sendDisabled = false,\n layout = \"card\",\n detailsContainer,\n onErrorChange,\n inputAriaControls,\n rows = 3,\n maxRows,\n actions,\n toolbarLeft,\n toolbarRight,\n texts,\n handleRef,\n attachments: attachmentsEnabled = true,\n attachmentCapabilities,\n attachmentCapabilitiesError,\n onAttachmentsChange,\n initialValue = \"\",\n onDraftChange,\n sendShortcut = \"enter\",\n autoFocus = false,\n onAutoFocusSettled,\n}: {\n onSend: (text: string, attachments?: ChatAttachmentInput[]) => void | Promise<void>;\n onStop?: () => void;\n running?: boolean;\n disabled?: boolean;\n sendDisabled?: boolean;\n layout?: \"card\" | \"toolbar\" | \"inline\";\n detailsContainer?: HTMLElement | null;\n onErrorChange?: (error: string | undefined) => void;\n inputAriaControls?: string;\n rows?: number;\n maxRows?: number;\n actions?: ToolbarAction[];\n toolbarLeft?: ReactNode;\n toolbarRight?: ReactNode;\n texts?: Partial<ChatTexts>;\n handleRef?: Ref<ChatInputHandle>;\n /** false = no attaching: neither button nor dropping or pasting files. */\n attachments?: boolean;\n attachmentCapabilities?: { input: readonly string[]; model: string };\n attachmentCapabilitiesError?: string;\n onAttachmentsChange?: (hasAttachments: boolean) => void;\n initialValue?: string;\n onDraftChange?: (text: string) => void;\n sendShortcut?: SendShortcut;\n autoFocus?: boolean;\n onAutoFocusSettled?: () => void;\n}) {\n const sendScope = useContext(ChatSendContext);\n const allTexts = { ...defaultTexts, ...texts };\n const { Button, StopButton, Toggle } = useQuasselComponents();\n const [draft, setDraft] = useState(initialValue);\n const [sending, setSending] = useState(false);\n const [sendError, setSendError] = useState<string>();\n const [failedSubmissions, setFailedSubmissions] = useState<{ id: number; draft: string; attachments: DraftAttachment[] }[]>([]);\n const nextFailedId = useRef(0);\n const pendingSend = useRef(false);\n const generation = useRef(0);\n useLayoutEffect(() => () => { generation.current += 1; }, []);\n const draftRevision = useRef(0);\n const [attachments, setAttachments] = useState<DraftAttachment[]>([]);\n const attachmentsRef = useRef<DraftAttachment[]>([]);\n const nextAttachmentId = useRef(0);\n const [attachmentError, setAttachmentError] = useState<string>();\n const updateAttachments = (update: (current: DraftAttachment[]) => DraftAttachment[]) => {\n attachmentsRef.current = update(attachmentsRef.current);\n setAttachments(attachmentsRef.current);\n };\n const addFiles = (files: File[]) => {\n if (!files.length) return;\n if (disabled || pendingSend.current) {\n setAttachmentError(allTexts.attachmentsWhileBusy);\n return;\n }\n try {\n validateAttachmentSelection(attachmentsRef.current.map((entry) => entry.file), files, allTexts);\n } catch (error) {\n setAttachmentError(error instanceof Error ? error.message : String(error));\n return;\n }\n setAttachmentError(undefined);\n const entries: DraftAttachment[] = files.map((file) => ({ id: ++nextAttachmentId.current, file, status: \"reading\" }));\n updateAttachments((current) => [...current, ...entries]);\n for (const entry of entries) {\n void encodeAttachment(entry.file).then(\n (input) => updateAttachments((current) => current.map((item) => item.id === entry.id ? { ...entry, status: \"ready\", input } : item)),\n () => updateAttachments((current) => current.map((item) => item.id === entry.id ? {\n ...entry, status: \"error\", error: allTexts.attachmentReadFailed,\n } : item)),\n );\n }\n };\n const rootRef = useRef<HTMLDivElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const autoFocusSettled = useRef(false);\n useEffect(() => {\n if (!autoFocus || autoFocusSettled.current) return;\n const input = textareaRef.current;\n if (!input) return;\n let frame = 0;\n const settle = () => {\n if (autoFocusSettled.current) return;\n autoFocusSettled.current = true;\n window.cancelAnimationFrame(frame);\n onAutoFocusSettled?.();\n };\n const onFocus = (event: FocusEvent) => { if (event.target !== input) settle(); };\n const focusWhenVisible = () => {\n if (autoFocusSettled.current) return;\n const dialog = [...document.querySelectorAll<HTMLElement>('[role=\"dialog\"], dialog[open]')]\n .find((element) => element.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true }) && !element.contains(input));\n if (dialog) {\n settle();\n return;\n }\n const rect = input.getBoundingClientRect();\n const visible = input.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true }) && rect.width > 0 && rect.height > 0 && !input.closest('[inert], [hidden], [aria-hidden=\"true\"]')\n && document.elementFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2) === input;\n if (visible && !input.disabled && !input.readOnly && document.visibilityState === \"visible\") {\n input.focus({ preventScroll: true });\n if (document.activeElement === input) {\n settle();\n return;\n }\n }\n frame = window.requestAnimationFrame(focusWhenVisible);\n };\n window.addEventListener(\"pointerdown\", settle, true);\n window.addEventListener(\"keydown\", settle, true);\n window.addEventListener(\"focusin\", onFocus);\n window.addEventListener(\"blur\", settle);\n if (!disabled) frame = window.requestAnimationFrame(focusWhenVisible);\n return () => {\n window.cancelAnimationFrame(frame);\n window.removeEventListener(\"pointerdown\", settle, true);\n window.removeEventListener(\"keydown\", settle, true);\n window.removeEventListener(\"focusin\", onFocus);\n window.removeEventListener(\"blur\", settle);\n };\n }, [autoFocus, disabled, onAutoFocusSettled]);\n const [compact, setCompact] = useState(false);\n const pendingFocus = useRef(false);\n const fileInput = useFileInput({\n disabled: disabled || sending,\n onFiles: addFiles,\n onPasteText: (text) => {\n const input = textareaRef.current;\n if (!input || disabled || pendingSend.current) return;\n const start = input.selectionStart;\n const end = input.selectionEnd;\n draftRevision.current += 1;\n setDraft((current) => current.slice(0, start) + text + current.slice(end));\n pendingFocus.current = true;\n },\n });\n const toolbar = layout === \"toolbar\";\n const inline = layout === \"inline\";\n const inputRows = inline || toolbar ? 1 : rows;\n const inputMaxRows = inline || toolbar ? 1 : maxRows;\n // The toolbar variant pulses while working; the host only sets the radius.\n const rootClasses = cn(\n \"qsl:flex qsl:shrink-0 qsl:flex-col qsl:overflow-hidden qsl:rounded-[var(--qsl-input-card-radius,--theme(--radius-xl))] qsl:border qsl:border-border-strong qsl:bg-background qsl:shadow-bar qsl:transition-colors qsl:focus-within:border-primary\",\n \"qsl:in-data-[tone=material]:rounded-xl qsl:in-data-[tone=material]:border-glass-edge/50 qsl:in-data-[tone=material]:bg-background\",\n toolbar && \"qsl:h-full qsl:min-w-0 qsl:flex-row qsl:items-center qsl:rounded-lg qsl:data-[working=true]:animate-working-pulse qsl:data-[working=true]:border-primary qsl:motion-reduce:data-[working=true]:animate-none\",\n fileInput.dragging && \"qsl:outline-2 qsl:outline-offset-[3px] qsl:outline-dashed qsl:outline-primary\",\n );\n const textareaClasses = cn(\n \"qsl:resize-none qsl:border-0 qsl:bg-transparent qsl:text-[length:var(--qsl-chat-font-size,13px)] qsl:leading-[var(--qsl-chat-line-height,1.5)] qsl:text-foreground qsl:placeholder:text-muted-foreground qsl:focus:outline-none\",\n inline ? \"qsl:min-w-0 qsl:flex-1 qsl:px-2.5 qsl:py-2\" : toolbar ? \"qsl:w-full qsl:min-w-0 qsl:flex-auto qsl:px-2 qsl:py-[3px] qsl:leading-[1.3]\" : \"qsl:px-3 qsl:pt-3 qsl:pb-2\",\n );\n const toolbarRowClasses = cn(\n \"qsl:flex qsl:items-center qsl:gap-2 qsl:border-t qsl:border-border-soft qsl:px-2 qsl:py-1.5 qsl:in-data-[tone=overseer-details]:flex-nowrap\",\n inline && \"qsl:flex-none qsl:gap-1 qsl:border-t-0 qsl:p-1\",\n toolbar && \"qsl:flex-wrap qsl:border-t-0\",\n );\n const toolbarSideClasses = \"qsl:flex qsl:min-w-0 qsl:items-center qsl:gap-2 qsl:in-data-[tone=overseer-details]:flex-nowrap\";\n const changeDraft = useCallback((text: string) => {\n draftRevision.current += 1;\n setDraft(text);\n }, []);\n\n useImperativeHandle(handleRef, () => ({\n insert: (text: string) => {\n pendingFocus.current = true;\n changeDraft(text);\n const element = textareaRef.current;\n element?.focus();\n if (element?.value === text) element.setSelectionRange(text.length, text.length);\n },\n focus: () => textareaRef.current?.focus(),\n submit: (onSubmit, options) => send(onSubmit, options?.allowEmpty),\n reset: () => {\n generation.current += 1;\n pendingSend.current = false;\n pendingFocus.current = false;\n changeDraft(\"\");\n updateAttachments(() => []);\n setSendError(undefined);\n setFailedSubmissions([]);\n setAttachmentError(undefined);\n setSending(false);\n fileInput.clearDragging();\n },\n }));\n\n useEffect(() => { onDraftChange?.(draft); }, [draft, onDraftChange]);\n\n useEffect(() => {\n if (!pendingFocus.current) {\n return;\n }\n pendingFocus.current = false;\n const element = textareaRef.current;\n if (element) {\n element.focus();\n element.setSelectionRange(element.value.length, element.value.length);\n }\n }, [draft, sending]);\n\n // Auto-grow: the height follows the content between rows and maxRows, then the textarea scrolls.\n const applyAutoGrow = useCallback(() => {\n const element = textareaRef.current;\n if (!element || inputMaxRows === undefined) {\n return;\n }\n const style = getComputedStyle(element);\n const lineHeight = Number.parseFloat(style.lineHeight) || Number.parseFloat(style.fontSize) * 1.4;\n const padding = Number.parseFloat(style.paddingTop) + Number.parseFloat(style.paddingBottom);\n const maximum = lineHeight * Math.max(inputMaxRows, inputRows) + padding;\n element.style.height = \"auto\";\n const contentHeight = element.scrollHeight;\n element.style.height = `${Math.min(contentHeight, maximum)}px`;\n element.style.overflowY = contentHeight > maximum ? \"auto\" : \"hidden\";\n }, [inputMaxRows, inputRows]);\n\n useEffect(() => {\n applyAutoGrow();\n }, [draft, applyAutoGrow]);\n\n // Hosts may lay the composer out a frame later; re-measure once the width settles.\n useEffect(() => {\n const element = textareaRef.current;\n if (!element || inputMaxRows === undefined) {\n return;\n }\n let lastWidth = element.clientWidth;\n const observer = new ResizeObserver(() => {\n if (element.clientWidth !== lastWidth) {\n lastWidth = element.clientWidth;\n applyAutoGrow();\n }\n });\n observer.observe(element);\n return () => observer.disconnect();\n }, [inputMaxRows, applyAutoGrow]);\n\n // Panel width instead of viewport width: the chat column can be arbitrarily narrow in the host.\n useEffect(() => {\n const element = rootRef.current;\n if (!element) {\n return;\n }\n const update = () => setCompact(element.clientWidth < COMPACT_WIDTH_PX);\n update();\n const observer = new ResizeObserver(update);\n observer.observe(element);\n return () => observer.disconnect();\n }, []);\n\n const hasAttachments = attachments.length > 0;\n useEffect(() => { onAttachmentsChange?.(hasAttachments); }, [hasAttachments, onAttachmentsChange]);\n const capabilityError = hasAttachments && attachmentCapabilitiesError ? attachmentCapabilitiesError : attachmentCapabilities ? attachmentCapabilityError(attachments.map((entry) => ({\n name: entry.file.name, mediaType: attachmentMediaType(entry.file),\n })), attachmentCapabilities, allTexts) : undefined;\n const hasContent = draft.trim().length > 0 || attachments.length > 0;\n const preparing = attachments.some((entry) => entry.status === \"reading\");\n const attachmentBlocked = attachments.some((entry) => entry.status !== \"ready\");\n const currentError = sendError ?? attachmentError ?? capabilityError ?? attachments.find((entry) => entry.status === \"error\")?.error;\n useEffect(() => { onErrorChange?.(currentError); }, [currentError, onErrorChange]);\n\n const send = async (onSubmit = onSend, allowEmpty = false) => {\n const text = draft.trim();\n const snapshot = attachmentsRef.current;\n if ((!allowEmpty && !text && !snapshot.length) || disabled || sendDisabled || pendingSend.current || capabilityError || snapshot.some((entry) => entry.status !== \"ready\")) {\n return;\n }\n pendingSend.current = true;\n const sentGeneration = generation.current;\n const sentRevision = draftRevision.current;\n const sentDraft = draft;\n const focusOrigin = document.activeElement;\n const startedFocused = focusOrigin === textareaRef.current || rootRef.current?.contains(focusOrigin);\n let leftComposer = false;\n const observeFocus = (event: Event) => {\n const target = event.target;\n if (target instanceof Node && !rootRef.current?.contains(target) && !detailsContainer?.contains(target)) leftComposer = true;\n };\n document.addEventListener(\"focusin\", observeFocus);\n document.addEventListener(\"pointerdown\", observeFocus);\n setSending(true);\n setSendError(undefined);\n setDraft(\"\");\n updateAttachments(() => []);\n try {\n const inputs = snapshot.flatMap((entry) => entry.status === \"ready\" ? [entry.input] : []);\n await onSubmit(text, inputs.length ? inputs : undefined);\n if (generation.current === sentGeneration && (text || inputs.length)) sendScope?.notify();\n } catch (error) {\n if (generation.current !== sentGeneration) return;\n if (draftRevision.current === sentRevision) {\n setDraft(sentDraft);\n updateAttachments((current) => [...snapshot, ...current]);\n } else if (sentDraft || snapshot.length) {\n const failed = { id: ++nextFailedId.current, draft: sentDraft, attachments: snapshot };\n setFailedSubmissions((current) => [...current, failed]);\n }\n setSendError(error instanceof Error ? error.message : String(error));\n } finally {\n document.removeEventListener(\"focusin\", observeFocus);\n document.removeEventListener(\"pointerdown\", observeFocus);\n if (generation.current === sentGeneration) {\n pendingSend.current = false;\n pendingFocus.current = !!startedFocused && !leftComposer && document.hasFocus()\n && (!toolbar || focusOrigin !== textareaRef.current) && (document.activeElement === focusOrigin\n || (!toolbar && document.activeElement === document.body));\n setSending(false);\n }\n }\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === \"Enter\" && !event.shiftKey && !event.nativeEvent.isComposing && event.nativeEvent.keyCode !== 229\n && (sendShortcut === \"enter\" || event.metaKey || event.ctrlKey)) {\n event.preventDefault();\n if (!event.repeat) void send();\n }\n };\n\n const attachmentPreviews = (\n attachments.length > 0 && (\n <ul className=\"qsl:flex qsl:max-h-[240px] qsl:flex-wrap qsl:gap-2 qsl:overflow-y-auto qsl:px-3 qsl:pt-2.5 qsl:in-data-[tone=overseer-details]:max-h-40 qsl:in-data-[tone=overseer-details]:overflow-y-auto\" aria-label={allTexts.attachments}>\n {attachments.map((entry) => (\n <li className={attachmentItemClasses} key={entry.id}>\n {entry.status === \"ready\" && entry.input.mediaType.startsWith(\"image/\") && (\n <img className={attachmentMediaClasses} src={`data:${entry.input.mediaType};base64,${entry.input.data}`} alt={entry.file.name} />\n )}\n {entry.status === \"ready\" && entry.input.mediaType.startsWith(\"video/\") && (\n <video className={attachmentMediaClasses} controls preload=\"metadata\" aria-label={entry.file.name} src={`data:${entry.input.mediaType};base64,${entry.input.data}`} />\n )}\n <div className=\"qsl:flex qsl:flex-col qsl:gap-1 qsl:p-2 qsl:pr-8 qsl:[overflow-wrap:anywhere]\">\n <span className=\"qsl:font-medium\" title={entry.file.name}>{entry.file.name}</span>\n <small>{formatAttachmentSize(entry.file.size)}</small>\n {entry.status === \"reading\" && <small role=\"status\">{allTexts.attachmentPreparing}</small>}\n {entry.status === \"error\" && <small role=\"alert\">{entry.error}</small>}\n </div>\n <Button\n aria-label={fillText(allTexts.removeAttachment, { name: entry.file.name })}\n className=\"qsl:absolute qsl:top-1 qsl:right-1\"\n disabled={disabled || sending}\n onClick={() => {\n updateAttachments((current) => current.filter((item) => item.id !== entry.id));\n setAttachmentError(undefined);\n textareaRef.current?.focus();\n }}\n size=\"icon-sm\"\n title={fillText(allTexts.removeAttachment, { name: entry.file.name })}\n variant=\"outline\"\n ><XIcon /></Button>\n </li>\n ))}\n </ul>\n )\n );\n const errors = <>\n {capabilityError && <p className={errorClasses} role=\"alert\">{capabilityError}</p>}\n {attachmentError && <p className={errorClasses} role=\"alert\">{attachmentError}</p>}\n {sendError && <p className={errorClasses} role=\"alert\">{sendError}</p>}\n {failedSubmissions.map((failed) => <div className={cn(errorClasses, \"qsl:flex qsl:flex-wrap qsl:items-center qsl:gap-2\")} key={failed.id} role=\"status\">\n <span>{allTexts.notSent} {failed.draft.slice(0, 100)}{failed.draft.length > 100 ? \" ...\" : \"\"}{failed.attachments.length > 0 ? ` ${fillText(allTexts.notSentAttachments, { count: failed.attachments.length })}` : \"\"} </span>\n <Button disabled={disabled || sending} size=\"sm\" variant=\"outline\" onClick={() => {\n try {\n validateAttachmentSelection(attachmentsRef.current.map((entry) => entry.file), failed.attachments.map((entry) => entry.file), allTexts);\n } catch (error) {\n setAttachmentError(error instanceof Error ? error.message : String(error));\n return;\n }\n draftRevision.current += 1;\n setDraft((current) => [current, failed.draft].filter(Boolean).join(\"\\n\\n\"));\n updateAttachments((current) => [...current, ...failed.attachments]);\n setFailedSubmissions((current) => current.filter((entry) => entry.id !== failed.id));\n setAttachmentError(undefined);\n pendingFocus.current = true;\n }}>{allTexts.insertUnsent}</Button>\n </div>)}\n </>;\n const sendButtons = <>\n {running && onStop && !hasContent && <StopButton className=\"qsl:flex-none\" label={allTexts.stop} onClick={onStop} size=\"icon-sm\" />}\n {(!running || !onStop || hasContent) && (\n <Button\n aria-label={allTexts.send}\n className=\"qsl:flex-none\"\n disabled={disabled || sendDisabled || sending || attachmentBlocked || !!capabilityError || !hasContent}\n onClick={() => { void send(); }}\n size=\"icon-sm\"\n title={running ? allTexts.sendIntoRun : allTexts.send}\n >\n <SendIcon size={14} />\n </Button>\n )}\n </>;\n const detailToolbar = (\n <div className={toolbarRowClasses} data-input=\"controls\">\n <div className={cn(toolbarSideClasses, \"qsl:in-data-[tone=overseer-details]:flex-none\", inline || toolbar ? \"qsl:flex-none\" : \"qsl:flex-auto\")}>\n {attachmentsEnabled && <Button\n aria-label={allTexts.attachFiles}\n disabled={disabled || sending}\n onClick={() => fileInput.inputRef.current?.click()}\n size=\"icon-sm\"\n title={fillText(allTexts.attachFilesHint, { count: MAX_CHAT_ATTACHMENTS, size: maxAttachmentSizeLabel })}\n variant=\"ghost\"\n >\n <PaperclipIcon />\n </Button>}\n {preparing && <span className={cn(\"qsl:text-xs qsl:text-muted-foreground\", inline && \"qsl:sr-only\")} role=\"status\">{allTexts.attachmentsPreparing}</span>}\n {actions?.map((action, index) => action.active === undefined ? (\n <Button disabled={action.disabled} key={index} onClick={action.onClick} size=\"sm\" title={action.title ?? action.label} variant=\"ghost\">\n {action.icon}\n {action.label && <span className={action.icon ? \"qsl:in-data-[compact=true]:hidden\" : undefined}>{action.label}</span>}\n </Button>\n ) : (\n <Toggle disabled={action.disabled} key={index} onPressedChange={() => action.onClick()} pressed={action.active} size=\"sm\" title={action.title ?? action.label}>\n {action.icon}\n {action.label && <span className={action.icon ? \"qsl:in-data-[compact=true]:hidden\" : undefined}>{action.label}</span>}\n </Toggle>\n ))}\n {toolbarLeft}\n </div>\n <div className={cn(toolbarSideClasses, \"qsl:in-data-[tone=overseer-details]:flex-1\", inline || toolbar ? \"qsl:flex-none\" : \"qsl:flex-[0_1_auto]\")}>\n {toolbarRight}\n {!toolbar && sendButtons}\n </div>\n </div>\n );\n const details = <div className=\"qsl:min-w-0\" data-compact={compact} data-quassel=\"\">\n {attachmentPreviews}\n {errors}\n {detailToolbar}\n </div>;\n\n const input = (\n <textarea\n aria-controls={inputAriaControls}\n className={textareaClasses}\n aria-label={allTexts.placeholder}\n disabled={!toolbar && disabled}\n readOnly={toolbar && disabled}\n onChange={(event) => changeDraft(event.target.value)}\n onKeyDown={onKeyDown}\n placeholder={running ? allTexts.steeringPlaceholder : allTexts.placeholder}\n ref={textareaRef}\n rows={inputRows}\n value={draft}\n />\n );\n\n return (\n <div\n className={rootClasses}\n data-compact={compact}\n data-layout={layout}\n data-quassel=\"\"\n data-working={running || sending}\n ref={rootRef}\n {...(attachmentsEnabled ? fileInput.dropProps : {})}\n >\n {attachmentsEnabled && <input\n aria-label={allTexts.attachFiles}\n hidden\n multiple\n type=\"file\"\n {...fileInput.inputProps}\n />}\n {!toolbar && attachmentPreviews}\n {inline ? <>{errors}<div className=\"qsl:flex qsl:min-w-0 qsl:items-center\">{input}{detailToolbar}</div></> : input}\n {toolbar ? <>\n <div className=\"qsl:flex qsl:flex-none qsl:items-center qsl:gap-1 qsl:p-1\">{sendButtons}</div>\n {detailsContainer && createPortal(details, detailsContainer)}\n </> : !inline && <>{errors}{detailToolbar}</>}\n\n </div>\n );\n}\n", "import { useRef, useState, type ChangeEvent, type ClipboardEvent, type DragEvent } from \"react\";\n\nexport function useFileInput({ disabled, onFiles, onPasteText }: {\n disabled?: boolean;\n onFiles: (files: File[]) => void | Promise<void>;\n onPasteText?: (text: string) => void;\n}) {\n const inputRef = useRef<HTMLInputElement>(null);\n const [dragging, setDragging] = useState(false);\n const receive = (files: File[]) => { if (files.length) void onFiles(files); };\n\n return {\n inputRef,\n dragging,\n clearDragging: () => setDragging(false),\n inputProps: {\n ref: inputRef,\n onChange: (event: ChangeEvent<HTMLInputElement>) => {\n const files = Array.from(event.currentTarget.files ?? []);\n event.currentTarget.value = \"\";\n receive(files);\n },\n },\n dropProps: {\n onDragOver: (event: DragEvent<HTMLElement>) => {\n if (!event.dataTransfer.types.includes(\"Files\")) return;\n event.preventDefault();\n event.dataTransfer.dropEffect = disabled ? \"none\" : \"copy\";\n setDragging(!disabled);\n },\n onDragLeave: (event: DragEvent<HTMLElement>) => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) setDragging(false);\n },\n onDrop: (event: DragEvent<HTMLElement>) => {\n if (!event.dataTransfer.types.includes(\"Files\")) return;\n event.preventDefault();\n setDragging(false);\n receive(Array.from(event.dataTransfer.files));\n },\n onPaste: (event: ClipboardEvent<HTMLElement>) => {\n const files = Array.from(event.clipboardData.files);\n if (!files.length) return;\n event.preventDefault();\n receive(files);\n const text = event.clipboardData.getData(\"text/plain\");\n if (text) onPasteText?.(text);\n },\n },\n };\n}\n", "import { CircleDotIcon, EyeOffIcon, ListCollapseIcon, ListIcon, type LucideIcon, ShapesIcon, TagsIcon, TextAlignJustifyIcon } from \"lucide-react\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\nimport { DetailMode } from \"./types\";\nimport { ChatTexts, defaultTexts } from \"./texts\";\n\nexport const DETAIL_MODES: readonly DetailMode[] = [\"off\", \"current\", \"icons\", \"chips\", \"grouped\", \"compact\", \"full\"];\n\nconst TEXT_KEYS: Record<DetailMode, keyof ChatTexts> = {\n off: \"detailModeOff\",\n current: \"detailModeCurrent\",\n icons: \"detailModeIcons\",\n chips: \"detailModeChips\",\n grouped: \"detailModeGrouped\",\n compact: \"detailModeCompact\",\n full: \"detailModeFull\",\n};\n\nconst ICONS: Record<DetailMode, LucideIcon> = {\n off: EyeOffIcon,\n current: CircleDotIcon,\n icons: ShapesIcon,\n chips: TagsIcon,\n grouped: ListCollapseIcon,\n compact: ListIcon,\n full: TextAlignJustifyIcon,\n};\n\nexport const detailModeLabel = (mode: DetailMode, texts?: Partial<ChatTexts>): string =>\n ({ ...defaultTexts, ...texts })[TEXT_KEYS[mode]];\n\n/**\n * An icon button that cycles the detail level of the thinking and tool steps. The order comes\n * from `modes`, the current value shows in the icon and in the tooltip.\n */\nexport function DetailModeSwitch({\n mode,\n onChange,\n modes = DETAIL_MODES,\n texts,\n className,\n}: {\n mode: DetailMode;\n onChange: (mode: DetailMode) => void;\n /** Selection and order of cycling; the default is all modes. */\n modes?: readonly DetailMode[];\n texts?: Partial<ChatTexts>;\n className?: string;\n}) {\n const allTexts = { ...defaultTexts, ...texts };\n const { Button } = useQuasselComponents();\n const current = modes.indexOf(mode);\n const next = modes[(current < 0 ? 0 : current + 1) % modes.length];\n const Icon = ICONS[mode];\n const title = `${allTexts.detailModeTitle}: ${detailModeLabel(mode, texts)}`;\n return (\n <Button aria-label={title} className={className} onClick={() => onChange(next)} size=\"icon-sm\" title={title} variant=\"ghost\">\n <Icon />\n </Button>\n );\n}\n", "import { ClockFadingIcon, ClockIcon } from \"lucide-react\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\nimport { type ChatTexts, defaultTexts } from \"./texts\";\n\nexport function TimestampSwitch({ showTimestamps, onChange, texts, className }: {\n showTimestamps: boolean;\n onChange: (showTimestamps: boolean) => void;\n texts?: Partial<ChatTexts>;\n className?: string;\n}) {\n const labels = { ...defaultTexts, ...texts };\n const { Button } = useQuasselComponents();\n const title = showTimestamps ? labels.hideTimestamps : labels.showTimestamps;\n return (\n <Button aria-label={title} aria-pressed={showTimestamps} className={className}\n onClick={() => onChange(!showTimestamps)} size=\"icon-sm\" title={title} variant=\"ghost\">\n {showTimestamps ? <ClockIcon /> : <ClockFadingIcon />}\n </Button>\n );\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { Message } from \"./events\";\n\nexport type { Role, ToolInfo, PendingAction, Message, ChatEvent, ChatTextCursor, ChatJournalCursor, ChatAttachment, ChatAttachmentInput, ChatAttachmentCapabilities, ChatStartupStatus } from \"./events\";\nexport { applyEvent, prettyJson, compactToolLine } from \"./events\";\n\n/**\n * current = only the running step, off = answers only, icons = steps as plain icons side by side,\n * chips = steps as icon + short text side by side (wrapping),\n * grouped = consecutive steps as one expandable line, single line each inside,\n * compact = thinking and tools on a single line, full = everything expanded.\n */\nexport type DetailMode = \"off\" | \"current\" | \"icons\" | \"chips\" | \"grouped\" | \"compact\" | \"full\";\n\n/** running = call still open, thinking = thought block still open, done = finished, error = failed. */\nexport type StepState = \"running\" | \"thinking\" | \"done\" | \"error\";\n\n/** The single derivation of a step state, so chips, hosts and tests read the same signal. */\nexport function stepState(message: Message): StepState {\n if (message.tool?.isError) {\n return \"error\";\n }\n if (message.role === \"thinking\") {\n return message.closed ? \"done\" : \"thinking\";\n }\n return message.tool !== undefined && message.tool.result === undefined ? \"running\" : \"done\";\n}\n\n/** A moment worth one screen reader announcement: a finished reply or a new pending action. */\nexport type ChatAnnouncement =\n | { kind: \"reply\"; message: Message }\n | { kind: \"action\"; message: Message };\n", "export interface ChatTexts {\n working: string;\n toolRunning: string;\n toolStillRunning: string;\n toolElapsedSeconds: string;\n currentTool: string;\n thinkingChip: string;\n toolChip: string;\n stepGroupOne: string;\n stepGroupMany: string;\n stepGroupCollapse: string;\n thinkingTitle: string;\n toolTitle: string;\n argumentsLabel: string;\n resultLabel: string;\n close: string;\n jumpToEnd: string;\n send: string;\n sendIntoRun: string;\n stop: string;\n placeholder: string;\n steeringPlaceholder: string;\n steered: string;\n detailModeTitle: string;\n detailModeOff: string;\n detailModeCurrent: string;\n detailModeIcons: string;\n detailModeChips: string;\n detailModeGrouped: string;\n detailModeCompact: string;\n detailModeFull: string;\n showTimestamps: string;\n hideTimestamps: string;\n copyMessage: string;\n editMessage: string;\n retryMessage: string;\n copyCode: string;\n copied: string;\n pendingAction: string;\n dismissAction: string;\n actionDismissed: string;\n actionFailed: string;\n clipboardUnavailable: string;\n transcript: string;\n attachments: string;\n attachFiles: string;\n attachFilesHint: string;\n removeAttachment: string;\n attachmentPreparing: string;\n attachmentsPreparing: string;\n attachmentReadFailed: string;\n attachmentsWhileBusy: string;\n tooManyAttachments: string;\n attachmentsTooLarge: string;\n attachmentUnsupported: string;\n attachmentUnsupportedByModel: string;\n attachmentKindImage: string;\n attachmentKindVideo: string;\n attachmentKindPdf: string;\n notSent: string;\n notSentAttachments: string;\n insertUnsent: string;\n}\n\n\nexport const fillText = (text: string, values: Record<string, string | number>): string =>\n text.replace(/\\{(\\w+)\\}/g, (match, name: string) => name in values ? String(values[name]) : match);\n\nexport const defaultTexts: ChatTexts = {\n working: \"Working ...\",\n toolRunning: \"running ...\",\n toolStillRunning: \"Tool running ...\",\n toolElapsedSeconds: \"{seconds} s\",\n currentTool: \"Tool running\",\n thinkingChip: \"Thinking\",\n toolChip: \"Tool\",\n stepGroupOne: \"1 step\",\n stepGroupMany: \"{count} steps\",\n stepGroupCollapse: \"Collapse\",\n thinkingTitle: \"Thinking trace\",\n toolTitle: \"Tool call\",\n argumentsLabel: \"Arguments\",\n resultLabel: \"Result\",\n close: \"Close\",\n jumpToEnd: \"Jump to end\",\n send: \"Send\",\n sendIntoRun: \"Feed into the running turn\",\n stop: \"Stop work\",\n placeholder: \"Write a message ...\",\n steeringPlaceholder: \"Interject ...\",\n steered: \"Fed into the running turn\",\n detailModeTitle: \"Step detail level\",\n detailModeOff: \"answers only\",\n detailModeCurrent: \"current\",\n detailModeIcons: \"icons\",\n detailModeChips: \"compact\",\n detailModeGrouped: \"grouped\",\n detailModeCompact: \"single line\",\n detailModeFull: \"everything\",\n showTimestamps: \"Show timestamps\",\n hideTimestamps: \"Hide timestamps\",\n copyMessage: \"Copy message\",\n editMessage: \"Edit message\",\n retryMessage: \"Request answer again\",\n copyCode: \"Copy code\",\n copied: \"Copied\",\n pendingAction: \"waiting for input\",\n dismissAction: \"Dismiss\",\n actionDismissed: \"dismissed\",\n actionFailed: \"Action failed\",\n clipboardUnavailable: \"The clipboard is not available\",\n transcript: \"Chat history\",\n attachments: \"Attachments\",\n attachFiles: \"Attach files\",\n attachFilesHint: \"Attach files (up to {count} files, {size} in total)\",\n removeAttachment: \"Remove {name}\",\n attachmentPreparing: \"Preparing ...\",\n attachmentsPreparing: \"Preparing attachments ...\",\n attachmentReadFailed: \"The file could not be read. Remove it and add it again.\",\n attachmentsWhileBusy: \"Wait until the input is ready again, then add the files again.\",\n tooManyAttachments: \"At most {count} attachments per message. Remove an attachment first.\",\n attachmentsTooLarge: \"Attachments may be at most {size} in total. Choose smaller files.\",\n attachmentUnsupported: \"This chat does not support {name} as {kind}. Remove the attachment.\",\n attachmentUnsupportedByModel: \"The model {model} does not support {name} as {kind}. Choose a suitable model or remove the attachment.\",\n attachmentKindImage: \"image\",\n attachmentKindVideo: \"video\",\n attachmentKindPdf: \"PDF\",\n notSent: \"Not sent:\",\n notSentAttachments: \"({count} attachments)\",\n insertUnsent: \"Insert unsent input\",\n};\n", "import type { CnFunction } from \"cn\";\nimport { createCn } from \"cn/config\";\n\nexport const cn: CnFunction = createCn({ prefix: \"qsl\", extend: { theme: { text: [\"meta\", \"trace\", \"label\"] } } });\n", "import { cn } from \"./ui/cn\";\nimport { type CSSProperties, ReactNode, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { createChatScroll } from \"./chat-scroll\";\nimport { ChatAnnouncement, DetailMode, Message, PendingAction, prettyJson, stepState, ToolInfo } from \"./types\";\nimport { ChatTexts, defaultTexts } from \"./texts\";\nimport { Markdown, MarkdownCodeBlocks, MarkdownLinks, markdownPlainText, type LinkClickHandler } from \"./Markdown\";\nimport { StepPopover } from \"./StepPopover\";\nimport { PendingActionCard } from \"./PendingActionCard\";\nimport { WorkingScenes } from \"./WorkingScenes\";\nimport { attachmentDownloadUrl, formatAttachmentSize } from \"./attachments\";\nimport { CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, LayersIcon, SparklesIcon, WrenchIcon } from \"lucide-react\";\nimport { appearanceStyle, type ChatAppearance, type TimestampOptions, type CodeBlockOptions, type BubbleOptions, type MessageActionsOptions } from \"./options\";\nimport { messageDate, timestampDay, timestampLabel } from \"./timestamps\";\nimport { formatElapsed, useElapsed } from \"./elapsed\";\nimport { MessageActions } from \"./MessageActions\";\nimport { ChatSendContext } from \"./ChatSendContext\";\nimport { ChatActionDock } from \"./ChatActionDock\";\nimport { announce as announceText } from \"./announce\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\n\nconst stepClasses = \"qsl:mt-[var(--qsl-chat-message-gap,16px)]\";\nconst denseStepClasses = \"qsl:mt-[var(--qsl-chat-dense-message-gap,8px)]\";\n\nconst traceClasses = \"qsl:flex qsl:w-full qsl:gap-2 qsl:pl-6 qsl:text-left qsl:text-trace qsl:leading-[1.375] qsl:text-muted-foreground\";\nconst traceButtonClasses = \"qsl:cursor-pointer qsl:rounded-md qsl:py-1 qsl:pr-2 qsl:transition-colors qsl:hover:bg-secondary qsl:hover:text-foreground qsl:focus-visible:bg-secondary qsl:focus-visible:text-foreground qsl:focus-visible:outline-none\";\nconst traceIconClasses = \"qsl:mt-0.5 qsl:flex-none qsl:opacity-60\";\nconst traceErrorIconClasses = \"qsl:mt-0.5 qsl:flex-none qsl:text-destructive qsl:opacity-100\";\nconst traceLineClasses = \"qsl:min-w-0 qsl:self-baseline qsl:font-mono qsl:[overflow-wrap:anywhere]\";\nconst traceRunningClasses = \"qsl:ml-1.5 qsl:opacity-60\";\n\nconst chipClasses = cn(\n \"qsl:inline-flex qsl:max-w-[220px] qsl:items-center qsl:gap-[5px] qsl:rounded-full qsl:border qsl:border-border-soft qsl:px-2.5 qsl:py-0.5\",\n \"qsl:font-mono qsl:text-meta qsl:leading-[1.6] qsl:text-muted-foreground qsl:transition-colors\",\n \"qsl:data-[state=running]:border-[color-mix(in_srgb,var(--qsl-primary)_40%,var(--qsl-border-soft))]\",\n \"qsl:data-[state=thinking]:border-[color-mix(in_srgb,var(--qsl-primary)_40%,var(--qsl-border-soft))]\",\n \"qsl:data-[state=error]:border-[color-mix(in_srgb,var(--qsl-destructive)_45%,var(--qsl-border-soft))]\",\n \"qsl:data-[state=done]:opacity-85\",\n);\nconst chipInteractiveClasses = \"qsl:cursor-pointer qsl:hover:border-border qsl:hover:bg-secondary qsl:hover:text-foreground qsl:focus-visible:border-border qsl:focus-visible:bg-secondary qsl:focus-visible:text-foreground qsl:focus-visible:outline-none qsl:data-[state=done]:hover:opacity-100 qsl:data-[state=done]:focus-visible:opacity-100\";\n\nconst collapseAtBottomFrom = 11;\n\nconst maxAnnouncementsAtOnce = 2;\n\nconst bubbleBodyClasses = \"qsl:relative qsl:max-w-[86%] qsl:px-3 qsl:py-2 qsl:leading-[var(--qsl-chat-line-height,1.625)] qsl:[overflow-wrap:anywhere] qsl:@max-[620px]/chat:max-w-full\";\n\nfunction isStep(message?: Message): boolean {\n return !!message && (message.role === \"thinking\" || message.role === \"tool\");\n}\n\nfunction isOpenAction(message: Message): message is Message & { action: PendingAction } {\n return message.role === \"action\" && message.action !== undefined && message.action.status === undefined;\n}\n\nfunction defaultArgumentsText(tool: ToolInfo): string {\n return prettyJson(tool.arguments);\n}\n\n/**\n * The transcript: its own scroll container with autoscroll while you are at the bottom, and a\n * jump-to-end button as soon as you are reading. Usable read-only without a composer.\n */\nexport function ChatMessages({\n messages,\n owner,\n detailMode = \"current\",\n running = false,\n working,\n stepsExpandable = true,\n groupsExpandable = true,\n texts,\n toolArgumentsText = defaultArgumentsText,\n renderTool,\n renderAction,\n onDismissAction,\n onLinkClick,\n emptyState,\n className,\n scrollerClassName,\n showTimestamps = false,\n announce,\n scrollerRef,\n maxWidth,\n horizontalPadding,\n jumpToEndThreshold = 120,\n appearance,\n timestampOptions,\n codeBlockOptions,\n bubbleOptions,\n messageActions,\n toolElapsedThreshold = 3000,\n}: {\n messages: Message[];\n /** Contributions with this Message.sender appear without a speech bubble; null keeps the message defaults. */\n owner?: string | null;\n detailMode?: DetailMode;\n running?: boolean;\n working?: ReactNode;\n /** false = thinking and tool steps cannot be expanded (no popover). */\n stepsExpandable?: boolean;\n /** false = step groups in grouped mode stay collapsed (header without toggle). */\n groupsExpandable?: boolean;\n texts?: Partial<ChatTexts>;\n toolArgumentsText?: (tool: ToolInfo) => string;\n /** Custom rendering for single tools; undefined = default rendering. */\n renderTool?: (tool: ToolInfo) => ReactNode | undefined;\n /** Rendering of a pending action by its owner; undefined = generic card. */\n renderAction?: (action: PendingAction, text: string) => ReactNode | undefined;\n onDismissAction?: (actionId: string) => void;\n /** Intercepts clicks on Markdown links; true = handled, the browser does not follow. */\n onLinkClick?: LinkClickHandler;\n emptyState?: ReactNode;\n className?: string;\n /** Host classes for the scroll container (data-quassel-transcript). */\n scrollerClassName?: string;\n /** true = subtle HH:MM column to the left of each block (Message.at). */\n showTimestamps?: boolean;\n /** Screen reader announcement of finished answers and new actions; false = the host announces itself. */\n announce?: false | ((announcement: ChatAnnouncement) => string | undefined);\n /** Exposes the scroll container so hosts can scroll without querying the DOM. */\n scrollerRef?: (element: HTMLDivElement | null) => void;\n maxWidth?: CSSProperties[\"maxWidth\"];\n horizontalPadding?: CSSProperties[\"paddingInline\"];\n jumpToEndThreshold?: number;\n appearance?: ChatAppearance;\n timestampOptions?: TimestampOptions;\n codeBlockOptions?: CodeBlockOptions;\n bubbleOptions?: BubbleOptions;\n messageActions?: MessageActionsOptions;\n /** Milliseconds before a running tool call shows its elapsed time (from Message.at) while running; false = never. */\n toolElapsedThreshold?: number | false;\n}) {\n const allTexts = { ...defaultTexts, ...texts };\n const { Button } = useQuasselComponents();\n const scrollArea = useRef<HTMLDivElement>(null);\n const threadRef = useRef<HTMLDivElement>(null);\n const scrollbarDragging = useRef(false);\n const touchY = useRef<number | undefined>(undefined);\n const [showJumpToEnd, setShowJumpToEnd] = useState(false);\n const [scroll] = useState(() => createChatScroll());\n const sendScope = useContext(ChatSendContext);\n const dock = useContext(ChatActionDock);\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n if (!showTimestamps || timestampOptions?.format !== \"relative\") return;\n setNow(Date.now());\n const timer = window.setInterval(() => setNow(Date.now()), 15_000);\n return () => window.clearInterval(timer);\n }, [showTimestamps, timestampOptions?.format]);\n\n // The transcript at mount time and whole batches (reset with replay) count as known, not as new.\n const announced = useRef<ReadonlySet<string>>(new Set(messages.map((message) => message.key)));\n useEffect(() => {\n const due = messages.filter((message, index) => !announced.current.has(message.key) && (\n message.role === \"action\"\n ? isOpenAction(message)\n : message.role === \"assistant\" && message.text.trim() !== \"\" && (message.closed === true || (!running && index === messages.length - 1))\n ));\n if (due.length === 0) {\n return;\n }\n announced.current = new Set([...announced.current, ...due.map((message) => message.key)]);\n if (announce === false || due.length > maxAnnouncementsAtOnce) {\n return;\n }\n due\n .map((message) => announce\n ? announce({ kind: message.role === \"action\" ? \"action\" : \"reply\", message })\n : markdownPlainText(message.text))\n .forEach((text) => text && announceText(text));\n }, [messages, running, announce]);\n const updateJumpVisibility = useCallback((viewport: HTMLDivElement) => {\n if (viewport.clientHeight > 0) setShowJumpToEnd(viewport.scrollHeight - viewport.clientHeight - viewport.scrollTop > jumpToEndThreshold);\n }, [jumpToEndThreshold]);\n useLayoutEffect(() => sendScope?.subscribe(() => {\n const viewport = scrollArea.current;\n if (!viewport) return;\n scroll.jump(viewport);\n updateJumpVisibility(viewport);\n }), [sendScope, scroll, updateJumpVisibility]);\n\n const pauseUp = (viewport: HTMLDivElement, target: EventTarget) => {\n let element = target instanceof Element ? target : null;\n while (element && element !== viewport) {\n if (element.scrollTop > 0 && /auto|scroll/.test(getComputedStyle(element).overflowY)) return;\n element = element.parentElement;\n }\n scroll.pause(viewport);\n };\n\n const checkEnd = useCallback(() => {\n const area = scrollArea.current;\n if (area) {\n scroll.scroll(area, scrollbarDragging.current);\n updateJumpVisibility(area);\n }\n }, [scroll, updateJumpVisibility]);\n\n useEffect(() => {\n const finishDrag = () => {\n if (scrollbarDragging.current && scrollArea.current) scroll.scroll(scrollArea.current, true);\n scrollbarDragging.current = false;\n };\n window.addEventListener(\"pointerup\", finishDrag);\n window.addEventListener(\"pointercancel\", finishDrag);\n return () => {\n window.removeEventListener(\"pointerup\", finishDrag);\n window.removeEventListener(\"pointercancel\", finishDrag);\n };\n }, [scroll]);\n\n // Content growth does not change the follow mode; lazily loaded media and the composer count too.\n useLayoutEffect(() => {\n const area = scrollArea.current;\n if (!area) return;\n const align = () => {\n scroll.layout(area, scrollbarDragging.current);\n updateJumpVisibility(area);\n };\n align();\n const observer = new ResizeObserver(align);\n observer.observe(area);\n if (threadRef.current) observer.observe(threadRef.current, { box: \"border-box\" });\n return () => observer.disconnect();\n });\n\n const visible = useMemo(\n () => {\n // Your own inputs after the running step do not end it; any other message does.\n const lastNonUser = messages.reduce((last, message, index) => message.role === \"user\" ? last : index, -1);\n return messages.filter((message, index) => {\n if (dock !== undefined && isOpenAction(message)) {\n return false;\n }\n if (detailMode === \"current\" && isStep(message)) {\n return running && index === lastNonUser\n && (message.role === \"thinking\" ? !message.closed : stepState(message) === \"running\");\n }\n if ((message.role === \"thinking\" || message.role === \"assistant\") && message.text.trim() === \"\" && !message.attachments?.length) {\n return false;\n }\n if (message.role === \"thinking\" || message.role === \"tool\") {\n return detailMode !== \"off\";\n }\n return true;\n });\n },\n [messages, detailMode, running, dock],\n );\n const openActions = dock ? messages.filter(isOpenAction) : [];\n\n const withTime = (content: ReactNode, key: string, at: string | undefined, dense = false): ReactNode =>\n showTimestamps\n ? (\n <div className={cn(\"qsl:flex qsl:items-baseline qsl:gap-2\", dense ? denseStepClasses : stepClasses)} key={`time-${key}`}>\n <time dateTime={messageDate(at)?.toISOString()} className={cn(\"qsl:flex-none qsl:text-meta qsl:tabular-nums qsl:text-muted-foreground qsl:opacity-85\",\n timestampOptions?.format && timestampOptions.format !== \"time\" ? \"qsl:w-[clamp(60px,20%,120px)]\" : \"qsl:w-[34px]\")}>\n {messageDate(at) ? timestampLabel(messageDate(at)!, timestampOptions, now) : \"\"}\n </time>\n <div className=\"qsl:min-w-0 qsl:flex-1 qsl:[&>*:first-child]:mt-0\">{content}</div>\n </div>\n )\n : content;\n\n // In the chip modes consecutive steps move together into one wrapping line, in grouped mode into one expandable line.\n const chipMode = detailMode === \"current\" || detailMode === \"chips\" || detailMode === \"icons\";\n const elapsedAfter = running && toolElapsedThreshold !== false ? toolElapsedThreshold : undefined;\n const groupMode = detailMode === \"grouped\";\n const blocks: ReactNode[] = [];\n let lastDay: string | undefined;\n let group: Message[] = [];\n const closeGroup = () => {\n if (group.length > 0) {\n const runningStep = running ? [...group].reverse().find((message) => [\"running\", \"thinking\"].includes(stepState(message))) : undefined;\n blocks.push(withTime(\n groupMode ? (\n <StepGroup\n elapsedAfter={elapsedAfter}\n expandable={stepsExpandable}\n groupExpandable={groupsExpandable}\n runningStep={runningStep}\n key={group[0].key}\n messages={group}\n texts={allTexts}\n toolArgumentsText={toolArgumentsText}\n />\n ) : (\n <StepRow\n elapsedAfter={elapsedAfter}\n expandable={stepsExpandable}\n key={group[0].key}\n messages={group}\n withText={detailMode !== \"icons\"}\n texts={allTexts}\n toolArgumentsText={toolArgumentsText}\n toolLabel={detailMode === \"current\" && !stepsExpandable ? allTexts.currentTool : undefined}\n />\n ),\n group[0].key,\n group[0].at,\n ));\n group = [];\n }\n };\n visible.forEach((message, index) => {\n const date = timestampOptions?.showDaySeparators ? messageDate(message.at) : undefined;\n if (date) {\n const day = timestampDay(date, timestampOptions);\n if (day.key !== lastDay) {\n closeGroup();\n blocks.push(<div className={cn(stepClasses, \"qsl:text-center qsl:text-xs qsl:text-muted-foreground\")} data-chat=\"day-separator\" data-day={day.key} key={`day-${message.key}`}>{day.label}</div>);\n lastDay = day.key;\n }\n }\n const customRendering = message.role === \"tool\" && message.tool && detailMode !== \"current\" ? renderTool?.(message.tool) : undefined;\n if (customRendering !== undefined) {\n closeGroup();\n blocks.push(withTime(\n <div className={stepClasses} key={message.key}>\n {customRendering}\n </div>,\n message.key,\n message.at,\n ));\n return;\n }\n if ((chipMode || groupMode) && isStep(message)) {\n group = [...group, message];\n return;\n }\n closeGroup();\n const dense = isStep(message) && isStep(visible[index - 1]);\n blocks.push(withTime(\n <Bubble\n detailMode={detailMode}\n dense={dense}\n elapsedAfter={elapsedAfter}\n expandable={stepsExpandable}\n key={message.key}\n message={message}\n plain={owner != null && message.sender === owner}\n texts={allTexts}\n toolArgumentsText={toolArgumentsText}\n renderAction={renderAction}\n onDismissAction={onDismissAction}\n bubbleOptions={bubbleOptions}\n messageActions={messageActions}\n />,\n message.key,\n message.at,\n dense,\n ));\n });\n closeGroup();\n\n const transcript = (\n <div className={cn(\"qsl:@container/chat qsl:relative qsl:flex qsl:min-h-0 qsl:flex-1 qsl:flex-col\", className)} data-quassel=\"\" style={{\n ...appearanceStyle(appearance),\n \"--qsl-chat-content-max-width\": typeof maxWidth === \"number\" ? `${maxWidth}px` : maxWidth,\n \"--qsl-chat-horizontal-padding\": typeof horizontalPadding === \"number\" ? `${horizontalPadding}px` : horizontalPadding,\n } as CSSProperties}>\n <div\n aria-label={allTexts.transcript}\n className={cn(\n \"qsl:min-h-0 qsl:flex-1 qsl:cursor-default qsl:overflow-y-auto qsl:text-[length:var(--qsl-chat-font-size,13px)] qsl:text-foreground\",\n \"qsl:[--qsl-fade-edge:calc(100%_-_var(--qsl-composer-height,0px))]\",\n \"qsl:[-webkit-mask-image:linear-gradient(to_bottom,#000_calc(var(--qsl-fade-edge)_-_40px),transparent_calc(var(--qsl-fade-edge)_+_16px))]\",\n \"qsl:[mask-image:linear-gradient(to_bottom,#000_calc(var(--qsl-fade-edge)_-_40px),transparent_calc(var(--qsl-fade-edge)_+_16px))]\",\n \"qsl:in-data-[tone=material]:p-0\",\n scrollerClassName,\n )}\n data-quassel-transcript=\"\"\n onScroll={checkEnd}\n onWheel={(event) => { if (!event.ctrlKey && event.deltaY < 0) pauseUp(event.currentTarget, event.target); }}\n onKeyDown={(event) => {\n const editable = event.target instanceof Element && event.target.closest(\"input, textarea, select, [contenteditable=true]\");\n if (!editable && ([\"ArrowUp\", \"PageUp\", \"Home\"].includes(event.key) || event.target === event.currentTarget && event.key === \" \" && event.shiftKey)) pauseUp(event.currentTarget, event.target);\n }}\n onPointerDown={(event) => {\n const viewport = event.currentTarget;\n scrollbarDragging.current = event.clientX >= viewport.getBoundingClientRect().right - Math.max(16, viewport.offsetWidth - viewport.clientWidth);\n }}\n onTouchStart={(event) => { touchY.current = event.touches[0]?.clientY; }}\n onTouchMove={(event) => {\n const next = event.touches[0]?.clientY;\n if (next !== undefined && touchY.current !== undefined && next > touchY.current) pauseUp(event.currentTarget, event.target);\n touchY.current = next;\n }}\n role=\"region\"\n tabIndex={0}\n ref={(element) => {\n scrollArea.current = element;\n scrollerRef?.(element);\n }}\n >\n {visible.length === 0 && !running ? (\n emptyState ?? null\n ) : (\n <div\n aria-busy={running || undefined}\n className={cn(\n \"qsl:mx-auto qsl:w-[calc(100%_-_2_*_var(--qsl-chat-horizontal-padding,24px))] qsl:max-w-[var(--qsl-chat-content-max-width,none)] qsl:pt-2\",\n \"qsl:pb-[calc(var(--qsl-composer-height,0px)_+_max(3.25em,40px))]\",\n \"qsl:in-data-[tone=material]:[&>*:first-child]:mt-0\",\n )}\n ref={threadRef}\n >\n {blocks}\n {running && (working ?? <WorkingScenes label={allTexts.working} />)}\n </div>\n )}\n </div>\n {showJumpToEnd && (\n <div className=\"qsl:pointer-events-none qsl:absolute qsl:inset-x-0 qsl:bottom-[calc(var(--qsl-composer-height,0px)_+_12px)] qsl:z-10 qsl:flex qsl:justify-center\">\n <Button aria-label={allTexts.jumpToEnd} className=\"qsl:pointer-events-auto qsl:rounded-full qsl:border qsl:border-primary-foreground/20 qsl:shadow-md\" size=\"icon\" title={allTexts.jumpToEnd} variant=\"default\" onClick={() => {\n if (scrollArea.current) {\n scroll.jump(scrollArea.current);\n updateJumpVisibility(scrollArea.current);\n }\n }}>\n <ChevronDownIcon />\n </Button>\n </div>\n )}\n {dock && openActions.length > 0 && createPortal(\n <div className=\"qsl:flex qsl:flex-col qsl:gap-[var(--qsl-chat-dense-message-gap,8px)] qsl:text-[length:var(--qsl-chat-font-size,13px)] qsl:text-foreground\" style={appearanceStyle(appearance)}>\n {openActions.map((message) => (\n <div key={message.key}>\n <ActionContent action={message.action} onDismissAction={onDismissAction} renderAction={renderAction} text={message.text} texts={allTexts} />\n </div>\n ))}\n </div>,\n dock,\n )}\n </div>\n );\n\n return <MarkdownLinks onLinkClick={onLinkClick}><MarkdownCodeBlocks options={codeBlockOptions} texts={allTexts}>{transcript}</MarkdownCodeBlocks></MarkdownLinks>;\n}\n\n/** Consecutive steps as chips side by side; the line wraps when space runs out. */\nfunction StepRow({\n messages,\n withText,\n expandable,\n elapsedAfter,\n texts,\n toolArgumentsText,\n toolLabel,\n}: {\n messages: Message[];\n withText: boolean;\n expandable: boolean;\n elapsedAfter: number | undefined;\n texts: ChatTexts;\n toolArgumentsText: (tool: ToolInfo) => string;\n toolLabel?: string;\n}) {\n const [detail, setDetail] = useState<{ key: string; position: { x: number; y: number } }>();\n const open = expandable && detail && messages.find((message) => message.key === detail.key);\n\n return (\n <div className={cn(stepClasses, \"qsl:flex qsl:flex-wrap qsl:items-center qsl:gap-x-1.5 qsl:gap-y-1 qsl:pl-6\")} data-step=\"row\">\n {messages.map((message) => {\n const thinking = message.role === \"thinking\";\n const tool = message.tool;\n const state = stepState(message);\n const running = state === \"running\" || state === \"thinking\";\n const label = thinking ? texts.thinkingChip : toolLabel ?? (tool?.name || message.text || texts.toolChip);\n const content = (\n <>\n {thinking ? (\n <SparklesIcon size={11} />\n ) : (\n <WrenchIcon className={tool?.isError ? \"qsl:text-destructive\" : undefined} size={11} />\n )}\n {withText && <span className=\"qsl:min-w-0 qsl:self-baseline qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap\">{label}</span>}\n {withText && <ToolElapsed after={elapsedAfter} className=\"qsl:flex-none qsl:self-baseline\" message={message} texts={texts} />}\n {withText && <span className=\"qsl:inline-flex qsl:w-2.5 qsl:flex-none qsl:items-center qsl:justify-center qsl:text-success\">{state === \"done\" && <CheckIcon size={10} />}</span>}\n </>\n );\n const classes = cn(chipClasses, !withText && \"qsl:p-1\", running && \"qsl:animate-fade-pulse qsl:motion-reduce:animate-none\");\n if (!expandable) {\n return (\n <span className={classes} data-kind={thinking ? \"thinking\" : \"tool\"} data-state={state} data-step=\"chip\" key={message.key} title={label}>\n {content}\n </span>\n );\n }\n return (\n <button\n aria-haspopup=\"dialog\"\n className={cn(classes, chipInteractiveClasses)}\n data-kind={thinking ? \"thinking\" : \"tool\"}\n data-state={state}\n data-step=\"chip\"\n key={message.key}\n onClick={(event) => setDetail({ key: message.key, position: { x: event.clientX, y: event.clientY } })}\n title={label}\n type=\"button\"\n >\n {content}\n </button>\n );\n })}\n {open && detail && (\n <StepPopover\n message={open}\n position={detail.position}\n texts={texts}\n toolArgumentsText={toolArgumentsText}\n onClose={() => setDetail(undefined)}\n />\n )}\n </div>\n );\n}\n\n/** Consecutive steps behind a header line; expanded, they stand below it as single-line rows. */\nfunction StepGroup({\n messages,\n runningStep,\n elapsedAfter,\n expandable,\n groupExpandable,\n texts,\n toolArgumentsText,\n}: {\n messages: Message[];\n /** The step the collapsed header names while the chat runs; undefined = nothing running. */\n runningStep: Message | undefined;\n elapsedAfter: number | undefined;\n expandable: boolean;\n groupExpandable: boolean;\n texts: ChatTexts;\n toolArgumentsText: (tool: ToolInfo) => string;\n}) {\n const [open, setOpen] = useState(false);\n const header = useRef<HTMLButtonElement>(null);\n const collapsedFromBottom = useRef(false);\n useLayoutEffect(() => {\n if (!open && collapsedFromBottom.current) {\n collapsedFromBottom.current = false;\n header.current?.scrollIntoView({ block: \"nearest\" });\n }\n }, [open]);\n const active = runningStep !== undefined;\n const failed = messages.some((message) => message.tool?.isError);\n const count = messages.length === 1 ? texts.stepGroupOne : texts.stepGroupMany.replace(\"{count}\", String(messages.length));\n const runningLabel = runningStep && (runningStep.role === \"thinking\" ? texts.thinkingChip : runningStep.tool?.name || runningStep.text || texts.toolChip);\n const summary = (\n <>\n <LayersIcon className={failed ? traceErrorIconClasses : traceIconClasses} size={12} />\n <span className={cn(traceLineClasses, \"qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap\")}>\n {count}\n {runningLabel && <span className={traceRunningClasses}>{runningLabel} {texts.toolRunning}</span>}\n {runningStep && <ToolElapsed after={elapsedAfter} message={runningStep} texts={texts} />}\n </span>\n </>\n );\n\n if (!groupExpandable) {\n return (\n <div className={stepClasses} data-step=\"group\">\n <div className={cn(traceClasses, \"qsl:items-center qsl:py-1 qsl:pr-2 qsl:pl-1\", active && \"qsl:animate-fade-pulse qsl:motion-reduce:animate-none\")}>{summary}</div>\n </div>\n );\n }\n\n return (\n <div className={stepClasses} data-step=\"group\">\n <button\n aria-expanded={open}\n className={cn(traceClasses, traceButtonClasses, \"qsl:items-center qsl:pl-1\", active && \"qsl:animate-fade-pulse qsl:motion-reduce:animate-none\")}\n onClick={() => setOpen((value) => !value)}\n ref={header}\n type=\"button\"\n >\n <ChevronRightIcon className={cn(\"qsl:flex-none qsl:opacity-60 qsl:transition-transform\", open && \"qsl:rotate-90\")} size={12} />\n {summary}\n </button>\n {open && (\n <div className=\"qsl:mt-0.5 qsl:flex qsl:flex-col qsl:gap-0.5 qsl:pl-3\">\n {messages.map((message) => (\n <TraceLine className=\"qsl:pl-3\" elapsedAfter={elapsedAfter} expandable={expandable} key={message.key} message={message} texts={texts} toolArgumentsText={toolArgumentsText} />\n ))}\n </div>\n )}\n {open && messages.length >= collapseAtBottomFrom && (\n <button\n className={cn(traceClasses, traceButtonClasses, \"qsl:mt-0.5 qsl:items-center qsl:pl-1\")}\n data-step=\"group-collapse\"\n onClick={() => {\n collapsedFromBottom.current = true;\n setOpen(false);\n }}\n type=\"button\"\n >\n <ChevronUpIcon className=\"qsl:flex-none qsl:opacity-60\" size={12} />\n <span className={traceLineClasses}>{texts.stepGroupCollapse}</span>\n </button>\n )}\n </div>\n );\n}\n\n/** One step as one line; when enabled, a click opens the details in the popover. */\nfunction TraceLine({\n message,\n className,\n elapsedAfter,\n expandable,\n texts,\n toolArgumentsText,\n}: {\n message: Message;\n className: string;\n elapsedAfter: number | undefined;\n expandable: boolean;\n texts: ChatTexts;\n toolArgumentsText: (tool: ToolInfo) => string;\n}) {\n const [detailPosition, setDetailPosition] = useState<{ x: number; y: number }>();\n const thinking = message.role === \"thinking\";\n const tool = message.tool;\n const classes = cn(traceClasses, className);\n const line = cn(traceLineClasses, thinking && \"qsl:font-sans qsl:italic qsl:whitespace-pre-wrap\", \"qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap\");\n const content = (\n <>\n {thinking ? (\n <SparklesIcon className={traceIconClasses} size={12} />\n ) : (\n <WrenchIcon className={tool?.isError ? traceErrorIconClasses : traceIconClasses} size={12} />\n )}\n <span className={line}>\n {message.text}\n {tool && tool.result === undefined && <span className={traceRunningClasses}>{texts.toolRunning}</span>}\n <ToolElapsed after={elapsedAfter} message={message} texts={texts} />\n </span>\n </>\n );\n const marks = { \"data-compact\": \"true\", \"data-kind\": thinking ? \"thinking\" : \"tool\", \"data-step\": \"line\" } as const;\n if (!expandable) {\n return <div className={classes} {...marks}>{content}</div>;\n }\n return (\n <>\n <button\n aria-expanded={detailPosition !== undefined}\n aria-haspopup=\"dialog\"\n className={cn(classes, traceButtonClasses)}\n {...marks}\n onClick={(event) => setDetailPosition({ x: event.clientX, y: event.clientY })}\n type=\"button\"\n >\n {content}\n </button>\n {detailPosition && (\n <StepPopover\n message={message}\n position={detailPosition}\n texts={texts}\n toolArgumentsText={toolArgumentsText}\n onClose={() => setDetailPosition(undefined)}\n />\n )}\n </>\n );\n}\n\n/** Elapsed time of a running tool call since Message.at; aria-hidden, so the ticking number never reaches screen readers. */\nfunction ToolElapsed({ message, after, texts, className = traceRunningClasses }: { message: Message; after: number | undefined; texts: ChatTexts; className?: string }) {\n const start = stepState(message) === \"running\" ? messageDate(message.at)?.getTime() : undefined;\n return after === undefined || start === undefined ? null : <Elapsed after={after} className={className} start={start} texts={texts} />;\n}\n\nfunction Elapsed({ start, after, className, texts }: { start: number; after: number; className: string; texts: ChatTexts }) {\n const elapsed = useElapsed(start);\n if (elapsed === undefined || elapsed < after) return null;\n return <span aria-hidden=\"true\" className={cn(className, \"qsl:tabular-nums\")} data-step=\"elapsed\">{formatElapsed(elapsed, texts)}</span>;\n}\n\nfunction Bubble({\n message,\n plain,\n detailMode,\n dense,\n elapsedAfter,\n expandable,\n texts,\n toolArgumentsText,\n renderAction,\n onDismissAction,\n bubbleOptions,\n messageActions,\n}: {\n message: Message;\n plain: boolean;\n detailMode: DetailMode;\n dense: boolean;\n elapsedAfter: number | undefined;\n expandable: boolean;\n texts: ChatTexts;\n toolArgumentsText: (tool: ToolInfo) => string;\n renderAction?: (action: PendingAction, text: string) => ReactNode | undefined;\n onDismissAction?: (actionId: string) => void;\n bubbleOptions?: BubbleOptions;\n messageActions?: MessageActionsOptions;\n}) {\n const stepSpacing = dense ? denseStepClasses : stepClasses;\n\n if (message.role === \"thinking\" || (message.role === \"tool\" && message.tool)) {\n if (detailMode === \"compact\") {\n return <TraceLine className={stepSpacing} elapsedAfter={elapsedAfter} expandable={expandable} message={message} texts={texts} toolArgumentsText={toolArgumentsText} />;\n }\n const thinking = message.role === \"thinking\";\n const tool = message.tool;\n const icon = thinking ? (\n <SparklesIcon className={traceIconClasses} size={12} />\n ) : (\n <WrenchIcon className={tool?.isError ? traceErrorIconClasses : traceIconClasses} size={12} />\n );\n const line = (\n <>\n {message.text}\n {tool && tool.result === undefined && <span className={traceRunningClasses}>{texts.toolRunning}</span>}\n <ToolElapsed after={elapsedAfter} message={message} texts={texts} />\n </>\n );\n return (\n <div className={cn(traceClasses, stepSpacing)} data-kind={thinking ? \"thinking\" : \"tool\"} data-step=\"detail\">\n {icon}\n <div className=\"qsl:min-w-0 qsl:flex-1\">\n <div className={cn(traceLineClasses, thinking && \"qsl:font-sans qsl:italic qsl:whitespace-pre-wrap\")}>{line}</div>\n {tool && (\n <div className=\"qsl:mt-0.5 qsl:border-l-2 qsl:border-border-soft qsl:pl-2\">\n <pre className=\"qsl:mb-0.5 qsl:max-h-[208px] qsl:overflow-auto qsl:font-mono qsl:text-meta qsl:leading-[1.375] qsl:break-all qsl:whitespace-pre-wrap qsl:opacity-80\">{toolArgumentsText(tool)}</pre>\n {tool.result !== undefined && (\n <pre className={cn(\"qsl:mb-0.5 qsl:max-h-[208px] qsl:overflow-auto qsl:font-mono qsl:text-meta qsl:leading-[1.375] qsl:break-all qsl:whitespace-pre-wrap qsl:opacity-80\",\n tool.isError && \"qsl:text-destructive qsl:opacity-100\")}>{prettyJson(tool.result)}</pre>\n )}\n </div>\n )}\n </div>\n </div>\n );\n }\n\n if (message.role === \"action\" && message.action) {\n return (\n <div className={stepSpacing}>\n <ActionContent action={message.action} onDismissAction={onDismissAction} renderAction={renderAction} text={message.text} texts={texts} />\n </div>\n );\n }\n\n if (message.role === \"system\") {\n return (\n <div className={cn(stepSpacing, \"qsl:border-l-2 qsl:border-destructive/50 qsl:pl-3 qsl:text-sm qsl:text-muted-foreground\")} data-message=\"system\">\n <Markdown text={message.text} />\n <MessageAttachments label={texts.attachments} message={message} />\n </div>\n );\n }\n\n if (!message.text.trim() && !message.attachments?.length) return null;\n\n const variant = bubbleOptions?.variant ?? \"default\";\n const useBubble = !plain && variant !== \"plain\" && (variant === \"bubbles\" || message.role === \"user\" || !!message.bubble);\n const side = (message.role === \"user\" ? bubbleOptions?.userSide : bubbleOptions?.assistantSide)\n ?? message.bubble?.side ?? (message.role === \"user\" ? \"end\" : \"start\");\n const sender = bubbleOptions?.senderLabel?.(message) ?? message.bubble?.label ?? message.sender;\n const showSender = bubbleOptions?.showSender ?? (!!message.bubble?.label && !plain);\n const content = <>\n {showSender && sender && <span className={cn(\"qsl:mb-[5px] qsl:table qsl:text-label qsl:leading-[1.45] qsl:font-semibold\",\n useBubble && message.bubble && \"qsl:rounded-full qsl:border qsl:border-white/30 qsl:bg-black/15 qsl:px-[7px] qsl:py-px qsl:tracking-[0.02em]\")} data-chat=\"sender\">{sender}</span>}\n <Markdown text={message.text} streaming={message.role === \"assistant\" && !message.closed} />\n <MessageAttachments label={texts.attachments} message={message} />\n {message.steered && <small className=\"qsl:mt-1 qsl:block qsl:text-label qsl:leading-[1.45] qsl:opacity-70\" data-chat=\"steered\">{texts.steered}</small>}\n <MessageActions message={message} options={messageActions} texts={texts} />\n </>;\n const cursor = message.role === \"assistant\" && message.textCursor ? JSON.stringify(message.textCursor) : undefined;\n if (!useBubble) return (\n <div data-chat-text-cursor={cursor} className={cn(stepSpacing, \"qsl:group qsl:relative qsl:w-full qsl:leading-[var(--qsl-chat-line-height,1.625)] qsl:text-foreground\")} data-message=\"answer\">\n {content}\n </div>\n );\n return (\n <div data-chat-text-cursor={cursor} className={cn(stepSpacing, \"qsl:flex\", side === \"end\" ? \"qsl:justify-end\" : \"qsl:justify-start\")}\n data-message={message.role === \"user\" && !message.bubble && variant === \"default\" ? \"user\" : \"bubble\"} data-side={side}>\n <div className={cn(bubbleBodyClasses, \"qsl:group\", message.bubble\n ? \"qsl:rounded-lg qsl:text-white qsl:[--qsl-scroll-cover:var(--qsl-primary)]\"\n : \"qsl:rounded-[var(--qsl-bubble-radius,10px_10px_4px_10px)] qsl:border qsl:border-border qsl:bg-secondary qsl:text-foreground qsl:[--qsl-scroll-cover:var(--qsl-secondary)] qsl:in-data-[tone=material]:rounded-[var(--qsl-bubble-radius,9px)] qsl:in-data-[tone=material]:border-glass-edge/20 qsl:in-data-[tone=material]:bg-primary/15 qsl:in-data-[tone=material]:text-foreground\")}\n data-tone={message.bubble ? \"on-color\" : undefined}\n style={{ background: message.bubble?.color, maxWidth: bubbleOptions?.maxWidth }}>\n {content}\n </div>\n </div>\n );\n}\n\nfunction ActionContent({\n action,\n text,\n texts,\n renderAction,\n onDismissAction,\n}: {\n action: PendingAction;\n text: string;\n texts: ChatTexts;\n renderAction?: (action: PendingAction, text: string) => ReactNode | undefined;\n onDismissAction?: (actionId: string) => void;\n}) {\n return renderAction?.(action, text) ?? (\n <PendingActionCard\n action={action}\n dismissedLabel={texts.actionDismissed}\n dismissLabel={texts.dismissAction}\n onDismiss={onDismissAction ? () => onDismissAction(action.actionId) : undefined}\n text={text}\n waitingLabel={texts.pendingAction}\n />\n );\n}\n\nfunction MessageAttachments({ message, label }: { message: Message; label: string }) {\n if (!message.attachments?.length) return null;\n return (\n <ul className=\"qsl:mt-2.5 qsl:flex qsl:flex-wrap qsl:gap-2\" aria-label={label}>\n {message.attachments.map((attachment, index) => (\n <li className=\"qsl:relative qsl:flex qsl:w-[190px] qsl:max-w-full qsl:min-w-0 qsl:flex-col qsl:overflow-hidden qsl:rounded-lg qsl:border qsl:border-border qsl:text-sm\" key={`${attachment.url}-${index}`}>\n {attachment.mediaType.startsWith(\"image/\") && <a href={attachmentDownloadUrl(attachment.url)} download={attachment.name}><img className=\"qsl:block qsl:h-[112px] qsl:w-full qsl:bg-secondary qsl:object-contain\" src={attachment.url} alt={attachment.name} loading=\"lazy\" /></a>}\n {attachment.mediaType.startsWith(\"video/\") && <video className=\"qsl:block qsl:h-[112px] qsl:w-full qsl:bg-secondary qsl:object-contain\" src={attachment.url} controls preload=\"metadata\" aria-label={attachment.name} />}\n <div className=\"qsl:flex qsl:flex-col qsl:gap-1 qsl:p-2 qsl:[overflow-wrap:anywhere]\">\n <a className=\"qsl:font-medium\" href={attachmentDownloadUrl(attachment.url)} download={attachment.name}>{attachment.name}</a>\n <small>{formatAttachmentSize(attachment.size)}</small>\n </div>\n </li>\n ))}\n </ul>\n );\n}\n", "interface ScrollViewport {\n scrollTop: number;\n readonly scrollHeight: number;\n readonly clientHeight: number;\n}\n\nconst atEnd = (viewport: ScrollViewport) => viewport.scrollHeight - viewport.clientHeight - viewport.scrollTop <= 24;\n\nexport function createChatScroll(onFollowChange: (following: boolean) => void = () => {}) {\n let following = true;\n let lastTop = 0;\n\n const follow = (value: boolean) => {\n if (following === value) return;\n following = value;\n onFollowChange(value);\n };\n const layout = (viewport: ScrollViewport, dragging = false) => {\n if (viewport.clientHeight <= 0) return;\n if (dragging && viewport.scrollTop < lastTop && !atEnd(viewport)) follow(false);\n if (following) viewport.scrollTop = Math.max(0, viewport.scrollHeight - viewport.clientHeight);\n else if (viewport.scrollHeight <= viewport.clientHeight) follow(true);\n lastTop = viewport.scrollTop;\n };\n return {\n layout,\n pause(viewport: ScrollViewport) {\n if (viewport.scrollTop > 0) follow(false);\n },\n scroll(viewport: ScrollViewport, dragging = false) {\n if (viewport.clientHeight <= 0) return;\n if (atEnd(viewport)) follow(true);\n else if (dragging && viewport.scrollTop < lastTop) follow(false);\n lastTop = viewport.scrollTop;\n },\n jump(viewport: ScrollViewport) {\n follow(true);\n layout(viewport);\n },\n };\n}\n", "import { createContext, ReactNode, useCallback, useContext, useRef } from \"react\";\nimport { Streamdown, type Components } from \"streamdown\";\nimport { CheckIcon, CopyIcon } from \"lucide-react\";\nimport { cn } from \"./ui/cn\";\nimport { useAllowUrl, useQuasselComponents } from \"./QuasselProvider\";\nimport type { CodeBlockOptions } from \"./options\";\nimport { type ChatTexts, defaultTexts } from \"./texts\";\nimport { copyChatText, useChatAction } from \"./useChatAction\";\n\nexport type LinkClickHandler = (href: string, label: string) => boolean;\n\nconst LinkClickContext = createContext<LinkClickHandler | undefined>(undefined);\nconst CodeBlockContext = createContext<{ options?: CodeBlockOptions; texts: ChatTexts }>({ texts: defaultTexts });\n\nexport function MarkdownCodeBlocks({ children, options, texts }: { children: ReactNode; options?: CodeBlockOptions; texts: ChatTexts }) {\n return <CodeBlockContext.Provider value={{ options, texts }}>{children}</CodeBlockContext.Provider>;\n}\n\nfunction CodeBlock({ children }: { children?: ReactNode }) {\n const { options, texts } = useContext(CodeBlockContext);\n const { Button } = useQuasselComponents();\n const code = useRef<HTMLPreElement>(null);\n const action = useChatAction();\n const label = action.status === \"done\" ? texts.copied : texts.copyCode;\n const block = <pre ref={code} data-chat=\"code-block\"\n className={cn(scrollbar, \"qsl:my-2 qsl:overflow-auto qsl:rounded-lg qsl:bg-secondary qsl:px-3 qsl:py-2 qsl:font-mono qsl:text-sm qsl:leading-relaxed qsl:in-data-[tone=on-color]:bg-black/30 qsl:in-data-[tone=on-color]:text-inherit\")}\n style={{ maxHeight: options?.maxHeight, whiteSpace: options?.wrap ? \"pre-wrap\" : undefined, overflowWrap: options?.wrap ? \"anywhere\" : undefined }}>{children}</pre>;\n if (!options?.showCopyButton) return block;\n return <div className=\"qsl:relative\">\n {block}\n <Button aria-label={label} className=\"qsl:absolute qsl:top-1 qsl:right-1 qsl:bg-secondary\" disabled={action.status === \"pending\"} size=\"icon-sm\" title={label} variant=\"ghost\"\n onClick={() => { void action.invoke(() => copyChatText(code.current?.textContent ?? \"\", texts.clipboardUnavailable), texts.actionFailed); }}>\n {action.status === \"done\" ? <CheckIcon /> : <CopyIcon />}\n </Button>\n {action.error && <p className=\"qsl:text-sm qsl:text-destructive\" role=\"alert\">{action.error}</p>}\n </div>;\n}\n\nexport function MarkdownLinks({ children, onLinkClick }: { children: ReactNode; onLinkClick?: LinkClickHandler }) {\n return <LinkClickContext.Provider value={onLinkClick}>{children}</LinkClickContext.Provider>;\n}\n\nfunction MarkdownLink({ href, children }: { href?: string; children?: ReactNode }) {\n const onLinkClick = useContext(LinkClickContext);\n if (!href || href === \"streamdown:incomplete-link\") {\n return <span>{children}</span>;\n }\n return (\n <a\n className=\"qsl:text-primary qsl:[text-underline-offset:2px] qsl:in-data-[tone=on-color]:text-inherit qsl:in-data-[tone=on-color]:underline\"\n href={href}\n onClick={(event) => {\n if (href && onLinkClick?.(href, event.currentTarget.textContent ?? \"\")) {\n event.preventDefault();\n }\n }}\n rel=\"noreferrer\"\n target=\"_blank\"\n >\n {children}\n </a>\n );\n}\n\n// Horizontal scrollbars stay visible - otherwise the overflow cannot be found.\nconst scrollbar = \"qsl:[scrollbar-width:thin] qsl:[&::-webkit-scrollbar]:block qsl:[&::-webkit-scrollbar]:h-2 qsl:[&::-webkit-scrollbar-thumb]:rounded-full qsl:[&::-webkit-scrollbar-thumb]:bg-border\";\n\n// The cover strips hide the cut at the edge; --qsl-scroll-cover comes from the surrounding bubble.\nconst scrollCover = \"qsl:bg-[linear-gradient(to_right,var(--qsl-scroll-cover,var(--qsl-background))_50%,transparent)_left/20px_100%_no-repeat_local,linear-gradient(to_left,var(--qsl-scroll-cover,var(--qsl-background))_50%,transparent)_right/20px_100%_no-repeat_local,linear-gradient(to_right,#00000047,transparent)_left/14px_100%_no-repeat_scroll,linear-gradient(to_left,#00000047,transparent)_right/14px_100%_no-repeat_scroll]\";\n\nconst headingClasses = \"qsl:mt-3 qsl:mb-1 qsl:text-[15px] qsl:font-medium\";\nconst cellClasses = \"qsl:max-w-[44ch] qsl:border qsl:border-border qsl:px-2 qsl:py-1 qsl:text-left qsl:align-top qsl:in-data-[tone=on-color]:border-white/35\";\n\nconst components: Components = {\n h1: ({ children }) => <h1 className=\"qsl:mt-3 qsl:mb-1 qsl:text-lg qsl:font-semibold\">{children}</h1>,\n h2: ({ children }) => <h2 className={headingClasses}>{children}</h2>,\n h3: ({ children }) => <h3 className={headingClasses}>{children}</h3>,\n h4: ({ children }) => <h4 className=\"qsl:mt-2 qsl:mb-1 qsl:text-base qsl:font-medium\">{children}</h4>,\n h5: ({ children }) => <h5 className=\"qsl:mt-2 qsl:mb-1 qsl:text-base qsl:font-medium\">{children}</h5>,\n h6: ({ children }) => <h6 className=\"qsl:mt-2 qsl:mb-1 qsl:text-base qsl:font-medium\">{children}</h6>,\n p: ({ children }) => <p className=\"qsl:[p+&]:mt-2\">{children}</p>,\n ul: ({ children }) => <ul className=\"qsl:my-2 qsl:list-disc qsl:pl-6 qsl:[li>&]:my-0\">{children}</ul>,\n ol: ({ children }) => <ol className=\"qsl:my-2 qsl:list-decimal qsl:pl-6 qsl:[li>&]:my-0\">{children}</ol>,\n li: ({ children }) => <li className=\"qsl:marker:text-muted-foreground qsl:in-data-[tone=on-color]:marker:text-inherit\">{children}</li>,\n hr: () => <hr className=\"qsl:my-3 qsl:border-t qsl:border-border\" />,\n img: ({ src, alt }) => <img alt={alt} className=\"qsl:h-auto qsl:max-w-full\" src={typeof src === \"string\" ? src : undefined} />,\n blockquote: ({ children }) => (\n <blockquote className=\"qsl:my-1 qsl:border-l-2 qsl:border-border qsl:pl-3 qsl:text-muted-foreground qsl:in-data-[tone=on-color]:border-white/50 qsl:in-data-[tone=on-color]:text-inherit\">{children}</blockquote>\n ),\n strong: ({ children }) => <strong className=\"qsl:font-medium\">{children}</strong>,\n em: ({ children }) => <em>{children}</em>,\n a: ({ href, children }) => <MarkdownLink href={href}>{children}</MarkdownLink>,\n pre: ({ children }) => <CodeBlock>{children}</CodeBlock>,\n code: ({ children, className }) => (\n <code className={cn(className, \"qsl:rounded-sm qsl:bg-secondary qsl:px-1 qsl:py-0.5 qsl:font-mono qsl:text-sm qsl:[overflow-wrap:anywhere] qsl:in-data-[tone=on-color]:bg-white/20 qsl:in-data-[tone=on-color]:text-inherit\", \"qsl:[pre>&]:bg-transparent qsl:[pre>&]:p-0\")}>{children}</code>\n ),\n // Without max-content the table shrinks to the container and stacks letters.\n table: ({ children }) => (\n <div className={cn(scrollbar, scrollCover, \"qsl:my-2 qsl:overflow-x-auto\")}>\n <table className=\"qsl:w-max qsl:min-w-full qsl:border-collapse qsl:text-sm\">{children}</table>\n </div>\n ),\n thead: ({ children }) => <thead>{children}</thead>,\n tbody: ({ children }) => <tbody>{children}</tbody>,\n tr: ({ children }) => <tr>{children}</tr>,\n th: ({ children }) => <th className={cn(cellClasses, \"qsl:bg-secondary qsl:font-medium qsl:in-data-[tone=on-color]:bg-white/15 qsl:in-data-[tone=on-color]:text-inherit\")}>{children}</th>,\n td: ({ children }) => <td className={cellClasses}>{children}</td>,\n};\n\nfunction transformUrl(url: string, allowUrl?: (url: string) => boolean) {\n if (allowUrl?.(url)) return url;\n const scheme = /^[^/?#]*:/.exec(url);\n return !scheme || /^(https?|mailto|tel|ftp|irc|ircs|xmpp):$/i.test(scheme[0]) ? url : \"\";\n}\n\nexport function Markdown({ text, streaming = false }: { text: string; streaming?: boolean }) {\n const allowUrl = useAllowUrl();\n const urlTransform = useCallback((url: string) => transformUrl(url, allowUrl), [allowUrl]);\n return (\n <Streamdown\n className=\"space-y-0 text-inherit\"\n prefix=\"qsl\"\n mode={streaming ? \"streaming\" : \"static\"}\n isAnimating={streaming}\n parseIncompleteMarkdown={streaming}\n components={components}\n controls={false}\n rehypePlugins={[]}\n urlTransform={urlTransform}\n skipHtml\n >\n {text}\n </Streamdown>\n );\n}\n\n/** The same syntax as the renderer, as plain text without markup, e.g. for screen reader announcements. */\nexport function markdownPlainText(text: string): string {\n return text\n .split(\"\\n\")\n .filter((line) => !/^\\s*```\\w*\\s*$/.test(line) && !isTableDivider(line))\n .map((line) => (line.trim().startsWith(\"|\") ? splitTableRow(line).join(\", \") : line)\n .replace(/^(#{1,6})\\s+/, \"\")\n .replace(/^\\s*>\\s?/, \"\")\n .replace(/^\\s*([-*+]|\\d+[.)])\\s+/, \"\")\n .replace(/!?\\[([^\\]]*)\\]\\(([^)]+)\\)|\\*\\*([^*]+)\\*\\*|__([^_]+)__|\\*([^*]+)\\*|`([^`]+)`/g, (_, link, _href, bold, boldUnderscore, italic, code) => link ?? bold ?? boldUnderscore ?? italic ?? code)\n .trim())\n .filter((line) => line !== \"\")\n .join(\"\\n\");\n}\n\nfunction splitTableRow(line: string): string[] {\n let row = line.trim();\n if (row.startsWith(\"|\")) {\n row = row.slice(1);\n }\n if (row.endsWith(\"|\")) {\n row = row.slice(0, -1);\n }\n return row.split(\"|\").map((cell) => cell.trim());\n}\n\nfunction isTableDivider(line: string): boolean {\n return /^\\s*\\|?\\s*:?-{1,}:?\\s*(\\|\\s*:?-{1,}:?\\s*)*\\|?\\s*$/.test(line) && line.includes(\"-\");\n}\n", "import { createContext, useContext, useMemo, type ComponentType, type ReactNode, type RefObject } from \"react\";\nimport { Button } from \"./ui/button\";\nimport { Card } from \"./ui/card\";\nimport { Popover, PopoverContent } from \"./ui/popover\";\nimport { StopButton } from \"./ui/stop-button\";\nimport { Toggle } from \"./ui/toggle\";\n\nexport type QuasselButtonVariant = \"default\" | \"outline\" | \"secondary\" | \"ghost\" | \"destructive\" | \"link\";\nexport type QuasselButtonSize = \"default\" | \"xs\" | \"sm\" | \"lg\" | \"icon\" | \"icon-xs\" | \"icon-sm\" | \"icon-lg\";\n\nexport interface QuasselButtonProps {\n variant?: QuasselButtonVariant;\n size?: QuasselButtonSize;\n className?: string;\n disabled?: boolean;\n title?: string;\n \"aria-label\"?: string;\n \"aria-pressed\"?: boolean;\n onClick?: () => void;\n children?: ReactNode;\n}\n\nexport interface QuasselToggleProps {\n variant?: \"default\" | \"outline\";\n size?: \"default\" | \"sm\" | \"lg\";\n className?: string;\n disabled?: boolean;\n title?: string;\n pressed?: boolean;\n onPressedChange?: (pressed: boolean) => void;\n children?: ReactNode;\n}\n\nexport interface QuasselCardProps {\n size?: \"default\" | \"sm\";\n className?: string;\n children?: ReactNode;\n}\n\nexport interface QuasselStopButtonProps {\n label: string;\n busy?: boolean;\n size?: QuasselButtonSize;\n className?: string;\n disabled?: boolean;\n title?: string;\n onClick?: () => void;\n}\n\nexport interface QuasselPopoverProps {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n children?: ReactNode;\n}\n\nexport interface QuasselPopoverAnchor {\n getBoundingClientRect: () => DOMRect;\n contextElement?: Element;\n}\n\n/** Where popovers mount: an element, a ref or a getter; resolved when the popover opens. */\nexport type QuasselPortalTarget = HTMLElement | ShadowRoot;\nexport type QuasselPortalContainer = QuasselPortalTarget | RefObject<QuasselPortalTarget | null> | (() => QuasselPortalTarget | null | undefined);\n\nexport interface QuasselPopoverContentProps {\n anchor?: QuasselPopoverAnchor;\n align?: \"start\" | \"center\" | \"end\";\n side?: \"top\" | \"bottom\" | \"left\" | \"right\" | \"inline-start\" | \"inline-end\";\n sideOffset?: number;\n collisionPadding?: number;\n className?: string;\n \"aria-label\"?: string;\n /** The resolved portalContainer of QuasselProvider; undefined = document.body. */\n portalContainer?: QuasselPortalTarget;\n children?: ReactNode;\n}\n\n/** The primitives quassel renders; a host replaces any of them through QuasselProvider. */\nexport interface QuasselComponents {\n Button: ComponentType<QuasselButtonProps>;\n Toggle: ComponentType<QuasselToggleProps>;\n Card: ComponentType<QuasselCardProps>;\n StopButton: ComponentType<QuasselStopButtonProps>;\n Popover: ComponentType<QuasselPopoverProps>;\n PopoverContent: ComponentType<QuasselPopoverContentProps>;\n}\n\nexport const defaultComponents: QuasselComponents = { Button, Toggle, Card, StopButton, Popover, PopoverContent };\n\ninterface QuasselSettings {\n components: QuasselComponents;\n allowUrl?: (url: string) => boolean;\n portalContainer?: QuasselPortalContainer;\n}\n\nconst QuasselContext = createContext<QuasselSettings>({ components: defaultComponents });\n\nexport function QuasselProvider({ components, allowUrl, portalContainer, children }: {\n /** Replaces single primitives; the rest stay the built-in ones or those of an outer provider. */\n components?: Partial<QuasselComponents>;\n /** Keeps Markdown link and image URLs that the default policy (http, https, mailto, tel, ftp, irc, xmpp, relative) would drop. */\n allowUrl?: (url: string) => boolean;\n /** Mounts quassel's popovers inside this element instead of document.body, e.g. within the host's theme wrapper. */\n portalContainer?: QuasselPortalContainer;\n children: ReactNode;\n}) {\n const outer = useContext(QuasselContext);\n const value = useMemo(() => ({\n components: { ...outer.components, ...components },\n allowUrl: allowUrl ?? outer.allowUrl,\n portalContainer: portalContainer ?? outer.portalContainer,\n }), [outer, components, allowUrl, portalContainer]);\n return <QuasselContext.Provider value={value}>{children}</QuasselContext.Provider>;\n}\n\nexport const useQuasselComponents = (): QuasselComponents => useContext(QuasselContext).components;\n\nexport const useAllowUrl = (): ((url: string) => boolean) | undefined => useContext(QuasselContext).allowUrl;\n\nexport function useQuasselPortalContainer(): QuasselPortalTarget | undefined {\n const container = useContext(QuasselContext).portalContainer;\n const target = typeof container === \"function\" ? container() : container && \"current\" in container ? container.current : container;\n return target ?? undefined;\n}\n", "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"./cn\"\n\nconst buttonVariants = cva(\n \"qsl:group/button qsl:inline-flex qsl:shrink-0 qsl:items-center qsl:justify-center qsl:rounded-lg qsl:border qsl:border-transparent qsl:bg-clip-padding qsl:text-sm qsl:font-medium qsl:whitespace-nowrap qsl:transition-all qsl:outline-none qsl:select-none qsl:focus-visible:border-ring qsl:focus-visible:ring-3 qsl:focus-visible:ring-ring/50 qsl:active:not-aria-[haspopup]:translate-y-px qsl:disabled:pointer-events-none qsl:disabled:opacity-50 qsl:aria-invalid:border-destructive qsl:aria-invalid:ring-3 qsl:aria-invalid:ring-destructive/20 qsl:dark:aria-invalid:border-destructive/50 qsl:dark:aria-invalid:ring-destructive/40 qsl:[&_svg]:pointer-events-none qsl:[&_svg]:shrink-0 qsl:[&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"qsl:bg-primary qsl:text-primary-foreground qsl:hover:bg-primary/80\",\n outline:\n \"qsl:border-border qsl:bg-background qsl:hover:bg-muted qsl:hover:text-foreground qsl:aria-expanded:bg-muted qsl:aria-expanded:text-foreground qsl:dark:border-input qsl:dark:bg-input/30 qsl:dark:hover:bg-input/50\",\n secondary:\n \"qsl:bg-secondary qsl:text-secondary-foreground qsl:hover:bg-[color-mix(in_oklch,var(--qsl-secondary),var(--qsl-foreground)_5%)] qsl:aria-expanded:bg-secondary qsl:aria-expanded:text-secondary-foreground\",\n ghost:\n \"qsl:hover:bg-muted qsl:hover:text-foreground qsl:aria-expanded:bg-muted qsl:aria-expanded:text-foreground qsl:dark:hover:bg-muted/50\",\n destructive:\n \"qsl:bg-destructive/10 qsl:text-destructive qsl:hover:bg-destructive/20 qsl:focus-visible:border-destructive/40 qsl:focus-visible:ring-destructive/20 qsl:dark:bg-destructive/20 qsl:dark:hover:bg-destructive/30 qsl:dark:focus-visible:ring-destructive/40\",\n link: \"qsl:text-primary qsl:underline-offset-4 qsl:hover:underline\",\n },\n size: {\n default:\n \"qsl:h-8 qsl:gap-1.5 qsl:px-2.5 qsl:has-data-[icon=inline-end]:pr-2 qsl:has-data-[icon=inline-start]:pl-2\",\n xs: \"qsl:h-6 qsl:gap-1 qsl:rounded-[min(--theme(--radius-md),10px)] qsl:px-2 qsl:text-xs qsl:in-data-[slot=button-group]:rounded-lg qsl:has-data-[icon=inline-end]:pr-1.5 qsl:has-data-[icon=inline-start]:pl-1.5 qsl:[&_svg:not([class*='size-'])]:size-3\",\n sm: \"qsl:h-7 qsl:gap-1 qsl:rounded-[min(--theme(--radius-md),12px)] qsl:px-2.5 qsl:text-[0.8rem] qsl:in-data-[slot=button-group]:rounded-lg qsl:has-data-[icon=inline-end]:pr-1.5 qsl:has-data-[icon=inline-start]:pl-1.5 qsl:[&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"qsl:h-9 qsl:gap-1.5 qsl:px-2.5 qsl:has-data-[icon=inline-end]:pr-2 qsl:has-data-[icon=inline-start]:pl-2\",\n icon: \"qsl:size-8\",\n \"icon-xs\":\n \"qsl:size-6 qsl:rounded-[min(--theme(--radius-md),10px)] qsl:in-data-[slot=button-group]:rounded-lg qsl:[&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"qsl:size-7 qsl:rounded-[min(--theme(--radius-md),12px)] qsl:in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"qsl:size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-quassel=\"\"\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n", "import * as React from \"react\"\nimport { cn } from \"./cn\"\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-quassel=\"\"\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"qsl:group/card qsl:flex qsl:flex-col qsl:gap-(--qsl-card-spacing) qsl:overflow-hidden qsl:rounded-panel qsl:border qsl:border-border qsl:bg-card qsl:py-(--qsl-card-spacing) qsl:text-sm qsl:text-card-foreground qsl:shadow-bar qsl:[--qsl-card-spacing:--spacing(4)] qsl:has-data-[slot=card-footer]:pb-0 qsl:has-[>img:first-child]:pt-0 qsl:data-[size=sm]:[--qsl-card-spacing:--spacing(3)] qsl:data-[size=sm]:has-data-[slot=card-footer]:pb-0 qsl:*:[img:first-child]:rounded-t-xl qsl:*:[img:last-child]:rounded-b-xl\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Card }\n", "import { Popover as PopoverPrimitive } from \"@base-ui/react/popover\"\nimport { cn } from \"./cn\"\n\nfunction Popover({ ...props }: PopoverPrimitive.Root.Props) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\n}\n\nfunction PopoverContent({\n className,\n align = \"center\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 8,\n anchor,\n collisionPadding,\n keepMounted,\n portalContainer,\n ...props\n}: PopoverPrimitive.Popup.Props &\n Pick<\n PopoverPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\" | \"anchor\" | \"collisionPadding\"\n > & Pick<PopoverPrimitive.Portal.Props, \"keepMounted\"> & { portalContainer?: HTMLElement | ShadowRoot }) {\n return (\n <PopoverPrimitive.Portal container={portalContainer} keepMounted={keepMounted}>\n <PopoverPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n anchor={anchor}\n collisionPadding={collisionPadding}\n side={side}\n sideOffset={sideOffset}\n className=\"qsl:isolate qsl:z-[110]\"\n >\n <PopoverPrimitive.Popup\n data-quassel=\"\"\n data-quassel-popover=\"\"\n data-slot=\"popover-content\"\n className={cn(\n \"qsl:z-[110] qsl:flex qsl:w-72 qsl:origin-(--transform-origin) qsl:flex-col qsl:gap-2.5 qsl:rounded-lg qsl:bg-popover qsl:p-2.5 qsl:text-sm qsl:text-popover-foreground qsl:shadow-md qsl:ring-1 qsl:ring-foreground/10 qsl:outline-hidden qsl:duration-100 qsl:data-[side=bottom]:slide-in-from-top-2 qsl:data-[side=inline-end]:slide-in-from-left-2 qsl:data-[side=inline-start]:slide-in-from-right-2 qsl:data-[side=left]:slide-in-from-right-2 qsl:data-[side=right]:slide-in-from-left-2 qsl:data-[side=top]:slide-in-from-bottom-2 qsl:data-open:animate-in qsl:data-open:fade-in-0 qsl:data-open:zoom-in-95 qsl:data-closed:animate-out qsl:data-closed:fade-out-0 qsl:data-closed:zoom-out-95\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Positioner>\n </PopoverPrimitive.Portal>\n )\n}\n\nexport { Popover, PopoverContent }\n", "import { SquareIcon } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"./cn\";\nimport { Button } from \"./button\";\nimport { Spinner } from \"./spinner\";\n\n/** The one stop glyph: a filled red square; never used as a state icon. */\nexport function StopGlyph({ className, ...props }: Omit<ComponentProps<typeof SquareIcon>, \"fill\">) {\n return <SquareIcon aria-hidden className={cn(\"qsl:text-destructive\", className)} fill=\"currentColor\" {...props} />;\n}\n\nconst stopButtonClass = \"qsl:text-destructive qsl:hover:bg-destructive/10 qsl:hover:text-destructive qsl:dark:hover:bg-destructive/20\";\n\n/** Every stop button looks the same: the glyph as icon, the word in the tooltip, red at rest and on hover. */\nexport function StopButton({ label, busy = false, className, title, ...props }: Omit<ComponentProps<typeof Button>, \"children\" | \"variant\"> & {\n label: string;\n busy?: boolean;\n}) {\n return <Button aria-busy={busy || undefined} aria-label={label} className={cn(stopButtonClass, className)} title={title ?? label} variant=\"ghost\" {...props}>\n {busy ? <Spinner /> : <StopGlyph />}\n </Button>;\n}\n", "import { cn } from \"./cn\"\nimport { Loader2Icon } from \"lucide-react\"\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <Loader2Icon data-slot=\"spinner\" role=\"status\" aria-label=\"Loading\" className={cn(\"qsl:size-4 qsl:animate-spin\", className)} {...props} />\n )\n}\n\nexport { Spinner }\n", "import { Toggle as TogglePrimitive } from \"@base-ui/react/toggle\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"./cn\"\n\nconst toggleVariants = cva(\n \"qsl:group/toggle qsl:inline-flex qsl:items-center qsl:justify-center qsl:gap-1 qsl:rounded-lg qsl:text-sm qsl:font-medium qsl:whitespace-nowrap qsl:transition-all qsl:outline-none qsl:hover:bg-muted qsl:hover:text-foreground qsl:focus-visible:border-ring qsl:focus-visible:ring-[3px] qsl:focus-visible:ring-ring/50 qsl:disabled:pointer-events-none qsl:disabled:opacity-50 qsl:aria-invalid:border-destructive qsl:aria-invalid:ring-destructive/20 qsl:aria-pressed:bg-muted qsl:data-[state=on]:bg-muted qsl:dark:aria-invalid:ring-destructive/40 qsl:[&_svg]:pointer-events-none qsl:[&_svg]:shrink-0 qsl:[&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"qsl:bg-transparent\",\n outline: \"qsl:border qsl:border-input qsl:bg-transparent qsl:hover:bg-muted\",\n },\n size: {\n default:\n \"qsl:h-8 qsl:min-w-8 qsl:px-2.5 qsl:has-data-[icon=inline-end]:pr-2 qsl:has-data-[icon=inline-start]:pl-2\",\n sm: \"qsl:h-7 qsl:min-w-7 qsl:rounded-[min(--theme(--radius-md),12px)] qsl:px-2.5 qsl:text-[0.8rem] qsl:has-data-[icon=inline-end]:pr-1.5 qsl:has-data-[icon=inline-start]:pl-1.5 qsl:[&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"qsl:h-9 qsl:min-w-9 qsl:px-2.5 qsl:has-data-[icon=inline-end]:pr-2 qsl:has-data-[icon=inline-start]:pl-2\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Toggle({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {\n return (\n <TogglePrimitive\n data-quassel=\"\"\n data-slot=\"toggle\"\n className={cn(toggleVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Toggle, toggleVariants }\n", "import { useEffect, useRef, useState } from \"react\";\n\nexport function useChatAction() {\n const pending = useRef(false);\n const [status, setStatus] = useState<\"idle\" | \"pending\" | \"done\">(\"idle\");\n const [error, setError] = useState<string>();\n useEffect(() => {\n if (status !== \"done\") return;\n const timer = window.setTimeout(() => setStatus(\"idle\"), 1800);\n return () => window.clearTimeout(timer);\n }, [status]);\n const invoke = async (action: () => void | Promise<void>, failureLabel: string) => {\n if (pending.current) return;\n pending.current = true;\n setError(undefined);\n setStatus(\"pending\");\n try {\n await action();\n setStatus(\"done\");\n } catch (failure) {\n const detail = failure instanceof Error ? failure.message : String(failure);\n setError(`${failureLabel}: ${detail}`);\n setStatus(\"idle\");\n } finally {\n pending.current = false;\n }\n };\n return { status, error, invoke };\n}\n\nexport async function copyChatText(text: string, unavailable: string) {\n if (!navigator.clipboard) throw new Error(unavailable);\n await navigator.clipboard.writeText(text);\n}\n", "import { useMemo } from \"react\";\nimport { SparklesIcon, WrenchIcon, XIcon } from \"lucide-react\";\nimport { cn } from \"./ui/cn\";\nimport { useQuasselComponents, useQuasselPortalContainer } from \"./QuasselProvider\";\nimport { Message, prettyJson } from \"./types\";\nimport { ChatTexts } from \"./texts\";\n\nconst preClasses = \"qsl:rounded-lg qsl:bg-secondary qsl:p-3 qsl:font-mono qsl:text-trace qsl:leading-[1.625] qsl:break-all qsl:whitespace-pre-wrap\";\n\nexport function StepPopover({\n message,\n position,\n texts,\n toolArgumentsText,\n onClose,\n}: {\n message: Message;\n position: { x: number; y: number };\n texts: ChatTexts;\n toolArgumentsText: (tool: NonNullable<Message[\"tool\"]>) => string;\n onClose: () => void;\n}) {\n const anchor = useMemo(() => ({\n getBoundingClientRect: () => new DOMRect(position.x, position.y, 0, 0),\n contextElement: document.documentElement,\n }), [position]);\n const { Button, Popover, PopoverContent } = useQuasselComponents();\n const portalContainer = useQuasselPortalContainer();\n const tool = message.tool;\n const thinking = message.role === \"thinking\";\n const title = thinking ? texts.thinkingTitle : texts.toolTitle;\n\n return (\n <Popover open onOpenChange={(open) => { if (!open) onClose(); }}>\n <PopoverContent\n align=\"start\"\n anchor={anchor}\n aria-label={title}\n className={cn(\n \"qsl:w-[min(680px,calc(100vw-32px))] qsl:gap-0 qsl:overflow-hidden qsl:p-0 qsl:text-[13px] qsl:leading-normal qsl:shadow-pop\",\n thinking ? \"qsl:max-h-none\" : \"qsl:max-h-[min(70vh,620px)]\",\n )}\n collisionPadding={16}\n portalContainer={portalContainer}\n side=\"bottom\"\n sideOffset={10}\n >\n <div className=\"qsl:flex qsl:flex-none qsl:items-center qsl:gap-2 qsl:border-b qsl:border-border-soft qsl:px-4 qsl:py-2.5\">\n {thinking ? (\n <SparklesIcon className=\"qsl:text-muted-foreground\" size={14} />\n ) : (\n <WrenchIcon className={tool?.isError ? \"qsl:text-destructive\" : \"qsl:text-muted-foreground\"} size={14} />\n )}\n <span className=\"qsl:min-w-0 qsl:flex-1 qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap qsl:font-medium\">{title}</span>\n <Button aria-label={texts.close} className=\"qsl:flex-none\" onClick={onClose} size=\"icon-sm\" title={texts.close} variant=\"ghost\">\n <XIcon />\n </Button>\n </div>\n <div className={cn(\"qsl:min-h-0 qsl:p-4\", thinking ? \"qsl:overflow-visible\" : \"qsl:overflow-auto\")}>\n {thinking ? (\n <div className=\"qsl:text-sm qsl:leading-[1.625] qsl:whitespace-pre-wrap\">{message.text}</div>\n ) : tool ? (\n <div className=\"qsl:flex qsl:flex-col qsl:gap-4\">\n <div className=\"qsl:font-mono qsl:text-sm\">{message.text}</div>\n <PopoverSection label={texts.argumentsLabel} value={toolArgumentsText(tool)} />\n {tool.result === undefined ? (\n <div className=\"qsl:text-sm qsl:text-muted-foreground\">{texts.toolStillRunning}</div>\n ) : (\n <PopoverSection error={tool.isError} label={texts.resultLabel} value={prettyJson(tool.result)} />\n )}\n </div>\n ) : null}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction PopoverSection({ label, value, error = false }: { label: string; value: string; error?: boolean }) {\n return (\n <section>\n <h3 className=\"qsl:mb-1.5 qsl:text-trace qsl:font-semibold qsl:tracking-[0.04em] qsl:text-muted-foreground qsl:uppercase\">{label}</h3>\n <pre className={cn(preClasses, error && \"qsl:text-destructive\")}>{value}</pre>\n </section>\n );\n}\n", "import { CheckIcon, XIcon } from \"lucide-react\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\nimport type { PendingAction } from \"./types\";\n\nconst cardClasses = \"qsl:gap-2.5 qsl:bg-background qsl:px-3.5 qsl:text-sm\";\n\nconst resultText = (result: unknown): string =>\n typeof result === \"string\" ? result : result === null || result === undefined ? \"\" : JSON.stringify(result);\n\n/**\n * The rendering of a pending action without a contribution from its owner: title, the hint\n * that input is expected, and dismissing. Only the plugin knows the form.\n */\nexport function PendingActionCard({\n text,\n action,\n waitingLabel,\n dismissLabel,\n dismissedLabel,\n onDismiss,\n}: {\n text: string;\n action: PendingAction;\n waitingLabel: string;\n dismissLabel: string;\n dismissedLabel: string;\n onDismiss?: () => void;\n}) {\n const { Button, Card } = useQuasselComponents();\n if (action.status !== undefined) {\n return (\n <Card className={cardClasses} size=\"sm\">\n <div className=\"qsl:leading-normal\">{text}</div>\n <div className=\"qsl:flex qsl:items-center qsl:gap-1.5 qsl:text-sm qsl:text-muted-foreground\" data-action=\"resolved\">\n {action.status === \"approved\" ? <CheckIcon className=\"qsl:text-success\" size={12} /> : <XIcon size={12} />}\n {action.status === \"approved\" ? resultText(action.result) : dismissedLabel}\n </div>\n </Card>\n );\n }\n\n return (\n <Card className={cardClasses} size=\"sm\">\n <div className=\"qsl:leading-normal\">{text}</div>\n <div className=\"qsl:flex qsl:items-center qsl:justify-between qsl:gap-2\">\n <span className=\"qsl:text-sm qsl:text-muted-foreground\" data-action=\"waiting\">{waitingLabel}</span>\n {onDismiss && (\n <Button onClick={onDismiss} size=\"sm\" variant=\"outline\">{dismissLabel}</Button>\n )}\n </div>\n </Card>\n );\n}\n", "import { useEffect, useState } from \"react\";\nimport { cn } from \"./ui/cn\";\n\nconst TRACK = 13;\nconst BASE_TICK_MS = 90;\nconst SCENE_CHANGE_MS = 2600;\n\n/** One cell per figure: emoji and punctuation share no grid, shifted text judders. */\nfunction track(figures: Record<number, string>, width = TRACK): string[] {\n return Array.from({ length: width }, (_, x) => figures[x] ?? \" \");\n}\n\ninterface Scene {\n id: string;\n tick: number;\n moving?: true;\n compact?: true;\n draw: (step: number) => string | string[];\n}\n\n/**\n * Small scenes in which something recognizable happens - the state changes visibly instead\n * of a figure just walking past. Scenes with movement return their track as cells, all others\n * as plain text.\n */\nconst SCENES: Scene[] = [\n {\n id: \"thinking\",\n tick: 2,\n draw: (step) => {\n const tick = step % 10;\n if (tick >= 8) return \"\\u{1F929}\\u{1F4A1}\";\n return \"\\u{1F914}\" + \"\\u{1F4AD}\".repeat(Math.min(tick, 3));\n },\n },\n {\n // Flies to the right, dragging its tail behind.\n id: \"rocket\",\n tick: 2,\n moving: true,\n draw: (step) => {\n const x = step % TRACK;\n return track({ [x - 2]: \"\u00B7\", [x - 1]: \"\\u{1F4A8}\", [x]: \"\\u{1F680}\" });\n },\n },\n {\n // The dots stay put and are eaten one by one.\n id: \"pacman\",\n tick: 2,\n moving: true,\n draw: (step) => {\n const x = step % TRACK;\n const figures: Record<number, string> = {};\n for (let i = x + 1; i < TRACK; i++) {\n figures[i] = \"\u00B7\";\n }\n figures[x] = step % 2 === 0 ? \"\\u{1F7E1}\" : \"\\u{1F315}\";\n return track(figures);\n },\n },\n {\n // A seed becomes a tree, then start over.\n id: \"growing\",\n compact: true,\n tick: 2,\n draw: (step) => {\n const stages = [\"\\u{1F331}\", \"\\u{1F331}\", \"\\u{1F33F}\", \"\\u{1F33F}\", \"\\u{1F343}\", \"\\u{1F333}\", \"\\u{1F333}\", \"\\u{1F333}\"];\n return stages[step % stages.length];\n },\n },\n {\n // The egg cracks, the chick hatches.\n id: \"hatching\",\n compact: true,\n tick: 2,\n draw: (step) => {\n const tick = step % 12;\n if (tick < 4) return \"\\u{1F95A}\";\n if (tick < 6) return \"\\u{1F95A}*\";\n if (tick < 9) return \"\\u{1F423}\";\n return \"\\u{1F425}\";\n },\n },\n {\n // Morse-like signal that resolves into an OK.\n id: \"signal\",\n tick: 2,\n draw: (step) => {\n const tick = step % 14;\n if (tick >= 11) return \"\\u{1F4E1} OK\";\n const pattern = [\"\u00B7\", \"\u00B7\u00B7\", \"\u00B7-\", \"-\u00B7\", \"\u00B7\u00B7-\", \"-\u00B7\u00B7\"];\n return \"\\u{1F4E1} \" + pattern[tick % pattern.length];\n },\n },\n {\n // Hourglass: the sand runs through, then it is flipped.\n id: \"hourglass\",\n tick: 2,\n draw: (step) => {\n const tick = step % 12;\n const grains = \"\u00B7\".repeat(Math.max(0, 5 - Math.floor(tick / 2)));\n return (tick < 10 ? \"\u23F3\" : \"\u231B\") + \" \" + grains;\n },\n },\n {\n // Egg, chick, hen - and she lays the next egg.\n id: \"chicken-cycle\",\n compact: true,\n tick: 3,\n draw: (step) => {\n const tick = step % 16;\n if (tick < 3) return \"\\u{1F95A}\";\n if (tick < 5) return \"\\u{1F95A}*\";\n if (tick < 8) return \"\\u{1F423}\";\n if (tick < 11) return \"\\u{1F424}\";\n if (tick < 14) return \"\\u{1F414}\";\n return \"\\u{1F414}\\u{1F95A}\";\n },\n },\n {\n // Hat, sparks - and the rabbit bolts.\n id: \"magic-hat\",\n compact: true,\n tick: 3,\n draw: (step) => {\n const tick = step % 14;\n if (tick < 4) return \"\\u{1F3A9}\";\n if (tick < 7) return \"\\u{1F3A9}*\";\n if (tick < 11) return \"\\u{1F3A9}\\u{1F407}\";\n return \"\\u{1F407}\\u{1F4A8}\";\n },\n },\n {\n // Red, yellow, green - and off.\n id: \"traffic-light\",\n compact: true,\n tick: 3,\n draw: (step) => {\n const tick = step % 12;\n if (tick < 4) return \"\\u{1F534}\";\n if (tick < 6) return \"\\u{1F7E1}\";\n if (tick < 8) return \"\\u{1F7E2}\";\n return \"\\u{1F697}\\u{1F4A8}\";\n },\n },\n {\n // Ringing, oversleeping, running off.\n id: \"alarm-clock\",\n compact: true,\n tick: 2,\n draw: (step) => {\n const tick = step % 14;\n if (tick < 5) return tick % 2 === 0 ? \"\u23F0\" : \"\\u{1F514}\";\n if (tick < 8) return \"\\u{1F634}\";\n if (tick < 10) return \"\\u{1F633}\";\n return \"\\u{1F3C3}\\u{1F4A8}\";\n },\n },\n {\n // A snail crawls to the flag - and celebrates.\n id: \"snail\",\n tick: 4,\n draw: (step) => {\n const tick = step % 8;\n if (tick < 5) return track({ [tick]: \"\\u{1F40C}\", 4: \"\\u{1F3C1}\" }, 5);\n return track({ 4: \"\\u{1F389}\" }, 5);\n },\n },\n];\n\nconst COMPACT_SCENES = SCENES.filter((scene) => scene.compact);\n\nexport interface WorkingScenesProps {\n /** Limits scenes to one or two visible characters for small status fields. */\n compact?: boolean;\n /** Text for screen readers, default \"Working ...\". */\n label?: string;\n}\n\n/**\n * The default working indicator: randomly rotating mini scenes. Random order and start phase,\n * so the same scenes never feel like a loop. The working prop of ChatMessages replaces it\n * completely.\n */\nexport function WorkingScenes({ label = \"Working ...\", compact = false }: WorkingScenesProps) {\n const scenes = compact ? COMPACT_SCENES : SCENES;\n const [sceneIndex, setSceneIndex] = useState(() => Math.floor(Math.random() * scenes.length));\n const [offset, setOffset] = useState(() => Math.floor(Math.random() * 20));\n const [frameTick, setFrameTick] = useState(0);\n const [reducedMotion, setReducedMotion] = useState(() => typeof window !== \"undefined\"\n && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches);\n const scene = scenes[sceneIndex % scenes.length];\n\n useEffect(() => {\n const preference = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const update = () => setReducedMotion(preference.matches);\n preference.addEventListener(\"change\", update);\n update();\n return () => preference.removeEventListener(\"change\", update);\n }, []);\n\n useEffect(() => {\n if (reducedMotion) return;\n const timer = window.setInterval(() => {\n setSceneIndex((previous) => (previous + 1 + Math.floor(Math.random() * (scenes.length - 1))) % scenes.length);\n setOffset(Math.floor(Math.random() * 20));\n setFrameTick(0);\n }, SCENE_CHANGE_MS);\n return () => window.clearInterval(timer);\n }, [reducedMotion, scenes]);\n\n useEffect(() => {\n if (reducedMotion) return;\n const timer = window.setInterval(() => setFrameTick((value) => value + 1), BASE_TICK_MS);\n return () => window.clearInterval(timer);\n }, [reducedMotion]);\n\n const frame = scene.draw(Math.floor(frameTick / scene.tick) + (scene.moving ? offset : 0));\n return (\n <span aria-label={label} className={cn(\"qsl:flex qsl:items-center qsl:gap-2.5 qsl:text-[13px]\", compact ? \"qsl:text-inherit\" : \"qsl:mt-4 qsl:text-foreground\")} data-chat=\"working\" role=\"status\">\n {!compact && <span aria-hidden=\"true\" className=\"qsl:text-muted-foreground qsl:opacity-70\">></span>}\n <span aria-hidden=\"true\" className={cn(\"qsl:inline-block qsl:flex-none qsl:font-mono qsl:[font-variant-ligatures:none]\", compact ? \"qsl:w-[2.4em] qsl:text-center\" : \"qsl:w-[15rem]\")} key={scene.id}>\n <span className=\"qsl:tracking-[0.02em] qsl:whitespace-pre qsl:motion-reduce:opacity-60\">\n {typeof frame === \"string\"\n ? frame\n : frame.map((cell, index) => (\n <span className=\"qsl:inline-block qsl:w-[1.35em] qsl:text-center\" key={index}>\n {cell}\n </span>\n ))}\n </span>\n </span>\n </span>\n );\n}\n", "import type { ChatAttachmentInput } from \"./events\";\n\nimport { chatAttachmentMediaType, MAX_CHAT_ATTACHMENTS, MAX_CHAT_ATTACHMENT_BYTES } from \"./chat-attachments\";\nimport { defaultTexts, fillText, type ChatTexts } from \"./texts\";\n\nexport { MAX_CHAT_ATTACHMENTS, MAX_CHAT_ATTACHMENT_BYTES };\n\nexport const maxAttachmentSizeLabel = `${MAX_CHAT_ATTACHMENT_BYTES / (1024 * 1024)} MiB`;\n\nexport function attachmentMediaType(file: { name: string; type: string }): string {\n return chatAttachmentMediaType(file.name, file.type);\n}\n\nexport function attachmentCapabilityError(\n files: readonly { name: string; mediaType: string }[],\n capabilities: { input: readonly string[]; model: string },\n texts: ChatTexts = defaultTexts,\n): string | undefined {\n for (const file of files) {\n const required = file.mediaType.startsWith(\"image/\") ? \"image\"\n : file.mediaType.startsWith(\"video/\") ? \"video\" : file.mediaType === \"application/pdf\" ? \"file\" : undefined;\n if (required && !capabilities.input.includes(required)) {\n const kind = required === \"image\" ? texts.attachmentKindImage : required === \"video\" ? texts.attachmentKindVideo : texts.attachmentKindPdf;\n if (!capabilities.model) return fillText(texts.attachmentUnsupported, { name: file.name, kind });\n return fillText(texts.attachmentUnsupportedByModel, { model: capabilities.model, name: file.name, kind });\n }\n }\n}\n\nexport function validateAttachmentSelection(existing: readonly { size: number }[], incoming: readonly { size: number }[], texts: ChatTexts = defaultTexts): void {\n if (existing.length + incoming.length > MAX_CHAT_ATTACHMENTS) {\n throw new Error(fillText(texts.tooManyAttachments, { count: MAX_CHAT_ATTACHMENTS }));\n }\n if ([...existing, ...incoming].reduce((total, file) => total + file.size, 0) > MAX_CHAT_ATTACHMENT_BYTES) {\n throw new Error(fillText(texts.attachmentsTooLarge, { size: maxAttachmentSizeLabel }));\n }\n}\n\nexport async function encodeAttachment(file: File): Promise<ChatAttachmentInput> {\n const bytes = new Uint8Array(await file.arrayBuffer());\n const chunks: string[] = [];\n for (let offset = 0; offset < bytes.length; offset += 8192) {\n chunks.push(String.fromCharCode(...bytes.subarray(offset, offset + 8192)));\n }\n return { name: file.name, mediaType: attachmentMediaType(file), data: btoa(chunks.join(\"\")) };\n}\n\nexport function formatAttachmentSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;\n}\n\nexport function attachmentDownloadUrl(url: string): string {\n if (/^(data|blob):/i.test(url)) return url;\n const [resource, fragment] = url.split(/#(.*)/s);\n return `${resource}${resource.includes(\"?\") ? \"&\" : \"?\"}download=1${fragment === undefined ? \"\" : `#${fragment}`}`;\n}\n", "import type { CSSProperties, ReactNode } from \"react\";\nimport type { Message } from \"./types\";\n\nexport interface ChatAppearance {\n fontSize?: CSSProperties[\"fontSize\"];\n lineHeight?: CSSProperties[\"lineHeight\"];\n messageGap?: CSSProperties[\"marginTop\"];\n denseMessageGap?: CSSProperties[\"marginTop\"];\n}\n\nexport interface TimestampOptions {\n format?: \"time\" | \"date-time\" | \"relative\";\n locale?: string;\n timeZone?: string;\n showDaySeparators?: boolean;\n}\n\nexport interface CodeBlockOptions {\n wrap?: boolean;\n maxHeight?: CSSProperties[\"maxHeight\"];\n showCopyButton?: boolean;\n}\n\nexport interface BubbleOptions {\n variant?: \"default\" | \"plain\" | \"bubbles\";\n maxWidth?: CSSProperties[\"maxWidth\"];\n userSide?: \"start\" | \"end\";\n assistantSide?: \"start\" | \"end\";\n showSender?: boolean;\n senderLabel?: (message: Message) => string | undefined;\n}\n\nexport interface MessageAction {\n id: string;\n label: string;\n icon?: ReactNode;\n disabled?: boolean;\n onClick: (message: Message) => void | Promise<void>;\n}\n\nexport interface MessageActionsOptions {\n copy?: boolean | ((message: Message) => boolean);\n edit?: (message: Message) => void | Promise<void>;\n retry?: (message: Message) => void | Promise<void>;\n custom?: (message: Message) => readonly MessageAction[];\n}\n\nexport type SendShortcut = \"enter\" | \"mod-enter\";\n\nconst cssLength = (value: string | number | undefined) => typeof value === \"number\" ? `${value}px` : value;\n\nexport const appearanceStyle = (appearance?: ChatAppearance): CSSProperties => ({\n \"--qsl-chat-font-size\": cssLength(appearance?.fontSize),\n \"--qsl-chat-line-height\": appearance?.lineHeight,\n \"--qsl-chat-message-gap\": cssLength(appearance?.messageGap),\n \"--qsl-chat-dense-message-gap\": cssLength(appearance?.denseMessageGap),\n} as CSSProperties);\n", "import type { TimestampOptions } from \"./options\";\n\nexport function messageDate(at: string | undefined): Date | undefined {\n if (!at) return undefined;\n const date = new Date(at);\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n\nexport function timestampLabel(date: Date, options: TimestampOptions = {}, now = Date.now()): string {\n if ((!options.format || options.format === \"time\") && !options.locale && !options.timeZone) {\n return `${String(date.getHours()).padStart(2, \"0\")}:${String(date.getMinutes()).padStart(2, \"0\")}`;\n }\n if (options.format === \"relative\") {\n const seconds = (date.getTime() - now) / 1000;\n const units: readonly [Intl.RelativeTimeFormatUnit, number][] = [\n [\"year\", 365 * 86400], [\"month\", 30 * 86400], [\"day\", 86400], [\"hour\", 3600], [\"minute\", 60],\n ];\n const [unit, divisor] = units.find(([, value]) => Math.abs(seconds) >= value) ?? [\"second\", 1];\n return new Intl.RelativeTimeFormat(options.locale, { numeric: \"auto\" }).format(Math.round(seconds / divisor), unit);\n }\n return new Intl.DateTimeFormat(options.locale, {\n timeZone: options.timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hourCycle: \"h23\",\n ...(options.format === \"date-time\" ? { year: \"numeric\", month: \"2-digit\", day: \"2-digit\" } as const : {}),\n }).format(date);\n}\n\nexport function timestampDay(date: Date, options: TimestampOptions = {}): { key: string; label: string } {\n const key = new Intl.DateTimeFormat(\"en-CA\", {\n timeZone: options.timeZone, year: \"numeric\", month: \"2-digit\", day: \"2-digit\",\n }).format(date);\n const label = new Intl.DateTimeFormat(options.locale, {\n timeZone: options.timeZone, dateStyle: \"long\",\n }).format(date);\n return { key, label };\n}\n", "import { useSyncExternalStore } from \"react\";\nimport { type ChatTexts, fillText } from \"./texts\";\n\nconst tickMs = 500;\n\n/** Under a minute \"{seconds} s\" from texts, then m:ss, from an hour on h:mm:ss. */\nexport function formatElapsed(ms: number, texts: Pick<ChatTexts, \"toolElapsedSeconds\">): string {\n const total = Math.max(0, Math.floor(ms / 1000));\n if (total < 60) return fillText(texts.toolElapsedSeconds, { seconds: total });\n const hours = Math.floor(total / 3600);\n const minutes = Math.floor(total / 60) % 60;\n const seconds = String(total % 60).padStart(2, \"0\");\n return hours > 0 ? `${hours}:${String(minutes).padStart(2, \"0\")}:${seconds}` : `${minutes}:${seconds}`;\n}\n\n/** One interval for every subscriber; it runs only while someone listens. */\nexport function createTicker(intervalMs = tickMs) {\n const listeners = new Set<() => void>();\n let now = Date.now();\n let timer: ReturnType<typeof setInterval> | undefined;\n return {\n subscribe(listener: () => void): () => void {\n listeners.add(listener);\n if (timer === undefined) {\n now = Date.now();\n timer = setInterval(() => {\n now = Date.now();\n listeners.forEach((notify) => notify());\n }, intervalMs);\n }\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0 && timer !== undefined) {\n clearInterval(timer);\n timer = undefined;\n }\n };\n },\n now(): number {\n const current = Date.now();\n if (timer === undefined && (current - now >= intervalMs || current < now)) now = current;\n return now;\n },\n active: (): boolean => timer !== undefined,\n };\n}\n\nexport const elapsedTicker = createTicker();\n\nconst nothingOnServer = () => undefined;\n\n/** Milliseconds since start in whole seconds, so a row renders only when its display changes; undefined on the server. */\nexport function useElapsed(start: number): number | undefined {\n return useSyncExternalStore(elapsedTicker.subscribe, () => Math.floor((elapsedTicker.now() - start) / 1000) * 1000, nothingOnServer);\n}\n", "import { CheckIcon, CopyIcon, PencilIcon, RotateCcwIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { cn } from \"./ui/cn\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\nimport type { MessageActionsOptions, MessageAction } from \"./options\";\nimport type { ChatTexts } from \"./texts\";\nimport type { Message } from \"./types\";\nimport { copyChatText, useChatAction } from \"./useChatAction\";\n\nconst actionClasses = cn(\n \"qsl:absolute qsl:top-1 qsl:right-1 qsl:z-[1] qsl:flex qsl:flex-wrap qsl:rounded-sm qsl:bg-secondary qsl:opacity-0\",\n \"qsl:shadow-[0_2px_6px_color-mix(in_srgb,var(--qsl-foreground)_15%,transparent)]\",\n \"qsl:pointer-events-none qsl:group-hover:pointer-events-auto qsl:group-hover:opacity-100 qsl:focus-within:pointer-events-auto qsl:focus-within:opacity-100\",\n \"qsl:[@media(hover:none)]:pointer-events-auto qsl:[@media(hover:none)]:opacity-100\",\n);\n\nexport function MessageActions({ message, options, texts }: { message: Message; options?: MessageActionsOptions; texts: ChatTexts }) {\n const action = useChatAction();\n const { Button } = useQuasselComponents();\n const [lastAction, setLastAction] = useState<string>();\n const copy = typeof options?.copy === \"function\" ? options.copy(message) : options?.copy ?? message.role === \"user\";\n const actions: MessageAction[] = [\n ...(copy && message.text.trim() ? [{ id: \"copy\", label: texts.copyMessage, icon: <CopyIcon />, onClick: () => copyChatText(message.text, texts.clipboardUnavailable) }] : []),\n ...(options?.edit && message.role === \"user\" ? [{ id: \"edit\", label: texts.editMessage, icon: <PencilIcon />, onClick: options.edit }] : []),\n ...(options?.retry && message.role === \"assistant\" ? [{ id: \"retry\", label: texts.retryMessage, icon: <RotateCcwIcon />, onClick: options.retry }] : []),\n ...options?.custom?.(message) ?? [],\n ];\n return <>\n {actions.length > 0 && <div className={actionClasses}>\n {actions.map((item) => {\n const copied = item.id === \"copy\" && lastAction === item.id && action.status === \"done\";\n const label = copied ? texts.copied : item.label;\n return <Button aria-label={label} className=\"qsl:text-inherit\" disabled={item.disabled || action.status === \"pending\"}\n key={item.id} size={item.icon ? \"icon-sm\" : \"sm\"} title={label} variant=\"ghost\"\n onClick={() => {\n setLastAction(item.id);\n void action.invoke(() => item.onClick(message), texts.actionFailed);\n }}>{copied ? <CheckIcon /> : item.icon ?? item.label}</Button>;\n })}\n </div>}\n {action.error && <p className=\"qsl:mt-2 qsl:text-sm qsl:text-destructive\" role=\"alert\">{action.error}</p>}\n </>;\n}\n", "import { createContext, type RefObject } from \"react\";\n\nexport interface ChatSendScope {\n notify: () => void;\n subscribe: (listener: () => void) => () => void;\n}\n\nexport const ChatSendContext = createContext<ChatSendScope | undefined>(undefined);\n\nexport function createChatSendScope(enabled: RefObject<boolean>): ChatSendScope {\n const listeners = new Set<() => void>();\n return {\n notify: () => { if (enabled.current) listeners.forEach((listener) => listener()); },\n subscribe: (listener) => {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n },\n };\n}\n", "import { createContext } from \"react\";\n\n/** Target of open actions: undefined = in the transcript, null = the dock above the input is not mounted yet. */\nexport const ChatActionDock = createContext<HTMLElement | null | undefined>(undefined);\n", "const intervalMs = 400;\nconst maxQueued = 5;\n\nlet region: HTMLElement | undefined;\nlet queued: readonly string[] = [];\nlet running = false;\n\nfunction liveRegion(): HTMLElement {\n if (region?.isConnected) {\n return region;\n }\n const element = document.createElement(\"div\");\n element.setAttribute(\"role\", \"status\");\n element.setAttribute(\"aria-live\", \"polite\");\n element.setAttribute(\"aria-atomic\", \"true\");\n Object.assign(element.style, {\n position: \"absolute\",\n width: \"1px\",\n height: \"1px\",\n margin: \"-1px\",\n padding: \"0\",\n border: \"0\",\n overflow: \"hidden\",\n clipPath: \"inset(50%)\",\n whiteSpace: \"nowrap\",\n });\n document.body.append(element);\n region = element;\n return element;\n}\n\nfunction next(): void {\n if (queued.length === 0) {\n running = false;\n return;\n }\n if (document.visibilityState === \"hidden\") {\n document.addEventListener(\"visibilitychange\", next, { once: true });\n return;\n }\n const [text, ...rest] = queued;\n queued = rest;\n const target = liveRegion();\n target.textContent = target.textContent === text ? `${text}\\u00a0` : text;\n window.setTimeout(next, intervalMs);\n}\n\n/** Announces text through a shared, hidden live region: throttled, and paused while the tab is hidden. */\nexport function announce(text: string): void {\n const content = text.trim();\n if (!content || typeof document === \"undefined\") {\n return;\n }\n queued = [...queued, content].slice(-maxQueued);\n if (running) {\n return;\n }\n running = true;\n liveRegion();\n window.setTimeout(next, intervalMs);\n}\n", "import { useEffect, useLayoutEffect, useRef, useState, type CSSProperties, type ReactNode, type Ref } from \"react\";\nimport { cn } from \"./ui/cn\";\nimport { ChatSendContext, createChatSendScope } from \"./ChatSendContext\";\nimport { ChatActionDock } from \"./ChatActionDock\";\nimport { appearanceStyle, type ChatAppearance } from \"./options\";\n\n/**\n * Transcript with an overlaid composer. The frame measures the composer itself and gives the\n * transcript the footer space it needs, so no host has to set inner dimensions.\n */\nexport function ChatPanel({\n children,\n composer,\n className,\n nodeRef,\n maxWidth,\n horizontalPadding,\n appearance,\n scrollOnSend = false,\n}: {\n children: ReactNode;\n /** The composer; it lies over the transcript, not below it. */\n composer?: ReactNode;\n className?: string;\n nodeRef?: Ref<HTMLDivElement>;\n maxWidth?: CSSProperties[\"maxWidth\"];\n horizontalPadding?: CSSProperties[\"paddingInline\"];\n appearance?: ChatAppearance;\n scrollOnSend?: boolean;\n}) {\n const root = useRef<HTMLDivElement>(null);\n const composerRef = useRef<HTMLDivElement>(null);\n const [dock, setDock] = useState<HTMLDivElement | null>(null);\n const hasComposer = composer !== undefined;\n const scrollOnSendRef = useRef(scrollOnSend);\n const [sendScope] = useState(() => createChatSendScope(scrollOnSendRef));\n useLayoutEffect(() => { scrollOnSendRef.current = scrollOnSend; }, [scrollOnSend]);\n\n useEffect(() => {\n const element = composerRef.current;\n const frame = root.current;\n if (!element || !frame) {\n return;\n }\n const measure = () => {\n frame.style.setProperty(\"--qsl-composer-height\", `${element.offsetHeight}px`);\n frame.style.setProperty(\"--qsl-panel-height\", `${frame.offsetHeight}px`);\n };\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n observer.observe(frame);\n measure();\n return () => {\n observer.disconnect();\n frame.style.removeProperty(\"--qsl-composer-height\");\n frame.style.removeProperty(\"--qsl-panel-height\");\n };\n }, [hasComposer]);\n\n return (\n <ChatSendContext.Provider value={sendScope}>\n <ChatActionDock.Provider value={hasComposer ? dock : undefined}>\n <div\n className={cn(\"qsl:relative qsl:flex qsl:min-h-0 qsl:min-w-0 qsl:flex-col qsl:overflow-hidden\", className)}\n data-chat=\"panel\"\n data-quassel=\"\"\n style={{\n ...appearanceStyle(appearance),\n \"--qsl-chat-content-max-width\": typeof maxWidth === \"number\" ? `${maxWidth}px` : maxWidth,\n \"--qsl-chat-horizontal-padding\": typeof horizontalPadding === \"number\" ? `${horizontalPadding}px` : horizontalPadding,\n } as CSSProperties}\n ref={(element) => {\n root.current = element;\n if (typeof nodeRef === \"function\") {\n nodeRef(element);\n } else if (nodeRef) {\n nodeRef.current = element;\n }\n }}\n >\n {children}\n {hasComposer && (\n <div className=\"qsl:absolute qsl:inset-x-0 qsl:bottom-0 qsl:z-[5] qsl:px-[var(--qsl-chat-horizontal-padding,24px)] qsl:pb-3.5 qsl:*:mx-auto qsl:*:max-w-[var(--qsl-chat-content-max-width,none)]\" data-chat=\"composer\" ref={composerRef}>\n <div>\n <div\n className=\"qsl:-mx-[16px] qsl:max-h-[calc(var(--qsl-panel-height,100dvh)_/_2)] qsl:overflow-y-auto qsl:px-[16px] qsl:pb-[var(--qsl-chat-message-gap,16px)] qsl:[-webkit-mask-image:linear-gradient(to_bottom,#000_calc(100%_-_var(--qsl-chat-message-gap,16px)),transparent)] qsl:[mask-image:linear-gradient(to_bottom,#000_calc(100%_-_var(--qsl-chat-message-gap,16px)),transparent)] qsl:empty:hidden\"\n data-chat=\"actions\"\n ref={setDock}\n />\n </div>\n {composer}\n </div>\n )}\n </div>\n </ChatActionDock.Provider>\n </ChatSendContext.Provider>\n );\n}\n", "import { PaperclipIcon, SendIcon, XIcon } from \"lucide-react\";\nimport { cn } from \"./ui/cn\";\nimport { useFileInput } from \"./ui/useFileInput\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\nimport { KeyboardEvent, ReactNode, Ref, useCallback, useContext, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { ChatTexts, defaultTexts, fillText } from \"./texts\";\nimport type { ChatAttachmentInput } from \"./events\";\nimport { attachmentCapabilityError, attachmentMediaType, encodeAttachment, formatAttachmentSize, MAX_CHAT_ATTACHMENTS, maxAttachmentSizeLabel, validateAttachmentSelection } from \"./attachments\";\nimport { ChatSendContext } from \"./ChatSendContext\";\nimport type { SendShortcut } from \"./options\";\n\ntype DraftAttachment = { id: number; file: File } & (\n | { status: \"reading\" }\n | { status: \"ready\"; input: ChatAttachmentInput }\n | { status: \"error\"; error: string }\n);\n\n// Below this panel width, accompanying labels collapse to their icons.\nconst COMPACT_WIDTH_PX = 480;\n\nconst errorClasses = \"qsl:px-3 qsl:py-2 qsl:text-sm qsl:text-destructive\";\nconst attachmentItemClasses = \"qsl:relative qsl:flex qsl:w-[190px] qsl:max-w-full qsl:min-w-0 qsl:flex-col qsl:overflow-hidden qsl:rounded-lg qsl:border qsl:border-border qsl:text-sm\";\nconst attachmentMediaClasses = \"qsl:block qsl:h-[112px] qsl:w-full qsl:bg-secondary qsl:object-contain\";\n\n/** A toolbar button, declarative: icon, text or both - plus click handler. */\nexport interface ToolbarAction {\n icon?: ReactNode;\n label?: string;\n title?: string;\n disabled?: boolean;\n active?: boolean;\n onClick: () => void;\n}\n\n/** Hosts control the draft from outside, e.g. to insert a template for editing. */\nexport interface ChatInputHandle {\n /** Replaces the draft, focuses the input and puts the caret at the end. */\n insert: (text: string) => void;\n focus: () => void;\n reset: () => void;\n submit: (onSubmit?: (text: string, attachments?: ChatAttachmentInput[]) => void | Promise<void>, options?: { allowEmpty?: boolean }) => Promise<void>;\n}\n\n/**\n * The input card: borderless textarea on top, toolbar below a hairline. Custom buttons come\n * declaratively through `actions` or freely through the left/right slots; while work is running\n * the stop button stays visible, and typing shows the send button next to it, which then\n * interjects. `rows` sets the initial height; with `maxRows` the textarea grows with its content\n * up to that number of rows and scrolls after that.\n */\nexport function ChatInputToolbar({\n onSend,\n onStop,\n running = false,\n disabled = false,\n sendDisabled = false,\n layout = \"card\",\n detailsContainer,\n onErrorChange,\n inputAriaControls,\n rows = 3,\n maxRows,\n actions,\n toolbarLeft,\n toolbarRight,\n texts,\n handleRef,\n attachments: attachmentsEnabled = true,\n attachmentCapabilities,\n attachmentCapabilitiesError,\n onAttachmentsChange,\n initialValue = \"\",\n onDraftChange,\n sendShortcut = \"enter\",\n autoFocus = false,\n onAutoFocusSettled,\n}: {\n onSend: (text: string, attachments?: ChatAttachmentInput[]) => void | Promise<void>;\n onStop?: () => void;\n running?: boolean;\n disabled?: boolean;\n sendDisabled?: boolean;\n layout?: \"card\" | \"toolbar\" | \"inline\";\n detailsContainer?: HTMLElement | null;\n onErrorChange?: (error: string | undefined) => void;\n inputAriaControls?: string;\n rows?: number;\n maxRows?: number;\n actions?: ToolbarAction[];\n toolbarLeft?: ReactNode;\n toolbarRight?: ReactNode;\n texts?: Partial<ChatTexts>;\n handleRef?: Ref<ChatInputHandle>;\n /** false = no attaching: neither button nor dropping or pasting files. */\n attachments?: boolean;\n attachmentCapabilities?: { input: readonly string[]; model: string };\n attachmentCapabilitiesError?: string;\n onAttachmentsChange?: (hasAttachments: boolean) => void;\n initialValue?: string;\n onDraftChange?: (text: string) => void;\n sendShortcut?: SendShortcut;\n autoFocus?: boolean;\n onAutoFocusSettled?: () => void;\n}) {\n const sendScope = useContext(ChatSendContext);\n const allTexts = { ...defaultTexts, ...texts };\n const { Button, StopButton, Toggle } = useQuasselComponents();\n const [draft, setDraft] = useState(initialValue);\n const [sending, setSending] = useState(false);\n const [sendError, setSendError] = useState<string>();\n const [failedSubmissions, setFailedSubmissions] = useState<{ id: number; draft: string; attachments: DraftAttachment[] }[]>([]);\n const nextFailedId = useRef(0);\n const pendingSend = useRef(false);\n const generation = useRef(0);\n useLayoutEffect(() => () => { generation.current += 1; }, []);\n const draftRevision = useRef(0);\n const [attachments, setAttachments] = useState<DraftAttachment[]>([]);\n const attachmentsRef = useRef<DraftAttachment[]>([]);\n const nextAttachmentId = useRef(0);\n const [attachmentError, setAttachmentError] = useState<string>();\n const updateAttachments = (update: (current: DraftAttachment[]) => DraftAttachment[]) => {\n attachmentsRef.current = update(attachmentsRef.current);\n setAttachments(attachmentsRef.current);\n };\n const addFiles = (files: File[]) => {\n if (!files.length) return;\n if (disabled || pendingSend.current) {\n setAttachmentError(allTexts.attachmentsWhileBusy);\n return;\n }\n try {\n validateAttachmentSelection(attachmentsRef.current.map((entry) => entry.file), files, allTexts);\n } catch (error) {\n setAttachmentError(error instanceof Error ? error.message : String(error));\n return;\n }\n setAttachmentError(undefined);\n const entries: DraftAttachment[] = files.map((file) => ({ id: ++nextAttachmentId.current, file, status: \"reading\" }));\n updateAttachments((current) => [...current, ...entries]);\n for (const entry of entries) {\n void encodeAttachment(entry.file).then(\n (input) => updateAttachments((current) => current.map((item) => item.id === entry.id ? { ...entry, status: \"ready\", input } : item)),\n () => updateAttachments((current) => current.map((item) => item.id === entry.id ? {\n ...entry, status: \"error\", error: allTexts.attachmentReadFailed,\n } : item)),\n );\n }\n };\n const rootRef = useRef<HTMLDivElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const autoFocusSettled = useRef(false);\n useEffect(() => {\n if (!autoFocus || autoFocusSettled.current) return;\n const input = textareaRef.current;\n if (!input) return;\n let frame = 0;\n const settle = () => {\n if (autoFocusSettled.current) return;\n autoFocusSettled.current = true;\n window.cancelAnimationFrame(frame);\n onAutoFocusSettled?.();\n };\n const onFocus = (event: FocusEvent) => { if (event.target !== input) settle(); };\n const focusWhenVisible = () => {\n if (autoFocusSettled.current) return;\n const dialog = [...document.querySelectorAll<HTMLElement>('[role=\"dialog\"], dialog[open]')]\n .find((element) => element.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true }) && !element.contains(input));\n if (dialog) {\n settle();\n return;\n }\n const rect = input.getBoundingClientRect();\n const visible = input.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true }) && rect.width > 0 && rect.height > 0 && !input.closest('[inert], [hidden], [aria-hidden=\"true\"]')\n && document.elementFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2) === input;\n if (visible && !input.disabled && !input.readOnly && document.visibilityState === \"visible\") {\n input.focus({ preventScroll: true });\n if (document.activeElement === input) {\n settle();\n return;\n }\n }\n frame = window.requestAnimationFrame(focusWhenVisible);\n };\n window.addEventListener(\"pointerdown\", settle, true);\n window.addEventListener(\"keydown\", settle, true);\n window.addEventListener(\"focusin\", onFocus);\n window.addEventListener(\"blur\", settle);\n if (!disabled) frame = window.requestAnimationFrame(focusWhenVisible);\n return () => {\n window.cancelAnimationFrame(frame);\n window.removeEventListener(\"pointerdown\", settle, true);\n window.removeEventListener(\"keydown\", settle, true);\n window.removeEventListener(\"focusin\", onFocus);\n window.removeEventListener(\"blur\", settle);\n };\n }, [autoFocus, disabled, onAutoFocusSettled]);\n const [compact, setCompact] = useState(false);\n const pendingFocus = useRef(false);\n const fileInput = useFileInput({\n disabled: disabled || sending,\n onFiles: addFiles,\n onPasteText: (text) => {\n const input = textareaRef.current;\n if (!input || disabled || pendingSend.current) return;\n const start = input.selectionStart;\n const end = input.selectionEnd;\n draftRevision.current += 1;\n setDraft((current) => current.slice(0, start) + text + current.slice(end));\n pendingFocus.current = true;\n },\n });\n const toolbar = layout === \"toolbar\";\n const inline = layout === \"inline\";\n const inputRows = inline || toolbar ? 1 : rows;\n const inputMaxRows = inline || toolbar ? 1 : maxRows;\n // The toolbar variant pulses while working; the host only sets the radius.\n const rootClasses = cn(\n \"qsl:flex qsl:shrink-0 qsl:flex-col qsl:overflow-hidden qsl:rounded-[var(--qsl-input-card-radius,--theme(--radius-xl))] qsl:border qsl:border-border-strong qsl:bg-background qsl:shadow-bar qsl:transition-colors qsl:focus-within:border-primary\",\n \"qsl:in-data-[tone=material]:rounded-xl qsl:in-data-[tone=material]:border-glass-edge/50 qsl:in-data-[tone=material]:bg-background\",\n toolbar && \"qsl:h-full qsl:min-w-0 qsl:flex-row qsl:items-center qsl:rounded-lg qsl:data-[working=true]:animate-working-pulse qsl:data-[working=true]:border-primary qsl:motion-reduce:data-[working=true]:animate-none\",\n fileInput.dragging && \"qsl:outline-2 qsl:outline-offset-[3px] qsl:outline-dashed qsl:outline-primary\",\n );\n const textareaClasses = cn(\n \"qsl:resize-none qsl:border-0 qsl:bg-transparent qsl:text-[length:var(--qsl-chat-font-size,13px)] qsl:leading-[var(--qsl-chat-line-height,1.5)] qsl:text-foreground qsl:placeholder:text-muted-foreground qsl:focus:outline-none\",\n inline ? \"qsl:min-w-0 qsl:flex-1 qsl:px-2.5 qsl:py-2\" : toolbar ? \"qsl:w-full qsl:min-w-0 qsl:flex-auto qsl:px-2 qsl:py-[3px] qsl:leading-[1.3]\" : \"qsl:px-3 qsl:pt-3 qsl:pb-2\",\n );\n const toolbarRowClasses = cn(\n \"qsl:flex qsl:items-center qsl:gap-2 qsl:border-t qsl:border-border-soft qsl:px-2 qsl:py-1.5 qsl:in-data-[tone=overseer-details]:flex-nowrap\",\n inline && \"qsl:flex-none qsl:gap-1 qsl:border-t-0 qsl:p-1\",\n toolbar && \"qsl:flex-wrap qsl:border-t-0\",\n );\n const toolbarSideClasses = \"qsl:flex qsl:min-w-0 qsl:items-center qsl:gap-2 qsl:in-data-[tone=overseer-details]:flex-nowrap\";\n const changeDraft = useCallback((text: string) => {\n draftRevision.current += 1;\n setDraft(text);\n }, []);\n\n useImperativeHandle(handleRef, () => ({\n insert: (text: string) => {\n pendingFocus.current = true;\n changeDraft(text);\n const element = textareaRef.current;\n element?.focus();\n if (element?.value === text) element.setSelectionRange(text.length, text.length);\n },\n focus: () => textareaRef.current?.focus(),\n submit: (onSubmit, options) => send(onSubmit, options?.allowEmpty),\n reset: () => {\n generation.current += 1;\n pendingSend.current = false;\n pendingFocus.current = false;\n changeDraft(\"\");\n updateAttachments(() => []);\n setSendError(undefined);\n setFailedSubmissions([]);\n setAttachmentError(undefined);\n setSending(false);\n fileInput.clearDragging();\n },\n }));\n\n useEffect(() => { onDraftChange?.(draft); }, [draft, onDraftChange]);\n\n useEffect(() => {\n if (!pendingFocus.current) {\n return;\n }\n pendingFocus.current = false;\n const element = textareaRef.current;\n if (element) {\n element.focus();\n element.setSelectionRange(element.value.length, element.value.length);\n }\n }, [draft, sending]);\n\n // Auto-grow: the height follows the content between rows and maxRows, then the textarea scrolls.\n const applyAutoGrow = useCallback(() => {\n const element = textareaRef.current;\n if (!element || inputMaxRows === undefined) {\n return;\n }\n const style = getComputedStyle(element);\n const lineHeight = Number.parseFloat(style.lineHeight) || Number.parseFloat(style.fontSize) * 1.4;\n const padding = Number.parseFloat(style.paddingTop) + Number.parseFloat(style.paddingBottom);\n const maximum = lineHeight * Math.max(inputMaxRows, inputRows) + padding;\n element.style.height = \"auto\";\n const contentHeight = element.scrollHeight;\n element.style.height = `${Math.min(contentHeight, maximum)}px`;\n element.style.overflowY = contentHeight > maximum ? \"auto\" : \"hidden\";\n }, [inputMaxRows, inputRows]);\n\n useEffect(() => {\n applyAutoGrow();\n }, [draft, applyAutoGrow]);\n\n // Hosts may lay the composer out a frame later; re-measure once the width settles.\n useEffect(() => {\n const element = textareaRef.current;\n if (!element || inputMaxRows === undefined) {\n return;\n }\n let lastWidth = element.clientWidth;\n const observer = new ResizeObserver(() => {\n if (element.clientWidth !== lastWidth) {\n lastWidth = element.clientWidth;\n applyAutoGrow();\n }\n });\n observer.observe(element);\n return () => observer.disconnect();\n }, [inputMaxRows, applyAutoGrow]);\n\n // Panel width instead of viewport width: the chat column can be arbitrarily narrow in the host.\n useEffect(() => {\n const element = rootRef.current;\n if (!element) {\n return;\n }\n const update = () => setCompact(element.clientWidth < COMPACT_WIDTH_PX);\n update();\n const observer = new ResizeObserver(update);\n observer.observe(element);\n return () => observer.disconnect();\n }, []);\n\n const hasAttachments = attachments.length > 0;\n useEffect(() => { onAttachmentsChange?.(hasAttachments); }, [hasAttachments, onAttachmentsChange]);\n const capabilityError = hasAttachments && attachmentCapabilitiesError ? attachmentCapabilitiesError : attachmentCapabilities ? attachmentCapabilityError(attachments.map((entry) => ({\n name: entry.file.name, mediaType: attachmentMediaType(entry.file),\n })), attachmentCapabilities, allTexts) : undefined;\n const hasContent = draft.trim().length > 0 || attachments.length > 0;\n const preparing = attachments.some((entry) => entry.status === \"reading\");\n const attachmentBlocked = attachments.some((entry) => entry.status !== \"ready\");\n const currentError = sendError ?? attachmentError ?? capabilityError ?? attachments.find((entry) => entry.status === \"error\")?.error;\n useEffect(() => { onErrorChange?.(currentError); }, [currentError, onErrorChange]);\n\n const send = async (onSubmit = onSend, allowEmpty = false) => {\n const text = draft.trim();\n const snapshot = attachmentsRef.current;\n if ((!allowEmpty && !text && !snapshot.length) || disabled || sendDisabled || pendingSend.current || capabilityError || snapshot.some((entry) => entry.status !== \"ready\")) {\n return;\n }\n pendingSend.current = true;\n const sentGeneration = generation.current;\n const sentRevision = draftRevision.current;\n const sentDraft = draft;\n const focusOrigin = document.activeElement;\n const startedFocused = focusOrigin === textareaRef.current || rootRef.current?.contains(focusOrigin);\n let leftComposer = false;\n const observeFocus = (event: Event) => {\n const target = event.target;\n if (target instanceof Node && !rootRef.current?.contains(target) && !detailsContainer?.contains(target)) leftComposer = true;\n };\n document.addEventListener(\"focusin\", observeFocus);\n document.addEventListener(\"pointerdown\", observeFocus);\n setSending(true);\n setSendError(undefined);\n setDraft(\"\");\n updateAttachments(() => []);\n try {\n const inputs = snapshot.flatMap((entry) => entry.status === \"ready\" ? [entry.input] : []);\n await onSubmit(text, inputs.length ? inputs : undefined);\n if (generation.current === sentGeneration && (text || inputs.length)) sendScope?.notify();\n } catch (error) {\n if (generation.current !== sentGeneration) return;\n if (draftRevision.current === sentRevision) {\n setDraft(sentDraft);\n updateAttachments((current) => [...snapshot, ...current]);\n } else if (sentDraft || snapshot.length) {\n const failed = { id: ++nextFailedId.current, draft: sentDraft, attachments: snapshot };\n setFailedSubmissions((current) => [...current, failed]);\n }\n setSendError(error instanceof Error ? error.message : String(error));\n } finally {\n document.removeEventListener(\"focusin\", observeFocus);\n document.removeEventListener(\"pointerdown\", observeFocus);\n if (generation.current === sentGeneration) {\n pendingSend.current = false;\n pendingFocus.current = !!startedFocused && !leftComposer && document.hasFocus()\n && (!toolbar || focusOrigin !== textareaRef.current) && (document.activeElement === focusOrigin\n || (!toolbar && document.activeElement === document.body));\n setSending(false);\n }\n }\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === \"Enter\" && !event.shiftKey && !event.nativeEvent.isComposing && event.nativeEvent.keyCode !== 229\n && (sendShortcut === \"enter\" || event.metaKey || event.ctrlKey)) {\n event.preventDefault();\n if (!event.repeat) void send();\n }\n };\n\n const attachmentPreviews = (\n attachments.length > 0 && (\n <ul className=\"qsl:flex qsl:max-h-[240px] qsl:flex-wrap qsl:gap-2 qsl:overflow-y-auto qsl:px-3 qsl:pt-2.5 qsl:in-data-[tone=overseer-details]:max-h-40 qsl:in-data-[tone=overseer-details]:overflow-y-auto\" aria-label={allTexts.attachments}>\n {attachments.map((entry) => (\n <li className={attachmentItemClasses} key={entry.id}>\n {entry.status === \"ready\" && entry.input.mediaType.startsWith(\"image/\") && (\n <img className={attachmentMediaClasses} src={`data:${entry.input.mediaType};base64,${entry.input.data}`} alt={entry.file.name} />\n )}\n {entry.status === \"ready\" && entry.input.mediaType.startsWith(\"video/\") && (\n <video className={attachmentMediaClasses} controls preload=\"metadata\" aria-label={entry.file.name} src={`data:${entry.input.mediaType};base64,${entry.input.data}`} />\n )}\n <div className=\"qsl:flex qsl:flex-col qsl:gap-1 qsl:p-2 qsl:pr-8 qsl:[overflow-wrap:anywhere]\">\n <span className=\"qsl:font-medium\" title={entry.file.name}>{entry.file.name}</span>\n <small>{formatAttachmentSize(entry.file.size)}</small>\n {entry.status === \"reading\" && <small role=\"status\">{allTexts.attachmentPreparing}</small>}\n {entry.status === \"error\" && <small role=\"alert\">{entry.error}</small>}\n </div>\n <Button\n aria-label={fillText(allTexts.removeAttachment, { name: entry.file.name })}\n className=\"qsl:absolute qsl:top-1 qsl:right-1\"\n disabled={disabled || sending}\n onClick={() => {\n updateAttachments((current) => current.filter((item) => item.id !== entry.id));\n setAttachmentError(undefined);\n textareaRef.current?.focus();\n }}\n size=\"icon-sm\"\n title={fillText(allTexts.removeAttachment, { name: entry.file.name })}\n variant=\"outline\"\n ><XIcon /></Button>\n </li>\n ))}\n </ul>\n )\n );\n const errors = <>\n {capabilityError && <p className={errorClasses} role=\"alert\">{capabilityError}</p>}\n {attachmentError && <p className={errorClasses} role=\"alert\">{attachmentError}</p>}\n {sendError && <p className={errorClasses} role=\"alert\">{sendError}</p>}\n {failedSubmissions.map((failed) => <div className={cn(errorClasses, \"qsl:flex qsl:flex-wrap qsl:items-center qsl:gap-2\")} key={failed.id} role=\"status\">\n <span>{allTexts.notSent} {failed.draft.slice(0, 100)}{failed.draft.length > 100 ? \" ...\" : \"\"}{failed.attachments.length > 0 ? ` ${fillText(allTexts.notSentAttachments, { count: failed.attachments.length })}` : \"\"} </span>\n <Button disabled={disabled || sending} size=\"sm\" variant=\"outline\" onClick={() => {\n try {\n validateAttachmentSelection(attachmentsRef.current.map((entry) => entry.file), failed.attachments.map((entry) => entry.file), allTexts);\n } catch (error) {\n setAttachmentError(error instanceof Error ? error.message : String(error));\n return;\n }\n draftRevision.current += 1;\n setDraft((current) => [current, failed.draft].filter(Boolean).join(\"\\n\\n\"));\n updateAttachments((current) => [...current, ...failed.attachments]);\n setFailedSubmissions((current) => current.filter((entry) => entry.id !== failed.id));\n setAttachmentError(undefined);\n pendingFocus.current = true;\n }}>{allTexts.insertUnsent}</Button>\n </div>)}\n </>;\n const sendButtons = <>\n {running && onStop && !hasContent && <StopButton className=\"qsl:flex-none\" label={allTexts.stop} onClick={onStop} size=\"icon-sm\" />}\n {(!running || !onStop || hasContent) && (\n <Button\n aria-label={allTexts.send}\n className=\"qsl:flex-none\"\n disabled={disabled || sendDisabled || sending || attachmentBlocked || !!capabilityError || !hasContent}\n onClick={() => { void send(); }}\n size=\"icon-sm\"\n title={running ? allTexts.sendIntoRun : allTexts.send}\n >\n <SendIcon size={14} />\n </Button>\n )}\n </>;\n const detailToolbar = (\n <div className={toolbarRowClasses} data-input=\"controls\">\n <div className={cn(toolbarSideClasses, \"qsl:in-data-[tone=overseer-details]:flex-none\", inline || toolbar ? \"qsl:flex-none\" : \"qsl:flex-auto\")}>\n {attachmentsEnabled && <Button\n aria-label={allTexts.attachFiles}\n disabled={disabled || sending}\n onClick={() => fileInput.inputRef.current?.click()}\n size=\"icon-sm\"\n title={fillText(allTexts.attachFilesHint, { count: MAX_CHAT_ATTACHMENTS, size: maxAttachmentSizeLabel })}\n variant=\"ghost\"\n >\n <PaperclipIcon />\n </Button>}\n {preparing && <span className={cn(\"qsl:text-xs qsl:text-muted-foreground\", inline && \"qsl:sr-only\")} role=\"status\">{allTexts.attachmentsPreparing}</span>}\n {actions?.map((action, index) => action.active === undefined ? (\n <Button disabled={action.disabled} key={index} onClick={action.onClick} size=\"sm\" title={action.title ?? action.label} variant=\"ghost\">\n {action.icon}\n {action.label && <span className={action.icon ? \"qsl:in-data-[compact=true]:hidden\" : undefined}>{action.label}</span>}\n </Button>\n ) : (\n <Toggle disabled={action.disabled} key={index} onPressedChange={() => action.onClick()} pressed={action.active} size=\"sm\" title={action.title ?? action.label}>\n {action.icon}\n {action.label && <span className={action.icon ? \"qsl:in-data-[compact=true]:hidden\" : undefined}>{action.label}</span>}\n </Toggle>\n ))}\n {toolbarLeft}\n </div>\n <div className={cn(toolbarSideClasses, \"qsl:in-data-[tone=overseer-details]:flex-1\", inline || toolbar ? \"qsl:flex-none\" : \"qsl:flex-[0_1_auto]\")}>\n {toolbarRight}\n {!toolbar && sendButtons}\n </div>\n </div>\n );\n const details = <div className=\"qsl:min-w-0\" data-compact={compact} data-quassel=\"\">\n {attachmentPreviews}\n {errors}\n {detailToolbar}\n </div>;\n\n const input = (\n <textarea\n aria-controls={inputAriaControls}\n className={textareaClasses}\n aria-label={allTexts.placeholder}\n disabled={!toolbar && disabled}\n readOnly={toolbar && disabled}\n onChange={(event) => changeDraft(event.target.value)}\n onKeyDown={onKeyDown}\n placeholder={running ? allTexts.steeringPlaceholder : allTexts.placeholder}\n ref={textareaRef}\n rows={inputRows}\n value={draft}\n />\n );\n\n return (\n <div\n className={rootClasses}\n data-compact={compact}\n data-layout={layout}\n data-quassel=\"\"\n data-working={running || sending}\n ref={rootRef}\n {...(attachmentsEnabled ? fileInput.dropProps : {})}\n >\n {attachmentsEnabled && <input\n aria-label={allTexts.attachFiles}\n hidden\n multiple\n type=\"file\"\n {...fileInput.inputProps}\n />}\n {!toolbar && attachmentPreviews}\n {inline ? <>{errors}<div className=\"qsl:flex qsl:min-w-0 qsl:items-center\">{input}{detailToolbar}</div></> : input}\n {toolbar ? <>\n <div className=\"qsl:flex qsl:flex-none qsl:items-center qsl:gap-1 qsl:p-1\">{sendButtons}</div>\n {detailsContainer && createPortal(details, detailsContainer)}\n </> : !inline && <>{errors}{detailToolbar}</>}\n\n </div>\n );\n}\n", "import { useRef, useState, type ChangeEvent, type ClipboardEvent, type DragEvent } from \"react\";\n\nexport function useFileInput({ disabled, onFiles, onPasteText }: {\n disabled?: boolean;\n onFiles: (files: File[]) => void | Promise<void>;\n onPasteText?: (text: string) => void;\n}) {\n const inputRef = useRef<HTMLInputElement>(null);\n const [dragging, setDragging] = useState(false);\n const receive = (files: File[]) => { if (files.length) void onFiles(files); };\n\n return {\n inputRef,\n dragging,\n clearDragging: () => setDragging(false),\n inputProps: {\n ref: inputRef,\n onChange: (event: ChangeEvent<HTMLInputElement>) => {\n const files = Array.from(event.currentTarget.files ?? []);\n event.currentTarget.value = \"\";\n receive(files);\n },\n },\n dropProps: {\n onDragOver: (event: DragEvent<HTMLElement>) => {\n if (!event.dataTransfer.types.includes(\"Files\")) return;\n event.preventDefault();\n event.dataTransfer.dropEffect = disabled ? \"none\" : \"copy\";\n setDragging(!disabled);\n },\n onDragLeave: (event: DragEvent<HTMLElement>) => {\n if (!event.currentTarget.contains(event.relatedTarget as Node | null)) setDragging(false);\n },\n onDrop: (event: DragEvent<HTMLElement>) => {\n if (!event.dataTransfer.types.includes(\"Files\")) return;\n event.preventDefault();\n setDragging(false);\n receive(Array.from(event.dataTransfer.files));\n },\n onPaste: (event: ClipboardEvent<HTMLElement>) => {\n const files = Array.from(event.clipboardData.files);\n if (!files.length) return;\n event.preventDefault();\n receive(files);\n const text = event.clipboardData.getData(\"text/plain\");\n if (text) onPasteText?.(text);\n },\n },\n };\n}\n", "import { CircleDotIcon, EyeOffIcon, ListCollapseIcon, ListIcon, type LucideIcon, ShapesIcon, TagsIcon, TextAlignJustifyIcon } from \"lucide-react\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\nimport { DetailMode } from \"./types\";\nimport { ChatTexts, defaultTexts } from \"./texts\";\n\nexport const DETAIL_MODES: readonly DetailMode[] = [\"off\", \"current\", \"icons\", \"chips\", \"grouped\", \"compact\", \"full\"];\n\nconst TEXT_KEYS: Record<DetailMode, keyof ChatTexts> = {\n off: \"detailModeOff\",\n current: \"detailModeCurrent\",\n icons: \"detailModeIcons\",\n chips: \"detailModeChips\",\n grouped: \"detailModeGrouped\",\n compact: \"detailModeCompact\",\n full: \"detailModeFull\",\n};\n\nconst ICONS: Record<DetailMode, LucideIcon> = {\n off: EyeOffIcon,\n current: CircleDotIcon,\n icons: ShapesIcon,\n chips: TagsIcon,\n grouped: ListCollapseIcon,\n compact: ListIcon,\n full: TextAlignJustifyIcon,\n};\n\nexport const detailModeLabel = (mode: DetailMode, texts?: Partial<ChatTexts>): string =>\n ({ ...defaultTexts, ...texts })[TEXT_KEYS[mode]];\n\n/**\n * An icon button that cycles the detail level of the thinking and tool steps. The order comes\n * from `modes`, the current value shows in the icon and in the tooltip.\n */\nexport function DetailModeSwitch({\n mode,\n onChange,\n modes = DETAIL_MODES,\n texts,\n className,\n}: {\n mode: DetailMode;\n onChange: (mode: DetailMode) => void;\n /** Selection and order of cycling; the default is all modes. */\n modes?: readonly DetailMode[];\n texts?: Partial<ChatTexts>;\n className?: string;\n}) {\n const allTexts = { ...defaultTexts, ...texts };\n const { Button } = useQuasselComponents();\n const current = modes.indexOf(mode);\n const next = modes[(current < 0 ? 0 : current + 1) % modes.length];\n const Icon = ICONS[mode];\n const title = `${allTexts.detailModeTitle}: ${detailModeLabel(mode, texts)}`;\n return (\n <Button aria-label={title} className={className} onClick={() => onChange(next)} size=\"icon-sm\" title={title} variant=\"ghost\">\n <Icon />\n </Button>\n );\n}\n", "import { ClockFadingIcon, ClockIcon } from \"lucide-react\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\nimport { type ChatTexts, defaultTexts } from \"./texts\";\n\nexport function TimestampSwitch({ showTimestamps, onChange, texts, className }: {\n showTimestamps: boolean;\n onChange: (showTimestamps: boolean) => void;\n texts?: Partial<ChatTexts>;\n className?: string;\n}) {\n const labels = { ...defaultTexts, ...texts };\n const { Button } = useQuasselComponents();\n const title = showTimestamps ? labels.hideTimestamps : labels.showTimestamps;\n return (\n <Button aria-label={title} aria-pressed={showTimestamps} className={className}\n onClick={() => onChange(!showTimestamps)} size=\"icon-sm\" title={title} variant=\"ghost\">\n {showTimestamps ? <ClockIcon /> : <ClockFadingIcon />}\n </Button>\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["useCallback", "useContext", "useEffect", "useMemo", "useRef", "useState", "createContext", "useContext", "useRef", "jsx", "jsx", "jsx", "jsx", "cva", "jsx", "cva", "jsx", "components", "jsx", "createContext", "useContext", "Button", "useRef", "useMemo", "jsx", "jsxs", "useMemo", "Button", "Popover", "PopoverContent", "CheckIcon", "XIcon", "jsx", "jsxs", "Button", "Card", "CheckIcon", "XIcon", "useEffect", "useState", "jsx", "jsxs", "useState", "useEffect", "CheckIcon", "SparklesIcon", "WrenchIcon", "intervalMs", "CheckIcon", "CopyIcon", "useState", "jsx", "jsxs", "Button", "useState", "CopyIcon", "CheckIcon", "createContext", "createContext", "Fragment", "jsx", "jsxs", "running", "announce", "Button", "useRef", "useState", "useContext", "useEffect", "useCallback", "useMemo", "next", "SparklesIcon", "WrenchIcon", "CheckIcon", "useEffect", "useLayoutEffect", "useRef", "useState", "jsx", "jsxs", "useRef", "useState", "useLayoutEffect", "useEffect", "XIcon", "useRef", "useState", "useCallback", "useContext", "useEffect", "useLayoutEffect", "useRef", "useState", "createPortal", "Fragment", "jsx", "jsxs", "running", "useContext", "Button", "StopButton", "Toggle", "useState", "useRef", "useLayoutEffect", "input", "useEffect", "useCallback", "XIcon", "createPortal", "jsx", "Button", "next", "jsx", "Button"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quassel",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Chat building blocks for React: streaming transcript with thinking and tool steps, input card, themable Tailwind styles and an event contract",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ronald Schlenker",
|