@devicai/ui 0.57.0 → 0.58.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 (171) hide show
  1. package/README.md +162 -0
  2. package/dist/cjs/api/types.js.map +1 -1
  3. package/dist/cjs/components/AICommandBar/AICommandBar.js +10 -7
  4. package/dist/cjs/components/AICommandBar/AICommandBar.js.map +1 -1
  5. package/dist/cjs/components/AICommandBar/useAICommandBar.js +7 -5
  6. package/dist/cjs/components/AICommandBar/useAICommandBar.js.map +1 -1
  7. package/dist/cjs/components/AIElementWrapper/AIElementWrapper.js +17 -14
  8. package/dist/cjs/components/AIElementWrapper/AIElementWrapper.js.map +1 -1
  9. package/dist/cjs/components/AIElementWrapper/useAIElementWrapper.js +7 -5
  10. package/dist/cjs/components/AIElementWrapper/useAIElementWrapper.js.map +1 -1
  11. package/dist/cjs/components/AIGenerationButton/AIGenerationButton.js +11 -6
  12. package/dist/cjs/components/AIGenerationButton/AIGenerationButton.js.map +1 -1
  13. package/dist/cjs/components/AIGenerationButton/useAIGenerationButton.js +6 -4
  14. package/dist/cjs/components/AIGenerationButton/useAIGenerationButton.js.map +1 -1
  15. package/dist/cjs/components/ChatDrawer/ChatDrawer.js +26 -12
  16. package/dist/cjs/components/ChatDrawer/ChatDrawer.js.map +1 -1
  17. package/dist/cjs/components/ChatDrawer/ChatInput.js +21 -15
  18. package/dist/cjs/components/ChatDrawer/ChatInput.js.map +1 -1
  19. package/dist/cjs/components/ChatDrawer/ChatMessages.js +54 -13
  20. package/dist/cjs/components/ChatDrawer/ChatMessages.js.map +1 -1
  21. package/dist/cjs/components/ChatDrawer/CompactionWidget.js +13 -4
  22. package/dist/cjs/components/ChatDrawer/CompactionWidget.js.map +1 -1
  23. package/dist/cjs/components/ChatDrawer/ConversationSelector.js +6 -4
  24. package/dist/cjs/components/ChatDrawer/ConversationSelector.js.map +1 -1
  25. package/dist/cjs/components/ChatDrawer/GuardrailNotice.js +40 -0
  26. package/dist/cjs/components/ChatDrawer/GuardrailNotice.js.map +1 -0
  27. package/dist/cjs/components/ChatDrawer/HandoffSubagentWidget.js +3 -1
  28. package/dist/cjs/components/ChatDrawer/HandoffSubagentWidget.js.map +1 -1
  29. package/dist/cjs/components/ChatDrawer/LimitBanner.js +19 -9
  30. package/dist/cjs/components/ChatDrawer/LimitBanner.js.map +1 -1
  31. package/dist/cjs/components/ChatDrawer/QueueNotice.js +19 -7
  32. package/dist/cjs/components/ChatDrawer/QueueNotice.js.map +1 -1
  33. package/dist/cjs/components/ChatDrawer/RecalledMemoriesWidget.js +17 -5
  34. package/dist/cjs/components/ChatDrawer/RecalledMemoriesWidget.js.map +1 -1
  35. package/dist/cjs/components/ChatDrawer/ReferenceChip.js +3 -1
  36. package/dist/cjs/components/ChatDrawer/ReferenceChip.js.map +1 -1
  37. package/dist/cjs/components/ChatDrawer/UsageBar.js +23 -18
  38. package/dist/cjs/components/ChatDrawer/UsageBar.js.map +1 -1
  39. package/dist/cjs/components/CoreMemoryModal/CoreMemoryModal.js +20 -9
  40. package/dist/cjs/components/CoreMemoryModal/CoreMemoryModal.js.map +1 -1
  41. package/dist/cjs/components/Feedback/FeedbackModal.js +5 -1
  42. package/dist/cjs/components/Feedback/FeedbackModal.js.map +1 -1
  43. package/dist/cjs/components/Feedback/MessageActions.js +3 -1
  44. package/dist/cjs/components/Feedback/MessageActions.js.map +1 -1
  45. package/dist/cjs/components/IntegrationsModal/ConnectFieldsForm.js +12 -8
  46. package/dist/cjs/components/IntegrationsModal/ConnectFieldsForm.js.map +1 -1
  47. package/dist/cjs/components/IntegrationsModal/IntegrationsHint.js +5 -3
  48. package/dist/cjs/components/IntegrationsModal/IntegrationsHint.js.map +1 -1
  49. package/dist/cjs/components/IntegrationsModal/IntegrationsLauncher.js +12 -3
  50. package/dist/cjs/components/IntegrationsModal/IntegrationsLauncher.js.map +1 -1
  51. package/dist/cjs/components/IntegrationsModal/IntegrationsPanel.js +34 -24
  52. package/dist/cjs/components/IntegrationsModal/IntegrationsPanel.js.map +1 -1
  53. package/dist/cjs/components/IntegrationsModal/IntegrationsToggle.js +15 -6
  54. package/dist/cjs/components/IntegrationsModal/IntegrationsToggle.js.map +1 -1
  55. package/dist/cjs/components/IntegrationsModal/McpConnectForm.js +15 -7
  56. package/dist/cjs/components/IntegrationsModal/McpConnectForm.js.map +1 -1
  57. package/dist/cjs/components/IntegrationsModal/McpServersSection.js +32 -19
  58. package/dist/cjs/components/IntegrationsModal/McpServersSection.js.map +1 -1
  59. package/dist/cjs/components/IntegrationsModal/useIntegrations.js +3 -1
  60. package/dist/cjs/components/IntegrationsModal/useIntegrations.js.map +1 -1
  61. package/dist/cjs/components/IntegrationsModal/useTenantMcp.js +3 -1
  62. package/dist/cjs/components/IntegrationsModal/useTenantMcp.js.map +1 -1
  63. package/dist/cjs/components/ThreadStateTag/ThreadStateTag.js +63 -40
  64. package/dist/cjs/components/ThreadStateTag/ThreadStateTag.js.map +1 -1
  65. package/dist/cjs/hooks/useDevicChat.js +11 -5
  66. package/dist/cjs/hooks/useDevicChat.js.map +1 -1
  67. package/dist/cjs/hooks/useSpeechRecording.js +8 -4
  68. package/dist/cjs/hooks/useSpeechRecording.js.map +1 -1
  69. package/dist/cjs/i18n/translate.js +48 -0
  70. package/dist/cjs/i18n/translate.js.map +1 -0
  71. package/dist/cjs/i18n/useTranslations.js +57 -0
  72. package/dist/cjs/i18n/useTranslations.js.map +1 -0
  73. package/dist/cjs/index.js +11 -0
  74. package/dist/cjs/index.js.map +1 -1
  75. package/dist/cjs/provider/DevicProvider.js +3 -1
  76. package/dist/cjs/provider/DevicProvider.js.map +1 -1
  77. package/dist/cjs/styles.css +1 -1
  78. package/dist/esm/api/types.d.ts +10 -1
  79. package/dist/esm/api/types.js.map +1 -1
  80. package/dist/esm/components/AICommandBar/AICommandBar.js +11 -8
  81. package/dist/esm/components/AICommandBar/AICommandBar.js.map +1 -1
  82. package/dist/esm/components/AICommandBar/AICommandBar.types.d.ts +10 -0
  83. package/dist/esm/components/AICommandBar/useAICommandBar.js +7 -5
  84. package/dist/esm/components/AICommandBar/useAICommandBar.js.map +1 -1
  85. package/dist/esm/components/AIElementWrapper/AIElementWrapper.js +17 -14
  86. package/dist/esm/components/AIElementWrapper/AIElementWrapper.js.map +1 -1
  87. package/dist/esm/components/AIElementWrapper/AIElementWrapper.types.d.ts +10 -0
  88. package/dist/esm/components/AIElementWrapper/useAIElementWrapper.js +7 -5
  89. package/dist/esm/components/AIElementWrapper/useAIElementWrapper.js.map +1 -1
  90. package/dist/esm/components/AIGenerationButton/AIGenerationButton.js +12 -7
  91. package/dist/esm/components/AIGenerationButton/AIGenerationButton.js.map +1 -1
  92. package/dist/esm/components/AIGenerationButton/AIGenerationButton.types.d.ts +10 -0
  93. package/dist/esm/components/AIGenerationButton/useAIGenerationButton.js +6 -4
  94. package/dist/esm/components/AIGenerationButton/useAIGenerationButton.js.map +1 -1
  95. package/dist/esm/components/ChatDrawer/ChatDrawer.js +27 -13
  96. package/dist/esm/components/ChatDrawer/ChatDrawer.js.map +1 -1
  97. package/dist/esm/components/ChatDrawer/ChatDrawer.types.d.ts +33 -0
  98. package/dist/esm/components/ChatDrawer/ChatInput.js +21 -15
  99. package/dist/esm/components/ChatDrawer/ChatInput.js.map +1 -1
  100. package/dist/esm/components/ChatDrawer/ChatMessages.d.ts +1 -1
  101. package/dist/esm/components/ChatDrawer/ChatMessages.js +54 -13
  102. package/dist/esm/components/ChatDrawer/ChatMessages.js.map +1 -1
  103. package/dist/esm/components/ChatDrawer/CompactionWidget.js +13 -4
  104. package/dist/esm/components/ChatDrawer/CompactionWidget.js.map +1 -1
  105. package/dist/esm/components/ChatDrawer/ConversationSelector.js +6 -4
  106. package/dist/esm/components/ChatDrawer/ConversationSelector.js.map +1 -1
  107. package/dist/esm/components/ChatDrawer/GuardrailNotice.d.ts +36 -0
  108. package/dist/esm/components/ChatDrawer/GuardrailNotice.js +38 -0
  109. package/dist/esm/components/ChatDrawer/GuardrailNotice.js.map +1 -0
  110. package/dist/esm/components/ChatDrawer/HandoffSubagentWidget.js +3 -1
  111. package/dist/esm/components/ChatDrawer/HandoffSubagentWidget.js.map +1 -1
  112. package/dist/esm/components/ChatDrawer/LimitBanner.js +19 -9
  113. package/dist/esm/components/ChatDrawer/LimitBanner.js.map +1 -1
  114. package/dist/esm/components/ChatDrawer/QueueNotice.js +19 -7
  115. package/dist/esm/components/ChatDrawer/QueueNotice.js.map +1 -1
  116. package/dist/esm/components/ChatDrawer/RecalledMemoriesWidget.js +17 -5
  117. package/dist/esm/components/ChatDrawer/RecalledMemoriesWidget.js.map +1 -1
  118. package/dist/esm/components/ChatDrawer/ReferenceChip.js +3 -1
  119. package/dist/esm/components/ChatDrawer/ReferenceChip.js.map +1 -1
  120. package/dist/esm/components/ChatDrawer/UsageBar.js +23 -18
  121. package/dist/esm/components/ChatDrawer/UsageBar.js.map +1 -1
  122. package/dist/esm/components/ChatDrawer/index.d.ts +2 -0
  123. package/dist/esm/components/CoreMemoryModal/CoreMemoryModal.js +20 -9
  124. package/dist/esm/components/CoreMemoryModal/CoreMemoryModal.js.map +1 -1
  125. package/dist/esm/components/Feedback/FeedbackModal.js +5 -1
  126. package/dist/esm/components/Feedback/FeedbackModal.js.map +1 -1
  127. package/dist/esm/components/Feedback/MessageActions.js +3 -1
  128. package/dist/esm/components/Feedback/MessageActions.js.map +1 -1
  129. package/dist/esm/components/IntegrationsModal/ConnectFieldsForm.js +12 -8
  130. package/dist/esm/components/IntegrationsModal/ConnectFieldsForm.js.map +1 -1
  131. package/dist/esm/components/IntegrationsModal/IntegrationsHint.js +5 -3
  132. package/dist/esm/components/IntegrationsModal/IntegrationsHint.js.map +1 -1
  133. package/dist/esm/components/IntegrationsModal/IntegrationsLauncher.js +12 -3
  134. package/dist/esm/components/IntegrationsModal/IntegrationsLauncher.js.map +1 -1
  135. package/dist/esm/components/IntegrationsModal/IntegrationsPanel.d.ts +1 -1
  136. package/dist/esm/components/IntegrationsModal/IntegrationsPanel.js +34 -24
  137. package/dist/esm/components/IntegrationsModal/IntegrationsPanel.js.map +1 -1
  138. package/dist/esm/components/IntegrationsModal/IntegrationsToggle.d.ts +1 -1
  139. package/dist/esm/components/IntegrationsModal/IntegrationsToggle.js +15 -6
  140. package/dist/esm/components/IntegrationsModal/IntegrationsToggle.js.map +1 -1
  141. package/dist/esm/components/IntegrationsModal/McpConnectForm.js +15 -7
  142. package/dist/esm/components/IntegrationsModal/McpConnectForm.js.map +1 -1
  143. package/dist/esm/components/IntegrationsModal/McpServersSection.js +32 -19
  144. package/dist/esm/components/IntegrationsModal/McpServersSection.js.map +1 -1
  145. package/dist/esm/components/IntegrationsModal/useIntegrations.js +3 -1
  146. package/dist/esm/components/IntegrationsModal/useIntegrations.js.map +1 -1
  147. package/dist/esm/components/IntegrationsModal/useTenantMcp.js +3 -1
  148. package/dist/esm/components/IntegrationsModal/useTenantMcp.js.map +1 -1
  149. package/dist/esm/components/ThreadStateTag/ThreadStateTag.js +63 -40
  150. package/dist/esm/components/ThreadStateTag/ThreadStateTag.js.map +1 -1
  151. package/dist/esm/hooks/useDevicChat.js +12 -6
  152. package/dist/esm/hooks/useDevicChat.js.map +1 -1
  153. package/dist/esm/hooks/useSpeechRecording.js +8 -4
  154. package/dist/esm/hooks/useSpeechRecording.js.map +1 -1
  155. package/dist/esm/i18n/index.d.ts +4 -0
  156. package/dist/esm/i18n/translate.d.ts +23 -0
  157. package/dist/esm/i18n/translate.js +43 -0
  158. package/dist/esm/i18n/translate.js.map +1 -0
  159. package/dist/esm/i18n/types.d.ts +27 -0
  160. package/dist/esm/i18n/useTranslations.d.ts +32 -0
  161. package/dist/esm/i18n/useTranslations.js +53 -0
  162. package/dist/esm/i18n/useTranslations.js.map +1 -0
  163. package/dist/esm/index.d.ts +4 -2
  164. package/dist/esm/index.js +3 -0
  165. package/dist/esm/index.js.map +1 -1
  166. package/dist/esm/provider/DevicProvider.d.ts +1 -1
  167. package/dist/esm/provider/DevicProvider.js +3 -1
  168. package/dist/esm/provider/DevicProvider.js.map +1 -1
  169. package/dist/esm/provider/types.d.ts +33 -0
  170. package/dist/esm/styles.css +1 -1
  171. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ChatInput.js","sources":["../../../../src/components/ChatDrawer/ChatInput.tsx"],"sourcesContent":["import React, { useState, useRef, useCallback, useMemo, useEffect } from 'react';\nimport { useOptionalDevicContext } from '../../provider';\nimport type { ChatInputProps } from './ChatDrawer.types';\nimport { useSpeechRecording } from '../../hooks/useSpeechRecording';\nimport { DevicApiClient } from '../../api/client';\nimport { ReferenceChip } from './ReferenceChip';\nimport {\n toPastedBlock,\n pastedPreview,\n pastedLineCount,\n type PastedText,\n} from './pastedText';\n\nconst FILE_TYPE_ACCEPT: Record<string, string[]> = {\n images: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],\n documents: [\n 'application/pdf',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'text/plain',\n 'text/csv',\n 'application/json',\n ],\n audio: ['audio/mpeg', 'audio/wav', 'audio/ogg'],\n video: ['video/mp4', 'video/webm', 'video/ogg'],\n};\n\n// Extensions accepted per category, on top of the MIME types above. The browser\n// derives `File.type` from the OS, which reports .json inconsistently: empty on\n// Windows without the registry entry, 'text/plain' on some Linux setups. Without\n// this fallback a .json picked from the dialog or dropped in would be silently\n// rejected on those machines.\nconst FILE_TYPE_ACCEPT_EXT: Record<string, string[]> = {\n documents: ['.json'],\n};\n\n// Extensions used to name images pasted from the clipboard, which arrive with a\n// generic name (\"image.png\") or none at all.\nconst IMAGE_EXT_BY_MIME: Record<string, string> = {\n 'image/jpeg': 'jpg',\n 'image/png': 'png',\n 'image/gif': 'gif',\n 'image/webp': 'webp',\n};\n\n// Handoff (hands-free) loop timings.\nconst HANDOFF_PENDING_MS = 1000; // default cancellable countdown before auto-send\nconst HANDOFF_INACTIVITY_MS = 6000; // silence (no speech) that ends the loop\nconst HANDOFF_HOLD_MS = 3000; // press-and-hold duration on the mic to arm hands-free\n\n/**\n * Chat input component with file upload support.\n *\n * When a widget is pending as 'input' it replaces the whole input area. The swap\n * lives here, in a component with no hooks of its own, so that each subtree is\n * mounted and unmounted whole. Returning the widget from inside ChatInputBox\n * instead would skip every hook below the early return, which violates the rules\n * of hooks (and is what react-hooks/rules-of-hooks flags). React tolerates that\n * particular shape today — its \"fewer hooks than expected\" check only fires once\n * at least one hook has run — so it is a latent fragility rather than a crash,\n * but the toggle is on the hot path for interactive widgets and does not need to\n * depend on that internal detail. Draft text in the textarea is dropped on the\n * swap, same as before.\n */\nexport function ChatInput(props: ChatInputProps): JSX.Element {\n const { pendingInputWidget, onSubmitWidget, onCancelWidget } = props;\n\n if (pendingInputWidget) {\n const WidgetComponent = pendingInputWidget.widget.component;\n return (\n <div className=\"devic-input-area\" data-widget-mode=\"input\">\n <div className=\"devic-input-widget\" data-tool-name={pendingInputWidget.toolName}>\n <WidgetComponent\n toolCall={pendingInputWidget.toolCall}\n params={pendingInputWidget.params}\n submit={(response) => onSubmitWidget?.(pendingInputWidget.toolCall.id, response)}\n cancel={(reason) => onCancelWidget?.(pendingInputWidget.toolCall.id, reason)}\n />\n </div>\n </div>\n );\n }\n\n return <ChatInputBox {...props} />;\n}\n\nfunction ChatInputBox({\n onSend,\n disabled = false,\n placeholder = 'Type a message...',\n enableFileUploads = false,\n allowedFileTypes = { images: true, documents: true },\n maxFileSize = 10 * 1024 * 1024, // 10MB\n enableLongTextPaste = false,\n longTextPasteThreshold = 2000,\n enableSpeechToText = false,\n speechLanguage,\n speechTenantId,\n speechAutoStop = true,\n speechAutoStopCountdownMs,\n speechAutoStopSilenceMs,\n speechAutoStopSilenceRatio,\n speechAutoStopSilenceLevel,\n speechAutoStopSpeechLevel,\n speechHandoff = false,\n speechHandoffSendDelayMs,\n speechHandoffHoldMs,\n apiKey,\n baseUrl,\n sendButtonContent,\n disabledMessage,\n isProcessing = false,\n onStop,\n allowQueueing = false,\n queueNotice,\n stopButtonContent,\n references,\n onRemoveReference,\n usageBar,\n limitBanner,\n integrationsHint,\n integrationsToggle,\n}: ChatInputProps): JSX.Element {\n const [message, setMessage] = useState('');\n const [files, setFiles] = useState<File[]>([]);\n // Long blocks of pasted text, kept out of the textarea and shown as cards.\n const [pastedTexts, setPastedTexts] = useState<PastedText[]>([]);\n const [isDraggingOver, setIsDraggingOver] = useState(false);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n // Monotonic counters so pasted images and text blocks get stable, unique ids.\n const pasteCounterRef = useRef(0);\n // Nested dragenter/dragleave events fire per child node; count them so the\n // overlay only clears when the pointer truly leaves the input area.\n const dragDepthRef = useRef(0);\n\n // Speech-to-text state\n const [transcriptId, setTranscriptId] = useState<string | undefined>();\n const [isTranscribing, setIsTranscribing] = useState(false);\n const [speechError, setSpeechError] = useState<string | null>(null);\n // Holds the latest confirmRecording so the auto-stop callback (created before\n // confirmRecording is defined) always calls the current closure.\n const confirmRef = useRef<() => void>(() => {});\n const recording = useSpeechRecording({\n bars: 5,\n autoStop: speechAutoStop,\n ...(speechAutoStopCountdownMs != null && {\n autoStopCountdownMs: speechAutoStopCountdownMs,\n }),\n ...(speechAutoStopSilenceMs != null && {\n autoStopSilenceMs: speechAutoStopSilenceMs,\n }),\n ...(speechAutoStopSilenceRatio != null && {\n autoStopSilenceRatio: speechAutoStopSilenceRatio,\n }),\n ...(speechAutoStopSilenceLevel != null && {\n autoStopSilenceLevel: speechAutoStopSilenceLevel,\n }),\n ...(speechAutoStopSpeechLevel != null && {\n autoStopSpeechLevel: speechAutoStopSpeechLevel,\n }),\n onAutoStop: () => confirmRef.current(),\n });\n\n // --- Handoff (hands-free loop) state ---\n const [handoffActive, setHandoffActive] = useState(false);\n const [pendingSend, setPendingSend] = useState(false);\n const [pendingProgress, setPendingProgress] = useState(1);\n // Ref mirror so async callbacks (rAF, timers, document listeners) read the\n // live value without going stale.\n const handoffActiveRef = useRef(false);\n const pendingRafRef = useRef<number | null>(null);\n const inactivityTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const prevProcessingRef = useRef(isProcessing);\n // Always-fresh send fn so the deferred auto-send uses the latest message.\n const handleSendRef = useRef<() => void>(() => {});\n\n // --- Press-and-hold to arm hands-free ---\n // Holding the mic for `holdMs` fills a ring (0→1) and activates hands-free;\n // releasing earlier falls back to a single one-shot recording.\n const [holdProgress, setHoldProgress] = useState(0);\n const [isHolding, setIsHolding] = useState(false);\n const holdRafRef = useRef<number | null>(null);\n const holdFiredRef = useRef(false);\n\n // Client used only for the /whisper transcription call.\n const devicContext = useOptionalDevicContext();\n const getTenantSession = devicContext?.getTenantSession;\n const onSessionExpired = devicContext?.onSessionExpired;\n const transcribeClient = useMemo(() => {\n if (!enableSpeechToText || (!apiKey && !getTenantSession)) return null;\n return new DevicApiClient({\n apiKey,\n baseUrl: baseUrl || 'https://api.devic.ai',\n getTenantSession,\n onSessionExpired,\n });\n }, [enableSpeechToText, apiKey, getTenantSession, baseUrl]);\n\n const speechEnabled =\n enableSpeechToText && recording.isSupported && !!transcribeClient;\n const isRecordingActive = recording.isRecording || recording.isPaused;\n\n // Calculate accepted file types\n const acceptedTypeList = useMemo(\n () =>\n Object.entries(allowedFileTypes)\n .filter(([, enabled]) => enabled)\n .flatMap(([type]) => FILE_TYPE_ACCEPT[type] || []),\n [allowedFileTypes]\n );\n const acceptedExtList = useMemo(\n () =>\n Object.entries(allowedFileTypes)\n .filter(([, enabled]) => enabled)\n .flatMap(([type]) => FILE_TYPE_ACCEPT_EXT[type] || []),\n [allowedFileTypes]\n );\n // The native dialog takes both MIME types and extensions in `accept`.\n const acceptedTypes = [...acceptedTypeList, ...acceptedExtList].join(',');\n\n // Single entry point for every way of attaching a file (button, paste, drop):\n // enforces the size limit and the allowed MIME types, which until now were\n // only hinted at the native file dialog and never actually checked.\n const addFiles = useCallback(\n (incoming: File[]) => {\n const validFiles = incoming.filter((file) => {\n if (file.size > maxFileSize) {\n console.warn(`File ${file.name} exceeds maximum size`);\n return false;\n }\n const name = file.name.toLowerCase();\n const allowed =\n acceptedTypeList.length === 0 ||\n acceptedTypeList.includes(file.type) ||\n acceptedExtList.some((ext) => name.endsWith(ext));\n if (!allowed) {\n console.warn(`File type ${file.type || 'unknown'} is not allowed`);\n return false;\n }\n return true;\n });\n if (validFiles.length > 0) setFiles((prev) => [...prev, ...validFiles]);\n },\n [maxFileSize, acceptedTypeList, acceptedExtList]\n );\n\n // Thumbnails for attached images. The cleanup revokes the previous batch on\n // every change (and on unmount), so the object URLs never leak.\n const filePreviews = useMemo(\n () =>\n files.map((file) =>\n file.type.startsWith('image/') ? URL.createObjectURL(file) : null\n ),\n [files]\n );\n useEffect(\n () => () => {\n filePreviews.forEach((url) => url && URL.revokeObjectURL(url));\n },\n [filePreviews]\n );\n\n // Auto-resize textarea\n const handleInput = useCallback(() => {\n const textarea = textareaRef.current;\n if (textarea) {\n textarea.style.height = 'auto';\n textarea.style.height = `${Math.min(textarea.scrollHeight, 120)}px`;\n }\n }, []);\n\n /** Whether there is anything to send. */\n const hasContent =\n !!message.trim() || files.length > 0 || pastedTexts.length > 0;\n\n /**\n * Busy, and this assistant does not queue: writing is pointless because the\n * message would be refused. Kept apart from `disabled`, which the stop button\n * also answers to — it lives in this same box and has to stay clickable.\n */\n const busyWithoutQueue = isProcessing && !allowQueueing;\n const inputDisabled = disabled || busyWithoutQueue;\n\n // Handle send\n const handleSend = useCallback(async () => {\n const trimmedMessage = message.trim();\n if (!trimmedMessage && files.length === 0 && pastedTexts.length === 0) return;\n if (inputDisabled) return;\n\n // Pasted text is shown as a card but still reaches the model in full: each\n // block is prepended to the message inside a delimiter the thread can parse\n // back out (see parsePastedBlocks in ChatMessages).\n const composedMessage =\n pastedTexts.length > 0\n ? [...pastedTexts.map(toPastedBlock), trimmedMessage]\n .filter(Boolean)\n .join('\\n\\n')\n : trimmedMessage;\n\n // Cleared straight away so the box is ready for the next message, and put\n // back if the conversation turned this one down — the text is the user's,\n // and losing it is not an acceptable way to report a refusal.\n const sentMessage = message;\n const sentFiles = files;\n const sentPastedTexts = pastedTexts;\n const sentTranscriptId = transcriptId;\n\n setMessage('');\n setFiles([]);\n setPastedTexts([]);\n setTranscriptId(undefined);\n\n // Reset textarea height\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto';\n }\n\n const result = await onSend(\n composedMessage,\n sentFiles.length > 0 ? sentFiles : undefined,\n sentTranscriptId ? { transcriptId: sentTranscriptId } : undefined,\n );\n\n if (result && 'rejected' in result) {\n // Only restores what the user has not started replacing already.\n setMessage((current) => current || sentMessage);\n setFiles((current) => (current.length ? current : sentFiles));\n setPastedTexts((current) => (current.length ? current : sentPastedTexts));\n setTranscriptId((current) => current ?? sentTranscriptId);\n }\n }, [message, files, pastedTexts, onSend, transcriptId, inputDisabled]);\n // Keep a fresh send fn for the deferred handoff auto-send.\n handleSendRef.current = handleSend;\n\n /**\n * Stopping the run hands back whatever was queued behind it. Put that text\n * back where it was written — quietly discarding something the user typed is\n * the one outcome a stop should not have.\n */\n const handleStop = useCallback(async () => {\n if (!onStop) return;\n const result = await onStop();\n const restoredText = (result as { restoredText?: string } | void)\n ?.restoredText;\n if (!restoredText) return;\n setMessage((current) =>\n [current, restoredText].filter(Boolean).join('\\n')\n );\n }, [onStop]);\n\n\n // --- Speech-to-text handlers ---\n\n const clearPending = useCallback(() => {\n if (pendingRafRef.current !== null) {\n cancelAnimationFrame(pendingRafRef.current);\n pendingRafRef.current = null;\n }\n setPendingSend(false);\n setPendingProgress(1);\n }, []);\n\n // Fully exit the hands-free loop and stop any recording in progress.\n const cancelHandoff = useCallback(() => {\n handoffActiveRef.current = false;\n setHandoffActive(false);\n clearPending();\n if (inactivityTimerRef.current) {\n clearTimeout(inactivityTimerRef.current);\n inactivityTimerRef.current = null;\n }\n recording.cancel();\n }, [clearPending, recording]);\n\n // One-shot recording: transcribe → fill the textarea for manual review/send.\n // No hands-free loop, so the textarea stays available afterwards.\n const startOneShotRecording = useCallback(() => {\n setSpeechError(null);\n void recording.start();\n }, [recording]);\n\n // Arm the hands-free loop and start listening.\n const startHandsfreeRecording = useCallback(() => {\n setSpeechError(null);\n handoffActiveRef.current = true;\n setHandoffActive(true);\n void recording.start();\n }, [recording]);\n\n // Stop and reset the press-and-hold progress loop.\n const clearHold = useCallback(() => {\n if (holdRafRef.current !== null) {\n cancelAnimationFrame(holdRafRef.current);\n holdRafRef.current = null;\n }\n setIsHolding(false);\n setHoldProgress(0);\n }, []);\n\n // Mic pressed: when hands-free is available, run a hold timer whose ring fills\n // (0→1) over `holdMs`. Completing it activates hands-free; releasing earlier\n // (handleMicPointerUp) falls back to a one-shot recording. Pointer capture\n // keeps the release event on the button even if the finger drifts off.\n const handleMicPointerDown = useCallback(\n (e: React.PointerEvent) => {\n if (disabled || isProcessing) return;\n try {\n e.currentTarget.setPointerCapture(e.pointerId);\n } catch {\n // ignore environments without pointer capture\n }\n const holdMs = speechHandoffHoldMs ?? HANDOFF_HOLD_MS;\n holdFiredRef.current = false;\n setIsHolding(true);\n setHoldProgress(0);\n const startedAt = Date.now();\n const step = () => {\n const progress = Math.min(1, (Date.now() - startedAt) / holdMs);\n setHoldProgress(progress);\n if (progress >= 1) {\n holdRafRef.current = null;\n holdFiredRef.current = true;\n setIsHolding(false);\n setHoldProgress(0);\n startHandsfreeRecording();\n return;\n }\n holdRafRef.current = requestAnimationFrame(step);\n };\n holdRafRef.current = requestAnimationFrame(step);\n },\n [disabled, isProcessing, speechHandoffHoldMs, startHandsfreeRecording],\n );\n\n // Mic released: if the hold already armed hands-free, do nothing; otherwise\n // treat it as a tap and start a one-shot recording.\n const handleMicPointerUp = useCallback(() => {\n if (holdFiredRef.current) {\n holdFiredRef.current = false;\n return;\n }\n if (holdRafRef.current === null && !isHolding) return; // already aborted\n clearHold();\n startOneShotRecording();\n }, [isHolding, clearHold, startOneShotRecording]);\n\n // Pointer cancelled (e.g. interrupted touch): abort the hold without recording.\n const handleMicPointerCancel = useCallback(() => {\n if (holdFiredRef.current) {\n holdFiredRef.current = false;\n return;\n }\n clearHold();\n }, [clearHold]);\n\n const cancelRecording = useCallback(() => {\n cancelHandoff();\n }, [cancelHandoff]);\n\n // Stop recording, transcribe the audio and fill the input for review.\n // Returns the trimmed transcription (or null if nothing was transcribed) so\n // the handoff loop can decide whether to auto-send or end.\n const confirmRecording = useCallback(async (): Promise<string | null> => {\n if (!transcribeClient) return null;\n const blob = await recording.stop();\n if (!blob || blob.size === 0) return null;\n\n setIsTranscribing(true);\n setSpeechError(null);\n try {\n const result = await transcribeClient.transcribeAudio(blob, {\n language: speechLanguage,\n tenantId: speechTenantId,\n });\n const text = (result.text || '').trim();\n if (text) {\n setMessage((prev) => (prev ? `${prev} ${text}`.trim() : text));\n setTranscriptId(result.transcriptId);\n }\n // Resize textarea and focus for review/edit.\n requestAnimationFrame(() => {\n const textarea = textareaRef.current;\n if (textarea) {\n textarea.style.height = 'auto';\n textarea.style.height = `${Math.min(textarea.scrollHeight, 120)}px`;\n textarea.focus();\n }\n });\n return text;\n } catch (e) {\n setSpeechError(\n `Could not transcribe the audio: ${(e as Error)?.message || 'unknown error'}`,\n );\n return null;\n } finally {\n setIsTranscribing(false);\n }\n }, [transcribeClient, recording, speechLanguage, speechTenantId]);\n\n // Cancellable countdown, then auto-send. Handoff stays active across the send\n // so the loop can continue after the assistant replies.\n const startPendingSend = useCallback(() => {\n const totalMs = speechHandoffSendDelayMs ?? HANDOFF_PENDING_MS;\n setPendingSend(true);\n setPendingProgress(1);\n const startedAt = Date.now();\n const step = () => {\n const elapsed = Date.now() - startedAt;\n setPendingProgress(Math.max(0, 1 - elapsed / totalMs));\n if (elapsed >= totalMs) {\n pendingRafRef.current = null;\n setPendingSend(false);\n setPendingProgress(1);\n handleSendRef.current(); // auto-send with the freshest message\n return;\n }\n pendingRafRef.current = requestAnimationFrame(step);\n };\n pendingRafRef.current = requestAnimationFrame(step);\n }, [speechHandoffSendDelayMs]);\n\n // Drives both the mic auto-stop and the manual confirm button, branching on\n // whether the hands-free loop is active.\n const handleConfirm = useCallback(async () => {\n const text = await confirmRecording();\n if (!handoffActiveRef.current) return; // normal mode: input already filled\n if (!text) {\n // Silent / empty turn → end the hands-free loop.\n cancelHandoff();\n setMessage('');\n setTranscriptId(undefined);\n return;\n }\n startPendingSend();\n }, [confirmRecording, cancelHandoff, startPendingSend]);\n\n // Auto-stop fires handleConfirm with the freshest closure.\n useEffect(() => {\n confirmRef.current = () => void handleConfirm();\n }, [handleConfirm]);\n\n // Any interaction during the pending countdown cancels the auto-send and\n // exits the loop (the user is taking manual control); text stays for editing.\n useEffect(() => {\n if (!pendingSend) return;\n const onInteract = () => {\n clearPending();\n handoffActiveRef.current = false;\n setHandoffActive(false);\n requestAnimationFrame(() => textareaRef.current?.focus());\n };\n document.addEventListener('mousedown', onInteract, true);\n document.addEventListener('keydown', onInteract, true);\n return () => {\n document.removeEventListener('mousedown', onInteract, true);\n document.removeEventListener('keydown', onInteract, true);\n };\n }, [pendingSend, clearPending]);\n\n // When the assistant finishes (isProcessing falls) while the loop is active,\n // re-activate listening for the next turn.\n useEffect(() => {\n const wasProcessing = prevProcessingRef.current;\n prevProcessingRef.current = isProcessing;\n if (\n handoffActive &&\n wasProcessing &&\n !isProcessing &&\n !disabled &&\n !pendingSend &&\n !isTranscribing &&\n !recording.isRecording &&\n !recording.isPaused\n ) {\n void recording.start();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isProcessing, handoffActive, disabled, pendingSend, isTranscribing]);\n\n // While listening in handoff with no speech yet, end the loop after a silence\n // window (an open mic with nothing said means the user is done).\n useEffect(() => {\n if (!(handoffActive && recording.isRecording && !recording.speechDetected)) {\n if (inactivityTimerRef.current) {\n clearTimeout(inactivityTimerRef.current);\n inactivityTimerRef.current = null;\n }\n return;\n }\n inactivityTimerRef.current = setTimeout(() => {\n if (handoffActiveRef.current && !recording.speechDetected) cancelHandoff();\n }, HANDOFF_INACTIVITY_MS);\n return () => {\n if (inactivityTimerRef.current) {\n clearTimeout(inactivityTimerRef.current);\n inactivityTimerRef.current = null;\n }\n };\n }, [handoffActive, recording.isRecording, recording.speechDetected, cancelHandoff]);\n\n // Cleanup deferred work on unmount.\n useEffect(() => {\n return () => {\n if (pendingRafRef.current !== null) cancelAnimationFrame(pendingRafRef.current);\n if (inactivityTimerRef.current) clearTimeout(inactivityTimerRef.current);\n if (holdRafRef.current !== null) cancelAnimationFrame(holdRafRef.current);\n };\n }, []);\n\n // Handle key press\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n },\n [handleSend]\n );\n\n // Handle file selection\n const handleFileSelect = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n addFiles(Array.from(e.target.files || []));\n\n // Reset input\n if (fileInputRef.current) {\n fileInputRef.current.value = '';\n }\n },\n [addFiles]\n );\n\n // Remove file\n const removeFile = useCallback((index: number) => {\n setFiles((prev) => prev.filter((_, i) => i !== index));\n }, []);\n\n // Remove a pasted-text card\n const removePastedText = useCallback((id: string) => {\n setPastedTexts((prev) => prev.filter((p) => p.id !== id));\n }, []);\n\n // Paste: files in the clipboard become attachments; a long block of plain\n // text becomes a card instead of flooding the textarea.\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const clipboard = e.clipboardData;\n if (!clipboard) return;\n\n if (enableFileUploads) {\n const pastedFiles = Array.from(clipboard.items)\n .filter((item) => item.kind === 'file')\n .map((item) => item.getAsFile())\n .filter((file): file is File => file !== null)\n .map((file) => {\n // Clipboard images share a generic name; give each one its own so\n // several pasted screenshots don't collapse into the same label.\n const ext = IMAGE_EXT_BY_MIME[file.type];\n if (!ext) return file;\n pasteCounterRef.current += 1;\n return new File([file], `pasted-image-${pasteCounterRef.current}.${ext}`, {\n type: file.type,\n });\n });\n\n if (pastedFiles.length > 0) {\n e.preventDefault();\n addFiles(pastedFiles);\n return;\n }\n }\n\n if (!enableLongTextPaste) return;\n\n const text = clipboard.getData('text/plain');\n if (text.length <= longTextPasteThreshold) return;\n\n e.preventDefault();\n pasteCounterRef.current += 1;\n setPastedTexts((prev) => [\n ...prev,\n { id: String(pasteCounterRef.current), text },\n ]);\n },\n [enableFileUploads, enableLongTextPaste, longTextPasteThreshold, addFiles]\n );\n\n // --- Drag & drop ---\n\n const handleDragEnter = useCallback(\n (e: React.DragEvent) => {\n if (!enableFileUploads || inputDisabled) return;\n if (!e.dataTransfer.types.includes('Files')) return;\n e.preventDefault();\n dragDepthRef.current += 1;\n setIsDraggingOver(true);\n },\n [enableFileUploads, inputDisabled]\n );\n\n const handleDragOver = useCallback(\n (e: React.DragEvent) => {\n if (!enableFileUploads || inputDisabled) return;\n if (!e.dataTransfer.types.includes('Files')) return;\n // Without this the browser navigates away to open the dropped file.\n e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n },\n [enableFileUploads, inputDisabled]\n );\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);\n if (dragDepthRef.current === 0) setIsDraggingOver(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n if (!enableFileUploads || inputDisabled) return;\n e.preventDefault();\n dragDepthRef.current = 0;\n setIsDraggingOver(false);\n addFiles(Array.from(e.dataTransfer.files || []));\n },\n [enableFileUploads, inputDisabled, addFiles]\n );\n\n return (\n <div\n className=\"devic-input-area\"\n data-dragging={isDraggingOver ? 'true' : 'false'}\n onDragEnter={handleDragEnter}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {isDraggingOver && (\n <div className=\"devic-drop-overlay\">\n <AttachIcon />\n <span>Drop files to attach</span>\n </div>\n )}\n {limitBanner}\n {usageBar}\n {integrationsHint}\n {queueNotice}\n {disabledMessage && disabled && (\n <div className=\"devic-input-disabled-notice\">\n <WaitingIcon />\n {disabledMessage}\n </div>\n )}\n {speechError && (\n <div className=\"devic-speech-error\" role=\"alert\">\n {speechError}\n </div>\n )}\n {handoffActive && (\n <div className=\"devic-handoff-bar\" data-waiting={isProcessing ? 'true' : 'false'}>\n <span className=\"devic-handoff-dot\" aria-hidden=\"true\" />\n <span className=\"devic-handoff-label\">\n {isProcessing ? 'Hands-free · waiting for reply' : 'Hands-free on'}\n </span>\n <button\n type=\"button\"\n className=\"devic-handoff-stop\"\n onClick={cancelHandoff}\n title=\"Stop hands-free\"\n aria-label=\"Stop hands-free\"\n >\n <CloseIcon />\n </button>\n </div>\n )}\n {references && references.length > 0 && (\n <div className=\"devic-reference-chips\">\n {references.map((ref) => (\n <ReferenceChip\n key={ref.id}\n label={ref.label}\n variant=\"input\"\n onRemove={() => onRemoveReference?.(ref.id)}\n />\n ))}\n </div>\n )}\n {pastedTexts.length > 0 && (\n <div className=\"devic-pasted-cards\">\n {pastedTexts.map((pasted) => (\n <div key={pasted.id} className=\"devic-pasted-card\">\n <p className=\"devic-pasted-card-preview\">\n {pastedPreview(pasted.text)}\n </p>\n <div className=\"devic-pasted-card-footer\">\n <span className=\"devic-pasted-card-badge\">PASTED</span>\n <span className=\"devic-pasted-card-meta\">\n {pastedLineCount(pasted.text)} lines\n </span>\n </div>\n <button\n className=\"devic-file-remove devic-pasted-card-remove\"\n onClick={() => removePastedText(pasted.id)}\n type=\"button\"\n title=\"Remove pasted text\"\n aria-label=\"Remove pasted text\"\n >\n &times;\n </button>\n </div>\n ))}\n </div>\n )}\n {files.length > 0 && (\n <div className=\"devic-file-preview\">\n {files.map((file, idx) => (\n <div key={idx} className=\"devic-file-preview-item\">\n {filePreviews[idx] ? (\n <img\n className=\"devic-file-preview-thumb\"\n src={filePreviews[idx]!}\n alt={file.name}\n />\n ) : (\n <FileIcon />\n )}\n <span>{file.name}</span>\n <button\n className=\"devic-file-remove\"\n onClick={() => removeFile(idx)}\n type=\"button\"\n >\n &times;\n </button>\n </div>\n ))}\n </div>\n )}\n\n <div className=\"devic-input-wrapper\">\n {pendingSend ? (\n <div className=\"devic-speech-panel\" data-state=\"pending\">\n <div className=\"devic-handoff-pending\">\n <div className=\"devic-handoff-pending-icon\">\n <SendCountdownRing progress={pendingProgress} />\n <SendIcon />\n </div>\n <div className=\"devic-handoff-pending-text\">\n <span className=\"devic-handoff-pending-title\">\n Sending… interact to cancel\n </span>\n {message.trim() && (\n <span className=\"devic-handoff-pending-preview\">{message.trim()}</span>\n )}\n </div>\n </div>\n </div>\n ) : isTranscribing ? (\n <div className=\"devic-speech-panel\" data-state=\"processing\">\n <span className=\"devic-speech-spinner\" aria-hidden=\"true\" />\n <span className=\"devic-speech-status\">Transcribing…</span>\n </div>\n ) : isRecordingActive ? (\n <div className=\"devic-speech-panel\" data-state=\"recording\">\n <button\n className=\"devic-input-btn devic-speech-cancel\"\n onClick={cancelRecording}\n type=\"button\"\n title=\"Cancel recording\"\n >\n <CloseIcon />\n </button>\n <div className=\"devic-speech-live\">\n <Equalizer levels={recording.levels} paused={recording.isPaused} />\n <span className=\"devic-speech-timer\">\n {formatDuration(recording.durationMs)}\n </span>\n </div>\n <button\n className=\"devic-input-btn\"\n onClick={recording.isPaused ? recording.resume : recording.pause}\n type=\"button\"\n title={recording.isPaused ? 'Resume' : 'Pause'}\n >\n {recording.isPaused ? <PlayIcon /> : <PauseIcon />}\n </button>\n <div\n className=\"devic-speech-confirm-wrap\"\n data-autostop={recording.isAutoStopping ? 'true' : 'false'}\n >\n {recording.isAutoStopping && (\n <AutoStopRing progress={recording.autoStopProgress} />\n )}\n <button\n className=\"devic-input-btn devic-speech-confirm\"\n onClick={() => void handleConfirm()}\n type=\"button\"\n title={\n recording.isAutoStopping\n ? 'Auto-sending… keep talking to cancel'\n : 'Confirm'\n }\n >\n <CheckIcon />\n </button>\n </div>\n </div>\n ) : (\n <>\n {/* Before the attachment: both add something to the message, and\n which apps it may reach is the wider of the two decisions. */}\n {integrationsToggle}\n\n {enableFileUploads && (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept={acceptedTypes}\n multiple\n onChange={handleFileSelect}\n style={{ display: 'none' }}\n />\n <button\n className=\"devic-input-btn\"\n onClick={() => fileInputRef.current?.click()}\n disabled={inputDisabled}\n type=\"button\"\n title=\"Attach file\"\n >\n <AttachIcon />\n </button>\n </>\n )}\n\n {speechEnabled && (\n <div\n className=\"devic-speech-mic-wrap\"\n data-holding={isHolding ? 'true' : 'false'}\n >\n {isHolding && <HoldRing progress={holdProgress} />}\n <button\n className=\"devic-input-btn devic-speech-mic\"\n onClick={speechHandoff ? undefined : startOneShotRecording}\n onPointerDown={speechHandoff ? handleMicPointerDown : undefined}\n onPointerUp={speechHandoff ? handleMicPointerUp : undefined}\n onPointerCancel={speechHandoff ? handleMicPointerCancel : undefined}\n // Dictating a message for the assistant to pick up next is a\n // reasonable thing to do mid-answer, and on a phone it is the\n // natural one. The hands-free loop is another matter: it\n // auto-sends when the assistant finishes, which with a queue\n // would chain sends — see the handoff effect below.\n disabled={inputDisabled || (isProcessing && speechHandoff)}\n type=\"button\"\n title={\n speechHandoff\n ? 'Tap to dictate · hold to start hands-free'\n : 'Record voice message'\n }\n >\n <MicIcon />\n </button>\n </div>\n )}\n\n <textarea\n ref={textareaRef}\n className=\"devic-input\"\n value={message}\n onChange={(e) => {\n const value = e.target.value;\n setMessage(value);\n // If the user clears the field, drop the transcript link so a fresh\n // message isn't wrongly attributed to the previous transcription.\n if (transcriptId && value.trim() === '') setTranscriptId(undefined);\n handleInput();\n }}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={\n busyWithoutQueue\n ? 'The assistant is answering…'\n : isProcessing\n ? 'Write while the assistant answers — it will be queued'\n : placeholder\n }\n disabled={inputDisabled}\n rows={1}\n />\n\n {/*\n Stop and send are not alternatives while a run is in flight: the\n run can be stopped, and a message can also be written for it to\n pick up. Showing only the stop button made the second impossible —\n a message typed then had nowhere to go. The send button still\n disappears with an empty box, so a busy conversation nobody is\n writing into still reads as \"stop only\".\n */}\n {isProcessing &&\n (stopButtonContent ? (\n <div className=\"devic-send-btn-wrapper\">\n <div className=\"devic-send-btn-custom\" aria-hidden=\"true\">\n {stopButtonContent}\n </div>\n <button\n className=\"devic-send-btn-overlay\"\n onClick={handleStop}\n type=\"button\"\n title=\"Stop\"\n />\n </div>\n ) : (\n <button\n className=\"devic-input-btn devic-stop-btn\"\n onClick={handleStop}\n type=\"button\"\n title=\"Stop\"\n >\n <StopIcon />\n </button>\n ))}\n {(!isProcessing || (allowQueueing && hasContent)) &&\n (sendButtonContent ? (\n <div className=\"devic-send-btn-wrapper\">\n <div className=\"devic-send-btn-custom\" aria-hidden=\"true\">\n {sendButtonContent}\n </div>\n <button\n className=\"devic-send-btn-overlay\"\n onClick={handleSend}\n disabled={inputDisabled || !hasContent}\n type=\"button\"\n title={\n isProcessing\n ? \"Queue this message for the assistant's next turn\"\n : 'Send message'\n }\n />\n </div>\n ) : (\n <button\n className=\"devic-input-btn devic-send-btn\"\n onClick={handleSend}\n disabled={inputDisabled || !hasContent}\n type=\"button\"\n title={\n isProcessing\n ? \"Queue this message for the assistant's next turn\"\n : 'Send message'\n }\n >\n <SendIcon />\n </button>\n ))}\n </>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Live equalizer rendered from the recording amplitude levels (0..1 per bar).\n * When paused, bars collapse to a flat baseline.\n */\nfunction Equalizer({\n levels,\n paused,\n}: {\n levels: number[];\n paused: boolean;\n}): JSX.Element {\n return (\n <div className=\"devic-equalizer\" aria-hidden=\"true\" data-paused={paused}>\n {levels.map((level, i) => (\n <span\n key={i}\n className=\"devic-equalizer-bar\"\n style={{ height: `${Math.max(10, Math.round((paused ? 0 : level) * 100))}%` }}\n />\n ))}\n </div>\n );\n}\n\n// Geometry for the auto-stop ring drawn around the confirm button.\nconst AUTOSTOP_RING_R = 18;\nconst AUTOSTOP_RING_C = 2 * Math.PI * AUTOSTOP_RING_R;\n\n/**\n * Inverted circular progress drawn around the confirm button. Driven by\n * `progress` (1 → 0): a full ring that drains to empty over the countdown.\n */\nfunction AutoStopRing({ progress }: { progress: number }): JSX.Element {\n return (\n <svg className=\"devic-autostop-ring\" viewBox=\"0 0 40 40\" aria-hidden=\"true\">\n <circle\n className=\"devic-autostop-ring-track\"\n cx=\"20\"\n cy=\"20\"\n r={AUTOSTOP_RING_R}\n />\n <circle\n className=\"devic-autostop-ring-progress\"\n cx=\"20\"\n cy=\"20\"\n r={AUTOSTOP_RING_R}\n style={{\n strokeDasharray: AUTOSTOP_RING_C,\n strokeDashoffset: AUTOSTOP_RING_C * (1 - progress),\n }}\n />\n </svg>\n );\n}\n\n/**\n * Draining ring around the send icon during the handoff pending countdown.\n * Visually distinct from the auto-stop ring (slate→primary track, larger).\n */\nfunction SendCountdownRing({ progress }: { progress: number }): JSX.Element {\n return (\n <svg className=\"devic-handoff-ring\" viewBox=\"0 0 44 44\" aria-hidden=\"true\">\n <circle className=\"devic-handoff-ring-track\" cx=\"22\" cy=\"22\" r={AUTOSTOP_RING_R} />\n <circle\n className=\"devic-handoff-ring-progress\"\n cx=\"22\"\n cy=\"22\"\n r={AUTOSTOP_RING_R}\n style={{\n strokeDasharray: AUTOSTOP_RING_C,\n strokeDashoffset: AUTOSTOP_RING_C * (1 - progress),\n }}\n />\n </svg>\n );\n}\n\n/**\n * Filling ring drawn around the mic button while the user presses and holds to\n * arm hands-free. Driven by `progress` (0 → 1): an empty ring that fills\n * clockwise over the hold duration. Inverse of the draining auto-stop ring.\n */\nfunction HoldRing({ progress }: { progress: number }): JSX.Element {\n return (\n <svg className=\"devic-mic-hold-ring\" viewBox=\"0 0 40 40\" aria-hidden=\"true\">\n <circle\n className=\"devic-mic-hold-ring-track\"\n cx=\"20\"\n cy=\"20\"\n r={AUTOSTOP_RING_R}\n />\n <circle\n className=\"devic-mic-hold-ring-progress\"\n cx=\"20\"\n cy=\"20\"\n r={AUTOSTOP_RING_R}\n style={{\n strokeDasharray: AUTOSTOP_RING_C,\n strokeDashoffset: AUTOSTOP_RING_C * (1 - progress),\n }}\n />\n </svg>\n );\n}\n\n/** Formats milliseconds as m:ss. */\nfunction formatDuration(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${minutes}:${seconds.toString().padStart(2, '0')}`;\n}\n\n/**\n * Attach icon\n */\nfunction AttachIcon(): JSX.Element {\n return (\n <svg\n width=\"20\"\n height=\"20\"\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=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n );\n}\n\n/**\n * Send icon\n */\nfunction SendIcon(): JSX.Element {\n return (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\" />\n </svg>\n );\n}\n\n/**\n * File icon\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 * Microphone icon\n */\nfunction MicIcon(): JSX.Element {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 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 <line x1=\"8\" y1=\"23\" x2=\"16\" y2=\"23\" />\n </svg>\n );\n}\n\n/**\n * Pause icon (two bars)\n */\nfunction PauseIcon(): JSX.Element {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n </svg>\n );\n}\n\n/**\n * Play icon (triangle)\n */\nfunction PlayIcon(): JSX.Element {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n );\n}\n\n/**\n * Check icon (confirm)\n */\nfunction CheckIcon(): JSX.Element {\n return (\n <svg\n width=\"18\"\n height=\"18\"\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\n/**\n * Close icon (cancel)\n */\nfunction CloseIcon(): JSX.Element {\n return (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\n/**\n * Stop icon (square)\n */\nfunction StopIcon(): JSX.Element {\n return (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"2\" />\n </svg>\n );\n}\n\n/**\n * Waiting icon (clock)\n */\nfunction WaitingIcon(): 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=\"10\" />\n <polyline points=\"12,6 12,12 16,14\" />\n </svg>\n );\n}\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"ChatInput.js","sources":["../../../../src/components/ChatDrawer/ChatInput.tsx"],"sourcesContent":["import React, { useState, useRef, useCallback, useMemo, useEffect } from 'react';\nimport { useOptionalDevicContext } from '../../provider';\nimport type { ChatInputProps } from './ChatDrawer.types';\nimport { useSpeechRecording } from '../../hooks/useSpeechRecording';\nimport { DevicApiClient } from '../../api/client';\nimport { ReferenceChip } from './ReferenceChip';\nimport { useTranslations } from '../../i18n';\nimport {\n toPastedBlock,\n pastedPreview,\n pastedLineCount,\n type PastedText,\n} from './pastedText';\n\nconst FILE_TYPE_ACCEPT: Record<string, string[]> = {\n images: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],\n documents: [\n 'application/pdf',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'text/plain',\n 'text/csv',\n 'application/json',\n ],\n audio: ['audio/mpeg', 'audio/wav', 'audio/ogg'],\n video: ['video/mp4', 'video/webm', 'video/ogg'],\n};\n\n// Extensions accepted per category, on top of the MIME types above. The browser\n// derives `File.type` from the OS, which reports .json inconsistently: empty on\n// Windows without the registry entry, 'text/plain' on some Linux setups. Without\n// this fallback a .json picked from the dialog or dropped in would be silently\n// rejected on those machines.\nconst FILE_TYPE_ACCEPT_EXT: Record<string, string[]> = {\n documents: ['.json'],\n};\n\n// Extensions used to name images pasted from the clipboard, which arrive with a\n// generic name (\"image.png\") or none at all.\nconst IMAGE_EXT_BY_MIME: Record<string, string> = {\n 'image/jpeg': 'jpg',\n 'image/png': 'png',\n 'image/gif': 'gif',\n 'image/webp': 'webp',\n};\n\n// Handoff (hands-free) loop timings.\nconst HANDOFF_PENDING_MS = 1000; // default cancellable countdown before auto-send\nconst HANDOFF_INACTIVITY_MS = 6000; // silence (no speech) that ends the loop\nconst HANDOFF_HOLD_MS = 3000; // press-and-hold duration on the mic to arm hands-free\n\n/**\n * Chat input component with file upload support.\n *\n * When a widget is pending as 'input' it replaces the whole input area. The swap\n * lives here, in a component with no hooks of its own, so that each subtree is\n * mounted and unmounted whole. Returning the widget from inside ChatInputBox\n * instead would skip every hook below the early return, which violates the rules\n * of hooks (and is what react-hooks/rules-of-hooks flags). React tolerates that\n * particular shape today — its \"fewer hooks than expected\" check only fires once\n * at least one hook has run — so it is a latent fragility rather than a crash,\n * but the toggle is on the hot path for interactive widgets and does not need to\n * depend on that internal detail. Draft text in the textarea is dropped on the\n * swap, same as before.\n */\nexport function ChatInput(props: ChatInputProps): JSX.Element {\n const { pendingInputWidget, onSubmitWidget, onCancelWidget } = props;\n\n if (pendingInputWidget) {\n const WidgetComponent = pendingInputWidget.widget.component;\n return (\n <div className=\"devic-input-area\" data-widget-mode=\"input\">\n <div className=\"devic-input-widget\" data-tool-name={pendingInputWidget.toolName}>\n <WidgetComponent\n toolCall={pendingInputWidget.toolCall}\n params={pendingInputWidget.params}\n submit={(response) => onSubmitWidget?.(pendingInputWidget.toolCall.id, response)}\n cancel={(reason) => onCancelWidget?.(pendingInputWidget.toolCall.id, reason)}\n />\n </div>\n </div>\n );\n }\n\n return <ChatInputBox {...props} />;\n}\n\nfunction ChatInputBox({\n onSend,\n disabled = false,\n placeholder = 'Type a message...',\n enableFileUploads = false,\n allowedFileTypes = { images: true, documents: true },\n maxFileSize = 10 * 1024 * 1024, // 10MB\n enableLongTextPaste = false,\n longTextPasteThreshold = 2000,\n enableSpeechToText = false,\n speechLanguage,\n speechTenantId,\n speechAutoStop = true,\n speechAutoStopCountdownMs,\n speechAutoStopSilenceMs,\n speechAutoStopSilenceRatio,\n speechAutoStopSilenceLevel,\n speechAutoStopSpeechLevel,\n speechHandoff = false,\n speechHandoffSendDelayMs,\n speechHandoffHoldMs,\n apiKey,\n baseUrl,\n sendButtonContent,\n disabledMessage,\n isProcessing = false,\n onStop,\n allowQueueing = false,\n queueNotice,\n stopButtonContent,\n references,\n onRemoveReference,\n usageBar,\n limitBanner,\n integrationsHint,\n integrationsToggle,\n}: ChatInputProps): JSX.Element {\n const t = useTranslations();\n const [message, setMessage] = useState('');\n const [files, setFiles] = useState<File[]>([]);\n // Long blocks of pasted text, kept out of the textarea and shown as cards.\n const [pastedTexts, setPastedTexts] = useState<PastedText[]>([]);\n const [isDraggingOver, setIsDraggingOver] = useState(false);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n // Monotonic counters so pasted images and text blocks get stable, unique ids.\n const pasteCounterRef = useRef(0);\n // Nested dragenter/dragleave events fire per child node; count them so the\n // overlay only clears when the pointer truly leaves the input area.\n const dragDepthRef = useRef(0);\n\n // Speech-to-text state\n const [transcriptId, setTranscriptId] = useState<string | undefined>();\n const [isTranscribing, setIsTranscribing] = useState(false);\n const [speechError, setSpeechError] = useState<string | null>(null);\n // Holds the latest confirmRecording so the auto-stop callback (created before\n // confirmRecording is defined) always calls the current closure.\n const confirmRef = useRef<() => void>(() => {});\n const recording = useSpeechRecording({\n bars: 5,\n autoStop: speechAutoStop,\n ...(speechAutoStopCountdownMs != null && {\n autoStopCountdownMs: speechAutoStopCountdownMs,\n }),\n ...(speechAutoStopSilenceMs != null && {\n autoStopSilenceMs: speechAutoStopSilenceMs,\n }),\n ...(speechAutoStopSilenceRatio != null && {\n autoStopSilenceRatio: speechAutoStopSilenceRatio,\n }),\n ...(speechAutoStopSilenceLevel != null && {\n autoStopSilenceLevel: speechAutoStopSilenceLevel,\n }),\n ...(speechAutoStopSpeechLevel != null && {\n autoStopSpeechLevel: speechAutoStopSpeechLevel,\n }),\n onAutoStop: () => confirmRef.current(),\n });\n\n // --- Handoff (hands-free loop) state ---\n const [handoffActive, setHandoffActive] = useState(false);\n const [pendingSend, setPendingSend] = useState(false);\n const [pendingProgress, setPendingProgress] = useState(1);\n // Ref mirror so async callbacks (rAF, timers, document listeners) read the\n // live value without going stale.\n const handoffActiveRef = useRef(false);\n const pendingRafRef = useRef<number | null>(null);\n const inactivityTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const prevProcessingRef = useRef(isProcessing);\n // Always-fresh send fn so the deferred auto-send uses the latest message.\n const handleSendRef = useRef<() => void>(() => {});\n\n // --- Press-and-hold to arm hands-free ---\n // Holding the mic for `holdMs` fills a ring (0→1) and activates hands-free;\n // releasing earlier falls back to a single one-shot recording.\n const [holdProgress, setHoldProgress] = useState(0);\n const [isHolding, setIsHolding] = useState(false);\n const holdRafRef = useRef<number | null>(null);\n const holdFiredRef = useRef(false);\n\n // Client used only for the /whisper transcription call.\n const devicContext = useOptionalDevicContext();\n const getTenantSession = devicContext?.getTenantSession;\n const onSessionExpired = devicContext?.onSessionExpired;\n const transcribeClient = useMemo(() => {\n if (!enableSpeechToText || (!apiKey && !getTenantSession)) return null;\n return new DevicApiClient({\n apiKey,\n baseUrl: baseUrl || 'https://api.devic.ai',\n getTenantSession,\n onSessionExpired,\n });\n }, [enableSpeechToText, apiKey, getTenantSession, baseUrl]);\n\n const speechEnabled =\n enableSpeechToText && recording.isSupported && !!transcribeClient;\n const isRecordingActive = recording.isRecording || recording.isPaused;\n\n // Calculate accepted file types\n const acceptedTypeList = useMemo(\n () =>\n Object.entries(allowedFileTypes)\n .filter(([, enabled]) => enabled)\n .flatMap(([type]) => FILE_TYPE_ACCEPT[type] || []),\n [allowedFileTypes]\n );\n const acceptedExtList = useMemo(\n () =>\n Object.entries(allowedFileTypes)\n .filter(([, enabled]) => enabled)\n .flatMap(([type]) => FILE_TYPE_ACCEPT_EXT[type] || []),\n [allowedFileTypes]\n );\n // The native dialog takes both MIME types and extensions in `accept`.\n const acceptedTypes = [...acceptedTypeList, ...acceptedExtList].join(',');\n\n // Single entry point for every way of attaching a file (button, paste, drop):\n // enforces the size limit and the allowed MIME types, which until now were\n // only hinted at the native file dialog and never actually checked.\n const addFiles = useCallback(\n (incoming: File[]) => {\n const validFiles = incoming.filter((file) => {\n if (file.size > maxFileSize) {\n console.warn(`File ${file.name} exceeds maximum size`);\n return false;\n }\n const name = file.name.toLowerCase();\n const allowed =\n acceptedTypeList.length === 0 ||\n acceptedTypeList.includes(file.type) ||\n acceptedExtList.some((ext) => name.endsWith(ext));\n if (!allowed) {\n console.warn(`File type ${file.type || 'unknown'} is not allowed`);\n return false;\n }\n return true;\n });\n if (validFiles.length > 0) setFiles((prev) => [...prev, ...validFiles]);\n },\n [maxFileSize, acceptedTypeList, acceptedExtList]\n );\n\n // Thumbnails for attached images. The cleanup revokes the previous batch on\n // every change (and on unmount), so the object URLs never leak.\n const filePreviews = useMemo(\n () =>\n files.map((file) =>\n file.type.startsWith('image/') ? URL.createObjectURL(file) : null\n ),\n [files]\n );\n useEffect(\n () => () => {\n filePreviews.forEach((url) => url && URL.revokeObjectURL(url));\n },\n [filePreviews]\n );\n\n // Auto-resize textarea\n const handleInput = useCallback(() => {\n const textarea = textareaRef.current;\n if (textarea) {\n textarea.style.height = 'auto';\n textarea.style.height = `${Math.min(textarea.scrollHeight, 120)}px`;\n }\n }, []);\n\n /** Whether there is anything to send. */\n const hasContent =\n !!message.trim() || files.length > 0 || pastedTexts.length > 0;\n\n /**\n * Busy, and this assistant does not queue: writing is pointless because the\n * message would be refused. Kept apart from `disabled`, which the stop button\n * also answers to — it lives in this same box and has to stay clickable.\n */\n const busyWithoutQueue = isProcessing && !allowQueueing;\n const inputDisabled = disabled || busyWithoutQueue;\n\n // Handle send\n const handleSend = useCallback(async () => {\n const trimmedMessage = message.trim();\n if (!trimmedMessage && files.length === 0 && pastedTexts.length === 0) return;\n if (inputDisabled) return;\n\n // Pasted text is shown as a card but still reaches the model in full: each\n // block is prepended to the message inside a delimiter the thread can parse\n // back out (see parsePastedBlocks in ChatMessages).\n const composedMessage =\n pastedTexts.length > 0\n ? [...pastedTexts.map(toPastedBlock), trimmedMessage]\n .filter(Boolean)\n .join('\\n\\n')\n : trimmedMessage;\n\n // Cleared straight away so the box is ready for the next message, and put\n // back if the conversation turned this one down — the text is the user's,\n // and losing it is not an acceptable way to report a refusal.\n const sentMessage = message;\n const sentFiles = files;\n const sentPastedTexts = pastedTexts;\n const sentTranscriptId = transcriptId;\n\n setMessage('');\n setFiles([]);\n setPastedTexts([]);\n setTranscriptId(undefined);\n\n // Reset textarea height\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto';\n }\n\n const result = await onSend(\n composedMessage,\n sentFiles.length > 0 ? sentFiles : undefined,\n sentTranscriptId ? { transcriptId: sentTranscriptId } : undefined,\n );\n\n if (result && 'rejected' in result) {\n // Only restores what the user has not started replacing already.\n setMessage((current) => current || sentMessage);\n setFiles((current) => (current.length ? current : sentFiles));\n setPastedTexts((current) => (current.length ? current : sentPastedTexts));\n setTranscriptId((current) => current ?? sentTranscriptId);\n }\n }, [message, files, pastedTexts, onSend, transcriptId, inputDisabled]);\n // Keep a fresh send fn for the deferred handoff auto-send.\n handleSendRef.current = handleSend;\n\n /**\n * Stopping the run hands back whatever was queued behind it. Put that text\n * back where it was written — quietly discarding something the user typed is\n * the one outcome a stop should not have.\n */\n const handleStop = useCallback(async () => {\n if (!onStop) return;\n const result = await onStop();\n const restoredText = (result as { restoredText?: string } | void)\n ?.restoredText;\n if (!restoredText) return;\n setMessage((current) =>\n [current, restoredText].filter(Boolean).join('\\n')\n );\n }, [onStop]);\n\n\n // --- Speech-to-text handlers ---\n\n const clearPending = useCallback(() => {\n if (pendingRafRef.current !== null) {\n cancelAnimationFrame(pendingRafRef.current);\n pendingRafRef.current = null;\n }\n setPendingSend(false);\n setPendingProgress(1);\n }, []);\n\n // Fully exit the hands-free loop and stop any recording in progress.\n const cancelHandoff = useCallback(() => {\n handoffActiveRef.current = false;\n setHandoffActive(false);\n clearPending();\n if (inactivityTimerRef.current) {\n clearTimeout(inactivityTimerRef.current);\n inactivityTimerRef.current = null;\n }\n recording.cancel();\n }, [clearPending, recording]);\n\n // One-shot recording: transcribe → fill the textarea for manual review/send.\n // No hands-free loop, so the textarea stays available afterwards.\n const startOneShotRecording = useCallback(() => {\n setSpeechError(null);\n void recording.start();\n }, [recording]);\n\n // Arm the hands-free loop and start listening.\n const startHandsfreeRecording = useCallback(() => {\n setSpeechError(null);\n handoffActiveRef.current = true;\n setHandoffActive(true);\n void recording.start();\n }, [recording]);\n\n // Stop and reset the press-and-hold progress loop.\n const clearHold = useCallback(() => {\n if (holdRafRef.current !== null) {\n cancelAnimationFrame(holdRafRef.current);\n holdRafRef.current = null;\n }\n setIsHolding(false);\n setHoldProgress(0);\n }, []);\n\n // Mic pressed: when hands-free is available, run a hold timer whose ring fills\n // (0→1) over `holdMs`. Completing it activates hands-free; releasing earlier\n // (handleMicPointerUp) falls back to a one-shot recording. Pointer capture\n // keeps the release event on the button even if the finger drifts off.\n const handleMicPointerDown = useCallback(\n (e: React.PointerEvent) => {\n if (disabled || isProcessing) return;\n try {\n e.currentTarget.setPointerCapture(e.pointerId);\n } catch {\n // ignore environments without pointer capture\n }\n const holdMs = speechHandoffHoldMs ?? HANDOFF_HOLD_MS;\n holdFiredRef.current = false;\n setIsHolding(true);\n setHoldProgress(0);\n const startedAt = Date.now();\n const step = () => {\n const progress = Math.min(1, (Date.now() - startedAt) / holdMs);\n setHoldProgress(progress);\n if (progress >= 1) {\n holdRafRef.current = null;\n holdFiredRef.current = true;\n setIsHolding(false);\n setHoldProgress(0);\n startHandsfreeRecording();\n return;\n }\n holdRafRef.current = requestAnimationFrame(step);\n };\n holdRafRef.current = requestAnimationFrame(step);\n },\n [disabled, isProcessing, speechHandoffHoldMs, startHandsfreeRecording],\n );\n\n // Mic released: if the hold already armed hands-free, do nothing; otherwise\n // treat it as a tap and start a one-shot recording.\n const handleMicPointerUp = useCallback(() => {\n if (holdFiredRef.current) {\n holdFiredRef.current = false;\n return;\n }\n if (holdRafRef.current === null && !isHolding) return; // already aborted\n clearHold();\n startOneShotRecording();\n }, [isHolding, clearHold, startOneShotRecording]);\n\n // Pointer cancelled (e.g. interrupted touch): abort the hold without recording.\n const handleMicPointerCancel = useCallback(() => {\n if (holdFiredRef.current) {\n holdFiredRef.current = false;\n return;\n }\n clearHold();\n }, [clearHold]);\n\n const cancelRecording = useCallback(() => {\n cancelHandoff();\n }, [cancelHandoff]);\n\n // Stop recording, transcribe the audio and fill the input for review.\n // Returns the trimmed transcription (or null if nothing was transcribed) so\n // the handoff loop can decide whether to auto-send or end.\n const confirmRecording = useCallback(async (): Promise<string | null> => {\n if (!transcribeClient) return null;\n const blob = await recording.stop();\n if (!blob || blob.size === 0) return null;\n\n setIsTranscribing(true);\n setSpeechError(null);\n try {\n const result = await transcribeClient.transcribeAudio(blob, {\n language: speechLanguage,\n tenantId: speechTenantId,\n });\n const text = (result.text || '').trim();\n if (text) {\n setMessage((prev) => (prev ? `${prev} ${text}`.trim() : text));\n setTranscriptId(result.transcriptId);\n }\n // Resize textarea and focus for review/edit.\n requestAnimationFrame(() => {\n const textarea = textareaRef.current;\n if (textarea) {\n textarea.style.height = 'auto';\n textarea.style.height = `${Math.min(textarea.scrollHeight, 120)}px`;\n textarea.focus();\n }\n });\n return text;\n } catch (e) {\n setSpeechError(\n t('Could not transcribe the audio: {error}', {\n error: (e as Error)?.message || t('unknown error'),\n }),\n );\n return null;\n } finally {\n setIsTranscribing(false);\n }\n }, [transcribeClient, recording, speechLanguage, speechTenantId, t]);\n\n // Cancellable countdown, then auto-send. Handoff stays active across the send\n // so the loop can continue after the assistant replies.\n const startPendingSend = useCallback(() => {\n const totalMs = speechHandoffSendDelayMs ?? HANDOFF_PENDING_MS;\n setPendingSend(true);\n setPendingProgress(1);\n const startedAt = Date.now();\n const step = () => {\n const elapsed = Date.now() - startedAt;\n setPendingProgress(Math.max(0, 1 - elapsed / totalMs));\n if (elapsed >= totalMs) {\n pendingRafRef.current = null;\n setPendingSend(false);\n setPendingProgress(1);\n handleSendRef.current(); // auto-send with the freshest message\n return;\n }\n pendingRafRef.current = requestAnimationFrame(step);\n };\n pendingRafRef.current = requestAnimationFrame(step);\n }, [speechHandoffSendDelayMs]);\n\n // Drives both the mic auto-stop and the manual confirm button, branching on\n // whether the hands-free loop is active.\n const handleConfirm = useCallback(async () => {\n const text = await confirmRecording();\n if (!handoffActiveRef.current) return; // normal mode: input already filled\n if (!text) {\n // Silent / empty turn → end the hands-free loop.\n cancelHandoff();\n setMessage('');\n setTranscriptId(undefined);\n return;\n }\n startPendingSend();\n }, [confirmRecording, cancelHandoff, startPendingSend]);\n\n // Auto-stop fires handleConfirm with the freshest closure.\n useEffect(() => {\n confirmRef.current = () => void handleConfirm();\n }, [handleConfirm]);\n\n // Any interaction during the pending countdown cancels the auto-send and\n // exits the loop (the user is taking manual control); text stays for editing.\n useEffect(() => {\n if (!pendingSend) return;\n const onInteract = () => {\n clearPending();\n handoffActiveRef.current = false;\n setHandoffActive(false);\n requestAnimationFrame(() => textareaRef.current?.focus());\n };\n document.addEventListener('mousedown', onInteract, true);\n document.addEventListener('keydown', onInteract, true);\n return () => {\n document.removeEventListener('mousedown', onInteract, true);\n document.removeEventListener('keydown', onInteract, true);\n };\n }, [pendingSend, clearPending]);\n\n // When the assistant finishes (isProcessing falls) while the loop is active,\n // re-activate listening for the next turn.\n useEffect(() => {\n const wasProcessing = prevProcessingRef.current;\n prevProcessingRef.current = isProcessing;\n if (\n handoffActive &&\n wasProcessing &&\n !isProcessing &&\n !disabled &&\n !pendingSend &&\n !isTranscribing &&\n !recording.isRecording &&\n !recording.isPaused\n ) {\n void recording.start();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isProcessing, handoffActive, disabled, pendingSend, isTranscribing]);\n\n // While listening in handoff with no speech yet, end the loop after a silence\n // window (an open mic with nothing said means the user is done).\n useEffect(() => {\n if (!(handoffActive && recording.isRecording && !recording.speechDetected)) {\n if (inactivityTimerRef.current) {\n clearTimeout(inactivityTimerRef.current);\n inactivityTimerRef.current = null;\n }\n return;\n }\n inactivityTimerRef.current = setTimeout(() => {\n if (handoffActiveRef.current && !recording.speechDetected) cancelHandoff();\n }, HANDOFF_INACTIVITY_MS);\n return () => {\n if (inactivityTimerRef.current) {\n clearTimeout(inactivityTimerRef.current);\n inactivityTimerRef.current = null;\n }\n };\n }, [handoffActive, recording.isRecording, recording.speechDetected, cancelHandoff]);\n\n // Cleanup deferred work on unmount.\n useEffect(() => {\n return () => {\n if (pendingRafRef.current !== null) cancelAnimationFrame(pendingRafRef.current);\n if (inactivityTimerRef.current) clearTimeout(inactivityTimerRef.current);\n if (holdRafRef.current !== null) cancelAnimationFrame(holdRafRef.current);\n };\n }, []);\n\n // Handle key press\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n },\n [handleSend]\n );\n\n // Handle file selection\n const handleFileSelect = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n addFiles(Array.from(e.target.files || []));\n\n // Reset input\n if (fileInputRef.current) {\n fileInputRef.current.value = '';\n }\n },\n [addFiles]\n );\n\n // Remove file\n const removeFile = useCallback((index: number) => {\n setFiles((prev) => prev.filter((_, i) => i !== index));\n }, []);\n\n // Remove a pasted-text card\n const removePastedText = useCallback((id: string) => {\n setPastedTexts((prev) => prev.filter((p) => p.id !== id));\n }, []);\n\n // Paste: files in the clipboard become attachments; a long block of plain\n // text becomes a card instead of flooding the textarea.\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const clipboard = e.clipboardData;\n if (!clipboard) return;\n\n if (enableFileUploads) {\n const pastedFiles = Array.from(clipboard.items)\n .filter((item) => item.kind === 'file')\n .map((item) => item.getAsFile())\n .filter((file): file is File => file !== null)\n .map((file) => {\n // Clipboard images share a generic name; give each one its own so\n // several pasted screenshots don't collapse into the same label.\n const ext = IMAGE_EXT_BY_MIME[file.type];\n if (!ext) return file;\n pasteCounterRef.current += 1;\n return new File([file], `pasted-image-${pasteCounterRef.current}.${ext}`, {\n type: file.type,\n });\n });\n\n if (pastedFiles.length > 0) {\n e.preventDefault();\n addFiles(pastedFiles);\n return;\n }\n }\n\n if (!enableLongTextPaste) return;\n\n const text = clipboard.getData('text/plain');\n if (text.length <= longTextPasteThreshold) return;\n\n e.preventDefault();\n pasteCounterRef.current += 1;\n setPastedTexts((prev) => [\n ...prev,\n { id: String(pasteCounterRef.current), text },\n ]);\n },\n [enableFileUploads, enableLongTextPaste, longTextPasteThreshold, addFiles]\n );\n\n // --- Drag & drop ---\n\n const handleDragEnter = useCallback(\n (e: React.DragEvent) => {\n if (!enableFileUploads || inputDisabled) return;\n if (!e.dataTransfer.types.includes('Files')) return;\n e.preventDefault();\n dragDepthRef.current += 1;\n setIsDraggingOver(true);\n },\n [enableFileUploads, inputDisabled]\n );\n\n const handleDragOver = useCallback(\n (e: React.DragEvent) => {\n if (!enableFileUploads || inputDisabled) return;\n if (!e.dataTransfer.types.includes('Files')) return;\n // Without this the browser navigates away to open the dropped file.\n e.preventDefault();\n e.dataTransfer.dropEffect = 'copy';\n },\n [enableFileUploads, inputDisabled]\n );\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);\n if (dragDepthRef.current === 0) setIsDraggingOver(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n if (!enableFileUploads || inputDisabled) return;\n e.preventDefault();\n dragDepthRef.current = 0;\n setIsDraggingOver(false);\n addFiles(Array.from(e.dataTransfer.files || []));\n },\n [enableFileUploads, inputDisabled, addFiles]\n );\n\n return (\n <div\n className=\"devic-input-area\"\n data-dragging={isDraggingOver ? 'true' : 'false'}\n onDragEnter={handleDragEnter}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {isDraggingOver && (\n <div className=\"devic-drop-overlay\">\n <AttachIcon />\n <span>{t('Drop files to attach')}</span>\n </div>\n )}\n {limitBanner}\n {usageBar}\n {integrationsHint}\n {queueNotice}\n {disabledMessage && disabled && (\n <div className=\"devic-input-disabled-notice\">\n <WaitingIcon />\n {disabledMessage}\n </div>\n )}\n {speechError && (\n <div className=\"devic-speech-error\" role=\"alert\">\n {speechError}\n </div>\n )}\n {handoffActive && (\n <div className=\"devic-handoff-bar\" data-waiting={isProcessing ? 'true' : 'false'}>\n <span className=\"devic-handoff-dot\" aria-hidden=\"true\" />\n <span className=\"devic-handoff-label\">\n {isProcessing\n ? t('Hands-free · waiting for reply')\n : t('Hands-free on')}\n </span>\n <button\n type=\"button\"\n className=\"devic-handoff-stop\"\n onClick={cancelHandoff}\n title={t('Stop hands-free')}\n aria-label={t('Stop hands-free')}\n >\n <CloseIcon />\n </button>\n </div>\n )}\n {references && references.length > 0 && (\n <div className=\"devic-reference-chips\">\n {references.map((ref) => (\n <ReferenceChip\n key={ref.id}\n label={ref.label}\n variant=\"input\"\n onRemove={() => onRemoveReference?.(ref.id)}\n />\n ))}\n </div>\n )}\n {pastedTexts.length > 0 && (\n <div className=\"devic-pasted-cards\">\n {pastedTexts.map((pasted) => (\n <div key={pasted.id} className=\"devic-pasted-card\">\n <p className=\"devic-pasted-card-preview\">\n {pastedPreview(pasted.text)}\n </p>\n <div className=\"devic-pasted-card-footer\">\n <span className=\"devic-pasted-card-badge\">{t('PASTED')}</span>\n <span className=\"devic-pasted-card-meta\">\n {t('{count} lines', { count: pastedLineCount(pasted.text) })}\n </span>\n </div>\n <button\n className=\"devic-file-remove devic-pasted-card-remove\"\n onClick={() => removePastedText(pasted.id)}\n type=\"button\"\n title={t('Remove pasted text')}\n aria-label={t('Remove pasted text')}\n >\n &times;\n </button>\n </div>\n ))}\n </div>\n )}\n {files.length > 0 && (\n <div className=\"devic-file-preview\">\n {files.map((file, idx) => (\n <div key={idx} className=\"devic-file-preview-item\">\n {filePreviews[idx] ? (\n <img\n className=\"devic-file-preview-thumb\"\n src={filePreviews[idx]!}\n alt={file.name}\n />\n ) : (\n <FileIcon />\n )}\n <span>{file.name}</span>\n <button\n className=\"devic-file-remove\"\n onClick={() => removeFile(idx)}\n type=\"button\"\n >\n &times;\n </button>\n </div>\n ))}\n </div>\n )}\n\n <div className=\"devic-input-wrapper\">\n {pendingSend ? (\n <div className=\"devic-speech-panel\" data-state=\"pending\">\n <div className=\"devic-handoff-pending\">\n <div className=\"devic-handoff-pending-icon\">\n <SendCountdownRing progress={pendingProgress} />\n <SendIcon />\n </div>\n <div className=\"devic-handoff-pending-text\">\n <span className=\"devic-handoff-pending-title\">\n Sending… interact to cancel\n </span>\n {message.trim() && (\n <span className=\"devic-handoff-pending-preview\">{message.trim()}</span>\n )}\n </div>\n </div>\n </div>\n ) : isTranscribing ? (\n <div className=\"devic-speech-panel\" data-state=\"processing\">\n <span className=\"devic-speech-spinner\" aria-hidden=\"true\" />\n <span className=\"devic-speech-status\">{t('Transcribing…')}</span>\n </div>\n ) : isRecordingActive ? (\n <div className=\"devic-speech-panel\" data-state=\"recording\">\n <button\n className=\"devic-input-btn devic-speech-cancel\"\n onClick={cancelRecording}\n type=\"button\"\n title={t('Cancel recording')}\n >\n <CloseIcon />\n </button>\n <div className=\"devic-speech-live\">\n <Equalizer levels={recording.levels} paused={recording.isPaused} />\n <span className=\"devic-speech-timer\">\n {formatDuration(recording.durationMs)}\n </span>\n </div>\n <button\n className=\"devic-input-btn\"\n onClick={recording.isPaused ? recording.resume : recording.pause}\n type=\"button\"\n title={recording.isPaused ? t('Resume') : t('Pause')}\n >\n {recording.isPaused ? <PlayIcon /> : <PauseIcon />}\n </button>\n <div\n className=\"devic-speech-confirm-wrap\"\n data-autostop={recording.isAutoStopping ? 'true' : 'false'}\n >\n {recording.isAutoStopping && (\n <AutoStopRing progress={recording.autoStopProgress} />\n )}\n <button\n className=\"devic-input-btn devic-speech-confirm\"\n onClick={() => void handleConfirm()}\n type=\"button\"\n title={\n recording.isAutoStopping\n ? t('Auto-sending… keep talking to cancel')\n : t('Confirm')\n }\n >\n <CheckIcon />\n </button>\n </div>\n </div>\n ) : (\n <>\n {/* Before the attachment: both add something to the message, and\n which apps it may reach is the wider of the two decisions. */}\n {integrationsToggle}\n\n {enableFileUploads && (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept={acceptedTypes}\n multiple\n onChange={handleFileSelect}\n style={{ display: 'none' }}\n />\n <button\n className=\"devic-input-btn\"\n onClick={() => fileInputRef.current?.click()}\n disabled={inputDisabled}\n type=\"button\"\n title={t('Attach file')}\n >\n <AttachIcon />\n </button>\n </>\n )}\n\n {speechEnabled && (\n <div\n className=\"devic-speech-mic-wrap\"\n data-holding={isHolding ? 'true' : 'false'}\n >\n {isHolding && <HoldRing progress={holdProgress} />}\n <button\n className=\"devic-input-btn devic-speech-mic\"\n onClick={speechHandoff ? undefined : startOneShotRecording}\n onPointerDown={speechHandoff ? handleMicPointerDown : undefined}\n onPointerUp={speechHandoff ? handleMicPointerUp : undefined}\n onPointerCancel={speechHandoff ? handleMicPointerCancel : undefined}\n // Dictating a message for the assistant to pick up next is a\n // reasonable thing to do mid-answer, and on a phone it is the\n // natural one. The hands-free loop is another matter: it\n // auto-sends when the assistant finishes, which with a queue\n // would chain sends — see the handoff effect below.\n disabled={inputDisabled || (isProcessing && speechHandoff)}\n type=\"button\"\n title={\n speechHandoff\n ? t('Tap to dictate · hold to start hands-free')\n : t('Record voice message')\n }\n >\n <MicIcon />\n </button>\n </div>\n )}\n\n <textarea\n ref={textareaRef}\n className=\"devic-input\"\n value={message}\n onChange={(e) => {\n const value = e.target.value;\n setMessage(value);\n // If the user clears the field, drop the transcript link so a fresh\n // message isn't wrongly attributed to the previous transcription.\n if (transcriptId && value.trim() === '') setTranscriptId(undefined);\n handleInput();\n }}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={\n busyWithoutQueue\n ? t('The assistant is answering…')\n : isProcessing\n ? t('Write while the assistant answers — it will be queued')\n : t(placeholder)\n }\n disabled={inputDisabled}\n rows={1}\n />\n\n {/*\n Stop and send are not alternatives while a run is in flight: the\n run can be stopped, and a message can also be written for it to\n pick up. Showing only the stop button made the second impossible —\n a message typed then had nowhere to go. The send button still\n disappears with an empty box, so a busy conversation nobody is\n writing into still reads as \"stop only\".\n */}\n {isProcessing &&\n (stopButtonContent ? (\n <div className=\"devic-send-btn-wrapper\">\n <div className=\"devic-send-btn-custom\" aria-hidden=\"true\">\n {stopButtonContent}\n </div>\n <button\n className=\"devic-send-btn-overlay\"\n onClick={handleStop}\n type=\"button\"\n title={t('Stop')}\n />\n </div>\n ) : (\n <button\n className=\"devic-input-btn devic-stop-btn\"\n onClick={handleStop}\n type=\"button\"\n title={t('Stop')}\n >\n <StopIcon />\n </button>\n ))}\n {(!isProcessing || (allowQueueing && hasContent)) &&\n (sendButtonContent ? (\n <div className=\"devic-send-btn-wrapper\">\n <div className=\"devic-send-btn-custom\" aria-hidden=\"true\">\n {sendButtonContent}\n </div>\n <button\n className=\"devic-send-btn-overlay\"\n onClick={handleSend}\n disabled={inputDisabled || !hasContent}\n type=\"button\"\n title={\n isProcessing\n ? t(\"Queue this message for the assistant's next turn\")\n : t('Send message')\n }\n />\n </div>\n ) : (\n <button\n className=\"devic-input-btn devic-send-btn\"\n onClick={handleSend}\n disabled={inputDisabled || !hasContent}\n type=\"button\"\n title={\n isProcessing\n ? t(\"Queue this message for the assistant's next turn\")\n : t('Send message')\n }\n >\n <SendIcon />\n </button>\n ))}\n </>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Live equalizer rendered from the recording amplitude levels (0..1 per bar).\n * When paused, bars collapse to a flat baseline.\n */\nfunction Equalizer({\n levels,\n paused,\n}: {\n levels: number[];\n paused: boolean;\n}): JSX.Element {\n return (\n <div className=\"devic-equalizer\" aria-hidden=\"true\" data-paused={paused}>\n {levels.map((level, i) => (\n <span\n key={i}\n className=\"devic-equalizer-bar\"\n style={{ height: `${Math.max(10, Math.round((paused ? 0 : level) * 100))}%` }}\n />\n ))}\n </div>\n );\n}\n\n// Geometry for the auto-stop ring drawn around the confirm button.\nconst AUTOSTOP_RING_R = 18;\nconst AUTOSTOP_RING_C = 2 * Math.PI * AUTOSTOP_RING_R;\n\n/**\n * Inverted circular progress drawn around the confirm button. Driven by\n * `progress` (1 → 0): a full ring that drains to empty over the countdown.\n */\nfunction AutoStopRing({ progress }: { progress: number }): JSX.Element {\n return (\n <svg className=\"devic-autostop-ring\" viewBox=\"0 0 40 40\" aria-hidden=\"true\">\n <circle\n className=\"devic-autostop-ring-track\"\n cx=\"20\"\n cy=\"20\"\n r={AUTOSTOP_RING_R}\n />\n <circle\n className=\"devic-autostop-ring-progress\"\n cx=\"20\"\n cy=\"20\"\n r={AUTOSTOP_RING_R}\n style={{\n strokeDasharray: AUTOSTOP_RING_C,\n strokeDashoffset: AUTOSTOP_RING_C * (1 - progress),\n }}\n />\n </svg>\n );\n}\n\n/**\n * Draining ring around the send icon during the handoff pending countdown.\n * Visually distinct from the auto-stop ring (slate→primary track, larger).\n */\nfunction SendCountdownRing({ progress }: { progress: number }): JSX.Element {\n return (\n <svg className=\"devic-handoff-ring\" viewBox=\"0 0 44 44\" aria-hidden=\"true\">\n <circle className=\"devic-handoff-ring-track\" cx=\"22\" cy=\"22\" r={AUTOSTOP_RING_R} />\n <circle\n className=\"devic-handoff-ring-progress\"\n cx=\"22\"\n cy=\"22\"\n r={AUTOSTOP_RING_R}\n style={{\n strokeDasharray: AUTOSTOP_RING_C,\n strokeDashoffset: AUTOSTOP_RING_C * (1 - progress),\n }}\n />\n </svg>\n );\n}\n\n/**\n * Filling ring drawn around the mic button while the user presses and holds to\n * arm hands-free. Driven by `progress` (0 → 1): an empty ring that fills\n * clockwise over the hold duration. Inverse of the draining auto-stop ring.\n */\nfunction HoldRing({ progress }: { progress: number }): JSX.Element {\n return (\n <svg className=\"devic-mic-hold-ring\" viewBox=\"0 0 40 40\" aria-hidden=\"true\">\n <circle\n className=\"devic-mic-hold-ring-track\"\n cx=\"20\"\n cy=\"20\"\n r={AUTOSTOP_RING_R}\n />\n <circle\n className=\"devic-mic-hold-ring-progress\"\n cx=\"20\"\n cy=\"20\"\n r={AUTOSTOP_RING_R}\n style={{\n strokeDasharray: AUTOSTOP_RING_C,\n strokeDashoffset: AUTOSTOP_RING_C * (1 - progress),\n }}\n />\n </svg>\n );\n}\n\n/** Formats milliseconds as m:ss. */\nfunction formatDuration(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${minutes}:${seconds.toString().padStart(2, '0')}`;\n}\n\n/**\n * Attach icon\n */\nfunction AttachIcon(): JSX.Element {\n return (\n <svg\n width=\"20\"\n height=\"20\"\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=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\" />\n </svg>\n );\n}\n\n/**\n * Send icon\n */\nfunction SendIcon(): JSX.Element {\n return (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\" />\n </svg>\n );\n}\n\n/**\n * File icon\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 * Microphone icon\n */\nfunction MicIcon(): JSX.Element {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 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 <line x1=\"8\" y1=\"23\" x2=\"16\" y2=\"23\" />\n </svg>\n );\n}\n\n/**\n * Pause icon (two bars)\n */\nfunction PauseIcon(): JSX.Element {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n </svg>\n );\n}\n\n/**\n * Play icon (triangle)\n */\nfunction PlayIcon(): JSX.Element {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n );\n}\n\n/**\n * Check icon (confirm)\n */\nfunction CheckIcon(): JSX.Element {\n return (\n <svg\n width=\"18\"\n height=\"18\"\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\n/**\n * Close icon (cancel)\n */\nfunction CloseIcon(): JSX.Element {\n return (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\n/**\n * Stop icon (square)\n */\nfunction StopIcon(): JSX.Element {\n return (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"2\" />\n </svg>\n );\n}\n\n/**\n * Waiting icon (clock)\n */\nfunction WaitingIcon(): 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=\"10\" />\n <polyline points=\"12,6 12,12 16,14\" />\n </svg>\n );\n}\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
1
  import type { ChatMessagesProps } from "./ChatDrawer.types";
2
2
  import "../Feedback/Feedback.css";
3
- export declare function ChatMessages({ messages, allMessages, isLoading, welcomeMessage, suggestedMessages, onSuggestedClick, toolRenderers, toolIcons, loadingIndicator, showFeedback, feedbackMap, onFeedback, handedOffSubThreadId, onHandoffCompleted, handoffWidgetRenderer, toolGroups, userMessageRenderer, assistantMessageRenderer, apiKey, baseUrl, pollingInterval, pendingInlineWidgets, onSubmitWidget, onCancelWidget, recalledMemories, recalledMemoriesRenderer, compactions, compaction, compactionRenderer, expandableCompaction, }: ChatMessagesProps): JSX.Element;
3
+ export declare function ChatMessages({ messages, allMessages, isLoading, welcomeMessage, suggestedMessages, onSuggestedClick, toolRenderers, toolIcons, loadingIndicator, showFeedback, feedbackMap, onFeedback, handedOffSubThreadId, onHandoffCompleted, handoffWidgetRenderer, toolGroups, userMessageRenderer, assistantMessageRenderer, apiKey, baseUrl, pollingInterval, pendingInlineWidgets, onSubmitWidget, onCancelWidget, recalledMemories, recalledMemoriesRenderer, compactions, compaction, compactionRenderer, expandableCompaction, guardrailRenderer, }: ChatMessagesProps): JSX.Element;
@@ -4,11 +4,13 @@ import { useOptionalDevicContext } from '../../provider/DevicContext.js';
4
4
  import { DevicApiClient } from '../../api/client.js';
5
5
  import { segmentToolCalls } from '../../utils/toolGroups.js';
6
6
  import Markdown from 'markdown-to-jsx';
7
+ import { useTranslations } from '../../i18n/useTranslations.js';
7
8
  import { MessageActions } from '../Feedback/MessageActions.js';
8
9
  import { HandoffSubagentWidget } from './HandoffSubagentWidget.js';
9
10
  import { ReferenceChip } from './ReferenceChip.js';
10
11
  import { RecalledMemoriesWidget } from './RecalledMemoriesWidget.js';
11
12
  import { CompactionWidget } from './CompactionWidget.js';
13
+ import { GuardrailNotice } from './GuardrailNotice.js';
12
14
  import { normalizeMessageFile } from '../../api/types.js';
13
15
  import { parsePastedBlocks, pastedPreview, pastedLineCount } from './pastedText.js';
14
16
 
@@ -18,6 +20,25 @@ import { parsePastedBlocks, pastedPreview, pastedLineCount } from './pastedText.
18
20
  // instead of a tool activity line. Agents have a same-named tool with a
19
21
  // different shape, but their timeline does not go through this component.
20
22
  const FINISH_EXECUTION_TOOL = "finish_execution";
23
+ // Role of the message the backend appends when a guardrail stops a turn. It is
24
+ // not something anyone said, so it renders as a notice rather than a bubble.
25
+ const GUARDRAIL_ROLE = "guard_rail";
26
+ /**
27
+ * `content.message` is typed as a string, but it does not always arrive as
28
+ * one: a tripped guardrail puts the whole provider result object there. Every
29
+ * text path downstream — the reference prefix, the pasted blocks, markdown —
30
+ * assumes a string and throws on anything else, taking the drawer with it.
31
+ * Read the field through here so a bad shape renders as nothing instead.
32
+ */
33
+ function readMessageText(message) {
34
+ const raw = message.content?.message;
35
+ return typeof raw === "string" ? raw : undefined;
36
+ }
37
+ /** The structured guardrail result, when one was sent instead of a sentence. */
38
+ function guardrailPayload(message) {
39
+ const raw = message.content?.message;
40
+ return raw && typeof raw === "object" ? raw : undefined;
41
+ }
21
42
  /**
22
43
  * Format timestamp to readable time
23
44
  */
@@ -43,6 +64,7 @@ function PauseGlyph() {
43
64
  * never triggers extra requests until the user actually wants to listen.
44
65
  */
45
66
  function TranscriptPlayback({ transcriptId, apiKey, baseUrl, }) {
67
+ const t = useTranslations();
46
68
  const devicContext = useOptionalDevicContext();
47
69
  const getTenantSession = devicContext?.getTenantSession;
48
70
  const onSessionExpired = devicContext?.onSessionExpired;
@@ -65,7 +87,7 @@ function TranscriptPlayback({ transcriptId, apiKey, baseUrl, }) {
65
87
  let url = audioUrlRef.current;
66
88
  if (!url) {
67
89
  if (!apiKey && !getTenantSession) {
68
- setError("Unavailable");
90
+ setError(t("Unavailable"));
69
91
  return null;
70
92
  }
71
93
  setIsLoading(true);
@@ -82,7 +104,7 @@ function TranscriptPlayback({ transcriptId, apiKey, baseUrl, }) {
82
104
  audioUrlRef.current = url;
83
105
  }
84
106
  catch {
85
- setError("Audio unavailable");
107
+ setError(t("Audio unavailable"));
86
108
  return null;
87
109
  }
88
110
  finally {
@@ -90,7 +112,7 @@ function TranscriptPlayback({ transcriptId, apiKey, baseUrl, }) {
90
112
  }
91
113
  }
92
114
  if (!url) {
93
- setError("Audio unavailable");
115
+ setError(t("Audio unavailable"));
94
116
  return null;
95
117
  }
96
118
  const audio = new Audio(url);
@@ -98,7 +120,7 @@ function TranscriptPlayback({ transcriptId, apiKey, baseUrl, }) {
98
120
  audio.onpause = () => setIsPlaying(false);
99
121
  audio.onended = () => setIsPlaying(false);
100
122
  audio.onerror = () => {
101
- setError("Playback failed");
123
+ setError(t("Playback failed"));
102
124
  setIsPlaying(false);
103
125
  };
104
126
  audioRef.current = audio;
@@ -115,11 +137,11 @@ function TranscriptPlayback({ transcriptId, apiKey, baseUrl, }) {
115
137
  await audio.play();
116
138
  }
117
139
  catch {
118
- setError("Playback failed");
140
+ setError(t("Playback failed"));
119
141
  }
120
142
  }
121
143
  };
122
- return (jsxs("div", { className: "devic-transcript-playback", "data-playing": isPlaying ? "true" : "false", title: "Dictated by voice", children: [jsx("button", { type: "button", className: "devic-transcript-btn", onClick: toggle, disabled: isLoading, "aria-label": isPlaying ? "Pause recording" : "Play recording", children: isLoading ? (jsx("span", { className: "devic-transcript-spinner", "aria-hidden": "true" })) : isPlaying ? (jsx(PauseGlyph, {})) : (jsx(PlayGlyph, {})) }), jsx("span", { className: "devic-transcript-icon", "aria-hidden": "true", children: jsx(MicGlyph, {}) }), jsx("span", { className: "devic-transcript-label", children: error || "Voice message" })] }));
144
+ return (jsxs("div", { className: "devic-transcript-playback", "data-playing": isPlaying ? "true" : "false", title: t("Dictated by voice"), children: [jsx("button", { type: "button", className: "devic-transcript-btn", onClick: toggle, disabled: isLoading, "aria-label": isPlaying ? t("Pause recording") : t("Play recording"), children: isLoading ? (jsx("span", { className: "devic-transcript-spinner", "aria-hidden": "true" })) : isPlaying ? (jsx(PauseGlyph, {})) : (jsx(PlayGlyph, {})) }), jsx("span", { className: "devic-transcript-icon", "aria-hidden": "true", children: jsx(MicGlyph, {}) }), jsx("span", { className: "devic-transcript-label", children: error || t("Voice message") })] }));
123
145
  }
124
146
  /**
125
147
  * Groups consecutive tool-call assistant messages (no text content)
@@ -151,8 +173,12 @@ function groupMessages(messages, isLoading) {
151
173
  // a tool activity line would just duplicate that bubble with plumbing.
152
174
  const visibleToolCalls = (msg.tool_calls || []).filter((toolCall) => toolCall.function?.name !== FINISH_EXECUTION_TOOL);
153
175
  const hasToolCalls = visibleToolCalls.length > 0;
154
- const hasText = !!msg.content?.message;
176
+ const hasText = !!readMessageText(msg);
155
177
  const hasFiles = msg.content?.files && msg.content.files.length > 0;
178
+ // A guardrail message is worth showing whatever its content turned out to
179
+ // be: a turn that was stopped should say so, and the payload is often an
180
+ // object rather than the text `hasText` looks for.
181
+ const isGuardrail = msg.role === GUARDRAIL_ROLE;
156
182
  if (hasToolCalls) {
157
183
  // If message has both text and tool_calls, show text first
158
184
  if (hasText || hasFiles) {
@@ -175,7 +201,7 @@ function groupMessages(messages, isLoading) {
175
201
  .slice(i)
176
202
  .some((m) => (m.role === "assistant" && m.content?.message) || m.role === "user");
177
203
  flushToolGroup(isLoading && !remainingMeaningful);
178
- if (hasText || hasFiles) {
204
+ if (hasText || hasFiles || isGuardrail) {
179
205
  result.push({ type: "message", message: msg });
180
206
  }
181
207
  }
@@ -188,6 +214,7 @@ function groupMessages(messages, isLoading) {
188
214
  * Collapsible tool actions group
189
215
  */
190
216
  function ToolGroup({ toolMessages, isActive, allMessages, toolRenderers, toolIcons, toolGroups, handedOffSubThreadId, onHandoffCompleted, handoffWidgetRenderer, apiKey, baseUrl, pollingInterval, }) {
217
+ const t = useTranslations();
191
218
  const [isCollapsed, setIsCollapsed] = useState(false);
192
219
  const shouldCollapse = toolMessages.length > 3 && !isActive;
193
220
  // Auto-collapse when transitioning from active to completed
@@ -202,7 +229,9 @@ function ToolGroup({ toolMessages, isActive, allMessages, toolRenderers, toolIco
202
229
  const renderToolItem = (msg, opts) => {
203
230
  const toolCall = msg.tool_calls?.[0];
204
231
  const toolName = toolCall?.function?.name;
205
- const summaryText = msg.summary || toolName || (opts.active ? "Processing..." : "Completed");
232
+ const summaryText = msg.summary ||
233
+ toolName ||
234
+ (opts.active ? t("Processing...") : t("Completed"));
206
235
  // Render HandoffSubagentWidget for hand_off_subagent tool calls
207
236
  if (toolName === "hand_off_subagent" && toolCall && allMessages) {
208
237
  const subThreadId = extractSubThreadId(toolCall.id, allMessages, handedOffSubThreadId);
@@ -315,7 +344,8 @@ function extractSubThreadId(toolCallId, allMessages, handedOffSubThreadId) {
315
344
  // Fall back to active handoff subthread ID
316
345
  return handedOffSubThreadId || null;
317
346
  }
318
- function ChatMessages({ messages, allMessages, isLoading, welcomeMessage, suggestedMessages, onSuggestedClick, toolRenderers, toolIcons, loadingIndicator, showFeedback = true, feedbackMap, onFeedback, handedOffSubThreadId, onHandoffCompleted, handoffWidgetRenderer, toolGroups, userMessageRenderer, assistantMessageRenderer, apiKey, baseUrl, pollingInterval, pendingInlineWidgets, onSubmitWidget, onCancelWidget, recalledMemories, recalledMemoriesRenderer, compactions, compaction, compactionRenderer, expandableCompaction, }) {
347
+ function ChatMessages({ messages, allMessages, isLoading, welcomeMessage, suggestedMessages, onSuggestedClick, toolRenderers, toolIcons, loadingIndicator, showFeedback = true, feedbackMap, onFeedback, handedOffSubThreadId, onHandoffCompleted, handoffWidgetRenderer, toolGroups, userMessageRenderer, assistantMessageRenderer, apiKey, baseUrl, pollingInterval, pendingInlineWidgets, onSubmitWidget, onCancelWidget, recalledMemories, recalledMemoriesRenderer, compactions, compaction, compactionRenderer, expandableCompaction, guardrailRenderer, }) {
348
+ const t = useTranslations();
319
349
  const containerRef = useRef(null);
320
350
  const prevLengthRef = useRef(messages.length);
321
351
  // Anchor each recall record to the message that brought it in: the
@@ -409,7 +439,17 @@ function ChatMessages({ messages, allMessages, isLoading, welcomeMessage, sugges
409
439
  return (jsxs(React.Fragment, { children: [jsx(ToolGroup, { toolMessages: item.toolMessages, isActive: item.isActive, allMessages: allMessages, toolRenderers: toolRenderers, toolIcons: toolIcons, toolGroups: toolGroups, handedOffSubThreadId: handedOffSubThreadId, onHandoffCompleted: onHandoffCompleted, handoffWidgetRenderer: handoffWidgetRenderer, apiKey: apiKey, baseUrl: baseUrl, pollingInterval: pollingInterval }), groupRecalls.length > 0 && (jsx(RecalledMemoriesWidget, { records: groupRecalls, isLoading: isLoading, renderer: recalledMemoriesRenderer })), renderCompactions(groupCompactions)] }, `tg-${item.toolMessages[0].uid}`));
410
440
  }
411
441
  const message = item.message;
412
- const rawText = message.content?.message;
442
+ // A stopped turn is not a bubble from either side: rendering it as one
443
+ // sent it down the user-message path, which parses its text and threw
444
+ // on the object a guardrail actually sends.
445
+ if (message.role === GUARDRAIL_ROLE) {
446
+ const noticeProps = {
447
+ payload: guardrailPayload(message),
448
+ text: readMessageText(message),
449
+ };
450
+ return (jsx(React.Fragment, { children: guardrailRenderer ? (guardrailRenderer(noticeProps)) : (jsx(GuardrailNotice, { ...noticeProps })) }, message.uid));
451
+ }
452
+ const rawText = readMessageText(message);
413
453
  const hasFiles = message.content?.files && message.content.files.length > 0;
414
454
  const isAssistant = message.role === "assistant";
415
455
  const currentFeedback = feedbackMap?.get(message.uid) || "none";
@@ -446,7 +486,7 @@ function ChatMessages({ messages, allMessages, isLoading, welcomeMessage, sugges
446
486
  })) : (jsx(Markdown, { options: { overrides: markdownOverrides }, children: bodyText }))) : null, hasFiles && (jsx("div", { className: "devic-message-files", children: message.content.files.map((raw, fileIdx) => {
447
487
  const file = normalizeMessageFile(raw);
448
488
  return file.type === "image" && file.url ? (jsx("a", { className: "devic-message-file-image", href: file.url, target: "_blank", rel: "noreferrer", children: jsx("img", { src: file.url, alt: file.name }) }, fileIdx)) : (jsxs("div", { className: "devic-message-file", children: [jsx(FileIcon, {}), jsx("span", { children: file.name })] }, fileIdx));
449
- }) })), !isAssistant && message.transcriptId && (jsx(TranscriptPlayback, { transcriptId: message.transcriptId, apiKey: apiKey, baseUrl: baseUrl }))] }), jsxs("div", { className: "devic-message-footer", children: [message.queued && (jsxs("span", { className: "devic-message-queued-label", children: [jsx(QueuedIcon, {}), "Queued"] })), jsx("span", { className: "devic-message-time", children: formatTime(message.timestamp) }), isAssistant && showFeedback && onFeedback && (jsx(MessageActions, { messageId: message.uid, messageContent: messageText, currentFeedback: currentFeedback, onFeedback: onFeedback, showCopy: true, showFeedback: true }))] })] }), messageRecalls.length > 0 && (jsx(RecalledMemoriesWidget, { records: messageRecalls, isLoading: isLoading, renderer: recalledMemoriesRenderer })), renderCompactions(messageCompactions)] }, message.uid));
489
+ }) })), !isAssistant && message.transcriptId && (jsx(TranscriptPlayback, { transcriptId: message.transcriptId, apiKey: apiKey, baseUrl: baseUrl }))] }), jsxs("div", { className: "devic-message-footer", children: [message.queued && (jsxs("span", { className: "devic-message-queued-label", children: [jsx(QueuedIcon, {}), t("Queued")] })), jsx("span", { className: "devic-message-time", children: formatTime(message.timestamp) }), isAssistant && showFeedback && onFeedback && (jsx(MessageActions, { messageId: message.uid, messageContent: messageText, currentFeedback: currentFeedback, onFeedback: onFeedback, showCopy: true, showFeedback: true }))] })] }), messageRecalls.length > 0 && (jsx(RecalledMemoriesWidget, { records: messageRecalls, isLoading: isLoading, renderer: recalledMemoriesRenderer })), renderCompactions(messageCompactions)] }, message.uid));
450
490
  }), isLoading && pendingRecalls.length > 0 && (jsx(RecalledMemoriesWidget, { records: pendingRecalls, isLoading: isLoading, renderer: recalledMemoriesRenderer })), renderCompactions(orphanCompactions), compaction?.state === "running" && (jsx(CompactionWidget, { checkpoint: null, activity: compaction, renderer: compactionRenderer })), pendingInlineWidgets && pendingInlineWidgets.length > 0 && (jsx("div", { className: "devic-inline-widgets", children: pendingInlineWidgets.map((wc) => {
451
491
  const WidgetComponent = wc.widget.component;
452
492
  return (jsx("div", { className: "devic-inline-widget", "data-tool-name": wc.toolName, children: jsx(WidgetComponent, { toolCall: wc.toolCall, params: wc.params, submit: (response) => onSubmitWidget?.(wc.toolCall.id, response), cancel: (reason) => onCancelWidget?.(wc.toolCall.id, reason) }) }, wc.toolCall.id));
@@ -492,8 +532,9 @@ function parseReferencedPrefix(content) {
492
532
  * expandable to read the whole thing without leaving the thread.
493
533
  */
494
534
  function PastedBlockCard({ block }) {
535
+ const t = useTranslations();
495
536
  const [expanded, setExpanded] = useState(false);
496
- return (jsx("div", { className: "devic-pasted-card", "data-expanded": expanded ? "true" : "false", children: jsxs("button", { type: "button", className: "devic-pasted-card-toggle", onClick: () => setExpanded((prev) => !prev), "aria-expanded": expanded, children: [expanded ? (jsx("pre", { className: "devic-pasted-card-full", children: block.text })) : (jsx("p", { className: "devic-pasted-card-preview", children: pastedPreview(block.text) })), jsxs("span", { className: "devic-pasted-card-footer", children: [jsx("span", { className: "devic-pasted-card-badge", children: "PASTED" }), jsxs("span", { className: "devic-pasted-card-meta", children: [pastedLineCount(block.text), " lines \u00B7 ", expanded ? "collapse" : "expand"] })] })] }) }));
537
+ return (jsx("div", { className: "devic-pasted-card", "data-expanded": expanded ? "true" : "false", children: jsxs("button", { type: "button", className: "devic-pasted-card-toggle", onClick: () => setExpanded((prev) => !prev), "aria-expanded": expanded, children: [expanded ? (jsx("pre", { className: "devic-pasted-card-full", children: block.text })) : (jsx("p", { className: "devic-pasted-card-preview", children: pastedPreview(block.text) })), jsxs("span", { className: "devic-pasted-card-footer", children: [jsx("span", { className: "devic-pasted-card-badge", children: t("PASTED") }), jsxs("span", { className: "devic-pasted-card-meta", children: [t("{count} lines", { count: pastedLineCount(block.text) }), " \u00B7", " ", expanded ? t("collapse") : t("expand")] })] })] }) }));
497
538
  }
498
539
 
499
540
  export { ChatMessages };