quassel 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChatActionDock.d.ts +2 -0
- package/ChatMessages.d.ts +3 -1
- package/README.md +6 -2
- package/chat.css +24 -0
- package/elapsed.d.ts +16 -0
- package/index.d.ts +1 -0
- package/index.js +145 -32
- package/index.js.map +4 -4
- package/package.json +1 -1
- package/texts.d.ts +1 -0
package/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 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/MessageActions.tsx", "../src/ChatSendContext.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 = nur der laufende Schritt, off = nur Antworten, icons = Schritte als reine Symbole nebeneinander,\n * chips = Schritte als Symbol + Kurztext nebeneinander (mit Umbruch),\n * grouped = aufeinanderfolgende Schritte als eine aufklappbare Zeile, dahinter einzeilig,\n * compact = Denken und Werkzeuge einzeilig, full = alles ausgeklappt.\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 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 timestamps: 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: \"Arbeitet ...\",\n toolRunning: \"l\u00E4uft ...\",\n toolStillRunning: \"Werkzeug l\u00E4uft ...\",\n currentTool: \"Werkzeug l\u00E4uft\",\n thinkingChip: \"Denken\",\n toolChip: \"Werkzeug\",\n stepGroupOne: \"1 Schritt\",\n stepGroupMany: \"{count} Schritte\",\n stepGroupCollapse: \"Einklappen\",\n thinkingTitle: \"Thinking-Trace\",\n toolTitle: \"Tool-Call\",\n argumentsLabel: \"Argumente\",\n resultLabel: \"Ergebnis\",\n close: \"Schlie\u00DFen\",\n jumpToEnd: \"Zum Ende springen\",\n send: \"Senden\",\n sendIntoRun: \"In den laufenden Turn einspeisen\",\n stop: \"Arbeit stoppen\",\n placeholder: \"Nachricht schreiben ...\",\n steeringPlaceholder: \"Dazwischenfunken ...\",\n steered: \"In den laufenden Turn eingespeist\",\n detailModeTitle: \"Detailgrad der Schritte\",\n detailModeOff: \"nur Antworten\",\n detailModeCurrent: \"aktuell\",\n detailModeIcons: \"Symbole\",\n detailModeChips: \"kompakt\",\n detailModeGrouped: \"gruppiert\",\n detailModeCompact: \"einzeilig\",\n detailModeFull: \"alles\",\n timestamps: \"Zeitstempel\",\n showTimestamps: \"Zeitstempel anzeigen\",\n hideTimestamps: \"Zeitstempel ausblenden\",\n copyMessage: \"Nachricht kopieren\",\n editMessage: \"Nachricht bearbeiten\",\n retryMessage: \"Antwort erneut anfordern\",\n copyCode: \"Code kopieren\",\n copied: \"Kopiert\",\n pendingAction: \"wartet auf Eingabe\",\n dismissAction: \"Verwerfen\",\n actionDismissed: \"verworfen\",\n actionFailed: \"Aktion fehlgeschlagen\",\n clipboardUnavailable: \"Die Zwischenablage ist nicht verf\u00FCgbar\",\n transcript: \"Chatverlauf\",\n attachments: \"Anh\u00E4nge\",\n attachFiles: \"Dateien anh\u00E4ngen\",\n attachFilesHint: \"Dateien anh\u00E4ngen (bis zu {count} Dateien, insgesamt {size})\",\n removeAttachment: \"{name} entfernen\",\n attachmentPreparing: \"Wird vorbereitet ...\",\n attachmentsPreparing: \"Anh\u00E4nge werden vorbereitet ...\",\n attachmentReadFailed: \"Datei konnte nicht gelesen werden. Entferne sie und f\u00FCge sie erneut hinzu.\",\n attachmentsWhileBusy: \"Warte, bis die Eingabe wieder bereit ist, und f\u00FCge die Dateien dann erneut hinzu.\",\n tooManyAttachments: \"H\u00F6chstens {count} Anh\u00E4nge pro Nachricht. Entferne zuerst einen Anhang.\",\n attachmentsTooLarge: \"Anh\u00E4nge d\u00FCrfen zusammen h\u00F6chstens {size} gro\u00DF sein. W\u00E4hle kleinere Dateien.\",\n attachmentUnsupported: \"Dieser Chat unterst\u00FCtzt {name} nicht als {kind}. Entferne den Anhang.\",\n attachmentUnsupportedByModel: \"Das Modell {model} unterst\u00FCtzt {name} nicht als {kind}. W\u00E4hle ein passendes Modell oder entferne den Anhang.\",\n attachmentKindImage: \"Bild\",\n attachmentKindVideo: \"Video\",\n attachmentKindPdf: \"PDF\",\n notSent: \"Nicht gesendet:\",\n notSentAttachments: \"({count} Anh\u00E4nge)\",\n insertUnsent: \"Nicht gesendete Eingabe einf\u00FCgen\",\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 { 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 { MessageActions } from \"./MessageActions\";\nimport { ChatSendContext } from \"./ChatSendContext\";\nimport { announce as ansagen } 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 hoechstensAnsagenAufEinmal = 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 istSchritt(message?: Message): boolean {\n return !!message && (message.role === \"thinking\" || message.role === \"tool\");\n}\n\nfunction defaultArgumentsText(tool: ToolInfo): string {\n return prettyJson(tool.arguments);\n}\n\n/**\n * Der Verlauf: eigener Scroll-Container mit Autoscroll, solange man unten ist,\n * und einem Zum-Ende-Knopf, sobald man liest. Ohne Eingabe read-only nutzbar.\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}: {\n messages: Message[];\n /** Beitr\u00E4ge mit diesem Message.sender erscheinen ohne Sprechblase; null beh\u00E4lt die Nachrichtenvorgaben. */\n owner?: string | null;\n detailMode?: DetailMode;\n running?: boolean;\n working?: ReactNode;\n /** false = Denk- und Werkzeug-Schritte lassen sich nicht aufklappen (kein Popover). */\n stepsExpandable?: boolean;\n texts?: Partial<ChatTexts>;\n toolArgumentsText?: (tool: ToolInfo) => string;\n /** Eigene Darstellung fuer einzelne Werkzeuge; undefined = Standarddarstellung. */\n renderTool?: (tool: ToolInfo) => ReactNode | undefined;\n /** Darstellung einer wartenden Aktion durch ihren Eigent\u00FCmer; undefined = generische Karte. */\n renderAction?: (action: PendingAction, text: string) => ReactNode | undefined;\n onDismissAction?: (actionId: string) => void;\n /** Faengt Klicks auf Markdown-Links ab; true = behandelt, der Browser folgt nicht. */\n onLinkClick?: LinkClickHandler;\n emptyState?: ReactNode;\n className?: string;\n /** Klassen des Hosts f\u00FCr den Scroll-Container (data-quassel-transcript). */\n scrollerClassName?: string;\n /** true = dezente HH:MM-Spalte links an jedem Block (Message.at). */\n showTimestamps?: boolean;\n /** Screenreader-Ansage fertiger Antworten und neuer Aktionen; false = der Host sagt selbst an. */\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}) {\n const alleTexte = { ...defaultTexts, ...texts };\n const { Button } = useQuasselComponents();\n const scrollBereich = 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 [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 // Der Verlauf beim Einh\u00E4ngen und ganze Sch\u00FCbe (Reset mit Replay) gelten als bekannt, nicht als neu.\n const angesagt = useRef<ReadonlySet<string>>(new Set(messages.map((message) => message.key)));\n useEffect(() => {\n const faellig = messages.filter((message, index) => !angesagt.current.has(message.key) && (\n message.role === \"action\"\n ? message.action !== undefined && message.action.status === undefined\n : message.role === \"assistant\" && message.text.trim() !== \"\" && (message.closed === true || (!running && index === messages.length - 1))\n ));\n if (faellig.length === 0) {\n return;\n }\n angesagt.current = new Set([...angesagt.current, ...faellig.map((message) => message.key)]);\n if (announce === false || faellig.length > hoechstensAnsagenAufEinmal) {\n return;\n }\n faellig\n .map((message) => announce\n ? announce({ kind: message.role === \"action\" ? \"action\" : \"reply\", message })\n : markdownPlainText(message.text))\n .forEach((text) => text && ansagen(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 = scrollBereich.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 pruefeEnde = useCallback(() => {\n const bereich = scrollBereich.current;\n if (bereich) {\n scroll.scroll(bereich, scrollbarDragging.current);\n updateJumpVisibility(bereich);\n }\n }, [scroll, updateJumpVisibility]);\n\n useEffect(() => {\n const finishDrag = () => {\n if (scrollbarDragging.current && scrollBereich.current) scroll.scroll(scrollBereich.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 // Inhaltswachstum \u00E4ndert den Folgemodus nicht; auch nachgeladene Medien und die Eingabe z\u00E4hlen.\n useLayoutEffect(() => {\n const bereich = scrollBereich.current;\n if (!bereich) return;\n const align = () => {\n scroll.layout(bereich, scrollbarDragging.current);\n updateJumpVisibility(bereich);\n };\n align();\n const beobachter = new ResizeObserver(align);\n beobachter.observe(bereich);\n if (threadRef.current) beobachter.observe(threadRef.current, { box: \"border-box\" });\n return () => beobachter.disconnect();\n });\n\n const visible = useMemo(\n () => {\n // Eigene Eingaben hinter dem laufenden Schritt beenden ihn nicht; jede andere Nachricht schon.\n const letzterFremder = messages.reduce((last, message, index) => message.role === \"user\" ? last : index, -1);\n return messages.filter((message, index) => {\n if (detailMode === \"current\" && istSchritt(message)) {\n return running && index === letzterFremder\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],\n );\n\n const mitZeit = (inhalt: ReactNode, key: string, at: string | undefined, dicht = false): ReactNode =>\n showTimestamps\n ? (\n <div className={cn(\"qsl:flex qsl:items-baseline qsl:gap-2\", dicht ? denseStepClasses : stepClasses)} key={`zeit-${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\">{inhalt}</div>\n </div>\n )\n : inhalt;\n\n // In den Chip-Modi ruecken aufeinanderfolgende Schritte in eine umbrechende Zeile zusammen, gruppiert in eine aufklappbare Zeile.\n const chipModus = detailMode === \"current\" || detailMode === \"chips\" || detailMode === \"icons\";\n const gruppenModus = detailMode === \"grouped\";\n const bloecke: ReactNode[] = [];\n let lastDay: string | undefined;\n let gruppe: Message[] = [];\n const schliesseGruppe = () => {\n if (gruppe.length > 0) {\n const letzterZustand = stepState(gruppe[gruppe.length - 1]);\n bloecke.push(mitZeit(\n gruppenModus ? (\n <StepGroup\n aktiv={running && (letzterZustand === \"running\" || letzterZustand === \"thinking\")}\n expandierbar={stepsExpandable}\n key={gruppe[0].key}\n messages={gruppe}\n texts={alleTexte}\n toolArgumentsText={toolArgumentsText}\n />\n ) : (\n <StepRow\n expandierbar={stepsExpandable}\n key={gruppe[0].key}\n messages={gruppe}\n mitText={detailMode !== \"icons\"}\n texts={alleTexte}\n toolArgumentsText={toolArgumentsText}\n toolLabel={detailMode === \"current\" && !stepsExpandable ? alleTexte.currentTool : undefined}\n />\n ),\n gruppe[0].key,\n gruppe[0].at,\n ));\n gruppe = [];\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 schliesseGruppe();\n bloecke.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 eigeneDarstellung = message.role === \"tool\" && message.tool && detailMode !== \"current\" ? renderTool?.(message.tool) : undefined;\n if (eigeneDarstellung !== undefined) {\n schliesseGruppe();\n bloecke.push(mitZeit(\n <div className={stepClasses} key={message.key}>\n {eigeneDarstellung}\n </div>,\n message.key,\n message.at,\n ));\n return;\n }\n if ((chipModus || gruppenModus) && istSchritt(message)) {\n gruppe = [...gruppe, message];\n return;\n }\n schliesseGruppe();\n const dicht = istSchritt(message) && istSchritt(visible[index - 1]);\n bloecke.push(mitZeit(\n <Bubble\n detailMode={detailMode}\n dicht={dicht}\n expandierbar={stepsExpandable}\n key={message.key}\n message={message}\n plain={owner != null && message.sender === owner}\n texts={alleTexte}\n toolArgumentsText={toolArgumentsText}\n renderAction={renderAction}\n onDismissAction={onDismissAction}\n bubbleOptions={bubbleOptions}\n messageActions={messageActions}\n />,\n message.key,\n message.at,\n dicht,\n ));\n });\n schliesseGruppe();\n\n const verlauf = (\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={alleTexte.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={pruefeEnde}\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 scrollBereich.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 {bloecke}\n {running && (working ?? <WorkingScenes label={alleTexte.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={alleTexte.jumpToEnd} className=\"qsl:pointer-events-auto qsl:rounded-full qsl:border qsl:border-primary-foreground/20 qsl:shadow-md\" size=\"icon\" title={alleTexte.jumpToEnd} variant=\"default\" onClick={() => {\n if (scrollBereich.current) {\n scroll.jump(scrollBereich.current);\n updateJumpVisibility(scrollBereich.current);\n }\n }}>\n <ChevronDownIcon />\n </Button>\n </div>\n )}\n </div>\n );\n\n return <MarkdownLinks onLinkClick={onLinkClick}><MarkdownCodeBlocks options={codeBlockOptions} texts={alleTexte}>{verlauf}</MarkdownCodeBlocks></MarkdownLinks>;\n}\n\n/** Aufeinanderfolgende Schritte als Chips nebeneinander; bei Platzmangel bricht die Zeile um. */\nfunction StepRow({\n messages,\n mitText,\n expandierbar,\n texts,\n toolArgumentsText,\n toolLabel,\n}: {\n messages: Message[];\n mitText: boolean;\n expandierbar: boolean;\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 offen = expandierbar && 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 {mitText && <span className=\"qsl:min-w-0 qsl:self-baseline qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap\">{label}</span>}\n {mitText && <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, !mitText && \"qsl:p-1\", running && \"qsl:animate-fade-pulse qsl:motion-reduce:animate-none\");\n if (!expandierbar) {\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 {offen && detail && (\n <StepPopover\n message={offen}\n position={detail.position}\n texts={texts}\n toolArgumentsText={toolArgumentsText}\n onClose={() => setDetail(undefined)}\n />\n )}\n </div>\n );\n}\n\n/** Aufeinanderfolgende Schritte hinter einer Kopfzeile; aufgeklappt stehen sie als einzeilige Zeilen darunter. */\nfunction StepGroup({\n messages,\n aktiv,\n expandierbar,\n texts,\n toolArgumentsText,\n}: {\n messages: Message[];\n aktiv: boolean;\n expandierbar: boolean;\n texts: ChatTexts;\n toolArgumentsText: (tool: ToolInfo) => string;\n}) {\n const [offen, setOffen] = useState(false);\n const kopf = useRef<HTMLButtonElement>(null);\n const vonUntenEingeklappt = useRef(false);\n useLayoutEffect(() => {\n if (!offen && vonUntenEingeklappt.current) {\n vonUntenEingeklappt.current = false;\n kopf.current?.scrollIntoView({ block: \"nearest\" });\n }\n }, [offen]);\n const letzte = messages[messages.length - 1];\n const fehler = messages.some((message) => message.tool?.isError);\n const anzahl = messages.length === 1 ? texts.stepGroupOne : texts.stepGroupMany.replace(\"{count}\", String(messages.length));\n const laufend = aktiv ? (letzte.role === \"thinking\" ? texts.thinkingChip : letzte.tool?.name || letzte.text || texts.toolChip) : undefined;\n\n return (\n <div className={stepClasses} data-step=\"group\">\n <button\n aria-expanded={offen}\n className={cn(traceClasses, traceButtonClasses, \"qsl:items-center qsl:pl-1\", aktiv && \"qsl:animate-fade-pulse qsl:motion-reduce:animate-none\")}\n onClick={() => setOffen((wert) => !wert)}\n ref={kopf}\n type=\"button\"\n >\n <ChevronRightIcon className={cn(\"qsl:flex-none qsl:opacity-60 qsl:transition-transform\", offen && \"qsl:rotate-90\")} size={12} />\n <LayersIcon className={fehler ? traceErrorIconClasses : traceIconClasses} size={12} />\n <span className={cn(traceLineClasses, \"qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap\")}>\n {anzahl}\n {laufend && <span className={traceRunningClasses}>{laufend} {texts.toolRunning}</span>}\n </span>\n </button>\n {offen && (\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\" expandierbar={expandierbar} key={message.key} message={message} texts={texts} toolArgumentsText={toolArgumentsText} />\n ))}\n </div>\n )}\n {offen && 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 vonUntenEingeklappt.current = true;\n setOffen(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/** Ein Schritt als eine Zeile; mit Freigabe oeffnet ein Klick die Details im Popover. */\nfunction TraceLine({\n message,\n className,\n expandierbar,\n texts,\n toolArgumentsText,\n}: {\n message: Message;\n className: string;\n expandierbar: 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 zeile = cn(traceLineClasses, thinking && \"qsl:font-sans qsl:italic qsl:whitespace-pre-wrap\", \"qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap\");\n const inhalt = (\n <>\n {thinking ? (\n <SparklesIcon className={traceIconClasses} size={12} />\n ) : (\n <WrenchIcon className={tool?.isError ? traceErrorIconClasses : traceIconClasses} size={12} />\n )}\n <span className={zeile}>\n {message.text}\n {tool && tool.result === undefined && <span className={traceRunningClasses}>{texts.toolRunning}</span>}\n </span>\n </>\n );\n const marks = { \"data-compact\": \"true\", \"data-kind\": thinking ? \"thinking\" : \"tool\", \"data-step\": \"line\" } as const;\n if (!expandierbar) {\n return <div className={classes} {...marks}>{inhalt}</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 {inhalt}\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\nfunction Bubble({\n message,\n plain,\n detailMode,\n dicht,\n expandierbar,\n texts,\n toolArgumentsText,\n renderAction,\n onDismissAction,\n bubbleOptions,\n messageActions,\n}: {\n message: Message;\n plain: boolean;\n detailMode: DetailMode;\n dicht: boolean;\n expandierbar: 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 schritt = dicht ? denseStepClasses : stepClasses;\n\n if (message.role === \"thinking\" || (message.role === \"tool\" && message.tool)) {\n if (detailMode === \"compact\") {\n return <TraceLine className={schritt} expandierbar={expandierbar} 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 zeile = (\n <>\n {message.text}\n {tool && tool.result === undefined && <span className={traceRunningClasses}>{texts.toolRunning}</span>}\n </>\n );\n return (\n <div className={cn(traceClasses, schritt)} 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\")}>{zeile}</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 const action = message.action;\n return (\n <div className={schritt}>\n {renderAction?.(action, message.text) ?? (\n <PendingActionCard\n action={action}\n dismissedLabel={texts.actionDismissed}\n dismissLabel={texts.dismissAction}\n onDismiss={onDismissAction ? () => onDismissAction(action.actionId) : undefined}\n text={message.text}\n waitingLabel={texts.pendingAction}\n />\n )}\n </div>\n );\n }\n\n if (message.role === \"system\") {\n return (\n <div className={cn(schritt, \"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(schritt, \"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(schritt, \"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 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// Waagerechte Rollbalken bleiben sichtbar - sonst ist der Ueberlauf nicht auffindbar.\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// Die Deckstreifen verbergen den Umbruch am Rand; --qsl-scroll-cover kommt aus der umgebenden Blase.\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 // Ohne max-content schrumpft die Tabelle auf den Container und stapelt Buchstaben.\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/** Dieselbe Syntax wie der Renderer, als Klartext ohne Markup, etwa f\u00FCr Screenreader-Ansagen. */\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, fett, fettUnterstrich, kursiv, code) => link ?? fett ?? fettUnterstrich ?? kursiv ?? 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/** Die eine Stopp-Glyphe: ein gef\u00FClltes rotes Quadrat; ein Zustandssymbol tr\u00E4gt sie nie. */\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/** Jeder Stopp-Knopf sieht gleich aus: die Glyphe als Symbol, das Wort im Tooltip, rot in Ruhe und beim 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 * Die Darstellung einer wartenden Aktion ohne Beitrag ihres Eigent\u00FCmers: Titel, der Hinweis,\n * dass eine Eingabe erwartet wird, und das Verwerfen. Die Form kennt nur das Plugin.\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 SPUR = 13;\nconst GRUNDTAKT_MS = 90;\nconst SZENENWECHSEL_MS = 2600;\n\n/** Eine Zelle je Figur: Emoji und Satzzeichen teilen sich kein Raster, geschobener Text ruckelt. */\nfunction bahn(figuren: Record<number, string>, breite = SPUR): string[] {\n return Array.from({ length: breite }, (_, x) => figuren[x] ?? \" \");\n}\n\ninterface Szene {\n id: string;\n takt: number;\n laufend?: true;\n compact?: true;\n zeichne: (schritt: number) => string | string[];\n}\n\n/**\n * Kleine Szenen, in denen etwas Erkennbares passiert - der Zustand aendert sich sichtbar,\n * statt dass nur eine Figur vorbeilaeuft. Szenen mit Bewegung geben ihre Bahn als Zellen\n * zurueck, alle anderen als schlichten Text.\n */\nconst SZENEN: Szene[] = [\n {\n id: \"denken\",\n takt: 2,\n zeichne: (schritt) => {\n const takt = schritt % 10;\n if (takt >= 8) return \"\\u{1F929}\\u{1F4A1}\";\n return \"\\u{1F914}\" + \"\\u{1F4AD}\".repeat(Math.min(takt, 3));\n },\n },\n {\n // Fliegt nach rechts und zieht ihren Schweif hinterher.\n id: \"rakete\",\n takt: 2,\n laufend: true,\n zeichne: (schritt) => {\n const x = schritt % SPUR;\n return bahn({ [x - 2]: \"\u00B7\", [x - 1]: \"\\u{1F4A8}\", [x]: \"\\u{1F680}\" });\n },\n },\n {\n // Die Punkte bleiben stehen und werden einzeln gefressen.\n id: \"pacman\",\n takt: 2,\n laufend: true,\n zeichne: (schritt) => {\n const x = schritt % SPUR;\n const figuren: Record<number, string> = {};\n for (let i = x + 1; i < SPUR; i++) {\n figuren[i] = \"\u00B7\";\n }\n figuren[x] = schritt % 2 === 0 ? \"\\u{1F7E1}\" : \"\\u{1F315}\";\n return bahn(figuren);\n },\n },\n {\n // Aus einem Samen wird ein Baum, dann von vorn.\n id: \"wachsen\",\n compact: true,\n takt: 2,\n zeichne: (schritt) => {\n const stufen = [\"\\u{1F331}\", \"\\u{1F331}\", \"\\u{1F33F}\", \"\\u{1F33F}\", \"\\u{1F343}\", \"\\u{1F333}\", \"\\u{1F333}\", \"\\u{1F333}\"];\n return stufen[schritt % stufen.length];\n },\n },\n {\n // Das Ei bekommt Risse, das Kueken schluepft.\n id: \"schluepfen\",\n compact: true,\n takt: 2,\n zeichne: (schritt) => {\n const takt = schritt % 12;\n if (takt < 4) return \"\\u{1F95A}\";\n if (takt < 6) return \"\\u{1F95A}*\";\n if (takt < 9) return \"\\u{1F423}\";\n return \"\\u{1F425}\";\n },\n },\n {\n // Morse-artiges Signal, das sich zu einem OK aufloest.\n id: \"signal\",\n takt: 2,\n zeichne: (schritt) => {\n const takt = schritt % 14;\n if (takt >= 11) return \"\\u{1F4E1} OK\";\n const muster = [\"\u00B7\", \"\u00B7\u00B7\", \"\u00B7-\", \"-\u00B7\", \"\u00B7\u00B7-\", \"-\u00B7\u00B7\"];\n return \"\\u{1F4E1} \" + muster[takt % muster.length];\n },\n },\n {\n // Sanduhr: der Sand laeuft durch, dann wird gedreht.\n id: \"sanduhr\",\n takt: 2,\n zeichne: (schritt) => {\n const takt = schritt % 12;\n const koerner = \"\u00B7\".repeat(Math.max(0, 5 - Math.floor(takt / 2)));\n return (takt < 10 ? \"\u23F3\" : \"\u231B\") + \" \" + koerner;\n },\n },\n {\n // Ei, Kueken, Henne - und die legt das naechste Ei.\n id: \"huhn-kreislauf\",\n compact: true,\n takt: 3,\n zeichne: (schritt) => {\n const takt = schritt % 16;\n if (takt < 3) return \"\\u{1F95A}\";\n if (takt < 5) return \"\\u{1F95A}*\";\n if (takt < 8) return \"\\u{1F423}\";\n if (takt < 11) return \"\\u{1F424}\";\n if (takt < 14) return \"\\u{1F414}\";\n return \"\\u{1F414}\\u{1F95A}\";\n },\n },\n {\n // Hut, Funken - und das Kaninchen tuermt.\n id: \"zauberhut\",\n compact: true,\n takt: 3,\n zeichne: (schritt) => {\n const takt = schritt % 14;\n if (takt < 4) return \"\\u{1F3A9}\";\n if (takt < 7) return \"\\u{1F3A9}*\";\n if (takt < 11) return \"\\u{1F3A9}\\u{1F407}\";\n return \"\\u{1F407}\\u{1F4A8}\";\n },\n },\n {\n // Rot, Gelb, Gruen - und ab.\n id: \"ampel\",\n compact: true,\n takt: 3,\n zeichne: (schritt) => {\n const takt = schritt % 12;\n if (takt < 4) return \"\\u{1F534}\";\n if (takt < 6) return \"\\u{1F7E1}\";\n if (takt < 8) return \"\\u{1F7E2}\";\n return \"\\u{1F697}\\u{1F4A8}\";\n },\n },\n {\n // Klingeln, verschlafen, losrennen.\n id: \"wecker\",\n compact: true,\n takt: 2,\n zeichne: (schritt) => {\n const takt = schritt % 14;\n if (takt < 5) return takt % 2 === 0 ? \"\u23F0\" : \"\\u{1F514}\";\n if (takt < 8) return \"\\u{1F634}\";\n if (takt < 10) return \"\\u{1F633}\";\n return \"\\u{1F3C3}\\u{1F4A8}\";\n },\n },\n {\n // Schnecke kriecht zur Flagge - und feiert.\n id: \"schnecke\",\n takt: 4,\n zeichne: (schritt) => {\n const takt = schritt % 8;\n if (takt < 5) return bahn({ [takt]: \"\\u{1F40C}\", 4: \"\\u{1F3C1}\" }, 5);\n return bahn({ 4: \"\\u{1F389}\" }, 5);\n },\n },\n];\n\nconst COMPACT_SCENES = SZENEN.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 fuer Screenreader, Default \"Arbeitet ...\". */\n label?: string;\n}\n\n/**\n * Der Default-Working-Indikator: zufaellig rotierende Mini-Szenen. Zufaellige Reihenfolge\n * und Startphase, damit dieselben Szenen nie wie eine Schleife wirken. Ueber die\n * working-Prop von ChatMessages laesst er sich komplett ersetzen.\n */\nexport function WorkingScenes({ label = \"Arbeitet ...\", compact = false }: WorkingScenesProps) {\n const scenes = compact ? COMPACT_SCENES : SZENEN;\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 }, SZENENWECHSEL_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), GRUNDTAKT_MS);\n return () => window.clearInterval(timer);\n }, [reducedMotion]);\n\n const frame = scene.zeichne(Math.floor(frameTick / scene.takt) + (scene.laufend ? 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 { 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", "const abstandMs = 400;\nconst hoechstensWartend = 5;\n\nlet region: HTMLElement | undefined;\nlet wartend: readonly string[] = [];\nlet laeuft = false;\n\nfunction ansageRegion(): 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 naechste(): void {\n if (wartend.length === 0) {\n laeuft = false;\n return;\n }\n if (document.visibilityState === \"hidden\") {\n document.addEventListener(\"visibilitychange\", naechste, { once: true });\n return;\n }\n const [text, ...rest] = wartend;\n wartend = rest;\n const ziel = ansageRegion();\n ziel.textContent = ziel.textContent === text ? `${text}\\u00a0` : text;\n window.setTimeout(naechste, abstandMs);\n}\n\n/** Sagt Text \u00FCber eine gemeinsame, versteckte Live-Region an: gedrosselt, und bei verstecktem Tab angehalten. */\nexport function announce(text: string): void {\n const inhalt = text.trim();\n if (!inhalt || typeof document === \"undefined\") {\n return;\n }\n wartend = [...wartend, inhalt].slice(-hoechstensWartend);\n if (laeuft) {\n return;\n }\n laeuft = true;\n ansageRegion();\n window.setTimeout(naechste, abstandMs);\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 { appearanceStyle, type ChatAppearance } from \"./options\";\n\n/**\n * Verlauf mit ueberlagerter Eingabe. Der Rahmen misst die Eingabe selbst und\n * gibt dem Verlauf den noetigen Fussraum, damit kein Host Innenmasse setzen muss.\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 /** Die Eingabe; sie liegt ueber dem Verlauf, nicht darunter. */\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 wurzel = useRef<HTMLDivElement>(null);\n const eingabe = useRef<HTMLDivElement>(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 = eingabe.current;\n const rahmen = wurzel.current;\n if (!element || !rahmen) {\n return;\n }\n const messen = () => rahmen.style.setProperty(\"--qsl-composer-height\", `${element.offsetHeight}px`);\n const beobachter = new ResizeObserver(messen);\n beobachter.observe(element);\n messen();\n return () => {\n beobachter.disconnect();\n rahmen.style.removeProperty(\"--qsl-composer-height\");\n };\n }, [hasComposer]);\n\n return (\n <ChatSendContext.Provider value={sendScope}>\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 wurzel.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={eingabe}>\n {composer}\n </div>\n )}\n </div>\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// Unter dieser Panel-Breite klappen mitlaufende Beschriftungen zu ihren Symbolen.\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/** Ein Toolbar-Knopf, deklarativ: Symbol, Text oder beides - plus Klick-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 steuern den Entwurf von aussen, z.B. um eine Vorlage zum Bearbeiten einzusetzen. */\nexport interface ChatInputHandle {\n /** Ersetzt den Entwurf, fokussiert die Eingabe und stellt die Schreibmarke ans Ende. */\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 * Die Eingabe-Karte: rahmenlose Textarea oben, Toolbar unter einer Haarlinie. Eigene\n * Kn\u00F6pfe kommen deklarativ \u00FCber `actions` oder frei \u00FCber die Slots links/rechts; bei\n * laufender Arbeit bleibt der Stop-Knopf sichtbar, und Tippen zeigt daneben den Senden-Knopf,\n * der zum Dazwischenfunken wird. `rows` bestimmt die Starth\u00F6he; mit `maxRows` w\u00E4chst die Textarea\n * mit dem Inhalt bis zu dieser Zeilenzahl und scrollt danach.\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 = kein Anh\u00E4ngen: weder Knopf noch Ablegen oder Einf\u00FCgen von Dateien. */\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 alleTexte = { ...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(alleTexte.attachmentsWhileBusy);\n return;\n }\n try {\n validateAttachmentSelection(attachmentsRef.current.map((entry) => entry.file), files, alleTexte);\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: alleTexte.attachmentReadFailed,\n } : item)),\n );\n }\n };\n const rootRef = useRef<HTMLDivElement>(null);\n const eingabeRef = useRef<HTMLTextAreaElement>(null);\n const autoFocusSettled = useRef(false);\n useEffect(() => {\n if (!autoFocus || autoFocusSettled.current) return;\n const input = eingabeRef.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 = eingabeRef.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 // Die Toolbar-Fassung pulsiert waehrend der Arbeit; der Host gibt nur den Radius vor.\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 = eingabeRef.current;\n element?.focus();\n if (element?.value === text) element.setSelectionRange(text.length, text.length);\n },\n focus: () => eingabeRef.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 = eingabeRef.current;\n if (element) {\n element.focus();\n element.setSelectionRange(element.value.length, element.value.length);\n }\n }, [draft, sending]);\n\n // Auto-Wachstum: Hoehe folgt dem Inhalt zwischen rows und maxRows, danach scrollt die Textarea.\n const applyAutoGrow = useCallback(() => {\n const element = eingabeRef.current;\n if (!element || inputMaxRows === undefined) {\n return;\n }\n const stil = getComputedStyle(element);\n const zeilenhoehe = Number.parseFloat(stil.lineHeight) || Number.parseFloat(stil.fontSize) * 1.4;\n const polster = Number.parseFloat(stil.paddingTop) + Number.parseFloat(stil.paddingBottom);\n const maximum = zeilenhoehe * Math.max(inputMaxRows, inputRows) + polster;\n element.style.height = \"auto\";\n const inhalt = element.scrollHeight;\n element.style.height = `${Math.min(inhalt, maximum)}px`;\n element.style.overflowY = inhalt > 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 = eingabeRef.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-Breite statt Viewport-Breite: die Chat-Spalte kann im Host beliebig schmal sein.\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 beobachter = new ResizeObserver(update);\n beobachter.observe(element);\n return () => beobachter.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, alleTexte) : 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 === eingabeRef.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 !== eingabeRef.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={alleTexte.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\">{alleTexte.attachmentPreparing}</small>}\n {entry.status === \"error\" && <small role=\"alert\">{entry.error}</small>}\n </div>\n <Button\n aria-label={fillText(alleTexte.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 eingabeRef.current?.focus();\n }}\n size=\"icon-sm\"\n title={fillText(alleTexte.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>{alleTexte.notSent} {failed.draft.slice(0, 100)}{failed.draft.length > 100 ? \" ...\" : \"\"}{failed.attachments.length > 0 ? ` ${fillText(alleTexte.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), alleTexte);\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 }}>{alleTexte.insertUnsent}</Button>\n </div>)}\n </>;\n const sendButtons = <>\n {running && onStop && !hasContent && <StopButton className=\"qsl:flex-none\" label={alleTexte.stop} onClick={onStop} size=\"icon-sm\" />}\n {(!running || !onStop || hasContent) && (\n <Button\n aria-label={alleTexte.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 ? alleTexte.sendIntoRun : alleTexte.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={alleTexte.attachFiles}\n disabled={disabled || sending}\n onClick={() => fileInput.inputRef.current?.click()}\n size=\"icon-sm\"\n title={fillText(alleTexte.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\">{alleTexte.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={alleTexte.placeholder}\n disabled={!toolbar && disabled}\n readOnly={toolbar && disabled}\n onChange={(event) => changeDraft(event.target.value)}\n onKeyDown={onKeyDown}\n placeholder={running ? alleTexte.steeringPlaceholder : alleTexte.placeholder}\n ref={eingabeRef}\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={alleTexte.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 { SparklesIcon } 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\nexport const detailModeLabel = (mode: DetailMode, texts?: Partial<ChatTexts>): string =>\n ({ ...defaultTexts, ...texts })[TEXT_KEYS[mode]];\n\n/**\n * Ein Knopf, der den Detailgrad der Denk- und Werkzeug-Schritte weiterschaltet. Die\n * Reihenfolge kommt aus `modes`, der aktuelle Wert steht als Beschriftung daneben.\n */\nexport function DetailModeSwitch({\n mode,\n onChange,\n modes = DETAIL_MODES,\n collapsible = true,\n texts,\n className,\n}: {\n mode: DetailMode;\n onChange: (mode: DetailMode) => void;\n /** Auswahl und Reihenfolge des Weiterschaltens; Default sind alle Modi. */\n modes?: readonly DetailMode[];\n /** false = die Beschriftung bleibt auch in einer schmalen Eingabe-Karte stehen. */\n collapsible?: boolean;\n texts?: Partial<ChatTexts>;\n className?: string;\n}) {\n const alleTexte = { ...defaultTexts, ...texts };\n const { Button } = useQuasselComponents();\n const aktuell = modes.indexOf(mode);\n const naechster = modes[(aktuell < 0 ? 0 : aktuell + 1) % modes.length];\n return (\n <Button\n aria-label={`${alleTexte.detailModeTitle}: ${detailModeLabel(mode, texts)}`}\n className={className}\n onClick={() => onChange(naechster)}\n size=\"sm\"\n title={`${alleTexte.detailModeTitle}: ${detailModeLabel(mode, texts)}`}\n variant=\"ghost\"\n >\n <SparklesIcon />\n <span className={collapsible ? \"qsl:in-data-[compact=true]:hidden\" : undefined}>{detailModeLabel(mode, texts)}</span>\n </Button>\n );\n}\n", "import { ClockIcon } from \"lucide-react\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\nimport { type ChatTexts, defaultTexts } from \"./texts\";\n\nexport function TimestampSwitch({ showTimestamps, onChange, collapsible = true, texts, className }: {\n showTimestamps: boolean;\n onChange: (showTimestamps: boolean) => void;\n collapsible?: boolean;\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=\"sm\" title={title} variant=\"ghost\">\n <ClockIcon />\n <span className={collapsible ? \"qsl:in-data-[compact=true]:hidden\" : undefined}>{labels.timestamps}</span>\n </Button>\n );\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
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", "CheckIcon", "CopyIcon", "useState", "jsx", "jsxs", "Button", "useState", "CopyIcon", "CheckIcon", "createContext", "Fragment", "jsx", "jsxs", "announce", "Button", "useRef", "useState", "useContext", "useEffect", "useCallback", "useMemo", "SparklesIcon", "WrenchIcon", "CheckIcon", "useEffect", "useLayoutEffect", "useRef", "useState", "jsx", "jsxs", "useRef", "useState", "useLayoutEffect", "useEffect", "XIcon", "useRef", "useState", "useCallback", "useContext", "useEffect", "useLayoutEffect", "useRef", "useState", "Fragment", "jsx", "jsxs", "useContext", "Button", "StopButton", "Toggle", "useState", "useRef", "useLayoutEffect", "input", "useEffect", "useCallback", "XIcon", "SparklesIcon", "jsx", "jsxs", "Button", "SparklesIcon", "jsx", "jsxs", "Button"]
|
|
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 = nur der laufende Schritt, off = nur Antworten, icons = Schritte als reine Symbole nebeneinander,\n * chips = Schritte als Symbol + Kurztext nebeneinander (mit Umbruch),\n * grouped = aufeinanderfolgende Schritte als eine aufklappbare Zeile, dahinter einzeilig,\n * compact = Denken und Werkzeuge einzeilig, full = alles ausgeklappt.\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 timestamps: 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: \"Arbeitet ...\",\n toolRunning: \"l\u00E4uft ...\",\n toolStillRunning: \"Werkzeug l\u00E4uft ...\",\n toolElapsedSeconds: \"{seconds} s\",\n currentTool: \"Werkzeug l\u00E4uft\",\n thinkingChip: \"Denken\",\n toolChip: \"Werkzeug\",\n stepGroupOne: \"1 Schritt\",\n stepGroupMany: \"{count} Schritte\",\n stepGroupCollapse: \"Einklappen\",\n thinkingTitle: \"Thinking-Trace\",\n toolTitle: \"Tool-Call\",\n argumentsLabel: \"Argumente\",\n resultLabel: \"Ergebnis\",\n close: \"Schlie\u00DFen\",\n jumpToEnd: \"Zum Ende springen\",\n send: \"Senden\",\n sendIntoRun: \"In den laufenden Turn einspeisen\",\n stop: \"Arbeit stoppen\",\n placeholder: \"Nachricht schreiben ...\",\n steeringPlaceholder: \"Dazwischenfunken ...\",\n steered: \"In den laufenden Turn eingespeist\",\n detailModeTitle: \"Detailgrad der Schritte\",\n detailModeOff: \"nur Antworten\",\n detailModeCurrent: \"aktuell\",\n detailModeIcons: \"Symbole\",\n detailModeChips: \"kompakt\",\n detailModeGrouped: \"gruppiert\",\n detailModeCompact: \"einzeilig\",\n detailModeFull: \"alles\",\n timestamps: \"Zeitstempel\",\n showTimestamps: \"Zeitstempel anzeigen\",\n hideTimestamps: \"Zeitstempel ausblenden\",\n copyMessage: \"Nachricht kopieren\",\n editMessage: \"Nachricht bearbeiten\",\n retryMessage: \"Antwort erneut anfordern\",\n copyCode: \"Code kopieren\",\n copied: \"Kopiert\",\n pendingAction: \"wartet auf Eingabe\",\n dismissAction: \"Verwerfen\",\n actionDismissed: \"verworfen\",\n actionFailed: \"Aktion fehlgeschlagen\",\n clipboardUnavailable: \"Die Zwischenablage ist nicht verf\u00FCgbar\",\n transcript: \"Chatverlauf\",\n attachments: \"Anh\u00E4nge\",\n attachFiles: \"Dateien anh\u00E4ngen\",\n attachFilesHint: \"Dateien anh\u00E4ngen (bis zu {count} Dateien, insgesamt {size})\",\n removeAttachment: \"{name} entfernen\",\n attachmentPreparing: \"Wird vorbereitet ...\",\n attachmentsPreparing: \"Anh\u00E4nge werden vorbereitet ...\",\n attachmentReadFailed: \"Datei konnte nicht gelesen werden. Entferne sie und f\u00FCge sie erneut hinzu.\",\n attachmentsWhileBusy: \"Warte, bis die Eingabe wieder bereit ist, und f\u00FCge die Dateien dann erneut hinzu.\",\n tooManyAttachments: \"H\u00F6chstens {count} Anh\u00E4nge pro Nachricht. Entferne zuerst einen Anhang.\",\n attachmentsTooLarge: \"Anh\u00E4nge d\u00FCrfen zusammen h\u00F6chstens {size} gro\u00DF sein. W\u00E4hle kleinere Dateien.\",\n attachmentUnsupported: \"Dieser Chat unterst\u00FCtzt {name} nicht als {kind}. Entferne den Anhang.\",\n attachmentUnsupportedByModel: \"Das Modell {model} unterst\u00FCtzt {name} nicht als {kind}. W\u00E4hle ein passendes Modell oder entferne den Anhang.\",\n attachmentKindImage: \"Bild\",\n attachmentKindVideo: \"Video\",\n attachmentKindPdf: \"PDF\",\n notSent: \"Nicht gesendet:\",\n notSentAttachments: \"({count} Anh\u00E4nge)\",\n insertUnsent: \"Nicht gesendete Eingabe einf\u00FCgen\",\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 ansagen } 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 hoechstensAnsagenAufEinmal = 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 istSchritt(message?: Message): boolean {\n return !!message && (message.role === \"thinking\" || message.role === \"tool\");\n}\n\nfunction istOffeneAktion(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 * Der Verlauf: eigener Scroll-Container mit Autoscroll, solange man unten ist,\n * und einem Zum-Ende-Knopf, sobald man liest. Ohne Eingabe read-only nutzbar.\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 /** Beitr\u00E4ge mit diesem Message.sender erscheinen ohne Sprechblase; null beh\u00E4lt die Nachrichtenvorgaben. */\n owner?: string | null;\n detailMode?: DetailMode;\n running?: boolean;\n working?: ReactNode;\n /** false = Denk- und Werkzeug-Schritte lassen sich nicht aufklappen (kein Popover). */\n stepsExpandable?: boolean;\n texts?: Partial<ChatTexts>;\n toolArgumentsText?: (tool: ToolInfo) => string;\n /** Eigene Darstellung fuer einzelne Werkzeuge; undefined = Standarddarstellung. */\n renderTool?: (tool: ToolInfo) => ReactNode | undefined;\n /** Darstellung einer wartenden Aktion durch ihren Eigent\u00FCmer; undefined = generische Karte. */\n renderAction?: (action: PendingAction, text: string) => ReactNode | undefined;\n onDismissAction?: (actionId: string) => void;\n /** Faengt Klicks auf Markdown-Links ab; true = behandelt, der Browser folgt nicht. */\n onLinkClick?: LinkClickHandler;\n emptyState?: ReactNode;\n className?: string;\n /** Klassen des Hosts f\u00FCr den Scroll-Container (data-quassel-transcript). */\n scrollerClassName?: string;\n /** true = dezente HH:MM-Spalte links an jedem Block (Message.at). */\n showTimestamps?: boolean;\n /** Screenreader-Ansage fertiger Antworten und neuer Aktionen; false = der Host sagt selbst an. */\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 alleTexte = { ...defaultTexts, ...texts };\n const { Button } = useQuasselComponents();\n const scrollBereich = 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 // Der Verlauf beim Einh\u00E4ngen und ganze Sch\u00FCbe (Reset mit Replay) gelten als bekannt, nicht als neu.\n const angesagt = useRef<ReadonlySet<string>>(new Set(messages.map((message) => message.key)));\n useEffect(() => {\n const faellig = messages.filter((message, index) => !angesagt.current.has(message.key) && (\n message.role === \"action\"\n ? istOffeneAktion(message)\n : message.role === \"assistant\" && message.text.trim() !== \"\" && (message.closed === true || (!running && index === messages.length - 1))\n ));\n if (faellig.length === 0) {\n return;\n }\n angesagt.current = new Set([...angesagt.current, ...faellig.map((message) => message.key)]);\n if (announce === false || faellig.length > hoechstensAnsagenAufEinmal) {\n return;\n }\n faellig\n .map((message) => announce\n ? announce({ kind: message.role === \"action\" ? \"action\" : \"reply\", message })\n : markdownPlainText(message.text))\n .forEach((text) => text && ansagen(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 = scrollBereich.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 pruefeEnde = useCallback(() => {\n const bereich = scrollBereich.current;\n if (bereich) {\n scroll.scroll(bereich, scrollbarDragging.current);\n updateJumpVisibility(bereich);\n }\n }, [scroll, updateJumpVisibility]);\n\n useEffect(() => {\n const finishDrag = () => {\n if (scrollbarDragging.current && scrollBereich.current) scroll.scroll(scrollBereich.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 // Inhaltswachstum \u00E4ndert den Folgemodus nicht; auch nachgeladene Medien und die Eingabe z\u00E4hlen.\n useLayoutEffect(() => {\n const bereich = scrollBereich.current;\n if (!bereich) return;\n const align = () => {\n scroll.layout(bereich, scrollbarDragging.current);\n updateJumpVisibility(bereich);\n };\n align();\n const beobachter = new ResizeObserver(align);\n beobachter.observe(bereich);\n if (threadRef.current) beobachter.observe(threadRef.current, { box: \"border-box\" });\n return () => beobachter.disconnect();\n });\n\n const visible = useMemo(\n () => {\n // Eigene Eingaben hinter dem laufenden Schritt beenden ihn nicht; jede andere Nachricht schon.\n const letzterFremder = messages.reduce((last, message, index) => message.role === \"user\" ? last : index, -1);\n return messages.filter((message, index) => {\n if (dock !== undefined && istOffeneAktion(message)) {\n return false;\n }\n if (detailMode === \"current\" && istSchritt(message)) {\n return running && index === letzterFremder\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 offeneAktionen = dock ? messages.filter(istOffeneAktion) : [];\n\n const mitZeit = (inhalt: ReactNode, key: string, at: string | undefined, dicht = false): ReactNode =>\n showTimestamps\n ? (\n <div className={cn(\"qsl:flex qsl:items-baseline qsl:gap-2\", dicht ? denseStepClasses : stepClasses)} key={`zeit-${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\">{inhalt}</div>\n </div>\n )\n : inhalt;\n\n // In den Chip-Modi ruecken aufeinanderfolgende Schritte in eine umbrechende Zeile zusammen, gruppiert in eine aufklappbare Zeile.\n const chipModus = detailMode === \"current\" || detailMode === \"chips\" || detailMode === \"icons\";\n const elapsedAfter = running && toolElapsedThreshold !== false ? toolElapsedThreshold : undefined;\n const gruppenModus = detailMode === \"grouped\";\n const bloecke: ReactNode[] = [];\n let lastDay: string | undefined;\n let gruppe: Message[] = [];\n const schliesseGruppe = () => {\n if (gruppe.length > 0) {\n const laufenderSchritt = running ? [...gruppe].reverse().find((message) => [\"running\", \"thinking\"].includes(stepState(message))) : undefined;\n bloecke.push(mitZeit(\n gruppenModus ? (\n <StepGroup\n elapsedAfter={elapsedAfter}\n expandierbar={stepsExpandable}\n laufenderSchritt={laufenderSchritt}\n key={gruppe[0].key}\n messages={gruppe}\n texts={alleTexte}\n toolArgumentsText={toolArgumentsText}\n />\n ) : (\n <StepRow\n elapsedAfter={elapsedAfter}\n expandierbar={stepsExpandable}\n key={gruppe[0].key}\n messages={gruppe}\n mitText={detailMode !== \"icons\"}\n texts={alleTexte}\n toolArgumentsText={toolArgumentsText}\n toolLabel={detailMode === \"current\" && !stepsExpandable ? alleTexte.currentTool : undefined}\n />\n ),\n gruppe[0].key,\n gruppe[0].at,\n ));\n gruppe = [];\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 schliesseGruppe();\n bloecke.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 eigeneDarstellung = message.role === \"tool\" && message.tool && detailMode !== \"current\" ? renderTool?.(message.tool) : undefined;\n if (eigeneDarstellung !== undefined) {\n schliesseGruppe();\n bloecke.push(mitZeit(\n <div className={stepClasses} key={message.key}>\n {eigeneDarstellung}\n </div>,\n message.key,\n message.at,\n ));\n return;\n }\n if ((chipModus || gruppenModus) && istSchritt(message)) {\n gruppe = [...gruppe, message];\n return;\n }\n schliesseGruppe();\n const dicht = istSchritt(message) && istSchritt(visible[index - 1]);\n bloecke.push(mitZeit(\n <Bubble\n detailMode={detailMode}\n dicht={dicht}\n elapsedAfter={elapsedAfter}\n expandierbar={stepsExpandable}\n key={message.key}\n message={message}\n plain={owner != null && message.sender === owner}\n texts={alleTexte}\n toolArgumentsText={toolArgumentsText}\n renderAction={renderAction}\n onDismissAction={onDismissAction}\n bubbleOptions={bubbleOptions}\n messageActions={messageActions}\n />,\n message.key,\n message.at,\n dicht,\n ));\n });\n schliesseGruppe();\n\n const verlauf = (\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={alleTexte.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={pruefeEnde}\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 scrollBereich.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 {bloecke}\n {running && (working ?? <WorkingScenes label={alleTexte.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={alleTexte.jumpToEnd} className=\"qsl:pointer-events-auto qsl:rounded-full qsl:border qsl:border-primary-foreground/20 qsl:shadow-md\" size=\"icon\" title={alleTexte.jumpToEnd} variant=\"default\" onClick={() => {\n if (scrollBereich.current) {\n scroll.jump(scrollBereich.current);\n updateJumpVisibility(scrollBereich.current);\n }\n }}>\n <ChevronDownIcon />\n </Button>\n </div>\n )}\n {dock && offeneAktionen.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 {offeneAktionen.map((message) => (\n <div key={message.key}>\n <ActionContent action={message.action} onDismissAction={onDismissAction} renderAction={renderAction} text={message.text} texts={alleTexte} />\n </div>\n ))}\n </div>,\n dock,\n )}\n </div>\n );\n\n return <MarkdownLinks onLinkClick={onLinkClick}><MarkdownCodeBlocks options={codeBlockOptions} texts={alleTexte}>{verlauf}</MarkdownCodeBlocks></MarkdownLinks>;\n}\n\n/** Aufeinanderfolgende Schritte als Chips nebeneinander; bei Platzmangel bricht die Zeile um. */\nfunction StepRow({\n messages,\n mitText,\n expandierbar,\n elapsedAfter,\n texts,\n toolArgumentsText,\n toolLabel,\n}: {\n messages: Message[];\n mitText: boolean;\n expandierbar: 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 offen = expandierbar && 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 {mitText && <span className=\"qsl:min-w-0 qsl:self-baseline qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap\">{label}</span>}\n {mitText && <ToolElapsed after={elapsedAfter} className=\"qsl:flex-none qsl:self-baseline\" message={message} texts={texts} />}\n {mitText && <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, !mitText && \"qsl:p-1\", running && \"qsl:animate-fade-pulse qsl:motion-reduce:animate-none\");\n if (!expandierbar) {\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 {offen && detail && (\n <StepPopover\n message={offen}\n position={detail.position}\n texts={texts}\n toolArgumentsText={toolArgumentsText}\n onClose={() => setDetail(undefined)}\n />\n )}\n </div>\n );\n}\n\n/** Aufeinanderfolgende Schritte hinter einer Kopfzeile; aufgeklappt stehen sie als einzeilige Zeilen darunter. */\nfunction StepGroup({\n messages,\n laufenderSchritt,\n elapsedAfter,\n expandierbar,\n texts,\n toolArgumentsText,\n}: {\n messages: Message[];\n /** The step the collapsed header names while the chat runs; undefined = nothing running. */\n laufenderSchritt: Message | undefined;\n elapsedAfter: number | undefined;\n expandierbar: boolean;\n texts: ChatTexts;\n toolArgumentsText: (tool: ToolInfo) => string;\n}) {\n const [offen, setOffen] = useState(false);\n const kopf = useRef<HTMLButtonElement>(null);\n const vonUntenEingeklappt = useRef(false);\n useLayoutEffect(() => {\n if (!offen && vonUntenEingeklappt.current) {\n vonUntenEingeklappt.current = false;\n kopf.current?.scrollIntoView({ block: \"nearest\" });\n }\n }, [offen]);\n const aktiv = laufenderSchritt !== undefined;\n const fehler = messages.some((message) => message.tool?.isError);\n const anzahl = messages.length === 1 ? texts.stepGroupOne : texts.stepGroupMany.replace(\"{count}\", String(messages.length));\n const laufend = laufenderSchritt && (laufenderSchritt.role === \"thinking\" ? texts.thinkingChip : laufenderSchritt.tool?.name || laufenderSchritt.text || texts.toolChip);\n\n return (\n <div className={stepClasses} data-step=\"group\">\n <button\n aria-expanded={offen}\n className={cn(traceClasses, traceButtonClasses, \"qsl:items-center qsl:pl-1\", aktiv && \"qsl:animate-fade-pulse qsl:motion-reduce:animate-none\")}\n onClick={() => setOffen((wert) => !wert)}\n ref={kopf}\n type=\"button\"\n >\n <ChevronRightIcon className={cn(\"qsl:flex-none qsl:opacity-60 qsl:transition-transform\", offen && \"qsl:rotate-90\")} size={12} />\n <LayersIcon className={fehler ? traceErrorIconClasses : traceIconClasses} size={12} />\n <span className={cn(traceLineClasses, \"qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap\")}>\n {anzahl}\n {laufend && <span className={traceRunningClasses}>{laufend} {texts.toolRunning}</span>}\n {laufenderSchritt && <ToolElapsed after={elapsedAfter} message={laufenderSchritt} texts={texts} />}\n </span>\n </button>\n {offen && (\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} expandierbar={expandierbar} key={message.key} message={message} texts={texts} toolArgumentsText={toolArgumentsText} />\n ))}\n </div>\n )}\n {offen && 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 vonUntenEingeklappt.current = true;\n setOffen(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/** Ein Schritt als eine Zeile; mit Freigabe oeffnet ein Klick die Details im Popover. */\nfunction TraceLine({\n message,\n className,\n elapsedAfter,\n expandierbar,\n texts,\n toolArgumentsText,\n}: {\n message: Message;\n className: string;\n elapsedAfter: number | undefined;\n expandierbar: 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 zeile = cn(traceLineClasses, thinking && \"qsl:font-sans qsl:italic qsl:whitespace-pre-wrap\", \"qsl:overflow-hidden qsl:text-ellipsis qsl:whitespace-nowrap\");\n const inhalt = (\n <>\n {thinking ? (\n <SparklesIcon className={traceIconClasses} size={12} />\n ) : (\n <WrenchIcon className={tool?.isError ? traceErrorIconClasses : traceIconClasses} size={12} />\n )}\n <span className={zeile}>\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 (!expandierbar) {\n return <div className={classes} {...marks}>{inhalt}</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 {inhalt}\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 dicht,\n elapsedAfter,\n expandierbar,\n texts,\n toolArgumentsText,\n renderAction,\n onDismissAction,\n bubbleOptions,\n messageActions,\n}: {\n message: Message;\n plain: boolean;\n detailMode: DetailMode;\n dicht: boolean;\n elapsedAfter: number | undefined;\n expandierbar: 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 schritt = dicht ? denseStepClasses : stepClasses;\n\n if (message.role === \"thinking\" || (message.role === \"tool\" && message.tool)) {\n if (detailMode === \"compact\") {\n return <TraceLine className={schritt} elapsedAfter={elapsedAfter} expandierbar={expandierbar} 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 zeile = (\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, schritt)} 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\")}>{zeile}</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={schritt}>\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(schritt, \"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(schritt, \"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(schritt, \"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// Waagerechte Rollbalken bleiben sichtbar - sonst ist der Ueberlauf nicht auffindbar.\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// Die Deckstreifen verbergen den Umbruch am Rand; --qsl-scroll-cover kommt aus der umgebenden Blase.\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 // Ohne max-content schrumpft die Tabelle auf den Container und stapelt Buchstaben.\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/** Dieselbe Syntax wie der Renderer, als Klartext ohne Markup, etwa f\u00FCr Screenreader-Ansagen. */\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, fett, fettUnterstrich, kursiv, code) => link ?? fett ?? fettUnterstrich ?? kursiv ?? 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/** Die eine Stopp-Glyphe: ein gef\u00FClltes rotes Quadrat; ein Zustandssymbol tr\u00E4gt sie nie. */\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/** Jeder Stopp-Knopf sieht gleich aus: die Glyphe als Symbol, das Wort im Tooltip, rot in Ruhe und beim 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 * Die Darstellung einer wartenden Aktion ohne Beitrag ihres Eigent\u00FCmers: Titel, der Hinweis,\n * dass eine Eingabe erwartet wird, und das Verwerfen. Die Form kennt nur das Plugin.\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 SPUR = 13;\nconst GRUNDTAKT_MS = 90;\nconst SZENENWECHSEL_MS = 2600;\n\n/** Eine Zelle je Figur: Emoji und Satzzeichen teilen sich kein Raster, geschobener Text ruckelt. */\nfunction bahn(figuren: Record<number, string>, breite = SPUR): string[] {\n return Array.from({ length: breite }, (_, x) => figuren[x] ?? \" \");\n}\n\ninterface Szene {\n id: string;\n takt: number;\n laufend?: true;\n compact?: true;\n zeichne: (schritt: number) => string | string[];\n}\n\n/**\n * Kleine Szenen, in denen etwas Erkennbares passiert - der Zustand aendert sich sichtbar,\n * statt dass nur eine Figur vorbeilaeuft. Szenen mit Bewegung geben ihre Bahn als Zellen\n * zurueck, alle anderen als schlichten Text.\n */\nconst SZENEN: Szene[] = [\n {\n id: \"denken\",\n takt: 2,\n zeichne: (schritt) => {\n const takt = schritt % 10;\n if (takt >= 8) return \"\\u{1F929}\\u{1F4A1}\";\n return \"\\u{1F914}\" + \"\\u{1F4AD}\".repeat(Math.min(takt, 3));\n },\n },\n {\n // Fliegt nach rechts und zieht ihren Schweif hinterher.\n id: \"rakete\",\n takt: 2,\n laufend: true,\n zeichne: (schritt) => {\n const x = schritt % SPUR;\n return bahn({ [x - 2]: \"\u00B7\", [x - 1]: \"\\u{1F4A8}\", [x]: \"\\u{1F680}\" });\n },\n },\n {\n // Die Punkte bleiben stehen und werden einzeln gefressen.\n id: \"pacman\",\n takt: 2,\n laufend: true,\n zeichne: (schritt) => {\n const x = schritt % SPUR;\n const figuren: Record<number, string> = {};\n for (let i = x + 1; i < SPUR; i++) {\n figuren[i] = \"\u00B7\";\n }\n figuren[x] = schritt % 2 === 0 ? \"\\u{1F7E1}\" : \"\\u{1F315}\";\n return bahn(figuren);\n },\n },\n {\n // Aus einem Samen wird ein Baum, dann von vorn.\n id: \"wachsen\",\n compact: true,\n takt: 2,\n zeichne: (schritt) => {\n const stufen = [\"\\u{1F331}\", \"\\u{1F331}\", \"\\u{1F33F}\", \"\\u{1F33F}\", \"\\u{1F343}\", \"\\u{1F333}\", \"\\u{1F333}\", \"\\u{1F333}\"];\n return stufen[schritt % stufen.length];\n },\n },\n {\n // Das Ei bekommt Risse, das Kueken schluepft.\n id: \"schluepfen\",\n compact: true,\n takt: 2,\n zeichne: (schritt) => {\n const takt = schritt % 12;\n if (takt < 4) return \"\\u{1F95A}\";\n if (takt < 6) return \"\\u{1F95A}*\";\n if (takt < 9) return \"\\u{1F423}\";\n return \"\\u{1F425}\";\n },\n },\n {\n // Morse-artiges Signal, das sich zu einem OK aufloest.\n id: \"signal\",\n takt: 2,\n zeichne: (schritt) => {\n const takt = schritt % 14;\n if (takt >= 11) return \"\\u{1F4E1} OK\";\n const muster = [\"\u00B7\", \"\u00B7\u00B7\", \"\u00B7-\", \"-\u00B7\", \"\u00B7\u00B7-\", \"-\u00B7\u00B7\"];\n return \"\\u{1F4E1} \" + muster[takt % muster.length];\n },\n },\n {\n // Sanduhr: der Sand laeuft durch, dann wird gedreht.\n id: \"sanduhr\",\n takt: 2,\n zeichne: (schritt) => {\n const takt = schritt % 12;\n const koerner = \"\u00B7\".repeat(Math.max(0, 5 - Math.floor(takt / 2)));\n return (takt < 10 ? \"\u23F3\" : \"\u231B\") + \" \" + koerner;\n },\n },\n {\n // Ei, Kueken, Henne - und die legt das naechste Ei.\n id: \"huhn-kreislauf\",\n compact: true,\n takt: 3,\n zeichne: (schritt) => {\n const takt = schritt % 16;\n if (takt < 3) return \"\\u{1F95A}\";\n if (takt < 5) return \"\\u{1F95A}*\";\n if (takt < 8) return \"\\u{1F423}\";\n if (takt < 11) return \"\\u{1F424}\";\n if (takt < 14) return \"\\u{1F414}\";\n return \"\\u{1F414}\\u{1F95A}\";\n },\n },\n {\n // Hut, Funken - und das Kaninchen tuermt.\n id: \"zauberhut\",\n compact: true,\n takt: 3,\n zeichne: (schritt) => {\n const takt = schritt % 14;\n if (takt < 4) return \"\\u{1F3A9}\";\n if (takt < 7) return \"\\u{1F3A9}*\";\n if (takt < 11) return \"\\u{1F3A9}\\u{1F407}\";\n return \"\\u{1F407}\\u{1F4A8}\";\n },\n },\n {\n // Rot, Gelb, Gruen - und ab.\n id: \"ampel\",\n compact: true,\n takt: 3,\n zeichne: (schritt) => {\n const takt = schritt % 12;\n if (takt < 4) return \"\\u{1F534}\";\n if (takt < 6) return \"\\u{1F7E1}\";\n if (takt < 8) return \"\\u{1F7E2}\";\n return \"\\u{1F697}\\u{1F4A8}\";\n },\n },\n {\n // Klingeln, verschlafen, losrennen.\n id: \"wecker\",\n compact: true,\n takt: 2,\n zeichne: (schritt) => {\n const takt = schritt % 14;\n if (takt < 5) return takt % 2 === 0 ? \"\u23F0\" : \"\\u{1F514}\";\n if (takt < 8) return \"\\u{1F634}\";\n if (takt < 10) return \"\\u{1F633}\";\n return \"\\u{1F3C3}\\u{1F4A8}\";\n },\n },\n {\n // Schnecke kriecht zur Flagge - und feiert.\n id: \"schnecke\",\n takt: 4,\n zeichne: (schritt) => {\n const takt = schritt % 8;\n if (takt < 5) return bahn({ [takt]: \"\\u{1F40C}\", 4: \"\\u{1F3C1}\" }, 5);\n return bahn({ 4: \"\\u{1F389}\" }, 5);\n },\n },\n];\n\nconst COMPACT_SCENES = SZENEN.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 fuer Screenreader, Default \"Arbeitet ...\". */\n label?: string;\n}\n\n/**\n * Der Default-Working-Indikator: zufaellig rotierende Mini-Szenen. Zufaellige Reihenfolge\n * und Startphase, damit dieselben Szenen nie wie eine Schleife wirken. Ueber die\n * working-Prop von ChatMessages laesst er sich komplett ersetzen.\n */\nexport function WorkingScenes({ label = \"Arbeitet ...\", compact = false }: WorkingScenesProps) {\n const scenes = compact ? COMPACT_SCENES : SZENEN;\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 }, SZENENWECHSEL_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), GRUNDTAKT_MS);\n return () => window.clearInterval(timer);\n }, [reducedMotion]);\n\n const frame = scene.zeichne(Math.floor(frameTick / scene.takt) + (scene.laufend ? 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/** Ziel offener Aktionen: undefined = im Verlauf, null = das Dock \u00FCber der Eingabe ist noch nicht eingeh\u00E4ngt. */\nexport const ChatActionDock = createContext<HTMLElement | null | undefined>(undefined);\n", "const abstandMs = 400;\nconst hoechstensWartend = 5;\n\nlet region: HTMLElement | undefined;\nlet wartend: readonly string[] = [];\nlet laeuft = false;\n\nfunction ansageRegion(): 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 naechste(): void {\n if (wartend.length === 0) {\n laeuft = false;\n return;\n }\n if (document.visibilityState === \"hidden\") {\n document.addEventListener(\"visibilitychange\", naechste, { once: true });\n return;\n }\n const [text, ...rest] = wartend;\n wartend = rest;\n const ziel = ansageRegion();\n ziel.textContent = ziel.textContent === text ? `${text}\\u00a0` : text;\n window.setTimeout(naechste, abstandMs);\n}\n\n/** Sagt Text \u00FCber eine gemeinsame, versteckte Live-Region an: gedrosselt, und bei verstecktem Tab angehalten. */\nexport function announce(text: string): void {\n const inhalt = text.trim();\n if (!inhalt || typeof document === \"undefined\") {\n return;\n }\n wartend = [...wartend, inhalt].slice(-hoechstensWartend);\n if (laeuft) {\n return;\n }\n laeuft = true;\n ansageRegion();\n window.setTimeout(naechste, abstandMs);\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 * Verlauf mit ueberlagerter Eingabe. Der Rahmen misst die Eingabe selbst und\n * gibt dem Verlauf den noetigen Fussraum, damit kein Host Innenmasse setzen muss.\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 /** Die Eingabe; sie liegt ueber dem Verlauf, nicht darunter. */\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 wurzel = useRef<HTMLDivElement>(null);\n const eingabe = 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 = eingabe.current;\n const rahmen = wurzel.current;\n if (!element || !rahmen) {\n return;\n }\n const messen = () => {\n rahmen.style.setProperty(\"--qsl-composer-height\", `${element.offsetHeight}px`);\n rahmen.style.setProperty(\"--qsl-panel-height\", `${rahmen.offsetHeight}px`);\n };\n const beobachter = new ResizeObserver(messen);\n beobachter.observe(element);\n beobachter.observe(rahmen);\n messen();\n return () => {\n beobachter.disconnect();\n rahmen.style.removeProperty(\"--qsl-composer-height\");\n rahmen.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 wurzel.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={eingabe}>\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// Unter dieser Panel-Breite klappen mitlaufende Beschriftungen zu ihren Symbolen.\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/** Ein Toolbar-Knopf, deklarativ: Symbol, Text oder beides - plus Klick-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 steuern den Entwurf von aussen, z.B. um eine Vorlage zum Bearbeiten einzusetzen. */\nexport interface ChatInputHandle {\n /** Ersetzt den Entwurf, fokussiert die Eingabe und stellt die Schreibmarke ans Ende. */\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 * Die Eingabe-Karte: rahmenlose Textarea oben, Toolbar unter einer Haarlinie. Eigene\n * Kn\u00F6pfe kommen deklarativ \u00FCber `actions` oder frei \u00FCber die Slots links/rechts; bei\n * laufender Arbeit bleibt der Stop-Knopf sichtbar, und Tippen zeigt daneben den Senden-Knopf,\n * der zum Dazwischenfunken wird. `rows` bestimmt die Starth\u00F6he; mit `maxRows` w\u00E4chst die Textarea\n * mit dem Inhalt bis zu dieser Zeilenzahl und scrollt danach.\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 = kein Anh\u00E4ngen: weder Knopf noch Ablegen oder Einf\u00FCgen von Dateien. */\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 alleTexte = { ...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(alleTexte.attachmentsWhileBusy);\n return;\n }\n try {\n validateAttachmentSelection(attachmentsRef.current.map((entry) => entry.file), files, alleTexte);\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: alleTexte.attachmentReadFailed,\n } : item)),\n );\n }\n };\n const rootRef = useRef<HTMLDivElement>(null);\n const eingabeRef = useRef<HTMLTextAreaElement>(null);\n const autoFocusSettled = useRef(false);\n useEffect(() => {\n if (!autoFocus || autoFocusSettled.current) return;\n const input = eingabeRef.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 = eingabeRef.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 // Die Toolbar-Fassung pulsiert waehrend der Arbeit; der Host gibt nur den Radius vor.\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 = eingabeRef.current;\n element?.focus();\n if (element?.value === text) element.setSelectionRange(text.length, text.length);\n },\n focus: () => eingabeRef.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 = eingabeRef.current;\n if (element) {\n element.focus();\n element.setSelectionRange(element.value.length, element.value.length);\n }\n }, [draft, sending]);\n\n // Auto-Wachstum: Hoehe folgt dem Inhalt zwischen rows und maxRows, danach scrollt die Textarea.\n const applyAutoGrow = useCallback(() => {\n const element = eingabeRef.current;\n if (!element || inputMaxRows === undefined) {\n return;\n }\n const stil = getComputedStyle(element);\n const zeilenhoehe = Number.parseFloat(stil.lineHeight) || Number.parseFloat(stil.fontSize) * 1.4;\n const polster = Number.parseFloat(stil.paddingTop) + Number.parseFloat(stil.paddingBottom);\n const maximum = zeilenhoehe * Math.max(inputMaxRows, inputRows) + polster;\n element.style.height = \"auto\";\n const inhalt = element.scrollHeight;\n element.style.height = `${Math.min(inhalt, maximum)}px`;\n element.style.overflowY = inhalt > 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 = eingabeRef.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-Breite statt Viewport-Breite: die Chat-Spalte kann im Host beliebig schmal sein.\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 beobachter = new ResizeObserver(update);\n beobachter.observe(element);\n return () => beobachter.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, alleTexte) : 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 === eingabeRef.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 !== eingabeRef.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={alleTexte.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\">{alleTexte.attachmentPreparing}</small>}\n {entry.status === \"error\" && <small role=\"alert\">{entry.error}</small>}\n </div>\n <Button\n aria-label={fillText(alleTexte.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 eingabeRef.current?.focus();\n }}\n size=\"icon-sm\"\n title={fillText(alleTexte.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>{alleTexte.notSent} {failed.draft.slice(0, 100)}{failed.draft.length > 100 ? \" ...\" : \"\"}{failed.attachments.length > 0 ? ` ${fillText(alleTexte.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), alleTexte);\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 }}>{alleTexte.insertUnsent}</Button>\n </div>)}\n </>;\n const sendButtons = <>\n {running && onStop && !hasContent && <StopButton className=\"qsl:flex-none\" label={alleTexte.stop} onClick={onStop} size=\"icon-sm\" />}\n {(!running || !onStop || hasContent) && (\n <Button\n aria-label={alleTexte.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 ? alleTexte.sendIntoRun : alleTexte.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={alleTexte.attachFiles}\n disabled={disabled || sending}\n onClick={() => fileInput.inputRef.current?.click()}\n size=\"icon-sm\"\n title={fillText(alleTexte.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\">{alleTexte.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={alleTexte.placeholder}\n disabled={!toolbar && disabled}\n readOnly={toolbar && disabled}\n onChange={(event) => changeDraft(event.target.value)}\n onKeyDown={onKeyDown}\n placeholder={running ? alleTexte.steeringPlaceholder : alleTexte.placeholder}\n ref={eingabeRef}\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={alleTexte.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 { SparklesIcon } 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\nexport const detailModeLabel = (mode: DetailMode, texts?: Partial<ChatTexts>): string =>\n ({ ...defaultTexts, ...texts })[TEXT_KEYS[mode]];\n\n/**\n * Ein Knopf, der den Detailgrad der Denk- und Werkzeug-Schritte weiterschaltet. Die\n * Reihenfolge kommt aus `modes`, der aktuelle Wert steht als Beschriftung daneben.\n */\nexport function DetailModeSwitch({\n mode,\n onChange,\n modes = DETAIL_MODES,\n collapsible = true,\n texts,\n className,\n}: {\n mode: DetailMode;\n onChange: (mode: DetailMode) => void;\n /** Auswahl und Reihenfolge des Weiterschaltens; Default sind alle Modi. */\n modes?: readonly DetailMode[];\n /** false = die Beschriftung bleibt auch in einer schmalen Eingabe-Karte stehen. */\n collapsible?: boolean;\n texts?: Partial<ChatTexts>;\n className?: string;\n}) {\n const alleTexte = { ...defaultTexts, ...texts };\n const { Button } = useQuasselComponents();\n const aktuell = modes.indexOf(mode);\n const naechster = modes[(aktuell < 0 ? 0 : aktuell + 1) % modes.length];\n return (\n <Button\n aria-label={`${alleTexte.detailModeTitle}: ${detailModeLabel(mode, texts)}`}\n className={className}\n onClick={() => onChange(naechster)}\n size=\"sm\"\n title={`${alleTexte.detailModeTitle}: ${detailModeLabel(mode, texts)}`}\n variant=\"ghost\"\n >\n <SparklesIcon />\n <span className={collapsible ? \"qsl:in-data-[compact=true]:hidden\" : undefined}>{detailModeLabel(mode, texts)}</span>\n </Button>\n );\n}\n", "import { ClockIcon } from \"lucide-react\";\nimport { useQuasselComponents } from \"./QuasselProvider\";\nimport { type ChatTexts, defaultTexts } from \"./texts\";\n\nexport function TimestampSwitch({ showTimestamps, onChange, collapsible = true, texts, className }: {\n showTimestamps: boolean;\n onChange: (showTimestamps: boolean) => void;\n collapsible?: boolean;\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=\"sm\" title={title} variant=\"ghost\">\n <ClockIcon />\n <span className={collapsible ? \"qsl:in-data-[compact=true]:hidden\" : undefined}>{labels.timestamps}</span>\n </Button>\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
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", "CheckIcon", "CopyIcon", "useState", "jsx", "jsxs", "Button", "useState", "CopyIcon", "CheckIcon", "createContext", "createContext", "Fragment", "jsx", "jsxs", "announce", "Button", "useRef", "useState", "useContext", "useEffect", "useCallback", "useMemo", "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", "useContext", "Button", "StopButton", "Toggle", "useState", "useRef", "useLayoutEffect", "input", "useEffect", "useCallback", "XIcon", "createPortal", "SparklesIcon", "jsx", "jsxs", "Button", "SparklesIcon", "jsx", "jsxs", "Button"]
|
|
7
7
|
}
|