(
messageParam?: string,
isVoiceInput = false,
files?: Array<{
id: string
name: string
size: number
type: string
file: File
dataUrl?: string
}>
)
| 199 | }, [isStreamingResponse]) |
| 200 | |
| 201 | const handleSendMessage = async ( |
| 202 | messageParam?: string, |
| 203 | isVoiceInput = false, |
| 204 | files?: Array<{ |
| 205 | id: string |
| 206 | name: string |
| 207 | size: number |
| 208 | type: string |
| 209 | file: File |
| 210 | dataUrl?: string |
| 211 | }> |
| 212 | ) => { |
| 213 | const messageToSend = messageParam ?? inputValue |
| 214 | if ((!messageToSend.trim() && (!files || files.length === 0)) || isLoading) return |
| 215 | |
| 216 | logger.info('Sending message:', { |
| 217 | messageToSend, |
| 218 | isVoiceInput, |
| 219 | conversationId, |
| 220 | filesCount: files?.length, |
| 221 | }) |
| 222 | |
| 223 | setUserHasScrolled(false) |
| 224 | |
| 225 | const userMessage: ChatMessage = { |
| 226 | id: generateId(), |
| 227 | content: messageToSend || (files && files.length > 0 ? `Sent ${files.length} file(s)` : ''), |
| 228 | type: 'user', |
| 229 | timestamp: new Date(), |
| 230 | attachments: files?.map((file) => ({ |
| 231 | id: file.id, |
| 232 | name: file.name, |
| 233 | type: file.type, |
| 234 | size: file.size, |
| 235 | dataUrl: file.dataUrl || '', |
| 236 | })), |
| 237 | } |
| 238 | |
| 239 | setMessages((prev) => [...prev, userMessage]) |
| 240 | setInputValue('') |
| 241 | setIsLoading(true) |
| 242 | |
| 243 | setTimeout(() => { |
| 244 | scrollToMessage(userMessage.id, true) |
| 245 | }, 100) |
| 246 | |
| 247 | const abortController = new AbortController() |
| 248 | const timeoutId = setTimeout(() => { |
| 249 | abortController.abort() |
| 250 | }, CHAT_REQUEST_TIMEOUT_MS) |
| 251 | |
| 252 | try { |
| 253 | const payloadFiles = |
| 254 | files && files.length > 0 |
| 255 | ? await Promise.all( |
| 256 | files.map(async (file) => ({ |
| 257 | name: file.name, |
| 258 | size: file.size, |
no test coverage detected