refactor: Cleanup

This commit is contained in:
Aleksander Grygier 2026-02-03 14:24:03 +01:00
parent bb4253ae20
commit 70efc41eb1
9 changed files with 41 additions and 18 deletions

View File

@ -20,6 +20,11 @@
isStreaming?: boolean;
}
type ToolResultLine = {
text: string;
image?: DatabaseMessageExtraImageFile;
};
let { content, message, isStreaming = false }: Props = $props();
let expandedStates: Record<number, boolean> = $state({});
@ -67,11 +72,6 @@
expandedStates[index] = !currentState;
}
type ToolResultLine = {
text: string;
image?: DatabaseMessageExtraImageFile;
};
function parseToolResultWithImages(
toolResult: string,
extras?: DatabaseMessage['extra']

View File

@ -32,6 +32,7 @@
import { modelsStore, modelOptions, selectedModelId } from '$lib/stores/models.svelte';
import { isFileTypeSupported, filterFilesByModalities } from '$lib/utils';
import { parseFilesToMessageExtras, processFilesToChatUploaded } from '$lib/utils/browser-only';
import { ErrorDialogType } from '$lib/enums';
import { onMount } from 'svelte';
import { fade, fly, slide } from 'svelte/transition';
import { Trash2, AlertTriangle, RefreshCw } from '@lucide/svelte';
@ -565,7 +566,7 @@
contextInfo={activeErrorDialog?.contextInfo}
onOpenChange={handleErrorDialogOpenChange}
open={Boolean(activeErrorDialog)}
type={activeErrorDialog?.type ?? 'server'}
type={activeErrorDialog?.type ?? ErrorDialogType.SERVER}
/>
<style>

View File

@ -1,10 +1,11 @@
<script lang="ts">
import * as AlertDialog from '$lib/components/ui/alert-dialog';
import { AlertTriangle, TimerOff } from '@lucide/svelte';
import { ErrorDialogType } from '$lib/enums';
interface Props {
open: boolean;
type: 'timeout' | 'server';
type: ErrorDialogType;
message: string;
contextInfo?: { n_prompt_tokens: number; n_ctx: number };
onOpenChange?: (open: boolean) => void;
@ -12,7 +13,7 @@
let { open = $bindable(), type, message, contextInfo, onOpenChange }: Props = $props();
const isTimeout = $derived(type === 'timeout');
const isTimeout = $derived(type === ErrorDialogType.TIMEOUT);
const title = $derived(isTimeout ? 'TCP Timeout' : 'Server Error');
const description = $derived(
isTimeout

View File

@ -21,6 +21,9 @@ export const REASONING_TAGS = {
END: '<<<reasoning_content_end>>>'
} as const;
// Regex for trimming leading/trailing newlines
export const TRIM_NEWLINES_REGEX = /^\n+|\n+$/g;
// Regex patterns for parsing agentic content
export const AGENTIC_REGEX = {
// Matches completed tool calls (with END marker)

View File

@ -41,3 +41,11 @@ export enum ContentPartType {
IMAGE_URL = 'image_url',
INPUT_AUDIO = 'input_audio'
}
/**
* Error dialog types for displaying server/timeout errors.
*/
export enum ErrorDialogType {
TIMEOUT = 'timeout',
SERVER = 'server'
}

View File

@ -5,6 +5,7 @@ export { AgenticSectionType } from './agentic';
export {
ChatMessageStatsView,
ContentPartType,
ErrorDialogType,
MessageRole,
MessageType,
ReasoningFormat

View File

@ -44,7 +44,7 @@ import type {
ErrorDialogState
} from '$lib/types/chat';
import type { ApiProcessingState, DatabaseMessage, DatabaseMessageExtra } from '$lib/types';
import { MessageRole, MessageType } from '$lib/enums';
import { ErrorDialogType, MessageRole, MessageType } from '$lib/enums';
interface ConversationStateEntry {
lastAccessed: number;
@ -497,7 +497,9 @@ class ChatStore {
console.error('Failed to send message:', error);
this.setChatLoading(currentConv.id, false);
const dialogType =
error instanceof Error && error.name === 'TimeoutError' ? 'timeout' : 'server';
error instanceof Error && error.name === 'TimeoutError'
? ErrorDialogType.TIMEOUT
: ErrorDialogType.SERVER;
const contextInfo = (
error as Error & { contextInfo?: { n_prompt_tokens: number; n_ctx: number } }
).contextInfo;
@ -677,7 +679,7 @@ class ChatStore {
error as Error & { contextInfo?: { n_prompt_tokens: number; n_ctx: number } }
).contextInfo;
this.showErrorDialog({
type: error.name === 'TimeoutError' ? 'timeout' : 'server',
type: error.name === 'TimeoutError' ? ErrorDialogType.TIMEOUT : ErrorDialogType.SERVER,
message: error.message,
contextInfo
});
@ -1083,7 +1085,8 @@ class ChatStore {
this.clearChatStreaming(msg.convId);
this.setProcessingState(msg.convId, null);
this.showErrorDialog({
type: error.name === 'TimeoutError' ? 'timeout' : 'server',
type:
error.name === 'TimeoutError' ? ErrorDialogType.TIMEOUT : ErrorDialogType.SERVER,
message: error.message
});
}

View File

@ -1,3 +1,4 @@
import type { ErrorDialogType } from '$lib/enums';
import type { DatabaseMessageExtra } from './database';
export interface ChatUploadedFile {
@ -119,7 +120,7 @@ export interface ChatStreamCallbacks {
* Error dialog state for displaying server/timeout errors
*/
export interface ErrorDialogState {
type: 'timeout' | 'server';
type: ErrorDialogType;
message: string;
contextInfo?: { n_prompt_tokens: number; n_ctx: number };
}

View File

@ -1,5 +1,10 @@
import { AgenticSectionType } from '$lib/enums';
import { AGENTIC_TAGS, AGENTIC_REGEX, REASONING_TAGS } from '$lib/constants/agentic';
import {
AGENTIC_TAGS,
AGENTIC_REGEX,
REASONING_TAGS,
TRIM_NEWLINES_REGEX
} from '$lib/constants/agentic';
/**
* Represents a parsed section of agentic content
@ -52,12 +57,12 @@ export function parseAgenticContent(rawContent: string): AgenticSection[] {
const sections: AgenticSection[] = [];
for (const segment of segments) {
if (segment.type === 'text') {
if (segment.type === AgenticSectionType.TEXT) {
sections.push(...parseToolCallContent(segment.content));
continue;
}
if (segment.type === 'reasoning') {
if (segment.type === AgenticSectionType.REASONING) {
if (segment.content.trim()) {
sections.push({ type: AgenticSectionType.REASONING, content: segment.content });
}
@ -105,7 +110,7 @@ function parseToolCallContent(rawContent: string): AgenticSection[] {
const toolName = match[1];
const toolArgs = match[2];
const toolResult = match[3].replace(/^\n+|\n+$/g, '');
const toolResult = match[3].replace(TRIM_NEWLINES_REGEX, '');
sections.push({
type: AgenticSectionType.TOOL_CALL,
@ -135,7 +140,7 @@ function parseToolCallContent(rawContent: string): AgenticSection[] {
const toolName = pendingMatch[1];
const toolArgs = pendingMatch[2];
const streamingResult = (pendingMatch[3] || '').replace(/^\n+|\n+$/g, '');
const streamingResult = (pendingMatch[3] || '').replace(TRIM_NEWLINES_REGEX, '');
sections.push({
type: AgenticSectionType.TOOL_CALL_PENDING,