@devicai/ui 0.50.0 → 0.52.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 +68 -1
- package/dist/cjs/api/client.js +15 -0
- package/dist/cjs/api/client.js.map +1 -1
- package/dist/cjs/api/types.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/ChatDrawer.js +138 -11
- package/dist/cjs/components/ChatDrawer/ChatDrawer.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/ChatInput.js +69 -13
- package/dist/cjs/components/ChatDrawer/ChatInput.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/ChatMessages.js +6 -2
- package/dist/cjs/components/ChatDrawer/ChatMessages.js.map +1 -1
- package/dist/cjs/components/ChatDrawer/QueueNotice.js +46 -0
- package/dist/cjs/components/ChatDrawer/QueueNotice.js.map +1 -0
- package/dist/cjs/components/IntegrationsModal/integrationChoice.js +59 -0
- package/dist/cjs/components/IntegrationsModal/integrationChoice.js.map +1 -0
- package/dist/cjs/hooks/useDevicChat.js +277 -32
- package/dist/cjs/hooks/useDevicChat.js.map +1 -1
- package/dist/cjs/hooks/usePolling.js +5 -2
- package/dist/cjs/hooks/usePolling.js.map +1 -1
- package/dist/cjs/index.js +7 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/styles.css +1 -1
- package/dist/esm/api/client.d.ts +2 -5
- package/dist/esm/api/client.js +15 -0
- package/dist/esm/api/client.js.map +1 -1
- package/dist/esm/api/types.d.ts +69 -1
- package/dist/esm/api/types.js.map +1 -1
- package/dist/esm/components/ChatDrawer/ChatDrawer.js +139 -12
- package/dist/esm/components/ChatDrawer/ChatDrawer.js.map +1 -1
- package/dist/esm/components/ChatDrawer/ChatDrawer.types.d.ts +56 -4
- package/dist/esm/components/ChatDrawer/ChatInput.js +69 -13
- package/dist/esm/components/ChatDrawer/ChatInput.js.map +1 -1
- package/dist/esm/components/ChatDrawer/ChatMessages.js +6 -2
- package/dist/esm/components/ChatDrawer/ChatMessages.js.map +1 -1
- package/dist/esm/components/ChatDrawer/QueueNotice.d.ts +23 -0
- package/dist/esm/components/ChatDrawer/QueueNotice.js +44 -0
- package/dist/esm/components/ChatDrawer/QueueNotice.js.map +1 -0
- package/dist/esm/components/ChatDrawer/index.d.ts +2 -0
- package/dist/esm/components/IntegrationsModal/index.d.ts +1 -0
- package/dist/esm/components/IntegrationsModal/integrationChoice.d.ts +16 -0
- package/dist/esm/components/IntegrationsModal/integrationChoice.js +54 -0
- package/dist/esm/components/IntegrationsModal/integrationChoice.js.map +1 -0
- package/dist/esm/hooks/index.d.ts +1 -1
- package/dist/esm/hooks/useDevicChat.d.ts +65 -5
- package/dist/esm/hooks/useDevicChat.js +277 -32
- package/dist/esm/hooks/useDevicChat.js.map +1 -1
- package/dist/esm/hooks/usePolling.d.ts +12 -0
- package/dist/esm/hooks/usePolling.js +5 -2
- package/dist/esm/hooks/usePolling.js.map +1 -1
- package/dist/esm/index.d.ts +5 -5
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/styles.css +1 -1
- package/package.json +1 -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 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 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(\"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(\"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 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 [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 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}: 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 pollingInterval={pollingInterval}\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","_Fragment"],"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 { 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 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 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(\"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(\"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 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 [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 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}: 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 pollingInterval={pollingInterval}\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 // 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 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 </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\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 [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","_Fragment"],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { QueueDisposition } from '../../api/types';
|
|
2
|
+
export interface QueueNoticeProps {
|
|
3
|
+
/** How many messages are waiting on this conversation right now. */
|
|
4
|
+
queuedCount: number;
|
|
5
|
+
/** What the last accepted message was told. Shapes the wording. */
|
|
6
|
+
willProcess?: QueueDisposition;
|
|
7
|
+
/**
|
|
8
|
+
* Something happened to a message that the count alone does not explain — it
|
|
9
|
+
* was turned down, or a stop threw it away. Replaces the standing text while
|
|
10
|
+
* it is set, since it is the more urgent of the two.
|
|
11
|
+
*/
|
|
12
|
+
alert?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The line above the input that says what happens to a message written while
|
|
16
|
+
* the assistant is working.
|
|
17
|
+
*
|
|
18
|
+
* Writing into a conversation that is busy is allowed but not obvious, so it is
|
|
19
|
+
* spelled out twice: before sending, what the button will do; after, what became
|
|
20
|
+
* of it. Suppress it with `options.hideQueueNotice`, or replace it with
|
|
21
|
+
* `options.queueNoticeRenderer`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function QueueNotice({ queuedCount, willProcess, alert, }: QueueNoticeProps): JSX.Element;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The line above the input that says what happens to a message written while
|
|
5
|
+
* the assistant is working.
|
|
6
|
+
*
|
|
7
|
+
* Writing into a conversation that is busy is allowed but not obvious, so it is
|
|
8
|
+
* spelled out twice: before sending, what the button will do; after, what became
|
|
9
|
+
* of it. Suppress it with `options.hideQueueNotice`, or replace it with
|
|
10
|
+
* `options.queueNoticeRenderer`.
|
|
11
|
+
*/
|
|
12
|
+
function QueueNotice({ queuedCount, willProcess, alert, }) {
|
|
13
|
+
return (jsxs("div", { className: "devic-queue-notice", "data-alert": alert ? 'true' : undefined, role: alert ? 'alert' : 'status', children: [jsx("span", { className: "devic-queue-notice-icon", "aria-hidden": "true", children: alert ? jsx(WarningIcon, {}) : jsx(ClockIcon, {}) }), jsx("span", { children: alert || noticeText(queuedCount, willProcess) })] }));
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Three different promises, so three different sentences.
|
|
17
|
+
*
|
|
18
|
+
* `after_delay` is the one that is easy to get wrong: an assistant with an input
|
|
19
|
+
* delay queues what is written while the conversation is *idle*, waiting for the
|
|
20
|
+
* sender to finish. Telling that person the assistant will pick it up "on its
|
|
21
|
+
* next turn" describes a turn that is not happening.
|
|
22
|
+
*/
|
|
23
|
+
function noticeText(queuedCount, willProcess) {
|
|
24
|
+
if (queuedCount <= 0) {
|
|
25
|
+
return 'The assistant is still answering. Send anyway and your message joins its next turn.';
|
|
26
|
+
}
|
|
27
|
+
const subject = queuedCount === 1 ? '1 message' : `${queuedCount} messages`;
|
|
28
|
+
if (willProcess === 'after_delay') {
|
|
29
|
+
return `${subject} waiting — the assistant is giving you a moment to finish before it answers.`;
|
|
30
|
+
}
|
|
31
|
+
if (willProcess === 'on_resume') {
|
|
32
|
+
return `${subject} waiting — the assistant picks ${queuedCount === 1 ? 'it' : 'them'} up when it comes back to this conversation.`;
|
|
33
|
+
}
|
|
34
|
+
return `${subject} waiting — the assistant picks ${queuedCount === 1 ? 'it' : 'them'} up on its next turn.`;
|
|
35
|
+
}
|
|
36
|
+
function WarningIcon() {
|
|
37
|
+
return (jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("path", { d: "M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }), jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }), jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })] }));
|
|
38
|
+
}
|
|
39
|
+
function ClockIcon() {
|
|
40
|
+
return (jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("circle", { cx: "12", cy: "12", r: "9" }), jsx("polyline", { points: "12 7 12 12 15 14" })] }));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { QueueNotice };
|
|
44
|
+
//# sourceMappingURL=QueueNotice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueueNotice.js","sources":["../../../../src/components/ChatDrawer/QueueNotice.tsx"],"sourcesContent":["import React from 'react';\nimport type { QueueDisposition } from '../../api/types';\n\nexport interface QueueNoticeProps {\n /** How many messages are waiting on this conversation right now. */\n queuedCount: number;\n /** What the last accepted message was told. Shapes the wording. */\n willProcess?: QueueDisposition;\n /**\n * Something happened to a message that the count alone does not explain — it\n * was turned down, or a stop threw it away. Replaces the standing text while\n * it is set, since it is the more urgent of the two.\n */\n alert?: string;\n}\n\n/**\n * The line above the input that says what happens to a message written while\n * the assistant is working.\n *\n * Writing into a conversation that is busy is allowed but not obvious, so it is\n * spelled out twice: before sending, what the button will do; after, what became\n * of it. Suppress it with `options.hideQueueNotice`, or replace it with\n * `options.queueNoticeRenderer`.\n */\nexport function QueueNotice({\n queuedCount,\n willProcess,\n alert,\n}: QueueNoticeProps): JSX.Element {\n return (\n <div\n className=\"devic-queue-notice\"\n data-alert={alert ? 'true' : undefined}\n role={alert ? 'alert' : 'status'}\n >\n <span className=\"devic-queue-notice-icon\" aria-hidden=\"true\">\n {alert ? <WarningIcon /> : <ClockIcon />}\n </span>\n <span>{alert || noticeText(queuedCount, willProcess)}</span>\n </div>\n );\n}\n\n/**\n * Three different promises, so three different sentences.\n *\n * `after_delay` is the one that is easy to get wrong: an assistant with an input\n * delay queues what is written while the conversation is *idle*, waiting for the\n * sender to finish. Telling that person the assistant will pick it up \"on its\n * next turn\" describes a turn that is not happening.\n */\nfunction noticeText(\n queuedCount: number,\n willProcess?: QueueDisposition\n): string {\n if (queuedCount <= 0) {\n return 'The assistant is still answering. Send anyway and your message joins its next turn.';\n }\n\n const subject = queuedCount === 1 ? '1 message' : `${queuedCount} messages`;\n\n if (willProcess === 'after_delay') {\n return `${subject} waiting — the assistant is giving you a moment to finish before it answers.`;\n }\n if (willProcess === 'on_resume') {\n return `${subject} waiting — the assistant picks ${\n queuedCount === 1 ? 'it' : 'them'\n } up when it comes back to this conversation.`;\n }\n return `${subject} waiting — the assistant picks ${\n queuedCount === 1 ? 'it' : 'them'\n } up on its next turn.`;\n}\n\nfunction WarningIcon(): 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=\"M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\" />\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\nfunction ClockIcon(): 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 <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <polyline points=\"12 7 12 12 15 14\" />\n </svg>\n );\n}\n"],"names":["_jsxs","_jsx"],"mappings":";;AAgBA;;;;;;;;AAQG;AACG,SAAU,WAAW,CAAC,EAC1B,WAAW,EACX,WAAW,EACX,KAAK,GACY,EAAA;AACjB,IAAA,QACEA,IAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAC,oBAAoB,EAAA,YAAA,EAClB,KAAK,GAAG,MAAM,GAAG,SAAS,EACtC,IAAI,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,EAAA,QAAA,EAAA,CAEhCC,cAAM,SAAS,EAAC,yBAAyB,EAAA,aAAA,EAAa,MAAM,EAAA,QAAA,EACzD,KAAK,GAAGA,GAAA,CAAC,WAAW,EAAA,EAAA,CAAG,GAAGA,GAAA,CAAC,SAAS,EAAA,EAAA,CAAG,EAAA,CACnC,EACPA,GAAA,CAAA,MAAA,EAAA,EAAA,QAAA,EAAO,KAAK,IAAI,UAAU,CAAC,WAAW,EAAE,WAAW,CAAC,EAAA,CAAQ,CAAA,EAAA,CACxD;AAEV;AAEA;;;;;;;AAOG;AACH,SAAS,UAAU,CACjB,WAAmB,EACnB,WAA8B,EAAA;AAE9B,IAAA,IAAI,WAAW,IAAI,CAAC,EAAE;AACpB,QAAA,OAAO,qFAAqF;IAC9F;AAEA,IAAA,MAAM,OAAO,GAAG,WAAW,KAAK,CAAC,GAAG,WAAW,GAAG,CAAA,EAAG,WAAW,WAAW;AAE3E,IAAA,IAAI,WAAW,KAAK,aAAa,EAAE;QACjC,OAAO,CAAA,EAAG,OAAO,CAAA,4EAAA,CAA8E;IACjG;AACA,IAAA,IAAI,WAAW,KAAK,WAAW,EAAE;AAC/B,QAAA,OAAO,CAAA,EAAG,OAAO,CAAA,+BAAA,EACf,WAAW,KAAK,CAAC,GAAG,IAAI,GAAG,MAC7B,8CAA8C;IAChD;AACA,IAAA,OAAO,CAAA,EAAG,OAAO,CAAA,+BAAA,EACf,WAAW,KAAK,CAAC,GAAG,IAAI,GAAG,MAC7B,uBAAuB;AACzB;AAEA,SAAS,WAAW,GAAA;AAClB,IAAA,QACED,IAAA,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,GAAA,CAAA,MAAA,EAAA,EAAM,CAAC,EAAC,0FAA0F,EAAA,CAAG,EACrGA,cAAM,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAA,CAAG,EACvCA,GAAA,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;AAEA,SAAS,SAAS,GAAA;IAChB,QACED,IAAA,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,GAAA,CAAA,QAAA,EAAA,EAAQ,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,CAAC,EAAC,GAAG,EAAA,CAAG,EAChCA,GAAA,CAAA,UAAA,EAAA,EAAU,MAAM,EAAC,kBAAkB,EAAA,CAAG,CAAA,EAAA,CAClC;AAEV;;"}
|
|
@@ -10,6 +10,8 @@ export { UsageBar } from './UsageBar';
|
|
|
10
10
|
export type { UsageBarProps, UsageBarDisplay, UsageBarData } from './UsageBar';
|
|
11
11
|
export { LimitBanner } from './LimitBanner';
|
|
12
12
|
export type { LimitBannerProps } from './LimitBanner';
|
|
13
|
+
export { QueueNotice } from './QueueNotice';
|
|
14
|
+
export type { QueueNoticeProps } from './QueueNotice';
|
|
13
15
|
export { RecalledMemoriesWidget } from './RecalledMemoriesWidget';
|
|
14
16
|
export type { RecalledMemoriesWidgetProps, RecalledMemoriesRenderer, RecalledMemoriesRendererProps, } from './RecalledMemoriesWidget';
|
|
15
17
|
export type { ChatDrawerProps, ChatDrawerOptions, ChatDrawerHandle, ChatMessagesProps, ChatInputProps, CustomPromptBoxProps, MessageBubbleRenderer, MessageBubbleRendererProps, ToolTimelineProps, AllowedFileTypes, ConversationSelectorProps, SuggestedMessage, } from './ChatDrawer.types';
|
|
@@ -16,3 +16,4 @@ export { McpConnectForm } from "./McpConnectForm";
|
|
|
16
16
|
export type { McpConnectFormProps } from "./McpConnectForm";
|
|
17
17
|
export { useTenantMcp } from "./useTenantMcp";
|
|
18
18
|
export type { TenantMcpState, UseTenantMcpOptions } from "./useTenantMcp";
|
|
19
|
+
export { integrationChoiceKey, readIntegrationChoice, writeIntegrationChoice, pruneIntegrationChoice, } from "./integrationChoice";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare function integrationChoiceKey(assistantId: string, tenantId?: string, subtenantId?: string): string;
|
|
2
|
+
/** Reads the remembered list, tolerating anything that is not one. */
|
|
3
|
+
export declare function readIntegrationChoice(key: string): string[];
|
|
4
|
+
export declare function writeIntegrationChoice(key: string, disabled: string[]): void;
|
|
5
|
+
/**
|
|
6
|
+
* Drops what is no longer on offer.
|
|
7
|
+
*
|
|
8
|
+
* Without this, remembering the choice would quietly reintroduce the bug the
|
|
9
|
+
* switch was written to avoid: disconnect an app, connect it again months
|
|
10
|
+
* later, and find it switched off for reasons nobody can reconstruct. The same
|
|
11
|
+
* goes for an MCP server the tenant removed.
|
|
12
|
+
*
|
|
13
|
+
* Returns the SAME array when nothing was stale, so a caller can use identity
|
|
14
|
+
* to avoid a pointless render.
|
|
15
|
+
*/
|
|
16
|
+
export declare function pruneIntegrationChoice(disabled: string[], liveIds: string[]): string[];
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { storage } from '../../utils/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What the end user switched off, remembered between visits.
|
|
5
|
+
*
|
|
6
|
+
* Held in the browser and nowhere else: it is a preference of whoever is at
|
|
7
|
+
* this keyboard, not of the tenant, and the server deliberately keeps nothing
|
|
8
|
+
* beyond the turn it was sent for.
|
|
9
|
+
*
|
|
10
|
+
* The key names the assistant AND the tenant it was made under, because a
|
|
11
|
+
* choice about one end user's Gmail means nothing to the next one — and a
|
|
12
|
+
* widget that switched an app off for a colleague who happens to share a
|
|
13
|
+
* browser profile would be a bug with a very long tail.
|
|
14
|
+
*/
|
|
15
|
+
const PREFIX = "devic:integrations:off";
|
|
16
|
+
function integrationChoiceKey(assistantId, tenantId, subtenantId) {
|
|
17
|
+
return `${PREFIX}:${assistantId}:${tenantId ?? ""}:${subtenantId ?? ""}`;
|
|
18
|
+
}
|
|
19
|
+
/** Reads the remembered list, tolerating anything that is not one. */
|
|
20
|
+
function readIntegrationChoice(key) {
|
|
21
|
+
const stored = storage.get(key);
|
|
22
|
+
if (!Array.isArray(stored))
|
|
23
|
+
return [];
|
|
24
|
+
return stored.filter((id) => typeof id === "string" && !!id);
|
|
25
|
+
}
|
|
26
|
+
function writeIntegrationChoice(key, disabled) {
|
|
27
|
+
// An empty list is the default, and leaving a `[]` behind in every visitor's
|
|
28
|
+
// storage for every assistant they ever opened is litter.
|
|
29
|
+
if (disabled.length === 0)
|
|
30
|
+
storage.remove(key);
|
|
31
|
+
else
|
|
32
|
+
storage.set(key, disabled);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Drops what is no longer on offer.
|
|
36
|
+
*
|
|
37
|
+
* Without this, remembering the choice would quietly reintroduce the bug the
|
|
38
|
+
* switch was written to avoid: disconnect an app, connect it again months
|
|
39
|
+
* later, and find it switched off for reasons nobody can reconstruct. The same
|
|
40
|
+
* goes for an MCP server the tenant removed.
|
|
41
|
+
*
|
|
42
|
+
* Returns the SAME array when nothing was stale, so a caller can use identity
|
|
43
|
+
* to avoid a pointless render.
|
|
44
|
+
*/
|
|
45
|
+
function pruneIntegrationChoice(disabled, liveIds) {
|
|
46
|
+
if (disabled.length === 0)
|
|
47
|
+
return disabled;
|
|
48
|
+
const live = new Set(liveIds);
|
|
49
|
+
const next = disabled.filter((id) => live.has(id));
|
|
50
|
+
return next.length === disabled.length ? disabled : next;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { integrationChoiceKey, pruneIntegrationChoice, readIntegrationChoice, writeIntegrationChoice };
|
|
54
|
+
//# sourceMappingURL=integrationChoice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrationChoice.js","sources":["../../../../src/components/IntegrationsModal/integrationChoice.ts"],"sourcesContent":["import { storage } from \"../../utils\";\n\n/**\n * What the end user switched off, remembered between visits.\n *\n * Held in the browser and nowhere else: it is a preference of whoever is at\n * this keyboard, not of the tenant, and the server deliberately keeps nothing\n * beyond the turn it was sent for.\n *\n * The key names the assistant AND the tenant it was made under, because a\n * choice about one end user's Gmail means nothing to the next one — and a\n * widget that switched an app off for a colleague who happens to share a\n * browser profile would be a bug with a very long tail.\n */\nconst PREFIX = \"devic:integrations:off\";\n\nexport function integrationChoiceKey(\n assistantId: string,\n tenantId?: string,\n subtenantId?: string\n): string {\n return `${PREFIX}:${assistantId}:${tenantId ?? \"\"}:${subtenantId ?? \"\"}`;\n}\n\n/** Reads the remembered list, tolerating anything that is not one. */\nexport function readIntegrationChoice(key: string): string[] {\n const stored = storage.get<unknown>(key);\n if (!Array.isArray(stored)) return [];\n return stored.filter((id): id is string => typeof id === \"string\" && !!id);\n}\n\nexport function writeIntegrationChoice(key: string, disabled: string[]): void {\n // An empty list is the default, and leaving a `[]` behind in every visitor's\n // storage for every assistant they ever opened is litter.\n if (disabled.length === 0) storage.remove(key);\n else storage.set(key, disabled);\n}\n\n/**\n * Drops what is no longer on offer.\n *\n * Without this, remembering the choice would quietly reintroduce the bug the\n * switch was written to avoid: disconnect an app, connect it again months\n * later, and find it switched off for reasons nobody can reconstruct. The same\n * goes for an MCP server the tenant removed.\n *\n * Returns the SAME array when nothing was stale, so a caller can use identity\n * to avoid a pointless render.\n */\nexport function pruneIntegrationChoice(\n disabled: string[],\n liveIds: string[]\n): string[] {\n if (disabled.length === 0) return disabled;\n const live = new Set(liveIds);\n const next = disabled.filter((id) => live.has(id));\n return next.length === disabled.length ? disabled : next;\n}\n"],"names":[],"mappings":";;AAEA;;;;;;;;;;;AAWG;AACH,MAAM,MAAM,GAAG,wBAAwB;SAEvB,oBAAoB,CAClC,WAAmB,EACnB,QAAiB,EACjB,WAAoB,EAAA;AAEpB,IAAA,OAAO,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA,EAAI,QAAQ,IAAI,EAAE,CAAA,CAAA,EAAI,WAAW,IAAI,EAAE,EAAE;AAC1E;AAEA;AACM,SAAU,qBAAqB,CAAC,GAAW,EAAA;IAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAU,GAAG,CAAC;AACxC,IAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;AAAE,QAAA,OAAO,EAAE;AACrC,IAAA,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAmB,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC;AAC5E;AAEM,SAAU,sBAAsB,CAAC,GAAW,EAAE,QAAkB,EAAA;;;AAGpE,IAAA,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC;;AACzC,QAAA,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC;AACjC;AAEA;;;;;;;;;;AAUG;AACG,SAAU,sBAAsB,CACpC,QAAkB,EAClB,OAAiB,EAAA;AAEjB,IAAA,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,QAAQ;AAC1C,IAAA,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC;AAC7B,IAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClD,IAAA,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,GAAG,QAAQ,GAAG,IAAI;AAC1D;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { useDevicChat } from './useDevicChat';
|
|
2
|
-
export type { UseDevicChatOptions, UseDevicChatResult } from './useDevicChat';
|
|
2
|
+
export type { UseDevicChatOptions, UseDevicChatResult, SendMessageResult, StopResult, } from './useDevicChat';
|
|
3
3
|
export { usePolling, resolvePollingInterval, DEFAULT_POLLING_INTERVAL_MS, MIN_POLLING_INTERVAL_MS, } from './usePolling';
|
|
4
4
|
export type { UsePollingOptions, UsePollingResult } from './usePolling';
|
|
5
5
|
export { useModelInterface } from './useModelInterface';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TenantMetadata, SubtenantMetadata } from '../provider';
|
|
2
2
|
import { type PendingWidgetCall } from './useModelInterface';
|
|
3
|
-
import type { ChatMessage, ChatFile, ModelInterfaceTool, RealtimeStatus, RecalledMemoryRecord, TenantLimitExceeded } from '../api/types';
|
|
3
|
+
import type { ChatMessage, ChatFile, ModelInterfaceTool, QueueDisposition, RealtimeStatus, RecalledMemoryRecord, TenantLimitExceeded } from '../api/types';
|
|
4
4
|
export interface UseDevicChatOptions {
|
|
5
5
|
/**
|
|
6
6
|
* Assistant identifier
|
|
@@ -91,6 +91,19 @@ export interface UseDevicChatOptions {
|
|
|
91
91
|
* an array of ChatFile with downloadUrl set.
|
|
92
92
|
*/
|
|
93
93
|
onFileUpload?: (files: File[]) => Promise<ChatFile[]>;
|
|
94
|
+
/**
|
|
95
|
+
* Whether this assistant takes messages while the conversation is busy.
|
|
96
|
+
*
|
|
97
|
+
* Left unset it is resolved from the assistant itself (`messageQueueEnabled`),
|
|
98
|
+
* through the shared per-assistant lookup — one request, shared with the
|
|
99
|
+
* avatar and the connected-apps control, whichever asks first. Pass a boolean
|
|
100
|
+
* to skip the lookup entirely or to override what it says.
|
|
101
|
+
*
|
|
102
|
+
* With it off the input closes while the assistant answers, as it always has.
|
|
103
|
+
* With it on, a message written mid-answer is accepted and joins the
|
|
104
|
+
* assistant's next turn.
|
|
105
|
+
*/
|
|
106
|
+
messageQueue?: boolean;
|
|
94
107
|
/**
|
|
95
108
|
* Enable debug logging to the browser console.
|
|
96
109
|
* Overrides the provider-level debug setting when provided.
|
|
@@ -98,6 +111,37 @@ export interface UseDevicChatOptions {
|
|
|
98
111
|
*/
|
|
99
112
|
debug?: boolean;
|
|
100
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* What became of a send.
|
|
116
|
+
*
|
|
117
|
+
* `queued` is an acceptance, not a failure: the message is on the conversation
|
|
118
|
+
* and will be answered later. `rejected` is the opposite — nothing was
|
|
119
|
+
* accepted, and the caller still holds the only copy of what the user wrote.
|
|
120
|
+
*/
|
|
121
|
+
export type SendMessageResult = {
|
|
122
|
+
queued: true;
|
|
123
|
+
queuePosition: number;
|
|
124
|
+
willProcess: QueueDisposition;
|
|
125
|
+
} | {
|
|
126
|
+
queued: false;
|
|
127
|
+
} | {
|
|
128
|
+
rejected: true;
|
|
129
|
+
/**
|
|
130
|
+
* `chat_busy`: this assistant does not queue and is working.
|
|
131
|
+
* `queue_full`: it does, and the queue is at its configured ceiling.
|
|
132
|
+
* `error`: anything else, already reported through `error`/`onError`.
|
|
133
|
+
*/
|
|
134
|
+
reason: 'chat_busy' | 'queue_full' | 'error';
|
|
135
|
+
message: string;
|
|
136
|
+
/** What the user wrote, so it can be restored. */
|
|
137
|
+
restoredText: string;
|
|
138
|
+
};
|
|
139
|
+
export interface StopResult {
|
|
140
|
+
/** Text of the queued messages the stop threw away, joined by newlines. */
|
|
141
|
+
restoredText?: string;
|
|
142
|
+
/** How many were discarded. */
|
|
143
|
+
discarded: number;
|
|
144
|
+
}
|
|
101
145
|
export interface UseDevicChatResult {
|
|
102
146
|
/**
|
|
103
147
|
* Current chat messages
|
|
@@ -157,7 +201,7 @@ export interface UseDevicChatResult {
|
|
|
157
201
|
* can send one message with everything on by passing `[]`.
|
|
158
202
|
*/
|
|
159
203
|
disabledIntegrations?: string[];
|
|
160
|
-
}) => Promise<
|
|
204
|
+
}) => Promise<SendMessageResult>;
|
|
161
205
|
/**
|
|
162
206
|
* Clear the chat and start a new conversation
|
|
163
207
|
*/
|
|
@@ -172,10 +216,26 @@ export interface UseDevicChatResult {
|
|
|
172
216
|
*/
|
|
173
217
|
onHandoffCompleted: () => void;
|
|
174
218
|
/**
|
|
175
|
-
*
|
|
176
|
-
*
|
|
219
|
+
* How many messages this conversation has accepted but not yet shown to the
|
|
220
|
+
* model. Includes anything queued through another channel, so it is the
|
|
221
|
+
* conversation's queue and not this client's.
|
|
222
|
+
*/
|
|
223
|
+
queuedCount: number;
|
|
224
|
+
/**
|
|
225
|
+
* Whether this assistant takes messages while it is busy — resolved from the
|
|
226
|
+
* assistant, or from the `messageQueue` option when given. False until the
|
|
227
|
+
* lookup settles: an input that opens and then closes is worse than one that
|
|
228
|
+
* opens a beat late.
|
|
229
|
+
*/
|
|
230
|
+
queueEnabled: boolean;
|
|
231
|
+
/**
|
|
232
|
+
* Stop the current conversation processing.
|
|
233
|
+
*
|
|
234
|
+
* Returns the text of anything the stop discarded, so the caller can put it
|
|
235
|
+
* back where the user wrote it — a stop should not be the way someone's
|
|
236
|
+
* typing disappears.
|
|
177
237
|
*/
|
|
178
|
-
stopChat: () =>
|
|
238
|
+
stopChat: () => Promise<StopResult>;
|
|
179
239
|
/**
|
|
180
240
|
* Pending tool calls that require user interaction via a response widget
|
|
181
241
|
*/
|