(props: UseMessageSenderProps)
| 46 | } |
| 47 | |
| 48 | export function useMessageSender(props: UseMessageSenderProps): UseMessageSenderReturn { |
| 49 | const { |
| 50 | currentSessionId, |
| 51 | contexts, |
| 52 | onClearContexts, |
| 53 | onSuccess, |
| 54 | onExitTemplateMode, |
| 55 | currentAgentType, |
| 56 | } = props; |
| 57 | |
| 58 | const sendMessage = useCallback(async ( |
| 59 | message: string, |
| 60 | options?: { |
| 61 | displayMessage?: string; |
| 62 | } |
| 63 | ) => { |
| 64 | if (!message.trim()) { |
| 65 | return; |
| 66 | } |
| 67 | |
| 68 | const trimmedMessage = message.trim(); |
| 69 | // Strip inline `#img:<name>` tags from the AI-bound text. The rich text |
| 70 | // editor inserts these when an image is pasted, but the named file does |
| 71 | // not exist on disk; image bytes are sent out-of-band via `imageContexts` |
| 72 | // below. Leaving the placeholder in the prompt misleads the model into |
| 73 | // looking up a non-existent file. The display message keeps the tag so |
| 74 | // the UI can still render the inline pill. |
| 75 | const stripImageTags = (text: string): string => |
| 76 | text |
| 77 | .replace(/#img:[^\s\n]+\s?/g, '') |
| 78 | .replace(/[ \t]+\n/g, '\n') |
| 79 | .replace(/\n{3,}/g, '\n\n') |
| 80 | .trim(); |
| 81 | const aiTrimmedMessage = stripImageTags(trimmedMessage); |
| 82 | let sessionId = currentSessionId; |
| 83 | log.debug('Send message initiated', { |
| 84 | textLength: trimmedMessage.length, |
| 85 | contextCount: contexts.length, |
| 86 | hasSession: !!sessionId, |
| 87 | agentType: currentAgentType || 'agentic', |
| 88 | }); |
| 89 | |
| 90 | try { |
| 91 | const flowChatManager = FlowChatManager.getInstance(); |
| 92 | let agentTypeForSend = currentAgentType || 'agentic'; |
| 93 | |
| 94 | if (!sessionId) { |
| 95 | const agentType = currentAgentType || 'agentic'; |
| 96 | |
| 97 | sessionId = await flowChatManager.createChatSession({}, agentType); |
| 98 | agentTypeForSend = |
| 99 | FlowChatManager.getInstance().getFlowChatState().sessions.get(sessionId)?.mode || |
| 100 | agentType; |
| 101 | log.debug('Session created', { sessionId, agentType, effectiveAgentType: agentTypeForSend }); |
| 102 | } else { |
| 103 | log.debug('Reusing existing session', { sessionId }); |
| 104 | } |
| 105 |
no test coverage detected