ui-checks:
name: UI Checks
needs: ui-build
- runs-on: ubuntu-slim
+ runs-on: ubuntu-latest
continue-on-error: true
steps:
- name: Checkout code
e2e-tests:
name: E2E Tests
needs: ui-build
- runs-on: ubuntu-slim
+ runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
*storybook.log
storybook-static
-*.code-workspace
\ No newline at end of file
+*.code-workspace
prettier,
...svelte.configs.prettier,
{
- languageOptions: {
- globals: { ...globals.browser, ...globals.node }
- },
+ languageOptions: { globals: { ...globals.browser, ...globals.node } },
rules: {
// typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.
// see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
'svelte/no-at-html-tags': 'off',
// This app uses hash-based routing (#/) where resolve() from $app/paths does not apply
'svelte/no-navigation-without-resolve': 'off',
+
// Enforce empty line at end of file
'eol-last': 'error'
}
}
},
"node_modules/@sveltejs/kit": {
- "version": "2.59.1",
- "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.59.1.tgz",
- "integrity": "sha512-d8OON70AphLdDesuTIl//M2O6fRTIicX8aYv8vhCiYEhTTI2OboKqey0Hu1A4VFhqwgqtq0vKDmPFGkw8kKmgw==",
+ "version": "2.60.1",
+ "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.60.1.tgz",
+ "integrity": "sha512-mQjlkNo+rJvpln7V2IGY2j99BqhcFbS4UN0AQNKNYfhBAFZTuCDAdW3a1sgf330mvtNvsBXn3HpAhcmvdJTcIQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/cookie": "^0.6.0",
"acorn": "^8.14.1",
"cookie": "^0.6.0",
- "devalue": "^5.6.4",
+ "devalue": "^5.8.1",
"esm-env": "^1.2.2",
"kleur": "^4.1.5",
"magic-string": "^0.30.5",
}
},
"node_modules/devalue": {
- "version": "5.6.4",
- "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.4.tgz",
- "integrity": "sha512-Gp6rDldRsFh/7XuouDbxMH3Mx8GMCcgzIb1pDTvNyn8pZGQ22u+Wa+lGV9dQCltFQ7uVw0MhRyb8XDskNFOReA==",
+ "version": "5.8.1",
+ "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.8.1.tgz",
+ "integrity": "sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==",
"license": "MIT"
},
"node_modules/devlop": {
}
},
"node_modules/express-rate-limit": {
- "version": "8.5.0",
- "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.0.tgz",
- "integrity": "sha512-XKhFohWaSBdVJNTi5TaHziqnPkv04I9UQV6q1Wy7Ui6GGQZVW12ojDFwqer14EvCXxjvPG0CyWXx7cAXpALB4Q==",
+ "version": "8.5.2",
+ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.2.tgz",
+ "integrity": "sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==",
"license": "MIT",
"dependencies": {
- "ip-address": "10.1.0"
+ "ip-address": "^10.2.0"
},
"engines": {
"node": ">= 16"
"license": "MIT"
},
"node_modules/fast-uri": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
- "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz",
+ "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==",
"funding": [
{
"type": "github",
}
},
"node_modules/hono": {
- "version": "4.12.14",
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.14.tgz",
- "integrity": "sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==",
+ "version": "4.12.19",
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.19.tgz",
+ "integrity": "sha512-xa3eYXYXx68XTT4hZ7dRzsXBhaq85ToSrlUJNoR0gwz/1Ap/CNwX47wfvV7pc/xWhjKVVkLT7zBJy8chhNguqQ==",
"license": "MIT",
"engines": {
"node": ">=16.9.0"
"license": "MIT"
},
"node_modules/ip-address": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
- "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
+ "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
"license": "MIT",
"engines": {
"node": ">= 12"
}
},
"node_modules/svelte": {
- "version": "5.55.1",
- "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.55.1.tgz",
- "integrity": "sha512-QjvU7EFemf6mRzdMGlAFttMWtAAVXrax61SZYHdkD6yoVGQ89VeyKfZD4H1JrV1WLmJBxWhFch9H6ig/87VGjw==",
+ "version": "5.55.7",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.55.7.tgz",
+ "integrity": "sha512-ymI5ykLPwIHW839E053FQbI1G+jnRFJEw3Kv5Y4njixVWywQBx+NUFpkkKyk5LIb36Fg9DVXSYpqiGekLD0hyw==",
"license": "MIT",
"dependencies": {
"@jridgewell/remapping": "^2.3.4",
"aria-query": "5.3.1",
"axobject-query": "^4.1.0",
"clsx": "^2.1.1",
- "devalue": "^5.6.4",
+ "devalue": "^5.8.1",
"esm-env": "^1.2.1",
"esrap": "^2.2.4",
"is-reference": "^3.0.3",
"license": "ISC"
},
"node_modules/ws": {
- "version": "8.18.3",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
- "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
+ "version": "8.20.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz",
+ "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==",
"dev": true,
"license": "MIT",
"engines": {
@import 'tailwindcss';
-@source ".";
-
+@source '.';
+@plugin '@tailwindcss/forms';
+@plugin '@tailwindcss/typography';
@import 'tw-animate-css';
@custom-variant dark (&:is(.dark *));
{#if videoSrc}
<video controls class="mb-4 w-full" src={videoSrc}>
+ <track kind="captions" src="" />
Your browser does not support the video element.
</video>
{:else}
SETTINGS_KEYS
} from '$lib/constants';
import { ColorMode, UrlProtocol } from '$lib/enums';
- import { FileTypeText } from '$lib/enums/files';
+ import { FileTypeText } from '$lib/enums/files.enums';
import { highlightCode, detectIncompleteCodeBlock, type IncompleteCodeBlock } from '$lib/utils';
import '$styles/katex-custom.scss';
import githubDarkCss from 'highlight.js/styles/github-dark.css?inline';
} from '$lib/constants';
import { RouterService } from '$lib/services/router.service';
import { setMode } from 'mode-watcher';
- import { ColorMode } from '$lib/enums/ui';
+ import { ColorMode } from '$lib/enums/ui.enums';
import { fade } from 'svelte/transition';
import { goto } from '$app/navigation';
import { page } from '$app/state';
import * as Select from '$lib/components/ui/select';
import { Textarea } from '$lib/components/ui/textarea';
import { SETTING_CONFIG_INFO, SETTINGS_KEYS } from '$lib/constants';
- import { SettingsFieldType } from '$lib/enums/settings';
+ import { SettingsFieldType } from '$lib/enums/settings.enums';
import { settingsStore } from '$lib/stores/settings.svelte';
import { serverStore } from '$lib/stores/server.svelte';
import { modelsStore, selectedModelName, propsCacheVersion } from '$lib/stores/models.svelte';
import { MCPTransportType } from '$lib/enums';
import type { ClientCapabilities, Implementation } from '$lib/types';
import type { Component } from 'svelte';
-import { MimeTypeImage } from '$lib/enums/files';
+import { MimeTypeImage } from '$lib/enums/files.enums';
export const DEFAULT_CLIENT_VERSION = '1.0.0';
export const MCP_CLIENT_NAME = 'llama-ui-mcp';
-import { ColorMode } from '$lib/enums/ui';
-import { SettingsFieldType } from '$lib/enums/settings';
+import { ColorMode } from '$lib/enums/ui.enums';
+import { SettingsFieldType } from '$lib/enums/settings.enums';
import { SyncableParameterType } from '$lib/enums';
import {
Funnel,
MimeTypeApplication,
MimeTypeText
} from '$lib/enums';
-import { FileExtensionVideo, FileTypeVideo } from '$lib/enums/files';
+import { FileExtensionVideo, FileTypeVideo } from '$lib/enums/files.enums';
// File type configuration using enums
export const AUDIO_FILE_TYPES = {
-import { ToolSource } from '$lib/enums/tools';
+import { ToolSource } from '$lib/enums/tools.enums';
export const TOOL_GROUP_LABELS = {
[ToolSource.BUILTIN]: 'Built-in',
--- /dev/null
+/**
+ * OpenAI-compatible tool call type.
+ */
+export enum ToolCallType {
+ FUNCTION = 'function'
+}
+
+/**
+ * Types of sections in agentic content display.
+ */
+export enum AgenticSectionType {
+ TEXT = 'text',
+ TOOL_CALL = 'tool_call',
+ TOOL_CALL_PENDING = 'tool_call_pending',
+ TOOL_CALL_STREAMING = 'tool_call_streaming',
+ REASONING = 'reasoning',
+ REASONING_PENDING = 'reasoning_pending'
+}
+++ /dev/null
-/**
- * OpenAI-compatible tool call type.
- */
-export enum ToolCallType {
- FUNCTION = 'function'
-}
-
-/**
- * Types of sections in agentic content display.
- */
-export enum AgenticSectionType {
- TEXT = 'text',
- TOOL_CALL = 'tool_call',
- TOOL_CALL_PENDING = 'tool_call_pending',
- TOOL_CALL_STREAMING = 'tool_call_streaming',
- REASONING = 'reasoning',
- REASONING_PENDING = 'reasoning_pending'
-}
--- /dev/null
+/**
+ * Attachment type enum for database message extras
+ */
+export enum AttachmentType {
+ AUDIO = 'AUDIO',
+ IMAGE = 'IMAGE',
+ VIDEO = 'VIDEO',
+ MCP_PROMPT = 'MCP_PROMPT',
+ MCP_RESOURCE = 'MCP_RESOURCE',
+ PDF = 'PDF',
+ TEXT = 'TEXT',
+ LEGACY_CONTEXT = 'context' // Legacy attachment type for backward compatibility
+}
+
+/**
+ * Unique identifiers for attachment menu items in the chat form action dropdowns.
+ * Used to select which file upload or attachment action is triggered.
+ */
+export enum AttachmentMenuItemId {
+ IMAGES = 'images',
+ AUDIO = 'audio',
+ VIDEO = 'video',
+ TEXT = 'text',
+ PDF = 'pdf',
+ SYSTEM_MESSAGE = 'system-message',
+ MCP_PROMPT = 'mcp-prompt',
+ MCP_RESOURCES = 'mcp-resources'
+}
+
+/**
+ * Defines when an attachment menu item should be enabled.
+ */
+export enum AttachmentItemEnabledWhen {
+ ALWAYS = 'always',
+ HAS_VISION_MODALITY = 'hasVisionModality',
+ HAS_AUDIO_MODALITY = 'hasAudioModality',
+ HAS_VIDEO_MODALITY = 'hasVideoModality'
+}
+
+/**
+ * Defines the callback action triggered when an attachment menu item is clicked.
+ */
+export enum AttachmentAction {
+ FILE_UPLOAD = 'onFileUpload',
+ SYSTEM_PROMPT_CLICK = 'onSystemPromptClick',
+ MCP_PROMPT_CLICK = 'onMcpPromptClick',
+ MCP_RESOURCES_CLICK = 'onMcpResourcesClick'
+}
+
+/**
+ * Visibility conditions for attachment menu items.
+ */
+export enum AttachmentItemVisibleWhen {
+ HAS_MCP_PROMPTS_SUPPORT = 'hasMcpPromptsSupport',
+ HAS_MCP_RESOURCES_SUPPORT = 'hasMcpResourcesSupport'
+}
+++ /dev/null
-/**
- * Attachment type enum for database message extras
- */
-export enum AttachmentType {
- AUDIO = 'AUDIO',
- IMAGE = 'IMAGE',
- VIDEO = 'VIDEO',
- MCP_PROMPT = 'MCP_PROMPT',
- MCP_RESOURCE = 'MCP_RESOURCE',
- PDF = 'PDF',
- TEXT = 'TEXT',
- LEGACY_CONTEXT = 'context' // Legacy attachment type for backward compatibility
-}
-
-/**
- * Unique identifiers for attachment menu items in the chat form action dropdowns.
- * Used to select which file upload or attachment action is triggered.
- */
-export enum AttachmentMenuItemId {
- IMAGES = 'images',
- AUDIO = 'audio',
- VIDEO = 'video',
- TEXT = 'text',
- PDF = 'pdf',
- SYSTEM_MESSAGE = 'system-message',
- MCP_PROMPT = 'mcp-prompt',
- MCP_RESOURCES = 'mcp-resources'
-}
-
-/**
- * Defines when an attachment menu item should be enabled.
- */
-export enum AttachmentItemEnabledWhen {
- ALWAYS = 'always',
- HAS_VISION_MODALITY = 'hasVisionModality',
- HAS_AUDIO_MODALITY = 'hasAudioModality',
- HAS_VIDEO_MODALITY = 'hasVideoModality'
-}
-
-/**
- * Defines the callback action triggered when an attachment menu item is clicked.
- */
-export enum AttachmentAction {
- FILE_UPLOAD = 'onFileUpload',
- SYSTEM_PROMPT_CLICK = 'onSystemPromptClick',
- MCP_PROMPT_CLICK = 'onMcpPromptClick',
- MCP_RESOURCES_CLICK = 'onMcpResourcesClick'
-}
-
-/**
- * Visibility conditions for attachment menu items.
- */
-export enum AttachmentItemVisibleWhen {
- HAS_MCP_PROMPTS_SUPPORT = 'hasMcpPromptsSupport',
- HAS_MCP_RESOURCES_SUPPORT = 'hasMcpResourcesSupport'
-}
--- /dev/null
+export enum ChatMessageStatsView {
+ GENERATION = 'generation',
+ READING = 'reading',
+ TOOLS = 'tools',
+ SUMMARY = 'summary'
+}
+
+/**
+ * Reasoning format options for API requests.
+ */
+export enum ReasoningFormat {
+ NONE = 'none',
+ AUTO = 'auto'
+}
+
+/**
+ * Message roles for chat messages.
+ */
+export enum MessageRole {
+ USER = 'user',
+ ASSISTANT = 'assistant',
+ SYSTEM = 'system',
+ TOOL = 'tool'
+}
+
+/**
+ * Message types for different content kinds.
+ */
+export enum MessageType {
+ ROOT = 'root',
+ TEXT = 'text',
+ THINK = 'think',
+ SYSTEM = 'system'
+}
+
+/**
+ * Content part types for API chat message content.
+ */
+export enum ContentPartType {
+ TEXT = 'text',
+ IMAGE_URL = 'image_url',
+ INPUT_AUDIO = 'input_audio',
+ INPUT_VIDEO = 'input_video'
+}
+
+/**
+ * Error dialog types for displaying server/timeout errors.
+ */
+export enum ErrorDialogType {
+ TIMEOUT = 'timeout',
+ SERVER = 'server'
+}
+
+export enum ConversationSelectionMode {
+ EXPORT = 'export',
+ IMPORT = 'import'
+}
+
+/**
+ * PDF view mode options for previewing PDF attachments.
+ */
+export enum PdfViewMode {
+ TEXT = 'text',
+ PAGES = 'pages'
+}
+++ /dev/null
-export enum ChatMessageStatsView {
- GENERATION = 'generation',
- READING = 'reading',
- TOOLS = 'tools',
- SUMMARY = 'summary'
-}
-
-/**
- * Reasoning format options for API requests.
- */
-export enum ReasoningFormat {
- NONE = 'none',
- AUTO = 'auto'
-}
-
-/**
- * Message roles for chat messages.
- */
-export enum MessageRole {
- USER = 'user',
- ASSISTANT = 'assistant',
- SYSTEM = 'system',
- TOOL = 'tool'
-}
-
-/**
- * Message types for different content kinds.
- */
-export enum MessageType {
- ROOT = 'root',
- TEXT = 'text',
- THINK = 'think',
- SYSTEM = 'system'
-}
-
-/**
- * Content part types for API chat message content.
- */
-export enum ContentPartType {
- TEXT = 'text',
- IMAGE_URL = 'image_url',
- INPUT_AUDIO = 'input_audio',
- INPUT_VIDEO = 'input_video'
-}
-
-/**
- * Error dialog types for displaying server/timeout errors.
- */
-export enum ErrorDialogType {
- TIMEOUT = 'timeout',
- SERVER = 'server'
-}
-
-export enum ConversationSelectionMode {
- EXPORT = 'export',
- IMPORT = 'import'
-}
-
-/**
- * PDF view mode options for previewing PDF attachments.
- */
-export enum PdfViewMode {
- TEXT = 'text',
- PAGES = 'pages'
-}
--- /dev/null
+/**
+ * Comprehensive dictionary of all supported file types in llama-ui
+ * Organized by category with TypeScript enums for better type safety
+ */
+
+// File type category enum
+export enum FileTypeCategory {
+ IMAGE = 'image',
+ AUDIO = 'audio',
+ VIDEO = 'video',
+ PDF = 'pdf',
+ TEXT = 'text'
+}
+
+/**
+ * Special file types for internal use (not MIME types)
+ */
+export enum SpecialFileType {
+ MCP_PROMPT = 'mcp-prompt'
+}
+
+// Specific file type enums for each category
+export enum FileTypeImage {
+ JPEG = 'jpeg',
+ PNG = 'png',
+ GIF = 'gif',
+ WEBP = 'webp',
+ SVG = 'svg'
+}
+
+export enum FileTypeAudio {
+ MP3 = 'mp3',
+ WAV = 'wav',
+ WEBM = 'webm'
+}
+
+export enum FileTypeVideo {
+ MP4 = 'mp4',
+ OGG = 'ogg'
+}
+
+export enum FileTypePdf {
+ PDF = 'pdf'
+}
+
+export enum FileTypeText {
+ PLAIN_TEXT = 'plainText',
+ MARKDOWN = 'md',
+ ASCIIDOC = 'asciidoc',
+ JAVASCRIPT = 'js',
+ TYPESCRIPT = 'ts',
+ JSX = 'jsx',
+ TSX = 'tsx',
+ CSS = 'css',
+ HTML = 'html',
+ JSON = 'json',
+ XML = 'xml',
+ YAML = 'yaml',
+ CSV = 'csv',
+ LOG = 'log',
+ PYTHON = 'python',
+ JAVA = 'java',
+ CPP = 'cpp',
+ PHP = 'php',
+ RUBY = 'ruby',
+ GO = 'go',
+ RUST = 'rust',
+ SHELL = 'shell',
+ SQL = 'sql',
+ R = 'r',
+ SCALA = 'scala',
+ KOTLIN = 'kotlin',
+ SWIFT = 'swift',
+ DART = 'dart',
+ VUE = 'vue',
+ SVELTE = 'svelte',
+ LATEX = 'latex',
+ BIBTEX = 'bibtex',
+ CUDA = 'cuda',
+ VULKAN = 'vulkan',
+ HASKELL = 'haskell',
+ CSHARP = 'csharp',
+ PROPERTIES = 'properties'
+}
+
+// File extension enums
+export enum FileExtensionImage {
+ JPG = '.jpg',
+ JPEG = '.jpeg',
+ PNG = '.png',
+ GIF = '.gif',
+ WEBP = '.webp',
+ SVG = '.svg'
+}
+
+export enum FileExtensionAudio {
+ MP3 = '.mp3',
+ WAV = '.wav'
+}
+
+export enum FileExtensionVideo {
+ MP4 = '.mp4',
+ OGG = '.ogg'
+}
+
+export enum FileExtensionPdf {
+ PDF = '.pdf'
+}
+
+export enum FileExtensionText {
+ TXT = '.txt',
+ MD = '.md',
+ ADOC = '.adoc',
+ JS = '.js',
+ TS = '.ts',
+ JSX = '.jsx',
+ TSX = '.tsx',
+ CSS = '.css',
+ HTML = '.html',
+ HTM = '.htm',
+ JSON = '.json',
+ XML = '.xml',
+ YAML = '.yaml',
+ YML = '.yml',
+ CSV = '.csv',
+ LOG = '.log',
+ PY = '.py',
+ JAVA = '.java',
+ CPP = '.cpp',
+ C = '.c',
+ H = '.h',
+ PHP = '.php',
+ RB = '.rb',
+ GO = '.go',
+ RS = '.rs',
+ SH = '.sh',
+ BAT = '.bat',
+ SQL = '.sql',
+ R = '.r',
+ SCALA = '.scala',
+ KT = '.kt',
+ SWIFT = '.swift',
+ DART = '.dart',
+ VUE = '.vue',
+ SVELTE = '.svelte',
+ TEX = '.tex',
+ BIB = '.bib',
+ CU = '.cu',
+ CUH = '.cuh',
+ COMP = '.comp',
+ HPP = '.hpp',
+ HS = '.hs',
+ PROPERTIES = '.properties',
+ CS = '.cs'
+}
+
+// MIME type prefixes and includes for content detection
+export enum MimeTypePrefix {
+ IMAGE = 'image/',
+ TEXT = 'text'
+}
+
+export enum MimeTypeIncludes {
+ JSON = 'json',
+ JAVASCRIPT = 'javascript',
+ TYPESCRIPT = 'typescript'
+}
+
+// URI patterns for content detection
+export enum UriPattern {
+ DATABASE_KEYWORD = 'database',
+ DATABASE_SCHEME = 'db://'
+}
+
+// MIME type enums
+export enum MimeTypeApplication {
+ PDF = 'application/pdf',
+ OCTET_STREAM = 'application/octet-stream'
+}
+
+export enum MimeTypeAudio {
+ MP3_MPEG = 'audio/mpeg',
+ MP3 = 'audio/mp3',
+ MP4 = 'audio/mp4',
+ WAV = 'audio/wav',
+ WEBM = 'audio/webm',
+ WEBM_OPUS = 'audio/webm;codecs=opus'
+}
+
+export enum MimeTypeVideo {
+ MP4 = 'video/mp4',
+ OGG = 'video/ogg'
+}
+
+export enum MimeTypeImage {
+ JPEG = 'image/jpeg',
+ JPG = 'image/jpg',
+ PNG = 'image/png',
+ GIF = 'image/gif',
+ WEBP = 'image/webp',
+ SVG = 'image/svg+xml',
+ ICO = 'image/x-icon',
+ ICO_MICROSOFT = 'image/vnd.microsoft.icon'
+}
+
+export enum MimeTypeText {
+ PLAIN = 'text/plain',
+ MARKDOWN = 'text/markdown',
+ ASCIIDOC = 'text/asciidoc',
+ JAVASCRIPT = 'text/javascript',
+ JAVASCRIPT_APP = 'application/javascript',
+ TYPESCRIPT = 'text/typescript',
+ JSX = 'text/jsx',
+ TSX = 'text/tsx',
+ CSS = 'text/css',
+ HTML = 'text/html',
+ JSON = 'application/json',
+ XML_TEXT = 'text/xml',
+ XML_APP = 'application/xml',
+ YAML_TEXT = 'text/yaml',
+ YAML_APP = 'application/yaml',
+ CSV = 'text/csv',
+ PYTHON = 'text/x-python',
+ JAVA = 'text/x-java-source',
+ CPP_HDR = 'text/x-c++hdr',
+ CPP_SRC = 'text/x-c++src',
+ CSHARP = 'text/x-csharp',
+ HASKELL = 'text/x-haskell',
+ C_SRC = 'text/x-csrc',
+ C_HDR = 'text/x-chdr',
+ PHP = 'text/x-php',
+ RUBY = 'text/x-ruby',
+ GO = 'text/x-go',
+ RUST = 'text/x-rust',
+ SHELL = 'text/x-shellscript',
+ BAT = 'application/x-bat',
+ SQL = 'text/x-sql',
+ R = 'text/x-r',
+ SCALA = 'text/x-scala',
+ KOTLIN = 'text/x-kotlin',
+ SWIFT = 'text/x-swift',
+ DART = 'text/x-dart',
+ VUE = 'text/x-vue',
+ SVELTE = 'text/x-svelte',
+ TEX = 'text/x-tex',
+ TEX_APP = 'application/x-tex',
+ LATEX = 'application/x-latex',
+ BIBTEX = 'text/x-bibtex',
+ CUDA = 'text/x-cuda',
+ PROPERTIES = 'text/properties'
+}
+++ /dev/null
-/**
- * Comprehensive dictionary of all supported file types in llama-ui
- * Organized by category with TypeScript enums for better type safety
- */
-
-// File type category enum
-export enum FileTypeCategory {
- IMAGE = 'image',
- AUDIO = 'audio',
- VIDEO = 'video',
- PDF = 'pdf',
- TEXT = 'text'
-}
-
-/**
- * Special file types for internal use (not MIME types)
- */
-export enum SpecialFileType {
- MCP_PROMPT = 'mcp-prompt'
-}
-
-// Specific file type enums for each category
-export enum FileTypeImage {
- JPEG = 'jpeg',
- PNG = 'png',
- GIF = 'gif',
- WEBP = 'webp',
- SVG = 'svg'
-}
-
-export enum FileTypeAudio {
- MP3 = 'mp3',
- WAV = 'wav',
- WEBM = 'webm'
-}
-
-export enum FileTypeVideo {
- MP4 = 'mp4',
- OGG = 'ogg'
-}
-
-export enum FileTypePdf {
- PDF = 'pdf'
-}
-
-export enum FileTypeText {
- PLAIN_TEXT = 'plainText',
- MARKDOWN = 'md',
- ASCIIDOC = 'asciidoc',
- JAVASCRIPT = 'js',
- TYPESCRIPT = 'ts',
- JSX = 'jsx',
- TSX = 'tsx',
- CSS = 'css',
- HTML = 'html',
- JSON = 'json',
- XML = 'xml',
- YAML = 'yaml',
- CSV = 'csv',
- LOG = 'log',
- PYTHON = 'python',
- JAVA = 'java',
- CPP = 'cpp',
- PHP = 'php',
- RUBY = 'ruby',
- GO = 'go',
- RUST = 'rust',
- SHELL = 'shell',
- SQL = 'sql',
- R = 'r',
- SCALA = 'scala',
- KOTLIN = 'kotlin',
- SWIFT = 'swift',
- DART = 'dart',
- VUE = 'vue',
- SVELTE = 'svelte',
- LATEX = 'latex',
- BIBTEX = 'bibtex',
- CUDA = 'cuda',
- VULKAN = 'vulkan',
- HASKELL = 'haskell',
- CSHARP = 'csharp',
- PROPERTIES = 'properties'
-}
-
-// File extension enums
-export enum FileExtensionImage {
- JPG = '.jpg',
- JPEG = '.jpeg',
- PNG = '.png',
- GIF = '.gif',
- WEBP = '.webp',
- SVG = '.svg'
-}
-
-export enum FileExtensionAudio {
- MP3 = '.mp3',
- WAV = '.wav'
-}
-
-export enum FileExtensionVideo {
- MP4 = '.mp4',
- OGG = '.ogg'
-}
-
-export enum FileExtensionPdf {
- PDF = '.pdf'
-}
-
-export enum FileExtensionText {
- TXT = '.txt',
- MD = '.md',
- ADOC = '.adoc',
- JS = '.js',
- TS = '.ts',
- JSX = '.jsx',
- TSX = '.tsx',
- CSS = '.css',
- HTML = '.html',
- HTM = '.htm',
- JSON = '.json',
- XML = '.xml',
- YAML = '.yaml',
- YML = '.yml',
- CSV = '.csv',
- LOG = '.log',
- PY = '.py',
- JAVA = '.java',
- CPP = '.cpp',
- C = '.c',
- H = '.h',
- PHP = '.php',
- RB = '.rb',
- GO = '.go',
- RS = '.rs',
- SH = '.sh',
- BAT = '.bat',
- SQL = '.sql',
- R = '.r',
- SCALA = '.scala',
- KT = '.kt',
- SWIFT = '.swift',
- DART = '.dart',
- VUE = '.vue',
- SVELTE = '.svelte',
- TEX = '.tex',
- BIB = '.bib',
- CU = '.cu',
- CUH = '.cuh',
- COMP = '.comp',
- HPP = '.hpp',
- HS = '.hs',
- PROPERTIES = '.properties',
- CS = '.cs'
-}
-
-// MIME type prefixes and includes for content detection
-export enum MimeTypePrefix {
- IMAGE = 'image/',
- TEXT = 'text'
-}
-
-export enum MimeTypeIncludes {
- JSON = 'json',
- JAVASCRIPT = 'javascript',
- TYPESCRIPT = 'typescript'
-}
-
-// URI patterns for content detection
-export enum UriPattern {
- DATABASE_KEYWORD = 'database',
- DATABASE_SCHEME = 'db://'
-}
-
-// MIME type enums
-export enum MimeTypeApplication {
- PDF = 'application/pdf',
- OCTET_STREAM = 'application/octet-stream'
-}
-
-export enum MimeTypeAudio {
- MP3_MPEG = 'audio/mpeg',
- MP3 = 'audio/mp3',
- MP4 = 'audio/mp4',
- WAV = 'audio/wav',
- WEBM = 'audio/webm',
- WEBM_OPUS = 'audio/webm;codecs=opus'
-}
-
-export enum MimeTypeVideo {
- MP4 = 'video/mp4',
- OGG = 'video/ogg'
-}
-
-export enum MimeTypeImage {
- JPEG = 'image/jpeg',
- JPG = 'image/jpg',
- PNG = 'image/png',
- GIF = 'image/gif',
- WEBP = 'image/webp',
- SVG = 'image/svg+xml',
- ICO = 'image/x-icon',
- ICO_MICROSOFT = 'image/vnd.microsoft.icon'
-}
-
-export enum MimeTypeText {
- PLAIN = 'text/plain',
- MARKDOWN = 'text/markdown',
- ASCIIDOC = 'text/asciidoc',
- JAVASCRIPT = 'text/javascript',
- JAVASCRIPT_APP = 'application/javascript',
- TYPESCRIPT = 'text/typescript',
- JSX = 'text/jsx',
- TSX = 'text/tsx',
- CSS = 'text/css',
- HTML = 'text/html',
- JSON = 'application/json',
- XML_TEXT = 'text/xml',
- XML_APP = 'application/xml',
- YAML_TEXT = 'text/yaml',
- YAML_APP = 'application/yaml',
- CSV = 'text/csv',
- PYTHON = 'text/x-python',
- JAVA = 'text/x-java-source',
- CPP_HDR = 'text/x-c++hdr',
- CPP_SRC = 'text/x-c++src',
- CSHARP = 'text/x-csharp',
- HASKELL = 'text/x-haskell',
- C_SRC = 'text/x-csrc',
- C_HDR = 'text/x-chdr',
- PHP = 'text/x-php',
- RUBY = 'text/x-ruby',
- GO = 'text/x-go',
- RUST = 'text/x-rust',
- SHELL = 'text/x-shellscript',
- BAT = 'application/x-bat',
- SQL = 'text/x-sql',
- R = 'text/x-r',
- SCALA = 'text/x-scala',
- KOTLIN = 'text/x-kotlin',
- SWIFT = 'text/x-swift',
- DART = 'text/x-dart',
- VUE = 'text/x-vue',
- SVELTE = 'text/x-svelte',
- TEX = 'text/x-tex',
- TEX_APP = 'application/x-tex',
- LATEX = 'application/x-latex',
- BIBTEX = 'text/x-bibtex',
- CUDA = 'text/x-cuda',
- PROPERTIES = 'text/properties'
-}
AttachmentItemEnabledWhen,
AttachmentAction,
AttachmentItemVisibleWhen
-} from './attachment';
+} from './attachment.enums';
-export { AgenticSectionType, ToolCallType } from './agentic';
+export { AgenticSectionType, ToolCallType } from './agentic.enums';
export {
ChatMessageStatsView,
MessageType,
PdfViewMode,
ReasoningFormat
-} from './chat';
+} from './chat.enums';
export {
FileTypeCategory,
MimeTypeImage,
MimeTypeText,
SpecialFileType
-} from './files';
+} from './files.enums';
export {
MCPConnectionPhase,
MCPContentType,
MCPRefType,
JsonSchemaType
-} from './mcp';
+} from './mcp.enums';
-export { ModelModality } from './model';
+export { ModelModality } from './model.enums';
-export { ServerRole, ServerModelStatus } from './server';
+export { ServerRole, ServerModelStatus } from './server.enums';
-export { ParameterSource, SyncableParameterType, SettingsFieldType } from './settings';
+export { ParameterSource, SyncableParameterType, SettingsFieldType } from './settings.enums';
-export { ColorMode, HtmlInputType, McpPromptVariant, TooltipSide, UrlProtocol } from './ui';
+export { ColorMode, HtmlInputType, McpPromptVariant, TooltipSide, UrlProtocol } from './ui.enums';
-export { KeyboardKey } from './keyboard';
+export { KeyboardKey } from './keyboard.enums';
-export { ToolSource, ToolPermissionDecision, ToolResponseField } from './tools';
+export { ToolSource, ToolPermissionDecision, ToolResponseField } from './tools.enums';
--- /dev/null
+/**
+ * Keyboard key names for event handling
+ */
+export enum KeyboardKey {
+ ENTER = 'Enter',
+ ESCAPE = 'Escape',
+ ARROW_UP = 'ArrowUp',
+ ARROW_DOWN = 'ArrowDown',
+ ARROW_LEFT = 'ArrowLeft',
+ ARROW_RIGHT = 'ArrowRight',
+ TAB = 'Tab',
+ D_LOWER = 'd',
+ D_UPPER = 'D',
+ E_UPPER = 'E',
+ K_LOWER = 'k',
+ O_LOWER = 'o',
+ O_UPPER = 'O',
+ SPACE = ' '
+}
+++ /dev/null
-/**
- * Keyboard key names for event handling
- */
-export enum KeyboardKey {
- ENTER = 'Enter',
- ESCAPE = 'Escape',
- ARROW_UP = 'ArrowUp',
- ARROW_DOWN = 'ArrowDown',
- ARROW_LEFT = 'ArrowLeft',
- ARROW_RIGHT = 'ArrowRight',
- TAB = 'Tab',
- D_LOWER = 'd',
- D_UPPER = 'D',
- E_UPPER = 'E',
- K_LOWER = 'k',
- O_LOWER = 'o',
- O_UPPER = 'O',
- SPACE = ' '
-}
--- /dev/null
+/**
+ * Connection lifecycle phases for MCP protocol
+ */
+export enum MCPConnectionPhase {
+ IDLE = 'idle',
+ TRANSPORT_CREATING = 'transport_creating',
+ TRANSPORT_READY = 'transport_ready',
+ INITIALIZING = 'initializing',
+ CAPABILITIES_EXCHANGED = 'capabilities_exchanged',
+ LISTING_TOOLS = 'listing_tools',
+ CONNECTED = 'connected',
+ ERROR = 'error',
+ DISCONNECTED = 'disconnected'
+}
+
+/**
+ * Log level for connection events
+ */
+export enum MCPLogLevel {
+ INFO = 'info',
+ WARN = 'warn',
+ ERROR = 'error'
+}
+
+/**
+ * Transport types for MCP connections
+ */
+export enum MCPTransportType {
+ WEBSOCKET = 'websocket',
+ STREAMABLE_HTTP = 'streamable_http',
+ SSE = 'sse'
+}
+
+/**
+ * Health check status for MCP servers
+ */
+export enum HealthCheckStatus {
+ IDLE = 'idle',
+ CONNECTING = 'connecting',
+ SUCCESS = 'success',
+ ERROR = 'error'
+}
+
+/**
+ * Content types for MCP tool results
+ */
+export enum MCPContentType {
+ TEXT = 'text',
+ IMAGE = 'image',
+ RESOURCE = 'resource'
+}
+
+/**
+ * JSON Schema types used in MCP tool definitions
+ */
+export enum JsonSchemaType {
+ OBJECT = 'object'
+}
+
+/**
+ * Reference types for MCP completions
+ */
+export enum MCPRefType {
+ PROMPT = 'ref/prompt',
+ RESOURCE = 'ref/resource'
+}
+++ /dev/null
-/**
- * Connection lifecycle phases for MCP protocol
- */
-export enum MCPConnectionPhase {
- IDLE = 'idle',
- TRANSPORT_CREATING = 'transport_creating',
- TRANSPORT_READY = 'transport_ready',
- INITIALIZING = 'initializing',
- CAPABILITIES_EXCHANGED = 'capabilities_exchanged',
- LISTING_TOOLS = 'listing_tools',
- CONNECTED = 'connected',
- ERROR = 'error',
- DISCONNECTED = 'disconnected'
-}
-
-/**
- * Log level for connection events
- */
-export enum MCPLogLevel {
- INFO = 'info',
- WARN = 'warn',
- ERROR = 'error'
-}
-
-/**
- * Transport types for MCP connections
- */
-export enum MCPTransportType {
- WEBSOCKET = 'websocket',
- STREAMABLE_HTTP = 'streamable_http',
- SSE = 'sse'
-}
-
-/**
- * Health check status for MCP servers
- */
-export enum HealthCheckStatus {
- IDLE = 'idle',
- CONNECTING = 'connecting',
- SUCCESS = 'success',
- ERROR = 'error'
-}
-
-/**
- * Content types for MCP tool results
- */
-export enum MCPContentType {
- TEXT = 'text',
- IMAGE = 'image',
- RESOURCE = 'resource'
-}
-
-/**
- * JSON Schema types used in MCP tool definitions
- */
-export enum JsonSchemaType {
- OBJECT = 'object'
-}
-
-/**
- * Reference types for MCP completions
- */
-export enum MCPRefType {
- PROMPT = 'ref/prompt',
- RESOURCE = 'ref/resource'
-}
--- /dev/null
+export enum ModelModality {
+ TEXT = 'TEXT',
+ AUDIO = 'AUDIO',
+ VISION = 'VISION',
+ VIDEO = 'VIDEO'
+}
+++ /dev/null
-export enum ModelModality {
- TEXT = 'TEXT',
- AUDIO = 'AUDIO',
- VISION = 'VISION',
- VIDEO = 'VIDEO'
-}
--- /dev/null
+/**
+ * Server role enum - used for single/multi-model mode
+ */
+export enum ServerRole {
+ /** Single model mode - server running with a specific model loaded */
+ MODEL = 'model',
+ /** Router mode - server managing multiple model instances */
+ ROUTER = 'router'
+}
+
+/**
+ * Model status enum - matches tools/server/server-models.h from C++ server
+ * Used as the `value` field in the status object from /models endpoint
+ */
+export enum ServerModelStatus {
+ UNLOADED = 'unloaded',
+ LOADING = 'loading',
+ LOADED = 'loaded',
+ SLEEPING = 'sleeping',
+ FAILED = 'failed'
+}
+++ /dev/null
-/**
- * Server role enum - used for single/multi-model mode
- */
-export enum ServerRole {
- /** Single model mode - server running with a specific model loaded */
- MODEL = 'model',
- /** Router mode - server managing multiple model instances */
- ROUTER = 'router'
-}
-
-/**
- * Model status enum - matches tools/server/server-models.h from C++ server
- * Used as the `value` field in the status object from /models endpoint
- */
-export enum ServerModelStatus {
- UNLOADED = 'unloaded',
- LOADING = 'loading',
- LOADED = 'loaded',
- SLEEPING = 'sleeping',
- FAILED = 'failed'
-}
--- /dev/null
+/**
+ * Parameter source - indicates whether a parameter uses default or custom value
+ */
+export enum ParameterSource {
+ DEFAULT = 'default',
+ CUSTOM = 'custom'
+}
+
+/**
+ * Syncable parameter type - data types for parameters that can be synced with server
+ */
+export enum SyncableParameterType {
+ NUMBER = 'number',
+ STRING = 'string',
+ BOOLEAN = 'boolean'
+}
+
+/**
+ * Settings field type - defines the input type for settings fields
+ */
+export enum SettingsFieldType {
+ INPUT = 'input',
+ TEXTAREA = 'textarea',
+ CHECKBOX = 'checkbox',
+ SELECT = 'select'
+}
+++ /dev/null
-/**
- * Parameter source - indicates whether a parameter uses default or custom value
- */
-export enum ParameterSource {
- DEFAULT = 'default',
- CUSTOM = 'custom'
-}
-
-/**
- * Syncable parameter type - data types for parameters that can be synced with server
- */
-export enum SyncableParameterType {
- NUMBER = 'number',
- STRING = 'string',
- BOOLEAN = 'boolean'
-}
-
-/**
- * Settings field type - defines the input type for settings fields
- */
-export enum SettingsFieldType {
- INPUT = 'input',
- TEXTAREA = 'textarea',
- CHECKBOX = 'checkbox',
- SELECT = 'select'
-}
--- /dev/null
+export enum ToolSource {
+ BUILTIN = 'builtin',
+ MCP = 'mcp',
+ CUSTOM = 'custom'
+}
+
+export enum ToolPermissionDecision {
+ ALWAYS = 'always',
+ ALWAYS_SERVER = 'always_server',
+ ONCE = 'once',
+ DENY = 'deny'
+}
+
+export enum ToolResponseField {
+ PLAIN_TEXT = 'plain_text_response',
+ ERROR = 'error'
+}
+++ /dev/null
-export enum ToolSource {
- BUILTIN = 'builtin',
- MCP = 'mcp',
- CUSTOM = 'custom'
-}
-
-export enum ToolPermissionDecision {
- ALWAYS = 'always',
- ALWAYS_SERVER = 'always_server',
- ONCE = 'once',
- DENY = 'deny'
-}
-
-export enum ToolResponseField {
- PLAIN_TEXT = 'plain_text_response',
- ERROR = 'error'
-}
--- /dev/null
+export enum ColorMode {
+ LIGHT = 'light',
+ DARK = 'dark',
+ SYSTEM = 'system'
+}
+
+export enum TooltipSide {
+ TOP = 'top',
+ RIGHT = 'right',
+ BOTTOM = 'bottom',
+ LEFT = 'left'
+}
+
+/**
+ * MCP prompt display variant
+ */
+export enum McpPromptVariant {
+ MESSAGE = 'message',
+ ATTACHMENT = 'attachment'
+}
+
+/**
+ * URL prefixes for protocol detection
+ */
+export enum UrlProtocol {
+ DATA = 'data:',
+ HTTP = 'http:',
+ HTTPS = 'https:',
+ WEBSOCKET = 'ws:',
+ WEBSOCKET_SECURE = 'wss:'
+}
+
+export enum HtmlInputType {
+ FILE = 'file'
+}
+++ /dev/null
-export enum ColorMode {
- LIGHT = 'light',
- DARK = 'dark',
- SYSTEM = 'system'
-}
-
-export enum TooltipSide {
- TOP = 'top',
- RIGHT = 'right',
- BOTTOM = 'bottom',
- LEFT = 'left'
-}
-
-/**
- * MCP prompt display variant
- */
-export enum McpPromptVariant {
- MESSAGE = 'message',
- ATTACHMENT = 'attachment'
-}
-
-/**
- * URL prefixes for protocol detection
- */
-export enum UrlProtocol {
- DATA = 'data:',
- HTTP = 'http:',
- HTTPS = 'https:',
- WEBSOCKET = 'ws:',
- WEBSOCKET_SECURE = 'wss:'
-}
-
-export enum HtmlInputType {
- FILE = 'file'
-}
-import type { MCPConnectionPhase, MCPLogLevel, HealthCheckStatus } from '$lib/enums/mcp';
-import type { ToolSource } from '$lib/enums/tools';
+import type { MCPConnectionPhase, MCPLogLevel, HealthCheckStatus } from '$lib/enums/mcp.enums';
+import type { ToolSource } from '$lib/enums/tools.enums';
import type {
Client,
ClientCapabilities as SDKClientCapabilities,
import { untrack } from 'svelte';
import { onMount } from 'svelte';
import { fade } from 'svelte/transition';
+
import {
DesktopIconStrip,
DialogConversationTitleUpdate,
SidebarNavigation
} from '$lib/components/app';
+
import { conversationsStore } from '$lib/stores/conversations.svelte';
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
import * as Tooltip from '$lib/components/ui/tooltip';
import { conversations } from '$lib/stores/conversations.svelte';
let { children } = $props();
-
let alwaysShowSidebarOnDesktop = $derived(config().alwaysShowSidebarOnDesktop);
let isMobile = new IsMobile();
let isDesktop = $derived(!isMobile.current);
let sidebarOpen = $state(false);
let mounted = $state(false);
let innerHeight = $state<number | undefined>();
+
let chatSidebar:
- | { activateSearchMode?: () => void; editActiveConversation?: () => void }
+ | {
+ activateSearchMode?: () => void;
+ editActiveConversation?: () => void;
+ }
| undefined = $state();
let titleUpdateDialogOpen = $state(false);
let titleUpdateCurrentTitle = $state('');
let titleUpdateNewTitle = $state('');
let titleUpdateResolve: ((value: boolean) => void) | null = null;
-
const panelNav = useSettingsNavigation();
function navigateToConversation(direction: -1 | 1) {
const allConvs = conversations();
+
if (allConvs.length === 0) return;
const currentId = page.params.id;
}
const idx = allConvs.findIndex((c) => c.id === currentId);
+
if (idx === -1) return;
const targetIdx = idx + direction;
// Global keyboard shortcuts
const { handleKeydown } = useKeyboardShortcuts({
editActiveConversation: () => chatSidebar?.editActiveConversation?.(),
-
navigateToPrevConversation: () => navigateToConversation(-1),
-
navigateToNextConversation: () => navigateToConversation(1)
});
$effect(() => {
if (alwaysShowSidebarOnDesktop && isDesktop) {
sidebarOpen = true;
+
return;
}
});
// Only fetch router models once when we have models loaded and in router mode
if (isRouter && modelsCount > 0 && !routerModelsFetched) {
routerModelsFetched = true;
+
untrack(() => {
modelsStore.fetchRouterModels();
});
<Tooltip.Provider delayDuration={TOOLTIP_DELAY_DURATION}>
<ModeWatcher />
-
<Toaster richColors />
<DialogConversationTitleUpdate
<Sidebar.Provider bind:open={sidebarOpen}>
<div class="flex h-screen w-full" style:height="{innerHeight}px">
- <Sidebar.Root variant="floating" class="h-full">
- <SidebarNavigation bind:this={chatSidebar} />
- </Sidebar.Root>
+ <Sidebar.Root variant="floating" class="h-full"
+ ><SidebarNavigation bind:this={chatSidebar} /></Sidebar.Root
+ >
{#if !(alwaysShowSidebarOnDesktop && isDesktop) && !(panelNav.isSettingsRoute && !isDesktop)}
{#if mounted}
/>
{/if}
- <Sidebar.Inset class="flex flex-1 flex-col overflow-hidden">
- {@render children?.()}
- </Sidebar.Inset>
+ <Sidebar.Inset class="flex flex-1 flex-col overflow-hidden"
+ >{@render children?.()}</Sidebar.Inset
+ >
</div>
</Sidebar.Provider>
</Tooltip.Provider>
beforeEach(() => {
const originalFetch = globalThis.fetch;
- vi.spyOn(globalThis, 'fetch').mockImplementation(async (input: RequestInfo | URL, init?: RequestInit) => {
- const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
+ vi.spyOn(globalThis, 'fetch').mockImplementation(
+ async (input: RequestInfo | URL, init?: RequestInit) => {
+ const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
- // Mock server props endpoint
- if (url.includes('/server')) {
- return new Response(
- JSON.stringify({
- mode: 'router',
- version: 'test',
- git_commit: 'test',
- git_branch: 'test'
- }),
- { status: 200, headers: { 'Content-Type': 'application/json' } }
- );
- }
+ // Mock server props endpoint
+ if (url.includes('/server')) {
+ return new Response(
+ JSON.stringify({
+ mode: 'router',
+ version: 'test',
+ git_commit: 'test',
+ git_branch: 'test'
+ }),
+ { status: 200, headers: { 'Content-Type': 'application/json' } }
+ );
+ }
- // Mock models list endpoint
- if (/\/v1\/models|\/models\b/.test(url)) {
- return new Response(
- JSON.stringify({
- object: 'list',
- data: [
- {
- id: 'test-model.gguf',
- object: 'model',
- owned_by: 'llamacpp',
- created: 0,
- in_cache: false,
- path: 'models/test-model.gguf',
- status: { value: 'unloaded' },
- meta: {}
- }
- ],
- models: [
- {
- model: 'test-model.gguf',
- name: 'Test Model',
- details: {}
- }
- ]
- }),
- { status: 200, headers: { 'Content-Type': 'application/json' } }
- );
- }
+ // Mock models list endpoint
+ if (/\/v1\/models|\/models\b/.test(url)) {
+ return new Response(
+ JSON.stringify({
+ object: 'list',
+ data: [
+ {
+ id: 'test-model.gguf',
+ object: 'model',
+ owned_by: 'llamacpp',
+ created: 0,
+ in_cache: false,
+ path: 'models/test-model.gguf',
+ status: { value: 'unloaded' },
+ meta: {}
+ }
+ ],
+ models: [
+ {
+ model: 'test-model.gguf',
+ name: 'Test Model',
+ details: {}
+ }
+ ]
+ }),
+ { status: 200, headers: { 'Content-Type': 'application/json' } }
+ );
+ }
- // Mock /props endpoint (used for modalities)
- if (url.includes('/props')) {
- return new Response(
- JSON.stringify({
- default_generation_settings: { n_ctx: 2048 }
- }),
- { status: 200, headers: { 'Content-Type': 'application/json' } }
- );
- }
+ // Mock /props endpoint (used for modalities)
+ if (url.includes('/props')) {
+ return new Response(
+ JSON.stringify({
+ default_generation_settings: { n_ctx: 2048 }
+ }),
+ { status: 200, headers: { 'Content-Type': 'application/json' } }
+ );
+ }
- // Mock /tools endpoint (used for built-in tools list)
- if (url.includes('/tools')) {
- return new Response(JSON.stringify([]), {
- status: 200,
- headers: { 'Content-Type': 'application/json' }
- });
- }
+ // Mock /tools endpoint (used for built-in tools list)
+ if (url.includes('/tools')) {
+ return new Response(JSON.stringify([]), {
+ status: 200,
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
- // Default: use real fetch
- return originalFetch(input, init);
- });
+ // Default: use real fetch
+ return originalFetch(input, init);
+ }
+ );
});
--- /dev/null
+/// <reference types="@vitest/browser-playwright" />