feat(llm): resolve sending double headers in responses, and not being able to send requests to ollama

This commit is contained in:
perf3ct
2025-06-07 00:02:26 +00:00
parent 20ec294774
commit 6bc9b3c184
6 changed files with 179 additions and 231 deletions

View File

@@ -825,7 +825,10 @@ async function streamMessage(req: Request, res: Response) {
success: true,
message: 'Streaming initiated successfully'
});
log.info(`Sent immediate success response for streaming setup`);
// Mark response as handled to prevent apiResultHandler from processing it again
(res as any).triliumResponseHandled = true;
// Create a new response object for streaming through WebSocket only
// We won't use HTTP streaming since we've already sent the HTTP response
@@ -889,78 +892,33 @@ async function streamMessage(req: Request, res: Response) {
thinking: showThinking ? 'Initializing streaming LLM response...' : undefined
});
// Instead of trying to reimplement the streaming logic ourselves,
// delegate to restChatService but set up the correct protocol:
// 1. We've already sent a success response to the initial POST
// 2. Now we'll have restChatService process the actual streaming through WebSocket
// Process the LLM request using the existing service but with streaming setup
// Since we've already sent the initial HTTP response, we'll use the WebSocket for streaming
try {
// Import the WebSocket service for sending messages
const wsService = (await import('../../services/ws.js')).default;
// Create a simple pass-through response object that won't write to the HTTP response
// but will allow restChatService to send WebSocket messages
const dummyResponse = {
writableEnded: false,
// Implement methods that would normally be used by restChatService
write: (_chunk: string) => {
// Silent no-op - we're only using WebSocket
return true;
// Call restChatService with streaming mode enabled
// The important part is setting method to GET to indicate streaming mode
await restChatService.handleSendMessage({
...req,
method: 'GET', // Indicate streaming mode
query: {
...req.query,
stream: 'true' // Add the required stream parameter
},
end: (_chunk?: string) => {
// Log when streaming is complete via WebSocket
log.info(`[${chatNoteId}] Completed HTTP response handling during WebSocket streaming`);
return dummyResponse;
body: {
content: enhancedContent,
useAdvancedContext: useAdvancedContext === true,
showThinking: showThinking === true
},
setHeader: (name: string, _value: string) => {
// Only log for content-type to reduce noise
if (name.toLowerCase() === 'content-type') {
log.info(`[${chatNoteId}] Setting up streaming for WebSocket only`);
}
return dummyResponse;
}
};
params: { chatNoteId }
} as unknown as Request, res);
} catch (streamError) {
log.error(`Error during WebSocket streaming: ${streamError}`);
// Process the streaming now through WebSocket only
try {
log.info(`[${chatNoteId}] Processing LLM streaming through WebSocket after successful initiation at ${new Date().toISOString()}`);
// Call restChatService with our enhanced request and dummy response
// The important part is setting method to GET to indicate streaming mode
await restChatService.handleSendMessage({
...req,
method: 'GET', // Indicate streaming mode
query: {
...req.query,
stream: 'true' // Add the required stream parameter
},
body: {
content: enhancedContent,
useAdvancedContext: useAdvancedContext === true,
showThinking: showThinking === true
},
params: { chatNoteId }
} as unknown as Request, dummyResponse as unknown as Response);
log.info(`[${chatNoteId}] WebSocket streaming completed at ${new Date().toISOString()}`);
} catch (streamError) {
log.error(`[${chatNoteId}] Error during WebSocket streaming: ${streamError}`);
// Send error message through WebSocket
wsService.sendMessageToAllClients({
type: 'llm-stream',
chatNoteId: chatNoteId,
error: `Error during streaming: ${streamError}`,
done: true
});
}
} catch (error) {
log.error(`Error during streaming: ${error}`);
// Send error to client via WebSocket
// Send error message through WebSocket
wsService.sendMessageToAllClients({
type: 'llm-stream',
chatNoteId: chatNoteId,
error: `Error processing message: ${error}`,
error: `Error during streaming: ${streamError}`,
done: true
});
}