From bb4253ae2080c3529c08d4ac66892ab2e3e96a41 Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Tue, 3 Feb 2026 14:11:43 +0100 Subject: [PATCH] refactor: Cleanup --- tools/server/webui/src/lib/enums/chat.ts | 9 +++++++ tools/server/webui/src/lib/enums/index.ts | 8 ++++++- .../webui/src/lib/services/chat.service.ts | 24 +++++++++---------- .../webui/src/lib/stores/agentic.svelte.ts | 8 ++++--- tools/server/webui/src/lib/types/api.d.ts | 4 ++-- 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/tools/server/webui/src/lib/enums/chat.ts b/tools/server/webui/src/lib/enums/chat.ts index ee4a2ed649..298ed41281 100644 --- a/tools/server/webui/src/lib/enums/chat.ts +++ b/tools/server/webui/src/lib/enums/chat.ts @@ -32,3 +32,12 @@ export enum MessageType { THINK = 'think', SYSTEM = 'system' } + +/** + * Content part types for API chat message content. + */ +export enum ContentPartType { + TEXT = 'text', + IMAGE_URL = 'image_url', + INPUT_AUDIO = 'input_audio' +} diff --git a/tools/server/webui/src/lib/enums/index.ts b/tools/server/webui/src/lib/enums/index.ts index 6874df291a..cdc3962744 100644 --- a/tools/server/webui/src/lib/enums/index.ts +++ b/tools/server/webui/src/lib/enums/index.ts @@ -2,7 +2,13 @@ export { AttachmentType } from './attachment'; export { AgenticSectionType } from './agentic'; -export { ChatMessageStatsView, MessageRole, MessageType, ReasoningFormat } from './chat'; +export { + ChatMessageStatsView, + ContentPartType, + MessageRole, + MessageType, + ReasoningFormat +} from './chat'; export { FileTypeCategory, diff --git a/tools/server/webui/src/lib/services/chat.service.ts b/tools/server/webui/src/lib/services/chat.service.ts index db3a581554..ebdd4374f8 100644 --- a/tools/server/webui/src/lib/services/chat.service.ts +++ b/tools/server/webui/src/lib/services/chat.service.ts @@ -1,6 +1,6 @@ import { getJsonHeaders, formatAttachmentText, isAbortError } from '$lib/utils'; import { AGENTIC_REGEX } from '$lib/constants/agentic'; -import { AttachmentType, MessageRole, ReasoningFormat } from '$lib/enums'; +import { AttachmentType, ContentPartType, MessageRole, ReasoningFormat } from '$lib/enums'; import type { ApiChatMessageContentPart, ApiChatCompletionToolCall } from '$lib/types/api'; import type { DatabaseMessageExtraMcpPrompt } from '$lib/types'; import { modelsStore } from '$lib/stores/models.svelte'; @@ -56,7 +56,7 @@ export class ChatService { } return content.map((part: ApiChatMessageContentPart) => { - if (part.type !== 'text' || !part.text) return part; + if (part.type !== ContentPartType.TEXT || !part.text) return part; return { ...part, text: part.text @@ -156,7 +156,7 @@ export class ChatService { normalizedMessages.forEach((msg) => { if (Array.isArray(msg.content)) { msg.content = msg.content.filter((part: ApiChatMessageContentPart) => { - if (part.type === 'image_url') { + if (part.type === ContentPartType.IMAGE_URL) { console.info( `[ChatService] Skipping image attachment in message history (model "${options.model}" does not support vision)` ); @@ -165,7 +165,7 @@ export class ChatService { return true; }); // If only text remains and it's a single part, simplify to string - if (msg.content.length === 1 && msg.content[0].type === 'text') { + if (msg.content.length === 1 && msg.content[0].type === ContentPartType.TEXT) { msg.content = msg.content[0].text; } } @@ -690,7 +690,7 @@ export class ChatService { if (message.content) { contentParts.push({ - type: 'text', + type: ContentPartType.TEXT, text: message.content }); } @@ -703,7 +703,7 @@ export class ChatService { for (const image of imageFiles) { contentParts.push({ - type: 'image_url', + type: ContentPartType.IMAGE_URL, image_url: { url: image.base64Url } }); } @@ -715,7 +715,7 @@ export class ChatService { for (const textFile of textFiles) { contentParts.push({ - type: 'text', + type: ContentPartType.TEXT, text: formatAttachmentText('File', textFile.name, textFile.content) }); } @@ -728,7 +728,7 @@ export class ChatService { for (const legacyContextFile of legacyContextFiles) { contentParts.push({ - type: 'text', + type: ContentPartType.TEXT, text: formatAttachmentText('File', legacyContextFile.name, legacyContextFile.content) }); } @@ -740,7 +740,7 @@ export class ChatService { for (const audio of audioFiles) { contentParts.push({ - type: 'input_audio', + type: ContentPartType.INPUT_AUDIO, input_audio: { data: audio.base64Data, format: audio.mimeType.includes('wav') ? 'wav' : 'mp3' @@ -757,13 +757,13 @@ export class ChatService { if (pdfFile.processedAsImages && pdfFile.images) { for (let i = 0; i < pdfFile.images.length; i++) { contentParts.push({ - type: 'image_url', + type: ContentPartType.IMAGE_URL, image_url: { url: pdfFile.images[i] } }); } } else { contentParts.push({ - type: 'text', + type: ContentPartType.TEXT, text: formatAttachmentText('PDF File', pdfFile.name, pdfFile.content) }); } @@ -776,7 +776,7 @@ export class ChatService { for (const mcpPrompt of mcpPrompts) { contentParts.push({ - type: 'text', + type: ContentPartType.TEXT, text: formatAttachmentText( 'MCP Prompt', mcpPrompt.name, diff --git a/tools/server/webui/src/lib/stores/agentic.svelte.ts b/tools/server/webui/src/lib/stores/agentic.svelte.ts index 196bbe413d..d9e36a80f9 100644 --- a/tools/server/webui/src/lib/stores/agentic.svelte.ts +++ b/tools/server/webui/src/lib/stores/agentic.svelte.ts @@ -23,7 +23,7 @@ import { mcpStore } from '$lib/stores/mcp.svelte'; import { modelsStore } from '$lib/stores/models.svelte'; import { isAbortError } from '$lib/utils'; import { DEFAULT_AGENTIC_CONFIG, AGENTIC_TAGS } from '$lib/constants/agentic'; -import { AttachmentType, MessageRole } from '$lib/enums'; +import { AttachmentType, ContentPartType, MessageRole } from '$lib/enums'; import type { AgenticFlowParams, AgenticFlowResult, @@ -527,12 +527,14 @@ class AgenticStore { this.emitToolCallResult(cleanedResult, maxToolPreviewLines, onChunk); - const contentParts: ApiChatMessageContentPart[] = [{ type: 'text', text: cleanedResult }]; + const contentParts: ApiChatMessageContentPart[] = [ + { type: ContentPartType.TEXT, text: cleanedResult } + ]; for (const attachment of attachments) { if (attachment.type === AttachmentType.IMAGE) { if (modelsStore.modelSupportsVision(options.model ?? '')) { contentParts.push({ - type: 'image_url', + type: ContentPartType.IMAGE_URL, image_url: { url: (attachment as DatabaseMessageExtraImageFile).base64Url } }); } else { diff --git a/tools/server/webui/src/lib/types/api.d.ts b/tools/server/webui/src/lib/types/api.d.ts index 22ad2215fc..b73fe4acb9 100644 --- a/tools/server/webui/src/lib/types/api.d.ts +++ b/tools/server/webui/src/lib/types/api.d.ts @@ -1,4 +1,4 @@ -import type { ServerModelStatus, ServerRole } from '$lib/enums'; +import type { ContentPartType, ServerModelStatus, ServerRole } from '$lib/enums'; import type { ChatMessagePromptProgress, ChatRole } from './chat'; export interface ApiChatCompletionToolFunction { @@ -13,7 +13,7 @@ export interface ApiChatCompletionTool { } export interface ApiChatMessageContentPart { - type: 'text' | 'image_url' | 'input_audio'; + type: ContentPartType; text?: string; image_url?: { url: string;