refactor: Utils imports + move types to `app.d.ts`

This commit is contained in:
Aleksander Grygier 2025-11-29 02:33:37 +01:00
parent ce9c9afe0d
commit 493ef08723
44 changed files with 292 additions and 138 deletions

View File

@ -4,14 +4,19 @@
// Import chat types from dedicated module // Import chat types from dedicated module
import type { import type {
// API types
ApiChatCompletionRequest, ApiChatCompletionRequest,
ApiChatCompletionResponse, ApiChatCompletionResponse,
ApiChatCompletionStreamChunk, ApiChatCompletionStreamChunk,
ApiChatCompletionToolCall,
ApiChatCompletionToolCallDelta,
ApiChatMessageData, ApiChatMessageData,
ApiChatMessageContentPart, ApiChatMessageContentPart,
ApiContextSizeError, ApiContextSizeError,
ApiErrorResponse, ApiErrorResponse,
ApiLlamaCppServerProps, ApiLlamaCppServerProps,
ApiModelDataEntry,
ApiModelListResponse,
ApiProcessingState, ApiProcessingState,
ApiRouterModelMeta, ApiRouterModelMeta,
ApiRouterModelsLoadRequest, ApiRouterModelsLoadRequest,
@ -20,21 +25,17 @@ import type {
ApiRouterModelsStatusResponse, ApiRouterModelsStatusResponse,
ApiRouterModelsListResponse, ApiRouterModelsListResponse,
ApiRouterModelsUnloadRequest, ApiRouterModelsUnloadRequest,
ApiRouterModelsUnloadResponse ApiRouterModelsUnloadResponse,
} from '$lib/types/api'; // Chat types
ChatAttachmentDisplayItem,
import { ServerRole, ServerModelStatus, ModelModality } from '$lib/enums'; ChatAttachmentPreviewItem,
import type {
ChatMessageType, ChatMessageType,
ChatRole, ChatRole,
ChatUploadedFile, ChatUploadedFile,
ChatMessageSiblingInfo, ChatMessageSiblingInfo,
ChatMessagePromptProgress, ChatMessagePromptProgress,
ChatMessageTimings ChatMessageTimings,
} from '$lib/types/chat'; // Database types
import type {
DatabaseConversation, DatabaseConversation,
DatabaseMessage, DatabaseMessage,
DatabaseMessageExtra, DatabaseMessageExtra,
@ -42,14 +43,20 @@ import type {
DatabaseMessageExtraImageFile, DatabaseMessageExtraImageFile,
DatabaseMessageExtraTextFile, DatabaseMessageExtraTextFile,
DatabaseMessageExtraPdfFile, DatabaseMessageExtraPdfFile,
DatabaseMessageExtraLegacyContext DatabaseMessageExtraLegacyContext,
} from '$lib/types/database'; ExportedConversation,
ExportedConversations,
import type { // Model types
ModelModalities,
ModelOption,
// Settings types
SettingsChatServiceOptions,
SettingsConfigValue, SettingsConfigValue,
SettingsFieldConfig, SettingsFieldConfig,
SettingsConfigType SettingsConfigType
} from '$lib/types/settings'; } from '$lib/types';
import { ServerRole, ServerModelStatus, ModelModality } from '$lib/enums';
declare global { declare global {
// namespace App { // namespace App {
@ -61,14 +68,19 @@ declare global {
// } // }
export { export {
// API types
ApiChatCompletionRequest, ApiChatCompletionRequest,
ApiChatCompletionResponse, ApiChatCompletionResponse,
ApiChatCompletionStreamChunk, ApiChatCompletionStreamChunk,
ApiChatCompletionToolCall,
ApiChatCompletionToolCallDelta,
ApiChatMessageData, ApiChatMessageData,
ApiChatMessageContentPart, ApiChatMessageContentPart,
ApiContextSizeError, ApiContextSizeError,
ApiErrorResponse, ApiErrorResponse,
ApiLlamaCppServerProps, ApiLlamaCppServerProps,
ApiModelDataEntry,
ApiModelListResponse,
ApiProcessingState, ApiProcessingState,
ApiRouterModelMeta, ApiRouterModelMeta,
ApiRouterModelsLoadRequest, ApiRouterModelsLoadRequest,
@ -78,13 +90,16 @@ declare global {
ApiRouterModelsListResponse, ApiRouterModelsListResponse,
ApiRouterModelsUnloadRequest, ApiRouterModelsUnloadRequest,
ApiRouterModelsUnloadResponse, ApiRouterModelsUnloadResponse,
ChatMessageData, // Chat types
ChatAttachmentDisplayItem,
ChatAttachmentPreviewItem,
ChatMessagePromptProgress, ChatMessagePromptProgress,
ChatMessageSiblingInfo, ChatMessageSiblingInfo,
ChatMessageTimings, ChatMessageTimings,
ChatMessageType, ChatMessageType,
ChatRole, ChatRole,
ChatUploadedFile, ChatUploadedFile,
// Database types
DatabaseConversation, DatabaseConversation,
DatabaseMessage, DatabaseMessage,
DatabaseMessageExtra, DatabaseMessageExtra,
@ -93,12 +108,19 @@ declare global {
DatabaseMessageExtraTextFile, DatabaseMessageExtraTextFile,
DatabaseMessageExtraPdfFile, DatabaseMessageExtraPdfFile,
DatabaseMessageExtraLegacyContext, DatabaseMessageExtraLegacyContext,
ExportedConversation,
ExportedConversations,
// Enum types
ModelModality, ModelModality,
ServerRole, ServerRole,
ServerModelStatus, ServerModelStatus,
// Model types
ModelModalities,
ModelOption,
// Settings types
SettingsChatServiceOptions,
SettingsConfigValue, SettingsConfigValue,
SettingsFieldConfig, SettingsFieldConfig,
SettingsConfigType, SettingsConfigType
SettingsChatServiceOptions
}; };
} }

View File

@ -3,10 +3,14 @@
import * as Alert from '$lib/components/ui/alert'; import * as Alert from '$lib/components/ui/alert';
import { SyntaxHighlightedCode } from '$lib/components/app'; import { SyntaxHighlightedCode } from '$lib/components/app';
import { FileText, Image, Music, FileIcon, Eye, Info } from '@lucide/svelte'; import { FileText, Image, Music, FileIcon, Eye, Info } from '@lucide/svelte';
import type { DatabaseMessageExtra } from '$lib/types/database'; import {
import { convertPDFToImage } from '$lib/utils/pdf-processing'; isTextFile,
import { isTextFile, isImageFile, isPdfFile, isAudioFile } from '$lib/utils/attachment-type'; isImageFile,
import { getLanguageFromFilename } from '$lib/utils/syntax-highlight-language'; isPdfFile,
isAudioFile,
getLanguageFromFilename
} from '$lib/utils';
import { convertPDFToImage } from '$lib/utils/browser-only';
import { modelsStore } from '$lib/stores/models.svelte'; import { modelsStore } from '$lib/stores/models.svelte';
interface Props { interface Props {

View File

@ -1,9 +1,6 @@
<script lang="ts"> <script lang="ts">
import { RemoveButton } from '$lib/components/app'; import { RemoveButton } from '$lib/components/app';
import { getFileTypeLabel, getPreviewText } from '$lib/utils/file-preview'; import { getFileTypeLabel, getPreviewText, formatFileSize, isTextFile } from '$lib/utils';
import { formatFileSize } from '$lib/utils/formatters';
import { isTextFile } from '$lib/utils/attachment-type';
import type { DatabaseMessageExtra, DatabaseMessageExtraPdfFile } from '$lib/types/database';
import { AttachmentType } from '$lib/enums'; import { AttachmentType } from '$lib/enums';
interface Props { interface Props {

View File

@ -3,9 +3,7 @@
import { Button } from '$lib/components/ui/button'; import { Button } from '$lib/components/ui/button';
import { ChevronLeft, ChevronRight } from '@lucide/svelte'; import { ChevronLeft, ChevronRight } from '@lucide/svelte';
import { DialogChatAttachmentPreview, DialogChatAttachmentsViewAll } from '$lib/components/app'; import { DialogChatAttachmentPreview, DialogChatAttachmentsViewAll } from '$lib/components/app';
import { getAttachmentDisplayItems } from '$lib/utils/attachment-display'; import { getAttachmentDisplayItems } from '$lib/utils';
import type { ChatAttachmentDisplayItem, ChatAttachmentPreviewItem } from '$lib/types/chat';
import type { DatabaseMessageExtra } from '$lib/types/database';
interface Props { interface Props {
class?: string; class?: string;

View File

@ -4,9 +4,7 @@
ChatAttachmentThumbnailFile, ChatAttachmentThumbnailFile,
DialogChatAttachmentPreview DialogChatAttachmentPreview
} from '$lib/components/app'; } from '$lib/components/app';
import { getAttachmentDisplayItems } from '$lib/utils/attachment-display'; import { getAttachmentDisplayItems } from '$lib/utils';
import type { ChatAttachmentPreviewItem } from '$lib/types/chat';
import type { DatabaseMessageExtra } from '$lib/types/database';
interface Props { interface Props {
uploadedFiles?: ChatUploadedFile[]; uploadedFiles?: ChatUploadedFile[];

View File

@ -24,14 +24,14 @@
MimeTypeImage, MimeTypeImage,
MimeTypeText MimeTypeText
} from '$lib/enums'; } from '$lib/enums';
import { isIMEComposing } from '$lib/utils';
import { import {
AudioRecorder, AudioRecorder,
convertToWav, convertToWav,
createAudioFile, createAudioFile,
isAudioRecordingSupported isAudioRecordingSupported
} from '$lib/utils/audio-recording'; } from '$lib/utils/browser-only';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { isIMEComposing } from '$lib/utils/is-ime-composing';
interface Props { interface Props {
class?: string; class?: string;

View File

@ -8,14 +8,13 @@
ModelsSelector ModelsSelector
} from '$lib/components/app'; } from '$lib/components/app';
import { FileTypeCategory } from '$lib/enums'; import { FileTypeCategory } from '$lib/enums';
import { getFileTypeCategory } from '$lib/utils/file-type'; import { getFileTypeCategory } from '$lib/utils';
import { config } from '$lib/stores/settings.svelte'; import { config } from '$lib/stores/settings.svelte';
import { modelsStore, modelOptions, selectedModelId } from '$lib/stores/models.svelte'; import { modelsStore, modelOptions, selectedModelId } from '$lib/stores/models.svelte';
import { isRouterMode } from '$lib/stores/server.svelte'; import { isRouterMode } from '$lib/stores/server.svelte';
import { chatStore } from '$lib/stores/chat.svelte'; import { chatStore } from '$lib/stores/chat.svelte';
import { activeMessages, usedModalities } from '$lib/stores/conversations.svelte'; import { activeMessages, usedModalities } from '$lib/stores/conversations.svelte';
import { useModelChangeValidation } from '$lib/hooks/use-model-change-validation.svelte'; import { useModelChangeValidation } from '$lib/hooks/use-model-change-validation.svelte';
import type { ChatUploadedFile } from '$lib/types/chat';
interface Props { interface Props {
canSend?: boolean; canSend?: boolean;

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { generateModalityAwareAcceptString } from '$lib/utils/modality-file-validation'; import { generateModalityAwareAcceptString } from '$lib/utils';
interface Props { interface Props {
accept?: string; accept?: string;

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import autoResizeTextarea from '$lib/utils/autoresize-textarea'; import { autoResizeTextarea } from '$lib/utils';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
interface Props { interface Props {

View File

@ -1,8 +1,6 @@
<script lang="ts"> <script lang="ts">
import { chatStore } from '$lib/stores/chat.svelte'; import { chatStore } from '$lib/stores/chat.svelte';
import { copyToClipboard } from '$lib/utils/copy'; import { copyToClipboard, isIMEComposing } from '$lib/utils';
import { isIMEComposing } from '$lib/utils/is-ime-composing';
import type { ApiChatCompletionToolCall } from '$lib/types/api';
import ChatMessageAssistant from './ChatMessageAssistant.svelte'; import ChatMessageAssistant from './ChatMessageAssistant.svelte';
import ChatMessageUser from './ChatMessageUser.svelte'; import ChatMessageUser from './ChatMessageUser.svelte';

View File

@ -11,7 +11,7 @@
import { useProcessingState } from '$lib/hooks/use-processing-state.svelte'; import { useProcessingState } from '$lib/hooks/use-processing-state.svelte';
import { useModelChangeValidation } from '$lib/hooks/use-model-change-validation.svelte'; import { useModelChangeValidation } from '$lib/hooks/use-model-change-validation.svelte';
import { isLoading } from '$lib/stores/chat.svelte'; import { isLoading } from '$lib/stores/chat.svelte';
import autoResizeTextarea from '$lib/utils/autoresize-textarea'; import { autoResizeTextarea, copyToClipboard } from '$lib/utils';
import { fade } from 'svelte/transition'; import { fade } from 'svelte/transition';
import { Check, X, Wrench } from '@lucide/svelte'; import { Check, X, Wrench } from '@lucide/svelte';
import { Button } from '$lib/components/ui/button'; import { Button } from '$lib/components/ui/button';
@ -21,8 +21,6 @@
import { config } from '$lib/stores/settings.svelte'; import { config } from '$lib/stores/settings.svelte';
import { conversationsStore } from '$lib/stores/conversations.svelte'; import { conversationsStore } from '$lib/stores/conversations.svelte';
import { isRouterMode } from '$lib/stores/server.svelte'; import { isRouterMode } from '$lib/stores/server.svelte';
import { copyToClipboard } from '$lib/utils/copy';
import type { ApiChatCompletionToolCall } from '$lib/types/api';
interface Props { interface Props {
class?: string; class?: string;

View File

@ -5,7 +5,7 @@
import { ChatAttachmentsList, MarkdownContent } from '$lib/components/app'; import { ChatAttachmentsList, MarkdownContent } from '$lib/components/app';
import { INPUT_CLASSES } from '$lib/constants/input-classes'; import { INPUT_CLASSES } from '$lib/constants/input-classes';
import { config } from '$lib/stores/settings.svelte'; import { config } from '$lib/stores/settings.svelte';
import autoResizeTextarea from '$lib/utils/autoresize-textarea'; import { autoResizeTextarea } from '$lib/utils';
import ChatMessageActions from './ChatMessageActions.svelte'; import ChatMessageActions from './ChatMessageActions.svelte';
interface Props { interface Props {

View File

@ -3,7 +3,7 @@
import { DatabaseService } from '$lib/services/database'; import { DatabaseService } from '$lib/services/database';
import { chatStore } from '$lib/stores/chat.svelte'; import { chatStore } from '$lib/stores/chat.svelte';
import { conversationsStore, activeConversation } from '$lib/stores/conversations.svelte'; import { conversationsStore, activeConversation } from '$lib/stores/conversations.svelte';
import { getMessageSiblings } from '$lib/utils/branching'; import { getMessageSiblings } from '$lib/utils';
interface Props { interface Props {
class?: string; class?: string;

View File

@ -26,10 +26,8 @@
import { config } from '$lib/stores/settings.svelte'; import { config } from '$lib/stores/settings.svelte';
import { serverLoading, serverError, serverStore, isRouterMode } from '$lib/stores/server.svelte'; import { serverLoading, serverError, serverStore, isRouterMode } from '$lib/stores/server.svelte';
import { modelsStore, modelOptions, selectedModelId } from '$lib/stores/models.svelte'; import { modelsStore, modelOptions, selectedModelId } from '$lib/stores/models.svelte';
import { parseFilesToMessageExtras } from '$lib/utils/convert-files-to-extra'; import { isFileTypeSupported, filterFilesByModalities } from '$lib/utils';
import { isFileTypeSupported } from '$lib/utils/file-type'; import { parseFilesToMessageExtras, processFilesToChatUploaded } from '$lib/utils/browser-only';
import { filterFilesByModalities } from '$lib/utils/modality-file-validation';
import { processFilesToChatUploaded } from '$lib/utils/process-uploaded-files';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { fade, fly, slide } from 'svelte/transition'; import { fade, fly, slide } from 'svelte/transition';
import { Trash2, AlertTriangle, RefreshCw } from '@lucide/svelte'; import { Trash2, AlertTriangle, RefreshCw } from '@lucide/svelte';

View File

@ -3,8 +3,7 @@
import { Button } from '$lib/components/ui/button'; import { Button } from '$lib/components/ui/button';
import { DialogConversationSelection } from '$lib/components/app'; import { DialogConversationSelection } from '$lib/components/app';
import { DatabaseService } from '$lib/services/database'; import { DatabaseService } from '$lib/services/database';
import type { ExportedConversations } from '$lib/types/database'; import { createMessageCountMap } from '$lib/utils';
import { createMessageCountMap } from '$lib/utils/conversation-utils';
import { conversationsStore } from '$lib/stores/conversations.svelte'; import { conversationsStore } from '$lib/stores/conversations.svelte';
let exportedConversations = $state<DatabaseConversation[]>([]); let exportedConversations = $state<DatabaseConversation[]>([]);

View File

@ -1,8 +1,7 @@
<script lang="ts"> <script lang="ts">
import * as Dialog from '$lib/components/ui/dialog'; import * as Dialog from '$lib/components/ui/dialog';
import type { DatabaseMessageExtra } from '$lib/types/database';
import { ChatAttachmentPreview } from '$lib/components/app'; import { ChatAttachmentPreview } from '$lib/components/app';
import { formatFileSize } from '$lib/utils/formatters'; import { formatFileSize } from '$lib/utils';
interface Props { interface Props {
open: boolean; open: boolean;

View File

@ -5,8 +5,7 @@
import { serverStore } from '$lib/stores/server.svelte'; import { serverStore } from '$lib/stores/server.svelte';
import { modelsStore } from '$lib/stores/models.svelte'; import { modelsStore } from '$lib/stores/models.svelte';
import { ChatService } from '$lib/services/chat'; import { ChatService } from '$lib/services/chat';
import type { ApiModelListResponse } from '$lib/types/api'; import { formatFileSize, formatParameters, formatNumber } from '$lib/utils';
import { formatFileSize, formatParameters, formatNumber } from '$lib/utils/formatters';
interface Props { interface Props {
open?: boolean; open?: boolean;

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { BadgeInfo } from '$lib/components/app'; import { BadgeInfo } from '$lib/components/app';
import { copyToClipboard } from '$lib/utils/copy'; import { copyToClipboard } from '$lib/utils';
import type { Component } from 'svelte'; import type { Component } from 'svelte';
interface Props { interface Props {

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { Copy } from '@lucide/svelte'; import { Copy } from '@lucide/svelte';
import { copyToClipboard } from '$lib/utils/copy'; import { copyToClipboard } from '$lib/utils';
interface Props { interface Props {
ariaLabel?: string; ariaLabel?: string;

View File

@ -7,9 +7,8 @@
import remarkRehype from 'remark-rehype'; import remarkRehype from 'remark-rehype';
import rehypeKatex from 'rehype-katex'; import rehypeKatex from 'rehype-katex';
import rehypeStringify from 'rehype-stringify'; import rehypeStringify from 'rehype-stringify';
import { copyCodeToClipboard } from '$lib/utils/copy'; import { copyCodeToClipboard, preprocessLaTeX } from '$lib/utils';
import { rehypeRestoreTableHtml } from '$lib/markdown/table-html-restorer'; import { rehypeRestoreTableHtml } from '$lib/markdown/table-html-restorer';
import { preprocessLaTeX } from '$lib/utils/latex-protection';
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import '$styles/katex-custom.scss'; import '$styles/katex-custom.scss';

View File

@ -3,7 +3,7 @@
import { ChevronDown, EyeOff, Loader2, MicOff, Package, Power } from '@lucide/svelte'; import { ChevronDown, EyeOff, Loader2, MicOff, Package, Power } from '@lucide/svelte';
import * as Tooltip from '$lib/components/ui/tooltip'; import * as Tooltip from '$lib/components/ui/tooltip';
import { cn } from '$lib/components/ui/utils'; import { cn } from '$lib/components/ui/utils';
import { portalToBody } from '$lib/utils/portal-to-body'; import { portalToBody } from '$lib/utils';
import { import {
modelsStore, modelsStore,
modelOptions, modelOptions,
@ -18,7 +18,6 @@
import { ServerModelStatus } from '$lib/enums'; import { ServerModelStatus } from '$lib/enums';
import { isRouterMode } from '$lib/stores/server.svelte'; import { isRouterMode } from '$lib/stores/server.svelte';
import { DialogModelInformation } from '$lib/components/app'; import { DialogModelInformation } from '$lib/components/app';
import type { ModelOption } from '$lib/types/models';
import { import {
MENU_MAX_WIDTH, MENU_MAX_WIDTH,
MENU_OFFSET, MENU_OFFSET,

View File

@ -1,7 +1,6 @@
import { modelsStore } from '$lib/stores/models.svelte'; import { modelsStore } from '$lib/stores/models.svelte';
import { isRouterMode } from '$lib/stores/server.svelte'; import { isRouterMode } from '$lib/stores/server.svelte';
import { toast } from 'svelte-sonner'; import { toast } from 'svelte-sonner';
import type { ModelModalities } from '$lib/types/models';
interface UseModelChangeValidationOptions { interface UseModelChangeValidationOptions {
/** /**

View File

@ -1,25 +1,5 @@
import { getJsonHeaders } from '$lib/utils/api-headers'; import { getJsonHeaders } from '$lib/utils';
import type {
ApiChatCompletionRequest,
ApiChatCompletionResponse,
ApiChatCompletionStreamChunk,
ApiChatCompletionToolCall,
ApiChatCompletionToolCallDelta,
ApiChatMessageData,
ApiModelListResponse
} from '$lib/types/api';
import { AttachmentType } from '$lib/enums'; import { AttachmentType } from '$lib/enums';
import type {
DatabaseMessage,
DatabaseMessageExtra,
DatabaseMessageExtraAudioFile,
DatabaseMessageExtraImageFile,
DatabaseMessageExtraLegacyContext,
DatabaseMessageExtraPdfFile,
DatabaseMessageExtraTextFile
} from '$lib/types/database';
import type { ChatMessagePromptProgress, ChatMessageTimings } from '$lib/types/chat';
import type { SettingsChatServiceOptions } from '$lib/types/settings';
/** /**
* ChatService - Low-level API communication layer for Chat Completions * ChatService - Low-level API communication layer for Chat Completions

View File

@ -1,5 +1,5 @@
import Dexie, { type EntityTable } from 'dexie'; import Dexie, { type EntityTable } from 'dexie';
import { findDescendantMessages } from '$lib/utils/branching'; import { findDescendantMessages } from '$lib/utils';
class LlamacppDatabase extends Dexie { class LlamacppDatabase extends Dexie {
conversations!: EntityTable<DatabaseConversation, string>; conversations!: EntityTable<DatabaseConversation, string>;

View File

@ -1,14 +1,6 @@
import { base } from '$app/paths'; import { base } from '$app/paths';
import { ServerModelStatus } from '$lib/enums'; import { ServerModelStatus } from '$lib/enums';
import { getJsonHeaders } from '$lib/utils/api-headers'; import { getJsonHeaders } from '$lib/utils';
import type {
ApiModelListResponse,
ApiModelDataEntry,
ApiRouterModelsListResponse,
ApiRouterModelsLoadResponse,
ApiRouterModelsUnloadResponse,
ApiRouterModelsStatusResponse
} from '$lib/types/api';
/** /**
* ModelsService - Stateless service for model management API communication * ModelsService - Stateless service for model management API communication

View File

@ -1,6 +1,5 @@
import { describe, it, expect } from 'vitest'; import { describe, it, expect } from 'vitest';
import { ParameterSyncService } from './parameter-sync'; import { ParameterSyncService } from './parameter-sync';
import type { ApiLlamaCppServerProps } from '$lib/types/api';
describe('ParameterSyncService', () => { describe('ParameterSyncService', () => {
describe('roundFloatingPoint', () => { describe('roundFloatingPoint', () => {

View File

@ -12,8 +12,7 @@
* - Provide sync utilities for settings store integration * - Provide sync utilities for settings store integration
*/ */
import type { ApiLlamaCppServerProps } from '$lib/types/api'; import { normalizeFloatingPoint } from '$lib/utils';
import { normalizeFloatingPoint } from '$lib/utils/precision';
export type ParameterSource = 'default' | 'custom'; export type ParameterSource = 'default' | 'custom';
export type ParameterValue = string | number | boolean; export type ParameterValue = string | number | boolean;

View File

@ -1,4 +1,4 @@
import { getAuthHeaders } from '$lib/utils/api-headers'; import { getAuthHeaders } from '$lib/utils';
/** /**
* PropsService - Server properties management * PropsService - Server properties management

View File

@ -3,17 +3,14 @@ import { conversationsStore } from '$lib/stores/conversations.svelte';
import { config } from '$lib/stores/settings.svelte'; import { config } from '$lib/stores/settings.svelte';
import { contextSize, isRouterMode } from '$lib/stores/server.svelte'; import { contextSize, isRouterMode } from '$lib/stores/server.svelte';
import { selectedModelName } from '$lib/stores/models.svelte'; import { selectedModelName } from '$lib/stores/models.svelte';
import { normalizeModelName } from '$lib/utils/model-names'; import {
import { filterByLeafNodeId, findDescendantMessages, findLeafNode } from '$lib/utils/branching'; normalizeModelName,
filterByLeafNodeId,
findDescendantMessages,
findLeafNode
} from '$lib/utils';
import { SvelteMap } from 'svelte/reactivity'; import { SvelteMap } from 'svelte/reactivity';
import { DEFAULT_CONTEXT } from '$lib/constants/default-context'; import { DEFAULT_CONTEXT } from '$lib/constants/default-context';
import type {
ChatMessageTimings,
ChatRole,
ChatMessageType,
ChatMessagePromptProgress
} from '$lib/types/chat';
import type { DatabaseMessage, DatabaseMessageExtra } from '$lib/types/database';
/** /**
* chatStore - Active AI interaction and streaming state management * chatStore - Active AI interaction and streaming state management
@ -487,7 +484,7 @@ class ChatStore {
conversationsStore.updateMessageAtIndex(idx, { toolCalls: streamedToolCallContent }); conversationsStore.updateMessageAtIndex(idx, { toolCalls: streamedToolCallContent });
}, },
onModel: (modelName: string) => recordModel(modelName), onModel: (modelName: string) => recordModel(modelName),
onTimings: (timings, promptProgress) => { onTimings: (timings: ChatMessageTimings, promptProgress?: ChatMessagePromptProgress) => {
const tokensPerSecond = const tokensPerSecond =
timings?.predicted_ms && timings?.predicted_n timings?.predicted_ms && timings?.predicted_n
? (timings.predicted_n / timings.predicted_ms) * 1000 ? (timings.predicted_n / timings.predicted_ms) * 1000
@ -1120,7 +1117,7 @@ class ChatStore {
thinking: originalThinking + appendedThinking thinking: originalThinking + appendedThinking
}); });
}, },
onTimings: (timings, promptProgress) => { onTimings: (timings: ChatMessageTimings, promptProgress?: ChatMessagePromptProgress) => {
const tokensPerSecond = const tokensPerSecond =
timings?.predicted_ms && timings?.predicted_n timings?.predicted_ms && timings?.predicted_n
? (timings.predicted_n / timings.predicted_ms) * 1000 ? (timings.predicted_n / timings.predicted_ms) * 1000

View File

@ -3,15 +3,8 @@ import { goto } from '$app/navigation';
import { toast } from 'svelte-sonner'; import { toast } from 'svelte-sonner';
import { DatabaseService } from '$lib/services/database'; import { DatabaseService } from '$lib/services/database';
import { config } from '$lib/stores/settings.svelte'; import { config } from '$lib/stores/settings.svelte';
import { filterByLeafNodeId, findLeafNode } from '$lib/utils/branching'; import { filterByLeafNodeId, findLeafNode } from '$lib/utils';
import { AttachmentType } from '$lib/enums'; import { AttachmentType } from '$lib/enums';
import type {
DatabaseConversation,
DatabaseMessage,
DatabaseMessageExtraPdfFile,
ExportedConversations
} from '$lib/types/database';
import type { ModelModalities } from '$lib/types/models';
/** /**
* conversationsStore - Persistent conversation data and lifecycle management * conversationsStore - Persistent conversation data and lifecycle management

View File

@ -3,8 +3,6 @@ import { ModelsService } from '$lib/services/models';
import { PropsService } from '$lib/services/props'; import { PropsService } from '$lib/services/props';
import { ServerModelStatus, ModelModality } from '$lib/enums'; import { ServerModelStatus, ModelModality } from '$lib/enums';
import { serverStore } from '$lib/stores/server.svelte'; import { serverStore } from '$lib/stores/server.svelte';
import type { ModelOption, ModelModalities } from '$lib/types/models';
import type { ApiModelDataEntry } from '$lib/types/api';
/** /**
* modelsStore - Reactive store for model management in both MODEL and ROUTER modes * modelsStore - Reactive store for model management in both MODEL and ROUTER modes
@ -217,7 +215,7 @@ class ModelsStore {
const response = await ModelsService.list(); const response = await ModelsService.list();
const models: ModelOption[] = response.data.map((item, index) => { const models: ModelOption[] = response.data.map((item: ApiModelDataEntry, index: number) => {
const details = response.models?.[index]; const details = response.models?.[index];
const rawCapabilities = Array.isArray(details?.capabilities) ? details?.capabilities : []; const rawCapabilities = Array.isArray(details?.capabilities) ? details?.capabilities : [];
const displayNameSource = const displayNameSource =
@ -229,7 +227,7 @@ class ModelsStore {
name: displayName, name: displayName,
model: details?.model || item.id, model: details?.model || item.id,
description: details?.description, description: details?.description,
capabilities: rawCapabilities.filter((value): value is string => Boolean(value)), capabilities: rawCapabilities.filter((value: unknown): value is string => Boolean(value)),
details: details?.details, details: details?.details,
meta: item.meta ?? null meta: item.meta ?? null
} satisfies ModelOption; } satisfies ModelOption;

View File

@ -33,10 +33,14 @@
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import { SETTING_CONFIG_DEFAULT } from '$lib/constants/settings-config'; import { SETTING_CONFIG_DEFAULT } from '$lib/constants/settings-config';
import { normalizeFloatingPoint } from '$lib/utils/precision';
import { ParameterSyncService } from '$lib/services/parameter-sync'; import { ParameterSyncService } from '$lib/services/parameter-sync';
import { serverStore } from '$lib/stores/server.svelte'; import { serverStore } from '$lib/stores/server.svelte';
import { setConfigValue, getConfigValue, configToParameterRecord } from '$lib/utils/config-helpers'; import {
configToParameterRecord,
normalizeFloatingPoint,
getConfigValue,
setConfigValue
} from '$lib/utils';
import { import {
CONFIG_LOCALSTORAGE_KEY, CONFIG_LOCALSTORAGE_KEY,
USER_OVERRIDES_LOCALSTORAGE_KEY USER_OVERRIDES_LOCALSTORAGE_KEY

View File

@ -0,0 +1,70 @@
/**
* Unified exports for all type definitions
* Import types from '$lib/types' for cleaner imports
*/
// API types
export type {
ApiChatMessageContentPart,
ApiContextSizeError,
ApiErrorResponse,
ApiChatMessageData,
ApiModelStatus,
ApiModelDataEntry,
ApiModelDetails,
ApiModelListResponse,
ApiLlamaCppServerProps,
ApiChatCompletionRequest,
ApiChatCompletionToolCallFunctionDelta,
ApiChatCompletionToolCallDelta,
ApiChatCompletionToolCall,
ApiChatCompletionStreamChunk,
ApiChatCompletionResponse,
ApiSlotData,
ApiProcessingState,
ApiRouterModelMeta,
ApiRouterModelsLoadRequest,
ApiRouterModelsLoadResponse,
ApiRouterModelsStatusRequest,
ApiRouterModelsStatusResponse,
ApiRouterModelsListResponse,
ApiRouterModelsUnloadRequest,
ApiRouterModelsUnloadResponse
} from './api';
// Chat types
export type {
ChatMessageType,
ChatRole,
ChatUploadedFile,
ChatAttachmentDisplayItem,
ChatAttachmentPreviewItem,
ChatMessageSiblingInfo,
ChatMessagePromptProgress,
ChatMessageTimings
} from './chat';
// Database types
export type {
DatabaseConversation,
DatabaseMessageExtraAudioFile,
DatabaseMessageExtraImageFile,
DatabaseMessageExtraLegacyContext,
DatabaseMessageExtraPdfFile,
DatabaseMessageExtraTextFile,
DatabaseMessageExtra,
DatabaseMessage,
ExportedConversation,
ExportedConversations
} from './database';
// Model types
export type { ModelModalities, ModelOption } from './models';
// Settings types
export type {
SettingsConfigValue,
SettingsFieldConfig,
SettingsChatServiceOptions,
SettingsConfigType
} from './settings';

View File

@ -1,8 +1,5 @@
import { FileTypeCategory } from '$lib/enums'; import { FileTypeCategory } from '$lib/enums';
import type { ChatAttachmentDisplayItem } from '$lib/types/chat'; import { getFileTypeCategory, getFileTypeCategoryByExtension, isImageFile } from '$lib/utils';
import type { DatabaseMessageExtra } from '$lib/types/database';
import { isImageFile } from '$lib/utils/attachment-type';
import { getFileTypeCategory, getFileTypeCategoryByExtension } from '$lib/utils/file-type';
export interface AttachmentDisplayItemsOptions { export interface AttachmentDisplayItemsOptions {
uploadedFiles?: ChatUploadedFile[]; uploadedFiles?: ChatUploadedFile[];

View File

@ -1,6 +1,5 @@
import { AttachmentType, FileTypeCategory } from '$lib/enums'; import { AttachmentType, FileTypeCategory } from '$lib/enums';
import { getFileTypeCategory, getFileTypeCategoryByExtension } from '$lib/utils/file-type'; import { getFileTypeCategory, getFileTypeCategoryByExtension } from '$lib/utils';
import type { DatabaseMessageExtra } from '$lib/types/database';
/** /**
* Gets the file type category from an uploaded file, checking both MIME type and extension * Gets the file type category from an uploaded file, checking both MIME type and extension

View File

@ -0,0 +1,35 @@
/**
* Browser-only utility exports
*
* These utilities require browser APIs (DOM, Canvas, MediaRecorder, etc.)
* and cannot be imported during SSR. Import from '$lib/utils/browser-only'
* only in client-side code or components that are not server-rendered.
*/
// Audio utilities (MediaRecorder API)
export {
AudioRecorder,
convertToWav,
createAudioFile,
isAudioRecordingSupported
} from './audio-recording';
// PDF processing utilities (pdfjs-dist with DOMMatrix)
export {
convertPDFToText,
convertPDFToImage,
isPdfFile as isPdfFileFromFile,
isApplicationMimeType
} from './pdf-processing';
// File conversion utilities (depends on pdf-processing)
export { parseFilesToMessageExtras, type FileProcessingResult } from './convert-files-to-extra';
// File upload processing utilities (depends on pdf-processing, svg-to-png, webp-to-png)
export { processFilesToChatUploaded } from './process-uploaded-files';
// SVG utilities (Canvas/Image API)
export { svgBase64UrlToPngDataURL, isSvgFile, isSvgMimeType } from './svg-to-png';
// WebP utilities (Canvas/Image API)
export { webpBase64UrlToPngDataURL, isWebpFile, isWebpMimeType } from './webp-to-png';

View File

@ -5,8 +5,6 @@
* with dynamic keys while maintaining TypeScript type safety. * with dynamic keys while maintaining TypeScript type safety.
*/ */
import type { SettingsConfigType } from '$lib/types/settings';
/** /**
* Type-safe helper to access config properties dynamically * Type-safe helper to access config properties dynamically
* Provides better type safety than direct casting to Record * Provides better type safety than direct casting to Record

View File

@ -4,7 +4,7 @@ import { isWebpMimeType, webpBase64UrlToPngDataURL } from './webp-to-png';
import { FileTypeCategory, AttachmentType } from '$lib/enums'; import { FileTypeCategory, AttachmentType } from '$lib/enums';
import { config, settingsStore } from '$lib/stores/settings.svelte'; import { config, settingsStore } from '$lib/stores/settings.svelte';
import { modelsStore } from '$lib/stores/models.svelte'; import { modelsStore } from '$lib/stores/models.svelte';
import { getFileTypeCategory } from '$lib/utils/file-type'; 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';

View File

@ -0,0 +1,87 @@
/**
* Unified exports for all utility functions
* Import utilities from '$lib/utils' for cleaner imports
*
* For browser-only utilities (pdf-processing, audio-recording, svg-to-png,
* webp-to-png, process-uploaded-files, convert-files-to-extra), use:
* import { ... } from '$lib/utils/browser-only'
*/
// API utilities
export { getAuthHeaders, getJsonHeaders } from './api-headers';
export { validateApiKey } from './api-key-validation';
// Attachment utilities
export {
getAttachmentDisplayItems,
type AttachmentDisplayItemsOptions
} from './attachment-display';
export { isTextFile, isImageFile, isPdfFile, isAudioFile } from './attachment-type';
// Textarea utilities
export { default as autoResizeTextarea } from './autoresize-textarea';
// Branching utilities
export {
filterByLeafNodeId,
findLeafNode,
findDescendantMessages,
getMessageSiblings,
getMessageDisplayList,
hasMessageSiblings,
getNextSibling,
getPreviousSibling
} from './branching';
// Config helpers
export { setConfigValue, getConfigValue, configToParameterRecord } from './config-helpers';
// Conversation utilities
export { createMessageCountMap, getMessageCount } from './conversation-utils';
// Clipboard utilities
export { copyToClipboard, copyCodeToClipboard } from './copy';
// File preview utilities
export { getFileTypeLabel, getPreviewText } from './file-preview';
// File type utilities
export {
getFileTypeCategory,
getFileTypeCategoryByExtension,
getFileTypeByExtension,
isFileTypeSupported
} from './file-type';
// Formatting utilities
export { formatFileSize, formatParameters, formatNumber } from './formatters';
// IME utilities
export { isIMEComposing } from './is-ime-composing';
// LaTeX utilities
export { maskInlineLaTeX, preprocessLaTeX } from './latex-protection';
// Modality file validation utilities
export {
isFileTypeSupportedByModel,
filterFilesByModalities,
generateModalityErrorMessage,
generateModalityAwareAcceptString,
type ModalityCapabilities
} from './modality-file-validation';
// Model name utilities
export { normalizeModelName, isValidModelName } from './model-names';
// Portal utilities
export { portalToBody } from './portal-to-body';
// Precision utilities
export { normalizeFloatingPoint, normalizeNumber } from './precision';
// Syntax highlighting utilities
export { getLanguageFromFilename } from './syntax-highlight-language';
// Text file utilities
export { isTextFileByName, readFileAsText, isLikelyTextFile } from './text-files';

View File

@ -3,7 +3,7 @@
* Ensures only compatible file types are processed based on model capabilities * Ensures only compatible file types are processed based on model capabilities
*/ */
import { getFileTypeCategory } from '$lib/utils/file-type'; import { getFileTypeCategory } from '$lib/utils';
import { import {
FileExtensionAudio, FileExtensionAudio,
FileExtensionImage, FileExtensionImage,

View File

@ -2,11 +2,11 @@ import { isSvgMimeType, svgBase64UrlToPngDataURL } from './svg-to-png';
import { isTextFileByName } from './text-files'; import { isTextFileByName } from './text-files';
import { isWebpMimeType, webpBase64UrlToPngDataURL } from './webp-to-png'; import { isWebpMimeType, webpBase64UrlToPngDataURL } from './webp-to-png';
import { FileTypeCategory } from '$lib/enums'; import { FileTypeCategory } from '$lib/enums';
import { getFileTypeCategory } from '$lib/utils/file-type';
import { modelsStore } from '$lib/stores/models.svelte'; import { modelsStore } from '$lib/stores/models.svelte';
import { settingsStore } from '$lib/stores/settings.svelte'; import { settingsStore } from '$lib/stores/settings.svelte';
import { toast } from 'svelte-sonner'; import { toast } from 'svelte-sonner';
import { convertPDFToText } from '$lib/utils/pdf-processing'; import { getFileTypeCategory } from '$lib/utils';
import { convertPDFToText } from './pdf-processing';
/** /**
* Read a file as a data URL (base64 encoded) * Read a file as a data URL (base64 encoded)

View File

@ -1,5 +1,5 @@
import type { PageLoad } from './$types'; import type { PageLoad } from './$types';
import { validateApiKey } from '$lib/utils/api-key-validation'; import { validateApiKey } from '$lib/utils';
export const load: PageLoad = async ({ fetch }) => { export const load: PageLoad = async ({ fetch }) => {
await validateApiKey(fetch); await validateApiKey(fetch);

View File

@ -1,5 +1,5 @@
import type { PageLoad } from './$types'; import type { PageLoad } from './$types';
import { validateApiKey } from '$lib/utils/api-key-validation'; import { validateApiKey } from '$lib/utils';
export const load: PageLoad = async ({ fetch }) => { export const load: PageLoad = async ({ fetch }) => {
await validateApiKey(fetch); await validateApiKey(fetch);

View File

@ -3,7 +3,7 @@
import ChatSidebar from '$lib/components/app/chat/ChatSidebar/ChatSidebar.svelte'; import ChatSidebar from '$lib/components/app/chat/ChatSidebar/ChatSidebar.svelte';
import { waitFor } from 'storybook/test'; import { waitFor } from 'storybook/test';
import { screen } from 'storybook/test'; import { screen } from 'storybook/test';
import type { DatabaseConversation } from '$lib/types/database'; import type { DatabaseConversation } from '$lib/types';
const { Story } = defineMeta({ const { Story } = defineMeta({
title: 'Components/ChatSidebar', title: 'Components/ChatSidebar',