@devicai/ui 0.58.0 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/cjs/api/assistantInfo.js.map +1 -1
- package/dist/cjs/api/client.js +17 -1
- package/dist/cjs/api/client.js.map +1 -1
- package/dist/cjs/api/types.js.map +1 -1
- package/dist/cjs/components/AICommandBar/AICommandBar.js +2 -1
- package/dist/cjs/components/AICommandBar/AICommandBar.js.map +1 -1
- package/dist/cjs/components/AICommandBar/useAICommandBar.js +5 -1
- package/dist/cjs/components/AICommandBar/useAICommandBar.js.map +1 -1
- package/dist/cjs/components/AIElementWrapper/AIElementWrapper.js +2 -1
- package/dist/cjs/components/AIElementWrapper/AIElementWrapper.js.map +1 -1
- package/dist/cjs/components/AIElementWrapper/activeWrapperRegistry.js.map +1 -1
- package/dist/cjs/components/AIElementWrapper/useAIElementWrapper.js +5 -1
- package/dist/cjs/components/AIElementWrapper/useAIElementWrapper.js.map +1 -1
- package/dist/cjs/components/AIGenerationButton/AIGenerationButton.js +2 -1
- package/dist/cjs/components/AIGenerationButton/AIGenerationButton.js.map +1 -1
- package/dist/cjs/components/AIGenerationButton/useAIGenerationButton.js +5 -1
- package/dist/cjs/components/AIGenerationButton/useAIGenerationButton.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/ChatDrawer.js +2 -1
- package/dist/cjs/components/ChatDrawer/ChatDrawer.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/ChatInput.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/ChatMessages.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/CompactionWidget.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/ConversationSelector.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/ErrorBoundary.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/GuardrailNotice.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/HandoffSubagentWidget.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/LimitBanner.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/QueueNotice.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/RecalledMemoriesWidget.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/ReferenceChip.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/ToolTimeline.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/UsageBar.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/pastedText.js.map +1 -1
- package/dist/cjs/components/CoreMemoryModal/CoreMemoryModal.js.map +1 -1
- package/dist/cjs/components/Feedback/FeedbackModal.js.map +1 -1
- package/dist/cjs/components/Feedback/MessageActions.js.map +1 -1
- package/dist/cjs/components/IntegrationsModal/ConnectFieldsForm.js.map +1 -1
- package/dist/cjs/components/IntegrationsModal/IntegrationLogo.js.map +1 -1
- package/dist/cjs/components/IntegrationsModal/IntegrationsHint.js.map +1 -1
- package/dist/cjs/components/IntegrationsModal/IntegrationsLauncher.js.map +1 -1
- package/dist/cjs/components/IntegrationsModal/IntegrationsModal.js.map +1 -1
- package/dist/cjs/components/IntegrationsModal/IntegrationsPanel.js.map +1 -1
- package/dist/cjs/components/IntegrationsModal/IntegrationsToggle.js.map +1 -1
- package/dist/cjs/components/IntegrationsModal/McpConnectForm.js.map +1 -1
- package/dist/cjs/components/IntegrationsModal/McpServersSection.js.map +1 -1
- package/dist/cjs/components/IntegrationsModal/integrationChoice.js.map +1 -1
- package/dist/cjs/components/IntegrationsModal/useIntegrations.js.map +1 -1
- package/dist/cjs/components/IntegrationsModal/useTenantMcp.js.map +1 -1
- package/dist/cjs/components/ThreadStateTag/ThreadStateTag.js.map +1 -1
- package/dist/cjs/components/theme.js.map +1 -1
- package/dist/cjs/hooks/useDevicChat.js +10 -2
- package/dist/cjs/hooks/useDevicChat.js.map +1 -1
- package/dist/cjs/hooks/useModelInterface.js.map +1 -1
- package/dist/cjs/hooks/usePolling.js +117 -7
- package/dist/cjs/hooks/usePolling.js.map +1 -1
- package/dist/cjs/hooks/useSpeechRecording.js.map +1 -1
- package/dist/cjs/i18n/translate.js.map +1 -1
- package/dist/cjs/i18n/useTranslations.js.map +1 -1
- package/dist/cjs/provider/DevicContext.js.map +1 -1
- package/dist/cjs/provider/DevicProvider.js +3 -1
- package/dist/cjs/provider/DevicProvider.js.map +1 -1
- package/dist/cjs/provider/sharedSession.js.map +1 -1
- package/dist/cjs/utils/avatar.js.map +1 -1
- package/dist/cjs/utils/consumeChatStream.js +44 -0
- package/dist/cjs/utils/consumeChatStream.js.map +1 -0
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/logger.js.map +1 -1
- package/dist/cjs/utils/toolGroups.js.map +1 -1
- package/dist/esm/api/assistantInfo.js.map +1 -1
- package/dist/esm/api/client.d.ts +5 -1
- package/dist/esm/api/client.js +17 -1
- package/dist/esm/api/client.js.map +1 -1
- package/dist/esm/api/types.d.ts +2 -0
- package/dist/esm/api/types.js.map +1 -1
- package/dist/esm/components/AICommandBar/AICommandBar.js +2 -1
- package/dist/esm/components/AICommandBar/AICommandBar.js.map +1 -1
- package/dist/esm/components/AICommandBar/AICommandBar.types.d.ts +6 -0
- package/dist/esm/components/AICommandBar/useAICommandBar.d.ts +2 -0
- package/dist/esm/components/AICommandBar/useAICommandBar.js +6 -2
- package/dist/esm/components/AICommandBar/useAICommandBar.js.map +1 -1
- package/dist/esm/components/AIElementWrapper/AIElementWrapper.js +2 -1
- package/dist/esm/components/AIElementWrapper/AIElementWrapper.js.map +1 -1
- package/dist/esm/components/AIElementWrapper/AIElementWrapper.types.d.ts +6 -0
- package/dist/esm/components/AIElementWrapper/activeWrapperRegistry.js.map +1 -1
- package/dist/esm/components/AIElementWrapper/useAIElementWrapper.d.ts +2 -0
- package/dist/esm/components/AIElementWrapper/useAIElementWrapper.js +6 -2
- package/dist/esm/components/AIElementWrapper/useAIElementWrapper.js.map +1 -1
- package/dist/esm/components/AIGenerationButton/AIGenerationButton.js +2 -1
- package/dist/esm/components/AIGenerationButton/AIGenerationButton.js.map +1 -1
- package/dist/esm/components/AIGenerationButton/AIGenerationButton.types.d.ts +6 -0
- package/dist/esm/components/AIGenerationButton/useAIGenerationButton.d.ts +2 -0
- package/dist/esm/components/AIGenerationButton/useAIGenerationButton.js +6 -2
- package/dist/esm/components/AIGenerationButton/useAIGenerationButton.js.map +1 -1
- package/dist/esm/components/ChatDrawer/ChatDrawer.js +2 -1
- package/dist/esm/components/ChatDrawer/ChatDrawer.js.map +1 -1
- package/dist/esm/components/ChatDrawer/ChatDrawer.types.d.ts +8 -0
- package/dist/esm/components/ChatDrawer/ChatInput.js.map +1 -1
- package/dist/esm/components/ChatDrawer/ChatMessages.js.map +1 -1
- package/dist/esm/components/ChatDrawer/CompactionWidget.js.map +1 -1
- package/dist/esm/components/ChatDrawer/ConversationSelector.js.map +1 -1
- package/dist/esm/components/ChatDrawer/ErrorBoundary.js.map +1 -1
- package/dist/esm/components/ChatDrawer/GuardrailNotice.js.map +1 -1
- package/dist/esm/components/ChatDrawer/HandoffSubagentWidget.js.map +1 -1
- package/dist/esm/components/ChatDrawer/LimitBanner.js.map +1 -1
- package/dist/esm/components/ChatDrawer/QueueNotice.js.map +1 -1
- package/dist/esm/components/ChatDrawer/RecalledMemoriesWidget.js.map +1 -1
- package/dist/esm/components/ChatDrawer/ReferenceChip.js.map +1 -1
- package/dist/esm/components/ChatDrawer/ToolTimeline.js.map +1 -1
- package/dist/esm/components/ChatDrawer/UsageBar.js.map +1 -1
- package/dist/esm/components/ChatDrawer/pastedText.js.map +1 -1
- package/dist/esm/components/CoreMemoryModal/CoreMemoryModal.js.map +1 -1
- package/dist/esm/components/Feedback/FeedbackModal.js.map +1 -1
- package/dist/esm/components/Feedback/MessageActions.js.map +1 -1
- package/dist/esm/components/IntegrationsModal/ConnectFieldsForm.js.map +1 -1
- package/dist/esm/components/IntegrationsModal/IntegrationLogo.js.map +1 -1
- package/dist/esm/components/IntegrationsModal/IntegrationsHint.js.map +1 -1
- package/dist/esm/components/IntegrationsModal/IntegrationsLauncher.js.map +1 -1
- package/dist/esm/components/IntegrationsModal/IntegrationsModal.js.map +1 -1
- package/dist/esm/components/IntegrationsModal/IntegrationsPanel.js.map +1 -1
- package/dist/esm/components/IntegrationsModal/IntegrationsToggle.js.map +1 -1
- package/dist/esm/components/IntegrationsModal/McpConnectForm.js.map +1 -1
- package/dist/esm/components/IntegrationsModal/McpServersSection.js.map +1 -1
- package/dist/esm/components/IntegrationsModal/integrationChoice.js.map +1 -1
- package/dist/esm/components/IntegrationsModal/useIntegrations.js.map +1 -1
- package/dist/esm/components/IntegrationsModal/useTenantMcp.js.map +1 -1
- package/dist/esm/components/ThreadStateTag/ThreadStateTag.js.map +1 -1
- package/dist/esm/components/theme.js.map +1 -1
- package/dist/esm/hooks/index.d.ts +1 -1
- package/dist/esm/hooks/useDevicChat.d.ts +6 -0
- package/dist/esm/hooks/useDevicChat.js +12 -4
- package/dist/esm/hooks/useDevicChat.js.map +1 -1
- package/dist/esm/hooks/useModelInterface.js.map +1 -1
- package/dist/esm/hooks/usePolling.d.ts +35 -0
- package/dist/esm/hooks/usePolling.js +114 -8
- package/dist/esm/hooks/usePolling.js.map +1 -1
- package/dist/esm/hooks/useSpeechRecording.js.map +1 -1
- package/dist/esm/i18n/translate.js.map +1 -1
- package/dist/esm/i18n/useTranslations.js.map +1 -1
- package/dist/esm/provider/DevicContext.js.map +1 -1
- package/dist/esm/provider/DevicProvider.d.ts +1 -1
- package/dist/esm/provider/DevicProvider.js +3 -1
- package/dist/esm/provider/DevicProvider.js.map +1 -1
- package/dist/esm/provider/sharedSession.js.map +1 -1
- package/dist/esm/provider/types.d.ts +18 -0
- package/dist/esm/utils/avatar.js.map +1 -1
- package/dist/esm/utils/consumeChatStream.d.ts +6 -0
- package/dist/esm/utils/consumeChatStream.js +42 -0
- package/dist/esm/utils/consumeChatStream.js.map +1 -0
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/logger.js.map +1 -1
- package/dist/esm/utils/toolGroups.js.map +1 -1
- package/package.json +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatMessages.js","sources":["../../../../../src/components/ChatDrawer/ChatMessages.tsx"],"sourcesContent":["import React, { useState, useEffect, useMemo, useRef } from \"react\";\nimport { useOptionalDevicContext } from \"../../provider\";\nimport Markdown from \"markdown-to-jsx\";\nimport { MessageActions } from \"../Feedback\";\nimport { HandoffSubagentWidget } from \"./HandoffSubagentWidget\";\nimport { ReferenceChip } from \"./ReferenceChip\";\nimport { RecalledMemoriesWidget } from \"./RecalledMemoriesWidget\";\nimport { CompactionWidget } from \"./CompactionWidget\";\nimport { GuardrailNotice, type GuardrailPayload } from \"./GuardrailNotice\";\nimport type { ChatMessagesProps, SuggestedMessage } from \"./ChatDrawer.types\";\nimport type { ChatMessage, CompactionCheckpoint, RecalledMemoryRecord, ToolGroupConfig, ToolGroupCall } from \"../../api/types\";\nimport { normalizeMessageFile } from \"../../api/types\";\nimport type { FeedbackState } from \"../Feedback\";\nimport { segmentToolCalls } from \"../../utils/toolGroups\";\nimport { useTranslations } from \"../../i18n\";\nimport { DevicApiClient } from \"../../api/client\";\nimport {\n parsePastedBlocks,\n pastedPreview,\n pastedLineCount,\n type PastedText,\n} from \"./pastedText\";\nimport \"../Feedback/Feedback.css\";\n\n// Backend finalizer tool for assistants configured with \"Require Tool Use to\n// Finish\". It carries the final answer in its `message` argument, which the\n// backend copies to content.message, so it renders as a plain assistant bubble\n// instead of a tool activity line. Agents have a same-named tool with a\n// different shape, but their timeline does not go through this component.\nconst FINISH_EXECUTION_TOOL = \"finish_execution\";\n\n// Role of the message the backend appends when a guardrail stops a turn. It is\n// not something anyone said, so it renders as a notice rather than a bubble.\nconst GUARDRAIL_ROLE = \"guard_rail\";\n\n/**\n * `content.message` is typed as a string, but it does not always arrive as\n * one: a tripped guardrail puts the whole provider result object there. Every\n * text path downstream — the reference prefix, the pasted blocks, markdown —\n * assumes a string and throws on anything else, taking the drawer with it.\n * Read the field through here so a bad shape renders as nothing instead.\n */\nfunction readMessageText(message: ChatMessage): string | undefined {\n const raw = message.content?.message;\n return typeof raw === \"string\" ? raw : undefined;\n}\n\n/** The structured guardrail result, when one was sent instead of a sentence. */\nfunction guardrailPayload(message: ChatMessage): GuardrailPayload | undefined {\n const raw = message.content?.message as unknown;\n return raw && typeof raw === \"object\" ? (raw as GuardrailPayload) : undefined;\n}\n\n/**\n * Format timestamp to readable time\n */\nfunction formatTime(timestamp: number): string {\n return new Date(timestamp).toLocaleTimeString([], {\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\nfunction MicGlyph(): JSX.Element {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"23\" />\n </svg>\n );\n}\n\nfunction PlayGlyph(): JSX.Element {\n return (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n );\n}\n\nfunction PauseGlyph(): JSX.Element {\n return (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\">\n <rect x=\"6\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" />\n <rect x=\"14\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" />\n </svg>\n );\n}\n\n/**\n * Compact playback control shown on user messages that were dictated by voice\n * (i.e. carry a `transcriptId`). The source audio URL is resolved lazily on the\n * first play via GET /api/v1/whisper/:transcriptId, so listing a conversation\n * never triggers extra requests until the user actually wants to listen.\n */\nfunction TranscriptPlayback({\n transcriptId,\n apiKey,\n baseUrl,\n}: {\n transcriptId: string;\n apiKey?: string;\n baseUrl?: string;\n}): JSX.Element {\n const t = useTranslations();\n const devicContext = useOptionalDevicContext();\n const getTenantSession = devicContext?.getTenantSession;\n const onSessionExpired = devicContext?.onSessionExpired;\n const [isPlaying, setIsPlaying] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const audioUrlRef = useRef<string | null>(null);\n const audioRef = useRef<HTMLAudioElement | null>(null);\n\n useEffect(() => {\n return () => {\n if (audioRef.current) {\n audioRef.current.pause();\n audioRef.current = null;\n }\n };\n }, []);\n\n const resolveAudio = async (): Promise<HTMLAudioElement | null> => {\n if (audioRef.current) return audioRef.current;\n let url = audioUrlRef.current;\n if (!url) {\n if (!apiKey && !getTenantSession) {\n setError(t(\"Unavailable\"));\n return null;\n }\n setIsLoading(true);\n setError(null);\n try {\n const client = new DevicApiClient({\n apiKey,\n baseUrl: baseUrl || \"https://api.devic.ai\",\n getTenantSession,\n onSessionExpired,\n });\n const transcript = await client.getTranscript(transcriptId);\n url = transcript.audioUrl || null;\n audioUrlRef.current = url;\n } catch {\n setError(t(\"Audio unavailable\"));\n return null;\n } finally {\n setIsLoading(false);\n }\n }\n if (!url) {\n setError(t(\"Audio unavailable\"));\n return null;\n }\n const audio = new Audio(url);\n audio.onplay = () => setIsPlaying(true);\n audio.onpause = () => setIsPlaying(false);\n audio.onended = () => setIsPlaying(false);\n audio.onerror = () => {\n setError(t(\"Playback failed\"));\n setIsPlaying(false);\n };\n audioRef.current = audio;\n return audio;\n };\n\n const toggle = async () => {\n if (isPlaying && audioRef.current) {\n audioRef.current.pause();\n return;\n }\n const audio = await resolveAudio();\n if (audio) {\n try {\n await audio.play();\n } catch {\n setError(t(\"Playback failed\"));\n }\n }\n };\n\n return (\n <div\n className=\"devic-transcript-playback\"\n data-playing={isPlaying ? \"true\" : \"false\"}\n title={t(\"Dictated by voice\")}\n >\n <button\n type=\"button\"\n className=\"devic-transcript-btn\"\n onClick={toggle}\n disabled={isLoading}\n aria-label={isPlaying ? t(\"Pause recording\") : t(\"Play recording\")}\n >\n {isLoading ? (\n <span className=\"devic-transcript-spinner\" aria-hidden=\"true\" />\n ) : isPlaying ? (\n <PauseGlyph />\n ) : (\n <PlayGlyph />\n )}\n </button>\n <span className=\"devic-transcript-icon\" aria-hidden=\"true\">\n <MicGlyph />\n </span>\n <span className=\"devic-transcript-label\">\n {error || t(\"Voice message\")}\n </span>\n </div>\n );\n}\n\n/**\n * Groups consecutive tool-call assistant messages (no text content)\n * into { toolMessages, isActive } groups, interleaved with regular messages.\n */\nfunction groupMessages(\n messages: ChatMessage[],\n isLoading: boolean,\n): Array<\n | { type: \"message\"; message: ChatMessage }\n | { type: \"toolGroup\"; toolMessages: ChatMessage[]; isActive: boolean }\n> {\n const result: Array<\n | { type: \"message\"; message: ChatMessage }\n | { type: \"toolGroup\"; toolMessages: ChatMessage[]; isActive: boolean }\n > = [];\n\n let currentToolGroup: ChatMessage[] = [];\n\n const flushToolGroup = (isActive: boolean) => {\n if (currentToolGroup.length > 0) {\n result.push({\n type: \"toolGroup\",\n toolMessages: [...currentToolGroup],\n isActive,\n });\n currentToolGroup = [];\n }\n };\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n\n // Skip developer, system and tool response messages\n if (msg.role === \"developer\" || msg.role === \"system\" || msg.role === \"tool\") {\n continue;\n }\n\n // `finish_execution` is not an action the assistant took, it is how the\n // backend delivers the final answer when the assistant is configured with\n // \"Require Tool Use to Finish\": the tool's `message` argument is copied to\n // content.message and rendered as the assistant bubble below. Showing it as\n // a tool activity line would just duplicate that bubble with plumbing.\n const visibleToolCalls = (msg.tool_calls || []).filter(\n (toolCall) => toolCall.function?.name !== FINISH_EXECUTION_TOOL,\n );\n const hasToolCalls = visibleToolCalls.length > 0;\n const hasText = !!readMessageText(msg);\n const hasFiles = msg.content?.files && msg.content.files.length > 0;\n // A guardrail message is worth showing whatever its content turned out to\n // be: a turn that was stopped should say so, and the payload is often an\n // object rather than the text `hasText` looks for.\n const isGuardrail = msg.role === GUARDRAIL_ROLE;\n\n if (hasToolCalls) {\n // If message has both text and tool_calls, show text first\n if (hasText || hasFiles) {\n // Flush any prior tool group before inserting the text message\n const remainingMeaningful = messages\n .slice(i + 1)\n .some(\n (m) =>\n (m.role === \"assistant\" && m.content?.message) ||\n m.role === \"user\",\n );\n flushToolGroup(isLoading && !remainingMeaningful);\n result.push({ type: \"message\", message: msg });\n }\n // Always accumulate the tool call\n currentToolGroup.push(\n visibleToolCalls.length === msg.tool_calls!.length\n ? msg\n : { ...msg, tool_calls: visibleToolCalls },\n );\n } else {\n // Regular message → flush any accumulated tool group first\n const remainingMeaningful = messages\n .slice(i)\n .some(\n (m) =>\n (m.role === \"assistant\" && m.content?.message) || m.role === \"user\",\n );\n flushToolGroup(isLoading && !remainingMeaningful);\n\n if (hasText || hasFiles || isGuardrail) {\n result.push({ type: \"message\", message: msg });\n }\n }\n }\n\n // Flush remaining tool group (is active if still loading)\n flushToolGroup(isLoading);\n\n return result;\n}\n\n/**\n * Collapsible tool actions group\n */\nfunction ToolGroup({\n toolMessages,\n isActive,\n allMessages,\n toolRenderers,\n toolIcons,\n toolGroups,\n handedOffSubThreadId,\n onHandoffCompleted,\n handoffWidgetRenderer,\n apiKey,\n baseUrl,\n pollingInterval,\n}: {\n toolMessages: ChatMessage[];\n isActive: boolean;\n allMessages?: ChatMessage[];\n toolRenderers?: Record<string, (input: any, output: any) => React.ReactNode>;\n toolIcons?: Record<string, React.ReactNode>;\n toolGroups?: ToolGroupConfig[];\n handedOffSubThreadId?: string;\n onHandoffCompleted?: () => void;\n handoffWidgetRenderer?: ChatMessagesProps[\"handoffWidgetRenderer\"];\n apiKey?: string;\n baseUrl?: string;\n pollingInterval?: number;\n}): JSX.Element {\n const t = useTranslations();\n const [isCollapsed, setIsCollapsed] = useState(false);\n const shouldCollapse = toolMessages.length > 3 && !isActive;\n\n // Auto-collapse when transitioning from active to completed\n const wasActiveRef = useRef(isActive);\n useEffect(() => {\n if (wasActiveRef.current && !isActive && toolMessages.length > 3) {\n setIsCollapsed(true);\n }\n wasActiveRef.current = isActive;\n }, [isActive, toolMessages.length]);\n\n const lastIndex = toolMessages.length - 1;\n\n const renderToolItem = (\n msg: ChatMessage,\n opts: { active?: boolean; showSpinner?: boolean },\n ) => {\n const toolCall = msg.tool_calls?.[0];\n const toolName = toolCall?.function?.name;\n const summaryText =\n msg.summary ||\n toolName ||\n (opts.active ? t(\"Processing...\") : t(\"Completed\"));\n\n // Render HandoffSubagentWidget for hand_off_subagent tool calls\n if (toolName === \"hand_off_subagent\" && toolCall && allMessages) {\n const subThreadId = extractSubThreadId(\n toolCall.id,\n allMessages,\n handedOffSubThreadId,\n );\n if (subThreadId) {\n return (\n <HandoffSubagentWidget\n subThreadId={subThreadId}\n onCompleted={onHandoffCompleted}\n renderWidget={handoffWidgetRenderer}\n apiKey={apiKey}\n baseUrl={baseUrl}\n pollingInterval={pollingInterval}\n />\n );\n }\n }\n\n // Custom renderer for completed tools\n if (!opts.active && toolName && toolRenderers?.[toolName] && allMessages) {\n const toolResponse = allMessages.find(\n (m) => m.role === \"tool\" && m.tool_call_id === toolCall!.id,\n );\n let input: any = {};\n try {\n input = JSON.parse(toolCall!.function.arguments);\n } catch {}\n const output =\n toolResponse?.content?.data ||\n toolResponse?.content?.message ||\n toolResponse?.content;\n return toolRenderers[toolName](input, output);\n }\n\n const icon = opts.showSpinner ? (\n <SpinnerIcon />\n ) : (\n (toolName && toolIcons?.[toolName]) || <ToolDoneIcon />\n );\n\n return (\n <>\n <span className=\"devic-tool-activity-icon\">{icon}</span>\n <span\n className={`devic-tool-activity-text ${opts.active ? \"devic-glow-text\" : \"\"}`}\n >\n {summaryText}\n </span>\n </>\n );\n };\n\n /** Resolve a ChatMessage into a ToolGroupCall */\n const resolveToolGroupCall = (msg: ChatMessage): ToolGroupCall | null => {\n const toolCall = msg.tool_calls?.[0];\n if (!toolCall) return null;\n const toolName = toolCall.function?.name;\n let input: any = {};\n try {\n input = JSON.parse(toolCall.function.arguments);\n } catch {}\n const toolResponse = allMessages?.find(\n (m) => m.role === \"tool\" && m.tool_call_id === toolCall.id,\n );\n const output =\n toolResponse?.content?.data ||\n toolResponse?.content?.message ||\n toolResponse?.content;\n return { name: toolName, input, output, toolCallId: toolCall.id };\n };\n\n /** Render completed tool messages, applying toolGroups segmentation when configured */\n const renderCompletedItems = (msgs: ChatMessage[]) => {\n if (!toolGroups || toolGroups.length === 0) {\n return msgs.map((msg) => (\n <div key={msg.uid} className=\"devic-tool-activity\">\n {renderToolItem(msg, {})}\n </div>\n ));\n }\n\n // Build ToolGroupCall array for completed messages\n const calls: Array<{ msg: ChatMessage; call: ToolGroupCall }> = [];\n for (const msg of msgs) {\n const call = resolveToolGroupCall(msg);\n if (call) {\n calls.push({ msg, call });\n }\n }\n\n const segments = segmentToolCalls(\n calls.map((c) => c.call),\n toolGroups,\n );\n\n const elements: React.ReactNode[] = [];\n let callIdx = 0;\n\n for (const segment of segments) {\n if (segment.type === \"group\") {\n const groupKey = segment.calls\n .map((c) => c.toolCallId)\n .join(\"-\");\n elements.push(\n <div key={`tg-group-${groupKey}`} className=\"devic-tool-activity devic-tool-activity--grouped\">\n {segment.config.renderer(segment.calls)}\n </div>,\n );\n callIdx += segment.calls.length;\n } else {\n const entry = calls[callIdx];\n elements.push(\n <div key={entry.msg.uid} className=\"devic-tool-activity\">\n {renderToolItem(entry.msg, {})}\n </div>,\n );\n callIdx += 1;\n }\n }\n\n return elements;\n };\n\n // If active, show all items; last one gets the glow treatment\n if (isActive) {\n // For active groups: render all completed items with grouping, then render the active (last) item individually\n const completedMessages = toolMessages.slice(0, lastIndex);\n const lastMsg = toolMessages[lastIndex];\n\n return (\n <div className=\"devic-tool-group\">\n {completedMessages.length > 0 && renderCompletedItems(completedMessages)}\n <div\n key={lastMsg.uid}\n className=\"devic-tool-activity devic-tool-activity--active\"\n >\n {renderToolItem(lastMsg, { active: true, showSpinner: true })}\n </div>\n </div>\n );\n }\n\n // Completed: collapse if > 3 actions\n if (shouldCollapse && isCollapsed) {\n return (\n <div className=\"devic-tool-group\">\n <button\n className=\"devic-tool-collapse-btn\"\n onClick={() => setIsCollapsed(false)}\n type=\"button\"\n >\n <ToolDoneIcon />\n <span>{toolMessages.length} actions</span>\n <ChevronDownIcon />\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"devic-tool-group\">\n {shouldCollapse && (\n <button\n className=\"devic-tool-collapse-btn\"\n onClick={() => setIsCollapsed(true)}\n type=\"button\"\n >\n <span>{toolMessages.length} actions</span>\n <ChevronUpIcon />\n </button>\n )}\n <div className=\"devic-tool-group-items\" data-expanded=\"true\">\n {renderCompletedItems(toolMessages)}\n </div>\n </div>\n );\n}\n\n/**\n * Messages list component\n */\nconst markdownOverrides = {\n table: {\n component: ({ children, ...props }: any) =>\n React.createElement(\n \"div\",\n { className: \"markdown-table\" },\n React.createElement(\"table\", props, children),\n ),\n },\n};\n\n/**\n * Extract subthread ID from a hand_off_subagent tool call.\n * Checks the tool response in allMessages first, then falls back to handedOffSubThreadId.\n */\nfunction extractSubThreadId(\n toolCallId: string,\n allMessages: ChatMessage[],\n handedOffSubThreadId?: string,\n): string | null {\n // Look for the tool response message\n const toolResponse = allMessages.find(\n (m) => m.role === \"tool\" && m.tool_call_id === toolCallId,\n );\n if (toolResponse) {\n const content = toolResponse.content?.data || toolResponse.content;\n if (content && typeof content === \"object\" && \"subthreadId\" in content) {\n return (content as any).subthreadId;\n }\n if (content && typeof content === \"object\" && \"subThreadId\" in content) {\n return (content as any).subThreadId;\n }\n }\n // Fall back to active handoff subthread ID\n return handedOffSubThreadId || null;\n}\n\nexport function ChatMessages({\n messages,\n allMessages,\n isLoading,\n welcomeMessage,\n suggestedMessages,\n onSuggestedClick,\n toolRenderers,\n toolIcons,\n loadingIndicator,\n showFeedback = true,\n feedbackMap,\n onFeedback,\n handedOffSubThreadId,\n onHandoffCompleted,\n handoffWidgetRenderer,\n toolGroups,\n userMessageRenderer,\n assistantMessageRenderer,\n apiKey,\n baseUrl,\n pollingInterval,\n pendingInlineWidgets,\n onSubmitWidget,\n onCancelWidget,\n recalledMemories,\n recalledMemoriesRenderer,\n compactions,\n compaction,\n compactionRenderer,\n expandableCompaction,\n guardrailRenderer,\n}: ChatMessagesProps): JSX.Element {\n const t = useTranslations();\n const containerRef = useRef<HTMLDivElement>(null);\n const prevLengthRef = useRef(messages.length);\n\n // Anchor each recall record to the message that brought it in: the\n // assistant message carrying its memory tool call (toolCallId), or the\n // message the backend named (messageUid — matched against serverUid too,\n // since user messages may render under an adopted optimistic uid). Records\n // whose anchor is not on screen yet (the run is still producing it) go to\n // the pending group shown at the bottom while loading.\n const { recallsByAnchor, pendingRecalls } = useMemo(() => {\n const byAnchor = new Map<string, RecalledMemoryRecord[]>();\n const pending: RecalledMemoryRecord[] = [];\n for (const record of recalledMemories ?? []) {\n let anchor: string | undefined;\n if (record.toolCallId) {\n anchor = messages.find((m) =>\n m.tool_calls?.some((tc) => tc.id === record.toolCallId)\n )?.uid;\n }\n if (!anchor && record.messageUid) {\n anchor = messages.find(\n (m) =>\n m.uid === record.messageUid || m.serverUid === record.messageUid\n )?.uid;\n }\n if (anchor) {\n const list = byAnchor.get(anchor);\n if (list) list.push(record);\n else byAnchor.set(anchor, [record]);\n } else {\n pending.push(record);\n }\n }\n return { recallsByAnchor: byAnchor, pendingRecalls: pending };\n }, [recalledMemories, messages]);\n\n // The strip renders after the message (or tool group) that anchors it.\n const recallsFor = (uids: string[]): RecalledMemoryRecord[] =>\n uids.flatMap((uid) => recallsByAnchor.get(uid) ?? []);\n\n // Compaction checkpoints, keyed by the LAST message each one folded: the\n // point where the assistant's view of the conversation stops. A checkpoint\n // whose anchor is not on screen (it folded messages this client never\n // loaded) is drawn at the top instead, so the cut is never invisible.\n const { compactionsByAnchor, orphanCompactions, activeCompactionUid } =\n useMemo(() => {\n const byAnchor = new Map<string, CompactionCheckpoint[]>();\n const orphans: CompactionCheckpoint[] = [];\n for (const checkpoint of compactions ?? []) {\n const anchor = checkpoint.anchorMessageUid\n ? messages.find(\n (m) =>\n m.uid === checkpoint.anchorMessageUid ||\n m.serverUid === checkpoint.anchorMessageUid\n )?.uid\n : undefined;\n if (anchor) {\n const list = byAnchor.get(anchor);\n if (list) list.push(checkpoint);\n else byAnchor.set(anchor, [checkpoint]);\n } else {\n orphans.push(checkpoint);\n }\n }\n // Only the newest checkpoint governs the context: each compaction\n // merges the previous summary into itself.\n const active = (compactions ?? []).reduce<CompactionCheckpoint | null>(\n (latest, candidate) =>\n !latest || candidate.index > latest.index ? candidate : latest,\n null\n );\n return {\n compactionsByAnchor: byAnchor,\n orphanCompactions: orphans,\n activeCompactionUid: active?.uid,\n };\n }, [compactions, messages]);\n\n const compactionsFor = (uids: string[]): CompactionCheckpoint[] =>\n uids.flatMap((uid) => compactionsByAnchor.get(uid) ?? []);\n\n const renderCompactions = (checkpoints: CompactionCheckpoint[]) =>\n checkpoints.map((checkpoint) => (\n <CompactionWidget\n key={checkpoint.uid}\n checkpoint={checkpoint}\n isActive={checkpoint.uid === activeCompactionUid}\n renderer={compactionRenderer}\n expandable={expandableCompaction}\n />\n ));\n\n // Auto-scroll to bottom when new messages arrive\n useEffect(() => {\n if (containerRef.current) {\n containerRef.current.scrollTop = containerRef.current.scrollHeight;\n }\n prevLengthRef.current = messages.length;\n }, [messages.length, isLoading]);\n\n const grouped = groupMessages(messages, isLoading);\n\n // Show loading dots only if there's no active tool group at the end\n const lastGroup = grouped[grouped.length - 1];\n const showLoadingDots =\n isLoading && !(lastGroup?.type === \"toolGroup\" && lastGroup.isActive);\n\n return (\n <div className=\"devic-messages-container\" ref={containerRef}>\n {messages.length === 0 &&\n !isLoading &&\n (welcomeMessage || suggestedMessages?.length) && (\n <div className=\"devic-welcome\">\n {welcomeMessage && (\n <p className=\"devic-welcome-text\">{welcomeMessage}</p>\n )}\n {suggestedMessages && suggestedMessages.length > 0 && (\n <div className=\"devic-suggested-messages\">\n {suggestedMessages.map((msg, idx) => {\n const isObject = typeof msg === \"object\" && msg !== null;\n const content = isObject ? (msg as SuggestedMessage).content : msg;\n const message = isObject ? (msg as SuggestedMessage).message : (msg as string);\n return (\n <button\n key={idx}\n className=\"devic-suggested-btn\"\n onClick={() => onSuggestedClick?.(message)}\n >\n {content}\n </button>\n );\n })}\n </div>\n )}\n </div>\n )}\n\n {grouped.map((item) => {\n if (item.type === \"toolGroup\") {\n const groupRecalls = recallsFor(\n item.toolMessages.map((m) => m.uid)\n );\n const groupCompactions = compactionsFor(\n item.toolMessages.map((m) => m.uid)\n );\n return (\n <React.Fragment key={`tg-${item.toolMessages[0].uid}`}>\n <ToolGroup\n toolMessages={item.toolMessages}\n isActive={item.isActive}\n allMessages={allMessages}\n toolRenderers={toolRenderers}\n toolIcons={toolIcons}\n toolGroups={toolGroups}\n handedOffSubThreadId={handedOffSubThreadId}\n onHandoffCompleted={onHandoffCompleted}\n handoffWidgetRenderer={handoffWidgetRenderer}\n apiKey={apiKey}\n baseUrl={baseUrl}\n pollingInterval={pollingInterval}\n />\n {groupRecalls.length > 0 && (\n <RecalledMemoriesWidget\n records={groupRecalls}\n isLoading={isLoading}\n renderer={recalledMemoriesRenderer}\n />\n )}\n {renderCompactions(groupCompactions)}\n </React.Fragment>\n );\n }\n\n const message = item.message;\n\n // A stopped turn is not a bubble from either side: rendering it as one\n // sent it down the user-message path, which parses its text and threw\n // on the object a guardrail actually sends.\n if (message.role === GUARDRAIL_ROLE) {\n const noticeProps = {\n payload: guardrailPayload(message),\n text: readMessageText(message),\n };\n return (\n <React.Fragment key={message.uid}>\n {guardrailRenderer ? (\n guardrailRenderer(noticeProps)\n ) : (\n <GuardrailNotice {...noticeProps} />\n )}\n </React.Fragment>\n );\n }\n\n const rawText = readMessageText(message);\n const hasFiles =\n message.content?.files && message.content.files.length > 0;\n const isAssistant = message.role === \"assistant\";\n const currentFeedback = feedbackMap?.get(message.uid) || \"none\";\n\n // Extract reference chips from user messages (sent by AIElementWrapper).\n // The ChatDrawer prefixes user messages with:\n // Elemento referenciado: \"label1\", \"label2\"\\n\\n<actual message>\n // We render the labels as chips and only display the actual message\n // text inside the bubble.\n const parsed = !isAssistant && rawText\n ? parseReferencedPrefix(rawText)\n : null;\n const messageText = parsed ? parsed.cleanContent : rawText;\n const refLabels = parsed ? parsed.references : [];\n\n // Long pasted text travels inside the message but is shown as a card,\n // so the bubble renders what the user actually typed. Runs after the\n // reference prefix, which ChatDrawer prepends to the composed message.\n const pasted = !isAssistant && messageText\n ? parsePastedBlocks(messageText)\n : null;\n const bodyText = pasted ? pasted.cleanContent : messageText;\n const pastedBlocks = pasted ? pasted.blocks : [];\n\n // A custom bubble renderer (per role) fully replaces the default\n // markdown rendering of the message text.\n const bubbleRenderer = isAssistant\n ? assistantMessageRenderer\n : userMessageRenderer;\n\n const messageRecalls = recallsFor([message.uid]);\n const messageCompactions = compactionsFor([message.uid]);\n\n return (\n <React.Fragment key={message.uid}>\n <div\n className=\"devic-message\"\n data-role={message.role}\n // Accepted but not seen by the model yet. Drawn as a message that\n // has not landed, so it is not mistaken for something the assistant\n // has already read.\n data-queued={message.queued ? 'true' : undefined}\n >\n {refLabels.length > 0 && (\n <div className=\"devic-message-references\">\n {refLabels.map((lbl, i) => (\n <ReferenceChip key={i} label={lbl} variant=\"message\" />\n ))}\n </div>\n )}\n <div className=\"devic-message-bubble\">\n {pastedBlocks.length > 0 && (\n <div className=\"devic-message-pasted\">\n {pastedBlocks.map((block) => (\n <PastedBlockCard key={block.id} block={block} />\n ))}\n </div>\n )}\n {bodyText ? (\n bubbleRenderer ? (\n bubbleRenderer({\n message,\n content: bodyText,\n role: isAssistant ? \"assistant\" : \"user\",\n references: refLabels,\n })\n ) : (\n <Markdown options={{ overrides: markdownOverrides }}>\n {bodyText}\n </Markdown>\n )\n ) : null}\n {hasFiles && (\n <div className=\"devic-message-files\">\n {message.content!.files!.map((raw, fileIdx) => {\n const file = normalizeMessageFile(raw);\n return file.type === \"image\" && file.url ? (\n <a\n key={fileIdx}\n className=\"devic-message-file-image\"\n href={file.url}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n <img src={file.url} alt={file.name} />\n </a>\n ) : (\n <div key={fileIdx} className=\"devic-message-file\">\n <FileIcon />\n <span>{file.name}</span>\n </div>\n );\n })}\n </div>\n )}\n {!isAssistant && message.transcriptId && (\n <TranscriptPlayback\n transcriptId={message.transcriptId}\n apiKey={apiKey}\n baseUrl={baseUrl}\n />\n )}\n </div>\n <div className=\"devic-message-footer\">\n {message.queued && (\n <span className=\"devic-message-queued-label\">\n <QueuedIcon />\n {t(\"Queued\")}\n </span>\n )}\n <span className=\"devic-message-time\">\n {formatTime(message.timestamp)}\n </span>\n {isAssistant && showFeedback && onFeedback && (\n <MessageActions\n messageId={message.uid}\n messageContent={messageText}\n currentFeedback={currentFeedback as FeedbackState}\n onFeedback={onFeedback}\n showCopy={true}\n showFeedback={true}\n />\n )}\n </div>\n </div>\n {messageRecalls.length > 0 && (\n <RecalledMemoriesWidget\n records={messageRecalls}\n isLoading={isLoading}\n renderer={recalledMemoriesRenderer}\n />\n )}\n {renderCompactions(messageCompactions)}\n </React.Fragment>\n );\n })}\n\n {/* Recall events whose anchor message has not landed yet — shown while\n the run is in flight so the user sees what the assistant recalled\n before the first response arrives. */}\n {isLoading && pendingRecalls.length > 0 && (\n <RecalledMemoriesWidget\n records={pendingRecalls}\n isLoading={isLoading}\n renderer={recalledMemoriesRenderer}\n />\n )}\n\n {/* Checkpoints whose anchor message is not on screen — this client only\n loaded the messages that still travel, so the cut has nowhere to sit\n in the thread. Shown here rather than dropped: the conversation is\n shorter than it looks, and that is worth saying. */}\n {renderCompactions(orphanCompactions)}\n\n {/* A compaction being written right now. It is a model call of its own,\n taken between two assistant messages, so without this the\n conversation simply appears to have gone quiet. */}\n {compaction?.state === \"running\" && (\n <CompactionWidget\n checkpoint={null}\n activity={compaction}\n renderer={compactionRenderer}\n />\n )}\n\n {pendingInlineWidgets && pendingInlineWidgets.length > 0 && (\n <div className=\"devic-inline-widgets\">\n {pendingInlineWidgets.map((wc) => {\n const WidgetComponent = wc.widget.component;\n return (\n <div\n key={wc.toolCall.id}\n className=\"devic-inline-widget\"\n data-tool-name={wc.toolName}\n >\n <WidgetComponent\n toolCall={wc.toolCall}\n params={wc.params}\n submit={(response) => onSubmitWidget?.(wc.toolCall.id, response)}\n cancel={(reason) => onCancelWidget?.(wc.toolCall.id, reason)}\n />\n </div>\n );\n })}\n </div>\n )}\n\n {showLoadingDots &&\n (loadingIndicator ? (\n <div className=\"devic-loading\">{loadingIndicator}</div>\n ) : (\n <div className=\"devic-loading\">\n <span className=\"devic-loading-dot\"></span>\n <span className=\"devic-loading-dot\"></span>\n <span className=\"devic-loading-dot\"></span>\n </div>\n ))}\n </div>\n );\n}\n\n/* ── Icons ── */\n\nfunction SpinnerIcon(): JSX.Element {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n className=\"devic-spinner\"\n >\n <path d=\"M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83\" />\n </svg>\n );\n}\n\nfunction ToolDoneIcon(): JSX.Element {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"20,6 9,17 4,12\" />\n </svg>\n );\n}\n\nfunction ChevronDownIcon(): JSX.Element {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"6,9 12,15 18,9\" />\n </svg>\n );\n}\n\nfunction ChevronUpIcon(): JSX.Element {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"6,15 12,9 18,15\" />\n </svg>\n );\n}\n\n/** Small clock on a queued bubble's footer. */\nfunction QueuedIcon(): JSX.Element {\n return (\n <svg\n width=\"11\"\n height=\"11\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <polyline points=\"12 7 12 12 15 14\" />\n </svg>\n );\n}\n\nfunction FileIcon(): JSX.Element {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14,2 14,8 20,8\" />\n </svg>\n );\n}\n\n/**\n * Extracts the \"Elemento referenciado: ...\" prefix that ChatDrawer prepends\n * to user messages when AIElementWrapper references are active. Returns the\n * parsed labels and the message text without the prefix. Returns null when\n * the content does not start with the prefix.\n */\nconst REFERENCE_PREFIX_RE =\n /^Elemento referenciado: ((?:\"[^\"]+\")(?:, \"[^\"]+\")*)\\n\\n([\\s\\S]*)$/;\n\nfunction parseReferencedPrefix(\n content: string\n): { references: string[]; cleanContent: string } | null {\n const m = content.match(REFERENCE_PREFIX_RE);\n if (!m) return null;\n const labels = (m[1].match(/\"([^\"]+)\"/g) || []).map((s) =>\n s.slice(1, -1)\n );\n return { references: labels, cleanContent: m[2] };\n}\n\n/**\n * A block of pasted text inside a sent message: collapsed to a card by default,\n * expandable to read the whole thing without leaving the thread.\n */\nfunction PastedBlockCard({ block }: { block: PastedText }): JSX.Element {\n const t = useTranslations();\n const [expanded, setExpanded] = useState(false);\n\n return (\n <div className=\"devic-pasted-card\" data-expanded={expanded ? \"true\" : \"false\"}>\n <button\n type=\"button\"\n className=\"devic-pasted-card-toggle\"\n onClick={() => setExpanded((prev) => !prev)}\n aria-expanded={expanded}\n >\n {expanded ? (\n <pre className=\"devic-pasted-card-full\">{block.text}</pre>\n ) : (\n <p className=\"devic-pasted-card-preview\">{pastedPreview(block.text)}</p>\n )}\n <span className=\"devic-pasted-card-footer\">\n <span className=\"devic-pasted-card-badge\">{t(\"PASTED\")}</span>\n <span className=\"devic-pasted-card-meta\">\n {t(\"{count} lines\", { count: pastedLineCount(block.text) })} ·{\" \"}\n {expanded ? t(\"collapse\") : t(\"expand\")}\n </span>\n </span>\n </button>\n </div>\n );\n}\n"],"names":["_jsxs","_jsx","useTranslations","useOptionalDevicContext","useState","useRef","useEffect","client","DevicApiClient","toolGroups","HandoffSubagentWidget","_Fragment","segmentToolCalls","useMemo","CompactionWidget","RecalledMemoriesWidget","GuardrailNotice","parsePastedBlocks","ReferenceChip","normalizeMessageFile","MessageActions","pastedPreview","pastedLineCount"],"mappings":";;;;;;;;;;;;;;;;;;AAwBA;AACA;AACA;AACA;AACA;AACA,MAAM,qBAAqB,GAAG,kBAAkB;AAEhD;AACA;AACA,MAAM,cAAc,GAAG,YAAY;AAEnC;;;;;;AAMG;AACH,SAAS,eAAe,CAAC,OAAoB,EAAA;AAC3C,IAAA,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO;AACpC,IAAA,OAAO,OAAO,GAAG,KAAK,QAAQ,GAAG,GAAG,GAAG,SAAS;AAClD;AAEA;AACA,SAAS,gBAAgB,CAAC,OAAoB,EAAA;AAC5C,IAAA,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,OAAkB;AAC/C,IAAA,OAAO,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,GAAI,GAAwB,GAAG,SAAS;AAC/E;AAEA;;AAEG;AACH,SAAS,UAAU,CAAC,SAAiB,EAAA;IACnC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,kBAAkB,CAAC,EAAE,EAAE;AAChD,QAAA,IAAI,EAAE,SAAS;AACf,QAAA,MAAM,EAAE,SAAS;AAClB,KAAA,CAAC;AACJ;AAEA,SAAS,QAAQ,GAAA;AACf,IAAA,QACEA,eAAA,CAAA,KAAA,EAAA,EACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EAAA,aAAA,EACV,MAAM,EAAA,QAAA,EAAA,CAElBC,cAAA,CAAA,MAAA,EAAA,EAAM,CAAC,EAAC,sDAAsD,EAAA,CAAG,EACjEA,cAAA,CAAA,MAAA,EAAA,EAAM,CAAC,EAAC,4BAA4B,EAAA,CAAG,EACvCA,yBAAM,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAA,CAAG,CAAA,EAAA,CACpC;AAEV;AAEA,SAAS,SAAS,GAAA;IAChB,QACEA,cAAA,CAAA,KAAA,EAAA,EAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,cAAc,EAAA,aAAA,EAAa,MAAM,EAAA,QAAA,EACpFA,cAAA,CAAA,MAAA,EAAA,EAAM,CAAC,EAAC,eAAe,EAAA,CAAG,EAAA,CACtB;AAEV;AAEA,SAAS,UAAU,GAAA;AACjB,IAAA,QACED,eAAA,CAAA,KAAA,EAAA,EAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,cAAc,EAAA,aAAA,EAAa,MAAM,EAAA,QAAA,EAAA,CACpFC,cAAA,CAAA,MAAA,EAAA,EAAM,CAAC,EAAC,GAAG,EAAC,CAAC,EAAC,GAAG,EAAC,KAAK,EAAC,GAAG,EAAC,MAAM,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,EAAA,CAAG,EACjDA,cAAA,CAAA,MAAA,EAAA,EAAM,CAAC,EAAC,IAAI,EAAC,CAAC,EAAC,GAAG,EAAC,KAAK,EAAC,GAAG,EAAC,MAAM,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,EAAA,CAAG,CAAA,EAAA,CAC9C;AAEV;AAEA;;;;;AAKG;AACH,SAAS,kBAAkB,CAAC,EAC1B,YAAY,EACZ,MAAM,EACN,OAAO,GAKR,EAAA;AACC,IAAA,MAAM,CAAC,GAAGC,+BAAe,EAAE;AAC3B,IAAA,MAAM,YAAY,GAAGC,oCAAuB,EAAE;AAC9C,IAAA,MAAM,gBAAgB,GAAG,YAAY,EAAE,gBAAgB;AACvD,IAAA,MAAM,gBAAgB,GAAG,YAAY,EAAE,gBAAgB;IACvD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAGC,cAAQ,CAAC,KAAK,CAAC;IACjD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAGA,cAAQ,CAAC,KAAK,CAAC;IACjD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAGA,cAAQ,CAAgB,IAAI,CAAC;AACvD,IAAA,MAAM,WAAW,GAAGC,YAAM,CAAgB,IAAI,CAAC;AAC/C,IAAA,MAAM,QAAQ,GAAGA,YAAM,CAA0B,IAAI,CAAC;IAEtDC,eAAS,CAAC,MAAK;AACb,QAAA,OAAO,MAAK;AACV,YAAA,IAAI,QAAQ,CAAC,OAAO,EAAE;AACpB,gBAAA,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE;AACxB,gBAAA,QAAQ,CAAC,OAAO,GAAG,IAAI;YACzB;AACF,QAAA,CAAC;IACH,CAAC,EAAE,EAAE,CAAC;AAEN,IAAA,MAAM,YAAY,GAAG,YAA6C;QAChE,IAAI,QAAQ,CAAC,OAAO;YAAE,OAAO,QAAQ,CAAC,OAAO;AAC7C,QAAA,IAAI,GAAG,GAAG,WAAW,CAAC,OAAO;QAC7B,IAAI,CAAC,GAAG,EAAE;AACR,YAAA,IAAI,CAAC,MAAM,IAAI,CAAC,gBAAgB,EAAE;AAChC,gBAAA,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;AAC1B,gBAAA,OAAO,IAAI;YACb;YACA,YAAY,CAAC,IAAI,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC;AACd,YAAA,IAAI;AACF,gBAAA,MAAMC,QAAM,GAAG,IAAIC,qBAAc,CAAC;oBAChC,MAAM;oBACN,OAAO,EAAE,OAAO,IAAI,sBAAsB;oBAC1C,gBAAgB;oBAChB,gBAAgB;AACjB,iBAAA,CAAC;gBACF,MAAM,UAAU,GAAG,MAAMD,QAAM,CAAC,aAAa,CAAC,YAAY,CAAC;AAC3D,gBAAA,GAAG,GAAG,UAAU,CAAC,QAAQ,IAAI,IAAI;AACjC,gBAAA,WAAW,CAAC,OAAO,GAAG,GAAG;YAC3B;AAAE,YAAA,MAAM;AACN,gBAAA,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;AAChC,gBAAA,OAAO,IAAI;YACb;oBAAU;gBACR,YAAY,CAAC,KAAK,CAAC;YACrB;QACF;QACA,IAAI,CAAC,GAAG,EAAE;AACR,YAAA,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;AAChC,YAAA,OAAO,IAAI;QACb;AACA,QAAA,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC;QAC5B,KAAK,CAAC,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC;QACvC,KAAK,CAAC,OAAO,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC;QACzC,KAAK,CAAC,OAAO,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC;AACzC,QAAA,KAAK,CAAC,OAAO,GAAG,MAAK;AACnB,YAAA,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;YAC9B,YAAY,CAAC,KAAK,CAAC;AACrB,QAAA,CAAC;AACD,QAAA,QAAQ,CAAC,OAAO,GAAG,KAAK;AACxB,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;AAED,IAAA,MAAM,MAAM,GAAG,YAAW;AACxB,QAAA,IAAI,SAAS,IAAI,QAAQ,CAAC,OAAO,EAAE;AACjC,YAAA,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE;YACxB;QACF;AACA,QAAA,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE;QAClC,IAAI,KAAK,EAAE;AACT,YAAA,IAAI;AACF,gBAAA,MAAM,KAAK,CAAC,IAAI,EAAE;YACpB;AAAE,YAAA,MAAM;AACN,gBAAA,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;YAChC;QACF;AACF,IAAA,CAAC;IAED,QACEP,eAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAC,2BAA2B,EAAA,cAAA,EACvB,SAAS,GAAG,MAAM,GAAG,OAAO,EAC1C,KAAK,EAAE,CAAC,CAAC,mBAAmB,CAAC,EAAA,QAAA,EAAA,CAE7BC,cAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,sBAAsB,EAChC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,SAAS,EAAA,YAAA,EACP,SAAS,GAAG,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,gBAAgB,CAAC,EAAA,QAAA,EAEjE,SAAS,IACRA,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,0BAA0B,EAAA,aAAA,EAAa,MAAM,EAAA,CAAG,IAC9D,SAAS,IACXA,cAAA,CAAC,UAAU,EAAA,EAAA,CAAG,KAEdA,cAAA,CAAC,SAAS,EAAA,EAAA,CAAG,CACd,EAAA,CACM,EACTA,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,uBAAuB,EAAA,aAAA,EAAa,MAAM,EAAA,QAAA,EACxDA,cAAA,CAAC,QAAQ,EAAA,EAAA,CAAG,EAAA,CACP,EACPA,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,wBAAwB,EAAA,QAAA,EACrC,KAAK,IAAI,CAAC,CAAC,eAAe,CAAC,EAAA,CACvB,CAAA,EAAA,CACH;AAEV;AAEA;;;AAGG;AACH,SAAS,aAAa,CACpB,QAAuB,EACvB,SAAkB,EAAA;IAKlB,MAAM,MAAM,GAGR,EAAE;IAEN,IAAI,gBAAgB,GAAkB,EAAE;AAExC,IAAA,MAAM,cAAc,GAAG,CAAC,QAAiB,KAAI;AAC3C,QAAA,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE;YAC/B,MAAM,CAAC,IAAI,CAAC;AACV,gBAAA,IAAI,EAAE,WAAW;AACjB,gBAAA,YAAY,EAAE,CAAC,GAAG,gBAAgB,CAAC;gBACnC,QAAQ;AACT,aAAA,CAAC;YACF,gBAAgB,GAAG,EAAE;QACvB;AACF,IAAA,CAAC;AAED,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACxC,QAAA,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC;;AAGvB,QAAA,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE;YAC5E;QACF;;;;;;QAOA,MAAM,gBAAgB,GAAG,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,EAAE,MAAM,CACpD,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,EAAE,IAAI,KAAK,qBAAqB,CAChE;AACD,QAAA,MAAM,YAAY,GAAG,gBAAgB,CAAC,MAAM,GAAG,CAAC;QAChD,MAAM,OAAO,GAAG,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC;AACtC,QAAA,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,EAAE,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;;;;AAInE,QAAA,MAAM,WAAW,GAAG,GAAG,CAAC,IAAI,KAAK,cAAc;QAE/C,IAAI,YAAY,EAAE;;AAEhB,YAAA,IAAI,OAAO,IAAI,QAAQ,EAAE;;gBAEvB,MAAM,mBAAmB,GAAG;AACzB,qBAAA,KAAK,CAAC,CAAC,GAAG,CAAC;AACX,qBAAA,IAAI,CACH,CAAC,CAAC,KACA,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO;AAC7C,oBAAA,CAAC,CAAC,IAAI,KAAK,MAAM,CACpB;AACH,gBAAA,cAAc,CAAC,SAAS,IAAI,CAAC,mBAAmB,CAAC;AACjD,gBAAA,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YAChD;;YAEA,gBAAgB,CAAC,IAAI,CACnB,gBAAgB,CAAC,MAAM,KAAK,GAAG,CAAC,UAAW,CAAC;AAC1C,kBAAE;kBACA,EAAE,GAAG,GAAG,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAC7C;QACH;aAAO;;YAEL,MAAM,mBAAmB,GAAG;iBACzB,KAAK,CAAC,CAAC;iBACP,IAAI,CACH,CAAC,CAAC,KACA,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,CAAC,CAAC,IAAI,KAAK,MAAM,CACtE;AACH,YAAA,cAAc,CAAC,SAAS,IAAI,CAAC,mBAAmB,CAAC;AAEjD,YAAA,IAAI,OAAO,IAAI,QAAQ,IAAI,WAAW,EAAE;AACtC,gBAAA,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YAChD;QACF;IACF;;IAGA,cAAc,CAAC,SAAS,CAAC;AAEzB,IAAA,OAAO,MAAM;AACf;AAEA;;AAEG;AACH,SAAS,SAAS,CAAC,EACjB,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,aAAa,EACb,SAAS,cACTQ,YAAU,EACV,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,MAAM,EACN,OAAO,EACP,eAAe,GAchB,EAAA;AACC,IAAA,MAAM,CAAC,GAAGP,+BAAe,EAAE;IAC3B,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAGE,cAAQ,CAAC,KAAK,CAAC;IACrD,MAAM,cAAc,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ;;AAG3D,IAAA,MAAM,YAAY,GAAGC,YAAM,CAAC,QAAQ,CAAC;IACrCC,eAAS,CAAC,MAAK;AACb,QAAA,IAAI,YAAY,CAAC,OAAO,IAAI,CAAC,QAAQ,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE;YAChE,cAAc,CAAC,IAAI,CAAC;QACtB;AACA,QAAA,YAAY,CAAC,OAAO,GAAG,QAAQ;IACjC,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;AAEnC,IAAA,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC;AAEzC,IAAA,MAAM,cAAc,GAAG,CACrB,GAAgB,EAChB,IAAiD,KAC/C;QACF,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC;AACpC,QAAA,MAAM,QAAQ,GAAG,QAAQ,EAAE,QAAQ,EAAE,IAAI;AACzC,QAAA,MAAM,WAAW,GACf,GAAG,CAAC,OAAO;YACX,QAAQ;AACR,aAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC;;QAGrD,IAAI,QAAQ,KAAK,mBAAmB,IAAI,QAAQ,IAAI,WAAW,EAAE;AAC/D,YAAA,MAAM,WAAW,GAAG,kBAAkB,CACpC,QAAQ,CAAC,EAAE,EACX,WAAW,EACX,oBAAoB,CACrB;YACD,IAAI,WAAW,EAAE;AACf,gBAAA,QACEL,cAAA,CAACS,2CAAqB,EAAA,EACpB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,kBAAkB,EAC/B,YAAY,EAAE,qBAAqB,EACnC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,eAAe,EAAA,CAChC;YAEN;QACF;;AAGA,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,QAAQ,IAAI,aAAa,GAAG,QAAQ,CAAC,IAAI,WAAW,EAAE;YACxE,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CACnC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,YAAY,KAAK,QAAS,CAAC,EAAE,CAC5D;YACD,IAAI,KAAK,GAAQ,EAAE;AACnB,YAAA,IAAI;gBACF,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAS,CAAC,QAAQ,CAAC,SAAS,CAAC;YAClD;YAAE,MAAM,EAAC;AACT,YAAA,MAAM,MAAM,GACV,YAAY,EAAE,OAAO,EAAE,IAAI;gBAC3B,YAAY,EAAE,OAAO,EAAE,OAAO;gBAC9B,YAAY,EAAE,OAAO;YACvB,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC;QAC/C;AAEA,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,IAC3BT,cAAA,CAAC,WAAW,EAAA,EAAA,CAAG,KAEf,CAAC,QAAQ,IAAI,SAAS,GAAG,QAAQ,CAAC,KAAKA,cAAA,CAAC,YAAY,EAAA,EAAA,CAAG,CACxD;AAED,QAAA,QACED,eAAA,CAAAW,mBAAA,EAAA,EAAA,QAAA,EAAA,CACEV,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,0BAA0B,EAAA,QAAA,EAAE,IAAI,EAAA,CAAQ,EACxDA,cAAA,CAAA,MAAA,EAAA,EACE,SAAS,EAAE,CAAA,yBAAA,EAA4B,IAAI,CAAC,MAAM,GAAG,iBAAiB,GAAG,EAAE,CAAA,CAAE,EAAA,QAAA,EAE5E,WAAW,EAAA,CACP,CAAA,EAAA,CACN;AAEP,IAAA,CAAC;;AAGD,IAAA,MAAM,oBAAoB,GAAG,CAAC,GAAgB,KAA0B;QACtE,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC;AACpC,QAAA,IAAI,CAAC,QAAQ;AAAE,YAAA,OAAO,IAAI;AAC1B,QAAA,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI;QACxC,IAAI,KAAK,GAAQ,EAAE;AACnB,QAAA,IAAI;YACF,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QACjD;QAAE,MAAM,EAAC;QACT,MAAM,YAAY,GAAG,WAAW,EAAE,IAAI,CACpC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,YAAY,KAAK,QAAQ,CAAC,EAAE,CAC3D;AACD,QAAA,MAAM,MAAM,GACV,YAAY,EAAE,OAAO,EAAE,IAAI;YAC3B,YAAY,EAAE,OAAO,EAAE,OAAO;YAC9B,YAAY,EAAE,OAAO;AACvB,QAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE;AACnE,IAAA,CAAC;;AAGD,IAAA,MAAM,oBAAoB,GAAG,CAAC,IAAmB,KAAI;QACnD,IAAI,CAACQ,YAAU,IAAIA,YAAU,CAAC,MAAM,KAAK,CAAC,EAAE;AAC1C,YAAA,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,MAClBR,cAAA,CAAA,KAAA,EAAA,EAAmB,SAAS,EAAC,qBAAqB,EAAA,QAAA,EAC/C,cAAc,CAAC,GAAG,EAAE,EAAE,CAAC,EAAA,EADhB,GAAG,CAAC,GAAG,CAEX,CACP,CAAC;QACJ;;QAGA,MAAM,KAAK,GAAqD,EAAE;AAClE,QAAA,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;AACtB,YAAA,MAAM,IAAI,GAAG,oBAAoB,CAAC,GAAG,CAAC;YACtC,IAAI,IAAI,EAAE;gBACR,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;YAC3B;QACF;QAEA,MAAM,QAAQ,GAAGW,2BAAgB,CAC/B,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EACxBH,YAAU,CACX;QAED,MAAM,QAAQ,GAAsB,EAAE;QACtC,IAAI,OAAO,GAAG,CAAC;AAEf,QAAA,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;AAC9B,YAAA,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE;AAC5B,gBAAA,MAAM,QAAQ,GAAG,OAAO,CAAC;qBACtB,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU;qBACvB,IAAI,CAAC,GAAG,CAAC;gBACZ,QAAQ,CAAC,IAAI,CACXR,cAAA,CAAA,KAAA,EAAA,EAAkC,SAAS,EAAC,kDAAkD,EAAA,QAAA,EAC3F,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAA,EAD/B,YAAY,QAAQ,CAAA,CAAE,CAE1B,CACP;AACD,gBAAA,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM;YACjC;iBAAO;AACL,gBAAA,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC;gBAC5B,QAAQ,CAAC,IAAI,CACXA,cAAA,CAAA,KAAA,EAAA,EAAyB,SAAS,EAAC,qBAAqB,EAAA,QAAA,EACrD,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,EAAA,EADtB,KAAK,CAAC,GAAG,CAAC,GAAG,CAEjB,CACP;gBACD,OAAO,IAAI,CAAC;YACd;QACF;AAEA,QAAA,OAAO,QAAQ;AACjB,IAAA,CAAC;;IAGD,IAAI,QAAQ,EAAE;;QAEZ,MAAM,iBAAiB,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC;AAC1D,QAAA,MAAM,OAAO,GAAG,YAAY,CAAC,SAAS,CAAC;AAEvC,QAAA,QACED,eAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,kBAAkB,EAAA,QAAA,EAAA,CAC9B,iBAAiB,CAAC,MAAM,GAAG,CAAC,IAAI,oBAAoB,CAAC,iBAAiB,CAAC,EACxEC,cAAA,CAAA,KAAA,EAAA,EAEE,SAAS,EAAC,iDAAiD,YAE1D,cAAc,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,IAHxD,OAAO,CAAC,GAAG,CAIZ,CAAA,EAAA,CACF;IAEV;;AAGA,IAAA,IAAI,cAAc,IAAI,WAAW,EAAE;AACjC,QAAA,QACEA,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,kBAAkB,EAAA,QAAA,EAC/BD,4BACE,SAAS,EAAC,yBAAyB,EACnC,OAAO,EAAE,MAAM,cAAc,CAAC,KAAK,CAAC,EACpC,IAAI,EAAC,QAAQ,EAAA,QAAA,EAAA,CAEbC,eAAC,YAAY,EAAA,EAAA,CAAG,EAChBD,eAAA,CAAA,MAAA,EAAA,EAAA,QAAA,EAAA,CAAO,YAAY,CAAC,MAAM,EAAA,UAAA,CAAA,EAAA,CAAgB,EAC1CC,cAAA,CAAC,eAAe,KAAG,CAAA,EAAA,CACZ,EAAA,CACL;IAEV;IAEA,QACED,eAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,kBAAkB,aAC9B,cAAc,KACbA,eAAA,CAAA,QAAA,EAAA,EACE,SAAS,EAAC,yBAAyB,EACnC,OAAO,EAAE,MAAM,cAAc,CAAC,IAAI,CAAC,EACnC,IAAI,EAAC,QAAQ,aAEbA,eAAA,CAAA,MAAA,EAAA,EAAA,QAAA,EAAA,CAAO,YAAY,CAAC,MAAM,EAAA,UAAA,CAAA,EAAA,CAAgB,EAC1CC,eAAC,aAAa,EAAA,EAAA,CAAG,CAAA,EAAA,CACV,CACV,EACDA,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,wBAAwB,EAAA,eAAA,EAAe,MAAM,EAAA,QAAA,EACzD,oBAAoB,CAAC,YAAY,CAAC,EAAA,CAC/B,CAAA,EAAA,CACF;AAEV;AAEA;;AAEG;AACH,MAAM,iBAAiB,GAAG;AACxB,IAAA,KAAK,EAAE;AACL,QAAA,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAO,KACrC,KAAK,CAAC,aAAa,CACjB,KAAK,EACL,EAAE,SAAS,EAAE,gBAAgB,EAAE,EAC/B,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,CAC9C;AACJ,KAAA;CACF;AAED;;;AAGG;AACH,SAAS,kBAAkB,CACzB,UAAkB,EAClB,WAA0B,EAC1B,oBAA6B,EAAA;;IAG7B,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CACnC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,YAAY,KAAK,UAAU,CAC1D;IACD,IAAI,YAAY,EAAE;QAChB,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,IAAI,IAAI,YAAY,CAAC,OAAO;QAClE,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,aAAa,IAAI,OAAO,EAAE;YACtE,OAAQ,OAAe,CAAC,WAAW;QACrC;QACA,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,aAAa,IAAI,OAAO,EAAE;YACtE,OAAQ,OAAe,CAAC,WAAW;QACrC;IACF;;IAEA,OAAO,oBAAoB,IAAI,IAAI;AACrC;AAEM,SAAU,YAAY,CAAC,EAC3B,QAAQ,EACR,WAAW,EACX,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,YAAY,GAAG,IAAI,EACnB,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,UAAU,EACV,mBAAmB,EACnB,wBAAwB,EACxB,MAAM,EACN,OAAO,EACP,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,wBAAwB,EACxB,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,GACC,EAAA;AAClB,IAAA,MAAM,CAAC,GAAGC,+BAAe,EAAE;AAC3B,IAAA,MAAM,YAAY,GAAGG,YAAM,CAAiB,IAAI,CAAC;IACjD,MAAM,aAAa,GAAGA,YAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;;;;;;;IAQ7C,MAAM,EAAE,eAAe,EAAE,cAAc,EAAE,GAAGQ,aAAO,CAAC,MAAK;AACvD,QAAA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkC;QAC1D,MAAM,OAAO,GAA2B,EAAE;AAC1C,QAAA,KAAK,MAAM,MAAM,IAAI,gBAAgB,IAAI,EAAE,EAAE;AAC3C,YAAA,IAAI,MAA0B;AAC9B,YAAA,IAAI,MAAM,CAAC,UAAU,EAAE;AACrB,gBAAA,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,KACvB,CAAC,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,MAAM,CAAC,UAAU,CAAC,CACxD,EAAE,GAAG;YACR;AACA,YAAA,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,EAAE;AAChC,gBAAA,MAAM,GAAG,QAAQ,CAAC,IAAI,CACpB,CAAC,CAAC,KACA,CAAC,CAAC,GAAG,KAAK,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC,SAAS,KAAK,MAAM,CAAC,UAAU,CACnE,EAAE,GAAG;YACR;YACA,IAAI,MAAM,EAAE;gBACV,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;AACjC,gBAAA,IAAI,IAAI;AAAE,oBAAA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;;oBACtB,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;YACrC;iBAAO;AACL,gBAAA,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;YACtB;QACF;QACA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE;AAC/D,IAAA,CAAC,EAAE,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;;IAGhC,MAAM,UAAU,GAAG,CAAC,IAAc,KAChC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;;;;;IAMvD,MAAM,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,GACnEA,aAAO,CAAC,MAAK;AACX,QAAA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkC;QAC1D,MAAM,OAAO,GAA2B,EAAE;AAC1C,QAAA,KAAK,MAAM,UAAU,IAAI,WAAW,IAAI,EAAE,EAAE;AAC1C,YAAA,MAAM,MAAM,GAAG,UAAU,CAAC;AACxB,kBAAE,QAAQ,CAAC,IAAI,CACX,CAAC,CAAC,KACA,CAAC,CAAC,GAAG,KAAK,UAAU,CAAC,gBAAgB;oBACrC,CAAC,CAAC,SAAS,KAAK,UAAU,CAAC,gBAAgB,CAC9C,EAAE;kBACH,SAAS;YACb,IAAI,MAAM,EAAE;gBACV,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;AACjC,gBAAA,IAAI,IAAI;AAAE,oBAAA,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;;oBAC1B,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,CAAC;YACzC;iBAAO;AACL,gBAAA,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;YAC1B;QACF;;;AAGA,QAAA,MAAM,MAAM,GAAG,CAAC,WAAW,IAAI,EAAE,EAAE,MAAM,CACvC,CAAC,MAAM,EAAE,SAAS,KAChB,CAAC,MAAM,IAAI,SAAS,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,SAAS,GAAG,MAAM,EAChE,IAAI,CACL;QACD,OAAO;AACL,YAAA,mBAAmB,EAAE,QAAQ;AAC7B,YAAA,iBAAiB,EAAE,OAAO;YAC1B,mBAAmB,EAAE,MAAM,EAAE,GAAG;SACjC;AACH,IAAA,CAAC,EAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAE7B,MAAM,cAAc,GAAG,CAAC,IAAc,KACpC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IAE3D,MAAM,iBAAiB,GAAG,CAAC,WAAmC,KAC5D,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,MACzBZ,cAAA,CAACa,iCAAgB,EAAA,EAEf,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,UAAU,CAAC,GAAG,KAAK,mBAAmB,EAChD,QAAQ,EAAE,kBAAkB,EAC5B,UAAU,EAAE,oBAAoB,EAAA,EAJ3B,UAAU,CAAC,GAAG,CAKnB,CACH,CAAC;;IAGJR,eAAS,CAAC,MAAK;AACb,QAAA,IAAI,YAAY,CAAC,OAAO,EAAE;YACxB,YAAY,CAAC,OAAO,CAAC,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,YAAY;QACpE;AACA,QAAA,aAAa,CAAC,OAAO,GAAG,QAAQ,CAAC,MAAM;IACzC,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAEhC,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,EAAE,SAAS,CAAC;;IAGlD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;AAC7C,IAAA,MAAM,eAAe,GACnB,SAAS,IAAI,EAAE,SAAS,EAAE,IAAI,KAAK,WAAW,IAAI,SAAS,CAAC,QAAQ,CAAC;AAEvE,IAAA,QACEN,eAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,0BAA0B,EAAC,GAAG,EAAE,YAAY,EAAA,QAAA,EAAA,CACxD,QAAQ,CAAC,MAAM,KAAK,CAAC;AACpB,gBAAA,CAAC,SAAS;iBACT,cAAc,IAAI,iBAAiB,EAAE,MAAM,CAAC,KAC3CA,eAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,eAAe,EAAA,QAAA,EAAA,CAC3B,cAAc,KACbC,cAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAC,oBAAoB,EAAA,QAAA,EAAE,cAAc,EAAA,CAAK,CACvD,EACA,iBAAiB,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,KAChDA,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,0BAA0B,EAAA,QAAA,EACtC,iBAAiB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,KAAI;4BAClC,MAAM,QAAQ,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;AACxD,4BAAA,MAAM,OAAO,GAAG,QAAQ,GAAI,GAAwB,CAAC,OAAO,GAAG,GAAG;AAClE,4BAAA,MAAM,OAAO,GAAG,QAAQ,GAAI,GAAwB,CAAC,OAAO,GAAI,GAAc;4BAC9E,QACEA,2BAEE,SAAS,EAAC,qBAAqB,EAC/B,OAAO,EAAE,MAAM,gBAAgB,GAAG,OAAO,CAAC,EAAA,QAAA,EAEzC,OAAO,EAAA,EAJH,GAAG,CAKD;AAEb,wBAAA,CAAC,CAAC,EAAA,CACE,CACP,CAAA,EAAA,CACG,CACP,EAEF,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;AACpB,gBAAA,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE;oBAC7B,MAAM,YAAY,GAAG,UAAU,CAC7B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CACpC;oBACD,MAAM,gBAAgB,GAAG,cAAc,CACrC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CACpC;oBACD,QACED,gBAAC,KAAK,CAAC,QAAQ,EAAA,EAAA,QAAA,EAAA,CACbC,cAAA,CAAC,SAAS,EAAA,EACR,YAAY,EAAE,IAAI,CAAC,YAAY,EAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,UAAU,EACtB,oBAAoB,EAAE,oBAAoB,EAC1C,kBAAkB,EAAE,kBAAkB,EACtC,qBAAqB,EAAE,qBAAqB,EAC5C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,eAAe,EAAA,CAChC,EACD,YAAY,CAAC,MAAM,GAAG,CAAC,KACtBA,cAAA,CAACc,6CAAsB,IACrB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,wBAAwB,EAAA,CAClC,CACH,EACA,iBAAiB,CAAC,gBAAgB,CAAC,CAAA,EAAA,EAtBjB,MAAM,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA,CAAE,CAuBpC;gBAErB;AAEA,gBAAA,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO;;;;AAK5B,gBAAA,IAAI,OAAO,CAAC,IAAI,KAAK,cAAc,EAAE;AACnC,oBAAA,MAAM,WAAW,GAAG;AAClB,wBAAA,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC;AAClC,wBAAA,IAAI,EAAE,eAAe,CAAC,OAAO,CAAC;qBAC/B;AACD,oBAAA,QACEd,cAAA,CAAC,KAAK,CAAC,QAAQ,EAAA,EAAA,QAAA,EACZ,iBAAiB,IAChB,iBAAiB,CAAC,WAAW,CAAC,KAE9BA,cAAA,CAACe,+BAAe,OAAK,WAAW,EAAA,CAAI,CACrC,EAAA,EALkB,OAAO,CAAC,GAAG,CAMf;gBAErB;AAEA,gBAAA,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC;AACxC,gBAAA,MAAM,QAAQ,GACZ,OAAO,CAAC,OAAO,EAAE,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;AAC5D,gBAAA,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,KAAK,WAAW;AAChD,gBAAA,MAAM,eAAe,GAAG,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,MAAM;;;;;;AAO/D,gBAAA,MAAM,MAAM,GAAG,CAAC,WAAW,IAAI;AAC7B,sBAAE,qBAAqB,CAAC,OAAO;sBAC7B,IAAI;AACR,gBAAA,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC,YAAY,GAAG,OAAO;AAC1D,gBAAA,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC,UAAU,GAAG,EAAE;;;;AAKjD,gBAAA,MAAM,MAAM,GAAG,CAAC,WAAW,IAAI;AAC7B,sBAAEC,4BAAiB,CAAC,WAAW;sBAC7B,IAAI;AACR,gBAAA,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC,YAAY,GAAG,WAAW;AAC3D,gBAAA,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,EAAE;;;gBAIhD,MAAM,cAAc,GAAG;AACrB,sBAAE;sBACA,mBAAmB;gBAEvB,MAAM,cAAc,GAAG,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAChD,MAAM,kBAAkB,GAAG,cAAc,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAExD,QACEjB,eAAA,CAAC,KAAK,CAAC,QAAQ,EAAA,EAAA,QAAA,EAAA,CACfA,eAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAC,eAAe,EAAA,WAAA,EACd,OAAO,CAAC,IAAI,EAAA,aAAA,EAIV,OAAO,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,EAAA,QAAA,EAAA,CAE/C,SAAS,CAAC,MAAM,GAAG,CAAC,KACnBC,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,0BAA0B,EAAA,QAAA,EACtC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,MACpBA,cAAA,CAACiB,2BAAa,EAAA,EAAS,KAAK,EAAE,GAAG,EAAE,OAAO,EAAC,SAAS,EAAA,EAAhC,CAAC,CAAkC,CACxD,CAAC,EAAA,CACE,CACP,EACDlB,eAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,sBAAsB,EAAA,QAAA,EAAA,CAClC,YAAY,CAAC,MAAM,GAAG,CAAC,KACtBC,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,sBAAsB,EAAA,QAAA,EAClC,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,MACtBA,cAAA,CAAC,eAAe,EAAA,EAAgB,KAAK,EAAE,KAAK,EAAA,EAAtB,KAAK,CAAC,EAAE,CAAkB,CACjD,CAAC,EAAA,CACE,CACP,EACA,QAAQ,IACP,cAAc,IACZ,cAAc,CAAC;4CACb,OAAO;AACP,4CAAA,OAAO,EAAE,QAAQ;4CACjB,IAAI,EAAE,WAAW,GAAG,WAAW,GAAG,MAAM;AACxC,4CAAA,UAAU,EAAE,SAAS;yCACtB,CAAC,KAEFA,cAAA,CAAC,QAAQ,IAAC,OAAO,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAA,QAAA,EAChD,QAAQ,EAAA,CACA,CACZ,IACC,IAAI,EACP,QAAQ,KACPA,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,qBAAqB,YACjC,OAAO,CAAC,OAAQ,CAAC,KAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,KAAI;AAC5C,gDAAA,MAAM,IAAI,GAAGkB,0BAAoB,CAAC,GAAG,CAAC;AACtC,gDAAA,OAAO,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,GAAG,IACtClB,sBAEE,SAAS,EAAC,0BAA0B,EACpC,IAAI,EAAE,IAAI,CAAC,GAAG,EACd,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,EAAA,QAAA,EAEhBA,wBAAK,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAA,CAAI,EAAA,EANjC,OAAO,CAOV,KAEJD,eAAA,CAAA,KAAA,EAAA,EAAmB,SAAS,EAAC,oBAAoB,EAAA,QAAA,EAAA,CAC/CC,cAAA,CAAC,QAAQ,KAAG,EACZA,cAAA,CAAA,MAAA,EAAA,EAAA,QAAA,EAAO,IAAI,CAAC,IAAI,EAAA,CAAQ,CAAA,EAAA,EAFhB,OAAO,CAGX,CACP;AACH,4CAAA,CAAC,CAAC,EAAA,CACE,CACP,EACA,CAAC,WAAW,IAAI,OAAO,CAAC,YAAY,KACnCA,cAAA,CAAC,kBAAkB,EAAA,EACjB,YAAY,EAAE,OAAO,CAAC,YAAY,EAClC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAAA,CAChB,CACH,CAAA,EAAA,CACG,EACND,yBAAK,SAAS,EAAC,sBAAsB,EAAA,QAAA,EAAA,CAClC,OAAO,CAAC,MAAM,KACbA,eAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,4BAA4B,EAAA,QAAA,EAAA,CAC1CC,cAAA,CAAC,UAAU,EAAA,EAAA,CAAG,EACb,CAAC,CAAC,QAAQ,CAAC,CAAA,EAAA,CACP,CACR,EACDA,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,oBAAoB,EAAA,QAAA,EACjC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,GACzB,EACN,WAAW,IAAI,YAAY,IAAI,UAAU,KACxCA,eAACmB,6BAAc,EAAA,EACb,SAAS,EAAE,OAAO,CAAC,GAAG,EACtB,cAAc,EAAE,WAAW,EAC3B,eAAe,EAAE,eAAgC,EACjD,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,IAAI,EACd,YAAY,EAAE,IAAI,GAClB,CACH,CAAA,EAAA,CACG,CAAA,EAAA,CACF,EACL,cAAc,CAAC,MAAM,GAAG,CAAC,KACxBnB,cAAA,CAACc,6CAAsB,IACrB,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,wBAAwB,EAAA,CAClC,CACH,EACA,iBAAiB,CAAC,kBAAkB,CAAC,KAlGjB,OAAO,CAAC,GAAG,CAmGf;AAErB,YAAA,CAAC,CAAC,EAKD,SAAS,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,KACrCd,cAAA,CAACc,6CAAsB,EAAA,EACrB,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,wBAAwB,GAClC,CACH,EAMA,iBAAiB,CAAC,iBAAiB,CAAC,EAKpC,UAAU,EAAE,KAAK,KAAK,SAAS,KAC9Bd,cAAA,CAACa,iCAAgB,EAAA,EACf,UAAU,EAAE,IAAI,EAChB,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,kBAAkB,EAAA,CAC5B,CACH,EAEA,oBAAoB,IAAI,oBAAoB,CAAC,MAAM,GAAG,CAAC,KACtDb,wBAAK,SAAS,EAAC,sBAAsB,EAAA,QAAA,EAClC,oBAAoB,CAAC,GAAG,CAAC,CAAC,EAAE,KAAI;AAC/B,oBAAA,MAAM,eAAe,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS;AAC3C,oBAAA,QACEA,cAAA,CAAA,KAAA,EAAA,EAEE,SAAS,EAAC,qBAAqB,EAAA,gBAAA,EACf,EAAE,CAAC,QAAQ,EAAA,QAAA,EAE3BA,cAAA,CAAC,eAAe,EAAA,EACd,QAAQ,EAAE,EAAE,CAAC,QAAQ,EACrB,MAAM,EAAE,EAAE,CAAC,MAAM,EACjB,MAAM,EAAE,CAAC,QAAQ,KAAK,cAAc,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,EAChE,MAAM,EAAE,CAAC,MAAM,KAAK,cAAc,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,EAAA,CAC5D,EAAA,EATG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAUf;AAEV,gBAAA,CAAC,CAAC,EAAA,CACE,CACP,EAEA,eAAe;iBACb,gBAAgB,IACfA,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,eAAe,EAAA,QAAA,EAAE,gBAAgB,EAAA,CAAO,KAEvDD,eAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,eAAe,EAAA,QAAA,EAAA,CAC5BC,yBAAM,SAAS,EAAC,mBAAmB,EAAA,CAAQ,EAC3CA,yBAAM,SAAS,EAAC,mBAAmB,EAAA,CAAQ,EAC3CA,yBAAM,SAAS,EAAC,mBAAmB,EAAA,CAAQ,CAAA,EAAA,CACvC,CACP,CAAC,CAAA,EAAA,CACA;AAEV;AAEA;AAEA,SAAS,WAAW,GAAA;AAClB,IAAA,QACEA,cAAA,CAAA,KAAA,EAAA,EACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,EACrB,SAAS,EAAC,eAAe,EAAA,QAAA,EAEzBA,yBAAM,CAAC,EAAC,oHAAoH,EAAA,CAAG,EAAA,CAC3H;AAEV;AAEA,SAAS,YAAY,GAAA;AACnB,IAAA,QACEA,cAAA,CAAA,KAAA,EAAA,EACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EAAA,QAAA,EAEtBA,6BAAU,MAAM,EAAC,gBAAgB,EAAA,CAAG,EAAA,CAChC;AAEV;AAEA,SAAS,eAAe,GAAA;AACtB,IAAA,QACEA,cAAA,CAAA,KAAA,EAAA,EACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EAAA,QAAA,EAEtBA,6BAAU,MAAM,EAAC,gBAAgB,EAAA,CAAG,EAAA,CAChC;AAEV;AAEA,SAAS,aAAa,GAAA;AACpB,IAAA,QACEA,cAAA,CAAA,KAAA,EAAA,EACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EAAA,QAAA,EAEtBA,6BAAU,MAAM,EAAC,iBAAiB,EAAA,CAAG,EAAA,CACjC;AAEV;AAEA;AACA,SAAS,UAAU,GAAA;IACjB,QACED,eAAA,CAAA,KAAA,EAAA,EACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EAAA,aAAA,EACV,MAAM,EAAA,QAAA,EAAA,CAElBC,cAAA,CAAA,QAAA,EAAA,EAAQ,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,CAAC,EAAC,GAAG,EAAA,CAAG,EAChCA,cAAA,CAAA,UAAA,EAAA,EAAU,MAAM,EAAC,kBAAkB,EAAA,CAAG,CAAA,EAAA,CAClC;AAEV;AAEA,SAAS,QAAQ,GAAA;IACf,QACED,yBACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EAAA,QAAA,EAAA,CAEtBC,cAAA,CAAA,MAAA,EAAA,EAAM,CAAC,EAAC,4DAA4D,EAAA,CAAG,EACvEA,cAAA,CAAA,UAAA,EAAA,EAAU,MAAM,EAAC,gBAAgB,EAAA,CAAG,CAAA,EAAA,CAChC;AAEV;AAEA;;;;;AAKG;AACH,MAAM,mBAAmB,GACvB,mEAAmE;AAErE,SAAS,qBAAqB,CAC5B,OAAe,EAAA;IAEf,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC;AAC5C,IAAA,IAAI,CAAC,CAAC;AAAE,QAAA,OAAO,IAAI;AACnB,IAAA,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,KACpD,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CACf;AACD,IAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;AACnD;AAEA;;;AAGG;AACH,SAAS,eAAe,CAAC,EAAE,KAAK,EAAyB,EAAA;AACvD,IAAA,MAAM,CAAC,GAAGC,+BAAe,EAAE;IAC3B,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAGE,cAAQ,CAAC,KAAK,CAAC;AAE/C,IAAA,QACEH,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,mBAAmB,EAAA,eAAA,EAAgB,QAAQ,GAAG,MAAM,GAAG,OAAO,EAAA,QAAA,EAC3ED,eAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,0BAA0B,EACpC,OAAO,EAAE,MAAM,WAAW,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,EAAA,eAAA,EAC5B,QAAQ,EAAA,QAAA,EAAA,CAEtB,QAAQ,IACPC,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,wBAAwB,EAAA,QAAA,EAAE,KAAK,CAAC,IAAI,EAAA,CAAO,KAE1DA,cAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAC,2BAA2B,EAAA,QAAA,EAAEoB,wBAAa,CAAC,KAAK,CAAC,IAAI,CAAC,EAAA,CAAK,CACzE,EACDrB,eAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,0BAA0B,EAAA,QAAA,EAAA,CACxCC,yBAAM,SAAS,EAAC,yBAAyB,EAAA,QAAA,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAQ,EAC9DD,eAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,wBAAwB,EAAA,QAAA,EAAA,CACrC,CAAC,CAAC,eAAe,EAAE,EAAE,KAAK,EAAEsB,0BAAe,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,EAAA,SAAA,EAAI,GAAG,EACjE,QAAQ,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAA,EAAA,CAClC,CAAA,EAAA,CACF,CAAA,EAAA,CACA,EAAA,CACL;AAEV;;"}
|
|
1
|
+
{"version":3,"file":"ChatMessages.js","sources":["../../../../../src/components/ChatDrawer/ChatMessages.tsx"],"sourcesContent":["import React, { useState, useEffect, useMemo, useRef } from \"react\";\nimport { useOptionalDevicContext } from \"../../provider\";\nimport Markdown from \"markdown-to-jsx\";\nimport { MessageActions } from \"../Feedback\";\nimport { HandoffSubagentWidget } from \"./HandoffSubagentWidget\";\nimport { ReferenceChip } from \"./ReferenceChip\";\nimport { RecalledMemoriesWidget } from \"./RecalledMemoriesWidget\";\nimport { CompactionWidget } from \"./CompactionWidget\";\nimport { GuardrailNotice, type GuardrailPayload } from \"./GuardrailNotice\";\nimport type { ChatMessagesProps, SuggestedMessage } from \"./ChatDrawer.types\";\nimport type { ChatMessage, CompactionCheckpoint, RecalledMemoryRecord, ToolGroupConfig, ToolGroupCall } from \"../../api/types\";\nimport { normalizeMessageFile } from \"../../api/types\";\nimport type { FeedbackState } from \"../Feedback\";\nimport { segmentToolCalls } from \"../../utils/toolGroups\";\nimport { useTranslations } from \"../../i18n\";\nimport { DevicApiClient } from \"../../api/client\";\nimport {\n parsePastedBlocks,\n pastedPreview,\n pastedLineCount,\n type PastedText,\n} from \"./pastedText\";\nimport \"../Feedback/Feedback.css\";\n\n// Backend finalizer tool for assistants configured with \"Require Tool Use to\n// Finish\". It carries the final answer in its `message` argument, which the\n// backend copies to content.message, so it renders as a plain assistant bubble\n// instead of a tool activity line. Agents have a same-named tool with a\n// different shape, but their timeline does not go through this component.\nconst FINISH_EXECUTION_TOOL = \"finish_execution\";\n\n// Role of the message the backend appends when a guardrail stops a turn. It is\n// not something anyone said, so it renders as a notice rather than a bubble.\nconst GUARDRAIL_ROLE = \"guard_rail\";\n\n/**\n * `content.message` is typed as a string, but it does not always arrive as\n * one: a tripped guardrail puts the whole provider result object there. Every\n * text path downstream — the reference prefix, the pasted blocks, markdown —\n * assumes a string and throws on anything else, taking the drawer with it.\n * Read the field through here so a bad shape renders as nothing instead.\n */\nfunction readMessageText(message: ChatMessage): string | undefined {\n const raw = message.content?.message;\n return typeof raw === \"string\" ? raw : undefined;\n}\n\n/** The structured guardrail result, when one was sent instead of a sentence. */\nfunction guardrailPayload(message: ChatMessage): GuardrailPayload | undefined {\n const raw = message.content?.message as unknown;\n return raw && typeof raw === \"object\" ? (raw as GuardrailPayload) : undefined;\n}\n\n/**\n * Format timestamp to readable time\n */\nfunction formatTime(timestamp: number): string {\n return new Date(timestamp).toLocaleTimeString([], {\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\nfunction MicGlyph(): JSX.Element {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"23\" />\n </svg>\n );\n}\n\nfunction PlayGlyph(): JSX.Element {\n return (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n );\n}\n\nfunction PauseGlyph(): JSX.Element {\n return (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\">\n <rect x=\"6\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" />\n <rect x=\"14\" y=\"5\" width=\"4\" height=\"14\" rx=\"1\" />\n </svg>\n );\n}\n\n/**\n * Compact playback control shown on user messages that were dictated by voice\n * (i.e. carry a `transcriptId`). The source audio URL is resolved lazily on the\n * first play via GET /api/v1/whisper/:transcriptId, so listing a conversation\n * never triggers extra requests until the user actually wants to listen.\n */\nfunction TranscriptPlayback({\n transcriptId,\n apiKey,\n baseUrl,\n}: {\n transcriptId: string;\n apiKey?: string;\n baseUrl?: string;\n}): JSX.Element {\n const t = useTranslations();\n const devicContext = useOptionalDevicContext();\n const getTenantSession = devicContext?.getTenantSession;\n const onSessionExpired = devicContext?.onSessionExpired;\n const [isPlaying, setIsPlaying] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const audioUrlRef = useRef<string | null>(null);\n const audioRef = useRef<HTMLAudioElement | null>(null);\n\n useEffect(() => {\n return () => {\n if (audioRef.current) {\n audioRef.current.pause();\n audioRef.current = null;\n }\n };\n }, []);\n\n const resolveAudio = async (): Promise<HTMLAudioElement | null> => {\n if (audioRef.current) return audioRef.current;\n let url = audioUrlRef.current;\n if (!url) {\n if (!apiKey && !getTenantSession) {\n setError(t(\"Unavailable\"));\n return null;\n }\n setIsLoading(true);\n setError(null);\n try {\n const client = new DevicApiClient({\n apiKey,\n baseUrl: baseUrl || \"https://api.devic.ai\",\n getTenantSession,\n onSessionExpired,\n });\n const transcript = await client.getTranscript(transcriptId);\n url = transcript.audioUrl || null;\n audioUrlRef.current = url;\n } catch {\n setError(t(\"Audio unavailable\"));\n return null;\n } finally {\n setIsLoading(false);\n }\n }\n if (!url) {\n setError(t(\"Audio unavailable\"));\n return null;\n }\n const audio = new Audio(url);\n audio.onplay = () => setIsPlaying(true);\n audio.onpause = () => setIsPlaying(false);\n audio.onended = () => setIsPlaying(false);\n audio.onerror = () => {\n setError(t(\"Playback failed\"));\n setIsPlaying(false);\n };\n audioRef.current = audio;\n return audio;\n };\n\n const toggle = async () => {\n if (isPlaying && audioRef.current) {\n audioRef.current.pause();\n return;\n }\n const audio = await resolveAudio();\n if (audio) {\n try {\n await audio.play();\n } catch {\n setError(t(\"Playback failed\"));\n }\n }\n };\n\n return (\n <div\n className=\"devic-transcript-playback\"\n data-playing={isPlaying ? \"true\" : \"false\"}\n title={t(\"Dictated by voice\")}\n >\n <button\n type=\"button\"\n className=\"devic-transcript-btn\"\n onClick={toggle}\n disabled={isLoading}\n aria-label={isPlaying ? t(\"Pause recording\") : t(\"Play recording\")}\n >\n {isLoading ? (\n <span className=\"devic-transcript-spinner\" aria-hidden=\"true\" />\n ) : isPlaying ? (\n <PauseGlyph />\n ) : (\n <PlayGlyph />\n )}\n </button>\n <span className=\"devic-transcript-icon\" aria-hidden=\"true\">\n <MicGlyph />\n </span>\n <span className=\"devic-transcript-label\">\n {error || t(\"Voice message\")}\n </span>\n </div>\n );\n}\n\n/**\n * Groups consecutive tool-call assistant messages (no text content)\n * into { toolMessages, isActive } groups, interleaved with regular messages.\n */\nfunction groupMessages(\n messages: ChatMessage[],\n isLoading: boolean,\n): Array<\n | { type: \"message\"; message: ChatMessage }\n | { type: \"toolGroup\"; toolMessages: ChatMessage[]; isActive: boolean }\n> {\n const result: Array<\n | { type: \"message\"; message: ChatMessage }\n | { type: \"toolGroup\"; toolMessages: ChatMessage[]; isActive: boolean }\n > = [];\n\n let currentToolGroup: ChatMessage[] = [];\n\n const flushToolGroup = (isActive: boolean) => {\n if (currentToolGroup.length > 0) {\n result.push({\n type: \"toolGroup\",\n toolMessages: [...currentToolGroup],\n isActive,\n });\n currentToolGroup = [];\n }\n };\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n\n // Skip developer, system and tool response messages\n if (msg.role === \"developer\" || msg.role === \"system\" || msg.role === \"tool\") {\n continue;\n }\n\n // `finish_execution` is not an action the assistant took, it is how the\n // backend delivers the final answer when the assistant is configured with\n // \"Require Tool Use to Finish\": the tool's `message` argument is copied to\n // content.message and rendered as the assistant bubble below. Showing it as\n // a tool activity line would just duplicate that bubble with plumbing.\n const visibleToolCalls = (msg.tool_calls || []).filter(\n (toolCall) => toolCall.function?.name !== FINISH_EXECUTION_TOOL,\n );\n const hasToolCalls = visibleToolCalls.length > 0;\n const hasText = !!readMessageText(msg);\n const hasFiles = msg.content?.files && msg.content.files.length > 0;\n // A guardrail message is worth showing whatever its content turned out to\n // be: a turn that was stopped should say so, and the payload is often an\n // object rather than the text `hasText` looks for.\n const isGuardrail = msg.role === GUARDRAIL_ROLE;\n\n if (hasToolCalls) {\n // If message has both text and tool_calls, show text first\n if (hasText || hasFiles) {\n // Flush any prior tool group before inserting the text message\n const remainingMeaningful = messages\n .slice(i + 1)\n .some(\n (m) =>\n (m.role === \"assistant\" && m.content?.message) ||\n m.role === \"user\",\n );\n flushToolGroup(isLoading && !remainingMeaningful);\n result.push({ type: \"message\", message: msg });\n }\n // Always accumulate the tool call\n currentToolGroup.push(\n visibleToolCalls.length === msg.tool_calls!.length\n ? msg\n : { ...msg, tool_calls: visibleToolCalls },\n );\n } else {\n // Regular message → flush any accumulated tool group first\n const remainingMeaningful = messages\n .slice(i)\n .some(\n (m) =>\n (m.role === \"assistant\" && m.content?.message) || m.role === \"user\",\n );\n flushToolGroup(isLoading && !remainingMeaningful);\n\n if (hasText || hasFiles || isGuardrail) {\n result.push({ type: \"message\", message: msg });\n }\n }\n }\n\n // Flush remaining tool group (is active if still loading)\n flushToolGroup(isLoading);\n\n return result;\n}\n\n/**\n * Collapsible tool actions group\n */\nfunction ToolGroup({\n toolMessages,\n isActive,\n allMessages,\n toolRenderers,\n toolIcons,\n toolGroups,\n handedOffSubThreadId,\n onHandoffCompleted,\n handoffWidgetRenderer,\n apiKey,\n baseUrl,\n pollingInterval,\n}: {\n toolMessages: ChatMessage[];\n isActive: boolean;\n allMessages?: ChatMessage[];\n toolRenderers?: Record<string, (input: any, output: any) => React.ReactNode>;\n toolIcons?: Record<string, React.ReactNode>;\n toolGroups?: ToolGroupConfig[];\n handedOffSubThreadId?: string;\n onHandoffCompleted?: () => void;\n handoffWidgetRenderer?: ChatMessagesProps[\"handoffWidgetRenderer\"];\n apiKey?: string;\n baseUrl?: string;\n pollingInterval?: number;\n}): JSX.Element {\n const t = useTranslations();\n const [isCollapsed, setIsCollapsed] = useState(false);\n const shouldCollapse = toolMessages.length > 3 && !isActive;\n\n // Auto-collapse when transitioning from active to completed\n const wasActiveRef = useRef(isActive);\n useEffect(() => {\n if (wasActiveRef.current && !isActive && toolMessages.length > 3) {\n setIsCollapsed(true);\n }\n wasActiveRef.current = isActive;\n }, [isActive, toolMessages.length]);\n\n const lastIndex = toolMessages.length - 1;\n\n const renderToolItem = (\n msg: ChatMessage,\n opts: { active?: boolean; showSpinner?: boolean },\n ) => {\n const toolCall = msg.tool_calls?.[0];\n const toolName = toolCall?.function?.name;\n const summaryText =\n msg.summary ||\n toolName ||\n (opts.active ? t(\"Processing...\") : t(\"Completed\"));\n\n // Render HandoffSubagentWidget for hand_off_subagent tool calls\n if (toolName === \"hand_off_subagent\" && toolCall && allMessages) {\n const subThreadId = extractSubThreadId(\n toolCall.id,\n allMessages,\n handedOffSubThreadId,\n );\n if (subThreadId) {\n return (\n <HandoffSubagentWidget\n subThreadId={subThreadId}\n onCompleted={onHandoffCompleted}\n renderWidget={handoffWidgetRenderer}\n apiKey={apiKey}\n baseUrl={baseUrl}\n pollingInterval={pollingInterval}\n />\n );\n }\n }\n\n // Custom renderer for completed tools\n if (!opts.active && toolName && toolRenderers?.[toolName] && allMessages) {\n const toolResponse = allMessages.find(\n (m) => m.role === \"tool\" && m.tool_call_id === toolCall!.id,\n );\n let input: any = {};\n try {\n input = JSON.parse(toolCall!.function.arguments);\n } catch {}\n const output =\n toolResponse?.content?.data ||\n toolResponse?.content?.message ||\n toolResponse?.content;\n return toolRenderers[toolName](input, output);\n }\n\n const icon = opts.showSpinner ? (\n <SpinnerIcon />\n ) : (\n (toolName && toolIcons?.[toolName]) || <ToolDoneIcon />\n );\n\n return (\n <>\n <span className=\"devic-tool-activity-icon\">{icon}</span>\n <span\n className={`devic-tool-activity-text ${opts.active ? \"devic-glow-text\" : \"\"}`}\n >\n {summaryText}\n </span>\n </>\n );\n };\n\n /** Resolve a ChatMessage into a ToolGroupCall */\n const resolveToolGroupCall = (msg: ChatMessage): ToolGroupCall | null => {\n const toolCall = msg.tool_calls?.[0];\n if (!toolCall) return null;\n const toolName = toolCall.function?.name;\n let input: any = {};\n try {\n input = JSON.parse(toolCall.function.arguments);\n } catch {}\n const toolResponse = allMessages?.find(\n (m) => m.role === \"tool\" && m.tool_call_id === toolCall.id,\n );\n const output =\n toolResponse?.content?.data ||\n toolResponse?.content?.message ||\n toolResponse?.content;\n return { name: toolName, input, output, toolCallId: toolCall.id };\n };\n\n /** Render completed tool messages, applying toolGroups segmentation when configured */\n const renderCompletedItems = (msgs: ChatMessage[]) => {\n if (!toolGroups || toolGroups.length === 0) {\n return msgs.map((msg) => (\n <div key={msg.uid} className=\"devic-tool-activity\">\n {renderToolItem(msg, {})}\n </div>\n ));\n }\n\n // Build ToolGroupCall array for completed messages\n const calls: Array<{ msg: ChatMessage; call: ToolGroupCall }> = [];\n for (const msg of msgs) {\n const call = resolveToolGroupCall(msg);\n if (call) {\n calls.push({ msg, call });\n }\n }\n\n const segments = segmentToolCalls(\n calls.map((c) => c.call),\n toolGroups,\n );\n\n const elements: React.ReactNode[] = [];\n let callIdx = 0;\n\n for (const segment of segments) {\n if (segment.type === \"group\") {\n const groupKey = segment.calls\n .map((c) => c.toolCallId)\n .join(\"-\");\n elements.push(\n <div key={`tg-group-${groupKey}`} className=\"devic-tool-activity devic-tool-activity--grouped\">\n {segment.config.renderer(segment.calls)}\n </div>,\n );\n callIdx += segment.calls.length;\n } else {\n const entry = calls[callIdx];\n elements.push(\n <div key={entry.msg.uid} className=\"devic-tool-activity\">\n {renderToolItem(entry.msg, {})}\n </div>,\n );\n callIdx += 1;\n }\n }\n\n return elements;\n };\n\n // If active, show all items; last one gets the glow treatment\n if (isActive) {\n // For active groups: render all completed items with grouping, then render the active (last) item individually\n const completedMessages = toolMessages.slice(0, lastIndex);\n const lastMsg = toolMessages[lastIndex];\n\n return (\n <div className=\"devic-tool-group\">\n {completedMessages.length > 0 && renderCompletedItems(completedMessages)}\n <div\n key={lastMsg.uid}\n className=\"devic-tool-activity devic-tool-activity--active\"\n >\n {renderToolItem(lastMsg, { active: true, showSpinner: true })}\n </div>\n </div>\n );\n }\n\n // Completed: collapse if > 3 actions\n if (shouldCollapse && isCollapsed) {\n return (\n <div className=\"devic-tool-group\">\n <button\n className=\"devic-tool-collapse-btn\"\n onClick={() => setIsCollapsed(false)}\n type=\"button\"\n >\n <ToolDoneIcon />\n <span>{toolMessages.length} actions</span>\n <ChevronDownIcon />\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"devic-tool-group\">\n {shouldCollapse && (\n <button\n className=\"devic-tool-collapse-btn\"\n onClick={() => setIsCollapsed(true)}\n type=\"button\"\n >\n <span>{toolMessages.length} actions</span>\n <ChevronUpIcon />\n </button>\n )}\n <div className=\"devic-tool-group-items\" data-expanded=\"true\">\n {renderCompletedItems(toolMessages)}\n </div>\n </div>\n );\n}\n\n/**\n * Messages list component\n */\nconst markdownOverrides = {\n table: {\n component: ({ children, ...props }: any) =>\n React.createElement(\n \"div\",\n { className: \"markdown-table\" },\n React.createElement(\"table\", props, children),\n ),\n },\n};\n\n/**\n * Extract subthread ID from a hand_off_subagent tool call.\n * Checks the tool response in allMessages first, then falls back to handedOffSubThreadId.\n */\nfunction extractSubThreadId(\n toolCallId: string,\n allMessages: ChatMessage[],\n handedOffSubThreadId?: string,\n): string | null {\n // Look for the tool response message\n const toolResponse = allMessages.find(\n (m) => m.role === \"tool\" && m.tool_call_id === toolCallId,\n );\n if (toolResponse) {\n const content = toolResponse.content?.data || toolResponse.content;\n if (content && typeof content === \"object\" && \"subthreadId\" in content) {\n return (content as any).subthreadId;\n }\n if (content && typeof content === \"object\" && \"subThreadId\" in content) {\n return (content as any).subThreadId;\n }\n }\n // Fall back to active handoff subthread ID\n return handedOffSubThreadId || null;\n}\n\nexport function ChatMessages({\n messages,\n allMessages,\n isLoading,\n welcomeMessage,\n suggestedMessages,\n onSuggestedClick,\n toolRenderers,\n toolIcons,\n loadingIndicator,\n showFeedback = true,\n feedbackMap,\n onFeedback,\n handedOffSubThreadId,\n onHandoffCompleted,\n handoffWidgetRenderer,\n toolGroups,\n userMessageRenderer,\n assistantMessageRenderer,\n apiKey,\n baseUrl,\n pollingInterval,\n pendingInlineWidgets,\n onSubmitWidget,\n onCancelWidget,\n recalledMemories,\n recalledMemoriesRenderer,\n compactions,\n compaction,\n compactionRenderer,\n expandableCompaction,\n guardrailRenderer,\n}: ChatMessagesProps): JSX.Element {\n const t = useTranslations();\n const containerRef = useRef<HTMLDivElement>(null);\n const prevLengthRef = useRef(messages.length);\n\n // Anchor each recall record to the message that brought it in: the\n // assistant message carrying its memory tool call (toolCallId), or the\n // message the backend named (messageUid — matched against serverUid too,\n // since user messages may render under an adopted optimistic uid). Records\n // whose anchor is not on screen yet (the run is still producing it) go to\n // the pending group shown at the bottom while loading.\n const { recallsByAnchor, pendingRecalls } = useMemo(() => {\n const byAnchor = new Map<string, RecalledMemoryRecord[]>();\n const pending: RecalledMemoryRecord[] = [];\n for (const record of recalledMemories ?? []) {\n let anchor: string | undefined;\n if (record.toolCallId) {\n anchor = messages.find((m) =>\n m.tool_calls?.some((tc) => tc.id === record.toolCallId)\n )?.uid;\n }\n if (!anchor && record.messageUid) {\n anchor = messages.find(\n (m) =>\n m.uid === record.messageUid || m.serverUid === record.messageUid\n )?.uid;\n }\n if (anchor) {\n const list = byAnchor.get(anchor);\n if (list) list.push(record);\n else byAnchor.set(anchor, [record]);\n } else {\n pending.push(record);\n }\n }\n return { recallsByAnchor: byAnchor, pendingRecalls: pending };\n }, [recalledMemories, messages]);\n\n // The strip renders after the message (or tool group) that anchors it.\n const recallsFor = (uids: string[]): RecalledMemoryRecord[] =>\n uids.flatMap((uid) => recallsByAnchor.get(uid) ?? []);\n\n // Compaction checkpoints, keyed by the LAST message each one folded: the\n // point where the assistant's view of the conversation stops. A checkpoint\n // whose anchor is not on screen (it folded messages this client never\n // loaded) is drawn at the top instead, so the cut is never invisible.\n const { compactionsByAnchor, orphanCompactions, activeCompactionUid } =\n useMemo(() => {\n const byAnchor = new Map<string, CompactionCheckpoint[]>();\n const orphans: CompactionCheckpoint[] = [];\n for (const checkpoint of compactions ?? []) {\n const anchor = checkpoint.anchorMessageUid\n ? messages.find(\n (m) =>\n m.uid === checkpoint.anchorMessageUid ||\n m.serverUid === checkpoint.anchorMessageUid\n )?.uid\n : undefined;\n if (anchor) {\n const list = byAnchor.get(anchor);\n if (list) list.push(checkpoint);\n else byAnchor.set(anchor, [checkpoint]);\n } else {\n orphans.push(checkpoint);\n }\n }\n // Only the newest checkpoint governs the context: each compaction\n // merges the previous summary into itself.\n const active = (compactions ?? []).reduce<CompactionCheckpoint | null>(\n (latest, candidate) =>\n !latest || candidate.index > latest.index ? candidate : latest,\n null\n );\n return {\n compactionsByAnchor: byAnchor,\n orphanCompactions: orphans,\n activeCompactionUid: active?.uid,\n };\n }, [compactions, messages]);\n\n const compactionsFor = (uids: string[]): CompactionCheckpoint[] =>\n uids.flatMap((uid) => compactionsByAnchor.get(uid) ?? []);\n\n const renderCompactions = (checkpoints: CompactionCheckpoint[]) =>\n checkpoints.map((checkpoint) => (\n <CompactionWidget\n key={checkpoint.uid}\n checkpoint={checkpoint}\n isActive={checkpoint.uid === activeCompactionUid}\n renderer={compactionRenderer}\n expandable={expandableCompaction}\n />\n ));\n\n // Auto-scroll to bottom when new messages arrive\n useEffect(() => {\n if (containerRef.current) {\n containerRef.current.scrollTop = containerRef.current.scrollHeight;\n }\n prevLengthRef.current = messages.length;\n }, [messages.length, isLoading]);\n\n const grouped = groupMessages(messages, isLoading);\n\n // Show loading dots only if there's no active tool group at the end\n const lastGroup = grouped[grouped.length - 1];\n const showLoadingDots =\n isLoading && !(lastGroup?.type === \"toolGroup\" && lastGroup.isActive);\n\n return (\n <div className=\"devic-messages-container\" ref={containerRef}>\n {messages.length === 0 &&\n !isLoading &&\n (welcomeMessage || suggestedMessages?.length) && (\n <div className=\"devic-welcome\">\n {welcomeMessage && (\n <p className=\"devic-welcome-text\">{welcomeMessage}</p>\n )}\n {suggestedMessages && suggestedMessages.length > 0 && (\n <div className=\"devic-suggested-messages\">\n {suggestedMessages.map((msg, idx) => {\n const isObject = typeof msg === \"object\" && msg !== null;\n const content = isObject ? (msg as SuggestedMessage).content : msg;\n const message = isObject ? (msg as SuggestedMessage).message : (msg as string);\n return (\n <button\n key={idx}\n className=\"devic-suggested-btn\"\n onClick={() => onSuggestedClick?.(message)}\n >\n {content}\n </button>\n );\n })}\n </div>\n )}\n </div>\n )}\n\n {grouped.map((item) => {\n if (item.type === \"toolGroup\") {\n const groupRecalls = recallsFor(\n item.toolMessages.map((m) => m.uid)\n );\n const groupCompactions = compactionsFor(\n item.toolMessages.map((m) => m.uid)\n );\n return (\n <React.Fragment key={`tg-${item.toolMessages[0].uid}`}>\n <ToolGroup\n toolMessages={item.toolMessages}\n isActive={item.isActive}\n allMessages={allMessages}\n toolRenderers={toolRenderers}\n toolIcons={toolIcons}\n toolGroups={toolGroups}\n handedOffSubThreadId={handedOffSubThreadId}\n onHandoffCompleted={onHandoffCompleted}\n handoffWidgetRenderer={handoffWidgetRenderer}\n apiKey={apiKey}\n baseUrl={baseUrl}\n pollingInterval={pollingInterval}\n />\n {groupRecalls.length > 0 && (\n <RecalledMemoriesWidget\n records={groupRecalls}\n isLoading={isLoading}\n renderer={recalledMemoriesRenderer}\n />\n )}\n {renderCompactions(groupCompactions)}\n </React.Fragment>\n );\n }\n\n const message = item.message;\n\n // A stopped turn is not a bubble from either side: rendering it as one\n // sent it down the user-message path, which parses its text and threw\n // on the object a guardrail actually sends.\n if (message.role === GUARDRAIL_ROLE) {\n const noticeProps = {\n payload: guardrailPayload(message),\n text: readMessageText(message),\n };\n return (\n <React.Fragment key={message.uid}>\n {guardrailRenderer ? (\n guardrailRenderer(noticeProps)\n ) : (\n <GuardrailNotice {...noticeProps} />\n )}\n </React.Fragment>\n );\n }\n\n const rawText = readMessageText(message);\n const hasFiles =\n message.content?.files && message.content.files.length > 0;\n const isAssistant = message.role === \"assistant\";\n const currentFeedback = feedbackMap?.get(message.uid) || \"none\";\n\n // Extract reference chips from user messages (sent by AIElementWrapper).\n // The ChatDrawer prefixes user messages with:\n // Elemento referenciado: \"label1\", \"label2\"\\n\\n<actual message>\n // We render the labels as chips and only display the actual message\n // text inside the bubble.\n const parsed = !isAssistant && rawText\n ? parseReferencedPrefix(rawText)\n : null;\n const messageText = parsed ? parsed.cleanContent : rawText;\n const refLabels = parsed ? parsed.references : [];\n\n // Long pasted text travels inside the message but is shown as a card,\n // so the bubble renders what the user actually typed. Runs after the\n // reference prefix, which ChatDrawer prepends to the composed message.\n const pasted = !isAssistant && messageText\n ? parsePastedBlocks(messageText)\n : null;\n const bodyText = pasted ? pasted.cleanContent : messageText;\n const pastedBlocks = pasted ? pasted.blocks : [];\n\n // A custom bubble renderer (per role) fully replaces the default\n // markdown rendering of the message text.\n const bubbleRenderer = isAssistant\n ? assistantMessageRenderer\n : userMessageRenderer;\n\n const messageRecalls = recallsFor([message.uid]);\n const messageCompactions = compactionsFor([message.uid]);\n\n return (\n <React.Fragment key={message.uid}>\n <div\n className=\"devic-message\"\n data-role={message.role}\n // Accepted but not seen by the model yet. Drawn as a message that\n // has not landed, so it is not mistaken for something the assistant\n // has already read.\n data-queued={message.queued ? 'true' : undefined}\n >\n {refLabels.length > 0 && (\n <div className=\"devic-message-references\">\n {refLabels.map((lbl, i) => (\n <ReferenceChip key={i} label={lbl} variant=\"message\" />\n ))}\n </div>\n )}\n <div className=\"devic-message-bubble\">\n {pastedBlocks.length > 0 && (\n <div className=\"devic-message-pasted\">\n {pastedBlocks.map((block) => (\n <PastedBlockCard key={block.id} block={block} />\n ))}\n </div>\n )}\n {bodyText ? (\n bubbleRenderer ? (\n bubbleRenderer({\n message,\n content: bodyText,\n role: isAssistant ? \"assistant\" : \"user\",\n references: refLabels,\n })\n ) : (\n <Markdown options={{ overrides: markdownOverrides }}>\n {bodyText}\n </Markdown>\n )\n ) : null}\n {hasFiles && (\n <div className=\"devic-message-files\">\n {message.content!.files!.map((raw, fileIdx) => {\n const file = normalizeMessageFile(raw);\n return file.type === \"image\" && file.url ? (\n <a\n key={fileIdx}\n className=\"devic-message-file-image\"\n href={file.url}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n <img src={file.url} alt={file.name} />\n </a>\n ) : (\n <div key={fileIdx} className=\"devic-message-file\">\n <FileIcon />\n <span>{file.name}</span>\n </div>\n );\n })}\n </div>\n )}\n {!isAssistant && message.transcriptId && (\n <TranscriptPlayback\n transcriptId={message.transcriptId}\n apiKey={apiKey}\n baseUrl={baseUrl}\n />\n )}\n </div>\n <div className=\"devic-message-footer\">\n {message.queued && (\n <span className=\"devic-message-queued-label\">\n <QueuedIcon />\n {t(\"Queued\")}\n </span>\n )}\n <span className=\"devic-message-time\">\n {formatTime(message.timestamp)}\n </span>\n {isAssistant && showFeedback && onFeedback && (\n <MessageActions\n messageId={message.uid}\n messageContent={messageText}\n currentFeedback={currentFeedback as FeedbackState}\n onFeedback={onFeedback}\n showCopy={true}\n showFeedback={true}\n />\n )}\n </div>\n </div>\n {messageRecalls.length > 0 && (\n <RecalledMemoriesWidget\n records={messageRecalls}\n isLoading={isLoading}\n renderer={recalledMemoriesRenderer}\n />\n )}\n {renderCompactions(messageCompactions)}\n </React.Fragment>\n );\n })}\n\n {/* Recall events whose anchor message has not landed yet — shown while\n the run is in flight so the user sees what the assistant recalled\n before the first response arrives. */}\n {isLoading && pendingRecalls.length > 0 && (\n <RecalledMemoriesWidget\n records={pendingRecalls}\n isLoading={isLoading}\n renderer={recalledMemoriesRenderer}\n />\n )}\n\n {/* Checkpoints whose anchor message is not on screen — this client only\n loaded the messages that still travel, so the cut has nowhere to sit\n in the thread. Shown here rather than dropped: the conversation is\n shorter than it looks, and that is worth saying. */}\n {renderCompactions(orphanCompactions)}\n\n {/* A compaction being written right now. It is a model call of its own,\n taken between two assistant messages, so without this the\n conversation simply appears to have gone quiet. */}\n {compaction?.state === \"running\" && (\n <CompactionWidget\n checkpoint={null}\n activity={compaction}\n renderer={compactionRenderer}\n />\n )}\n\n {pendingInlineWidgets && pendingInlineWidgets.length > 0 && (\n <div className=\"devic-inline-widgets\">\n {pendingInlineWidgets.map((wc) => {\n const WidgetComponent = wc.widget.component;\n return (\n <div\n key={wc.toolCall.id}\n className=\"devic-inline-widget\"\n data-tool-name={wc.toolName}\n >\n <WidgetComponent\n toolCall={wc.toolCall}\n params={wc.params}\n submit={(response) => onSubmitWidget?.(wc.toolCall.id, response)}\n cancel={(reason) => onCancelWidget?.(wc.toolCall.id, reason)}\n />\n </div>\n );\n })}\n </div>\n )}\n\n {showLoadingDots &&\n (loadingIndicator ? (\n <div className=\"devic-loading\">{loadingIndicator}</div>\n ) : (\n <div className=\"devic-loading\">\n <span className=\"devic-loading-dot\"></span>\n <span className=\"devic-loading-dot\"></span>\n <span className=\"devic-loading-dot\"></span>\n </div>\n ))}\n </div>\n );\n}\n\n/* ── Icons ── */\n\nfunction SpinnerIcon(): JSX.Element {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n className=\"devic-spinner\"\n >\n <path d=\"M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83\" />\n </svg>\n );\n}\n\nfunction ToolDoneIcon(): JSX.Element {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"20,6 9,17 4,12\" />\n </svg>\n );\n}\n\nfunction ChevronDownIcon(): JSX.Element {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"6,9 12,15 18,9\" />\n </svg>\n );\n}\n\nfunction ChevronUpIcon(): JSX.Element {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"6,15 12,9 18,15\" />\n </svg>\n );\n}\n\n/** Small clock on a queued bubble's footer. */\nfunction QueuedIcon(): JSX.Element {\n return (\n <svg\n width=\"11\"\n height=\"11\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <polyline points=\"12 7 12 12 15 14\" />\n </svg>\n );\n}\n\nfunction FileIcon(): JSX.Element {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14,2 14,8 20,8\" />\n </svg>\n );\n}\n\n/**\n * Extracts the \"Elemento referenciado: ...\" prefix that ChatDrawer prepends\n * to user messages when AIElementWrapper references are active. Returns the\n * parsed labels and the message text without the prefix. Returns null when\n * the content does not start with the prefix.\n */\nconst REFERENCE_PREFIX_RE =\n /^Elemento referenciado: ((?:\"[^\"]+\")(?:, \"[^\"]+\")*)\\n\\n([\\s\\S]*)$/;\n\nfunction parseReferencedPrefix(\n content: string\n): { references: string[]; cleanContent: string } | null {\n const m = content.match(REFERENCE_PREFIX_RE);\n if (!m) return null;\n const labels = (m[1].match(/\"([^\"]+)\"/g) || []).map((s) =>\n s.slice(1, -1)\n );\n return { references: labels, cleanContent: m[2] };\n}\n\n/**\n * A block of pasted text inside a sent message: collapsed to a card by default,\n * expandable to read the whole thing without leaving the thread.\n */\nfunction PastedBlockCard({ block }: { block: PastedText }): JSX.Element {\n const t = useTranslations();\n const [expanded, setExpanded] = useState(false);\n\n return (\n <div className=\"devic-pasted-card\" data-expanded={expanded ? \"true\" : \"false\"}>\n <button\n type=\"button\"\n className=\"devic-pasted-card-toggle\"\n onClick={() => setExpanded((prev) => !prev)}\n aria-expanded={expanded}\n >\n {expanded ? (\n <pre className=\"devic-pasted-card-full\">{block.text}</pre>\n ) : (\n <p className=\"devic-pasted-card-preview\">{pastedPreview(block.text)}</p>\n )}\n <span className=\"devic-pasted-card-footer\">\n <span className=\"devic-pasted-card-badge\">{t(\"PASTED\")}</span>\n <span className=\"devic-pasted-card-meta\">\n {t(\"{count} lines\", { count: pastedLineCount(block.text) })} ·{\" \"}\n {expanded ? t(\"collapse\") : t(\"expand\")}\n </span>\n </span>\n </button>\n </div>\n );\n}\n"],"names":["_jsxs","_jsx","useTranslations","useOptionalDevicContext","useState","useRef","useEffect","client","DevicApiClient","toolGroups","HandoffSubagentWidget","_Fragment","segmentToolCalls","useMemo","CompactionWidget","RecalledMemoriesWidget","GuardrailNotice","parsePastedBlocks","ReferenceChip","normalizeMessageFile","MessageActions","pastedPreview","pastedLineCount"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CompactionWidget.js","sources":["../../../../../src/components/ChatDrawer/CompactionWidget.tsx"],"sourcesContent":["import { useState, type JSX, type ReactNode } from \"react\";\nimport { useTranslations } from \"../../i18n\";\nimport type {\n CompactionActivity,\n CompactionCheckpoint,\n CompactionSummary,\n} from \"../../api/types\";\n\n/** Data handed to a custom compaction renderer. */\nexport interface CompactionRendererProps {\n /**\n * The checkpoint at this point of the conversation. Null while a compaction\n * is being written and there is nothing to show yet.\n */\n checkpoint: CompactionCheckpoint | null;\n /**\n * True for the checkpoint that currently governs the context. Each\n * compaction merges the previous summary into itself, so the earlier ones\n * are a record rather than something still being sent.\n */\n isActive: boolean;\n /**\n * The compaction happening right now, or null. Present without a checkpoint\n * means one is being written; the numbers say what it is folding.\n */\n activity: CompactionActivity | null;\n}\n\n/** Replaces the built-in compaction marker. Return null to hide it. */\nexport type CompactionRenderer = (props: CompactionRendererProps) => ReactNode;\n\nfunction formatTokens(value: number): string {\n if (!value) return \"0\";\n if (value < 1000) return String(value);\n if (value < 1_000_000) return `${(value / 1000).toFixed(1)}k`;\n return `${(value / 1_000_000).toFixed(2)}M`;\n}\n\nfunction CompressIcon(): JSX.Element {\n return (\n <svg\n className=\"devic-compaction-icon\"\n width=\"13\"\n height=\"13\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 14 10 14 10 20\" />\n <polyline points=\"20 10 14 10 14 4\" />\n <line x1=\"14\" y1=\"10\" x2=\"21\" y2=\"3\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n );\n}\n\nfunction ChevronIcon({ up }: { up: boolean }): JSX.Element {\n return (\n <svg\n className=\"devic-compaction-chevron\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n style={{ transform: up ? \"rotate(180deg)\" : undefined }}\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n );\n}\n\nfunction Section({\n title,\n children,\n}: {\n title: string;\n children: ReactNode;\n}): JSX.Element {\n return (\n <div className=\"devic-compaction-section\">\n <span className=\"devic-compaction-section-title\">{title}</span>\n {children}\n </div>\n );\n}\n\nfunction Bullets({ items }: { items?: string[] }): JSX.Element | null {\n if (!items?.length) return null;\n return (\n <ul className=\"devic-compaction-list\">\n {items.map((item, i) => (\n <li key={i}>{item}</li>\n ))}\n </ul>\n );\n}\n\nfunction hasStructure(summary: CompactionSummary): boolean {\n return Boolean(\n summary.goal ||\n summary.constraints?.length ||\n summary.inProgress ||\n summary.pending?.length ||\n summary.decisions?.length ||\n summary.data?.length ||\n summary.done?.length ||\n summary.openQuestions?.length\n );\n}\n\nexport interface CompactionWidgetProps {\n checkpoint: CompactionCheckpoint | null;\n isActive?: boolean;\n activity?: CompactionActivity | null;\n renderer?: CompactionRenderer;\n /**\n * Lets the reader open the checkpoint and read what it says.\n *\n * Off by default, because what opens is not metadata: it is a model-written\n * account of the conversation — its goal, the decisions taken and why, what\n * is still pending, and the identifiers lifted out of it verbatim. That is\n * the right thing to put in front of an operator and the wrong thing to put\n * in front of the customer the conversation is with, so the closed form is\n * the default and opening it is a decision the host makes.\n *\n * Collapsed it still says a compaction happened and how much it folded:\n * hiding that would misrepresent the conversation, which is the opposite of\n * the point.\n */\n expandable?: boolean;\n}\n\n/**\n * The cut line in the conversation.\n *\n * Anchored to the last message a checkpoint folded, it marks the exact point\n * where the assistant's view of the conversation stops: everything above it\n * is still here, still readable, and no longer sent. It is a rule across the\n * thread with the headline numbers, and — where the host opts in with\n * `expandable` — it opens to show what the assistant reads in place of those\n * messages.\n *\n * With no checkpoint yet and a compaction in flight it says so instead — that\n * is a model call of its own, and without it the conversation just appears to\n * have gone quiet.\n *\n * Deliberately not a message bubble: a checkpoint is not something anyone\n * said.\n */\nexport function CompactionWidget({\n checkpoint,\n isActive = true,\n activity = null,\n renderer,\n expandable = false,\n}: CompactionWidgetProps): JSX.Element | null {\n const t = useTranslations();\n const [expanded, setExpanded] = useState(false);\n\n if (renderer) {\n return <>{renderer({ checkpoint, isActive, activity })}</>;\n }\n\n const running = activity?.state === \"running\";\n\n if (!checkpoint) {\n if (!running) return null;\n return (\n <div className=\"devic-compaction devic-compaction-running\">\n <span className=\"devic-compaction-rule\" />\n <span className=\"devic-compaction-pill\">\n <CompressIcon />\n <span className=\"devic-compaction-title\">\n {t(\"Compacting context\")}\n </span>\n <span className=\"devic-compaction-meta\">\n {activity!.messageCount === 1\n ? t(\"1 message\")\n : t(\"{count} messages\", { count: activity!.messageCount })}{\" \"}\n · {t(\"{tokens} tokens\", { tokens: formatTokens(activity!.tokensBefore) })}\n </span>\n <span className=\"devic-compaction-dots\" aria-hidden=\"true\">\n <i />\n <i />\n <i />\n </span>\n </span>\n <span className=\"devic-compaction-rule\" />\n </div>\n );\n }\n\n const summary = checkpoint.summary || {};\n const structured = hasStructure(summary);\n\n const tooltip =\n checkpoint.compactedMessageCount === 1\n ? t(\n \"1 message is still in this conversation but no longer sent to the assistant\"\n )\n : t(\n \"{count} messages are still in this conversation but no longer sent to the assistant\",\n { count: checkpoint.compactedMessageCount }\n );\n\n //The headline, identical either way: whether the checkpoint can be opened\n //changes what the reader may inspect, never what the marker claims.\n const headline = (\n <>\n <CompressIcon />\n <span className=\"devic-compaction-title\">\n {t(\"Context compacted\")}\n {checkpoint.index > 1 ? ` (#${checkpoint.index})` : \"\"}\n </span>\n <span className=\"devic-compaction-meta\">\n {t(\"{count} messages\", { count: checkpoint.compactedMessageCount })} ·{\" \"}\n {t(\"{before} → {after} tokens\", {\n before: formatTokens(checkpoint.tokensBefore),\n after: formatTokens(checkpoint.tokensAfter),\n })}\n </span>\n {!isActive && (\n <span\n className=\"devic-compaction-tag\"\n title={t(\n \"Superseded by a later compaction, which merged this summary into itself. Kept for the record.\"\n )}\n >\n {t(\"superseded\")}\n </span>\n )}\n </>\n );\n\n return (\n <div className=\"devic-compaction\">\n <div className=\"devic-compaction-head\">\n <span className=\"devic-compaction-rule\" />\n {expandable ? (\n <button\n type=\"button\"\n className=\"devic-compaction-pill\"\n onClick={() => setExpanded((v) => !v)}\n aria-expanded={expanded}\n title={tooltip}\n >\n {headline}\n <ChevronIcon up={expanded} />\n </button>\n ) : (\n //A span, not a disabled button: there is nothing here to operate, so\n //it should not reach the keyboard or announce itself as a control.\n <span\n className=\"devic-compaction-pill devic-compaction-pill-static\"\n title={tooltip}\n >\n {headline}\n </span>\n )}\n <span className=\"devic-compaction-rule\" />\n </div>\n\n {expandable && expanded && (\n <div className=\"devic-compaction-body\">\n <div className=\"devic-compaction-note\">\n {t(\n \"This is what the assistant reads in place of the messages above. The messages themselves are still here.\"\n )}\n </div>\n\n {structured && (\n <>\n {summary.goal && <Section title={t(\"Goal\")}>{summary.goal}</Section>}\n {!!summary.constraints?.length && (\n <Section title={t(\"Constraints\")}>\n <Bullets items={summary.constraints} />\n </Section>\n )}\n {summary.inProgress && (\n <Section title={t(\"In progress\")}>{summary.inProgress}</Section>\n )}\n {!!summary.pending?.length && (\n <Section title={t(\"Pending\")}>\n <Bullets items={summary.pending} />\n </Section>\n )}\n {!!summary.decisions?.length && (\n <Section title={t(\"Decisions\")}>\n <Bullets items={summary.decisions} />\n </Section>\n )}\n {!!summary.data?.length && (\n <Section title={t(\"Key data\")}>\n <Bullets\n items={summary.data.map((entry) =>\n entry.label ? `${entry.label}: ${entry.value}` : entry.value\n )}\n />\n </Section>\n )}\n {!!summary.done?.length && (\n <Section title={t(\"Done\")}>\n <Bullets items={summary.done} />\n </Section>\n )}\n {!!summary.openQuestions?.length && (\n <Section title={t(\"Open questions\")}>\n <Bullets items={summary.openQuestions} />\n </Section>\n )}\n </>\n )}\n\n {summary.raw && (\n <Section title={structured ? t(\"Notes\") : t(\"Summary\")}>\n <div className=\"devic-compaction-raw\">{summary.raw}</div>\n </Section>\n )}\n\n {!!checkpoint.facts?.length && (\n <Section title={t(\"Preserved exactly\")}>\n <div className=\"devic-compaction-facts\">\n {checkpoint.facts.map((fact, i) => (\n <span key={i} className=\"devic-compaction-fact\">\n {fact.label ? (\n <span className=\"devic-compaction-fact-label\">\n {fact.label}:{\" \"}\n </span>\n ) : null}\n {fact.value}\n </span>\n ))}\n </div>\n </Section>\n )}\n </div>\n )}\n </div>\n );\n}\n\nexport default CompactionWidget;\n"],"names":["_jsxs","_jsx","useTranslations","useState","_Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CompactionWidget.js","sources":["../../../../../src/components/ChatDrawer/CompactionWidget.tsx"],"sourcesContent":["import { useState, type JSX, type ReactNode } from \"react\";\nimport { useTranslations } from \"../../i18n\";\nimport type {\n CompactionActivity,\n CompactionCheckpoint,\n CompactionSummary,\n} from \"../../api/types\";\n\n/** Data handed to a custom compaction renderer. */\nexport interface CompactionRendererProps {\n /**\n * The checkpoint at this point of the conversation. Null while a compaction\n * is being written and there is nothing to show yet.\n */\n checkpoint: CompactionCheckpoint | null;\n /**\n * True for the checkpoint that currently governs the context. Each\n * compaction merges the previous summary into itself, so the earlier ones\n * are a record rather than something still being sent.\n */\n isActive: boolean;\n /**\n * The compaction happening right now, or null. Present without a checkpoint\n * means one is being written; the numbers say what it is folding.\n */\n activity: CompactionActivity | null;\n}\n\n/** Replaces the built-in compaction marker. Return null to hide it. */\nexport type CompactionRenderer = (props: CompactionRendererProps) => ReactNode;\n\nfunction formatTokens(value: number): string {\n if (!value) return \"0\";\n if (value < 1000) return String(value);\n if (value < 1_000_000) return `${(value / 1000).toFixed(1)}k`;\n return `${(value / 1_000_000).toFixed(2)}M`;\n}\n\nfunction CompressIcon(): JSX.Element {\n return (\n <svg\n className=\"devic-compaction-icon\"\n width=\"13\"\n height=\"13\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 14 10 14 10 20\" />\n <polyline points=\"20 10 14 10 14 4\" />\n <line x1=\"14\" y1=\"10\" x2=\"21\" y2=\"3\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n );\n}\n\nfunction ChevronIcon({ up }: { up: boolean }): JSX.Element {\n return (\n <svg\n className=\"devic-compaction-chevron\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n style={{ transform: up ? \"rotate(180deg)\" : undefined }}\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n );\n}\n\nfunction Section({\n title,\n children,\n}: {\n title: string;\n children: ReactNode;\n}): JSX.Element {\n return (\n <div className=\"devic-compaction-section\">\n <span className=\"devic-compaction-section-title\">{title}</span>\n {children}\n </div>\n );\n}\n\nfunction Bullets({ items }: { items?: string[] }): JSX.Element | null {\n if (!items?.length) return null;\n return (\n <ul className=\"devic-compaction-list\">\n {items.map((item, i) => (\n <li key={i}>{item}</li>\n ))}\n </ul>\n );\n}\n\nfunction hasStructure(summary: CompactionSummary): boolean {\n return Boolean(\n summary.goal ||\n summary.constraints?.length ||\n summary.inProgress ||\n summary.pending?.length ||\n summary.decisions?.length ||\n summary.data?.length ||\n summary.done?.length ||\n summary.openQuestions?.length\n );\n}\n\nexport interface CompactionWidgetProps {\n checkpoint: CompactionCheckpoint | null;\n isActive?: boolean;\n activity?: CompactionActivity | null;\n renderer?: CompactionRenderer;\n /**\n * Lets the reader open the checkpoint and read what it says.\n *\n * Off by default, because what opens is not metadata: it is a model-written\n * account of the conversation — its goal, the decisions taken and why, what\n * is still pending, and the identifiers lifted out of it verbatim. That is\n * the right thing to put in front of an operator and the wrong thing to put\n * in front of the customer the conversation is with, so the closed form is\n * the default and opening it is a decision the host makes.\n *\n * Collapsed it still says a compaction happened and how much it folded:\n * hiding that would misrepresent the conversation, which is the opposite of\n * the point.\n */\n expandable?: boolean;\n}\n\n/**\n * The cut line in the conversation.\n *\n * Anchored to the last message a checkpoint folded, it marks the exact point\n * where the assistant's view of the conversation stops: everything above it\n * is still here, still readable, and no longer sent. It is a rule across the\n * thread with the headline numbers, and — where the host opts in with\n * `expandable` — it opens to show what the assistant reads in place of those\n * messages.\n *\n * With no checkpoint yet and a compaction in flight it says so instead — that\n * is a model call of its own, and without it the conversation just appears to\n * have gone quiet.\n *\n * Deliberately not a message bubble: a checkpoint is not something anyone\n * said.\n */\nexport function CompactionWidget({\n checkpoint,\n isActive = true,\n activity = null,\n renderer,\n expandable = false,\n}: CompactionWidgetProps): JSX.Element | null {\n const t = useTranslations();\n const [expanded, setExpanded] = useState(false);\n\n if (renderer) {\n return <>{renderer({ checkpoint, isActive, activity })}</>;\n }\n\n const running = activity?.state === \"running\";\n\n if (!checkpoint) {\n if (!running) return null;\n return (\n <div className=\"devic-compaction devic-compaction-running\">\n <span className=\"devic-compaction-rule\" />\n <span className=\"devic-compaction-pill\">\n <CompressIcon />\n <span className=\"devic-compaction-title\">\n {t(\"Compacting context\")}\n </span>\n <span className=\"devic-compaction-meta\">\n {activity!.messageCount === 1\n ? t(\"1 message\")\n : t(\"{count} messages\", { count: activity!.messageCount })}{\" \"}\n · {t(\"{tokens} tokens\", { tokens: formatTokens(activity!.tokensBefore) })}\n </span>\n <span className=\"devic-compaction-dots\" aria-hidden=\"true\">\n <i />\n <i />\n <i />\n </span>\n </span>\n <span className=\"devic-compaction-rule\" />\n </div>\n );\n }\n\n const summary = checkpoint.summary || {};\n const structured = hasStructure(summary);\n\n const tooltip =\n checkpoint.compactedMessageCount === 1\n ? t(\n \"1 message is still in this conversation but no longer sent to the assistant\"\n )\n : t(\n \"{count} messages are still in this conversation but no longer sent to the assistant\",\n { count: checkpoint.compactedMessageCount }\n );\n\n //The headline, identical either way: whether the checkpoint can be opened\n //changes what the reader may inspect, never what the marker claims.\n const headline = (\n <>\n <CompressIcon />\n <span className=\"devic-compaction-title\">\n {t(\"Context compacted\")}\n {checkpoint.index > 1 ? ` (#${checkpoint.index})` : \"\"}\n </span>\n <span className=\"devic-compaction-meta\">\n {t(\"{count} messages\", { count: checkpoint.compactedMessageCount })} ·{\" \"}\n {t(\"{before} → {after} tokens\", {\n before: formatTokens(checkpoint.tokensBefore),\n after: formatTokens(checkpoint.tokensAfter),\n })}\n </span>\n {!isActive && (\n <span\n className=\"devic-compaction-tag\"\n title={t(\n \"Superseded by a later compaction, which merged this summary into itself. Kept for the record.\"\n )}\n >\n {t(\"superseded\")}\n </span>\n )}\n </>\n );\n\n return (\n <div className=\"devic-compaction\">\n <div className=\"devic-compaction-head\">\n <span className=\"devic-compaction-rule\" />\n {expandable ? (\n <button\n type=\"button\"\n className=\"devic-compaction-pill\"\n onClick={() => setExpanded((v) => !v)}\n aria-expanded={expanded}\n title={tooltip}\n >\n {headline}\n <ChevronIcon up={expanded} />\n </button>\n ) : (\n //A span, not a disabled button: there is nothing here to operate, so\n //it should not reach the keyboard or announce itself as a control.\n <span\n className=\"devic-compaction-pill devic-compaction-pill-static\"\n title={tooltip}\n >\n {headline}\n </span>\n )}\n <span className=\"devic-compaction-rule\" />\n </div>\n\n {expandable && expanded && (\n <div className=\"devic-compaction-body\">\n <div className=\"devic-compaction-note\">\n {t(\n \"This is what the assistant reads in place of the messages above. The messages themselves are still here.\"\n )}\n </div>\n\n {structured && (\n <>\n {summary.goal && <Section title={t(\"Goal\")}>{summary.goal}</Section>}\n {!!summary.constraints?.length && (\n <Section title={t(\"Constraints\")}>\n <Bullets items={summary.constraints} />\n </Section>\n )}\n {summary.inProgress && (\n <Section title={t(\"In progress\")}>{summary.inProgress}</Section>\n )}\n {!!summary.pending?.length && (\n <Section title={t(\"Pending\")}>\n <Bullets items={summary.pending} />\n </Section>\n )}\n {!!summary.decisions?.length && (\n <Section title={t(\"Decisions\")}>\n <Bullets items={summary.decisions} />\n </Section>\n )}\n {!!summary.data?.length && (\n <Section title={t(\"Key data\")}>\n <Bullets\n items={summary.data.map((entry) =>\n entry.label ? `${entry.label}: ${entry.value}` : entry.value\n )}\n />\n </Section>\n )}\n {!!summary.done?.length && (\n <Section title={t(\"Done\")}>\n <Bullets items={summary.done} />\n </Section>\n )}\n {!!summary.openQuestions?.length && (\n <Section title={t(\"Open questions\")}>\n <Bullets items={summary.openQuestions} />\n </Section>\n )}\n </>\n )}\n\n {summary.raw && (\n <Section title={structured ? t(\"Notes\") : t(\"Summary\")}>\n <div className=\"devic-compaction-raw\">{summary.raw}</div>\n </Section>\n )}\n\n {!!checkpoint.facts?.length && (\n <Section title={t(\"Preserved exactly\")}>\n <div className=\"devic-compaction-facts\">\n {checkpoint.facts.map((fact, i) => (\n <span key={i} className=\"devic-compaction-fact\">\n {fact.label ? (\n <span className=\"devic-compaction-fact-label\">\n {fact.label}:{\" \"}\n </span>\n ) : null}\n {fact.value}\n </span>\n ))}\n </div>\n </Section>\n )}\n </div>\n )}\n </div>\n );\n}\n\nexport default CompactionWidget;\n"],"names":["_jsxs","_jsx","useTranslations","useState","_Fragment"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationSelector.js","sources":["../../../../../src/components/ChatDrawer/ConversationSelector.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport { useOptionalDevicContext } from '../../provider';\nimport { DevicApiClient } from '../../api/client';\nimport type { ConversationSummary } from '../../api/types';\nimport type { ConversationSelectorProps } from './ChatDrawer.types';\nimport { useTranslations } from '../../i18n';\n\nconst PAGE_SIZE = 10;\n\nexport function ConversationSelector({\n assistantId,\n currentChatUid,\n onSelect,\n onNewChat,\n apiKey: propsApiKey,\n baseUrl: propsBaseUrl,\n tenantId: propsTenantId,\n subtenantId: propsSubtenantId,\n conversationPreview,\n}: ConversationSelectorProps): JSX.Element {\n const t = useTranslations();\n const context = useOptionalDevicContext();\n const apiKey = propsApiKey || context?.apiKey;\n const baseUrl = propsBaseUrl || context?.baseUrl || 'https://api.devic.ai';\n const tenantId = propsTenantId || context?.tenantId;\n const subtenantId = propsSubtenantId || context?.subtenantId;\n\n const [isOpen, setIsOpen] = useState(false);\n const [conversations, setConversations] = useState<ConversationSummary[]>([]);\n const [search, setSearch] = useState('');\n const [loading, setLoading] = useState(false);\n const [loadingMore, setLoadingMore] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n const [firstMessages, setFirstMessages] = useState<Record<string, string | null>>({});\n const fetchedChatsRef = useRef<Set<string>>(new Set());\n const dropdownRef = useRef<HTMLDivElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const clientRef = useRef<DevicApiClient | null>(null);\n const getTenantSession = context?.getTenantSession;\n const onSessionExpired = context?.onSessionExpired;\n\n if (!clientRef.current && (apiKey || getTenantSession)) {\n clientRef.current = new DevicApiClient({ apiKey, baseUrl, getTenantSession, onSessionExpired });\n }\n\n // Update client config when props/context change\n useEffect(() => {\n if (clientRef.current) {\n clientRef.current.setConfig({ apiKey, baseUrl, getTenantSession, onSessionExpired });\n } else if (apiKey || getTenantSession) {\n clientRef.current = new DevicApiClient({ apiKey, baseUrl, getTenantSession, onSessionExpired });\n }\n }, [apiKey, baseUrl, getTenantSession]);\n\n const fetchConversations = useCallback(async (offset = 0, append = false) => {\n if (!clientRef.current) return;\n if (offset === 0) {\n setLoading(true);\n } else {\n setLoadingMore(true);\n }\n try {\n const response = await clientRef.current.listConversations(assistantId, {\n tenantId,\n subtenantId,\n offset,\n limit: PAGE_SIZE,\n });\n setConversations((prev) => append ? [...prev, ...response.histories] : response.histories);\n setHasMore(offset + response.histories.length < response.total);\n } catch {\n // silently fail\n } finally {\n setLoading(false);\n setLoadingMore(false);\n }\n }, [assistantId, tenantId, subtenantId]);\n\n useEffect(() => {\n if (isOpen) {\n fetchConversations(0);\n }\n }, [isOpen, fetchConversations]);\n\n // Fetch conversations when currentChatUid changes so the selector label is correct\n useEffect(() => {\n if (currentChatUid && conversations.length === 0) {\n fetchConversations(0);\n }\n }, [currentChatUid, conversations.length, fetchConversations]);\n\n const handleLoadMore = useCallback(() => {\n if (!loadingMore && hasMore) {\n fetchConversations(conversations.length, true);\n }\n }, [loadingMore, hasMore, conversations.length, fetchConversations]);\n\n // Lazy-fetch first user message for unnamed conversations\n useEffect(() => {\n if (conversationPreview !== 'firstMessage' || !clientRef.current || !isOpen) return;\n const unnamed = conversations.filter((c) => !c.name && !fetchedChatsRef.current.has(c.chatUID));\n if (unnamed.length === 0) return;\n\n // Mark as loading (null = loading)\n unnamed.forEach((c) => fetchedChatsRef.current.add(c.chatUID));\n setFirstMessages((prev) => {\n const next = { ...prev };\n unnamed.forEach((c) => { next[c.chatUID] = null; });\n return next;\n });\n\n unnamed.forEach((conv) => {\n clientRef.current!.getChatHistory(assistantId, conv.chatUID, { tenantId }).then((history) => {\n const firstUserMsg = history.chatContent?.find((m) => m.role === 'user');\n const text = firstUserMsg?.content?.message || '';\n setFirstMessages((prev) => ({ ...prev, [conv.chatUID]: text || '' }));\n }).catch(() => {\n setFirstMessages((prev) => ({ ...prev, [conv.chatUID]: '' }));\n });\n });\n }, [conversations, isOpen, conversationPreview, assistantId, tenantId]);\n\n // Close on outside click\n useEffect(() => {\n if (!isOpen) return;\n const handler = (e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [isOpen]);\n\n const getConversationLabel = (conv: ConversationSummary): string => {\n if (conv.name) return conv.name;\n if (conversationPreview === 'firstMessage') {\n const msg = firstMessages[conv.chatUID];\n if (msg === null) return '...';\n if (msg) return msg;\n }\n return formatDate(conv.creationTimestampMs);\n };\n\n const currentConv = conversations.find((c) => c.chatUID === currentChatUid);\n const currentName = currentConv\n ? getConversationLabel(currentConv)\n : t('New chat');\n\n const filtered = conversations.filter((c) => {\n if (!search) return true;\n const q = search.toLowerCase();\n if ((c.name || '').toLowerCase().includes(q)) return true;\n if (conversationPreview === 'firstMessage') {\n const msg = firstMessages[c.chatUID];\n if (msg && msg.toLowerCase().includes(q)) return true;\n }\n return false;\n });\n\n return (\n <div className=\"devic-conversation-selector\" ref={dropdownRef}>\n <button\n className=\"devic-conversation-selector-trigger\"\n onClick={() => setIsOpen(!isOpen)}\n type=\"button\"\n >\n <span className=\"devic-conversation-selector-label\">{currentName}</span>\n <ChevronIcon open={isOpen} />\n </button>\n\n {isOpen && (\n <div className=\"devic-conversation-dropdown\">\n <div className=\"devic-conversation-search-wrapper\">\n <input\n className=\"devic-conversation-search\"\n type=\"text\"\n placeholder={t('Search conversations...')}\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n autoFocus\n />\n </div>\n\n <div\n className=\"devic-conversation-list\"\n ref={listRef}\n >\n {loading && (\n <div className=\"devic-conversation-loading\">{t('Loading...')}</div>\n )}\n {!loading && filtered.length === 0 && (\n <div className=\"devic-conversation-empty\">\n {t('No conversations')}\n </div>\n )}\n {!loading &&\n filtered.map((conv) => (\n <button\n key={conv.chatUID}\n className=\"devic-conversation-item\"\n data-active={conv.chatUID === currentChatUid}\n type=\"button\"\n onClick={() => {\n onSelect(conv.chatUID);\n setIsOpen(false);\n }}\n >\n {conv.chatUID === currentChatUid && (\n <span className=\"devic-conversation-item-check\">\n <CheckIcon />\n </span>\n )}\n <span className=\"devic-conversation-item-name\">\n {getConversationLabel(conv)}\n </span>\n <span className=\"devic-conversation-item-date\">\n {formatDate(conv.lastEditTimestampMs || conv.creationTimestampMs)}\n </span>\n </button>\n ))}\n {loadingMore && (\n <div className=\"devic-conversation-loading\">\n {t('Loading more...')}\n </div>\n )}\n {!loadingMore && hasMore && !loading && (\n <button\n className=\"devic-conversation-load-more\"\n type=\"button\"\n onClick={handleLoadMore}\n >\n {t('Load more')}\n </button>\n )}\n </div>\n\n <button\n className=\"devic-conversation-new\"\n type=\"button\"\n onClick={() => {\n onNewChat();\n setIsOpen(false);\n }}\n >\n {t('+ Start a new chat')}\n </button>\n </div>\n )}\n </div>\n );\n}\n\nfunction ChevronIcon({ open }: { open: boolean }): JSX.Element {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{ transform: open ? 'rotate(180deg)' : undefined, transition: '0.2s' }}\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n );\n}\n\nfunction CheckIcon(): JSX.Element {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20,6 9,17 4,12\" />\n </svg>\n );\n}\n\nfunction formatDate(ms: number): string {\n const d = new Date(ms);\n const now = new Date();\n if (d.toDateString() === now.toDateString()) {\n return d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });\n }\n return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' });\n}\n"],"names":["useTranslations","useOptionalDevicContext","useState","useRef","DevicApiClient","useEffect","useCallback","_jsxs","_jsx"],"mappings":";;;;;;;;AAOA,MAAM,SAAS,GAAG,EAAE;AAEd,SAAU,oBAAoB,CAAC,EACnC,WAAW,EACX,cAAc,EACd,QAAQ,EACR,SAAS,EACT,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,aAAa,EACvB,WAAW,EAAE,gBAAgB,EAC7B,mBAAmB,GACO,EAAA;AAC1B,IAAA,MAAM,CAAC,GAAGA,+BAAe,EAAE;AAC3B,IAAA,MAAM,OAAO,GAAGC,oCAAuB,EAAE;AACzC,IAAA,MAAM,MAAM,GAAG,WAAW,IAAI,OAAO,EAAE,MAAM;IAC7C,MAAM,OAAO,GAAG,YAAY,IAAI,OAAO,EAAE,OAAO,IAAI,sBAAsB;AAC1E,IAAA,MAAM,QAAQ,GAAG,aAAa,IAAI,OAAO,EAAE,QAAQ;AACnD,IAAA,MAAM,WAAW,GAAG,gBAAgB,IAAI,OAAO,EAAE,WAAW;IAE5D,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAGC,cAAQ,CAAC,KAAK,CAAC;IAC3C,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAGA,cAAQ,CAAwB,EAAE,CAAC;IAC7E,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAGA,cAAQ,CAAC,EAAE,CAAC;IACxC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAGA,cAAQ,CAAC,KAAK,CAAC;IAC7C,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAGA,cAAQ,CAAC,KAAK,CAAC;IACrD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAGA,cAAQ,CAAC,IAAI,CAAC;IAC5C,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAGA,cAAQ,CAAgC,EAAE,CAAC;IACrF,MAAM,eAAe,GAAGC,YAAM,CAAc,IAAI,GAAG,EAAE,CAAC;AACtD,IAAA,MAAM,WAAW,GAAGA,YAAM,CAAiB,IAAI,CAAC;AAChD,IAAA,MAAM,OAAO,GAAGA,YAAM,CAAiB,IAAI,CAAC;AAC5C,IAAA,MAAM,SAAS,GAAGA,YAAM,CAAwB,IAAI,CAAC;AACrD,IAAA,MAAM,gBAAgB,GAAG,OAAO,EAAE,gBAAgB;AAClD,IAAA,MAAM,gBAAgB,GAAG,OAAO,EAAE,gBAAgB;IAElD,IAAI,CAAC,SAAS,CAAC,OAAO,KAAK,MAAM,IAAI,gBAAgB,CAAC,EAAE;AACtD,QAAA,SAAS,CAAC,OAAO,GAAG,IAAIC,qBAAc,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;IACjG;;IAGAC,eAAS,CAAC,MAAK;AACb,QAAA,IAAI,SAAS,CAAC,OAAO,EAAE;AACrB,YAAA,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;QACtF;AAAO,aAAA,IAAI,MAAM,IAAI,gBAAgB,EAAE;AACrC,YAAA,SAAS,CAAC,OAAO,GAAG,IAAID,qBAAc,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;QACjG;IACF,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC;AAEvC,IAAA,MAAM,kBAAkB,GAAGE,iBAAW,CAAC,OAAO,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,KAAI;QAC1E,IAAI,CAAC,SAAS,CAAC,OAAO;YAAE;AACxB,QAAA,IAAI,MAAM,KAAK,CAAC,EAAE;YAChB,UAAU,CAAC,IAAI,CAAC;QAClB;aAAO;YACL,cAAc,CAAC,IAAI,CAAC;QACtB;AACA,QAAA,IAAI;YACF,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC,WAAW,EAAE;gBACtE,QAAQ;gBACR,WAAW;gBACX,MAAM;AACN,gBAAA,KAAK,EAAE,SAAS;AACjB,aAAA,CAAC;YACF,gBAAgB,CAAC,CAAC,IAAI,KAAK,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC;AAC1F,YAAA,UAAU,CAAC,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC;QACjE;AAAE,QAAA,MAAM;;QAER;gBAAU;YACR,UAAU,CAAC,KAAK,CAAC;YACjB,cAAc,CAAC,KAAK,CAAC;QACvB;IACF,CAAC,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IAExCD,eAAS,CAAC,MAAK;QACb,IAAI,MAAM,EAAE;YACV,kBAAkB,CAAC,CAAC,CAAC;QACvB;AACF,IAAA,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;;IAGhCA,eAAS,CAAC,MAAK;QACb,IAAI,cAAc,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE;YAChD,kBAAkB,CAAC,CAAC,CAAC;QACvB;IACF,CAAC,EAAE,CAAC,cAAc,EAAE,aAAa,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AAE9D,IAAA,MAAM,cAAc,GAAGC,iBAAW,CAAC,MAAK;AACtC,QAAA,IAAI,CAAC,WAAW,IAAI,OAAO,EAAE;AAC3B,YAAA,kBAAkB,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC;QAChD;AACF,IAAA,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;;IAGpED,eAAS,CAAC,MAAK;QACb,IAAI,mBAAmB,KAAK,cAAc,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,CAAC,MAAM;YAAE;AAC7E,QAAA,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAC/F,QAAA,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE;;AAG1B,QAAA,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAC9D,QAAA,gBAAgB,CAAC,CAAC,IAAI,KAAI;AACxB,YAAA,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE;YACxB,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AACnD,YAAA,OAAO,IAAI;AACb,QAAA,CAAC,CAAC;AAEF,QAAA,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,KAAI;YACvB,SAAS,CAAC,OAAQ,CAAC,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,KAAI;AAC1F,gBAAA,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;gBACxE,MAAM,IAAI,GAAG,YAAY,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE;gBACjD,gBAAgB,CAAC,CAAC,IAAI,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;AACvE,YAAA,CAAC,CAAC,CAAC,KAAK,CAAC,MAAK;gBACZ,gBAAgB,CAAC,CAAC,IAAI,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,GAAG,EAAE,EAAE,CAAC,CAAC;AAC/D,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;AACJ,IAAA,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,mBAAmB,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;;IAGvEA,eAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,MAAM;YAAE;AACb,QAAA,MAAM,OAAO,GAAG,CAAC,CAAa,KAAI;AAChC,YAAA,IAAI,WAAW,CAAC,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAc,CAAC,EAAE;gBAC1E,SAAS,CAAC,KAAK,CAAC;YAClB;AACF,QAAA,CAAC;AACD,QAAA,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,OAAO,CAAC;QAC/C,OAAO,MAAM,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,OAAO,CAAC;AACjE,IAAA,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;AAEZ,IAAA,MAAM,oBAAoB,GAAG,CAAC,IAAyB,KAAY;QACjE,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC,IAAI;AAC/B,QAAA,IAAI,mBAAmB,KAAK,cAAc,EAAE;YAC1C,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC;YACvC,IAAI,GAAG,KAAK,IAAI;AAAE,gBAAA,OAAO,KAAK;AAC9B,YAAA,IAAI,GAAG;AAAE,gBAAA,OAAO,GAAG;QACrB;AACA,QAAA,OAAO,UAAU,CAAC,IAAI,CAAC,mBAAmB,CAAC;AAC7C,IAAA,CAAC;AAED,IAAA,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,KAAK,cAAc,CAAC;IAC3E,MAAM,WAAW,GAAG;AAClB,UAAE,oBAAoB,CAAC,WAAW;AAClC,UAAE,CAAC,CAAC,UAAU,CAAC;IAEjB,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,KAAI;AAC1C,QAAA,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,IAAI;AACxB,QAAA,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE;AAC9B,QAAA,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AAAE,YAAA,OAAO,IAAI;AACzD,QAAA,IAAI,mBAAmB,KAAK,cAAc,EAAE;YAC1C,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC;YACpC,IAAI,GAAG,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AAAE,gBAAA,OAAO,IAAI;QACvD;AACA,QAAA,OAAO,KAAK;AACd,IAAA,CAAC,CAAC;AAEF,IAAA,QACEE,eAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,6BAA6B,EAAC,GAAG,EAAE,WAAW,EAAA,QAAA,EAAA,CAC3DA,eAAA,CAAA,QAAA,EAAA,EACE,SAAS,EAAC,qCAAqC,EAC/C,OAAO,EAAE,MAAM,SAAS,CAAC,CAAC,MAAM,CAAC,EACjC,IAAI,EAAC,QAAQ,EAAA,QAAA,EAAA,CAEbC,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,mCAAmC,EAAA,QAAA,EAAE,WAAW,EAAA,CAAQ,EACxEA,cAAA,CAAC,WAAW,EAAA,EAAC,IAAI,EAAE,MAAM,EAAA,CAAI,CAAA,EAAA,CACtB,EAER,MAAM,KACLD,eAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,6BAA6B,EAAA,QAAA,EAAA,CAC1CC,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,mCAAmC,EAAA,QAAA,EAChDA,0BACE,SAAS,EAAC,2BAA2B,EACrC,IAAI,EAAC,MAAM,EACX,WAAW,EAAE,CAAC,CAAC,yBAAyB,CAAC,EACzC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC1C,SAAS,EAAA,IAAA,EAAA,CACT,GACE,EAEND,eAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAC,yBAAyB,EACnC,GAAG,EAAE,OAAO,aAEX,OAAO,KACNC,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,4BAA4B,EAAA,QAAA,EAAE,CAAC,CAAC,YAAY,CAAC,EAAA,CAAO,CACpE,EACA,CAAC,OAAO,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,KAChCA,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,0BAA0B,EAAA,QAAA,EACtC,CAAC,CAAC,kBAAkB,CAAC,EAAA,CAClB,CACP,EACA,CAAC,OAAO;gCACP,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,MAChBD,eAAA,CAAA,QAAA,EAAA,EAEE,SAAS,EAAC,yBAAyB,EAAA,aAAA,EACtB,IAAI,CAAC,OAAO,KAAK,cAAc,EAC5C,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,MAAK;AACZ,wCAAA,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;wCACtB,SAAS,CAAC,KAAK,CAAC;oCAClB,CAAC,EAAA,QAAA,EAAA,CAEA,IAAI,CAAC,OAAO,KAAK,cAAc,KAC9BC,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,+BAA+B,YAC7CA,cAAA,CAAC,SAAS,EAAA,EAAA,CAAG,EAAA,CACR,CACR,EACDA,yBAAM,SAAS,EAAC,8BAA8B,EAAA,QAAA,EAC3C,oBAAoB,CAAC,IAAI,CAAC,EAAA,CACtB,EACPA,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,8BAA8B,EAAA,QAAA,EAC3C,UAAU,CAAC,IAAI,CAAC,mBAAmB,IAAI,IAAI,CAAC,mBAAmB,CAAC,EAAA,CAC5D,CAAA,EAAA,EAnBF,IAAI,CAAC,OAAO,CAoBV,CACV,CAAC,EACH,WAAW,KACVA,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,4BAA4B,EAAA,QAAA,EACxC,CAAC,CAAC,iBAAiB,CAAC,EAAA,CACjB,CACP,EACA,CAAC,WAAW,IAAI,OAAO,IAAI,CAAC,OAAO,KAClCA,cAAA,CAAA,QAAA,EAAA,EACE,SAAS,EAAC,8BAA8B,EACxC,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,cAAc,EAAA,QAAA,EAEtB,CAAC,CAAC,WAAW,CAAC,EAAA,CACR,CACV,CAAA,EAAA,CACG,EAENA,cAAA,CAAA,QAAA,EAAA,EACE,SAAS,EAAC,wBAAwB,EAClC,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,MAAK;AACZ,4BAAA,SAAS,EAAE;4BACX,SAAS,CAAC,KAAK,CAAC;wBAClB,CAAC,EAAA,QAAA,EAEA,CAAC,CAAC,oBAAoB,CAAC,GACjB,CAAA,EAAA,CACL,CACP,CAAA,EAAA,CACG;AAEV;AAEA,SAAS,WAAW,CAAC,EAAE,IAAI,EAAqB,EAAA;AAC9C,IAAA,QACEA,cAAA,CAAA,KAAA,EAAA,EACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,GAAG,gBAAgB,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,EAAA,QAAA,EAE7EA,cAAA,CAAA,UAAA,EAAA,EAAU,MAAM,EAAC,gBAAgB,EAAA,CAAG,EAAA,CAChC;AAEV;AAEA,SAAS,SAAS,GAAA;AAChB,IAAA,QACEA,cAAA,CAAA,KAAA,EAAA,EAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,KAAK,EAAC,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,EAAA,QAAA,EAC9IA,6BAAU,MAAM,EAAC,gBAAgB,EAAA,CAAG,EAAA,CAChC;AAEV;AAEA,SAAS,UAAU,CAAC,EAAU,EAAA;AAC5B,IAAA,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC;AACtB,IAAA,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE;IACtB,IAAI,CAAC,CAAC,YAAY,EAAE,KAAK,GAAG,CAAC,YAAY,EAAE,EAAE;AAC3C,QAAA,OAAO,CAAC,CAAC,kBAAkB,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAChF;IACA,OAAO,CAAC,CAAC,kBAAkB,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAChH;;"}
|
|
1
|
+
{"version":3,"file":"ConversationSelector.js","sources":["../../../../../src/components/ChatDrawer/ConversationSelector.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport { useOptionalDevicContext } from '../../provider';\nimport { DevicApiClient } from '../../api/client';\nimport type { ConversationSummary } from '../../api/types';\nimport type { ConversationSelectorProps } from './ChatDrawer.types';\nimport { useTranslations } from '../../i18n';\n\nconst PAGE_SIZE = 10;\n\nexport function ConversationSelector({\n assistantId,\n currentChatUid,\n onSelect,\n onNewChat,\n apiKey: propsApiKey,\n baseUrl: propsBaseUrl,\n tenantId: propsTenantId,\n subtenantId: propsSubtenantId,\n conversationPreview,\n}: ConversationSelectorProps): JSX.Element {\n const t = useTranslations();\n const context = useOptionalDevicContext();\n const apiKey = propsApiKey || context?.apiKey;\n const baseUrl = propsBaseUrl || context?.baseUrl || 'https://api.devic.ai';\n const tenantId = propsTenantId || context?.tenantId;\n const subtenantId = propsSubtenantId || context?.subtenantId;\n\n const [isOpen, setIsOpen] = useState(false);\n const [conversations, setConversations] = useState<ConversationSummary[]>([]);\n const [search, setSearch] = useState('');\n const [loading, setLoading] = useState(false);\n const [loadingMore, setLoadingMore] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n const [firstMessages, setFirstMessages] = useState<Record<string, string | null>>({});\n const fetchedChatsRef = useRef<Set<string>>(new Set());\n const dropdownRef = useRef<HTMLDivElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const clientRef = useRef<DevicApiClient | null>(null);\n const getTenantSession = context?.getTenantSession;\n const onSessionExpired = context?.onSessionExpired;\n\n if (!clientRef.current && (apiKey || getTenantSession)) {\n clientRef.current = new DevicApiClient({ apiKey, baseUrl, getTenantSession, onSessionExpired });\n }\n\n // Update client config when props/context change\n useEffect(() => {\n if (clientRef.current) {\n clientRef.current.setConfig({ apiKey, baseUrl, getTenantSession, onSessionExpired });\n } else if (apiKey || getTenantSession) {\n clientRef.current = new DevicApiClient({ apiKey, baseUrl, getTenantSession, onSessionExpired });\n }\n }, [apiKey, baseUrl, getTenantSession]);\n\n const fetchConversations = useCallback(async (offset = 0, append = false) => {\n if (!clientRef.current) return;\n if (offset === 0) {\n setLoading(true);\n } else {\n setLoadingMore(true);\n }\n try {\n const response = await clientRef.current.listConversations(assistantId, {\n tenantId,\n subtenantId,\n offset,\n limit: PAGE_SIZE,\n });\n setConversations((prev) => append ? [...prev, ...response.histories] : response.histories);\n setHasMore(offset + response.histories.length < response.total);\n } catch {\n // silently fail\n } finally {\n setLoading(false);\n setLoadingMore(false);\n }\n }, [assistantId, tenantId, subtenantId]);\n\n useEffect(() => {\n if (isOpen) {\n fetchConversations(0);\n }\n }, [isOpen, fetchConversations]);\n\n // Fetch conversations when currentChatUid changes so the selector label is correct\n useEffect(() => {\n if (currentChatUid && conversations.length === 0) {\n fetchConversations(0);\n }\n }, [currentChatUid, conversations.length, fetchConversations]);\n\n const handleLoadMore = useCallback(() => {\n if (!loadingMore && hasMore) {\n fetchConversations(conversations.length, true);\n }\n }, [loadingMore, hasMore, conversations.length, fetchConversations]);\n\n // Lazy-fetch first user message for unnamed conversations\n useEffect(() => {\n if (conversationPreview !== 'firstMessage' || !clientRef.current || !isOpen) return;\n const unnamed = conversations.filter((c) => !c.name && !fetchedChatsRef.current.has(c.chatUID));\n if (unnamed.length === 0) return;\n\n // Mark as loading (null = loading)\n unnamed.forEach((c) => fetchedChatsRef.current.add(c.chatUID));\n setFirstMessages((prev) => {\n const next = { ...prev };\n unnamed.forEach((c) => { next[c.chatUID] = null; });\n return next;\n });\n\n unnamed.forEach((conv) => {\n clientRef.current!.getChatHistory(assistantId, conv.chatUID, { tenantId }).then((history) => {\n const firstUserMsg = history.chatContent?.find((m) => m.role === 'user');\n const text = firstUserMsg?.content?.message || '';\n setFirstMessages((prev) => ({ ...prev, [conv.chatUID]: text || '' }));\n }).catch(() => {\n setFirstMessages((prev) => ({ ...prev, [conv.chatUID]: '' }));\n });\n });\n }, [conversations, isOpen, conversationPreview, assistantId, tenantId]);\n\n // Close on outside click\n useEffect(() => {\n if (!isOpen) return;\n const handler = (e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [isOpen]);\n\n const getConversationLabel = (conv: ConversationSummary): string => {\n if (conv.name) return conv.name;\n if (conversationPreview === 'firstMessage') {\n const msg = firstMessages[conv.chatUID];\n if (msg === null) return '...';\n if (msg) return msg;\n }\n return formatDate(conv.creationTimestampMs);\n };\n\n const currentConv = conversations.find((c) => c.chatUID === currentChatUid);\n const currentName = currentConv\n ? getConversationLabel(currentConv)\n : t('New chat');\n\n const filtered = conversations.filter((c) => {\n if (!search) return true;\n const q = search.toLowerCase();\n if ((c.name || '').toLowerCase().includes(q)) return true;\n if (conversationPreview === 'firstMessage') {\n const msg = firstMessages[c.chatUID];\n if (msg && msg.toLowerCase().includes(q)) return true;\n }\n return false;\n });\n\n return (\n <div className=\"devic-conversation-selector\" ref={dropdownRef}>\n <button\n className=\"devic-conversation-selector-trigger\"\n onClick={() => setIsOpen(!isOpen)}\n type=\"button\"\n >\n <span className=\"devic-conversation-selector-label\">{currentName}</span>\n <ChevronIcon open={isOpen} />\n </button>\n\n {isOpen && (\n <div className=\"devic-conversation-dropdown\">\n <div className=\"devic-conversation-search-wrapper\">\n <input\n className=\"devic-conversation-search\"\n type=\"text\"\n placeholder={t('Search conversations...')}\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n autoFocus\n />\n </div>\n\n <div\n className=\"devic-conversation-list\"\n ref={listRef}\n >\n {loading && (\n <div className=\"devic-conversation-loading\">{t('Loading...')}</div>\n )}\n {!loading && filtered.length === 0 && (\n <div className=\"devic-conversation-empty\">\n {t('No conversations')}\n </div>\n )}\n {!loading &&\n filtered.map((conv) => (\n <button\n key={conv.chatUID}\n className=\"devic-conversation-item\"\n data-active={conv.chatUID === currentChatUid}\n type=\"button\"\n onClick={() => {\n onSelect(conv.chatUID);\n setIsOpen(false);\n }}\n >\n {conv.chatUID === currentChatUid && (\n <span className=\"devic-conversation-item-check\">\n <CheckIcon />\n </span>\n )}\n <span className=\"devic-conversation-item-name\">\n {getConversationLabel(conv)}\n </span>\n <span className=\"devic-conversation-item-date\">\n {formatDate(conv.lastEditTimestampMs || conv.creationTimestampMs)}\n </span>\n </button>\n ))}\n {loadingMore && (\n <div className=\"devic-conversation-loading\">\n {t('Loading more...')}\n </div>\n )}\n {!loadingMore && hasMore && !loading && (\n <button\n className=\"devic-conversation-load-more\"\n type=\"button\"\n onClick={handleLoadMore}\n >\n {t('Load more')}\n </button>\n )}\n </div>\n\n <button\n className=\"devic-conversation-new\"\n type=\"button\"\n onClick={() => {\n onNewChat();\n setIsOpen(false);\n }}\n >\n {t('+ Start a new chat')}\n </button>\n </div>\n )}\n </div>\n );\n}\n\nfunction ChevronIcon({ open }: { open: boolean }): JSX.Element {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{ transform: open ? 'rotate(180deg)' : undefined, transition: '0.2s' }}\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n );\n}\n\nfunction CheckIcon(): JSX.Element {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20,6 9,17 4,12\" />\n </svg>\n );\n}\n\nfunction formatDate(ms: number): string {\n const d = new Date(ms);\n const now = new Date();\n if (d.toDateString() === now.toDateString()) {\n return d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });\n }\n return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' });\n}\n"],"names":["useTranslations","useOptionalDevicContext","useState","useRef","DevicApiClient","useEffect","useCallback","_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorBoundary.js","sources":["../../../../../src/components/ChatDrawer/ErrorBoundary.tsx"],"sourcesContent":["import React, { Component } from 'react';\nimport type { ReactNode, ErrorInfo } from 'react';\n\ninterface Props {\n children: ReactNode;\n fallback?: ReactNode;\n}\n\ninterface State {\n hasError: boolean;\n}\n\nexport class ChatDrawerErrorBoundary extends Component<Props, State> {\n state: State = { hasError: false };\n\n static getDerivedStateFromError(): State {\n return { hasError: true };\n }\n\n componentDidCatch(error: Error, info: ErrorInfo): void {\n console.error('[devic-ui] ChatDrawer error:', error, info.componentStack);\n }\n\n render(): ReactNode {\n if (this.state.hasError) {\n return this.props.fallback ?? null;\n }\n return this.props.children;\n }\n}\n"],"names":["Component"],"mappings":";;;;AAYM,MAAO,uBAAwB,SAAQA,eAAuB,CAAA;AAApE,IAAA,WAAA,GAAA;;AACE,QAAA,IAAA,CAAA,KAAK,GAAU,EAAE,QAAQ,EAAE,KAAK,EAAE;IAgBpC;AAdE,IAAA,OAAO,wBAAwB,GAAA;AAC7B,QAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC3B;IAEA,iBAAiB,CAAC,KAAY,EAAE,IAAe,EAAA;QAC7C,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC;IAC3E;IAEA,MAAM,GAAA;AACJ,QAAA,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;AACvB,YAAA,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI;QACpC;AACA,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ;IAC5B;AACD
|
|
1
|
+
{"version":3,"file":"ErrorBoundary.js","sources":["../../../../../src/components/ChatDrawer/ErrorBoundary.tsx"],"sourcesContent":["import React, { Component } from 'react';\nimport type { ReactNode, ErrorInfo } from 'react';\n\ninterface Props {\n children: ReactNode;\n fallback?: ReactNode;\n}\n\ninterface State {\n hasError: boolean;\n}\n\nexport class ChatDrawerErrorBoundary extends Component<Props, State> {\n state: State = { hasError: false };\n\n static getDerivedStateFromError(): State {\n return { hasError: true };\n }\n\n componentDidCatch(error: Error, info: ErrorInfo): void {\n console.error('[devic-ui] ChatDrawer error:', error, info.componentStack);\n }\n\n render(): ReactNode {\n if (this.state.hasError) {\n return this.props.fallback ?? null;\n }\n return this.props.children;\n }\n}\n"],"names":["Component"],"mappings":";;;;AAYM,MAAO,uBAAwB,SAAQA,eAAuB,CAAA;AAApE,IAAA,WAAA,GAAA;;AACE,QAAA,IAAA,CAAA,KAAK,GAAU,EAAE,QAAQ,EAAE,KAAK,EAAE;IAgBpC;AAdE,IAAA,OAAO,wBAAwB,GAAA;AAC7B,QAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC3B;IAEA,iBAAiB,CAAC,KAAY,EAAE,IAAe,EAAA;QAC7C,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC;IAC3E;IAEA,MAAM,GAAA;AACJ,QAAA,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;AACvB,YAAA,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI;QACpC;AACA,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ;IAC5B;AACD;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GuardrailNotice.js","sources":["../../../../../src/components/ChatDrawer/GuardrailNotice.tsx"],"sourcesContent":["import React from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useTranslations } from \"../../i18n\";\nimport type { Translator } from \"../../i18n\";\n\n/**\n * What the backend records when a guardrail stops a turn. Sent as the content\n * of a `guard_rail` message, and mirrored on the conversation itself.\n *\n * Every field is optional on purpose: this is a provider payload, its shape\n * varies with the guardrail that fired, and the notice has to survive whatever\n * comes back.\n */\nexport interface GuardrailPayload {\n tripwireTriggered?: boolean;\n info?: {\n guardrail_name?: string;\n flagged?: boolean;\n confidence?: number;\n threshold?: number;\n stage_name?: string;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\nexport interface GuardrailNoticeProps {\n /** The guardrail result, when the backend sent a structured one. */\n payload?: GuardrailPayload;\n /** The message text, when the backend sent a plain sentence instead. */\n text?: string;\n}\n\nexport type GuardrailRenderer = (props: GuardrailNoticeProps) => ReactNode;\n\n/**\n * The line that replaces the answer when a guardrail stopped the turn.\n *\n * It is deliberately not a message bubble: nobody said this, the assistant was\n * prevented from speaking. What it does say is which guardrail fired, because\n * a reader who only sees \"blocked\" cannot tell a topic filter from an outage.\n */\nexport function GuardrailNotice({\n payload,\n text,\n}: GuardrailNoticeProps): JSX.Element {\n const t = useTranslations();\n return (\n <div className=\"devic-guardrail-notice\" role=\"status\">\n <span className=\"devic-guardrail-notice-icon\" aria-hidden=\"true\">\n <ShieldIcon />\n </span>\n <span>{text || noticeText(t, payload)}</span>\n </div>\n );\n}\n\n/**\n * Names the guardrail when the payload carries a name, and stays vague when it\n * does not — an invented name is worse than no name.\n *\n * The name is a `{name}` placeholder rather than interpolated here, so a\n * translation can put it wherever that language needs it.\n */\nfunction noticeText(t: Translator, payload?: GuardrailPayload): string {\n const name = payload?.info?.guardrail_name;\n const stage = payload?.info?.stage_name;\n\n if (!name) {\n return t(\"This message was stopped by a guardrail.\");\n }\n if (stage === \"input\") {\n return t(\"Your message was stopped by the “{name}” guardrail.\", { name });\n }\n return t(\"The answer was stopped by the “{name}” guardrail.\", { name });\n}\n\nfunction ShieldIcon(): JSX.Element {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\" />\n <line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\" />\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\" />\n </svg>\n );\n}\n"],"names":["useTranslations","_jsxs","_jsx"],"mappings":";;;;;AAmCA;;;;;;AAMG;SACa,eAAe,CAAC,EAC9B,OAAO,EACP,IAAI,GACiB,EAAA;AACrB,IAAA,MAAM,CAAC,GAAGA,+BAAe,EAAE;AAC3B,IAAA,QACEC,eAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,wBAAwB,EAAC,IAAI,EAAC,QAAQ,aACnDC,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,6BAA6B,iBAAa,MAAM,EAAA,QAAA,EAC9DA,cAAA,CAAC,UAAU,EAAA,EAAA,CAAG,EAAA,CACT,EACPA,cAAA,CAAA,MAAA,EAAA,EAAA,QAAA,EAAO,IAAI,IAAI,UAAU,CAAC,CAAC,EAAE,OAAO,CAAC,EAAA,CAAQ,CAAA,EAAA,CACzC;AAEV;AAEA;;;;;;AAMG;AACH,SAAS,UAAU,CAAC,CAAa,EAAE,OAA0B,EAAA;AAC3D,IAAA,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,EAAE,cAAc;AAC1C,IAAA,MAAM,KAAK,GAAG,OAAO,EAAE,IAAI,EAAE,UAAU;IAEvC,IAAI,CAAC,IAAI,EAAE;AACT,QAAA,OAAO,CAAC,CAAC,0CAA0C,CAAC;IACtD;AACA,IAAA,IAAI,KAAK,KAAK,OAAO,EAAE;QACrB,OAAO,CAAC,CAAC,qDAAqD,EAAE,EAAE,IAAI,EAAE,CAAC;IAC3E;IACA,OAAO,CAAC,CAAC,mDAAmD,EAAE,EAAE,IAAI,EAAE,CAAC;AACzE;AAEA,SAAS,UAAU,GAAA;AACjB,IAAA,QACED,eAAA,CAAA,KAAA,EAAA,EACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EAAA,QAAA,EAAA,CAEtBC,cAAA,CAAA,MAAA,EAAA,EAAM,CAAC,EAAC,6CAA6C,EAAA,CAAG,EACxDA,yBAAM,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAA,CAAG,EACvCA,cAAA,CAAA,MAAA,EAAA,EAAM,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,OAAO,EAAC,EAAE,EAAC,IAAI,EAAA,CAAG,CAAA,EAAA,CACvC;AAEV
|
|
1
|
+
{"version":3,"file":"GuardrailNotice.js","sources":["../../../../../src/components/ChatDrawer/GuardrailNotice.tsx"],"sourcesContent":["import React from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useTranslations } from \"../../i18n\";\nimport type { Translator } from \"../../i18n\";\n\n/**\n * What the backend records when a guardrail stops a turn. Sent as the content\n * of a `guard_rail` message, and mirrored on the conversation itself.\n *\n * Every field is optional on purpose: this is a provider payload, its shape\n * varies with the guardrail that fired, and the notice has to survive whatever\n * comes back.\n */\nexport interface GuardrailPayload {\n tripwireTriggered?: boolean;\n info?: {\n guardrail_name?: string;\n flagged?: boolean;\n confidence?: number;\n threshold?: number;\n stage_name?: string;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\nexport interface GuardrailNoticeProps {\n /** The guardrail result, when the backend sent a structured one. */\n payload?: GuardrailPayload;\n /** The message text, when the backend sent a plain sentence instead. */\n text?: string;\n}\n\nexport type GuardrailRenderer = (props: GuardrailNoticeProps) => ReactNode;\n\n/**\n * The line that replaces the answer when a guardrail stopped the turn.\n *\n * It is deliberately not a message bubble: nobody said this, the assistant was\n * prevented from speaking. What it does say is which guardrail fired, because\n * a reader who only sees \"blocked\" cannot tell a topic filter from an outage.\n */\nexport function GuardrailNotice({\n payload,\n text,\n}: GuardrailNoticeProps): JSX.Element {\n const t = useTranslations();\n return (\n <div className=\"devic-guardrail-notice\" role=\"status\">\n <span className=\"devic-guardrail-notice-icon\" aria-hidden=\"true\">\n <ShieldIcon />\n </span>\n <span>{text || noticeText(t, payload)}</span>\n </div>\n );\n}\n\n/**\n * Names the guardrail when the payload carries a name, and stays vague when it\n * does not — an invented name is worse than no name.\n *\n * The name is a `{name}` placeholder rather than interpolated here, so a\n * translation can put it wherever that language needs it.\n */\nfunction noticeText(t: Translator, payload?: GuardrailPayload): string {\n const name = payload?.info?.guardrail_name;\n const stage = payload?.info?.stage_name;\n\n if (!name) {\n return t(\"This message was stopped by a guardrail.\");\n }\n if (stage === \"input\") {\n return t(\"Your message was stopped by the “{name}” guardrail.\", { name });\n }\n return t(\"The answer was stopped by the “{name}” guardrail.\", { name });\n}\n\nfunction ShieldIcon(): JSX.Element {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\" />\n <line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\" />\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\" />\n </svg>\n );\n}\n"],"names":["useTranslations","_jsxs","_jsx"],"mappings":";;;;;AAmCA;;;;;;AAMG;SACa,eAAe,CAAC,EAC9B,OAAO,EACP,IAAI,GACiB,EAAA;AACrB,IAAA,MAAM,CAAC,GAAGA,+BAAe,EAAE;AAC3B,IAAA,QACEC,eAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,wBAAwB,EAAC,IAAI,EAAC,QAAQ,aACnDC,cAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,6BAA6B,iBAAa,MAAM,EAAA,QAAA,EAC9DA,cAAA,CAAC,UAAU,EAAA,EAAA,CAAG,EAAA,CACT,EACPA,cAAA,CAAA,MAAA,EAAA,EAAA,QAAA,EAAO,IAAI,IAAI,UAAU,CAAC,CAAC,EAAE,OAAO,CAAC,EAAA,CAAQ,CAAA,EAAA,CACzC;AAEV;AAEA;;;;;;AAMG;AACH,SAAS,UAAU,CAAC,CAAa,EAAE,OAA0B,EAAA;AAC3D,IAAA,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,EAAE,cAAc;AAC1C,IAAA,MAAM,KAAK,GAAG,OAAO,EAAE,IAAI,EAAE,UAAU;IAEvC,IAAI,CAAC,IAAI,EAAE;AACT,QAAA,OAAO,CAAC,CAAC,0CAA0C,CAAC;IACtD;AACA,IAAA,IAAI,KAAK,KAAK,OAAO,EAAE;QACrB,OAAO,CAAC,CAAC,qDAAqD,EAAE,EAAE,IAAI,EAAE,CAAC;IAC3E;IACA,OAAO,CAAC,CAAC,mDAAmD,EAAE,EAAE,IAAI,EAAE,CAAC;AACzE;AAEA,SAAS,UAAU,GAAA;AACjB,IAAA,QACED,eAAA,CAAA,KAAA,EAAA,EACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EAAA,QAAA,EAAA,CAEtBC,cAAA,CAAA,MAAA,EAAA,EAAM,CAAC,EAAC,6CAA6C,EAAA,CAAG,EACxDA,yBAAM,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAA,CAAG,EACvCA,cAAA,CAAA,MAAA,EAAA,EAAM,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,OAAO,EAAC,EAAE,EAAC,IAAI,EAAA,CAAG,CAAA,EAAA,CACvC;AAEV;;;;"}
|