mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-30 18:05:55 +01:00 
			
		
		
		
	feat(llm): use ckeditor for text input area for mention support instead of textinput
This commit is contained in:
		| @@ -5,6 +5,7 @@ import BasicWidget from "../basic_widget.js"; | |||||||
| import toastService from "../../services/toast.js"; | import toastService from "../../services/toast.js"; | ||||||
| import appContext from "../../components/app_context.js"; | import appContext from "../../components/app_context.js"; | ||||||
| import server from "../../services/server.js"; | import server from "../../services/server.js"; | ||||||
|  | import noteAutocompleteService from "../../services/note_autocomplete.js"; | ||||||
|  |  | ||||||
| import { TPL, addMessageToChat, showSources, hideSources, showLoadingIndicator, hideLoadingIndicator } from "./ui.js"; | import { TPL, addMessageToChat, showSources, hideSources, showLoadingIndicator, hideLoadingIndicator } from "./ui.js"; | ||||||
| import { formatMarkdown } from "./utils.js"; | import { formatMarkdown } from "./utils.js"; | ||||||
| @@ -13,13 +14,16 @@ import { extractInChatToolSteps } from "./message_processor.js"; | |||||||
| import { validateEmbeddingProviders } from "./validation.js"; | import { validateEmbeddingProviders } from "./validation.js"; | ||||||
| import type { MessageData, ToolExecutionStep, ChatData } from "./types.js"; | import type { MessageData, ToolExecutionStep, ChatData } from "./types.js"; | ||||||
| import { formatCodeBlocks } from "../../services/syntax_highlight.js"; | import { formatCodeBlocks } from "../../services/syntax_highlight.js"; | ||||||
|  | import { ClassicEditor, type CKTextEditor, type MentionFeed } from "@triliumnext/ckeditor5"; | ||||||
|  | import type { Suggestion } from "../../services/note_autocomplete.js"; | ||||||
|  |  | ||||||
| import "../../stylesheets/llm_chat.css"; | import "../../stylesheets/llm_chat.css"; | ||||||
|  |  | ||||||
| export default class LlmChatPanel extends BasicWidget { | export default class LlmChatPanel extends BasicWidget { | ||||||
|     private noteContextChatMessages!: HTMLElement; |     private noteContextChatMessages!: HTMLElement; | ||||||
|     private noteContextChatForm!: HTMLFormElement; |     private noteContextChatForm!: HTMLFormElement; | ||||||
|     private noteContextChatInput!: HTMLTextAreaElement; |     private noteContextChatInput!: HTMLElement; | ||||||
|  |     private noteContextChatInputEditor!: CKTextEditor; | ||||||
|     private noteContextChatSendButton!: HTMLButtonElement; |     private noteContextChatSendButton!: HTMLButtonElement; | ||||||
|     private chatContainer!: HTMLElement; |     private chatContainer!: HTMLElement; | ||||||
|     private loadingIndicator!: HTMLElement; |     private loadingIndicator!: HTMLElement; | ||||||
| @@ -104,7 +108,7 @@ export default class LlmChatPanel extends BasicWidget { | |||||||
|         const element = this.$widget[0]; |         const element = this.$widget[0]; | ||||||
|         this.noteContextChatMessages = element.querySelector('.note-context-chat-messages') as HTMLElement; |         this.noteContextChatMessages = element.querySelector('.note-context-chat-messages') as HTMLElement; | ||||||
|         this.noteContextChatForm = element.querySelector('.note-context-chat-form') as HTMLFormElement; |         this.noteContextChatForm = element.querySelector('.note-context-chat-form') as HTMLFormElement; | ||||||
|         this.noteContextChatInput = element.querySelector('.note-context-chat-input') as HTMLTextAreaElement; |         this.noteContextChatInput = element.querySelector('.note-context-chat-input') as HTMLElement; | ||||||
|         this.noteContextChatSendButton = element.querySelector('.note-context-chat-send-button') as HTMLButtonElement; |         this.noteContextChatSendButton = element.querySelector('.note-context-chat-send-button') as HTMLButtonElement; | ||||||
|         this.chatContainer = element.querySelector('.note-context-chat-container') as HTMLElement; |         this.chatContainer = element.querySelector('.note-context-chat-container') as HTMLElement; | ||||||
|         this.loadingIndicator = element.querySelector('.loading-indicator') as HTMLElement; |         this.loadingIndicator = element.querySelector('.loading-indicator') as HTMLElement; | ||||||
| @@ -124,15 +128,81 @@ export default class LlmChatPanel extends BasicWidget { | |||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|  |         // Initialize CKEditor with mention support (async) | ||||||
|  |         this.initializeCKEditor().then(() => { | ||||||
|             this.initializeEventListeners(); |             this.initializeEventListeners(); | ||||||
|  |         }).catch(error => { | ||||||
|  |             console.error('Failed to initialize CKEditor, falling back to basic event listeners:', error); | ||||||
|  |             this.initializeBasicEventListeners(); | ||||||
|  |         }); | ||||||
|  |  | ||||||
|         return this.$widget; |         return this.$widget; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private async initializeCKEditor() { | ||||||
|  |         const mentionSetup: MentionFeed[] = [ | ||||||
|  |             { | ||||||
|  |                 marker: "@", | ||||||
|  |                 feed: (queryText: string) => noteAutocompleteService.autocompleteSourceForCKEditor(queryText), | ||||||
|  |                 itemRenderer: (item) => { | ||||||
|  |                     const suggestion = item as Suggestion; | ||||||
|  |                     const itemElement = document.createElement("button"); | ||||||
|  |                     itemElement.innerHTML = `${suggestion.highlightedNotePathTitle} `; | ||||||
|  |                     return itemElement; | ||||||
|  |                 }, | ||||||
|  |                 minimumCharacters: 0 | ||||||
|  |             } | ||||||
|  |         ]; | ||||||
|  |  | ||||||
|  |         this.noteContextChatInputEditor = await ClassicEditor.create(this.noteContextChatInput, { | ||||||
|  |             toolbar: { | ||||||
|  |                 items: [] // No toolbar for chat input | ||||||
|  |             }, | ||||||
|  |             placeholder: this.noteContextChatInput.getAttribute('data-placeholder') || 'Enter your message...', | ||||||
|  |             mention: { | ||||||
|  |                 feeds: mentionSetup | ||||||
|  |             }, | ||||||
|  |             licenseKey: "GPL" | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         // Set minimal height | ||||||
|  |         const editorElement = this.noteContextChatInputEditor.ui.getEditableElement(); | ||||||
|  |         if (editorElement) { | ||||||
|  |             editorElement.style.minHeight = '60px'; | ||||||
|  |             editorElement.style.maxHeight = '200px'; | ||||||
|  |             editorElement.style.overflowY = 'auto'; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Set up keybindings after editor is ready | ||||||
|  |         this.setupEditorKeyBindings(); | ||||||
|  |  | ||||||
|  |         console.log('CKEditor initialized successfully for LLM chat input'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private initializeBasicEventListeners() { | ||||||
|  |         // Fallback event listeners for when CKEditor fails to initialize | ||||||
|  |         this.noteContextChatForm.addEventListener('submit', (e) => { | ||||||
|  |             e.preventDefault(); | ||||||
|  |             // In fallback mode, the noteContextChatInput should contain a textarea | ||||||
|  |             const textarea = this.noteContextChatInput.querySelector('textarea'); | ||||||
|  |             if (textarea) { | ||||||
|  |                 const content = textarea.value; | ||||||
|  |                 this.sendMessage(content); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     cleanup() { |     cleanup() { | ||||||
|         console.log(`LlmChatPanel cleanup called, removing any active WebSocket subscriptions`); |         console.log(`LlmChatPanel cleanup called, removing any active WebSocket subscriptions`); | ||||||
|         this._messageHandler = null; |         this._messageHandler = null; | ||||||
|         this._messageHandlerId = null; |         this._messageHandlerId = null; | ||||||
|  |  | ||||||
|  |         // Clean up CKEditor instance | ||||||
|  |         if (this.noteContextChatInputEditor) { | ||||||
|  |             this.noteContextChatInputEditor.destroy().catch(error => { | ||||||
|  |                 console.error('Error destroying CKEditor:', error); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -531,18 +601,31 @@ export default class LlmChatPanel extends BasicWidget { | |||||||
|     private async sendMessage(content: string) { |     private async sendMessage(content: string) { | ||||||
|         if (!content.trim()) return; |         if (!content.trim()) return; | ||||||
|  |  | ||||||
|  |         // Extract mentions from the content if using CKEditor | ||||||
|  |         let mentions: Array<{noteId: string; title: string; notePath: string}> = []; | ||||||
|  |         let plainTextContent = content; | ||||||
|  |  | ||||||
|  |         if (this.noteContextChatInputEditor) { | ||||||
|  |             const extracted = this.extractMentionsAndContent(content); | ||||||
|  |             mentions = extracted.mentions; | ||||||
|  |             plainTextContent = extracted.content; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         // Add the user message to the UI and data model |         // Add the user message to the UI and data model | ||||||
|         this.addMessageToChat('user', content); |         this.addMessageToChat('user', plainTextContent); | ||||||
|         this.messages.push({ |         this.messages.push({ | ||||||
|             role: 'user', |             role: 'user', | ||||||
|             content: content |             content: plainTextContent, | ||||||
|  |             mentions: mentions.length > 0 ? mentions : undefined | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         // Save the data immediately after a user message |         // Save the data immediately after a user message | ||||||
|         await this.saveCurrentData(); |         await this.saveCurrentData(); | ||||||
|  |  | ||||||
|         // Clear input and show loading state |         // Clear input and show loading state | ||||||
|         this.noteContextChatInput.value = ''; |         if (this.noteContextChatInputEditor) { | ||||||
|  |             this.noteContextChatInputEditor.setData(''); | ||||||
|  |         } | ||||||
|         showLoadingIndicator(this.loadingIndicator); |         showLoadingIndicator(this.loadingIndicator); | ||||||
|         this.hideSources(); |         this.hideSources(); | ||||||
|  |  | ||||||
| @@ -555,9 +638,10 @@ export default class LlmChatPanel extends BasicWidget { | |||||||
|  |  | ||||||
|             // Create the message parameters |             // Create the message parameters | ||||||
|             const messageParams = { |             const messageParams = { | ||||||
|                 content, |                 content: plainTextContent, | ||||||
|                 useAdvancedContext, |                 useAdvancedContext, | ||||||
|                 showThinking |                 showThinking, | ||||||
|  |                 mentions: mentions.length > 0 ? mentions : undefined | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             // Try websocket streaming (preferred method) |             // Try websocket streaming (preferred method) | ||||||
| @@ -621,7 +705,9 @@ export default class LlmChatPanel extends BasicWidget { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Clear input and show loading state |         // Clear input and show loading state | ||||||
|         this.noteContextChatInput.value = ''; |         if (this.noteContextChatInputEditor) { | ||||||
|  |             this.noteContextChatInputEditor.setData(''); | ||||||
|  |         } | ||||||
|         showLoadingIndicator(this.loadingIndicator); |         showLoadingIndicator(this.loadingIndicator); | ||||||
|         this.hideSources(); |         this.hideSources(); | ||||||
|  |  | ||||||
| @@ -1213,22 +1299,122 @@ export default class LlmChatPanel extends BasicWidget { | |||||||
|     private initializeEventListeners() { |     private initializeEventListeners() { | ||||||
|         this.noteContextChatForm.addEventListener('submit', (e) => { |         this.noteContextChatForm.addEventListener('submit', (e) => { | ||||||
|             e.preventDefault(); |             e.preventDefault(); | ||||||
|             const content = this.noteContextChatInput.value; |  | ||||||
|  |             let content = ''; | ||||||
|  |  | ||||||
|  |             if (this.noteContextChatInputEditor && this.noteContextChatInputEditor.getData) { | ||||||
|  |                 // Use CKEditor content | ||||||
|  |                 content = this.noteContextChatInputEditor.getData(); | ||||||
|  |             } else { | ||||||
|  |                 // Fallback: check if there's a textarea (fallback mode) | ||||||
|  |                 const textarea = this.noteContextChatInput.querySelector('textarea'); | ||||||
|  |                 if (textarea) { | ||||||
|  |                     content = textarea.value; | ||||||
|  |                 } else { | ||||||
|  |                     // Last resort: try to get text content from the div | ||||||
|  |                     content = this.noteContextChatInput.textContent || this.noteContextChatInput.innerText || ''; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (content.trim()) { | ||||||
|                 this.sendMessage(content); |                 this.sendMessage(content); | ||||||
|  |             } | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         // Add auto-resize functionality to the textarea |         // Handle Enter key (send on Enter, new line on Shift+Enter) via CKEditor | ||||||
|         this.noteContextChatInput.addEventListener('input', () => { |         // We'll set this up after CKEditor is initialized | ||||||
|             this.noteContextChatInput.style.height = 'auto'; |         this.setupEditorKeyBindings(); | ||||||
|             this.noteContextChatInput.style.height = `${this.noteContextChatInput.scrollHeight}px`; |     } | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         // Handle Enter key (send on Enter, new line on Shift+Enter) |     private setupEditorKeyBindings() { | ||||||
|         this.noteContextChatInput.addEventListener('keydown', (e) => { |         if (this.noteContextChatInputEditor && this.noteContextChatInputEditor.keystrokes) { | ||||||
|             if (e.key === 'Enter' && !e.shiftKey) { |             try { | ||||||
|                 e.preventDefault(); |                 this.noteContextChatInputEditor.keystrokes.set('Enter', (key, stop) => { | ||||||
|  |                     if (!key.shiftKey) { | ||||||
|  |                         stop(); | ||||||
|                         this.noteContextChatForm.dispatchEvent(new Event('submit')); |                         this.noteContextChatForm.dispatchEvent(new Event('submit')); | ||||||
|                     } |                     } | ||||||
|                 }); |                 }); | ||||||
|  |                 console.log('CKEditor keybindings set up successfully'); | ||||||
|  |             } catch (error) { | ||||||
|  |                 console.warn('Failed to set up CKEditor keybindings:', error); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Extract note mentions and content from CKEditor | ||||||
|  |      */ | ||||||
|  |     private extractMentionsAndContent(editorData: string): { content: string; mentions: Array<{noteId: string; title: string; notePath: string}> } { | ||||||
|  |         const mentions: Array<{noteId: string; title: string; notePath: string}> = []; | ||||||
|  |  | ||||||
|  |         // Parse the HTML content to extract mentions | ||||||
|  |         const tempDiv = document.createElement('div'); | ||||||
|  |         tempDiv.innerHTML = editorData; | ||||||
|  |  | ||||||
|  |         // Find all mention elements - CKEditor uses specific patterns for mentions | ||||||
|  |         // Look for elements with data-mention attribute or specific mention classes | ||||||
|  |         const mentionElements = tempDiv.querySelectorAll('[data-mention], .mention, span[data-id]'); | ||||||
|  |  | ||||||
|  |         mentionElements.forEach(mentionEl => { | ||||||
|  |             try { | ||||||
|  |                 // Try different ways to extract mention data based on CKEditor's format | ||||||
|  |                 let mentionData: any = null; | ||||||
|  |  | ||||||
|  |                 // Method 1: data-mention attribute (JSON format) | ||||||
|  |                 if (mentionEl.hasAttribute('data-mention')) { | ||||||
|  |                     mentionData = JSON.parse(mentionEl.getAttribute('data-mention') || '{}'); | ||||||
|  |                 } | ||||||
|  |                 // Method 2: data-id attribute (simple format) | ||||||
|  |                 else if (mentionEl.hasAttribute('data-id')) { | ||||||
|  |                     const dataId = mentionEl.getAttribute('data-id'); | ||||||
|  |                     const textContent = mentionEl.textContent || ''; | ||||||
|  |  | ||||||
|  |                     // Parse the dataId to extract note information | ||||||
|  |                     if (dataId && dataId.startsWith('@')) { | ||||||
|  |                         const cleanId = dataId.substring(1); // Remove the @ | ||||||
|  |                         mentionData = { | ||||||
|  |                             id: cleanId, | ||||||
|  |                             name: textContent, | ||||||
|  |                             notePath: cleanId // Assume the ID contains the path | ||||||
|  |                         }; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 // Method 3: Check if this is a reference link (href=#notePath) | ||||||
|  |                 else if (mentionEl.tagName === 'A' && mentionEl.hasAttribute('href')) { | ||||||
|  |                     const href = mentionEl.getAttribute('href'); | ||||||
|  |                     if (href && href.startsWith('#')) { | ||||||
|  |                         const notePath = href.substring(1); | ||||||
|  |                         mentionData = { | ||||||
|  |                             notePath: notePath, | ||||||
|  |                             noteTitle: mentionEl.textContent || 'Unknown Note' | ||||||
|  |                         }; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (mentionData && (mentionData.notePath || mentionData.link)) { | ||||||
|  |                     const notePath = mentionData.notePath || mentionData.link?.substring(1); // Remove # from link | ||||||
|  |                     const noteId = notePath ? notePath.split('/').pop() : null; | ||||||
|  |                     const title = mentionData.noteTitle || mentionData.name || mentionEl.textContent || 'Unknown Note'; | ||||||
|  |  | ||||||
|  |                     if (noteId) { | ||||||
|  |                         mentions.push({ | ||||||
|  |                             noteId: noteId, | ||||||
|  |                             title: title, | ||||||
|  |                             notePath: notePath | ||||||
|  |                         }); | ||||||
|  |                         console.log(`Extracted mention: noteId=${noteId}, title=${title}, notePath=${notePath}`); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } catch (e) { | ||||||
|  |                 console.warn('Failed to parse mention data:', e, mentionEl); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         // Convert to plain text for the LLM, but preserve the structure | ||||||
|  |         const content = tempDiv.textContent || tempDiv.innerText || ''; | ||||||
|  |  | ||||||
|  |         console.log(`Extracted ${mentions.length} mentions from editor content`); | ||||||
|  |         return { content, mentions }; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -24,6 +24,11 @@ export interface MessageData { | |||||||
|     role: string; |     role: string; | ||||||
|     content: string; |     content: string; | ||||||
|     timestamp?: Date; |     timestamp?: Date; | ||||||
|  |     mentions?: Array<{ | ||||||
|  |         noteId: string; | ||||||
|  |         title: string; | ||||||
|  |         notePath: string; | ||||||
|  |     }>; | ||||||
| } | } | ||||||
|  |  | ||||||
| export interface ChatData { | export interface ChatData { | ||||||
|   | |||||||
| @@ -31,11 +31,11 @@ export const TPL = ` | |||||||
|  |  | ||||||
|     <form class="note-context-chat-form d-flex flex-column border-top p-2"> |     <form class="note-context-chat-form d-flex flex-column border-top p-2"> | ||||||
|         <div class="d-flex chat-input-container mb-2"> |         <div class="d-flex chat-input-container mb-2"> | ||||||
|             <textarea |             <div | ||||||
|                 class="form-control note-context-chat-input" |                 class="form-control note-context-chat-input flex-grow-1" | ||||||
|                 placeholder="${t('ai_llm.enter_message')}" |                 style="min-height: 60px; max-height: 200px; overflow-y: auto;" | ||||||
|                 rows="2" |                 data-placeholder="${t('ai_llm.enter_message')}" | ||||||
|             ></textarea> |             ></div> | ||||||
|             <button type="submit" class="btn btn-primary note-context-chat-send-button ms-2 d-flex align-items-center justify-content-center"> |             <button type="submit" class="btn btn-primary note-context-chat-send-button ms-2 d-flex align-items-center justify-content-center"> | ||||||
|                 <i class="bx bx-send"></i> |                 <i class="bx bx-send"></i> | ||||||
|             </button> |             </button> | ||||||
|   | |||||||
| @@ -808,7 +808,7 @@ async function streamMessage(req: Request, res: Response) { | |||||||
|     log.info("=== Starting streamMessage ==="); |     log.info("=== Starting streamMessage ==="); | ||||||
|     try { |     try { | ||||||
|         const chatNoteId = req.params.chatNoteId; |         const chatNoteId = req.params.chatNoteId; | ||||||
|         const { content, useAdvancedContext, showThinking } = req.body; |         const { content, useAdvancedContext, showThinking, mentions } = req.body; | ||||||
|  |  | ||||||
|         if (!content || typeof content !== 'string' || content.trim().length === 0) { |         if (!content || typeof content !== 'string' || content.trim().length === 0) { | ||||||
|             throw new Error('Content cannot be empty'); |             throw new Error('Content cannot be empty'); | ||||||
| @@ -823,17 +823,51 @@ async function streamMessage(req: Request, res: Response) { | |||||||
|         // Update last active timestamp |         // Update last active timestamp | ||||||
|         session.lastActive = new Date(); |         session.lastActive = new Date(); | ||||||
|  |  | ||||||
|         // Add user message to the session |         // Process mentions if provided | ||||||
|  |         let enhancedContent = content; | ||||||
|  |         if (mentions && Array.isArray(mentions) && mentions.length > 0) { | ||||||
|  |             log.info(`Processing ${mentions.length} note mentions`); | ||||||
|  |  | ||||||
|  |             // Import note service to get note content | ||||||
|  |             const becca = (await import('../../becca/becca.js')).default; | ||||||
|  |  | ||||||
|  |             const mentionContexts: string[] = []; | ||||||
|  |  | ||||||
|  |             for (const mention of mentions) { | ||||||
|  |                 try { | ||||||
|  |                     const note = becca.getNote(mention.noteId); | ||||||
|  |                     if (note && !note.isDeleted) { | ||||||
|  |                         const noteContent = note.getContent(); | ||||||
|  |                         if (noteContent && typeof noteContent === 'string' && noteContent.trim()) { | ||||||
|  |                             mentionContexts.push(`\n\n--- Content from "${mention.title}" (${mention.noteId}) ---\n${noteContent}\n--- End of "${mention.title}" ---`); | ||||||
|  |                             log.info(`Added content from note "${mention.title}" (${mention.noteId})`); | ||||||
|  |                         } | ||||||
|  |                     } else { | ||||||
|  |                         log.info(`Referenced note not found or deleted: ${mention.noteId}`); | ||||||
|  |                     } | ||||||
|  |                 } catch (error) { | ||||||
|  |                     log.error(`Error retrieving content for note ${mention.noteId}: ${error}`); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Enhance the content with note references | ||||||
|  |             if (mentionContexts.length > 0) { | ||||||
|  |                 enhancedContent = `${content}\n\n=== Referenced Notes ===\n${mentionContexts.join('\n')}`; | ||||||
|  |                 log.info(`Enhanced content with ${mentionContexts.length} note references`); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Add user message to the session (with enhanced content for processing) | ||||||
|         session.messages.push({ |         session.messages.push({ | ||||||
|             role: 'user', |             role: 'user', | ||||||
|             content, |             content: enhancedContent, | ||||||
|             timestamp: new Date() |             timestamp: new Date() | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         // Create request parameters for the pipeline |         // Create request parameters for the pipeline | ||||||
|         const requestParams = { |         const requestParams = { | ||||||
|             chatNoteId: chatNoteId, |             chatNoteId: chatNoteId, | ||||||
|             content, |             content: enhancedContent, | ||||||
|             useAdvancedContext: useAdvancedContext === true, |             useAdvancedContext: useAdvancedContext === true, | ||||||
|             showThinking: showThinking === true, |             showThinking: showThinking === true, | ||||||
|             stream: true // Always stream for this endpoint |             stream: true // Always stream for this endpoint | ||||||
| @@ -851,9 +885,9 @@ async function streamMessage(req: Request, res: Response) { | |||||||
|             params: { |             params: { | ||||||
|                 chatNoteId: chatNoteId |                 chatNoteId: chatNoteId | ||||||
|             }, |             }, | ||||||
|             // Make sure the original content is available to the handler |             // Make sure the enhanced content is available to the handler | ||||||
|             body: { |             body: { | ||||||
|                 content, |                 content: enhancedContent, | ||||||
|                 useAdvancedContext: useAdvancedContext === true, |                 useAdvancedContext: useAdvancedContext === true, | ||||||
|                 showThinking: showThinking === true |                 showThinking: showThinking === true | ||||||
|             } |             } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user