refactor: Types

This commit is contained in:
Aleksander Grygier 2026-01-25 01:39:49 +01:00
parent 5fd3523b4c
commit 3c7357e82c
19 changed files with 269 additions and 193 deletions

View File

@ -27,7 +27,15 @@ import { mcpClient } from '$lib/clients';
import { ChatService } from '$lib/services'; import { ChatService } from '$lib/services';
import { config } from '$lib/stores/settings.svelte'; import { config } from '$lib/stores/settings.svelte';
import { agenticStore } from '$lib/stores/agentic.svelte'; import { agenticStore } from '$lib/stores/agentic.svelte';
import type { AgenticMessage, AgenticToolCallList, AgenticConfig } from '$lib/types/agentic'; import type {
AgenticMessage,
AgenticToolCallList,
AgenticConfig,
AgenticFlowCallbacks,
AgenticFlowOptions,
AgenticFlowParams,
AgenticFlowResult
} from '$lib/types/agentic';
import type { import type {
ApiChatCompletionToolCall, ApiChatCompletionToolCall,
ApiChatMessageData, ApiChatMessageData,
@ -44,8 +52,7 @@ import type { MCPToolCall } from '$lib/types';
import type { import type {
DatabaseMessage, DatabaseMessage,
DatabaseMessageExtra, DatabaseMessageExtra,
DatabaseMessageExtraImageFile, DatabaseMessageExtraImageFile
McpServerOverride
} from '$lib/types/database'; } from '$lib/types/database';
import { AttachmentType, MessageRole } from '$lib/enums'; import { AttachmentType, MessageRole } from '$lib/enums';
@ -88,46 +95,6 @@ function toAgenticMessages(messages: ApiChatMessageData[]): AgenticMessage[] {
}); });
} }
export interface AgenticFlowCallbacks {
onChunk?: (chunk: string) => void;
onReasoningChunk?: (chunk: string) => void;
onToolCallChunk?: (serializedToolCalls: string) => void;
onAttachments?: (extras: DatabaseMessageExtra[]) => void;
onModel?: (model: string) => void;
onComplete?: (
content: string,
reasoningContent?: string,
timings?: ChatMessageTimings,
toolCalls?: string
) => void;
onError?: (error: Error) => void;
onTimings?: (timings?: ChatMessageTimings, promptProgress?: ChatMessagePromptProgress) => void;
}
export interface AgenticFlowOptions {
stream?: boolean;
model?: string;
temperature?: number;
max_tokens?: number;
[key: string]: unknown;
}
export interface AgenticFlowParams {
/** Conversation ID for per-conversation state tracking */
conversationId: string;
messages: (ApiChatMessageData | (DatabaseMessage & { extra?: DatabaseMessageExtra[] }))[];
options?: AgenticFlowOptions;
callbacks: AgenticFlowCallbacks;
signal?: AbortSignal;
/** Per-chat MCP server overrides */
perChatOverrides?: McpServerOverride[];
}
export interface AgenticFlowResult {
handled: boolean;
error?: Error;
}
interface AgenticStoreStateCallbacks { interface AgenticStoreStateCallbacks {
setRunning: (conversationId: string, running: boolean) => void; setRunning: (conversationId: string, running: boolean) => void;
setCurrentTurn: (conversationId: string, turn: number) => void; setCurrentTurn: (conversationId: string, turn: number) => void;

View File

@ -18,57 +18,16 @@ import { agenticStore } from '$lib/stores/agentic.svelte';
import { DEFAULT_CONTEXT } from '$lib/constants/default-context'; import { DEFAULT_CONTEXT } from '$lib/constants/default-context';
import { SYSTEM_MESSAGE_PLACEHOLDER } from '$lib/constants/ui'; import { SYSTEM_MESSAGE_PLACEHOLDER } from '$lib/constants/ui';
import { REASONING_TAGS } from '$lib/constants/agentic'; import { REASONING_TAGS } from '$lib/constants/agentic';
import type { ChatMessageTimings, ChatMessagePromptProgress } from '$lib/types/chat'; import type {
ChatMessageTimings,
ChatMessagePromptProgress,
ChatStreamCallbacks,
ErrorDialogState
} from '$lib/types/chat';
import type { DatabaseMessage, DatabaseMessageExtra } from '$lib/types/database'; import type { DatabaseMessage, DatabaseMessageExtra } from '$lib/types/database';
import type { ApiProcessingState } from '$lib/types/api';
import { MessageRole, MessageType } from '$lib/enums'; import { MessageRole, MessageType } from '$lib/enums';
export interface ApiProcessingState {
status: 'idle' | 'preparing' | 'generating';
tokensDecoded: number;
tokensRemaining: number;
contextUsed: number;
contextTotal: number;
outputTokensUsed: number;
outputTokensMax: number;
hasNextToken: boolean;
tokensPerSecond: number;
temperature: number;
topP: number;
speculative: boolean;
progressPercent?: number;
promptProgress?: {
total: number;
cache: number;
processed: number;
time_ms: number;
};
promptTokens: number;
promptMs?: number;
cacheTokens: number;
}
export interface ErrorDialogState {
type: 'timeout' | 'server';
message: string;
contextInfo?: { n_prompt_tokens: number; n_ctx: number };
}
export interface ChatStreamCallbacks {
onChunk?: (chunk: string) => void;
onReasoningChunk?: (chunk: string) => void;
onToolCallChunk?: (chunk: string) => void;
onAttachments?: (extras: DatabaseMessageExtra[]) => void;
onModel?: (model: string) => void;
onTimings?: (timings?: ChatMessageTimings, promptProgress?: ChatMessagePromptProgress) => void;
onComplete?: (
content?: string,
reasoningContent?: string,
timings?: ChatMessageTimings,
toolCallContent?: string
) => void;
onError?: (error: Error) => void;
}
interface ChatStoreStateCallbacks { interface ChatStoreStateCallbacks {
setChatLoading: (convId: string, loading: boolean) => void; setChatLoading: (convId: string, loading: boolean) => void;
setChatStreaming: (convId: string, response: string, messageId: string) => void; setChatStreaming: (convId: string, response: string, messageId: string) => void;

View File

@ -21,16 +21,9 @@ export { MCPClient, mcpClient } from './mcp.client';
// Chat Client // Chat Client
export { ChatClient, chatClient } from './chat.client'; export { ChatClient, chatClient } from './chat.client';
export type { ChatStreamCallbacks, ApiProcessingState, ErrorDialogState } from './chat.client';
// Agentic Client // Agentic Client
export { AgenticClient, agenticClient } from './agentic.client'; export { AgenticClient, agenticClient } from './agentic.client';
export type {
AgenticFlowCallbacks,
AgenticFlowOptions,
AgenticFlowParams,
AgenticFlowResult
} from './agentic.client';
// Conversations Client // Conversations Client
export { ConversationsClient, conversationsClient } from './conversations.client'; export { ConversationsClient, conversationsClient } from './conversations.client';

View File

@ -1,8 +1,4 @@
export interface BinaryDetectionOptions { import type { BinaryDetectionOptions } from '$lib/types';
prefixLength: number;
suspiciousCharThresholdRatio: number;
maxAbsoluteNullBytes: number;
}
export const DEFAULT_BINARY_DETECTION_OPTIONS: BinaryDetectionOptions = { export const DEFAULT_BINARY_DETECTION_OPTIONS: BinaryDetectionOptions = {
prefixLength: 1024 * 10, // Check the first 10KB of the string prefixLength: 1024 * 10, // Check the first 10KB of the string

View File

@ -1,20 +1,7 @@
import { activeProcessingState } from '$lib/stores/chat.svelte'; import { activeProcessingState } from '$lib/stores/chat.svelte';
import { config } from '$lib/stores/settings.svelte'; import { config } from '$lib/stores/settings.svelte';
import { STATS_UNITS } from '$lib/constants/processing-info'; import { STATS_UNITS } from '$lib/constants/processing-info';
import type { ApiProcessingState, LiveProcessingStats, LiveGenerationStats } from '$lib/types';
interface LiveProcessingStats {
tokensProcessed: number;
totalTokens: number;
timeMs: number;
tokensPerSecond: number;
etaSecs?: number;
}
interface LiveGenerationStats {
tokensGenerated: number;
timeMs: number;
tokensPerSecond: number;
}
export interface UseProcessingStateReturn { export interface UseProcessingStateReturn {
readonly processingState: ApiProcessingState | null; readonly processingState: ApiProcessingState | null;

View File

@ -13,24 +13,13 @@
*/ */
import { normalizeFloatingPoint } from '$lib/utils'; import { normalizeFloatingPoint } from '$lib/utils';
import type {
export type ParameterSource = 'default' | 'custom'; SyncableParameter,
export type ParameterValue = string | number | boolean; ParameterRecord,
export type ParameterRecord = Record<string, ParameterValue>; ParameterInfo,
ParameterValue,
export interface ParameterInfo { ParameterSource
value: string | number | boolean; } from '$lib/types';
source: ParameterSource;
serverDefault?: string | number | boolean;
userOverride?: string | number | boolean;
}
export interface SyncableParameter {
key: string;
serverKey: string;
type: 'number' | 'string' | 'boolean';
canSync: boolean;
}
/** /**
* Mapping of webui setting keys to server parameter keys * Mapping of webui setting keys to server parameter keys

View File

@ -26,21 +26,18 @@
*/ */
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import type { AgenticFlowParams, AgenticFlowResult } from '$lib/clients'; import type {
import type { AgenticSession, AgenticConfig } from '$lib/types/agentic'; AgenticFlowParams,
import type { SettingsConfigType } from '$lib/types/settings'; AgenticFlowResult,
import type { McpServerOverride } from '$lib/types/database'; AgenticSession,
AgenticConfig,
SettingsConfigType,
McpServerOverride
} from '$lib/types';
import { DEFAULT_AGENTIC_CONFIG } from '$lib/constants/agentic'; import { DEFAULT_AGENTIC_CONFIG } from '$lib/constants/agentic';
import { mcpStore } from '$lib/stores/mcp.svelte'; import { mcpStore } from '$lib/stores/mcp.svelte';
import { agenticClient } from '$lib/clients/agentic.client'; import { agenticClient } from '$lib/clients/agentic.client';
export type {
AgenticFlowCallbacks,
AgenticFlowOptions,
AgenticFlowParams,
AgenticFlowResult
} from '$lib/clients';
/** /**
* Creates a fresh agentic session with default values. * Creates a fresh agentic session with default values.
*/ */

View File

@ -21,12 +21,15 @@
import { SvelteMap } from 'svelte/reactivity'; import { SvelteMap } from 'svelte/reactivity';
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import { chatClient, type ApiProcessingState, type ErrorDialogState } from '$lib/clients'; import { chatClient } from '$lib/clients';
import type { DatabaseMessage, DatabaseMessageExtra } from '$lib/types/database'; import type {
ApiProcessingState,
ErrorDialogState,
DatabaseMessage,
DatabaseMessageExtra
} from '$lib/types';
import { MessageRole, MessageType } from '$lib/enums'; import { MessageRole, MessageType } from '$lib/enums';
export type { ApiProcessingState, ErrorDialogState };
class ChatStore { class ChatStore {
activeProcessingState = $state<ApiProcessingState | null>(null); activeProcessingState = $state<ApiProcessingState | null>(null);
currentResponse = $state(''); currentResponse = $state('');

View File

@ -1,5 +1,11 @@
import type { MessageRole } from '$lib/enums'; import type { MessageRole } from '$lib/enums';
import type { ApiChatCompletionRequest, ApiChatMessageContentPart } from './api'; import type {
ApiChatCompletionRequest,
ApiChatMessageContentPart,
ApiChatMessageData
} from './api';
import type { ChatMessageTimings, ChatMessagePromptProgress } from './chat';
import type { DatabaseMessage, DatabaseMessageExtra, McpServerOverride } from './database';
/** /**
* Agentic orchestration configuration. * Agentic orchestration configuration.
@ -61,3 +67,53 @@ export interface AgenticSession {
lastError: Error | null; lastError: Error | null;
streamingToolCall: { name: string; arguments: string } | null; streamingToolCall: { name: string; arguments: string } | null;
} }
/**
* Callbacks for agentic flow execution
*/
export interface AgenticFlowCallbacks {
onChunk?: (chunk: string) => void;
onReasoningChunk?: (chunk: string) => void;
onToolCallChunk?: (serializedToolCalls: string) => void;
onAttachments?: (extras: DatabaseMessageExtra[]) => void;
onModel?: (model: string) => void;
onComplete?: (
content: string,
reasoningContent?: string,
timings?: ChatMessageTimings,
toolCalls?: string
) => void;
onError?: (error: Error) => void;
onTimings?: (timings?: ChatMessageTimings, promptProgress?: ChatMessagePromptProgress) => void;
}
/**
* Options for agentic flow execution
*/
export interface AgenticFlowOptions {
stream?: boolean;
model?: string;
temperature?: number;
max_tokens?: number;
[key: string]: unknown;
}
/**
* Parameters for starting an agentic flow
*/
export interface AgenticFlowParams {
conversationId: string;
messages: (ApiChatMessageData | (DatabaseMessage & { extra?: DatabaseMessageExtra[] }))[];
options?: AgenticFlowOptions;
callbacks: AgenticFlowCallbacks;
signal?: AbortSignal;
perChatOverrides?: McpServerOverride[];
}
/**
* Result of an agentic flow execution
*/
export interface AgenticFlowResult {
handled: boolean;
error?: Error;
}

View File

@ -1,3 +1,5 @@
import type { DatabaseMessageExtra } from './database';
export interface ChatUploadedFile { export interface ChatUploadedFile {
id: string; id: string;
name: string; name: string;
@ -93,3 +95,67 @@ export interface ChatMessageToolCallTiming {
duration_ms: number; duration_ms: number;
success: boolean; success: boolean;
} }
/**
* Callbacks for streaming chat responses
*/
export interface ChatStreamCallbacks {
onChunk?: (chunk: string) => void;
onReasoningChunk?: (chunk: string) => void;
onToolCallChunk?: (chunk: string) => void;
onAttachments?: (extras: DatabaseMessageExtra[]) => void;
onModel?: (model: string) => void;
onTimings?: (timings?: ChatMessageTimings, promptProgress?: ChatMessagePromptProgress) => void;
onComplete?: (
content?: string,
reasoningContent?: string,
timings?: ChatMessageTimings,
toolCallContent?: string
) => void;
onError?: (error: Error) => void;
}
/**
* Error dialog state for displaying server/timeout errors
*/
export interface ErrorDialogState {
type: 'timeout' | 'server';
message: string;
contextInfo?: { n_prompt_tokens: number; n_ctx: number };
}
/**
* Live processing stats during prompt evaluation
*/
export interface LiveProcessingStats {
tokensProcessed: number;
totalTokens: number;
timeMs: number;
tokensPerSecond: number;
etaSecs?: number;
}
/**
* Live generation stats during token generation
*/
export interface LiveGenerationStats {
tokensGenerated: number;
timeMs: number;
tokensPerSecond: number;
}
/**
* Options for getting attachment display items
*/
export interface AttachmentDisplayItemsOptions {
uploadedFiles?: ChatUploadedFile[];
attachments?: DatabaseMessageExtra[];
}
/**
* Result of file processing operation
*/
export interface FileProcessingResult {
extras: DatabaseMessageExtra[];
emptyFiles: string[];
}

View File

@ -1,3 +1,5 @@
import type { AttachmentType } from '$lib/enums';
/** /**
* Common utility types used across the application * Common utility types used across the application
*/ */
@ -10,3 +12,32 @@ export interface KeyValuePair {
key: string; key: string;
value: string; value: string;
} }
/**
* Binary detection configuration options
*/
export interface BinaryDetectionOptions {
/** Number of characters to check from the beginning of the file */
prefixLength: number;
/** Maximum ratio of suspicious characters allowed (0.0 to 1.0) */
suspiciousCharThresholdRatio: number;
/** Maximum absolute number of null bytes allowed */
maxAbsoluteNullBytes: number;
}
/**
* Format for text attachments when copied to clipboard
*/
export interface ClipboardTextAttachment {
type: typeof AttachmentType.TEXT;
name: string;
content: string;
}
/**
* Parsed result from clipboard content
*/
export interface ParsedClipboardContent {
message: string;
textAttachments: ClipboardTextAttachment[];
}

View File

@ -39,11 +39,21 @@ export type {
ChatAttachmentPreviewItem, ChatAttachmentPreviewItem,
ChatMessageSiblingInfo, ChatMessageSiblingInfo,
ChatMessagePromptProgress, ChatMessagePromptProgress,
ChatMessageTimings ChatMessageTimings,
ChatMessageAgenticTimings,
ChatMessageAgenticTurnStats,
ChatMessageToolCallTiming,
ChatStreamCallbacks,
ErrorDialogState,
LiveProcessingStats,
LiveGenerationStats,
AttachmentDisplayItemsOptions,
FileProcessingResult
} from './chat.d'; } from './chat.d';
// Database types // Database types
export type { export type {
McpServerOverride,
DatabaseConversation, DatabaseConversation,
DatabaseMessageExtraAudioFile, DatabaseMessageExtraAudioFile,
DatabaseMessageExtraImageFile, DatabaseMessageExtraImageFile,
@ -58,18 +68,28 @@ export type {
} from './database'; } from './database';
// Model types // Model types
export type { ModelModalities, ModelOption } from './models'; export type { ModelModalities, ModelOption, ModalityCapabilities } from './models';
// Settings types // Settings types
export type { export type {
SettingsConfigValue, SettingsConfigValue,
SettingsFieldConfig, SettingsFieldConfig,
SettingsChatServiceOptions, SettingsChatServiceOptions,
SettingsConfigType SettingsConfigType,
ParameterSource,
ParameterValue,
ParameterRecord,
ParameterInfo,
SyncableParameter
} from './settings'; } from './settings';
// Common types // Common types
export type { KeyValuePair } from './common'; export type {
KeyValuePair,
BinaryDetectionOptions,
ClipboardTextAttachment,
ParsedClipboardContent
} from './common';
// MCP types // MCP types
export type { export type {
@ -99,3 +119,18 @@ export type {
GetPromptResult, GetPromptResult,
PromptMessage PromptMessage
} from './mcp'; } from './mcp';
// Agentic types
export type {
AgenticConfig,
AgenticToolCallPayload,
AgenticMessage,
AgenticAssistantMessage,
AgenticToolCallList,
AgenticChatCompletionRequest,
AgenticSession,
AgenticFlowCallbacks,
AgenticFlowOptions,
AgenticFlowParams,
AgenticFlowResult
} from './agentic';

View File

@ -69,3 +69,24 @@ export interface SettingsChatServiceOptions {
export type SettingsConfigType = typeof SETTING_CONFIG_DEFAULT & { export type SettingsConfigType = typeof SETTING_CONFIG_DEFAULT & {
[key: string]: SettingsConfigValue; [key: string]: SettingsConfigValue;
}; };
/**
* Parameter synchronization types for server defaults and user overrides
*/
export type ParameterSource = 'default' | 'custom';
export type ParameterValue = string | number | boolean;
export type ParameterRecord = Record<string, ParameterValue>;
export interface ParameterInfo {
value: string | number | boolean;
source: ParameterSource;
serverDefault?: string | number | boolean;
userOverride?: string | number | boolean;
}
export interface SyncableParameter {
key: string;
serverKey: string;
type: 'number' | 'string' | 'boolean';
canSync: boolean;
}

View File

@ -1,5 +1,10 @@
import { AttachmentType, FileTypeCategory, SpecialFileType } from '$lib/enums'; import { AttachmentType, FileTypeCategory, SpecialFileType } from '$lib/enums';
import { getFileTypeCategory, getFileTypeCategoryByExtension, isImageFile } from '$lib/utils'; import { getFileTypeCategory, getFileTypeCategoryByExtension, isImageFile } from '$lib/utils';
import type {
AttachmentDisplayItemsOptions,
ChatUploadedFile,
DatabaseMessageExtra
} from '$lib/types';
/** /**
* Formats attachment content for API requests with consistent header style. * Formats attachment content for API requests with consistent header style.
@ -21,11 +26,6 @@ export function formatAttachmentText(
return `\n\n--- ${label}: ${header} ---\n${content}`; return `\n\n--- ${label}: ${header} ---\n${content}`;
} }
export interface AttachmentDisplayItemsOptions {
uploadedFiles?: ChatUploadedFile[];
attachments?: DatabaseMessageExtra[];
}
/** /**
* Check if an uploaded file is an MCP prompt * Check if an uploaded file is an MCP prompt
*/ */

View File

@ -3,8 +3,10 @@ import { AttachmentType } from '$lib/enums';
import type { import type {
DatabaseMessageExtra, DatabaseMessageExtra,
DatabaseMessageExtraTextFile, DatabaseMessageExtraTextFile,
DatabaseMessageExtraLegacyContext DatabaseMessageExtraLegacyContext,
} from '$lib/types/database'; ClipboardTextAttachment,
ParsedClipboardContent
} from '$lib/types';
/** /**
* Copy text to clipboard with toast notification * Copy text to clipboard with toast notification
@ -68,23 +70,6 @@ export async function copyCodeToClipboard(
return copyToClipboard(rawCode, successMessage, errorMessage); return copyToClipboard(rawCode, successMessage, errorMessage);
} }
/**
* Format for text attachments when copied to clipboard
*/
export interface ClipboardTextAttachment {
type: typeof AttachmentType.TEXT;
name: string;
content: string;
}
/**
* Parsed result from clipboard content
*/
export interface ParsedClipboardContent {
message: string;
textAttachments: ClipboardTextAttachment[];
}
/** /**
* Formats a message with text attachments for clipboard copying. * Formats a message with text attachments for clipboard copying.
* *

View File

@ -7,6 +7,7 @@ import { modelsStore } from '$lib/stores/models.svelte';
import { getFileTypeCategory } from '$lib/utils'; import { getFileTypeCategory } from '$lib/utils';
import { readFileAsText, isLikelyTextFile } from './text-files'; import { readFileAsText, isLikelyTextFile } from './text-files';
import { toast } from 'svelte-sonner'; import { toast } from 'svelte-sonner';
import type { FileProcessingResult, ChatUploadedFile, DatabaseMessageExtra } from '$lib/types';
function readFileAsBase64(file: File): Promise<string> { function readFileAsBase64(file: File): Promise<string> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -25,11 +26,6 @@ function readFileAsBase64(file: File): Promise<string> {
}); });
} }
export interface FileProcessingResult {
extras: DatabaseMessageExtra[];
emptyFiles: string[];
}
export async function parseFilesToMessageExtras( export async function parseFilesToMessageExtras(
files: ChatUploadedFile[], files: ChatUploadedFile[],
activeModelId?: string activeModelId?: string

View File

@ -13,10 +13,7 @@ export { apiFetch, apiFetchWithParams, apiPost, type ApiFetchOptions } from './a
export { validateApiKey } from './api-key-validation'; export { validateApiKey } from './api-key-validation';
// Attachment utilities // Attachment utilities
export { export { getAttachmentDisplayItems } from './attachment-display';
getAttachmentDisplayItems,
type AttachmentDisplayItemsOptions
} from './attachment-display';
export { isTextFile, isImageFile, isPdfFile, isAudioFile } from './attachment-type'; export { isTextFile, isImageFile, isPdfFile, isAudioFile } from './attachment-type';
// Textarea utilities // Textarea utilities
@ -46,9 +43,7 @@ export {
copyCodeToClipboard, copyCodeToClipboard,
formatMessageForClipboard, formatMessageForClipboard,
parseClipboardContent, parseClipboardContent,
hasClipboardAttachments, hasClipboardAttachments
type ClipboardTextAttachment,
type ParsedClipboardContent
} from './clipboard'; } from './clipboard';
// File preview utilities // File preview utilities

View File

@ -5,7 +5,7 @@
import { getFileTypeCategory } from '$lib/utils'; import { getFileTypeCategory } from '$lib/utils';
import { FileTypeCategory } from '$lib/enums'; import { FileTypeCategory } from '$lib/enums';
import type { ModalityCapabilities } from '$lib/types/models'; import type { ModalityCapabilities } from '$lib/types';
/** /**
* Check if a file type is supported by the given modalities * Check if a file type is supported by the given modalities

View File

@ -4,7 +4,7 @@
*/ */
import { DEFAULT_BINARY_DETECTION_OPTIONS } from '$lib/constants/binary-detection'; import { DEFAULT_BINARY_DETECTION_OPTIONS } from '$lib/constants/binary-detection';
import type { BinaryDetectionOptions } from '$lib/constants/binary-detection'; import type { BinaryDetectionOptions } from '$lib/types';
import { FileExtensionText } from '$lib/enums'; import { FileExtensionText } from '$lib/enums';
/** /**