@djangocfg/ui-tools 2.1.383 → 2.1.384

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/ChatRoot-JVR3M3H2.mjs +5 -0
  2. package/dist/{ChatRoot-6IZFM5HM.mjs.map → ChatRoot-JVR3M3H2.mjs.map} +1 -1
  3. package/dist/ChatRoot-LXIUBOXF.cjs +14 -0
  4. package/dist/{ChatRoot-LW4XNIKP.cjs.map → ChatRoot-LXIUBOXF.cjs.map} +1 -1
  5. package/dist/{chunk-OZAU3QWD.cjs → chunk-HPK3EWBF.cjs} +8 -8
  6. package/dist/chunk-HPK3EWBF.cjs.map +1 -0
  7. package/dist/{chunk-UWVP6LCW.mjs → chunk-PEKBT75W.mjs} +8 -8
  8. package/dist/chunk-PEKBT75W.mjs.map +1 -0
  9. package/dist/index.cjs +54 -54
  10. package/dist/index.d.cts +12 -7
  11. package/dist/index.d.ts +12 -7
  12. package/dist/index.mjs +3 -3
  13. package/package.json +6 -6
  14. package/src/tools/Chat/core/audio/defaults.ts +16 -11
  15. package/src/tools/Chat/core/audio/sounds/error.ts +3 -0
  16. package/src/tools/Chat/core/audio/sounds/mention.ts +3 -0
  17. package/src/tools/Chat/core/audio/sounds/notification.ts +3 -0
  18. package/src/tools/Chat/core/audio/sounds/received.ts +3 -0
  19. package/src/tools/Chat/core/audio/sounds/sent.ts +3 -0
  20. package/src/tools/Chat/core/audio/sounds/start.ts +3 -0
  21. package/src/tools/SpeechRecognition/core/audio/defaults.ts +4 -4
  22. package/dist/ChatRoot-6IZFM5HM.mjs +0 -5
  23. package/dist/ChatRoot-LW4XNIKP.cjs +0 -14
  24. package/dist/chunk-OZAU3QWD.cjs.map +0 -1
  25. package/dist/chunk-UWVP6LCW.mjs.map +0 -1
  26. package/src/audio-assets.d.ts +0 -8
  27. package/src/tools/Chat/core/audio/sounds/error.mp3 +0 -0
  28. package/src/tools/Chat/core/audio/sounds/mention.mp3 +0 -0
  29. package/src/tools/Chat/core/audio/sounds/notification.mp3 +0 -0
  30. package/src/tools/Chat/core/audio/sounds/received.mp3 +0 -0
  31. package/src/tools/Chat/core/audio/sounds/sent.mp3 +0 -0
  32. package/src/tools/Chat/core/audio/sounds/start.mp3 +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/tools/Chat/types/labels.ts","../src/tools/Chat/config.ts","../src/tools/Chat/core/reducer.ts","../src/tools/Chat/core/ids.ts","../src/tools/Chat/core/logger.ts","../src/tools/Chat/core/markdown.ts","../src/tools/Chat/hooks/useChat.ts","../src/tools/Chat/hooks/useChatLayout.ts","../src/tools/Chat/core/audio/defaults.ts","../src/tools/Chat/hooks/useChatAudio.ts","../src/tools/Chat/context/ChatProvider.tsx","../src/tools/Chat/hooks/useAutoFocusOnStreamEnd.ts","../src/tools/Chat/utils/sanitizeDraft.ts","../src/tools/Chat/hooks/useChatComposer.ts","../src/tools/Chat/hooks/useFocusOnEmptyClick.ts","../src/tools/Chat/styles/useChatStyles.ts","../src/tools/Chat/components/Attachments.tsx","../src/tools/Chat/components/Composer.tsx","../src/tools/Chat/components/EmptyState.tsx","../src/tools/Chat/components/ErrorBanner.tsx","../src/tools/Chat/components/JumpToLatest.tsx","../src/tools/Chat/core/persona.ts","../src/tools/Chat/components/StreamingIndicator.tsx","../src/tools/Chat/components/Sources.tsx","../src/tools/Chat/components/ToolCalls.tsx","../src/tools/Chat/components/MessageActions.tsx","../src/tools/Chat/components/MessageBubble.tsx","../src/tools/Chat/components/MessageList.tsx","../src/tools/Chat/components/ChatRoot.tsx"],"names":["useCallback","useEffect","useRef","useMemo","useState","jsx","FileIcon","Composer","jsxs","cn","X","memo","ToolCallItem","RefreshCw","ActionButton","forwardRef","MessageList"],"mappings":"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","file":"chunk-UWVP6LCW.mjs","sourcesContent":["/**\n * UI label strings — i18n is the host's job. Pass overrides via\n * `ChatConfig.labels` and merge with `DEFAULT_LABELS`.\n */\n\nexport interface ChatLabels {\n send: string;\n cancel: string;\n copy: string;\n regenerate: string;\n edit: string;\n delete: string;\n retry: string;\n newChat: string;\n loadMore: string;\n jumpToLatest: string;\n attach: string;\n voice: string;\n errorGeneric: string;\n cancelledSuffix: string;\n}\n\nexport const DEFAULT_LABELS: ChatLabels = {\n send: 'Send',\n cancel: 'Stop',\n copy: 'Copy',\n regenerate: 'Regenerate',\n edit: 'Edit',\n delete: 'Delete',\n retry: 'Retry',\n newChat: 'New chat',\n loadMore: 'Load more',\n jumpToLatest: 'Jump to latest',\n attach: 'Attach files',\n voice: 'Voice input',\n errorGeneric: 'Something went wrong',\n cancelledSuffix: '[cancelled]',\n};\n","/**\n * Chat defaults and constants.\n */\n\nexport const STORAGE_KEYS = {\n mode: 'djc-chat-mode',\n sidebarWidth: 'djc-chat-sidebar-width',\n composerHistory: 'djc-chat-composer-history',\n} as const;\n\nexport const CSS_VARS = {\n reserve: '--djc-chat-reserve',\n} as const;\n\nexport const DEFAULT_Z_INDEX = 9000;\n\nexport const LIMITS = {\n /** Max characters per single message. */\n messageMaxLength: 8000,\n /** Max attachments per message. */\n attachmentsMax: 10,\n /** Composer history slots. */\n composerHistorySize: 50,\n /** Coalesce stream tokens within this window before dispatching. */\n streamCoalesceMs: 16,\n /** Default history page size. */\n pageSize: 50,\n /** Virtualize list when >= this many messages (host-controlled threshold). */\n virtualizeThreshold: 50,\n /** SSE idle timeout. */\n sseIdleMs: 45_000,\n} as const;\n\nexport const DEFAULT_SIDEBAR = {\n width: 420,\n min: 320,\n max: 720,\n} as const;\n\nexport const HOTKEYS = {\n send: 'mod+enter',\n cancel: 'esc',\n newChat: 'mod+shift+n',\n toggleOpen: 'mod+/',\n focusComposer: 'mod+l',\n} as const;\n\nexport const CHAT_EVENT_NAME = 'djc:chat:send';\n\nexport interface ChatEventDetail {\n content: string;\n sessionId?: string;\n attachments?: unknown[];\n metadata?: Record<string, unknown>;\n}\n","/**\n * Pure chat state machine. Zero React. Zero I/O.\n *\n * Invariants:\n * - At most one message has `isStreaming === true` at any time. It is always\n * the last message in the array.\n * - Messages are immutable; updates produce new objects.\n * - `version` bumps on edit so memo keys invalidate.\n */\n\nimport type { ChatAttachment, ChatMessage, ChatSource, ChatToolCall } from '../types';\n\nexport interface ChatState {\n sessionId: string | null;\n messages: ChatMessage[];\n /** Initial history load in flight. */\n isLoading: boolean;\n /** Assistant is generating a reply. */\n isStreaming: boolean;\n /** Older history page in flight. */\n isLoadingMore: boolean;\n hasMore: boolean;\n oldestCursor: string | null;\n error: string | null;\n}\n\nexport const initialState: ChatState = {\n sessionId: null,\n messages: [],\n isLoading: false,\n isStreaming: false,\n isLoadingMore: false,\n hasMore: true,\n oldestCursor: null,\n error: null,\n};\n\nexport type ChatAction =\n | {\n type: 'SESSION_SET';\n sessionId: string;\n messages?: ChatMessage[];\n hasMore?: boolean;\n cursor?: string | null;\n }\n | { type: 'HISTORY_LOAD_START' }\n | {\n type: 'HISTORY_LOAD_DONE';\n messages: ChatMessage[];\n hasMore: boolean;\n cursor: string | null;\n }\n | { type: 'HISTORY_MORE_START' }\n | {\n type: 'HISTORY_MORE_DONE';\n messages: ChatMessage[];\n hasMore: boolean;\n cursor: string | null;\n }\n | { type: 'MESSAGE_USER_ADD'; message: ChatMessage }\n | { type: 'STREAM_START'; id: string; createdAt?: number }\n | { type: 'STREAM_CHUNK'; delta: string }\n | { type: 'STREAM_TOOL_ACTIVITY'; tool: string }\n | { type: 'TOOL_CALL_START'; messageId: string; toolCall: ChatToolCall }\n | { type: 'TOOL_CALL_DELTA'; messageId: string; toolId: string; delta: string }\n | {\n type: 'TOOL_CALL_END';\n messageId: string;\n toolId: string;\n output: unknown;\n status: 'success' | 'error';\n }\n | {\n type: 'STREAM_DONE';\n id: string;\n tokensIn?: number;\n tokensOut?: number;\n sources?: ChatSource[];\n }\n | { type: 'STREAM_CANCELLED'; id: string; partialText: string; label?: string }\n | { type: 'STREAM_ERROR'; id?: string; message: string }\n | { type: 'STREAM_CANCEL_PLACEHOLDER'; id: string }\n | { type: 'STREAM_RESUME_EXISTING' }\n | { type: 'MESSAGE_EDIT'; id: string; content: string }\n | { type: 'MESSAGE_DELETE'; id: string }\n | { type: 'MESSAGE_INJECT'; message: ChatMessage; position?: 'append' | 'prepend' }\n | { type: 'MESSAGE_PATCH'; id: string; patch: Partial<ChatMessage> }\n | { type: 'MESSAGES_CLEAR' }\n | { type: 'ERROR_SET'; error: string | null }\n | {\n type: 'ATTACHMENT_PROGRESS';\n messageId: string;\n attachmentId: string;\n progress?: number;\n status?: ChatAttachment['status'];\n };\n\nfunction updateLastStreaming(\n messages: ChatMessage[],\n patch: (m: ChatMessage) => ChatMessage,\n): ChatMessage[] {\n const idx = findLastStreamingIndex(messages);\n if (idx === -1) return messages;\n const next = messages.slice();\n next[idx] = patch(messages[idx]);\n return next;\n}\n\nfunction findLastStreamingIndex(messages: ChatMessage[]): number {\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n if (messages[i].isStreaming) return i;\n }\n return -1;\n}\n\nfunction patchMessageById(\n messages: ChatMessage[],\n id: string,\n patch: (m: ChatMessage) => ChatMessage,\n): ChatMessage[] {\n const idx = messages.findIndex((m) => m.id === id);\n if (idx === -1) return messages;\n const next = messages.slice();\n next[idx] = patch(messages[idx]);\n return next;\n}\n\nexport function reducer(state: ChatState, action: ChatAction): ChatState {\n switch (action.type) {\n case 'SESSION_SET':\n return {\n ...state,\n sessionId: action.sessionId,\n messages: action.messages ?? state.messages,\n hasMore: action.hasMore ?? state.hasMore,\n oldestCursor: action.cursor ?? state.oldestCursor,\n error: null,\n };\n\n case 'HISTORY_LOAD_START':\n return { ...state, isLoading: true, error: null };\n\n case 'HISTORY_LOAD_DONE':\n return {\n ...state,\n isLoading: false,\n messages: action.messages,\n hasMore: action.hasMore,\n oldestCursor: action.cursor,\n };\n\n case 'HISTORY_MORE_START':\n return { ...state, isLoadingMore: true };\n\n case 'HISTORY_MORE_DONE':\n return {\n ...state,\n isLoadingMore: false,\n // Older messages prepend to the top.\n messages: [...action.messages, ...state.messages],\n hasMore: action.hasMore,\n oldestCursor: action.cursor,\n };\n\n case 'MESSAGE_USER_ADD':\n return {\n ...state,\n messages: [...state.messages, action.message],\n error: null,\n };\n\n case 'STREAM_START': {\n if (state.isStreaming) {\n if (typeof console !== 'undefined') {\n // eslint-disable-next-line no-console\n console.warn('[chat] STREAM_START while already streaming, ignoring');\n }\n return state;\n }\n const placeholder: ChatMessage = {\n id: action.id,\n role: 'assistant',\n content: '',\n createdAt: action.createdAt ?? Date.now(),\n isStreaming: true,\n };\n return {\n ...state,\n isStreaming: true,\n messages: [...state.messages, placeholder],\n };\n }\n\n case 'STREAM_CHUNK': {\n const messages = updateLastStreaming(state.messages, (m) => ({\n ...m,\n content: m.content + action.delta,\n }));\n return { ...state, messages };\n }\n\n case 'STREAM_TOOL_ACTIVITY': {\n const messages = updateLastStreaming(state.messages, (m) => ({\n ...m,\n toolActivity: action.tool,\n }));\n return { ...state, messages };\n }\n\n case 'TOOL_CALL_START': {\n const messages = patchMessageById(state.messages, action.messageId, (m) => ({\n ...m,\n toolCalls: [...(m.toolCalls ?? []), action.toolCall],\n }));\n return { ...state, messages };\n }\n\n case 'TOOL_CALL_DELTA': {\n const messages = patchMessageById(state.messages, action.messageId, (m) => {\n if (!m.toolCalls) return m;\n return {\n ...m,\n toolCalls: m.toolCalls.map((tc) =>\n tc.id === action.toolId\n ? { ...tc, streamingText: (tc.streamingText ?? '') + action.delta }\n : tc,\n ),\n };\n });\n return { ...state, messages };\n }\n\n case 'TOOL_CALL_END': {\n const messages = patchMessageById(state.messages, action.messageId, (m) => {\n if (!m.toolCalls) return m;\n return {\n ...m,\n toolCalls: m.toolCalls.map((tc) =>\n tc.id === action.toolId\n ? {\n ...tc,\n output: action.output,\n status: action.status,\n streamingText: undefined,\n endedAt: Date.now(),\n }\n : tc,\n ),\n };\n });\n return { ...state, messages };\n }\n\n case 'STREAM_DONE': {\n const patched = patchMessageById(state.messages, action.id, (m) => ({\n ...m,\n isStreaming: false,\n tokensIn: action.tokensIn ?? m.tokensIn,\n tokensOut: action.tokensOut ?? m.tokensOut,\n sources: action.sources ?? m.sources,\n }));\n // Drop an assistant message that ended up completely empty (no text, no\n // tool calls). This happens in the HITL approval flow: the first stream\n // produces only tool calls + approval_required and no text body, so the\n // placeholder should not leave a blank bubble in the chat.\n const msg = patched.find((m) => m.id === action.id);\n const messages =\n msg && !msg.content && !(msg.toolCalls?.length)\n ? patched.filter((m) => m.id !== action.id)\n : patched;\n return { ...state, isStreaming: false, messages };\n }\n\n case 'STREAM_CANCELLED': {\n const suffix = action.label ?? '[cancelled]';\n const messages = patchMessageById(state.messages, action.id, (m) => ({\n ...m,\n isStreaming: false,\n content: action.partialText + (action.partialText ? `\\n\\n_${suffix}_` : `_${suffix}_`),\n }));\n return { ...state, isStreaming: false, messages };\n }\n\n case 'STREAM_ERROR': {\n const messages = action.id\n ? patchMessageById(state.messages, action.id, (m) => ({\n ...m,\n isStreaming: false,\n isError: true,\n }))\n : state.messages;\n return { ...state, isStreaming: false, error: action.message, messages };\n }\n\n case 'STREAM_CANCEL_PLACEHOLDER':\n // Remove the freshly-created empty assistant placeholder (resume path).\n return {\n ...state,\n isStreaming: false,\n messages: state.messages.filter((m) => m.id !== action.id),\n };\n\n case 'STREAM_RESUME_EXISTING': {\n // Mark the last assistant message as streaming so resume chunks append to it.\n const lastIdx = (() => {\n for (let i = state.messages.length - 1; i >= 0; i--) {\n if (state.messages[i].role === 'assistant') return i;\n }\n return -1;\n })();\n if (lastIdx === -1) return { ...state, isStreaming: true };\n const msgs = state.messages.slice();\n msgs[lastIdx] = { ...msgs[lastIdx], isStreaming: true };\n return { ...state, isStreaming: true, messages: msgs };\n }\n\n case 'MESSAGE_EDIT': {\n const messages = patchMessageById(state.messages, action.id, (m) => ({\n ...m,\n content: action.content,\n version: (m.version ?? 0) + 1,\n }));\n return { ...state, messages };\n }\n\n case 'MESSAGE_DELETE':\n return {\n ...state,\n messages: state.messages.filter((m) => m.id !== action.id),\n };\n\n case 'MESSAGE_INJECT': {\n // De-dupe by id: if a message with this id already exists, merge\n // instead of duplicating. Avoids double-render when external code\n // re-emits the same payload (Centrifugo replay, SWR retry, …).\n const existingIdx = state.messages.findIndex((m) => m.id === action.message.id);\n if (existingIdx >= 0) {\n const messages = state.messages.slice();\n const prev = messages[existingIdx]!;\n messages[existingIdx] = {\n ...prev,\n ...action.message,\n version: (prev.version ?? 0) + 1,\n };\n return { ...state, messages };\n }\n const next =\n action.position === 'prepend'\n ? [action.message, ...state.messages]\n : [...state.messages, action.message];\n return { ...state, messages: next };\n }\n\n case 'MESSAGE_PATCH': {\n const messages = patchMessageById(state.messages, action.id, (m) => ({\n ...m,\n ...action.patch,\n version: (m.version ?? 0) + 1,\n }));\n return { ...state, messages };\n }\n\n case 'MESSAGES_CLEAR':\n return {\n ...state,\n messages: [],\n isStreaming: false,\n error: null,\n };\n\n case 'ERROR_SET':\n return { ...state, error: action.error };\n\n case 'ATTACHMENT_PROGRESS': {\n const messages = patchMessageById(state.messages, action.messageId, (m) => {\n if (!m.attachments) return m;\n return {\n ...m,\n attachments: m.attachments.map((a) =>\n a.id === action.attachmentId\n ? {\n ...a,\n progress: action.progress ?? a.progress,\n status: action.status ?? a.status,\n }\n : a,\n ),\n };\n });\n return { ...state, messages };\n }\n\n default: {\n // Exhaustiveness check.\n const _exhaustive: never = action;\n void _exhaustive;\n return state;\n }\n }\n}\n","/**\n * ID generation. Uses crypto.randomUUID when available with a fallback\n * for older environments (and SSR bundles that may not have crypto).\n */\n\nlet counter = 0;\n\nexport function createId(prefix = 'm'): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return `${prefix}_${crypto.randomUUID()}`;\n }\n counter += 1;\n return `${prefix}_${Date.now().toString(36)}_${counter.toString(36)}_${Math.random()\n .toString(36)\n .slice(2, 8)}`;\n}\n","/**\n * Chat dev logger.\n *\n * A thin namespaced wrapper over `consola` that no-ops in production unless\n * the host app explicitly opts in via `<ChatRoot debug />`. The default\n * detection uses `isDev` from `@djangocfg/ui-core/lib/env` (NODE_ENV).\n *\n * Why a dedicated module: chat is async and event-heavy (bootstrap, transport,\n * SSE chunks, tool calls, regenerate, …). Inline `console.log`s rot fast and\n * leak into prod. A single `getChatLogger()` call gives every layer the same\n * namespaced sub-logger and keeps zero-cost gating in one place.\n *\n * Sub-loggers:\n * bootstrap — initial session bootstrap (createSession / loadHistory)\n * transport — outbound transport calls + responses\n * stream — SSE chunk / tool / message_end events\n * lifecycle — sendMessage, regenerate, newSession, edits\n * tools — tool_call_start / _delta / _end specifics\n * error — caught errors (always emitted as `error` level)\n */\nimport { consola, type ConsolaInstance } from 'consola';\n\nimport { isDev } from '@djangocfg/ui-core/lib';\n\nexport type ChatLogScope = 'bootstrap' | 'transport' | 'stream' | 'lifecycle' | 'tools' | 'error';\n\nexport interface ChatLogger {\n bootstrap: ConsolaInstance;\n transport: ConsolaInstance;\n stream: ConsolaInstance;\n lifecycle: ConsolaInstance;\n tools: ConsolaInstance;\n error: ConsolaInstance;\n /** True when this logger is actually emitting (host opted in or NODE_ENV=development). */\n enabled: boolean;\n}\n\nconst SCOPES: ChatLogScope[] = ['bootstrap', 'transport', 'stream', 'lifecycle', 'tools', 'error'];\n\n/** Module-level cache so all hooks/components share the same logger instance per `enabled` mode. */\nconst cache = new Map<boolean, ChatLogger>();\n\nfunction buildLogger(enabled: boolean): ChatLogger {\n const root = consola.withTag('chat');\n const subs = Object.fromEntries(\n SCOPES.map((scope) => [scope, root.withTag(scope)]),\n ) as Record<ChatLogScope, ConsolaInstance>;\n\n if (!enabled) {\n // Silence everything except `error` — surfaced errors should never go\n // missing even if the host didn't opt in to debug logs.\n for (const scope of SCOPES) {\n if (scope === 'error') continue;\n subs[scope].level = -999;\n }\n }\n\n return { ...subs, enabled };\n}\n\n/**\n * Get the chat logger.\n * @param debug Explicit override from the host. `undefined` falls back to `isDev`.\n */\nexport function getChatLogger(debug?: boolean): ChatLogger {\n const enabled = debug ?? isDev;\n let logger = cache.get(enabled);\n if (!logger) {\n logger = buildLogger(enabled);\n cache.set(enabled, logger);\n }\n return logger;\n}\n","/**\n * Token coalescer. Buffers stream tokens within a small time window before\n * dispatching a single aggregated chunk. Prevents 60+ re-renders per second\n * on fast streams.\n */\n\nimport { LIMITS } from '../config';\n\nexport interface TokenBuffer {\n /** Append a delta. Returns immediately. */\n push(delta: string): void;\n /** Force flush and resolve any pending timer. */\n flush(): void;\n /** Stop accepting tokens; flush whatever is buffered. */\n close(): void;\n}\n\nexport function createTokenBuffer(\n onFlush: (delta: string) => void,\n windowMs = LIMITS.streamCoalesceMs,\n): TokenBuffer {\n let pending = '';\n let timer: ReturnType<typeof setTimeout> | null = null;\n let closed = false;\n\n const flush = () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n if (pending) {\n const out = pending;\n pending = '';\n onFlush(out);\n }\n };\n\n return {\n push(delta: string) {\n if (closed || !delta) return;\n pending += delta;\n if (windowMs <= 0) {\n flush();\n return;\n }\n if (timer === null) {\n timer = setTimeout(flush, windowMs);\n }\n },\n flush,\n close() {\n closed = true;\n flush();\n },\n };\n}\n","'use client';\n\nimport { useCallback, useEffect, useReducer, useRef } from 'react';\n\nimport type {\n ChatAttachment,\n ChatMessage,\n ChatPersona,\n ChatStreamEvent,\n ChatTransport,\n ChatToolCall,\n} from '../types';\nimport { LIMITS } from '../config';\nimport {\n type ChatState,\n initialState,\n reducer,\n type ChatAction,\n} from '../core/reducer';\nimport { createId } from '../core/ids';\nimport { getChatLogger } from '../core/logger';\nimport { createTokenBuffer } from '../core/markdown';\n\nexport interface UseChatConfig {\n transport: ChatTransport;\n initialSessionId?: string;\n autoCreateSession?: boolean;\n streaming?: boolean;\n pageSize?: number;\n onError?: (err: Error) => void;\n /** Fires once an assistant message finishes streaming (or buffered send returns). */\n onMessageEnd?: (msg: ChatMessage) => void;\n /** Fires after a user message is added to the state (right before streaming starts). */\n onMessageSent?: (msg: ChatMessage) => void;\n /** Fires when the assistant placeholder is created (first byte / pre-stream). */\n onStreamStart?: (assistantMessageId: string) => void;\n metadata?: Record<string, unknown>;\n /** Stamped on outgoing user messages as `message.sender`. */\n userPersona?: ChatPersona;\n /**\n * Rewrite the outgoing message content right before it hits the\n * transport — runs after the user bubble is added (so history shows\n * the original) but before `transport.stream/send`. Sync or async.\n * Return the original to opt out for that call.\n *\n * Use case: strip rich-display chips (e.g. mention links) so the LLM\n * sees plain text, while the bubble keeps the chip rendering. Plan64.\n */\n onBeforeSend?: (content: string) => string | Promise<string>;\n /**\n * Enable verbose dev-mode logging (consola, namespace `chat:*`).\n * Defaults to `isDev` from `@djangocfg/ui-core/lib`. Pass `false` to silence\n * even in development; `true` to force on in production.\n */\n debug?: boolean;\n}\n\nexport interface UseChatReturn extends ChatState {\n sendMessage: (content: string, attachments?: ChatAttachment[]) => Promise<void>;\n cancelStream: () => void;\n regenerate: (messageId?: string) => Promise<void>;\n editMessage: (id: string, content: string) => Promise<void>;\n deleteMessage: (id: string) => void;\n clearMessages: () => void;\n loadMore: () => Promise<void>;\n newSession: () => Promise<void>;\n lastError: Error | null;\n /**\n * Inject a complete message from outside (push notification, admin\n * takeover, system notice). De-duped by id. Position defaults to\n * `append` — pass `prepend` for retroactive inserts.\n */\n injectMessage: (message: ChatMessage, position?: 'append' | 'prepend') => void;\n /**\n * Patch fields of an existing message in place (e.g. live-edit the\n * admin's last reply, mark a message as resolved). No-op if the id\n * doesn't exist.\n */\n updateMessage: (id: string, patch: Partial<ChatMessage>) => void;\n}\n\nexport function useChat(config: UseChatConfig): UseChatReturn {\n const [state, dispatch] = useReducer(reducer, initialState);\n const stateRef = useRef(state);\n stateRef.current = state;\n\n const abortRef = useRef<AbortController | null>(null);\n const lastErrorRef = useRef<Error | null>(null);\n const streamingMsgIdRef = useRef<string | null>(null);\n // Promise resolved once the initial session is available (or `null` when the\n // bootstrap finished without producing one — e.g. autoCreateSession=false).\n // Action methods (sendMessage, regenerate, …) await this so users who type\n // before the first network round-trip resolves don't hit \"No active session\".\n const bootstrapRef = useRef<Promise<string | null> | null>(null);\n\n const { transport, autoCreateSession = true, streaming = true, pageSize = LIMITS.pageSize } =\n config;\n const log = getChatLogger(config.debug);\n\n // Initial session bootstrap.\n //\n // Strict Mode quirk: this effect runs twice in dev (mount → unmount → mount).\n // Previous design used `initRef` to skip the second run, but the first run's\n // cleanup sets `cancelled = true`, so its dispatch never lands — and the\n // second run was blocked. Result: bootstrap silently completed the network\n // call but never wrote sessionId to state.\n //\n // Fix: drop `initRef`. On the second mount we DO re-run, but `bootstrapRef`\n // is preserved across renders so we don't re-fetch if a previous run already\n // succeeded — we just resolve from existing state.\n useEffect(() => {\n let cancelled = false;\n\n // If a prior run already produced a sessionId, skip.\n if (stateRef.current.sessionId) {\n return;\n }\n\n // Show \"loading\" state immediately so the UI doesn't look idle while we\n // wait for createSession / loadHistory to come back.\n if (config.initialSessionId || autoCreateSession) {\n dispatch({ type: 'HISTORY_LOAD_START' });\n }\n\n log.bootstrap.info('start', {\n mode: config.initialSessionId ? 'resume' : autoCreateSession ? 'create' : 'idle',\n initialSessionId: config.initialSessionId,\n });\n\n const run = async (): Promise<string | null> => {\n const t0 = performance.now();\n try {\n if (config.initialSessionId) {\n if (!cancelled) {\n dispatch({\n type: 'SESSION_SET',\n sessionId: config.initialSessionId,\n });\n }\n const page = await transport.loadHistory(config.initialSessionId, null, pageSize);\n if (cancelled) {\n log.bootstrap.debug('cancelled (post-loadHistory)');\n // Even though *this* effect is cancelled, the network call did\n // succeed — return the sessionId so awaitSession() doesn't see\n // a phantom null when the next mount picks up.\n return config.initialSessionId;\n }\n dispatch({\n type: 'HISTORY_LOAD_DONE',\n messages: page.messages,\n hasMore: page.hasMore,\n cursor: page.nextCursor,\n });\n log.bootstrap.success('resumed', {\n sessionId: config.initialSessionId,\n messages: page.messages.length,\n hasMore: page.hasMore,\n elapsedMs: Math.round(performance.now() - t0),\n });\n return config.initialSessionId;\n }\n if (autoCreateSession) {\n const info = await transport.createSession({ metadata: config.metadata });\n // We always commit the session to state even if this effect was\n // cancelled — the network call already succeeded, throwing away the\n // sessionId would just trigger a duplicate createSession on remount.\n dispatch({\n type: 'SESSION_SET',\n sessionId: info.sessionId,\n messages: info.messages ?? [],\n hasMore: info.hasMore ?? false,\n cursor: info.cursor ?? null,\n });\n dispatch({\n type: 'HISTORY_LOAD_DONE',\n messages: info.messages ?? [],\n hasMore: info.hasMore ?? false,\n cursor: info.cursor ?? null,\n });\n log.bootstrap.success(cancelled ? 'created (post-cancel)' : 'created', {\n sessionId: info.sessionId,\n resumed: info.resumed ?? false,\n cancelled,\n elapsedMs: Math.round(performance.now() - t0),\n });\n return info.sessionId;\n }\n log.bootstrap.debug('idle (no initialSessionId, autoCreateSession=false)');\n return null;\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n if (cancelled) {\n log.bootstrap.debug('cancelled (in catch)', { message: e.message });\n return null;\n }\n lastErrorRef.current = e;\n dispatch({ type: 'ERROR_SET', error: e.message });\n config.onError?.(e);\n log.error.error('bootstrap failed', { message: e.message, elapsedMs: Math.round(performance.now() - t0) });\n return null;\n }\n };\n bootstrapRef.current = run();\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n /** Wait for the initial session bootstrap to settle, then return whatever\n * sessionId is now in state. Safe to call multiple times. */\n const awaitSession = useCallback(async (): Promise<string | null> => {\n if (stateRef.current.sessionId) return stateRef.current.sessionId;\n if (bootstrapRef.current) {\n const id = await bootstrapRef.current;\n if (id) return id;\n }\n return stateRef.current.sessionId;\n }, []);\n\n const consumeStream = useCallback(\n async (\n sessionId: string,\n content: string,\n attachments?: ChatAttachment[],\n ): Promise<void> => {\n const ctrl = new AbortController();\n abortRef.current = ctrl;\n const assistantId = createId('a');\n streamingMsgIdRef.current = assistantId;\n\n const iterator = transport.stream(sessionId, content, {\n signal: ctrl.signal,\n attachments,\n metadata: config.metadata,\n });\n\n // Peek at the first event — if it's `resume_start` we reuse the last assistant\n // message instead of creating a new empty placeholder. The peek happens inside\n // the try/catch so any transport error (network, 401, etc.) is handled normally.\n let peekedEvent: ChatStreamEvent | null = null;\n\n dispatch({ type: 'STREAM_START', id: assistantId });\n config.onStreamStart?.(assistantId);\n log.stream.info('start', { sessionId, assistantId, chars: content.length });\n\n const tokenBuffer = createTokenBuffer((delta) =>\n dispatch({ type: 'STREAM_CHUNK', delta }),\n );\n\n let serverMessageId: string | null = null;\n let chunkCount = 0;\n let charsReceived = 0;\n const t0 = performance.now();\n\n try {\n // Peek first event to detect resume_start — must be inside try/catch so\n // transport errors (network down, 401) are caught and shown as error banners.\n const firstResult = await iterator.next();\n if (!firstResult.done) {\n const ev = firstResult.value as ChatStreamEvent;\n if (ev.type === 'resume_start') {\n // Switch existing placeholder to continueExisting mode: remove the\n // just-created empty placeholder and mark the last assistant msg streaming.\n dispatch({ type: 'STREAM_CANCEL_PLACEHOLDER', id: assistantId });\n dispatch({ type: 'STREAM_RESUME_EXISTING' });\n } else {\n peekedEvent = ev;\n }\n }\n\n if (peekedEvent) handleEvent(peekedEvent);\n\n for await (const ev of iterator) {\n if (ctrl.signal.aborted) break;\n handleEvent(ev);\n }\n tokenBuffer.flush();\n\n // If transport never emitted message_end, finalize manually.\n if (stateRef.current.isStreaming) {\n dispatch({ type: 'STREAM_DONE', id: assistantId });\n }\n\n const finalMsg = stateRef.current.messages.find((m) => m.id === assistantId);\n if (finalMsg) config.onMessageEnd?.(finalMsg);\n log.stream.success('done', {\n assistantId,\n chunks: chunkCount,\n chars: charsReceived,\n elapsedMs: Math.round(performance.now() - t0),\n });\n } catch (err) {\n tokenBuffer.close();\n if (ctrl.signal.aborted) {\n const partial =\n stateRef.current.messages.find((m) => m.id === assistantId)?.content ?? '';\n dispatch({ type: 'STREAM_CANCELLED', id: assistantId, partialText: partial });\n log.stream.warn('cancelled', { assistantId, partialChars: partial.length });\n return;\n }\n const e = err instanceof Error ? err : new Error(String(err));\n lastErrorRef.current = e;\n dispatch({ type: 'STREAM_ERROR', id: assistantId, message: e.message });\n config.onError?.(e);\n log.error.error('stream failed', { assistantId, message: e.message });\n } finally {\n tokenBuffer.close();\n if (abortRef.current === ctrl) abortRef.current = null;\n streamingMsgIdRef.current = null;\n }\n\n function handleEvent(ev: ChatStreamEvent) {\n switch (ev.type) {\n case 'message_start':\n serverMessageId = ev.messageId;\n log.stream.debug('message_start', { messageId: ev.messageId });\n return;\n case 'chunk':\n tokenBuffer.push(ev.delta);\n chunkCount += 1;\n charsReceived += ev.delta.length;\n return;\n case 'tool_activity':\n tokenBuffer.flush();\n dispatch({ type: 'STREAM_TOOL_ACTIVITY', tool: ev.tool });\n log.tools.debug('activity', { tool: ev.tool, status: ev.status });\n return;\n case 'tool_call_start': {\n tokenBuffer.flush();\n const toolCall: ChatToolCall = {\n id: ev.toolId,\n name: ev.name,\n input: ev.input,\n status: 'running',\n startedAt: Date.now(),\n sourceHostname: ev.sourceHostname,\n };\n dispatch({\n type: 'TOOL_CALL_START',\n messageId: assistantId,\n toolCall,\n });\n log.tools.info('call_start', { toolId: ev.toolId, name: ev.name });\n return;\n }\n case 'tool_call_delta':\n dispatch({\n type: 'TOOL_CALL_DELTA',\n messageId: assistantId,\n toolId: ev.toolId,\n delta: ev.delta,\n });\n return;\n case 'tool_call_end':\n dispatch({\n type: 'TOOL_CALL_END',\n messageId: assistantId,\n toolId: ev.toolId,\n output: ev.output,\n status: ev.status,\n });\n log.tools.info('call_end', { toolId: ev.toolId, status: ev.status });\n return;\n case 'message_end':\n tokenBuffer.flush();\n dispatch({\n type: 'STREAM_DONE',\n id: assistantId,\n tokensIn: ev.tokensIn,\n tokensOut: ev.tokensOut,\n sources: ev.sources,\n });\n log.stream.debug('message_end', {\n tokensIn: ev.tokensIn,\n tokensOut: ev.tokensOut,\n sources: ev.sources?.length ?? 0,\n });\n return;\n case 'error':\n tokenBuffer.flush();\n dispatch({\n type: 'STREAM_ERROR',\n id: assistantId,\n message: ev.message,\n });\n log.error.error('stream event error', { code: ev.code, message: ev.message });\n return;\n }\n // unreachable; prevents unused-var on serverMessageId\n void serverMessageId;\n }\n },\n [transport, config],\n );\n\n const consumeBuffered = useCallback(\n async (sessionId: string, content: string, attachments?: ChatAttachment[]): Promise<void> => {\n const ctrl = new AbortController();\n abortRef.current = ctrl;\n try {\n const reply = await transport.send(sessionId, content, {\n signal: ctrl.signal,\n attachments,\n metadata: config.metadata,\n });\n const placeholderId = createId('a');\n dispatch({ type: 'STREAM_START', id: placeholderId });\n config.onStreamStart?.(placeholderId);\n dispatch({ type: 'STREAM_CHUNK', delta: reply.content });\n dispatch({ type: 'STREAM_DONE', id: placeholderId });\n config.onMessageEnd?.(reply);\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n lastErrorRef.current = e;\n dispatch({ type: 'STREAM_ERROR', message: e.message });\n config.onError?.(e);\n } finally {\n if (abortRef.current === ctrl) abortRef.current = null;\n }\n },\n [transport, config],\n );\n\n const sendMessage = useCallback(\n async (content: string, attachments?: ChatAttachment[]) => {\n // Wait for the initial session bootstrap if it's still in flight.\n // Without this, fast typers hit \"No active session\" before\n // transport.createSession resolves.\n log.lifecycle.info('sendMessage', {\n chars: content.length,\n attachments: attachments?.length ?? 0,\n hasSession: !!stateRef.current.sessionId,\n });\n const sessionId = await awaitSession();\n if (!sessionId) {\n const e = new Error('No active session');\n lastErrorRef.current = e;\n dispatch({ type: 'ERROR_SET', error: e.message });\n config.onError?.(e);\n log.error.error('sendMessage aborted: no session');\n return;\n }\n if (!content.trim() && !(attachments && attachments.length > 0)) {\n log.lifecycle.debug('sendMessage skipped (empty)');\n return;\n }\n if (stateRef.current.isStreaming) {\n log.lifecycle.debug('sendMessage skipped (already streaming)');\n return;\n }\n\n const userMsg: ChatMessage = {\n id: createId('u'),\n role: 'user',\n content,\n createdAt: Date.now(),\n attachments,\n sender: config.userPersona,\n };\n dispatch({ type: 'MESSAGE_USER_ADD', message: userMsg });\n config.onMessageSent?.(userMsg);\n\n // History bubble shows the original; transport sees the rewrite.\n // Use case: strip rich-display chips so the LLM sees plain text.\n let outbound = content;\n if (config.onBeforeSend) {\n try {\n outbound = await config.onBeforeSend(content);\n } catch (err) {\n log.error.error('onBeforeSend threw — falling back to original content', err);\n }\n }\n\n if (streaming) {\n await consumeStream(sessionId, outbound, attachments);\n } else {\n await consumeBuffered(sessionId, outbound, attachments);\n }\n },\n [streaming, consumeStream, consumeBuffered, config, awaitSession, log],\n );\n\n const cancelStream = useCallback(() => {\n abortRef.current?.abort();\n }, []);\n\n const regenerate = useCallback(\n async (messageId?: string) => {\n log.lifecycle.info('regenerate', { messageId: messageId ?? '(last)' });\n const messages = stateRef.current.messages;\n let targetUserIdx = -1;\n if (messageId) {\n const idx = messages.findIndex((m) => m.id === messageId);\n if (idx !== -1) {\n targetUserIdx =\n messages[idx].role === 'user' ? idx : findPreviousUserIndex(messages, idx);\n }\n } else {\n targetUserIdx = findLastUserIndex(messages);\n }\n if (targetUserIdx === -1) return;\n const userMsg = messages[targetUserIdx];\n // Drop everything after this user message.\n for (let i = messages.length - 1; i > targetUserIdx; i -= 1) {\n dispatch({ type: 'MESSAGE_DELETE', id: messages[i].id });\n }\n const sessionId = await awaitSession();\n if (!sessionId) return;\n if (streaming) {\n await consumeStream(sessionId, userMsg.content, userMsg.attachments);\n } else {\n await consumeBuffered(sessionId, userMsg.content, userMsg.attachments);\n }\n },\n [streaming, consumeStream, consumeBuffered, awaitSession],\n );\n\n const editMessage = useCallback(\n async (id: string, content: string) => {\n dispatch({ type: 'MESSAGE_EDIT', id, content });\n const msg = stateRef.current.messages.find((m) => m.id === id);\n if (msg?.role === 'user') {\n await regenerate(id);\n }\n },\n [regenerate],\n );\n\n const deleteMessage = useCallback((id: string) => {\n dispatch({ type: 'MESSAGE_DELETE', id });\n }, []);\n\n const injectMessage = useCallback(\n (message: ChatMessage, position?: 'append' | 'prepend') => {\n dispatch({ type: 'MESSAGE_INJECT', message, position });\n },\n [],\n );\n\n const updateMessage = useCallback(\n (id: string, patch: Partial<ChatMessage>) => {\n dispatch({ type: 'MESSAGE_PATCH', id, patch });\n },\n [],\n );\n\n const clearMessages = useCallback(() => {\n abortRef.current?.abort();\n dispatch({ type: 'MESSAGES_CLEAR' });\n }, []);\n\n const loadMore = useCallback(async () => {\n const sessionId = stateRef.current.sessionId;\n if (!sessionId) return;\n if (stateRef.current.isLoadingMore || !stateRef.current.hasMore) return;\n dispatch({ type: 'HISTORY_MORE_START' });\n try {\n const page = await transport.loadHistory(\n sessionId,\n stateRef.current.oldestCursor,\n pageSize,\n );\n dispatch({\n type: 'HISTORY_MORE_DONE',\n messages: page.messages,\n hasMore: page.hasMore,\n cursor: page.nextCursor,\n });\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n lastErrorRef.current = e;\n dispatch({ type: 'ERROR_SET', error: e.message });\n config.onError?.(e);\n }\n }, [transport, pageSize, config]);\n\n const newSession = useCallback(async () => {\n log.lifecycle.info('newSession', { previous: stateRef.current.sessionId });\n abortRef.current?.abort();\n const previous = stateRef.current.sessionId;\n if (previous) {\n try {\n await transport.closeSession(previous);\n } catch {\n /* ignore */\n }\n }\n dispatch({ type: 'MESSAGES_CLEAR' });\n try {\n const info = await transport.createSession({ metadata: config.metadata });\n dispatch({\n type: 'SESSION_SET',\n sessionId: info.sessionId,\n messages: info.messages ?? [],\n hasMore: info.hasMore ?? false,\n cursor: info.cursor ?? null,\n });\n log.lifecycle.success('newSession ok', { sessionId: info.sessionId });\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n lastErrorRef.current = e;\n dispatch({ type: 'ERROR_SET', error: e.message });\n config.onError?.(e);\n log.error.error('newSession failed', { message: e.message });\n }\n }, [transport, config]);\n\n return {\n ...state,\n sendMessage,\n cancelStream,\n regenerate,\n editMessage,\n deleteMessage,\n clearMessages,\n loadMore,\n newSession,\n lastError: lastErrorRef.current,\n injectMessage,\n updateMessage,\n };\n}\n\nfunction findLastUserIndex(messages: ChatMessage[]): number {\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n if (messages[i].role === 'user') return i;\n }\n return -1;\n}\n\nfunction findPreviousUserIndex(messages: ChatMessage[], from: number): number {\n for (let i = from - 1; i >= 0; i -= 1) {\n if (messages[i].role === 'user') return i;\n }\n return -1;\n}\n\n// Suppress unused-action warnings if the action union grows.\ntype _Used = ChatAction;\n","'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { useLocalStorage, useMediaQuery } from '@djangocfg/ui-core/hooks';\n\nimport { CSS_VARS, DEFAULT_SIDEBAR, STORAGE_KEYS } from '../config';\nimport type { ChatDisplayMode } from '../types';\n\nexport interface UseChatLayoutConfig {\n defaultMode?: ChatDisplayMode;\n storageKey?: string;\n sidebarStorageKey?: string;\n reserveCssVar?: string;\n defaultSidebarWidth?: number;\n minSidebarWidth?: number;\n maxSidebarWidth?: number;\n /** Mobile breakpoint, e.g. '(max-width: 640px)'. */\n mobileQuery?: string;\n}\n\nexport interface UseChatLayoutReturn {\n mode: ChatDisplayMode;\n setMode: (m: ChatDisplayMode) => void;\n open: () => void;\n close: () => void;\n toggle: () => void;\n sidebarWidth: number;\n setSidebarWidth: (w: number) => void;\n isMobile: boolean;\n /** Mode after mobile collapse rules — sidebar/floating become fullscreen on mobile. */\n effectiveMode: ChatDisplayMode;\n}\n\nconst DEFAULT_MOBILE_QUERY = '(max-width: 640px)';\n\nexport function useChatLayout(config: UseChatLayoutConfig = {}): UseChatLayoutReturn {\n const {\n defaultMode = 'closed',\n storageKey = STORAGE_KEYS.mode,\n sidebarStorageKey = STORAGE_KEYS.sidebarWidth,\n reserveCssVar = CSS_VARS.reserve,\n defaultSidebarWidth = DEFAULT_SIDEBAR.width,\n minSidebarWidth = DEFAULT_SIDEBAR.min,\n maxSidebarWidth = DEFAULT_SIDEBAR.max,\n mobileQuery = DEFAULT_MOBILE_QUERY,\n } = config;\n\n const [mode, setMode] = useLocalStorage<ChatDisplayMode>(storageKey, defaultMode);\n const [sidebarWidthRaw, setSidebarWidthRaw] = useLocalStorage<number>(\n sidebarStorageKey,\n defaultSidebarWidth,\n );\n const isMobile = useMediaQuery(mobileQuery);\n\n const setSidebarWidth = useCallback(\n (w: number) => {\n const clamped = Math.max(minSidebarWidth, Math.min(maxSidebarWidth, w));\n setSidebarWidthRaw(clamped);\n },\n [setSidebarWidthRaw, minSidebarWidth, maxSidebarWidth],\n );\n\n const [previousOpenMode, setPreviousOpenMode] = useState<ChatDisplayMode>(\n mode === 'closed' ? 'embedded' : mode,\n );\n useEffect(() => {\n if (mode !== 'closed') setPreviousOpenMode(mode);\n }, [mode]);\n\n const open = useCallback(() => {\n setMode(previousOpenMode === 'closed' ? 'embedded' : previousOpenMode);\n }, [setMode, previousOpenMode]);\n\n const close = useCallback(() => setMode('closed'), [setMode]);\n const toggle = useCallback(() => {\n setMode((mode === 'closed' ? previousOpenMode : 'closed') as ChatDisplayMode);\n }, [setMode, mode, previousOpenMode]);\n\n const effectiveMode = useMemo<ChatDisplayMode>(() => {\n if (mode === 'closed') return 'closed';\n if (isMobile && (mode === 'sidebar' || mode === 'floating')) return 'fullscreen';\n return mode;\n }, [mode, isMobile]);\n\n // Reserve right padding when in sidebar mode.\n useEffect(() => {\n if (typeof document === 'undefined') return;\n const root = document.documentElement;\n if (effectiveMode === 'sidebar') {\n root.style.setProperty(reserveCssVar, `${sidebarWidthRaw}px`);\n } else {\n root.style.removeProperty(reserveCssVar);\n }\n return () => {\n root.style.removeProperty(reserveCssVar);\n };\n }, [effectiveMode, sidebarWidthRaw, reserveCssVar]);\n\n return {\n mode,\n setMode,\n open,\n close,\n toggle,\n sidebarWidth: sidebarWidthRaw,\n setSidebarWidth,\n isMobile,\n effectiveMode,\n };\n}\n","/**\n * Built-in chat notification sounds.\n *\n * Bundled into the JS at build time as base64 data URLs (`tsup.config.ts`\n * loader: `.mp3 → dataurl`). Total ≈ 136KB, gzipped ≈ 130KB — added to\n * the lazy Chat tool so hosts get notification sounds with zero setup.\n *\n * Source files live in `./sounds/`. Re-encode via ffmpeg if you tweak:\n *\n * ffmpeg -i in.mp3 -ac 2 -ar 44100 -b:a 128k -af 'atrim=0:1.4,afade=t=out:st=1.22:d=0.18' out.mp3\n */\n\nimport sent from './sounds/sent.mp3';\nimport received from './sounds/received.mp3';\nimport start from './sounds/start.mp3';\nimport errorSound from './sounds/error.mp3';\nimport mention from './sounds/mention.mp3';\nimport notification from './sounds/notification.mp3';\n\nimport type { ChatAudioSounds } from './types';\n\n/**\n * Default chat notification sounds. Pass to `useChatAudio` (or spread\n * into a custom map) so hosts don't have to ship assets themselves.\n *\n * @example\n * ```tsx\n * const audio = useChatAudio({ sounds: DEFAULT_CHAT_SOUNDS });\n *\n * // Override one event:\n * const audio = useChatAudio({\n * sounds: { ...DEFAULT_CHAT_SOUNDS, mention: '/custom-mention.mp3' },\n * });\n * ```\n */\nexport const DEFAULT_CHAT_SOUNDS: ChatAudioSounds = {\n messageSent: sent,\n messageReceived: received,\n streamStart: start,\n error: errorSound,\n mention,\n notification,\n};\n","'use client';\n\nimport { useNotificationSounds } from '@djangocfg/ui-core/hooks';\n\nimport { DEFAULT_CHAT_SOUNDS } from '../core/audio/defaults';\nimport type {\n ChatAudioConfig,\n ChatAudioEvent,\n UseChatAudioReturn,\n} from '../core/audio/types';\n\nconst STORAGE_KEY = 'djangocfg-chat-audio:prefs';\n\n/**\n * Slack / Linear / Intercom-style per-event volume scale. Applied on top\n * of the master volume so error / status sounds don't startle the user\n * sitting next to a busy chat. Override per-event via\n * `config.eventVolumes`, or pass `eventVolumes: {}` to disable defaults.\n */\nconst DEFAULT_EVENT_VOLUMES: Partial<Record<ChatAudioEvent, number>> = {\n error: 0.25,\n mention: 1,\n messageSent: 0.5,\n messageReceived: 0.7,\n streamStart: 0.3,\n notification: 0.9,\n};\n\n/**\n * Chat-specific audio facade. Thin wrapper over `useNotificationSounds`\n * from `@djangocfg/ui-core` — keeps the `ChatAudioEvent` typing while\n * the underlying bus / prefs / Safari-unlock logic lives in ui-core.\n */\nexport function useChatAudio(config: ChatAudioConfig = {}): UseChatAudioReturn {\n // Auto-fallback to built-in sounds when:\n // - host hasn't passed a `sounds` map (most apps)\n // - host hasn't opted into `silenced` mode (native hosts skip this)\n // Pass `sounds: {}` explicitly to disable both defaults and embedded.\n const resolvedSounds =\n config.sounds === undefined && !config.silenced ? DEFAULT_CHAT_SOUNDS : config.sounds;\n\n const api = useNotificationSounds<ChatAudioEvent>({\n storageKey: STORAGE_KEY,\n sounds: resolvedSounds,\n volume: config.volume,\n eventVolumes: config.eventVolumes ?? DEFAULT_EVENT_VOLUMES,\n muted: config.muted,\n shouldPlay: config.shouldPlay,\n respectReducedMotion: config.respectReducedMotion,\n respectReducedData: config.respectReducedData,\n muteWhenHidden: config.muteWhenHidden,\n silenced: config.silenced,\n onSoundEvent: config.onSoundEvent,\n });\n\n return {\n play: api.play,\n preload: api.preload,\n unlock: api.unlock,\n isUnlocked: api.isUnlocked,\n muted: api.muted,\n setMuted: api.setMuted,\n toggleMute: api.toggleMute,\n volume: api.volume,\n setVolume: api.setVolume,\n isEventEnabled: api.isEventEnabled,\n setEventEnabled: api.setEventEnabled,\n isSilent: api.isSilent,\n };\n}\n","'use client';\n\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport type { ChatConfig, ChatLabels, ChatTransport } from '../types';\nimport { DEFAULT_LABELS } from '../types';\n\nimport { useChat, type UseChatReturn } from '../hooks/useChat';\nimport { useChatLayout, type UseChatLayoutReturn } from '../hooks/useChatLayout';\nimport { useChatAudio } from '../hooks/useChatAudio';\nimport type { ChatAudioConfig, UseChatAudioReturn } from '../core/audio/types';\n\n/** Imperative handle a composer (built-in or custom) registers so\n * other parts of the chat tree can drive it without prop-drilling a\n * ref. `focus()` is the baseline; the rest is optional so non-textarea\n * hosts can keep returning `{ focus }` only.\n *\n * Implemented by:\n * - built-in `<Composer>` — backed by `useChatComposer.textareaRef`.\n * - `@djangocfg/ui-tools/markdown-editor` — backed by the TipTap\n * editor (`editor.commands.focus('end')`).\n * Consumed by `VoiceComposerSlot` for the focus / move-caret behaviour\n * during live dictation.\n */\nexport interface ComposerHandle {\n focus: () => void;\n /** Move the caret to the very end of the input. */\n moveCursorToEnd?: () => void;\n /** Read the current draft text. Needed by voice dictation to anchor\n * partial transcripts onto the user's already-typed prefix. */\n getValue?: () => string;\n /** Replace the current draft text. Voice dictation uses this to push\n * interim + final transcripts into the composer without owning a\n * controlled binding. */\n setValue?: (value: string) => void;\n}\n\nexport interface ChatContextValue extends UseChatReturn {\n layout: UseChatLayoutReturn;\n config: ChatConfig;\n labels: ChatLabels;\n audio: UseChatAudioReturn;\n /** True iff the host wired at least one ``audio.sounds[event]`` URL.\n * Components like ``AudioToggle`` use this to auto-hide when there\n * is nothing to mute. */\n hasAudio: boolean;\n /** Composer registry. The built-in `<Composer>` calls\n * `registerComposer({ focus })` on mount; custom composers (e.g.\n * cmdop's MarkdownEditor wrapper) do the same via the\n * `useRegisterComposer` helper. Read it via `composer?.focus()` —\n * null until any composer has mounted. Plan64 follow-up. */\n composer: ComposerHandle | null;\n registerComposer: (handle: ComposerHandle | null) => void;\n}\n\nconst Ctx = createContext<ChatContextValue | null>(null);\n\nexport interface ChatProviderProps {\n transport: ChatTransport;\n config?: ChatConfig;\n initialSessionId?: string;\n autoCreateSession?: boolean;\n streaming?: boolean;\n /** Audio-trigger configuration. Off by default (no `sounds` map). */\n audio?: ChatAudioConfig;\n /** Enable verbose dev logging via consola. Defaults to `isDev`. */\n debug?: boolean;\n /**\n * Rewrite outgoing message content before it hits the transport.\n * History bubble keeps the original; useful for stripping rich-\n * display chips so the LLM sees plain text. See `useChat`.\n */\n onBeforeSend?: (content: string) => string | Promise<string>;\n children?: ReactNode;\n}\n\nexport function ChatProvider({\n transport,\n config = {},\n initialSessionId,\n autoCreateSession,\n streaming,\n audio,\n debug,\n onBeforeSend,\n children,\n}: ChatProviderProps) {\n const audioApi = useChatAudio(audio ?? {});\n\n // Keep latest audio API in a ref so the chat-callback closures stay\n // referentially stable (don't re-mount transport on every audio change).\n const audioRef = useRef(audioApi);\n audioRef.current = audioApi;\n\n const onMessageSent = useCallback(() => audioRef.current.play('messageSent'), []);\n const onMessageEnd = useCallback(() => audioRef.current.play('messageReceived'), []);\n const onStreamStart = useCallback(() => audioRef.current.play('streamStart'), []);\n const onError = useCallback(() => audioRef.current.play('error'), []);\n\n const chat = useChat({\n transport,\n initialSessionId,\n autoCreateSession,\n streaming,\n debug,\n metadata: {\n locale: config.locale ?? config.prefs?.locale,\n slug: config.slug,\n },\n userPersona: config.user,\n onMessageSent,\n onMessageEnd,\n onStreamStart,\n onError,\n onBeforeSend,\n });\n const layout = useChatLayout({ defaultMode: 'embedded' });\n\n // Auto-unlock audio on the first user gesture inside the provider.\n const rootRef = useRef<HTMLDivElement | null>(null);\n useEffect(() => {\n if (audioApi.isUnlocked) return;\n const root = rootRef.current;\n if (!root) return;\n const handler = () => {\n audioApi.unlock();\n };\n root.addEventListener('pointerdown', handler, { once: true, capture: true });\n root.addEventListener('keydown', handler, { once: true, capture: true });\n return () => {\n root.removeEventListener('pointerdown', handler, { capture: true });\n root.removeEventListener('keydown', handler, { capture: true });\n };\n }, [audioApi]);\n\n const labels = useMemo<ChatLabels>(\n () => ({ ...DEFAULT_LABELS, ...(config.labels ?? {}) }),\n [config.labels],\n );\n\n const hasAudio = useMemo<boolean>(() => {\n const sounds = audio?.sounds;\n if (!sounds) return false;\n return Object.values(sounds).some(\n (v) => typeof v === 'string' && v.length > 0,\n );\n }, [audio]);\n\n // Composer registry — kept in state (not a ref) so consumers\n // observing `ctx.composer` re-render when a composer mounts /\n // unmounts. The setter is the API surface; pass it to the composer\n // on mount and call with `null` on unmount.\n const [composer, setComposer] = useState<ComposerHandle | null>(null);\n const registerComposer = useCallback((handle: ComposerHandle | null) => {\n setComposer(handle);\n }, []);\n\n const value = useMemo<ChatContextValue>(\n () => ({ ...chat, layout, config, labels, audio: audioApi, hasAudio, composer, registerComposer }),\n [chat, layout, config, labels, audioApi, hasAudio, composer, registerComposer],\n );\n\n return (\n <Ctx.Provider value={value}>\n <div ref={rootRef} style={{ display: 'contents' }}>\n {children}\n </div>\n </Ctx.Provider>\n );\n}\n\nexport function useChatContext(): ChatContextValue {\n const v = useContext(Ctx);\n if (!v) throw new Error('useChatContext must be used inside <ChatProvider>');\n return v;\n}\n\nexport function useChatContextOptional(): ChatContextValue | null {\n return useContext(Ctx);\n}\n","'use client';\n\nimport { type RefObject, useEffect, useRef } from 'react';\n\nimport { useChatContextOptional, type ComposerHandle } from '../context';\n\n/** Anything with a `.focus()` method — covers HTMLElement, the\n * composer's textareaRef from `useChatComposer`, and any custom\n * imperative handle exposing the same shape. */\nexport interface Focusable {\n focus: () => void;\n}\n\nexport interface UseAutoFocusOnStreamEndOptions {\n /** True while an assistant reply is streaming. The hook fires the\n * focus() call on the true → false transition.\n *\n * When omitted, the hook reads `isStreaming` from `useChatContext`.\n * Pass it explicitly only if you're driving stream state from your\n * own store (cmdop's Wails event bus, for example). */\n isStreaming?: boolean;\n /** Ref / handle to focus when the reply lands.\n *\n * When omitted, the hook uses the composer handle registered in\n * the chat context — the built-in `<Composer>` registers itself\n * automatically, custom composers can opt in via\n * `useRegisterComposer`. Pass `targetRef` only when you need to\n * focus something other than the composer (e.g. an \"approve\"\n * button, a quick-reply chip). */\n targetRef?: RefObject<Focusable | HTMLElement | null>;\n /** Opt-out. Default true. Pass false to disable without unmounting\n * the hook (e.g. user preference). */\n enabled?: boolean;\n /** Delay the focus call by this many ms. Default 0 = next animation\n * frame, which lets the streaming bubble's final commit settle\n * before focus pulls scroll. Bump to 50-150ms for layouts that\n * re-mount the composer after the final chunk. */\n delayMs?: number;\n}\n\n/**\n * Refocus the chat composer the moment the assistant reply finishes\n * streaming. Standard chat UX: the user types → sends → reads the\n * reply → starts typing again without reaching for the mouse.\n *\n * Default (zero-config) usage — works the moment a `<Composer>` is\n * mounted inside a `<ChatProvider>`:\n *\n * useAutoFocusOnStreamEnd();\n *\n * Custom composer / advanced wiring:\n *\n * const ref = useRef<{ focus: () => void } | null>(null);\n * useAutoFocusOnStreamEnd({ targetRef: ref });\n *\n * Driving stream state yourself:\n *\n * useAutoFocusOnStreamEnd({ isStreaming: myExternalStreaming });\n *\n * Only the true → false transition fires focus — toggling `enabled`\n * mid-stream won't steal focus while the user is reading.\n */\nexport function useAutoFocusOnStreamEnd(\n options: UseAutoFocusOnStreamEndOptions = {},\n): void {\n const { isStreaming: isStreamingProp, targetRef, enabled = true, delayMs = 0 } = options;\n const ctx = useChatContextOptional();\n // Prefer the prop (caller knows best), fall back to context.\n const isStreaming = isStreamingProp ?? ctx?.isStreaming ?? false;\n\n // Keep latest ctx-composer in a ref so the focus effect always\n // sees the freshest registered handle without re-firing when\n // composers re-mount.\n const composerHandleRef = useRef<ComposerHandle | null>(null);\n composerHandleRef.current = ctx?.composer ?? null;\n\n const prevStreamingRef = useRef(isStreaming);\n\n useEffect(() => {\n const wasStreaming = prevStreamingRef.current;\n prevStreamingRef.current = isStreaming;\n\n if (!enabled) return;\n if (!(wasStreaming && !isStreaming)) return;\n\n const focusNow = () => {\n // Resolve target in priority order: explicit ref > registered\n // composer handle. Refs may carry an HTMLElement (raw DOM) or\n // any object with `.focus()`; both are handled by the same\n // call site below.\n const explicit = targetRef?.current as Focusable | null;\n const target: Focusable | null = explicit ?? composerHandleRef.current;\n target?.focus();\n };\n\n if (delayMs > 0) {\n const id = window.setTimeout(focusNow, delayMs);\n return () => window.clearTimeout(id);\n }\n const raf = requestAnimationFrame(focusNow);\n return () => cancelAnimationFrame(raf);\n }, [isStreaming, enabled, delayMs, targetRef]);\n}\n\n/**\n * Helper for custom composers (anything that's NOT the built-in\n * `<Composer>`) to register their focus() with the chat context so\n * `useAutoFocusOnStreamEnd()` and other consumers work without\n * prop-drilling.\n *\n * Usage inside your custom composer:\n *\n * const focus = useCallback(() => {\n * myEditorRef.current?.commands.focus();\n * }, []);\n * useRegisterComposer(focus);\n *\n * No-op when called outside a `<ChatProvider>`.\n */\nexport function useRegisterComposer(handle: ComposerHandle): void {\n const ctx = useChatContextOptional();\n const register = ctx?.registerComposer;\n const focus = handle.focus;\n const moveCursorToEnd = handle.moveCursorToEnd;\n useEffect(() => {\n if (!register) return;\n register({ focus, moveCursorToEnd });\n return () => register(null);\n }, [register, focus, moveCursorToEnd]);\n}\n","/**\n * sanitizeDraft — minimal pre-submit cleanup for chat-composer drafts.\n *\n * Mirrors the conservative behaviour ChatGPT / Claude / Telegram\n * actually ship: clean the obvious junk the user didn't intend to\n * send, touch nothing that *could* be intentional.\n *\n * **What we DO touch:**\n *\n * 1. Trim leading/trailing whitespace (spaces, tabs, newlines,\n * NBSP). The user typing `\\n\\n hello \\n` meant `hello`.\n * 2. Normalise line endings — `\\r\\n` / `\\r` → `\\n`. Pasted Windows\n * / old-mac text gets the same internal shape, so the LLM\n * tokeniser and markdown renderer see one canonical form.\n * 3. Strip zero-width / invisible characters that web-paste\n * smuggles in: ZWSP (U+200B), ZWNJ (U+200C), ZWJ (U+200D),\n * BOM / ZWNBSP (U+FEFF). They're invisible, break LLM\n * tokenisation, and the user never meant to type them.\n *\n * **What we DO NOT touch (and why):**\n *\n * - **Internal whitespace runs** (3+ spaces, tabs, blank lines).\n * Code indentation depends on these. ChatGPT preserves them as\n * typed — \" if (x):\\n return\" stays four-space-indented.\n * Collapsing them is the path to subtly broken code snippets.\n *\n * - **Bidi override marks** (U+200E LRM, U+200F RLM, U+202A..U+202E).\n * Legitimately used in Arabic / Hebrew / mixed-direction text.\n * Stripping silently breaks RTL users. If a specific deployment\n * wants to block them as a security measure, do it at that layer\n * with explicit user-visible feedback.\n *\n * - **Tabs vs spaces** beyond rule 1. Could be either code or\n * prose; without parsing markdown we can't tell.\n *\n * - **Emoji, mentions, URLs, code spans** — passthrough text.\n *\n * The function is intentionally tiny — every rule earns its keep\n * with a concrete \"user pasted X from Y, got nonsense\" story.\n *\n * **Idempotent**: `sanitizeDraft(sanitizeDraft(x)) === sanitizeDraft(x)`.\n */\nexport function sanitizeDraft(input: string): string {\n if (!input) return '';\n\n // Strip zero-width invisibles. Done FIRST so the trim below sees\n // the real content edges — a stray ZWSP at the start would\n // otherwise count as non-whitespace and survive the trim.\n // U+200B ZWSP, U+200C ZWNJ, U+200D ZWJ, U+FEFF BOM/ZWNBSP.\n let s = input.replace(/[​‌‍]/g, '');\n\n // Normalise line endings.\n s = s.replace(/\\r\\n?/g, '\\n');\n\n // Trim outer whitespace (includes \\n, \\t, NBSP via String.trim).\n s = s.trim();\n\n return s;\n}\n\n/**\n * Convenience predicate: true when the draft is non-empty AFTER\n * sanitation. Use to gate Send buttons / Enter submits so an empty\n * or whitespace-only draft never produces a real message.\n *\n * Cheaper than sanitizeDraft(input).length > 0 only marginally —\n * we still allocate the cleaned string. Kept as a named helper for\n * call-site clarity.\n */\nexport function isSubmittableDraft(input: string): boolean {\n return sanitizeDraft(input).length > 0;\n}\n","'use client';\n\nimport {\n type ChangeEvent,\n type ClipboardEvent,\n type KeyboardEvent,\n type RefObject,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport type { ChatAttachment } from '../types';\nimport { LIMITS } from '../config';\nimport { sanitizeDraft } from '../utils/sanitizeDraft';\n\nexport interface UseChatComposerOptions {\n onSubmit: (content: string, attachments: ChatAttachment[]) => void | Promise<void>;\n initialValue?: string;\n maxLength?: number;\n maxAttachments?: number;\n disabled?: boolean;\n /** 'enter' = Enter sends, Shift+Enter newline. 'cmd+enter' = Enter inserts newline, Cmd/Ctrl+Enter sends. */\n submitOn?: 'enter' | 'cmd+enter';\n history?: { enabled?: boolean; size?: number };\n onPasteFiles?: (files: File[]) => void;\n /**\n * Persist the current draft to `sessionStorage` under this key. The\n * draft is loaded once on mount (overrides `initialValue` if non-\n * empty) and rewritten on every value change. Cleared on `reset()`.\n *\n * Pass a per-conversation id to keep separate drafts per chat. Pass\n * `undefined` (default) to disable persistence — composer behaves\n * exactly as before. Plan64.\n */\n persistKey?: string;\n /**\n * Skip pre-submit draft sanitation (trim + line-ending normalise +\n * zero-width strip). Default `false` — sanitation matches what\n * ChatGPT / Claude / Telegram ship and is what consumers want 99% of\n * the time. Set to `true` for niche flows that need byte-perfect\n * passthrough (clipboard inspector, raw-prompt debug tool).\n */\n preserveExactValue?: boolean;\n}\n\nexport interface UseChatComposerReturn {\n value: string;\n setValue: (next: string) => void;\n attachments: ChatAttachment[];\n addAttachment: (a: ChatAttachment) => void;\n removeAttachment: (id: string) => void;\n isSubmitting: boolean;\n canSubmit: boolean;\n submit: () => Promise<void>;\n reset: () => void;\n focus: () => void;\n textareaRef: RefObject<HTMLTextAreaElement | null>;\n textareaProps: {\n ref: RefObject<HTMLTextAreaElement | null>;\n value: string;\n disabled: boolean;\n onChange: (e: ChangeEvent<HTMLTextAreaElement>) => void;\n onKeyDown: (e: KeyboardEvent<HTMLTextAreaElement>) => void;\n onPaste: (e: ClipboardEvent<HTMLTextAreaElement>) => void;\n };\n recallPrevious: () => void;\n recallNext: () => void;\n}\n\nconst MAX_TEXTAREA_HEIGHT = 240;\n\nexport function useChatComposer(options: UseChatComposerOptions): UseChatComposerReturn {\n const {\n onSubmit,\n initialValue = '',\n maxLength = LIMITS.messageMaxLength,\n maxAttachments = LIMITS.attachmentsMax,\n disabled = false,\n submitOn = 'enter',\n history = { enabled: true, size: LIMITS.composerHistorySize },\n onPasteFiles,\n persistKey,\n preserveExactValue = false,\n } = options;\n\n // Hydrate draft from sessionStorage on mount when a key is provided.\n // We read once, lazily — switching `persistKey` mid-life (e.g.\n // session change) requires a parent remount via React `key`, same\n // pattern as `<MessageList>`. Avoids accidental cross-session\n // bleed-through when the parent forgets to remount.\n const initialFromStorage = (() => {\n if (!persistKey || typeof window === 'undefined') return initialValue;\n try {\n const stored = window.sessionStorage.getItem(`chat:draft:${persistKey}`);\n return stored && stored.length > 0 ? stored : initialValue;\n } catch {\n return initialValue;\n }\n })();\n const [value, setValueState] = useState(initialFromStorage);\n\n // Persist on every value change. Throwaway swallow keeps quota /\n // private-mode failures from breaking the composer.\n useEffect(() => {\n if (!persistKey || typeof window === 'undefined') return;\n try {\n const k = `chat:draft:${persistKey}`;\n if (value.length > 0) window.sessionStorage.setItem(k, value);\n else window.sessionStorage.removeItem(k);\n } catch {\n /* noop — quota / disabled storage is non-fatal */\n }\n }, [value, persistKey]);\n const [attachments, setAttachments] = useState<ChatAttachment[]>([]);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n const historyRef = useRef<{ items: string[]; index: number }>({ items: [], index: -1 });\n\n const setValue = useCallback(\n (next: string) => {\n setValueState(next.length > maxLength ? next.slice(0, maxLength) : next);\n },\n [maxLength],\n );\n\n // Autosize textarea on value change.\n useEffect(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.style.height = 'auto';\n el.style.height = `${Math.min(el.scrollHeight, MAX_TEXTAREA_HEIGHT)}px`;\n }, [value]);\n\n const reset = useCallback(() => {\n setValueState('');\n setAttachments([]);\n historyRef.current.index = -1;\n }, []);\n\n const focus = useCallback(() => {\n requestAnimationFrame(() => textareaRef.current?.focus());\n }, []);\n\n const submit = useCallback(async () => {\n // Sanitise BEFORE the empty-guard so a draft of only whitespace\n // (` \\n\\n `) is treated as empty — saves a round trip for\n // \"send\" attempts that would produce nothing.\n //\n // sanitizeDraft is intentionally conservative: trim outer\n // whitespace, normalise line endings, strip zero-width chars.\n // It does NOT collapse internal whitespace or cap blank lines\n // (would break code indentation / intentional separators). See\n // utils/sanitizeDraft.ts for the full ruleset + rationale.\n //\n // The cleaned text is what reaches `onSubmit` (matches ChatGPT /\n // Claude / Telegram behaviour — the bubble shows what the user\n // last saw, sans accidental trailing whitespace). Niche callers\n // can opt out via `preserveExactValue`.\n const cleaned = preserveExactValue ? value : sanitizeDraft(value);\n if ((!cleaned && attachments.length === 0) || isSubmitting || disabled) return;\n setIsSubmitting(true);\n try {\n if (history.enabled !== false && cleaned) {\n const buf = historyRef.current.items;\n if (buf[buf.length - 1] !== cleaned) {\n buf.push(cleaned);\n if (buf.length > (history.size ?? LIMITS.composerHistorySize)) buf.shift();\n }\n historyRef.current.index = -1;\n }\n const snapshot = [...attachments];\n reset();\n await onSubmit(cleaned, snapshot);\n } finally {\n setIsSubmitting(false);\n }\n }, [value, attachments, isSubmitting, disabled, history, onSubmit, reset, preserveExactValue]);\n\n const addAttachment = useCallback(\n (a: ChatAttachment) => {\n setAttachments((prev) => {\n if (prev.some((p) => p.id === a.id)) {\n return prev.map((p) => (p.id === a.id ? a : p));\n }\n if (prev.length >= maxAttachments) return prev;\n return [...prev, a];\n });\n },\n [maxAttachments],\n );\n\n const removeAttachment = useCallback((id: string) => {\n setAttachments((prev) => prev.filter((a) => a.id !== id));\n }, []);\n\n const recallPrevious = useCallback(() => {\n const { items } = historyRef.current;\n if (!items.length) return;\n const next = historyRef.current.index < 0 ? items.length - 1 : Math.max(0, historyRef.current.index - 1);\n historyRef.current.index = next;\n setValueState(items[next]);\n }, []);\n\n const recallNext = useCallback(() => {\n const { items } = historyRef.current;\n if (!items.length || historyRef.current.index < 0) return;\n const next = historyRef.current.index + 1;\n if (next >= items.length) {\n historyRef.current.index = -1;\n setValueState('');\n return;\n }\n historyRef.current.index = next;\n setValueState(items[next]);\n }, []);\n\n const onChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement>) => {\n setValue(e.target.value);\n },\n [setValue],\n );\n\n const onKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter') {\n const isCmd = e.metaKey || e.ctrlKey;\n const shouldSend = submitOn === 'cmd+enter' ? isCmd : !e.shiftKey;\n if (shouldSend) {\n e.preventDefault();\n void submit();\n }\n return;\n }\n if (history.enabled !== false && value === '' && attachments.length === 0) {\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n recallPrevious();\n } else if (e.key === 'ArrowDown' && historyRef.current.index >= 0) {\n e.preventDefault();\n recallNext();\n }\n }\n },\n [submitOn, submit, history, value, attachments.length, recallPrevious, recallNext],\n );\n\n const onPaste = useCallback(\n (e: ClipboardEvent<HTMLTextAreaElement>) => {\n const files = Array.from(e.clipboardData?.files ?? []);\n if (files.length && onPasteFiles) {\n e.preventDefault();\n onPasteFiles(files);\n }\n },\n [onPasteFiles],\n );\n\n // canSubmit mirrors what submit() will actually do — gate the Send\n // button on the post-sanitation result so a whitespace-only draft\n // renders Send as disabled (no false-hope affordance).\n // preserveExactValue callers fall back to raw .trim() — they\n // opted out of sanitation, but we still don't enable Send on a\n // pure-whitespace draft (an empty message is rarely intentional).\n const canSubmit =\n !disabled && !isSubmitting && (\n (preserveExactValue ? value.trim().length : sanitizeDraft(value).length) > 0\n || attachments.length > 0\n );\n\n return {\n value,\n setValue,\n attachments,\n addAttachment,\n removeAttachment,\n isSubmitting,\n canSubmit,\n submit,\n reset,\n focus,\n textareaRef,\n textareaProps: {\n ref: textareaRef,\n value,\n disabled,\n onChange,\n onKeyDown,\n onPaste,\n },\n recallPrevious,\n recallNext,\n };\n}\n","'use client';\n\nimport { useCallback, useRef } from 'react';\nimport type { MouseEvent as ReactMouseEvent, RefObject } from 'react';\n\nimport { useChatContextOptional, type ComposerHandle } from '../context';\nimport type { Focusable } from './useAutoFocusOnStreamEnd';\n\nexport interface UseFocusOnEmptyClickOptions {\n /**\n * Custom focus target. Defaults to the composer registered in the chat\n * context.\n */\n targetRef?: RefObject<Focusable | HTMLElement | null>;\n /** Opt-out without unmounting the hook. @default true */\n enabled?: boolean;\n /**\n * Don't focus if currently streaming (user is reading the reply).\n * @default true\n */\n skipWhileStreaming?: boolean;\n}\n\n/**\n * \"Click anywhere in the chat → focus the composer\" — Slack / Linear /\n * ChatGPT behaviour.\n *\n * Returns a single `onMouseUp` handler to attach to the scrollable\n * messages container. Heuristics that mirror the popular chat apps:\n *\n * 1. Ignore clicks on interactive elements (`button`, `a`, `input`,\n * `textarea`, `[role=\"button\"]`, `[contenteditable]`, …) — they\n * have their own behaviour.\n * 2. Ignore clicks that produced a text selection (drag-to-select).\n * Stealing focus would break copy-paste flow.\n * 3. Ignore touch input — on mobile the system focuses the textarea\n * via tap on the composer itself; touching messages should never\n * open the keyboard.\n * 4. Optionally skip while the assistant is streaming so the user\n * can keep reading without the keyboard popping up.\n *\n * @example\n * ```tsx\n * const onMouseUp = useFocusOnEmptyClick();\n * <div ref={scrollRef} onMouseUp={onMouseUp}>{messages}</div>\n * ```\n */\nexport function useFocusOnEmptyClick(\n options: UseFocusOnEmptyClickOptions = {},\n): (event: ReactMouseEvent<HTMLElement>) => void {\n const { targetRef, enabled = true, skipWhileStreaming = true } = options;\n const ctx = useChatContextOptional();\n\n const composerHandleRef = useRef<ComposerHandle | null>(null);\n composerHandleRef.current = ctx?.composer ?? null;\n\n const isStreamingRef = useRef(false);\n isStreamingRef.current = ctx?.isStreaming ?? false;\n\n return useCallback(\n (event: ReactMouseEvent<HTMLElement>) => {\n if (!enabled) return;\n if (skipWhileStreaming && isStreamingRef.current) return;\n\n // Touch / pen → never steal focus (mobile keyboard pop is hostile).\n const pointerType = (event.nativeEvent as PointerEvent).pointerType;\n if (pointerType && pointerType !== 'mouse') return;\n\n // Drag-selected text → don't steal focus.\n const selection = typeof window !== 'undefined' ? window.getSelection?.() : null;\n if (selection && !selection.isCollapsed && selection.toString().length > 0) {\n return;\n }\n\n // Click landed on something interactive → it handles itself.\n const target = event.target as HTMLElement | null;\n if (!target) return;\n if (isInteractive(target)) return;\n\n // Refocus.\n const explicit = targetRef?.current as Focusable | HTMLElement | null | undefined;\n if (explicit) {\n explicit.focus?.();\n return;\n }\n composerHandleRef.current?.focus?.();\n },\n [enabled, skipWhileStreaming, targetRef],\n );\n}\n\nconst INTERACTIVE_SELECTORS = [\n 'a[href]',\n 'button',\n 'input',\n 'textarea',\n 'select',\n 'label',\n 'summary',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"menuitem\"]',\n '[role=\"tab\"]',\n '[contenteditable]:not([contenteditable=\"false\"])',\n '[data-no-autofocus]',\n].join(',');\n\nfunction isInteractive(el: HTMLElement | null): boolean {\n if (!el) return false;\n return !!el.closest(INTERACTIVE_SELECTORS);\n}\n","/**\n * Role-aware style hooks for chat surfaces.\n *\n * Pure utility hooks — no React state, no side effects, just memoized\n * className strings derived from `bubbleTokens`. They exist so:\n * - components don't import token constants directly (single facade)\n * - \"the user-bubble link color\" can be changed in one file\n * - tests can mock the hook to assert intent without parsing classNames\n */\n\nimport { useMemo } from 'react';\n\nimport {\n ANCHOR,\n BUBBLE_SURFACE,\n DESTRUCTIVE_SURFACE,\n TOGGLE,\n TOOL_CALL,\n type ChatBubbleSurface,\n} from './bubbleTokens';\n\nexport interface ChatBubbleStyles {\n /** className for the bubble container (background + text + border). */\n surface: string;\n /** className for an inline anchor inside markdown. */\n anchor: string;\n /** className for a secondary inline action (e.g. show more). */\n toggle: string;\n}\n\n/**\n * Resolve bubble + content styles for a single message.\n *\n * @param role 'user' | 'assistant' | 'system' (system defaults to assistant styling)\n * @param isError marks the bubble as a failed turn (overrides surface)\n *\n * @example\n * ```tsx\n * const { surface, anchor } = useChatBubbleStyles(message.role, !!message.isError);\n * <div className={cn('rounded-2xl px-3.5 py-2', surface)}>…</div>\n * ```\n */\nexport function useChatBubbleStyles(\n role: 'user' | 'assistant' | 'system',\n isError: boolean,\n): ChatBubbleStyles {\n return useMemo(() => {\n const isUser = role === 'user';\n const variant: ChatBubbleSurface = isUser ? 'user' : isError ? 'error' : 'assistant';\n return {\n surface: BUBBLE_SURFACE[variant],\n anchor: isUser ? ANCHOR.user : ANCHOR.assistant,\n toggle: isUser ? TOGGLE.user : TOGGLE.assistant,\n };\n }, [role, isError]);\n}\n\nexport interface ChatRoleStyles {\n anchor: string;\n toggle: string;\n}\n\n/**\n * Lightweight variant when only role matters (no error state, no surface).\n * Use in shared markdown renderers that don't know about bubble background.\n */\nexport function useChatRoleStyles(isUser: boolean): ChatRoleStyles {\n return useMemo(\n () => ({\n anchor: isUser ? ANCHOR.user : ANCHOR.assistant,\n toggle: isUser ? TOGGLE.user : TOGGLE.assistant,\n }),\n [isUser],\n );\n}\n\nexport interface ChatDestructiveStyles {\n banner: string;\n hover: string;\n hoverStrong: string;\n text: string;\n menuItem: string;\n toolErrorText: string;\n}\n\n/**\n * Destructive (delete / error) class facade. Hook form keeps the API\n * symmetric with the others; under the hood it returns a frozen object.\n */\nexport function useChatDestructiveStyles(): ChatDestructiveStyles {\n return DESTRUCTIVE_STYLES;\n}\n\nconst DESTRUCTIVE_STYLES: ChatDestructiveStyles = {\n banner: DESTRUCTIVE_SURFACE.banner,\n hover: DESTRUCTIVE_SURFACE.hover,\n hoverStrong: DESTRUCTIVE_SURFACE.hoverStrong,\n text: DESTRUCTIVE_SURFACE.text,\n menuItem: DESTRUCTIVE_SURFACE.menuItem,\n toolErrorText: TOOL_CALL.errorText,\n};\n","'use client';\n\nimport { type ReactNode } from 'react';\nimport { File as FileIcon, X } from 'lucide-react';\n\nimport { cn } from '@djangocfg/ui-core/lib';\n\nimport { useChatDestructiveStyles } from '../styles';\nimport type { ChatAttachment } from '../types';\n\nexport interface AttachmentRendererArgs {\n attachment: ChatAttachment;\n /** True when shown inside the composer's staging tray (denser layout). */\n isInComposer: boolean;\n onClick?: () => void;\n onRemove?: () => void;\n}\n\nexport type AttachmentRenderer = (args: AttachmentRendererArgs) => ReactNode;\n\nexport interface AttachmentRendererMap {\n image?: AttachmentRenderer;\n audio?: AttachmentRenderer;\n video?: AttachmentRenderer;\n file?: AttachmentRenderer;\n /** Fallback renderer when no per-type entry matched. */\n default?: AttachmentRenderer;\n}\n\ninterface CommonProps {\n attachments: ChatAttachment[];\n maxVisible?: number;\n onClick?: (a: ChatAttachment) => void;\n onRemove?: (a: ChatAttachment) => void;\n isInComposer?: boolean;\n className?: string;\n}\n\n// ---------------------------------------------------------------------------\n// AttachmentsGrid — flex-wrap, ideal for thumbnails / file chips.\n// ---------------------------------------------------------------------------\n\nexport interface AttachmentsGridProps extends CommonProps {\n layout?: 'wrap' | 'grid';\n}\n\nexport function AttachmentsGrid({\n attachments,\n maxVisible,\n onClick,\n onRemove,\n isInComposer = false,\n layout = 'wrap',\n className,\n}: AttachmentsGridProps) {\n if (!attachments?.length) return null;\n const visible = maxVisible ? attachments.slice(0, maxVisible) : attachments;\n return (\n <div\n className={cn(\n layout === 'grid' ? 'grid grid-cols-3 gap-2' : 'flex flex-wrap gap-2',\n className,\n )}\n >\n {visible.map((a) => (\n <AttachmentTile\n key={a.id}\n attachment={a}\n isInComposer={isInComposer}\n onClick={onClick ? () => onClick(a) : undefined}\n onRemove={onRemove ? () => onRemove(a) : undefined}\n />\n ))}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// AttachmentsList — vertical stack, designed for rich custom renderers\n// (LazyAudioPlayer, video players, document previews).\n// ---------------------------------------------------------------------------\n\nexport interface AttachmentsListProps extends CommonProps {\n /** Per-type renderer overrides. Falls back to the default tile. */\n renderers?: AttachmentRendererMap;\n}\n\nexport function AttachmentsList({\n attachments,\n maxVisible,\n onClick,\n onRemove,\n renderers,\n isInComposer = false,\n className,\n}: AttachmentsListProps) {\n if (!attachments?.length) return null;\n const visible = maxVisible ? attachments.slice(0, maxVisible) : attachments;\n return (\n <div className={cn('flex w-full flex-col gap-2', className)}>\n {visible.map((a) => {\n const renderer = renderers?.[a.type] ?? renderers?.default;\n const args: AttachmentRendererArgs = {\n attachment: a,\n isInComposer,\n onClick: onClick ? () => onClick(a) : undefined,\n onRemove: onRemove ? () => onRemove(a) : undefined,\n };\n if (renderer) {\n return (\n <div key={a.id} className=\"relative w-full min-w-0\">\n {renderer(args)}\n {args.onRemove ? <RemoveBtn onRemove={args.onRemove} /> : null}\n </div>\n );\n }\n return <AttachmentTile key={a.id} {...args} />;\n })}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Attachments — backwards-compatible facade. Picks the right component based\n// on whether `renderers` are supplied. Existing call-sites keep working.\n// ---------------------------------------------------------------------------\n\nexport interface AttachmentsProps extends CommonProps {\n layout?: 'grid' | 'row';\n renderers?: AttachmentRendererMap;\n}\n\nexport function Attachments(props: AttachmentsProps) {\n const { renderers, layout, ...rest } = props;\n if (renderers) {\n return <AttachmentsList {...rest} renderers={renderers} />;\n }\n return <AttachmentsGrid {...rest} layout={layout === 'grid' ? 'grid' : 'wrap'} />;\n}\n\n// ---------------------------------------------------------------------------\n// Tile + remove btn (default renderers).\n// ---------------------------------------------------------------------------\n\nfunction AttachmentTile({ attachment, onClick, onRemove }: AttachmentRendererArgs) {\n const isImage = attachment.type === 'image';\n const isUploading = attachment.status === 'uploading';\n\n const inner = isImage ? (\n <img\n src={attachment.thumbnailUrl ?? attachment.url}\n alt={attachment.name ?? 'attachment'}\n className=\"h-16 w-16 rounded-md object-cover\"\n loading=\"lazy\"\n />\n ) : (\n <div className=\"flex max-w-44 items-center gap-2 rounded-md border border-border bg-background/60 px-2 py-1.5 text-xs\">\n <FileIcon aria-hidden className=\"size-4 shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{attachment.name ?? 'file'}</span>\n </div>\n );\n\n return (\n <div className=\"relative\">\n {onClick ? (\n <button type=\"button\" onClick={onClick} className=\"block\">\n {inner}\n </button>\n ) : (\n inner\n )}\n {isUploading ? (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center rounded-md bg-background/70 text-[10px] font-medium\">\n {attachment.progress != null ? `${Math.round(attachment.progress * 100)}%` : '…'}\n </div>\n ) : null}\n {onRemove ? <RemoveBtn onRemove={onRemove} /> : null}\n </div>\n );\n}\n\nfunction RemoveBtn({ onRemove }: { onRemove: () => void }) {\n const styles = useChatDestructiveStyles();\n return (\n <button\n type=\"button\"\n aria-label=\"Remove attachment\"\n onClick={onRemove}\n className={cn(\n 'absolute -right-1.5 -top-1.5 grid h-4 w-4 place-items-center rounded-full border border-border bg-background text-muted-foreground',\n styles.hoverStrong,\n )}\n >\n <X aria-hidden className=\"size-2.5\" />\n </button>\n );\n}\n","'use client';\n\nimport { type ReactNode, forwardRef, useEffect, useRef } from 'react';\nimport { Paperclip, Send, Square } from 'lucide-react';\n\nimport { Button, Textarea } from '@djangocfg/ui-core/components';\nimport { cn } from '@djangocfg/ui-core/lib';\n\nimport { useChatContextOptional } from '../context';\nimport type { UseChatComposerReturn } from '../hooks/useChatComposer';\nimport { Attachments } from './Attachments';\n\nexport type ComposerSize = 'sm' | 'md' | 'lg';\n\nexport interface ComposerProps {\n composer: UseChatComposerReturn;\n placeholder?: string;\n disabled?: boolean;\n showAttachmentButton?: boolean;\n onPickFiles?: () => void;\n toolbarStart?: ReactNode;\n toolbarEnd?: ReactNode;\n attachmentTray?: ReactNode;\n className?: string;\n textareaClassName?: string;\n /** Visual size — controls textarea height + button slot size.\n *\n * - ``sm`` — 32px slot, dense compact composer (admin sidebars, etc).\n * - ``md`` — 36px slot, default. Same as the legacy fixed size.\n * - ``lg`` — 48px slot, generous textarea. Use when the chat is\n * the page's primary surface (onboarding, support).\n */\n size?: ComposerSize;\n /** Show \"Stop\" button instead of \"Send\" while streaming. */\n isStreaming?: boolean;\n onCancel?: () => void;\n}\n\nconst SIZE_CLASSES: Record<ComposerSize, {\n slot: string;\n button: string;\n iconButton: string;\n textarea: string;\n text: string;\n padding: string;\n containerPadding: string;\n}> = {\n sm: {\n slot: '[&>:not(textarea)]:h-8',\n button: 'h-8 w-8',\n iconButton: 'size-3.5',\n textarea: 'min-h-8 max-h-48 px-3 py-1.5',\n text: 'text-sm',\n padding: 'gap-1.5',\n containerPadding: 'px-2 pt-1.5 pb-[max(0.375rem,env(safe-area-inset-bottom))]',\n },\n md: {\n slot: '[&>:not(textarea)]:h-9',\n button: 'h-9 w-9',\n iconButton: 'size-4',\n textarea: 'min-h-9 max-h-60 px-3.5 py-2',\n text: 'text-base sm:text-sm',\n padding: 'gap-1.5',\n containerPadding: 'px-2.5 pt-2 pb-[max(0.5rem,env(safe-area-inset-bottom))]',\n },\n lg: {\n slot: '[&>:not(textarea)]:h-12',\n button: 'h-12 w-12',\n iconButton: 'size-5',\n textarea: 'min-h-12 max-h-72 px-4 py-3',\n text: 'text-base',\n padding: 'gap-2',\n containerPadding: 'px-3.5 pt-3 pb-[max(0.875rem,env(safe-area-inset-bottom))]',\n },\n};\n\nexport const Composer = forwardRef<HTMLDivElement, ComposerProps>(function Composer(\n {\n composer,\n placeholder = 'Type a message...',\n disabled,\n showAttachmentButton = false,\n onPickFiles,\n toolbarStart,\n toolbarEnd,\n attachmentTray,\n className,\n textareaClassName,\n size = 'md',\n isStreaming: isStreamingProp,\n onCancel: onCancelProp,\n },\n ref,\n) {\n const ctx = useChatContextOptional();\n const isStreaming = isStreamingProp ?? ctx?.isStreaming ?? false;\n const onCancel = onCancelProp ?? ctx?.cancelStream;\n const isDisabled = disabled ?? isStreaming;\n const sz = SIZE_CLASSES[size];\n\n // Register the composer's focus() with the chat context so other\n // parts of the tree (e.g. useAutoFocusOnStreamEnd) can drive it\n // imperatively without prop-drilling a ref. No-op when used outside\n // a ChatProvider.\n const register = ctx?.registerComposer;\n const composerFocus = composer.focus;\n const composerSetValue = composer.setValue;\n const textareaRef = composer.textareaRef;\n // `getValue` reads the live ref instead of closing over `composer.value`\n // so we don't need to re-register on every keystroke. Same trick for\n // `setValue` — handler identity stays stable across renders.\n const getValueRef = useRef<() => string>(() => composer.value);\n getValueRef.current = () => composer.value;\n useEffect(() => {\n if (!register) return;\n register({\n focus: composerFocus,\n moveCursorToEnd: () => {\n const el = textareaRef.current;\n if (!el) return;\n const end = el.value.length;\n el.setSelectionRange(end, end);\n },\n getValue: () => getValueRef.current(),\n setValue: composerSetValue,\n });\n return () => register(null);\n }, [register, composerFocus, composerSetValue, textareaRef]);\n\n return (\n <div\n ref={ref}\n className={cn(\n 'border-t border-border bg-background/95',\n sz.containerPadding,\n className,\n )}\n >\n {composer.attachments.length > 0 ? (\n <div className=\"mb-1.5\">\n {attachmentTray ?? (\n <Attachments\n attachments={composer.attachments}\n onRemove={(a) => composer.removeAttachment(a.id)}\n />\n )}\n </div>\n ) : null}\n\n {/* Size-aware slot row. ``[&>:not(textarea)]:h-{N}`` enforces a\n * consistent slot height so toolbar buttons line up with the\n * textarea baseline. Toolbar slots that want to opt out can\n * pass an explicit class like `!h-auto`. */}\n <div className={cn('flex items-end [&>:not(textarea)]:shrink-0', sz.padding, sz.slot)}>\n {showAttachmentButton ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={onPickFiles}\n aria-label=\"Attach files\"\n disabled={isDisabled}\n className={sz.button}\n >\n <Paperclip aria-hidden className={sz.iconButton} />\n </Button>\n ) : null}\n\n {toolbarStart}\n\n <Textarea\n {...composer.textareaProps}\n rows={1}\n placeholder={placeholder}\n aria-label={placeholder}\n aria-multiline=\"true\"\n disabled={isDisabled}\n className={cn(\n 'flex-1 resize-none rounded-2xl',\n sz.textarea,\n sz.text,\n textareaClassName,\n )}\n />\n\n {toolbarEnd}\n\n {isStreaming ? (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"icon\"\n onClick={onCancel}\n aria-label=\"Stop\"\n aria-keyshortcuts=\"Escape\"\n className={sz.button}\n >\n <Square aria-hidden className={sz.iconButton} />\n </Button>\n ) : (\n <Button\n type=\"button\"\n size=\"icon\"\n onClick={() => void composer.submit()}\n disabled={!composer.canSubmit}\n aria-label=\"Send\"\n aria-keyshortcuts=\"Enter\"\n className={sz.button}\n >\n <Send aria-hidden className={sz.iconButton} />\n </Button>\n )}\n </div>\n </div>\n );\n});\n","'use client';\n\nimport { Sparkles } from 'lucide-react';\n\nimport { cn } from '@djangocfg/ui-core/lib';\n\nexport interface EmptyStateProps {\n greeting?: string;\n description?: string;\n suggestions?: Array<{ label: string; prompt: string }>;\n onPickSuggestion?: (prompt: string) => void;\n className?: string;\n}\n\nexport function EmptyState({\n greeting,\n description,\n suggestions,\n onPickSuggestion,\n className,\n}: EmptyStateProps) {\n return (\n <div className={cn('flex flex-col items-center gap-3 px-4 py-12 text-center', className)}>\n <div className=\"grid size-10 place-items-center rounded-full bg-muted\">\n <Sparkles aria-hidden className=\"size-5 text-muted-foreground\" />\n </div>\n {greeting ? <h2 className=\"text-base font-semibold\">{greeting}</h2> : null}\n {description ? (\n <p className=\"max-w-md text-sm text-muted-foreground\">{description}</p>\n ) : null}\n {suggestions?.length ? (\n <div className=\"mt-2 grid w-full max-w-md grid-cols-1 gap-2 sm:grid-cols-2\">\n {suggestions.map((s) => (\n <button\n key={s.prompt}\n type=\"button\"\n onClick={() => onPickSuggestion?.(s.prompt)}\n className=\"rounded-lg border border-border bg-background/60 px-3 py-2 text-left text-xs hover:bg-accent\"\n >\n {s.label}\n </button>\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n","'use client';\n\nimport { AlertCircle, RefreshCw, X } from 'lucide-react';\n\nimport { cn } from '@djangocfg/ui-core/lib';\n\nimport { useChatDestructiveStyles } from '../styles';\n\nexport interface ErrorBannerProps {\n error: string | null;\n onDismiss?: () => void;\n onRetry?: () => void;\n className?: string;\n}\n\nexport function ErrorBanner({ error, onDismiss, onRetry, className }: ErrorBannerProps) {\n const styles = useChatDestructiveStyles();\n if (!error) return null;\n return (\n <div\n role=\"alert\"\n className={cn(\n 'mx-2.5 my-2 flex items-start gap-2 rounded-md px-3 py-2 text-xs',\n styles.banner,\n className,\n )}\n >\n <AlertCircle aria-hidden className=\"mt-0.5 size-3.5 shrink-0\" />\n <p className=\"min-w-0 flex-1 break-words\">{error}</p>\n {onRetry ? (\n <button\n type=\"button\"\n onClick={onRetry}\n className={cn('inline-flex items-center gap-1 rounded px-1.5 py-0.5', styles.hover)}\n >\n <RefreshCw aria-hidden className=\"size-3\" /> Retry\n </button>\n ) : null}\n {onDismiss ? (\n <button\n type=\"button\"\n aria-label=\"Dismiss\"\n onClick={onDismiss}\n className={cn('rounded p-0.5', styles.hover)}\n >\n <X aria-hidden className=\"size-3\" />\n </button>\n ) : null}\n </div>\n );\n}\n","'use client';\n\nimport { ArrowDown } from 'lucide-react';\n\nimport { cn } from '@djangocfg/ui-core/lib';\n\nexport interface JumpToLatestProps {\n visible?: boolean;\n unreadCount?: number;\n onClick?: () => void;\n className?: string;\n}\n\nexport function JumpToLatest({ visible, unreadCount = 0, onClick, className }: JumpToLatestProps) {\n if (!visible) return null;\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-live=\"polite\"\n className={cn(\n 'pointer-events-auto inline-flex items-center gap-1.5 rounded-full border border-border bg-background px-3 py-1 text-xs shadow-md hover:bg-accent',\n className,\n )}\n >\n <ArrowDown aria-hidden className=\"size-3.5\" />\n {unreadCount > 0 ? `${unreadCount} new` : 'Jump to latest'}\n </button>\n );\n}\n","// Persona resolution helpers — pure, no React.\n//\n// Resolution cascade for a bubble's persona:\n// 1. message.sender (per-message override; multi-user chats)\n// 2. config.user / config.assistant (provider-level default)\n// 3. role-based fallback ('You' / 'AI')\n\nimport type { ChatAssistantContext, ChatMessage, ChatPersona, ChatUserContext } from '../types';\n\nconst FALLBACK_USER: ChatPersona = { name: 'You', initials: 'You' };\nconst FALLBACK_ASSISTANT: ChatPersona = { name: 'AI', initials: 'AI' };\n\nexport function resolvePersona(\n message: Pick<ChatMessage, 'role' | 'sender'>,\n user?: ChatUserContext,\n assistant?: ChatAssistantContext,\n): ChatPersona {\n if (message.sender) return message.sender;\n if (message.role === 'user') return user ?? FALLBACK_USER;\n if (message.role === 'assistant') return assistant ?? FALLBACK_ASSISTANT;\n return { name: message.role };\n}\n\n/** Compute initials for an avatar fallback. */\nexport function deriveInitials(persona: ChatPersona, role?: string): string {\n if (persona.initials) return persona.initials;\n if (persona.name) {\n const parts = persona.name.trim().split(/\\s+/);\n if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();\n return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\n }\n if (role === 'user') return 'You';\n if (role === 'assistant') return 'AI';\n return '?';\n}\n","'use client';\n\nimport { memo } from 'react';\nimport { cn } from '@djangocfg/ui-core/lib';\n\nexport interface StreamingIndicatorProps {\n variant?: 'dots' | 'pulse';\n label?: string;\n className?: string;\n}\n\n/**\n * StreamingIndicator — animated dots or pulse for streaming state.\n *\n * Memoised: re-renders only when `variant`, `label` or `className`\n * change. All props are primitives, so default shallow comparison is\n * sufficient.\n */\nfunction StreamingIndicatorRaw({ variant = 'dots', label, className }: StreamingIndicatorProps) {\n return (\n <span\n className={cn('inline-flex items-center gap-1.5 text-xs text-muted-foreground', className)}\n aria-live=\"off\"\n >\n {variant === 'dots' ? (\n <span className=\"inline-flex gap-0.5\" aria-hidden>\n <span className=\"size-1 animate-bounce rounded-full bg-current [animation-delay:-0.2s]\" />\n <span className=\"size-1 animate-bounce rounded-full bg-current [animation-delay:-0.1s]\" />\n <span className=\"size-1 animate-bounce rounded-full bg-current\" />\n </span>\n ) : (\n <span className=\"inline-block size-1.5 animate-pulse rounded-full bg-current\" aria-hidden />\n )}\n {label ? <span className=\"italic\">{label}</span> : null}\n </span>\n );\n}\n\nexport const StreamingIndicator = memo(StreamingIndicatorRaw);\n","'use client';\n\nimport { ExternalLink } from 'lucide-react';\n\nimport { cn } from '@djangocfg/ui-core/lib';\n\nimport type { ChatSource } from '../types';\n\nexport interface SourcesProps {\n sources: ChatSource[];\n layout?: 'inline' | 'grid';\n maxVisible?: number;\n onClick?: (source: ChatSource) => void;\n className?: string;\n}\n\nexport function Sources({ sources, layout = 'inline', maxVisible, onClick, className }: SourcesProps) {\n if (!sources?.length) return null;\n const visible = maxVisible ? sources.slice(0, maxVisible) : sources;\n const remaining = maxVisible ? Math.max(0, sources.length - maxVisible) : 0;\n\n return (\n <div\n className={cn(\n 'mt-2 flex flex-wrap gap-1.5',\n layout === 'grid' && 'grid grid-cols-2',\n className,\n )}\n >\n {visible.map((s, i) => {\n const handle = onClick ? () => onClick(s) : undefined;\n const Tag = handle ? 'button' : 'a';\n const props = handle\n ? ({ type: 'button', onClick: handle } as const)\n : ({ href: s.url, target: '_blank', rel: 'noopener noreferrer' } as const);\n return (\n <Tag\n key={`${s.url}-${i}`}\n {...props}\n className=\"inline-flex max-w-full items-center gap-1 rounded-md border border-border bg-background/60 px-2 py-1 text-xs text-foreground/80 hover:bg-accent hover:text-foreground\"\n title={s.snippet ?? s.title}\n >\n <span className=\"truncate\">{s.title || s.url}</span>\n <ExternalLink aria-hidden className=\"size-3 shrink-0 opacity-60\" />\n </Tag>\n );\n })}\n {remaining > 0 ? (\n <span className=\"inline-flex items-center rounded-md border border-dashed border-border px-2 py-1 text-xs text-muted-foreground\">\n +{remaining}\n </span>\n ) : null}\n </div>\n );\n}\n","'use client';\n\nimport { memo, type ReactNode, useEffect, useRef, useState } from 'react';\nimport { ChevronDown, ChevronRight, Loader2 } from 'lucide-react';\n\nimport { cn } from '@djangocfg/ui-core/lib';\n\nimport type { ChatToolCall } from '../types';\n\nexport type ToolPayloadKind = 'input' | 'output' | 'streaming';\n\nexport interface ToolCallsProps {\n calls: ChatToolCall[];\n /** Open every panel up-front. Default: false (panels are closed). */\n defaultExpanded?: boolean;\n /** Auto-open while a tool is running, then auto-close on completion.\n * User toggles after that are remembered. Default: true. */\n expandWhileStreaming?: boolean;\n /** Override how the tool input payload is rendered. Receives the raw value. */\n renderInput?: (input: unknown, call: ChatToolCall) => ReactNode;\n /** Override how the tool output payload is rendered. */\n renderOutput?: (output: unknown, call: ChatToolCall) => ReactNode;\n /** Override how the live `streamingText` is rendered. */\n renderStreaming?: (text: string, call: ChatToolCall) => ReactNode;\n /** Single override for all three; specific renderers above take precedence. */\n renderPayload?: (value: unknown, kind: ToolPayloadKind, call: ChatToolCall) => ReactNode;\n /**\n * Rendered once **after** all tool-call panels — always visible, outside\n * the collapsible panels. Use for rich UI derived from tool outputs (e.g.\n * vehicle cards, map pins, tax breakdowns). Receives the full calls array\n * so the renderer can aggregate across multiple tool calls.\n */\n renderAfterCalls?: (calls: ChatToolCall[]) => ReactNode;\n /**\n * Custom renderer for each individual tool-call panel. When provided,\n * replaces the default collapsible `<ToolCallItem>`. Return `null` to\n * suppress a specific call while still letting others render.\n */\n renderToolCall?: (call: ChatToolCall) => ReactNode;\n /**\n * When `true`, the collapsible tool-call panels are not rendered at all.\n * `renderAfterCalls` still runs — use together to show only rich UI with\n * no raw accordion panels visible.\n */\n hideToolCalls?: boolean;\n className?: string;\n}\n\nexport function ToolCalls({\n calls,\n defaultExpanded = false,\n expandWhileStreaming = true,\n renderInput,\n renderOutput,\n renderStreaming,\n renderPayload,\n renderAfterCalls,\n renderToolCall,\n hideToolCalls = false,\n className,\n}: ToolCallsProps) {\n if (!calls?.length) return null;\n return (\n <div className={cn('mt-2 space-y-1.5', className)}>\n {!hideToolCalls && calls.map((call) =>\n renderToolCall\n ? <div key={call.id}>{renderToolCall(call)}</div>\n : (\n <ToolCallItem\n key={call.id}\n call={call}\n defaultExpanded={defaultExpanded}\n expandWhileStreaming={expandWhileStreaming}\n renderInput={renderInput}\n renderOutput={renderOutput}\n renderStreaming={renderStreaming}\n renderPayload={renderPayload}\n />\n ),\n )}\n {renderAfterCalls ? renderAfterCalls(calls) : null}\n </div>\n );\n}\n\ninterface ItemProps {\n call: ChatToolCall;\n defaultExpanded: boolean;\n expandWhileStreaming: boolean;\n renderInput?: ToolCallsProps['renderInput'];\n renderOutput?: ToolCallsProps['renderOutput'];\n renderStreaming?: ToolCallsProps['renderStreaming'];\n renderPayload?: ToolCallsProps['renderPayload'];\n}\n\nconst ToolCallItem = memo(function ToolCallItem({\n call,\n defaultExpanded,\n expandWhileStreaming,\n renderInput,\n renderOutput,\n renderStreaming,\n renderPayload,\n}: ItemProps) {\n const isRunning = call.status === 'running';\n const initialOpen = defaultExpanded || (expandWhileStreaming && isRunning);\n const [open, setOpen] = useState(initialOpen);\n // Remember manual interaction so completion doesn't override it.\n const userToggledRef = useRef(false);\n const wasRunningRef = useRef(isRunning);\n\n // Auto-collapse on running → completed transition, unless user has interacted.\n useEffect(() => {\n if (wasRunningRef.current && !isRunning) {\n if (!userToggledRef.current && !defaultExpanded) {\n setOpen(false);\n }\n }\n wasRunningRef.current = isRunning;\n }, [isRunning, defaultExpanded]);\n\n const handleToggle = () => {\n userToggledRef.current = true;\n setOpen((v) => !v);\n };\n\n const Icon = open ? ChevronDown : ChevronRight;\n const statusColor =\n call.status === 'success'\n ? 'text-emerald-500'\n : call.status === 'error'\n ? 'text-destructive'\n : call.status === 'cancelled'\n ? 'text-muted-foreground'\n : 'text-amber-500';\n\n const renderValue = (value: unknown, kind: ToolPayloadKind): ReactNode => {\n if (kind === 'input' && renderInput) return renderInput(value, call);\n if (kind === 'output' && renderOutput) return renderOutput(value, call);\n if (kind === 'streaming' && renderStreaming)\n return renderStreaming(typeof value === 'string' ? value : String(value), call);\n if (renderPayload) return renderPayload(value, kind, call);\n return <DefaultPayload value={value} kind={kind} />;\n };\n\n return (\n <div className=\"overflow-hidden rounded-md border border-border bg-muted/30\">\n <button\n type=\"button\"\n onClick={handleToggle}\n aria-expanded={open}\n className=\"flex w-full items-center gap-2 px-2 py-1.5 text-left text-xs hover:bg-muted/60\"\n >\n <Icon aria-hidden className=\"size-3 shrink-0 text-muted-foreground\" />\n {isRunning ? (\n <Loader2 aria-hidden className=\"size-3 shrink-0 animate-spin text-amber-500\" />\n ) : (\n <span className={cn('size-2 shrink-0 rounded-full', statusColor.replace('text-', 'bg-'))} />\n )}\n <span className=\"font-mono text-foreground\">{call.name}</span>\n <span className={cn('ml-auto', statusColor)}>{call.status}</span>\n </button>\n {open ? (\n <div className=\"space-y-1 border-t border-border px-2 py-1.5 text-[11px]\">\n {call.input != null ? renderValue(call.input, 'input') : null}\n {call.streamingText != null\n ? renderValue(call.streamingText, 'streaming')\n : call.output !== undefined\n ? renderValue(call.output, 'output')\n : null}\n </div>\n ) : null}\n </div>\n );\n}, (prev, next) => {\n // Re-render only when the call's observable surface actually changed.\n // Render-prop callbacks are accepted as referentially stable by callers —\n // they live in toolCallsProps which itself rarely changes.\n const a = prev.call;\n const b = next.call;\n return (\n a.id === b.id &&\n a.status === b.status &&\n a.output === b.output &&\n a.streamingText === b.streamingText &&\n prev.defaultExpanded === next.defaultExpanded &&\n prev.expandWhileStreaming === next.expandWhileStreaming &&\n prev.renderInput === next.renderInput &&\n prev.renderOutput === next.renderOutput &&\n prev.renderStreaming === next.renderStreaming &&\n prev.renderPayload === next.renderPayload\n );\n});\n\nfunction DefaultPayload({ value, kind }: { value: unknown; kind: ToolPayloadKind }) {\n const isStreamingOrString = kind === 'streaming' || typeof value === 'string';\n const muted = kind === 'input';\n return (\n <pre\n className={cn(\n 'overflow-auto rounded bg-background/60 p-1.5 font-mono',\n kind === 'input' ? 'max-h-32' : 'max-h-48',\n muted ? 'text-muted-foreground' : 'text-foreground/90',\n )}\n >\n {isStreamingOrString ? String(value) : safeStringify(value)}\n </pre>\n );\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n","'use client';\n\nimport { memo } from 'react';\nimport { Copy, Pencil, RefreshCw, Trash } from 'lucide-react';\n\nimport { cn } from '@djangocfg/ui-core/lib';\n\nimport { useChatDestructiveStyles } from '../styles';\nimport type { ChatRole } from '../types';\n\nexport interface MessageActionsProps {\n role: ChatRole;\n onCopy?: () => void;\n onRegenerate?: () => void;\n onEdit?: () => void;\n onDelete?: () => void;\n hideOn?: Array<ChatRole>;\n className?: string;\n}\n\n/**\n * MessageActions — copy/regenerate/edit/delete buttons for a chat bubble.\n *\n * Memoised: re-renders only when `role`, `hideOn`, `className` or\n * any handler reference changes. Event handlers are compared by\n * reference — callers should stabilise them with useCallback.\n */\nfunction MessageActionsRaw({\n role,\n onCopy,\n onRegenerate,\n onEdit,\n onDelete,\n hideOn,\n className,\n}: MessageActionsProps) {\n if (hideOn?.includes(role)) return null;\n return (\n <div\n className={cn(\n 'mt-1 flex items-center gap-0.5 opacity-0 transition-opacity group-hover/msg:opacity-100 focus-within:opacity-100',\n className,\n )}\n >\n {onCopy ? <ActionButton onClick={onCopy} label=\"Copy\" icon={Copy} /> : null}\n {onRegenerate && role === 'assistant' ? (\n <ActionButton onClick={onRegenerate} label=\"Regenerate\" icon={RefreshCw} />\n ) : null}\n {onEdit && role === 'user' ? (\n <ActionButton onClick={onEdit} label=\"Edit\" icon={Pencil} />\n ) : null}\n {onDelete ? <ActionButton onClick={onDelete} label=\"Delete\" icon={Trash} destructive /> : null}\n </div>\n );\n}\n\nconst ActionButton = memo(function ActionButton({\n onClick,\n label,\n icon: Icon,\n destructive,\n}: {\n onClick: () => void;\n label: string;\n icon: typeof Copy;\n destructive?: boolean;\n}) {\n const styles = useChatDestructiveStyles();\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n className={cn(\n 'rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground',\n destructive && cn(styles.hover, 'hover:text-destructive'),\n )}\n >\n <Icon aria-hidden className=\"size-3\" />\n </button>\n );\n});\n\nexport const MessageActions = memo(MessageActionsRaw);\n","'use client';\n\nimport { memo, type ReactNode } from 'react';\n\nimport { Avatar, AvatarFallback, AvatarImage } from '@djangocfg/ui-core/components';\nimport { cn } from '@djangocfg/ui-core/lib';\n\nimport { MarkdownMessage } from '../../../components/markdown';\nimport type {\n ChatAssistantContext,\n ChatAttachment,\n ChatMessage,\n ChatSource,\n ChatToolCall,\n ChatUserContext,\n} from '../types';\nimport { resolvePersona, deriveInitials } from '../core/persona';\nimport { useChatContextOptional } from '../context';\nimport { useChatBubbleStyles } from '../styles';\nimport { StreamingIndicator } from './StreamingIndicator';\nimport { Sources } from './Sources';\nimport { ToolCalls } from './ToolCalls';\nimport {\n AttachmentsGrid,\n AttachmentsList,\n type AttachmentRendererMap,\n} from './Attachments';\nimport { MessageActions } from './MessageActions';\nimport type { ToolCallsProps } from './ToolCalls';\n\nexport interface MessageBubbleProps {\n message: ChatMessage;\n isUser?: boolean;\n showAvatar?: boolean;\n /** Override avatar URL (skips persona resolution). */\n avatarSrc?: string;\n /** Override avatar fallback (skips persona resolution). */\n avatarFallback?: ReactNode;\n /** Personas — when provided, take precedence over context. */\n user?: ChatUserContext;\n assistant?: ChatAssistantContext;\n showTimestamp?: boolean;\n showActions?: boolean;\n isCompact?: boolean;\n className?: string;\n beforeContent?: ReactNode;\n afterContent?: ReactNode;\n toolCallsRenderer?: (calls: ChatToolCall[]) => ReactNode;\n /** Forwarded to the default `<ToolCalls>` when `toolCallsRenderer` is not set. */\n toolCallsProps?: Omit<ToolCallsProps, 'calls'>;\n sourcesRenderer?: (sources: ChatSource[]) => ReactNode;\n attachmentsRenderer?: (atts: ChatAttachment[]) => ReactNode;\n /** Per-type attachment renderers forwarded to default `<Attachments>`. */\n attachmentRenderers?: AttachmentRendererMap;\n /** Click handler for attachment tiles (e.g. open lightbox). */\n onAttachmentOpen?: (a: ChatAttachment) => void;\n onCopy?: () => void;\n onRegenerate?: () => void;\n onEdit?: () => void;\n onDelete?: () => void;\n /**\n * Extra content rendered alongside the default copy/regenerate/edit/\n * delete actions (after them, on the same row). Hosts pass app-\n * specific affordances here — e.g. \"Send to plan\", \"Add note\",\n * \"Open in inspector\" — without having to fork `<MessageActions>`.\n * Receives the message so renderers can branch by id / role / etc.\n * Plan64.\n */\n messageActionsExtra?: (m: ChatMessage) => ReactNode;\n /**\n * Override the default streaming indicator (the dots / pulse + tool\n * activity label). Receives the message so the host can read\n * `toolActivity`, the running tool call name, etc., and render a\n * richer affordance (\"Running cmd_execute on vps-audi…\"). Plan64.\n *\n * Renders in two slots: as the in-bubble pre-token affordance, and\n * as the inline label above the bubble when `toolActivity` is set.\n * The render-prop is called for both — branch on `m.content` if\n * you need different behaviour per slot.\n */\n streamingIndicator?: (m: ChatMessage) => ReactNode;\n}\n\nconst MessageBubbleInner = ({\n message,\n isUser: isUserProp,\n showAvatar = true,\n avatarSrc,\n avatarFallback,\n user,\n assistant,\n showTimestamp = false,\n showActions = true,\n isCompact = false,\n className,\n beforeContent,\n afterContent,\n toolCallsRenderer,\n toolCallsProps,\n sourcesRenderer,\n attachmentsRenderer,\n attachmentRenderers,\n onAttachmentOpen,\n onCopy,\n onRegenerate,\n onEdit,\n onDelete,\n messageActionsExtra,\n streamingIndicator,\n}: MessageBubbleProps) => {\n const isUser = isUserProp ?? message.role === 'user';\n const isStreaming = !!message.isStreaming;\n const isErr = !!message.isError;\n const { surface: bubbleSurface } = useChatBubbleStyles(\n isUser ? 'user' : 'assistant',\n isErr,\n );\n\n const ctx = useChatContextOptional();\n const persona = resolvePersona(\n message,\n user ?? ctx?.config.user,\n assistant ?? ctx?.config.assistant,\n );\n const initials = deriveInitials(persona, message.role);\n const personaName = persona.name ?? (isUser ? 'You' : 'Assistant');\n\n return (\n <div\n role=\"article\"\n aria-label={`${personaName} said: ${message.content.slice(0, 80)}`}\n aria-busy={isStreaming || undefined}\n data-role={message.role}\n className={cn(\n 'group/msg flex gap-2.5 px-2.5 py-2',\n isUser ? 'flex-row-reverse' : 'flex-row',\n className,\n )}\n >\n {showAvatar ? (\n <Avatar\n className=\"size-7 shrink-0\"\n title={persona.description ?? personaName}\n >\n {avatarSrc || persona.avatarUrl ? (\n <AvatarImage src={avatarSrc ?? persona.avatarUrl} alt={personaName} />\n ) : null}\n <AvatarFallback className=\"text-[10px]\">\n {avatarFallback ?? initials}\n </AvatarFallback>\n </Avatar>\n ) : null}\n\n <div className={cn('min-w-0 flex-1', isUser && 'flex flex-col items-end')}>\n {beforeContent}\n {message.attachments?.length\n ? attachmentsRenderer\n ? attachmentsRenderer(message.attachments)\n : (\n <div className=\"mb-1.5 w-full\">\n {attachmentRenderers ? (\n <AttachmentsList\n attachments={message.attachments}\n renderers={attachmentRenderers}\n onClick={onAttachmentOpen}\n className={isUser ? 'items-end' : undefined}\n />\n ) : (\n <AttachmentsGrid\n attachments={message.attachments}\n onClick={onAttachmentOpen}\n className={isUser ? 'justify-end' : undefined}\n />\n )}\n </div>\n )\n : null}\n\n <div\n className={cn(\n 'inline-block max-w-full rounded-2xl px-3.5 py-2 text-sm',\n bubbleSurface,\n )}\n >\n {isStreaming && message.toolActivity ? (\n <div className=\"mb-1.5\">\n {streamingIndicator\n ? streamingIndicator(message)\n : <StreamingIndicator label={message.toolActivity} />}\n </div>\n ) : null}\n\n {message.content || !isStreaming ? (\n <MarkdownMessage\n content={message.content || (isErr ? '*Failed to generate a response.*' : '')}\n isUser={isUser}\n isCompact={isCompact}\n plainText={isStreaming}\n />\n ) : (\n streamingIndicator ? streamingIndicator(message) : <StreamingIndicator />\n )}\n </div>\n\n {message.toolCalls?.length\n ? toolCallsRenderer\n ? toolCallsRenderer(message.toolCalls)\n : <ToolCalls calls={message.toolCalls} {...toolCallsProps} />\n : null}\n\n {message.sources?.length && !isStreaming\n ? sourcesRenderer\n ? sourcesRenderer(message.sources)\n : <Sources sources={message.sources} />\n : null}\n\n {showActions && !isStreaming ? (\n <div className=\"flex items-center gap-0.5\">\n <MessageActions\n role={message.role}\n onCopy={onCopy}\n onRegenerate={onRegenerate}\n onEdit={onEdit}\n onDelete={onDelete}\n />\n {messageActionsExtra ? messageActionsExtra(message) : null}\n </div>\n ) : null}\n\n {showTimestamp ? (\n <div className=\"mt-1 text-[10px] text-muted-foreground\">\n {new Date(message.createdAt).toLocaleTimeString()}\n </div>\n ) : null}\n\n {afterContent}\n </div>\n </div>\n );\n};\n\nexport const MessageBubble = memo(MessageBubbleInner, (prev, next) => {\n const a = prev.message;\n const b = next.message;\n return (\n a.id === b.id &&\n a.content === b.content &&\n a.isStreaming === b.isStreaming &&\n a.isError === b.isError &&\n (a.version ?? 0) === (b.version ?? 0) &&\n a.toolActivity === b.toolActivity &&\n a.toolCalls === b.toolCalls &&\n a.sources === b.sources &&\n a.attachments === b.attachments\n );\n});\nMessageBubble.displayName = 'MessageBubble';\n","'use client';\n\nimport {\n type ReactNode,\n type RefObject,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Virtuoso, type VirtuosoHandle } from 'react-virtuoso';\n\nimport { cn } from '@djangocfg/ui-core/lib';\nimport { Spinner } from '@djangocfg/ui-core/components';\nimport { useCopy } from '@djangocfg/ui-core/hooks';\n\nimport type { ChatMessage } from '../types';\nimport { useChatContextOptional } from '../context';\nimport { MessageBubble } from './MessageBubble';\n\nexport interface MessageListProps {\n messages?: ChatMessage[];\n renderItem?: (m: ChatMessage, i: number) => ReactNode;\n renderEmpty?: () => ReactNode;\n isLoadingMore?: boolean;\n /**\n * Fires when the user scrolls within `topThresholdPx` of the top of\n * the list — wire to your `loadMore()` here. Replaces the previous\n * `topSentinelRef` API. The callback is gated by Virtuoso, so it\n * won't fire repeatedly while a load is in flight (Virtuoso pauses\n * `startReached` until `data` length grows).\n */\n onStartReached?: () => void;\n /**\n * @deprecated Kept as a no-op for backwards compatibility — wire\n * `onStartReached` instead. Virtuoso owns the scroll viewport now,\n * external sentinels never see scroll events.\n */\n topSentinelRef?: RefObject<HTMLDivElement | null>;\n /**\n * @deprecated Kept as a no-op for backwards compatibility — Virtuoso\n * exposes `scrollToIndex` via the imperative handle instead. See\n * `useChatScroll` for the chat-friendly wrapper.\n */\n bottomRef?: RefObject<HTMLDivElement | null>;\n className?: string;\n itemClassName?: string;\n /**\n * Skip virtualization and render through plain `.map()`. Use for\n * stories / debugging where DevTools needs to see every node, or\n * when `messages` is guaranteed-tiny. Default: `false` — virtualize\n * always. Plan64.\n */\n noVirtualize?: boolean;\n /**\n * @deprecated No-op as of 2.1.373. We intentionally let Virtuoso run\n * its first-item probe pass: cmdop bubbles vary from 40px (one-line\n * user message) to 800px (markdown with code blocks), so any single\n * estimate fed here forces a measure/reshape loop on every render.\n * The kept prop avoids a breaking-change bump for hosts that still\n * pass it explicitly.\n */\n defaultItemHeight?: number;\n /**\n * Fires when the viewport sticky state changes — `true` when the\n * user is pinned to the bottom (streaming token deltas keep them\n * there), `false` once they scroll up. Wire to your \"Jump to\n * latest\" affordance via the inverse: render the pill when\n * `!isAtBottom`. Plan64.\n */\n onAtBottomChange?: (isAtBottom: boolean) => void;\n /**\n * Pixel distance from the bottom that still counts as \"at bottom\".\n * Default 120 — generous enough that mid-message users keep getting\n * sticky-followed (matches ChatGPT / Slack feel) while still letting\n * a deliberate scroll-up break the lock. Plan11.\n */\n atBottomThreshold?: number;\n /**\n * Force-scroll to the bottom when this id changes. Wire to the id of\n * the most-recently-sent user message: every send re-anchors the\n * viewport so users always see their own bubble + the incoming\n * reply, even if they were scrolled up. Plan11.\n */\n scrollAnchorId?: string | number | null;\n}\n\nexport interface MessageListHandle {\n scrollToBottom: (smooth?: boolean) => void;\n scrollToIndex: (index: number, smooth?: boolean) => void;\n}\n\nexport const MessageList = forwardRef<MessageListHandle, MessageListProps>(function MessageList(\n {\n messages: messagesProp,\n renderItem,\n renderEmpty,\n isLoadingMore: isLoadingMoreProp,\n onStartReached,\n className,\n itemClassName,\n noVirtualize = false,\n defaultItemHeight: _deprecatedDefaultItemHeight,\n onAtBottomChange,\n atBottomThreshold = 120,\n scrollAnchorId,\n },\n ref,\n) {\n void _deprecatedDefaultItemHeight;\n const ctx = useChatContextOptional();\n const messages = messagesProp ?? ctx?.messages ?? [];\n const isLoadingMore = isLoadingMoreProp ?? ctx?.isLoadingMore ?? false;\n const { copyToClipboard } = useCopy();\n\n const virtuosoRef = useRef<VirtuosoHandle | null>(null);\n // Virtuoso's `atBottomStateChange` only fires when the list is\n // scrollable AND the user actually scrolls. With ≤3 short bubbles the\n // total height stays below the viewport, virtuoso never fires \"at\n // bottom\", and the `<JumpToLatest>` pill stays stuck. Track the\n // scroller directly: when content fits, force `atBottom=true`.\n const scrollerRef = useRef<HTMLElement | Window | null>(null);\n const [isScrollable, setIsScrollable] = useState(false);\n const lastReportedAtBottomRef = useRef<boolean | null>(null);\n const reportAtBottom = useCallback(\n (value: boolean) => {\n if (lastReportedAtBottomRef.current === value) return;\n lastReportedAtBottomRef.current = value;\n onAtBottomChange?.(value);\n },\n [onAtBottomChange],\n );\n // Track whether we've already landed on the bottom for the initial\n // history. Virtuoso's `initialTopMostItemIndex` only fires on first\n // mount and uses the `messages` length at that moment. Chats almost\n // always mount with `messages=[]` and then receive history one\n // dispatch later — so we ALSO fire an imperative scroll when the\n // first non-empty batch arrives. Subsequent updates fall through to\n // `followOutput` (sticky-bottom while the user is at bottom).\n const didInitialScrollRef = useRef(false);\n\n useImperativeHandle(\n ref,\n () => ({\n scrollToBottom: (smooth = false) => {\n virtuosoRef.current?.scrollToIndex({\n index: 'LAST',\n behavior: smooth ? 'smooth' : 'auto',\n align: 'end',\n });\n },\n scrollToIndex: (index, smooth = false) => {\n virtuosoRef.current?.scrollToIndex({\n index,\n behavior: smooth ? 'smooth' : 'auto',\n });\n },\n }),\n [],\n );\n\n const defaultRenderItem = useCallback(\n (m: ChatMessage) => (\n <div className={itemClassName}>\n <MessageBubble\n message={m}\n onCopy={() => void copyToClipboard(m.content)}\n onRegenerate={ctx ? () => void ctx.regenerate(m.id) : undefined}\n onDelete={ctx ? () => ctx.deleteMessage(m.id) : undefined}\n />\n </div>\n ),\n [itemClassName, ctx, copyToClipboard],\n );\n\n const itemRenderer = renderItem ?? defaultRenderItem;\n // Jump to bottom on the first non-empty messages batch. Wrapped in\n // rAF so virtuoso has measured the new items before we ask it to\n // scroll — otherwise the call happens while the list is still\n // mid-layout and lands on the wrong offset.\n useEffect(() => {\n if (didInitialScrollRef.current) return;\n if (messages.length === 0) return;\n didInitialScrollRef.current = true;\n const id = requestAnimationFrame(() => {\n virtuosoRef.current?.scrollToIndex({\n index: 'LAST',\n align: 'end',\n behavior: 'auto',\n });\n });\n return () => cancelAnimationFrame(id);\n }, [messages.length]);\n\n // Force-scroll to bottom whenever the consumer bumps `scrollAnchorId`\n // (typically the id of the latest user-sent message). Two rAFs so\n // Virtuoso has measured the freshly-pushed bubble before we land,\n // otherwise the call lands on the previous height and clips the new\n // message under the composer. The initial-mount effect above handles\n // first paint, so we skip until it has run.\n useEffect(() => {\n if (scrollAnchorId == null) return;\n if (!didInitialScrollRef.current) return;\n let raf1 = 0;\n let raf2 = 0;\n raf1 = requestAnimationFrame(() => {\n raf2 = requestAnimationFrame(() => {\n virtuosoRef.current?.scrollToIndex({\n index: 'LAST',\n align: 'end',\n behavior: 'smooth',\n });\n });\n });\n return () => {\n cancelAnimationFrame(raf1);\n cancelAnimationFrame(raf2);\n };\n }, [scrollAnchorId]);\n\n // Watch the scroll container: when content fits (scrollHeight ≤ clientHeight)\n // there's nothing to scroll, the user is by definition \"at bottom\", and the\n // Jump-to-latest pill must stay hidden regardless of what virtuoso reports.\n useEffect(() => {\n const el = scrollerRef.current;\n if (!el || el === window || !(el instanceof HTMLElement)) return;\n\n const probe = () => {\n const scrollable = el.scrollHeight > el.clientHeight + 1;\n setIsScrollable(scrollable);\n if (!scrollable) reportAtBottom(true);\n };\n\n probe();\n const ro = new ResizeObserver(probe);\n ro.observe(el);\n return () => ro.disconnect();\n }, [reportAtBottom, messages.length]);\n\n // Virtuoso may invoke `computeItemKey` for an index briefly out of\n // sync with `data` during fast state churn (streaming chunks +\n // Strict Mode double-mount). `m` arrives undefined in that window.\n // Falling back to the index keeps the lookup stable instead of\n // crashing with `undefined.id` — the next pass with the real item\n // re-keys it correctly. See react-virtuoso issue #532 / #1045.\n const computeItemKey = useCallback(\n (index: number, m: ChatMessage | undefined) => m?.id ?? index,\n [],\n );\n\n // Wrap user-supplied onStartReached so we don't double-fire while a\n // load is already in flight. Virtuoso pauses startReached until\n // `data` grows, but our consumers pass `onStartReached={loadMore}`\n // directly — `loadMore` sets `isLoadingMore=true` synchronously, so\n // we can suppress further calls until that flag drops back to false.\n const startReachedHandler = useMemo(() => {\n if (!onStartReached) return undefined;\n let inFlight = false;\n return () => {\n if (inFlight || isLoadingMore) return;\n inFlight = true;\n try {\n onStartReached();\n } finally {\n // Release on the next tick — Virtuoso re-fires startReached\n // only after data length changes, so the inFlight guard is\n // belt+suspenders against same-frame double calls.\n queueMicrotask(() => {\n inFlight = false;\n });\n }\n };\n }, [onStartReached, isLoadingMore]);\n\n // Empty path — render renderEmpty instead of the virtualizer to avoid\n // a blank Virtuoso frame and the cost of mounting it for nothing.\n if (messages.length === 0) {\n return (\n <div\n role=\"log\"\n aria-live=\"polite\"\n aria-atomic=\"false\"\n className={cn('flex-1 overflow-y-auto', className)}\n >\n {renderEmpty?.() ?? null}\n </div>\n );\n }\n\n if (noVirtualize) {\n return (\n <div\n role=\"log\"\n aria-live=\"polite\"\n aria-atomic=\"false\"\n className={cn('flex-1 overflow-y-auto', className)}\n >\n {isLoadingMore ? (\n <div className=\"flex justify-center py-2\">\n <Spinner className=\"size-4 text-muted-foreground\" />\n </div>\n ) : null}\n {messages.map((m, i) => (\n <div key={m.id ?? i}>{itemRenderer(m, i)}</div>\n ))}\n </div>\n );\n }\n\n return (\n <Virtuoso\n ref={virtuosoRef}\n role=\"log\"\n aria-live=\"polite\"\n aria-atomic=\"false\"\n className={cn('flex-1', className)}\n data={messages}\n computeItemKey={computeItemKey}\n itemContent={(index, m) => (m ? itemRenderer(m, index) : null)}\n // No `defaultItemHeight` — Virtuoso uses its first-item probe\n // pass. We previously fed it `120` which was wildly low for\n // chat bubbles (markdown + code blocks reach 500px+) and forced\n // virtuoso into a measure/reshape loop on every render: predicted\n // height << real height → page recompute → measure → repeat,\n // visible as jittery scrolling and bubbles \"blinking\" in and out.\n // The probe pass costs one extra render on mount; that's cheaper\n // than perpetual reshape.\n //\n // No `alignToBottom` — it only matters when the list is shorter\n // than the viewport (centers items near the bottom). Combined\n // with dynamic bubble heights it triggered the same measure loop:\n // virtuoso recomputes top padding on every size change to keep\n // the cluster bottom-aligned. `initialTopMostItemIndex` + the\n // mount-time imperative scroll already land us at the bottom on\n // open, which is what users actually want.\n //\n // No `increaseViewportBy` overscan — virtuoso's default (~0px)\n // is the right call for chat: every overscanned bubble re-renders\n // on every streaming token delta, so a 400px buffer means 3–4\n // extra bubbles re-rendering at 60Hz during a stream. Default\n // keeps the working set tight.\n initialTopMostItemIndex={messages.length > 0 ? messages.length - 1 : 0}\n atBottomThreshold={atBottomThreshold}\n followOutput={(isAtBottom) => (isAtBottom ? 'auto' : false)}\n scrollerRef={(el) => {\n scrollerRef.current = el;\n }}\n atBottomStateChange={(atBottom) => {\n // Force `true` when the list isn't scrollable — virtuoso's signal\n // can stall in `false` on short transcripts (no scroll events fire).\n reportAtBottom(!isScrollable ? true : atBottom);\n }}\n startReached={startReachedHandler}\n // Spinner while older history is loading. Rendering it as the\n // Header keeps it inside the virtualized scroll, so it doesn't\n // shift the viewport when it appears/disappears.\n //\n // Always pass an object — virtuoso indexes `components[name]`\n // internally without a null-guard, so passing `undefined` here\n // crashes with `d[l]` on any render where the empty-defaults\n // path runs (regression: ui-tools 2.1.369 first ship).\n components={\n isLoadingMore\n ? {\n Header: () => (\n <div className=\"flex justify-center py-2\">\n <Spinner className=\"size-4 text-muted-foreground\" />\n </div>\n ),\n }\n : EMPTY_COMPONENTS\n }\n />\n );\n});\n\n// Stable empty-components reference — passed when `isLoadingMore` is\n// false so virtuoso's `components[name]` lookups never see undefined.\nconst EMPTY_COMPONENTS = {} as const;\n","'use client';\n\nimport { type ReactNode, useMemo, useRef, useState } from 'react';\n\nimport { cn } from '@djangocfg/ui-core/lib';\n\nimport type { ChatAttachment, ChatConfig, ChatMessage, ChatTransport } from '../types';\nimport type { ChatAudioConfig } from '../core/audio/types';\nimport { ChatProvider, useChatContext, type ChatContextValue } from '../context';\nimport { useAutoFocusOnStreamEnd } from '../hooks/useAutoFocusOnStreamEnd';\nimport { useChatComposer, type UseChatComposerReturn } from '../hooks/useChatComposer';\nimport { useFocusOnEmptyClick } from '../hooks/useFocusOnEmptyClick';\nimport { Composer, type ComposerSize } from './Composer';\nimport { EmptyState } from './EmptyState';\nimport { ErrorBanner } from './ErrorBanner';\nimport { JumpToLatest } from './JumpToLatest';\nimport { MessageBubble } from './MessageBubble';\nimport { MessageList, type MessageListHandle } from './MessageList';\nimport type { AttachmentRendererMap } from './Attachments';\nimport type { ToolCallsProps } from './ToolCalls';\n\nexport interface ChatRootProps {\n // ---- core wiring -------------------------------------------------------\n transport: ChatTransport;\n config?: ChatConfig;\n initialSessionId?: string;\n autoCreateSession?: boolean;\n streaming?: boolean;\n /** Audio-trigger configuration. Off by default (no `sounds` map). */\n audio?: ChatAudioConfig;\n /**\n * Verbose dev-mode logging via `consola` (namespace `chat:*`).\n * Defaults to `isDev` from `@djangocfg/ui-core/lib`. Pass `false` to silence\n * even in development, or `true` to force on in production for debugging.\n */\n debug?: boolean;\n className?: string;\n\n // ---- named ReactNode slots --------------------------------------------\n /** Sticky banner above the message list (e.g. quota warning). */\n banner?: ReactNode;\n /** Header row below the banner — title / actions / session switcher. */\n header?: ReactNode;\n /** Footer slot below the composer (disclaimers, model picker). */\n footer?: ReactNode;\n /** Replaces the default `<EmptyState>` rendered when the conversation is empty. */\n empty?: ReactNode;\n /** Slot left of the textarea inside `<Composer>`. */\n composerToolbarStart?: ReactNode;\n /** Slot right of the textarea inside `<Composer>`. */\n composerToolbarEnd?: ReactNode;\n /** Replaces the default attachment tray inside `<Composer>`. */\n composerAttachmentTray?: ReactNode;\n /** Replaces the default `<JumpToLatest>` floating pill. */\n jumpToLatest?: ReactNode;\n\n // ---- render-prop slots (need access to data) --------------------------\n /** Replace `<MessageBubble>` per message. */\n renderMessage?: (m: ChatMessage, i: number) => ReactNode;\n /** Render the header lazily — receives the chat context. */\n renderHeader?: (ctx: ChatContextValue) => ReactNode;\n /** Render the empty-state lazily — receives a `setValue` to seed the composer. */\n renderEmpty?: (api: { setValue: (v: string) => void; focus: () => void }) => ReactNode;\n /** Forwarded into `<MessageBubble toolCallsProps>` so hosts can swap payload renderers. */\n toolCallsProps?: Omit<ToolCallsProps, 'calls'>;\n /** Per-type attachment renderers — `{ image, audio, video, file, default }`. */\n attachmentRenderers?: AttachmentRendererMap;\n /** Called when an attachment tile is clicked (e.g. open lightbox). */\n onAttachmentOpen?: (attachment: ChatAttachment) => void;\n\n // ---- composer customization -------------------------------------------\n /** Show the paperclip \"attach\" button in the composer. */\n showAttachmentButton?: boolean;\n /** Called when the user clicks the attach button (host opens its file picker). */\n onPickFiles?: () => void;\n /** Hide the composer input area entirely (e.g. while waiting for human approval). */\n hideComposer?: boolean;\n /** Composer size variant. Default ``md`` (36px slot). Use ``lg`` for primary\n * surfaces (onboarding, full-page chat), ``sm`` for dense sidebars. */\n composerSize?: ComposerSize;\n /** Extra className forwarded to the `<MessageList>` scroll container.\n * Use to add padding inside the scroll area so the scrollbar stays flush\n * with the edge (e.g. `\"px-6 pt-6 sm:px-8\"`). */\n listClassName?: string;\n /** Extra className forwarded to the `<Composer>` wrapper div. */\n composerClassName?: string;\n /**\n * Click in the message area → focus the composer (Slack / ChatGPT / Linear).\n * Honours selection drag, interactive elements, and touch input.\n * @default true\n */\n focusOnEmptyClick?: boolean;\n}\n\nexport function ChatRoot(props: ChatRootProps) {\n const { transport, config, initialSessionId, autoCreateSession, streaming, audio, debug, className, listClassName, ...slots } = props;\n return (\n <ChatProvider\n transport={transport}\n config={config}\n initialSessionId={initialSessionId}\n autoCreateSession={autoCreateSession}\n streaming={streaming}\n audio={audio}\n debug={debug}\n >\n <ChatRootShell className={className} listClassName={listClassName} slots={slots} />\n </ChatProvider>\n );\n}\n\ninterface ChatRootShellProps {\n className?: string;\n listClassName?: string;\n slots: Omit<ChatRootProps, 'transport' | 'config' | 'initialSessionId' | 'autoCreateSession' | 'streaming' | 'audio' | 'debug' | 'className' | 'listClassName'>;\n}\n\nfunction ChatRootShell({ className, listClassName, slots }: ChatRootShellProps) {\n const chat = useChatContext();\n const composer = useChatComposer({\n onSubmit: (content, attachments) => chat.sendMessage(content, attachments),\n disabled: chat.isStreaming,\n });\n const onMessagesMouseUp = useFocusOnEmptyClick({\n enabled: slots.focusOnEmptyClick !== false,\n });\n // Re-focus the composer on the streaming → idle edge. Was dropped in\n // a previous refactor — restored here so the standard chat UX (type\n // → send → read → keep typing without clicking) works again.\n useAutoFocusOnStreamEnd();\n // MessageList (virtuoso) owns the scroll viewport. We talk to it\n // via the imperative handle (scrollToBottom on JumpToLatest click)\n // and via the `onAtBottomChange` callback (drives the pill).\n const listRef = useRef<MessageListHandle | null>(null);\n const [isAtBottom, setIsAtBottom] = useState(true);\n // The id of the most-recent user-sent message. We pass it as\n // `scrollAnchorId` to MessageList so every send re-anchors the\n // viewport — fixes \"I sent a message but the chat didn't scroll\n // down\". Recomputed lazily; the resulting id only flips when a new\n // user message lands.\n const lastUserMessageId = useMemo(() => {\n const msgs = chat.messages;\n for (let i = msgs.length - 1; i >= 0; i -= 1) {\n if (msgs[i].role === 'user') return msgs[i].id;\n }\n return null;\n }, [chat.messages]);\n const handleStartReached = chat.hasMore && !chat.isLoadingMore\n ? () => void chat.loadMore()\n : undefined;\n\n const greeting = chat.config.greeting ?? 'How can I help?';\n const description = chat.config.description;\n const suggestions = chat.config.suggestions;\n\n const headerNode = slots.renderHeader ? slots.renderHeader(chat) : slots.header;\n\n const emptyNode = slots.empty\n ?? (slots.renderEmpty\n ? slots.renderEmpty({ setValue: composer.setValue, focus: composer.focus })\n : (\n <EmptyState\n greeting={greeting}\n description={description}\n suggestions={suggestions}\n onPickSuggestion={(prompt) => {\n composer.setValue(prompt);\n composer.focus();\n }}\n />\n ));\n\n const renderItem = slots.renderMessage\n ?? ((m: ChatMessage) => (\n <MessageBubble\n key={m.id}\n message={m}\n toolCallsProps={slots.toolCallsProps}\n attachmentRenderers={slots.attachmentRenderers}\n onAttachmentOpen={slots.onAttachmentOpen}\n onCopy={() => copy(m.content)}\n onRegenerate={() => void chat.regenerate(m.id)}\n onDelete={() => chat.deleteMessage(m.id)}\n />\n ));\n\n return (\n <div className={cn('relative flex h-full min-h-0 flex-col overflow-hidden', className)}>\n {slots.banner ?? null}\n {headerNode ?? null}\n <div className=\"relative flex min-h-0 flex-1 flex-col\" onMouseUp={onMessagesMouseUp}>\n <ErrorBanner\n error={chat.error}\n onDismiss={chat.error ? () => chat.clearMessages() : undefined}\n onRetry={chat.error ? () => void chat.regenerate() : undefined}\n />\n <MessageList\n ref={listRef}\n renderItem={renderItem}\n renderEmpty={() => <>{emptyNode}</>}\n className={listClassName}\n onStartReached={handleStartReached}\n onAtBottomChange={setIsAtBottom}\n scrollAnchorId={lastUserMessageId}\n />\n <div className=\"pointer-events-none absolute inset-x-0 bottom-2 flex justify-center\">\n {slots.jumpToLatest ?? (\n <JumpToLatest\n visible={!isAtBottom}\n onClick={() => listRef.current?.scrollToBottom(true)}\n />\n )}\n </div>\n </div>\n {!slots.hideComposer && (\n <Composer\n composer={composer}\n placeholder={chat.config.placeholder}\n showAttachmentButton={slots.showAttachmentButton}\n onPickFiles={slots.onPickFiles}\n toolbarStart={slots.composerToolbarStart}\n toolbarEnd={slots.composerToolbarEnd}\n attachmentTray={slots.composerAttachmentTray}\n size={slots.composerSize}\n />\n )}\n {slots.footer ?? null}\n </div>\n );\n}\n\nfunction copy(text: string) {\n if (typeof navigator !== 'undefined' && navigator.clipboard) {\n void navigator.clipboard.writeText(text);\n }\n}\n\n// re-export for convenience: composer hook return is a common slot dependency\nexport type { UseChatComposerReturn };\n"]}
@@ -1,8 +0,0 @@
1
- // Audio assets are bundled as base64 data URLs via tsup's `dataurl` loader
2
- // (see `tsup.config.ts`). This declaration lets TypeScript accept the
3
- // `import receivedSound from './sounds/received.mp3'` pattern.
4
-
5
- declare module '*.mp3' {
6
- const src: string;
7
- export default src;
8
- }