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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,14 +8,13 @@
ModelsSelector
} from '$lib/components/app';
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 { modelsStore, modelOptions, selectedModelId } from '$lib/stores/models.svelte';
import { isRouterMode } from '$lib/stores/server.svelte';
import { chatStore } from '$lib/stores/chat.svelte';
import { activeMessages, usedModalities } from '$lib/stores/conversations.svelte';
import { useModelChangeValidation } from '$lib/hooks/use-model-change-validation.svelte';
import type { ChatUploadedFile } from '$lib/types/chat';
interface Props {
canSend?: boolean;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,9 +7,8 @@
import remarkRehype from 'remark-rehype';
import rehypeKatex from 'rehype-katex';
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 { preprocessLaTeX } from '$lib/utils/latex-protection';
import { browser } from '$app/environment';
import '$styles/katex-custom.scss';

View File

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

View File

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

View File

@ -1,25 +1,5 @@
import { getJsonHeaders } from '$lib/utils/api-headers';
import type {
ApiChatCompletionRequest,
ApiChatCompletionResponse,
ApiChatCompletionStreamChunk,
ApiChatCompletionToolCall,
ApiChatCompletionToolCallDelta,
ApiChatMessageData,
ApiModelListResponse
} from '$lib/types/api';
import { getJsonHeaders } from '$lib/utils';
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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,17 +3,14 @@ import { conversationsStore } from '$lib/stores/conversations.svelte';
import { config } from '$lib/stores/settings.svelte';
import { contextSize, isRouterMode } from '$lib/stores/server.svelte';
import { selectedModelName } from '$lib/stores/models.svelte';
import { normalizeModelName } from '$lib/utils/model-names';
import { filterByLeafNodeId, findDescendantMessages, findLeafNode } from '$lib/utils/branching';
import {
normalizeModelName,
filterByLeafNodeId,
findDescendantMessages,
findLeafNode
} from '$lib/utils';
import { SvelteMap } from 'svelte/reactivity';
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
@ -487,7 +484,7 @@ class ChatStore {
conversationsStore.updateMessageAtIndex(idx, { toolCalls: streamedToolCallContent });
},
onModel: (modelName: string) => recordModel(modelName),
onTimings: (timings, promptProgress) => {
onTimings: (timings: ChatMessageTimings, promptProgress?: ChatMessagePromptProgress) => {
const tokensPerSecond =
timings?.predicted_ms && timings?.predicted_n
? (timings.predicted_n / timings.predicted_ms) * 1000
@ -1120,7 +1117,7 @@ class ChatStore {
thinking: originalThinking + appendedThinking
});
},
onTimings: (timings, promptProgress) => {
onTimings: (timings: ChatMessageTimings, promptProgress?: ChatMessagePromptProgress) => {
const tokensPerSecond =
timings?.predicted_ms && timings?.predicted_n
? (timings.predicted_n / timings.predicted_ms) * 1000

View File

@ -3,15 +3,8 @@ import { goto } from '$app/navigation';
import { toast } from 'svelte-sonner';
import { DatabaseService } from '$lib/services/database';
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 type {
DatabaseConversation,
DatabaseMessage,
DatabaseMessageExtraPdfFile,
ExportedConversations
} from '$lib/types/database';
import type { ModelModalities } from '$lib/types/models';
/**
* 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 { ServerModelStatus, ModelModality } from '$lib/enums';
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
@ -217,7 +215,7 @@ class ModelsStore {
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 rawCapabilities = Array.isArray(details?.capabilities) ? details?.capabilities : [];
const displayNameSource =
@ -229,7 +227,7 @@ class ModelsStore {
name: displayName,
model: details?.model || item.id,
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,
meta: item.meta ?? null
} satisfies ModelOption;

View File

@ -33,10 +33,14 @@
import { browser } from '$app/environment';
import { SETTING_CONFIG_DEFAULT } from '$lib/constants/settings-config';
import { normalizeFloatingPoint } from '$lib/utils/precision';
import { ParameterSyncService } from '$lib/services/parameter-sync';
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 {
CONFIG_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 type { ChatAttachmentDisplayItem } from '$lib/types/chat';
import type { DatabaseMessageExtra } from '$lib/types/database';
import { isImageFile } from '$lib/utils/attachment-type';
import { getFileTypeCategory, getFileTypeCategoryByExtension } from '$lib/utils/file-type';
import { getFileTypeCategory, getFileTypeCategoryByExtension, isImageFile } from '$lib/utils';
export interface AttachmentDisplayItemsOptions {
uploadedFiles?: ChatUploadedFile[];

View File

@ -1,6 +1,5 @@
import { AttachmentType, FileTypeCategory } from '$lib/enums';
import { getFileTypeCategory, getFileTypeCategoryByExtension } from '$lib/utils/file-type';
import type { DatabaseMessageExtra } from '$lib/types/database';
import { getFileTypeCategory, getFileTypeCategoryByExtension } from '$lib/utils';
/**
* 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.
*/
import type { SettingsConfigType } from '$lib/types/settings';
/**
* Type-safe helper to access config properties dynamically
* 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 { config, settingsStore } from '$lib/stores/settings.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 { 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
*/
import { getFileTypeCategory } from '$lib/utils/file-type';
import { getFileTypeCategory } from '$lib/utils';
import {
FileExtensionAudio,
FileExtensionImage,

View File

@ -2,11 +2,11 @@ import { isSvgMimeType, svgBase64UrlToPngDataURL } from './svg-to-png';
import { isTextFileByName } from './text-files';
import { isWebpMimeType, webpBase64UrlToPngDataURL } from './webp-to-png';
import { FileTypeCategory } from '$lib/enums';
import { getFileTypeCategory } from '$lib/utils/file-type';
import { modelsStore } from '$lib/stores/models.svelte';
import { settingsStore } from '$lib/stores/settings.svelte';
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)

View File

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

View File

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

View File

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