@devicai/ui 0.36.0 → 0.37.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.
Files changed (44) hide show
  1. package/README.md +50 -0
  2. package/dist/cjs/api/client.js +29 -0
  3. package/dist/cjs/api/client.js.map +1 -1
  4. package/dist/cjs/api/types.js.map +1 -1
  5. package/dist/cjs/components/ChatDrawer/ChatDrawer.js +15 -2
  6. package/dist/cjs/components/ChatDrawer/ChatDrawer.js.map +1 -1
  7. package/dist/cjs/components/ChatDrawer/ChatMessages.js +47 -12
  8. package/dist/cjs/components/ChatDrawer/ChatMessages.js.map +1 -1
  9. package/dist/cjs/components/ChatDrawer/RecalledMemoriesWidget.js +77 -0
  10. package/dist/cjs/components/ChatDrawer/RecalledMemoriesWidget.js.map +1 -0
  11. package/dist/cjs/components/CoreMemoryModal/CoreMemoryModal.js +165 -0
  12. package/dist/cjs/components/CoreMemoryModal/CoreMemoryModal.js.map +1 -0
  13. package/dist/cjs/hooks/useDevicChat.js +26 -3
  14. package/dist/cjs/hooks/useDevicChat.js.map +1 -1
  15. package/dist/cjs/index.js +4 -0
  16. package/dist/cjs/index.js.map +1 -1
  17. package/dist/cjs/styles.css +1 -1
  18. package/dist/esm/api/client.d.ts +40 -1
  19. package/dist/esm/api/client.js +29 -0
  20. package/dist/esm/api/client.js.map +1 -1
  21. package/dist/esm/api/types.d.ts +109 -0
  22. package/dist/esm/api/types.js.map +1 -1
  23. package/dist/esm/components/ChatDrawer/ChatDrawer.js +15 -2
  24. package/dist/esm/components/ChatDrawer/ChatDrawer.js.map +1 -1
  25. package/dist/esm/components/ChatDrawer/ChatDrawer.types.d.ts +35 -1
  26. package/dist/esm/components/ChatDrawer/ChatMessages.d.ts +1 -1
  27. package/dist/esm/components/ChatDrawer/ChatMessages.js +48 -13
  28. package/dist/esm/components/ChatDrawer/ChatMessages.js.map +1 -1
  29. package/dist/esm/components/ChatDrawer/RecalledMemoriesWidget.d.ts +27 -0
  30. package/dist/esm/components/ChatDrawer/RecalledMemoriesWidget.js +75 -0
  31. package/dist/esm/components/ChatDrawer/RecalledMemoriesWidget.js.map +1 -0
  32. package/dist/esm/components/ChatDrawer/index.d.ts +2 -0
  33. package/dist/esm/components/CoreMemoryModal/CoreMemoryModal.d.ts +37 -0
  34. package/dist/esm/components/CoreMemoryModal/CoreMemoryModal.js +163 -0
  35. package/dist/esm/components/CoreMemoryModal/CoreMemoryModal.js.map +1 -0
  36. package/dist/esm/components/CoreMemoryModal/index.d.ts +2 -0
  37. package/dist/esm/hooks/useDevicChat.d.ts +8 -1
  38. package/dist/esm/hooks/useDevicChat.js +27 -4
  39. package/dist/esm/hooks/useDevicChat.js.map +1 -1
  40. package/dist/esm/index.d.ts +5 -3
  41. package/dist/esm/index.js +2 -0
  42. package/dist/esm/index.js.map +1 -1
  43. package/dist/esm/styles.css +1 -1
  44. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ChatMessages.js","sources":["../../../../../src/components/ChatDrawer/ChatMessages.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from \"react\";\nimport Markdown from \"markdown-to-jsx\";\nimport { MessageActions } from \"../Feedback\";\nimport { HandoffSubagentWidget } from \"./HandoffSubagentWidget\";\nimport { ReferenceChip } from \"./ReferenceChip\";\nimport type { ChatMessagesProps, SuggestedMessage } from \"./ChatDrawer.types\";\nimport type { ChatMessage, ToolGroupConfig, ToolGroupCall } from \"../../api/types\";\nimport { normalizeMessageFile } from \"../../api/types\";\nimport type { FeedbackState } from \"../Feedback\";\nimport { segmentToolCalls } from \"../../utils/toolGroups\";\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/**\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 [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) {\n setError(\"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 });\n const transcript = await client.getTranscript(transcriptId);\n url = transcript.audioUrl || null;\n audioUrlRef.current = url;\n } catch {\n setError(\"Audio unavailable\");\n return null;\n } finally {\n setIsLoading(false);\n }\n }\n if (!url) {\n setError(\"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(\"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(\"Playback failed\");\n }\n }\n };\n\n return (\n <div\n className=\"devic-transcript-playback\"\n data-playing={isPlaying ? \"true\" : \"false\"}\n title=\"Dictated by voice\"\n >\n <button\n type=\"button\"\n className=\"devic-transcript-btn\"\n onClick={toggle}\n disabled={isLoading}\n aria-label={isPlaying ? \"Pause recording\" : \"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 || \"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 = !!msg.content?.message;\n const hasFiles = msg.content?.files && msg.content.files.length > 0;\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) {\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}: {\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}): JSX.Element {\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 || toolName || (opts.active ? \"Processing...\" : \"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 />\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 pendingInlineWidgets,\n onSubmitWidget,\n onCancelWidget,\n}: ChatMessagesProps): JSX.Element {\n const containerRef = useRef<HTMLDivElement>(null);\n const prevLengthRef = useRef(messages.length);\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 return (\n <ToolGroup\n key={`tg-${item.toolMessages[0].uid}`}\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 />\n );\n }\n\n const message = item.message;\n const rawText = message.content?.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 return (\n <div\n key={message.uid}\n className=\"devic-message\"\n data-role={message.role}\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 <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 );\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\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 [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\">PASTED</span>\n <span className=\"devic-pasted-card-meta\">\n {pastedLineCount(block.text)} lines · {expanded ? \"collapse\" : \"expand\"}\n </span>\n </span>\n </button>\n </div>\n );\n}\n"],"names":["_jsxs","_jsx","useState","useRef","useEffect","client","DevicApiClient","toolGroups","HandoffSubagentWidget","_Fragment","segmentToolCalls","parsePastedBlocks","ReferenceChip","normalizeMessageFile","MessageActions","pastedPreview","pastedLineCount"],"mappings":"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"}
1
+ {"version":3,"file":"ChatMessages.js","sources":["../../../../../src/components/ChatDrawer/ChatMessages.tsx"],"sourcesContent":["import React, { useState, useEffect, useMemo, useRef } from \"react\";\nimport Markdown from \"markdown-to-jsx\";\nimport { MessageActions } from \"../Feedback\";\nimport { HandoffSubagentWidget } from \"./HandoffSubagentWidget\";\nimport { ReferenceChip } from \"./ReferenceChip\";\nimport { RecalledMemoriesWidget } from \"./RecalledMemoriesWidget\";\nimport type { ChatMessagesProps, SuggestedMessage } from \"./ChatDrawer.types\";\nimport type { ChatMessage, RecalledMemoryRecord, ToolGroupConfig, ToolGroupCall } from \"../../api/types\";\nimport { normalizeMessageFile } from \"../../api/types\";\nimport type { FeedbackState } from \"../Feedback\";\nimport { segmentToolCalls } from \"../../utils/toolGroups\";\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/**\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 [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) {\n setError(\"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 });\n const transcript = await client.getTranscript(transcriptId);\n url = transcript.audioUrl || null;\n audioUrlRef.current = url;\n } catch {\n setError(\"Audio unavailable\");\n return null;\n } finally {\n setIsLoading(false);\n }\n }\n if (!url) {\n setError(\"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(\"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(\"Playback failed\");\n }\n }\n };\n\n return (\n <div\n className=\"devic-transcript-playback\"\n data-playing={isPlaying ? \"true\" : \"false\"}\n title=\"Dictated by voice\"\n >\n <button\n type=\"button\"\n className=\"devic-transcript-btn\"\n onClick={toggle}\n disabled={isLoading}\n aria-label={isPlaying ? \"Pause recording\" : \"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 || \"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 = !!msg.content?.message;\n const hasFiles = msg.content?.files && msg.content.files.length > 0;\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) {\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}: {\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}): JSX.Element {\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 || toolName || (opts.active ? \"Processing...\" : \"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 />\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 pendingInlineWidgets,\n onSubmitWidget,\n onCancelWidget,\n recalledMemories,\n recalledMemoriesRenderer,\n}: ChatMessagesProps): JSX.Element {\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 // 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 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 />\n {groupRecalls.length > 0 && (\n <RecalledMemoriesWidget\n records={groupRecalls}\n isLoading={isLoading}\n renderer={recalledMemoriesRenderer}\n />\n )}\n </React.Fragment>\n );\n }\n\n const message = item.message;\n const rawText = message.content?.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\n return (\n <React.Fragment key={message.uid}>\n <div\n className=\"devic-message\"\n data-role={message.role}\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 <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 </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 {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\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 [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\">PASTED</span>\n <span className=\"devic-pasted-card-meta\">\n {pastedLineCount(block.text)} lines · {expanded ? \"collapse\" : \"expand\"}\n </span>\n </span>\n </button>\n </div>\n );\n}\n"],"names":["_jsxs","_jsx","useState","useRef","useEffect","client","DevicApiClient","toolGroups","HandoffSubagentWidget","_Fragment","segmentToolCalls","useMemo","RecalledMemoriesWidget","parsePastedBlocks","ReferenceChip","normalizeMessageFile","MessageActions","pastedPreview","pastedLineCount"],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var React = require('react');
5
+
6
+ const SOURCE_LABELS = {
7
+ conversation_start: "Automatic recall",
8
+ search_memory: "Memory search",
9
+ search_memory_nodes: "Graph node search",
10
+ explore_memory_graph: "Graph exploration",
11
+ };
12
+ function dedupeFacts(records) {
13
+ const seen = new Set();
14
+ const facts = [];
15
+ for (const record of records) {
16
+ for (const fact of record.facts ?? []) {
17
+ const key = (fact.fact ?? "").trim().toLowerCase();
18
+ if (!key || seen.has(key))
19
+ continue;
20
+ seen.add(key);
21
+ facts.push(fact);
22
+ }
23
+ }
24
+ return facts;
25
+ }
26
+ function dedupeEntities(records) {
27
+ const seen = new Set();
28
+ return records
29
+ .flatMap((r) => r.entities ?? [])
30
+ .filter((e) => {
31
+ const key = (e.name ?? "").trim().toLowerCase();
32
+ if (!key || seen.has(key))
33
+ return false;
34
+ seen.add(key);
35
+ return true;
36
+ });
37
+ }
38
+ function BrainIcon() {
39
+ return (jsxRuntime.jsxs("svg", { className: "devic-recall-icon", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [jsxRuntime.jsx("path", { d: "M9.5 2a2.5 2.5 0 0 0-2.45 2A3.5 3.5 0 0 0 4.6 8.6 3.5 3.5 0 0 0 3 11.5c0 1.1.5 2.08 1.29 2.73A3.5 3.5 0 0 0 7 20a3 3 0 0 0 5-2.24V4.5A2.5 2.5 0 0 0 9.5 2Z" }), jsxRuntime.jsx("path", { d: "M14.5 2a2.5 2.5 0 0 1 2.45 2 3.5 3.5 0 0 1 2.45 4.6A3.5 3.5 0 0 1 21 11.5a3.49 3.49 0 0 1-1.29 2.73A3.5 3.5 0 0 1 17 20a3 3 0 0 1-5-2.24V4.5A2.5 2.5 0 0 1 14.5 2Z" })] }));
40
+ }
41
+ function ChevronIcon({ up }) {
42
+ return (jsxRuntime.jsx("svg", { className: "devic-recall-chevron", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", style: { transform: up ? "rotate(180deg)" : undefined }, children: jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" }) }));
43
+ }
44
+ /**
45
+ * Collapsible "Recalled memories" strip interleaved in the chat with the
46
+ * message that brought long-term memories into the conversation. Collapsed it
47
+ * summarizes ("N facts · M entities"); expanded it lists the facts (with
48
+ * their graph endpoints), the entities and any previous-session context.
49
+ * Renders nothing when the records carry no content.
50
+ */
51
+ function RecalledMemoriesWidget({ records, isLoading = false, renderer, }) {
52
+ const [expanded, setExpanded] = React.useState(false);
53
+ if (renderer) {
54
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderer({ records, isLoading }) });
55
+ }
56
+ const facts = dedupeFacts(records);
57
+ const entities = dedupeEntities(records);
58
+ const turns = records
59
+ .filter((r) => r.source === "conversation_start")
60
+ .flatMap((r) => r.turns ?? []);
61
+ const sources = [...new Set(records.map((r) => SOURCE_LABELS[r.source]))];
62
+ if (!facts.length && !entities.length && !turns.length)
63
+ return null;
64
+ const summaryParts = [];
65
+ if (facts.length) {
66
+ summaryParts.push(`${facts.length} fact${facts.length > 1 ? "s" : ""}`);
67
+ }
68
+ if (entities.length) {
69
+ summaryParts.push(`${entities.length} entit${entities.length > 1 ? "ies" : "y"}`);
70
+ }
71
+ return (jsxRuntime.jsxs("div", { className: "devic-recall", children: [jsxRuntime.jsxs("button", { type: "button", className: "devic-recall-header", onClick: () => setExpanded((v) => !v), "aria-expanded": expanded, children: [jsxRuntime.jsx(BrainIcon, {}), jsxRuntime.jsx("span", { className: "devic-recall-title", children: "Recalled memories" }), summaryParts.length > 0 && (jsxRuntime.jsx("span", { className: "devic-recall-summary", children: summaryParts.join(" · ") })), jsxRuntime.jsx("span", { className: "devic-recall-spacer" }), sources.map((s) => (jsxRuntime.jsx("span", { className: "devic-recall-source", children: s }, s))), jsxRuntime.jsx(ChevronIcon, { up: expanded })] }), expanded && (jsxRuntime.jsxs("div", { className: "devic-recall-body", children: [facts.length > 0 && (jsxRuntime.jsx("div", { className: "devic-recall-facts", children: facts.map((fact, i) => (jsxRuntime.jsxs("div", { className: "devic-recall-fact", children: [jsxRuntime.jsx("span", { children: fact.fact }), jsxRuntime.jsxs("span", { className: "devic-recall-fact-meta", children: [fact.source && fact.target
72
+ ? `${fact.source} → ${fact.relation} → ${fact.target}`
73
+ : fact.relation, fact.validAt ? ` · since ${fact.validAt.slice(0, 10)}` : ""] })] }, i))) })), entities.length > 0 && (jsxRuntime.jsx("div", { className: "devic-recall-entities", children: entities.map((entity) => (jsxRuntime.jsxs("span", { className: "devic-recall-entity", title: entity.summary || undefined, children: [entity.name, jsxRuntime.jsxs("span", { className: "devic-recall-entity-type", children: [" ", "\u00B7 ", entity.type] })] }, entity.id))) })), turns.length > 0 && (jsxRuntime.jsxs("div", { className: "devic-recall-turns", children: [jsxRuntime.jsx("span", { className: "devic-recall-turns-title", children: "Previous session context" }), turns.map((turn, i) => (jsxRuntime.jsxs("span", { className: "devic-recall-turn", children: [jsxRuntime.jsxs("span", { className: "devic-recall-turn-role", children: [turn.role, ":"] }), " ", turn.content] }, i)))] }))] }))] }));
74
+ }
75
+
76
+ exports.RecalledMemoriesWidget = RecalledMemoriesWidget;
77
+ //# sourceMappingURL=RecalledMemoriesWidget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecalledMemoriesWidget.js","sources":["../../../../../src/components/ChatDrawer/RecalledMemoriesWidget.tsx"],"sourcesContent":["import { useState, type JSX, type ReactNode } from \"react\";\nimport type {\n RecalledMemoryEntity,\n RecalledMemoryFact,\n RecalledMemoryRecord,\n} from \"../../api/types\";\n\n/** Data handed to a custom recalled-memories renderer. */\nexport interface RecalledMemoriesRendererProps {\n /** The recall events anchored at this point of the conversation. */\n records: RecalledMemoryRecord[];\n /** True while the run that produced (or is producing) them is in flight. */\n isLoading: boolean;\n}\n\n/** Replaces the built-in \"Recalled memories\" strip. Return null to hide it. */\nexport type RecalledMemoriesRenderer = (\n props: RecalledMemoriesRendererProps\n) => ReactNode;\n\nconst SOURCE_LABELS: Record<RecalledMemoryRecord[\"source\"], string> = {\n conversation_start: \"Automatic recall\",\n search_memory: \"Memory search\",\n search_memory_nodes: \"Graph node search\",\n explore_memory_graph: \"Graph exploration\",\n};\n\nfunction dedupeFacts(records: RecalledMemoryRecord[]): RecalledMemoryFact[] {\n const seen = new Set<string>();\n const facts: RecalledMemoryFact[] = [];\n for (const record of records) {\n for (const fact of record.facts ?? []) {\n const key = (fact.fact ?? \"\").trim().toLowerCase();\n if (!key || seen.has(key)) continue;\n seen.add(key);\n facts.push(fact);\n }\n }\n return facts;\n}\n\nfunction dedupeEntities(\n records: RecalledMemoryRecord[]\n): RecalledMemoryEntity[] {\n const seen = new Set<string>();\n return records\n .flatMap((r) => r.entities ?? [])\n .filter((e) => {\n const key = (e.name ?? \"\").trim().toLowerCase();\n if (!key || seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nfunction BrainIcon(): JSX.Element {\n return (\n <svg\n className=\"devic-recall-icon\"\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 aria-hidden=\"true\"\n >\n <path d=\"M9.5 2a2.5 2.5 0 0 0-2.45 2A3.5 3.5 0 0 0 4.6 8.6 3.5 3.5 0 0 0 3 11.5c0 1.1.5 2.08 1.29 2.73A3.5 3.5 0 0 0 7 20a3 3 0 0 0 5-2.24V4.5A2.5 2.5 0 0 0 9.5 2Z\" />\n <path d=\"M14.5 2a2.5 2.5 0 0 1 2.45 2 3.5 3.5 0 0 1 2.45 4.6A3.5 3.5 0 0 1 21 11.5a3.49 3.49 0 0 1-1.29 2.73A3.5 3.5 0 0 1 17 20a3 3 0 0 1-5-2.24V4.5A2.5 2.5 0 0 1 14.5 2Z\" />\n </svg>\n );\n}\n\nfunction ChevronIcon({ up }: { up: boolean }): JSX.Element {\n return (\n <svg\n className=\"devic-recall-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\nexport interface RecalledMemoriesWidgetProps {\n records: RecalledMemoryRecord[];\n /** True while the run that produced the records is still processing. */\n isLoading?: boolean;\n /** Custom renderer replacing the built-in strip. */\n renderer?: RecalledMemoriesRenderer;\n}\n\n/**\n * Collapsible \"Recalled memories\" strip interleaved in the chat with the\n * message that brought long-term memories into the conversation. Collapsed it\n * summarizes (\"N facts · M entities\"); expanded it lists the facts (with\n * their graph endpoints), the entities and any previous-session context.\n * Renders nothing when the records carry no content.\n */\nexport function RecalledMemoriesWidget({\n records,\n isLoading = false,\n renderer,\n}: RecalledMemoriesWidgetProps): JSX.Element | null {\n const [expanded, setExpanded] = useState(false);\n\n if (renderer) {\n return <>{renderer({ records, isLoading })}</>;\n }\n\n const facts = dedupeFacts(records);\n const entities = dedupeEntities(records);\n const turns = records\n .filter((r) => r.source === \"conversation_start\")\n .flatMap((r) => r.turns ?? []);\n const sources = [...new Set(records.map((r) => SOURCE_LABELS[r.source]))];\n\n if (!facts.length && !entities.length && !turns.length) return null;\n\n const summaryParts: string[] = [];\n if (facts.length) {\n summaryParts.push(`${facts.length} fact${facts.length > 1 ? \"s\" : \"\"}`);\n }\n if (entities.length) {\n summaryParts.push(\n `${entities.length} entit${entities.length > 1 ? \"ies\" : \"y\"}`\n );\n }\n\n return (\n <div className=\"devic-recall\">\n <button\n type=\"button\"\n className=\"devic-recall-header\"\n onClick={() => setExpanded((v) => !v)}\n aria-expanded={expanded}\n >\n <BrainIcon />\n <span className=\"devic-recall-title\">Recalled memories</span>\n {summaryParts.length > 0 && (\n <span className=\"devic-recall-summary\">\n {summaryParts.join(\" · \")}\n </span>\n )}\n <span className=\"devic-recall-spacer\" />\n {sources.map((s) => (\n <span key={s} className=\"devic-recall-source\">\n {s}\n </span>\n ))}\n <ChevronIcon up={expanded} />\n </button>\n\n {expanded && (\n <div className=\"devic-recall-body\">\n {facts.length > 0 && (\n <div className=\"devic-recall-facts\">\n {facts.map((fact, i) => (\n <div key={i} className=\"devic-recall-fact\">\n <span>{fact.fact}</span>\n <span className=\"devic-recall-fact-meta\">\n {fact.source && fact.target\n ? `${fact.source} → ${fact.relation} → ${fact.target}`\n : fact.relation}\n {fact.validAt ? ` · since ${fact.validAt.slice(0, 10)}` : \"\"}\n </span>\n </div>\n ))}\n </div>\n )}\n\n {entities.length > 0 && (\n <div className=\"devic-recall-entities\">\n {entities.map((entity) => (\n <span\n key={entity.id}\n className=\"devic-recall-entity\"\n title={entity.summary || undefined}\n >\n {entity.name}\n <span className=\"devic-recall-entity-type\">\n {\" \"}\n · {entity.type}\n </span>\n </span>\n ))}\n </div>\n )}\n\n {turns.length > 0 && (\n <div className=\"devic-recall-turns\">\n <span className=\"devic-recall-turns-title\">\n Previous session context\n </span>\n {turns.map((turn, i) => (\n <span key={i} className=\"devic-recall-turn\">\n <span className=\"devic-recall-turn-role\">{turn.role}:</span>{\" \"}\n {turn.content}\n </span>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n\nexport default RecalledMemoriesWidget;\n"],"names":["_jsxs","_jsx","useState","_Fragment"],"mappings":"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"}
@@ -0,0 +1,165 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var React = require('react');
5
+ var reactDom = require('react-dom');
6
+ var client = require('../../api/client.js');
7
+ var DevicContext = require('../../provider/DevicContext.js');
8
+
9
+ /** Canonical sections of the core tier, in display order. */
10
+ const SECTIONS = ["persona", "instructions", "decisions", "profile"];
11
+ function BrainIcon() {
12
+ return (jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [jsxRuntime.jsx("path", { d: "M9.5 2a2.5 2.5 0 0 0-2.45 2A3.5 3.5 0 0 0 4.6 8.6 3.5 3.5 0 0 0 3 11.5c0 1.1.5 2.08 1.29 2.73A3.5 3.5 0 0 0 7 20a3 3 0 0 0 5-2.24V4.5A2.5 2.5 0 0 0 9.5 2Z" }), jsxRuntime.jsx("path", { d: "M14.5 2a2.5 2.5 0 0 1 2.45 2 3.5 3.5 0 0 1 2.45 4.6A3.5 3.5 0 0 1 21 11.5a3.49 3.49 0 0 1-1.29 2.73A3.5 3.5 0 0 1 17 20a3 3 0 0 1-5-2.24V4.5A2.5 2.5 0 0 1 14.5 2Z" })] }));
13
+ }
14
+ function PinIcon() {
15
+ return (jsxRuntime.jsx("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "currentColor", stroke: "none", "aria-hidden": "true", children: jsxRuntime.jsx("path", { d: "M16 3a1 1 0 0 1 .97 1.243l-1.2 4.8 3.937 3.938A1 1 0 0 1 19 14.688V15a1 1 0 0 1-1 1h-5v6l-1 1-1-1v-6H6a1 1 0 0 1-1-1v-.312a1 1 0 0 1 .293-.707L9.23 9.043l-1.2-4.8A1 1 0 0 1 9 3h7Z" }) }));
16
+ }
17
+ /**
18
+ * Modal showing — and, when `editable`, managing — the core memory of an
19
+ * assistant for a tenant/subtenant combination: the standing entries
20
+ * (persona, instructions, decisions, profile) injected into every prompt of
21
+ * the bucket the assistant resolves there. Lets the end user see and control
22
+ * what the assistant permanently remembers about them.
23
+ *
24
+ * Backed by the public memory API (`/api/v1/memory/assistants/:id/core`);
25
+ * the API key needs that endpoint allowed.
26
+ */
27
+ function CoreMemoryModal({ isOpen, onClose, assistantId, tenantId, subtenantId, apiKey, baseUrl, editable = true, title = "Assistant memory", }) {
28
+ const context = DevicContext.useOptionalDevicContext();
29
+ const resolvedApiKey = apiKey || context?.apiKey;
30
+ const resolvedBaseUrl = baseUrl || context?.baseUrl || "https://api.devic.ai";
31
+ const resolvedTenantId = tenantId || context?.tenantId;
32
+ const resolvedSubtenantId = subtenantId || context?.subtenantId;
33
+ const client$1 = React.useMemo(() => resolvedApiKey
34
+ ? new client.DevicApiClient({
35
+ apiKey: resolvedApiKey,
36
+ baseUrl: resolvedBaseUrl,
37
+ })
38
+ : null, [resolvedApiKey, resolvedBaseUrl]);
39
+ const [loading, setLoading] = React.useState(false);
40
+ const [enabled, setEnabled] = React.useState(true);
41
+ const [entries, setEntries] = React.useState([]);
42
+ const [limits, setLimits] = React.useState(null);
43
+ const [error, setError] = React.useState(null);
44
+ const [saving, setSaving] = React.useState(false);
45
+ // Inline composer / editor state
46
+ const [composerOpen, setComposerOpen] = React.useState(false);
47
+ const [composerSection, setComposerSection] = React.useState("profile");
48
+ const [composerText, setComposerText] = React.useState("");
49
+ const [editingId, setEditingId] = React.useState(null);
50
+ const [editingText, setEditingText] = React.useState("");
51
+ const scopeOptions = React.useMemo(() => ({
52
+ tenantId: resolvedTenantId || undefined,
53
+ subtenantId: resolvedSubtenantId || undefined,
54
+ }), [resolvedTenantId, resolvedSubtenantId]);
55
+ const refresh = React.useCallback(async () => {
56
+ if (!client$1) {
57
+ setError("API key not configured");
58
+ return;
59
+ }
60
+ setLoading(true);
61
+ setError(null);
62
+ try {
63
+ const list = await client$1.getCoreMemory(assistantId, scopeOptions);
64
+ setEnabled(list.enabled);
65
+ setEntries(list.entries);
66
+ setLimits(list.limits ?? null);
67
+ }
68
+ catch (err) {
69
+ setError(err instanceof Error ? err.message : String(err));
70
+ }
71
+ finally {
72
+ setLoading(false);
73
+ }
74
+ }, [client$1, assistantId, scopeOptions]);
75
+ // Fetch on every open (memory may have changed since the last look).
76
+ const wasOpenRef = React.useRef(false);
77
+ React.useEffect(() => {
78
+ if (isOpen && !wasOpenRef.current) {
79
+ setComposerOpen(false);
80
+ setComposerText("");
81
+ setEditingId(null);
82
+ void refresh();
83
+ }
84
+ wasOpenRef.current = isOpen;
85
+ }, [isOpen, refresh]);
86
+ // Escape closes
87
+ React.useEffect(() => {
88
+ if (!isOpen)
89
+ return;
90
+ const onKey = (e) => {
91
+ if (e.key === "Escape")
92
+ onClose();
93
+ };
94
+ document.addEventListener("keydown", onKey);
95
+ return () => document.removeEventListener("keydown", onKey);
96
+ }, [isOpen, onClose]);
97
+ const runWrite = React.useCallback(async (write) => {
98
+ setSaving(true);
99
+ setError(null);
100
+ try {
101
+ await write();
102
+ await refresh();
103
+ return true;
104
+ }
105
+ catch (err) {
106
+ setError(err instanceof Error ? err.message : String(err));
107
+ return false;
108
+ }
109
+ finally {
110
+ setSaving(false);
111
+ }
112
+ }, [refresh]);
113
+ const handleAdd = async () => {
114
+ if (!client$1 || !composerText.trim())
115
+ return;
116
+ const ok = await runWrite(() => client$1.addCoreMemoryEntry(assistantId, { content: composerText.trim(), section: composerSection }, scopeOptions));
117
+ if (ok) {
118
+ setComposerOpen(false);
119
+ setComposerText("");
120
+ }
121
+ };
122
+ const handleSaveEdit = async (entry) => {
123
+ if (!client$1 || !editingText.trim())
124
+ return;
125
+ const ok = await runWrite(() => client$1.updateCoreMemoryEntry(assistantId, entry.id, { content: editingText.trim() }, scopeOptions));
126
+ if (ok)
127
+ setEditingId(null);
128
+ };
129
+ const handleRemove = async (entry) => {
130
+ if (!client$1)
131
+ return;
132
+ await runWrite(() => client$1.deleteCoreMemoryEntry(assistantId, entry.id, scopeOptions));
133
+ };
134
+ if (!isOpen)
135
+ return null;
136
+ // Group entries by section, canonical sections first.
137
+ const sections = [];
138
+ const bySection = new Map();
139
+ for (const entry of entries) {
140
+ const list = bySection.get(entry.section);
141
+ if (list)
142
+ list.push(entry);
143
+ else
144
+ bySection.set(entry.section, [entry]);
145
+ }
146
+ for (const name of SECTIONS) {
147
+ const list = bySection.get(name);
148
+ if (list) {
149
+ sections.push({ name, entries: list });
150
+ bySection.delete(name);
151
+ }
152
+ }
153
+ for (const [name, list] of bySection)
154
+ sections.push({ name, entries: list });
155
+ return reactDom.createPortal(jsxRuntime.jsx("div", { className: "devic-cm-overlay", onClick: onClose, children: jsxRuntime.jsxs("div", { className: "devic-cm-modal", role: "dialog", "aria-modal": "true", "aria-label": title, onClick: (e) => e.stopPropagation(), children: [jsxRuntime.jsxs("div", { className: "devic-cm-header", children: [jsxRuntime.jsxs("h3", { className: "devic-cm-title", children: [jsxRuntime.jsx(BrainIcon, {}), title] }), jsxRuntime.jsx("button", { className: "devic-cm-close", onClick: onClose, type: "button", "aria-label": "Close", children: "\u00D7" })] }), jsxRuntime.jsxs("div", { className: "devic-cm-body", children: [error && jsxRuntime.jsx("div", { className: "devic-cm-error", children: error }), loading ? (jsxRuntime.jsx("div", { className: "devic-cm-loading", children: "Loading memory\u2026" })) : !enabled ? (jsxRuntime.jsx("div", { className: "devic-cm-empty", children: "Memory is not enabled for this assistant." })) : entries.length === 0 && !composerOpen ? (jsxRuntime.jsx("div", { className: "devic-cm-empty", children: "Nothing remembered yet. What the assistant learns and is told to keep will appear here." })) : (sections.map((section) => (jsxRuntime.jsxs("div", { className: "devic-cm-section", children: [jsxRuntime.jsx("div", { className: "devic-cm-section-title", children: section.name }), section.entries.map((entry) => (jsxRuntime.jsx("div", { className: "devic-cm-entry", children: editingId === entry.id ? (jsxRuntime.jsxs("div", { className: "devic-cm-editor", children: [jsxRuntime.jsx("textarea", { className: "devic-cm-textarea", value: editingText, maxLength: limits?.maxEntryChars || undefined, onChange: (e) => setEditingText(e.target.value), disabled: saving, autoFocus: true }), jsxRuntime.jsxs("div", { className: "devic-cm-editor-actions", children: [jsxRuntime.jsx("button", { type: "button", className: "devic-cm-btn devic-cm-btn-primary", onClick: () => handleSaveEdit(entry), disabled: saving || !editingText.trim(), children: "Save" }), jsxRuntime.jsx("button", { type: "button", className: "devic-cm-btn", onClick: () => setEditingId(null), disabled: saving, children: "Cancel" })] })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "devic-cm-entry-content", children: [entry.pinned && (jsxRuntime.jsx("span", { className: "devic-cm-pin", title: "Pinned: always kept, never changed by the assistant", children: jsxRuntime.jsx(PinIcon, {}) })), jsxRuntime.jsx("span", { children: entry.content })] }), editable && (jsxRuntime.jsxs("div", { className: "devic-cm-entry-actions", children: [jsxRuntime.jsx("button", { type: "button", className: "devic-cm-btn devic-cm-btn-small", onClick: () => {
156
+ setEditingId(entry.id);
157
+ setEditingText(entry.content);
158
+ }, disabled: saving, children: "Edit" }), jsxRuntime.jsx("button", { type: "button", className: "devic-cm-btn devic-cm-btn-small devic-cm-btn-danger", onClick: () => handleRemove(entry), disabled: saving, children: "Remove" })] }))] })) }, entry.id)))] }, section.name)))), editable && enabled && !loading && (jsxRuntime.jsx("div", { className: "devic-cm-composer", children: composerOpen ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "devic-cm-composer-row", children: jsxRuntime.jsx("select", { className: "devic-cm-select", value: composerSection, onChange: (e) => setComposerSection(e.target.value), disabled: saving, children: SECTIONS.map((s) => (jsxRuntime.jsx("option", { value: s, children: s }, s))) }) }), jsxRuntime.jsx("textarea", { className: "devic-cm-textarea", placeholder: "Something the assistant should always remember\u2026", value: composerText, maxLength: limits?.maxEntryChars || undefined, onChange: (e) => setComposerText(e.target.value), disabled: saving, autoFocus: true }), jsxRuntime.jsxs("div", { className: "devic-cm-editor-actions", children: [jsxRuntime.jsx("button", { type: "button", className: "devic-cm-btn devic-cm-btn-primary", onClick: handleAdd, disabled: saving || !composerText.trim(), children: "Add" }), jsxRuntime.jsx("button", { type: "button", className: "devic-cm-btn", onClick: () => {
159
+ setComposerOpen(false);
160
+ setComposerText("");
161
+ }, disabled: saving, children: "Cancel" })] })] })) : (jsxRuntime.jsx("button", { type: "button", className: "devic-cm-btn", onClick: () => setComposerOpen(true), disabled: saving, children: "+ Add memory" })) }))] }), limits && enabled && (jsxRuntime.jsxs("div", { className: "devic-cm-footer", children: [entries.length, "/", limits.maxEntries, " entries \u00B7 up to", " ", limits.maxEntryChars, " characters each"] }))] }) }), document.body);
162
+ }
163
+
164
+ exports.CoreMemoryModal = CoreMemoryModal;
165
+ //# sourceMappingURL=CoreMemoryModal.js.map