import { SvelteMap } from 'svelte/reactivity';
import { ToolsService } from '$lib/services/tools.service';
import { isAbortError } from '$lib/utils';
-import {
- DEFAULT_AGENTIC_CONFIG,
- NEWLINE_SEPARATOR,
- LLM_ERROR_BLOCK_START,
- LLM_ERROR_BLOCK_END
-} from '$lib/constants';
+import { DEFAULT_AGENTIC_CONFIG, NEWLINE_SEPARATOR } from '$lib/constants';
import {
IMAGE_MIME_TO_EXTENSION,
DATA_URI_BASE64_REGEX,
return;
}
const normalizedError = error instanceof Error ? error : new Error('LLM stream error');
- // Save error as content in the current turn
- onChunk?.(`${LLM_ERROR_BLOCK_START}${normalizedError.message}${LLM_ERROR_BLOCK_END}`);
+ // preserve partial output as is, the outer error dialog informs the user separately
await onAssistantTurnComplete?.(
- turnContent + `${LLM_ERROR_BLOCK_START}${normalizedError.message}${LLM_ERROR_BLOCK_END}`,
+ turnContent,
turnReasoningContent || undefined,
this.buildFinalTimings(capturedTimings, agenticTimings),
undefined
);
}
},
- onError: (error: Error) => {
+ onError: async (error: Error) => {
this.setStreamingActive(false);
if (isAbortError(error)) {
cleanupStreamingState();
return;
}
console.error('Streaming error:', error);
+ // keep whatever was streamed so far, the message stays in memory and in DB
+ await this.savePartialResponseIfNeeded(convId);
cleanupStreamingState();
this.clearPendingMessage(convId);
- const idx = conversationsStore.findMessageIndex(assistantMessage.id);
- if (idx !== -1) {
- const failedMessage = conversationsStore.removeMessageAtIndex(idx);
- if (failedMessage) DatabaseService.deleteMessage(failedMessage.id).catch(console.error);
- }
const contextInfo = (
error as Error & { contextInfo?: { n_prompt_tokens: number; n_ctx: number } }
).contextInfo;
}
console.error('Continue generation error:', error);
- conversationsStore.updateMessageAtIndex(idx, { content: originalContent });
-
- await DatabaseService.updateMessage(msg.id, { content: originalContent });
+ // keep whatever was appended so far, the message stays in memory and in DB
+ await DatabaseService.updateMessage(msg.id, {
+ content: originalContent + appendedContent,
+ reasoningContent: originalReasoning + appendedReasoning || undefined,
+ timestamp: Date.now()
+ });
+ conversationsStore.updateMessageAtIndex(idx, {
+ content: originalContent + appendedContent,
+ reasoningContent: originalReasoning + appendedReasoning || undefined,
+ timestamp: Date.now()
+ });
this.setChatLoading(msg.convId, false);
this.clearChatStreaming(msg.convId);