docs: Centralize and enhance service documentation
This commit is contained in:
parent
530868f5a1
commit
c6e5da11e6
|
|
@ -16,38 +16,6 @@ import type { ApiChatMessageContentPart, ApiChatCompletionToolCall } from '$lib/
|
|||
import type { DatabaseMessageExtraMcpPrompt, DatabaseMessageExtraMcpResource } from '$lib/types';
|
||||
import { modelsStore } from '$lib/stores/models.svelte';
|
||||
|
||||
/**
|
||||
* ChatService - Low-level API communication layer for Chat Completions
|
||||
*
|
||||
* **Terminology - Chat vs Conversation:**
|
||||
* - **Chat**: The active interaction space with the Chat Completions API. This service
|
||||
* handles the real-time communication with the AI backend - sending messages, receiving
|
||||
* streaming responses, and managing request lifecycles. "Chat" is ephemeral and runtime-focused.
|
||||
* - **Conversation**: The persistent database entity storing all messages and metadata.
|
||||
* Managed by ConversationsService/Store, conversations persist across sessions.
|
||||
*
|
||||
* This service handles direct communication with the llama-server's Chat Completions API.
|
||||
* It provides the network layer abstraction for AI model interactions while remaining
|
||||
* stateless and focused purely on API communication.
|
||||
*
|
||||
* **Architecture & Relationships:**
|
||||
* - **ChatService** (this class): Stateless API communication layer
|
||||
* - Handles HTTP requests/responses with the llama-server
|
||||
* - Manages streaming and non-streaming response parsing
|
||||
* - Provides per-conversation request abortion capabilities
|
||||
* - Converts database messages to API format
|
||||
* - Handles error translation for server responses
|
||||
*
|
||||
* - **chatStore**: Uses ChatService for all AI model communication
|
||||
* - **conversationsStore**: Provides message context for API requests
|
||||
*
|
||||
* **Key Responsibilities:**
|
||||
* - Message format conversion (DatabaseMessage → API format)
|
||||
* - Streaming response handling with real-time callbacks
|
||||
* - Reasoning content extraction and processing
|
||||
* - File attachment processing (images, PDFs, audio, text)
|
||||
* - Request lifecycle management (abort via AbortSignal)
|
||||
*/
|
||||
export class ChatService {
|
||||
private static stripReasoningContent(
|
||||
content: ApiChatMessageData['content'] | null | undefined
|
||||
|
|
|
|||
|
|
@ -19,53 +19,6 @@ const db = new LlamacppDatabase();
|
|||
import { v4 as uuid } from 'uuid';
|
||||
import { MessageRole } from '$lib/enums';
|
||||
|
||||
/**
|
||||
* DatabaseService - Stateless IndexedDB communication layer
|
||||
*
|
||||
* **Terminology - Chat vs Conversation:**
|
||||
* - **Chat**: The active interaction space with the Chat Completions API (ephemeral, runtime).
|
||||
* - **Conversation**: The persistent database entity storing all messages and metadata.
|
||||
* This service handles raw database operations for conversations - the lowest layer
|
||||
* in the persistence stack.
|
||||
*
|
||||
* This service provides a stateless data access layer built on IndexedDB using Dexie ORM.
|
||||
* It handles all low-level storage operations for conversations and messages with support
|
||||
* for complex branching and message threading. All methods are static - no instance state.
|
||||
*
|
||||
* **Architecture & Relationships (bottom to top):**
|
||||
* - **DatabaseService** (this class): Stateless IndexedDB operations
|
||||
* - Lowest layer - direct Dexie/IndexedDB communication
|
||||
* - Pure CRUD operations without business logic
|
||||
* - Handles branching tree structure (parent-child relationships)
|
||||
* - Provides transaction safety for multi-table operations
|
||||
*
|
||||
* - **ConversationsService**: Stateless business logic layer
|
||||
* - Uses DatabaseService for all persistence operations
|
||||
* - Adds import/export, navigation, and higher-level operations
|
||||
*
|
||||
* - **conversationsStore**: Reactive state management for conversations
|
||||
* - Uses ConversationsService for database operations
|
||||
* - Manages conversation list, active conversation, and messages in memory
|
||||
*
|
||||
* - **chatStore**: Active AI interaction management
|
||||
* - Uses conversationsStore for conversation context
|
||||
* - Directly uses DatabaseService for message CRUD during streaming
|
||||
*
|
||||
* **Key Features:**
|
||||
* - **Conversation CRUD**: Create, read, update, delete conversations
|
||||
* - **Message CRUD**: Add, update, delete messages with branching support
|
||||
* - **Branch Operations**: Create branches, find descendants, cascade deletions
|
||||
* - **Transaction Safety**: Atomic operations for data consistency
|
||||
*
|
||||
* **Database Schema:**
|
||||
* - `conversations`: id, lastModified, currNode, name
|
||||
* - `messages`: id, convId, type, role, timestamp, parent, children
|
||||
*
|
||||
* **Branching Model:**
|
||||
* Messages form a tree structure where each message can have multiple children,
|
||||
* enabling conversation branching and alternative response paths. The conversation's
|
||||
* `currNode` tracks the currently active branch endpoint.
|
||||
*/
|
||||
export class DatabaseService {
|
||||
/**
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,6 +1,262 @@
|
|||
/**
|
||||
*
|
||||
* SERVICES
|
||||
*
|
||||
* Stateless service layer for API communication and data operations.
|
||||
* Services handle protocol-level concerns (HTTP, WebSocket, MCP, IndexedDB)
|
||||
* without managing reactive state — that responsibility belongs to stores.
|
||||
*
|
||||
* **Design Principles:**
|
||||
* - All methods are static — no instance state
|
||||
* - Pure I/O operations (network requests, database queries)
|
||||
* - No Svelte runes or reactive primitives
|
||||
* - Error handling at the protocol level; business-level error handling in stores
|
||||
*
|
||||
* **Architecture (bottom to top):**
|
||||
* - **Services** (this layer): Stateless protocol communication
|
||||
* - **Stores**: Reactive state management consuming services
|
||||
* - **Components**: UI consuming stores
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* **ChatService** - Chat Completions API communication layer
|
||||
*
|
||||
* Handles direct communication with the llama-server's `/v1/chat/completions` endpoint.
|
||||
* Provides streaming and non-streaming response parsing, message format conversion
|
||||
* (DatabaseMessage → API format), and request lifecycle management.
|
||||
*
|
||||
* **Terminology - Chat vs Conversation:**
|
||||
* - **Chat**: The active interaction space with the Chat Completions API. Ephemeral and
|
||||
* runtime-focused — sending messages, receiving streaming responses, managing request lifecycles.
|
||||
* - **Conversation**: The persistent database entity storing all messages and metadata.
|
||||
* Managed by conversationsStore, conversations persist across sessions.
|
||||
*
|
||||
* **Architecture & Relationships:**
|
||||
* - **ChatService** (this class): Stateless API communication layer
|
||||
* - Handles HTTP requests/responses with the llama-server
|
||||
* - Manages streaming and non-streaming response parsing
|
||||
* - Converts database messages to API format (multimodal, tool calls)
|
||||
* - Handles error translation with user-friendly messages
|
||||
*
|
||||
* - **chatStore**: Primary consumer — uses ChatService for all AI model communication
|
||||
* - **agenticStore**: Uses ChatService for multi-turn agentic loop streaming
|
||||
* - **conversationsStore**: Provides message context for API requests
|
||||
*
|
||||
* **Key Responsibilities:**
|
||||
* - Streaming response handling with real-time content/reasoning/tool-call callbacks
|
||||
* - Non-streaming response parsing with complete response extraction
|
||||
* - Database message to API format conversion (attachments, tool calls, multimodal)
|
||||
* - Tool call delta merging for incremental streaming aggregation
|
||||
* - Request parameter assembly (sampling, penalties, custom params)
|
||||
* - File attachment processing (images, PDFs, audio, text, MCP prompts/resources)
|
||||
* - Reasoning content stripping from prompt history to avoid KV cache pollution
|
||||
* - Error translation (network, timeout, server errors → user-friendly messages)
|
||||
*
|
||||
* @see chatStore in stores/chat.svelte.ts — primary consumer for chat state management
|
||||
* @see agenticStore in stores/agentic.svelte.ts — uses ChatService for agentic loop streaming
|
||||
* @see conversationsStore in stores/conversations.svelte.ts — provides message context
|
||||
*/
|
||||
export { ChatService } from './chat.service';
|
||||
|
||||
/**
|
||||
* **DatabaseService** - IndexedDB persistence layer via Dexie ORM
|
||||
*
|
||||
* Provides stateless data access for conversations and messages using IndexedDB.
|
||||
* Handles all low-level storage operations including branching tree structures,
|
||||
* cascade deletions, and transaction safety for multi-table operations.
|
||||
*
|
||||
* **Architecture & Relationships (bottom to top):**
|
||||
* - **DatabaseService** (this class): Stateless IndexedDB operations
|
||||
* - Lowest layer — direct Dexie/IndexedDB communication
|
||||
* - Pure CRUD operations without business logic
|
||||
* - Handles branching tree structure (parent-child relationships)
|
||||
* - Provides transaction safety for multi-table operations
|
||||
*
|
||||
* - **conversationsStore**: Reactive state management layer
|
||||
* - Uses DatabaseService for all persistence operations
|
||||
* - Manages conversation list, active conversation, and messages in memory
|
||||
*
|
||||
* - **chatStore**: Active AI interaction management
|
||||
* - Uses conversationsStore for conversation context
|
||||
* - Directly uses DatabaseService for message CRUD during streaming
|
||||
*
|
||||
* **Key Responsibilities:**
|
||||
* - Conversation CRUD (create, read, update, delete)
|
||||
* - Message CRUD with branching support (parent-child relationships)
|
||||
* - Root message and system prompt creation
|
||||
* - Cascade deletion of message branches (descendants)
|
||||
* - Transaction-safe multi-table operations
|
||||
* - Conversation import with duplicate detection
|
||||
*
|
||||
* **Database Schema:**
|
||||
* - `conversations`: id, lastModified, currNode, name
|
||||
* - `messages`: id, convId, type, role, timestamp, parent, children
|
||||
*
|
||||
* **Branching Model:**
|
||||
* Messages form a tree structure where each message can have multiple children,
|
||||
* enabling conversation branching and alternative response paths. The conversation's
|
||||
* `currNode` tracks the currently active branch endpoint.
|
||||
*
|
||||
* @see conversationsStore in stores/conversations.svelte.ts — reactive layer on top of DatabaseService
|
||||
* @see chatStore in stores/chat.svelte.ts — uses DatabaseService directly for message CRUD during streaming
|
||||
*/
|
||||
export { DatabaseService } from './database.service';
|
||||
|
||||
/**
|
||||
* **ModelsService** - Model management API communication
|
||||
*
|
||||
* Handles communication with model-related endpoints for both MODEL (single model)
|
||||
* and ROUTER (multi-model) server modes. Provides model listing, loading/unloading,
|
||||
* and status checking without managing any model state.
|
||||
*
|
||||
* **Architecture & Relationships:**
|
||||
* - **ModelsService** (this class): Stateless HTTP communication
|
||||
* - Sends requests to model endpoints
|
||||
* - Parses and returns typed API responses
|
||||
* - Provides model status utility methods
|
||||
*
|
||||
* - **modelsStore**: Primary consumer — manages reactive model state
|
||||
* - Calls ModelsService for all model API operations
|
||||
* - Handles polling, caching, and state updates
|
||||
*
|
||||
* **Key Responsibilities:**
|
||||
* - List available models via OpenAI-compatible `/v1/models` endpoint
|
||||
* - Load/unload models via `/models/load` and `/models/unload` (ROUTER mode)
|
||||
* - Model status queries (loaded, loading)
|
||||
*
|
||||
* **Server Mode Behavior:**
|
||||
* - **MODEL mode**: Only `list()` is relevant — single model always loaded
|
||||
* - **ROUTER mode**: Full lifecycle — `list()`, `listRouter()`, `load()`, `unload()`
|
||||
*
|
||||
* **Endpoints:**
|
||||
* - `GET /v1/models` — OpenAI-compatible model list (both modes)
|
||||
* - `POST /models/load` — Load a model (ROUTER mode only)
|
||||
* - `POST /models/unload` — Unload a model (ROUTER mode only)
|
||||
*
|
||||
* @see modelsStore in stores/models.svelte.ts — primary consumer for reactive model state
|
||||
*/
|
||||
export { ModelsService } from './models.service';
|
||||
|
||||
/**
|
||||
* **PropsService** - Server properties and capabilities retrieval
|
||||
*
|
||||
* Fetches server configuration, model information, and capabilities from the `/props`
|
||||
* endpoint. Supports both global server props and per-model props (ROUTER mode).
|
||||
*
|
||||
* **Architecture & Relationships:**
|
||||
* - **PropsService** (this class): Stateless HTTP communication
|
||||
* - Fetches server properties from `/props` endpoint
|
||||
* - Handles authentication and request parameters
|
||||
* - Returns typed `ApiLlamaCppServerProps` responses
|
||||
*
|
||||
* - **serverStore**: Consumes global server properties (role detection, connection state)
|
||||
* - **modelsStore**: Consumes per-model properties (modalities, context size)
|
||||
* - **settingsStore**: Syncs default generation parameters from props response
|
||||
*
|
||||
* **Key Responsibilities:**
|
||||
* - Fetch global server properties (default generation settings, modalities)
|
||||
* - Fetch per-model properties in ROUTER mode via `?model=<id>` parameter
|
||||
* - Handle autoload control to prevent unintended model loading
|
||||
*
|
||||
* **API Behavior:**
|
||||
* - `GET /props` → Global server props (MODEL mode: includes modalities)
|
||||
* - `GET /props?model=<id>` → Per-model props (ROUTER mode: model-specific modalities)
|
||||
* - `&autoload=false` → Prevents model auto-loading when querying props
|
||||
*
|
||||
* @see serverStore in stores/server.svelte.ts — consumes global server props
|
||||
* @see modelsStore in stores/models.svelte.ts — consumes per-model props for modalities
|
||||
* @see settingsStore in stores/settings.svelte.ts — syncs default generation params from props
|
||||
*/
|
||||
export { PropsService } from './props.service';
|
||||
|
||||
/**
|
||||
* **ParameterSyncService** - Server defaults and user settings synchronization
|
||||
*
|
||||
* Manages the complex logic of merging server-provided default parameters with
|
||||
* user-configured overrides. Ensures the UI reflects the actual server state
|
||||
* while preserving user customizations. Tracks parameter sources (server default
|
||||
* vs user override) for display in the settings UI.
|
||||
*
|
||||
* **Architecture & Relationships:**
|
||||
* - **ParameterSyncService** (this class): Stateless sync logic
|
||||
* - Pure functions for parameter extraction, merging, and diffing
|
||||
* - No side effects — receives data in, returns data out
|
||||
* - Handles floating-point precision normalization
|
||||
*
|
||||
* - **settingsStore**: Primary consumer — calls sync methods during:
|
||||
* - Initial load (`syncWithServerDefaults`)
|
||||
* - Settings reset (`forceSyncWithServerDefaults`)
|
||||
* - Parameter info queries (`getParameterInfo`)
|
||||
*
|
||||
* - **PropsService**: Provides raw server props that feed into extraction
|
||||
*
|
||||
* **Key Responsibilities:**
|
||||
* - Extract syncable parameters from server `/props` response
|
||||
* - Merge server defaults with user overrides (user wins)
|
||||
* - Track parameter source (Custom vs Default) for UI badges
|
||||
* - Validate server parameter values by type (number, string, boolean)
|
||||
* - Create diffs between current settings and server defaults
|
||||
* - Floating-point precision normalization for consistent comparisons
|
||||
*
|
||||
* **Parameter Source Priority:**
|
||||
* 1. **User Override** (Custom badge) — explicitly set by user in settings
|
||||
* 2. **Server Default** (Default badge) — from `/props` endpoint
|
||||
* 3. **App Default** — hardcoded fallback when server props unavailable
|
||||
*
|
||||
* **Exports:**
|
||||
* - `ParameterSyncService` class — static methods for sync logic
|
||||
* - `SYNCABLE_PARAMETERS` — mapping of webui setting keys to server parameter keys
|
||||
*
|
||||
* @see settingsStore in stores/settings.svelte.ts — primary consumer for settings sync
|
||||
* @see ChatSettingsParameterSourceIndicator — displays parameter source badges in UI
|
||||
*/
|
||||
export { ParameterSyncService } from './parameter-sync.service';
|
||||
|
||||
/**
|
||||
* **MCPService** - Low-level MCP protocol communication layer
|
||||
*
|
||||
* Implements the client-side MCP (Model Context Protocol) SDK operations for connecting
|
||||
* to MCP servers, discovering capabilities, and executing protocol operations.
|
||||
* Supports multiple transport types: WebSocket, StreamableHTTP, and SSE (legacy fallback).
|
||||
*
|
||||
* **Architecture & Relationships:**
|
||||
* - **MCPService** (this class): Stateless protocol communication
|
||||
* - Creates and manages transport connections (WebSocket, StreamableHTTP, SSE)
|
||||
* - Wraps MCP SDK client operations with error handling
|
||||
* - Formats tool results and extracts server info
|
||||
* - Provides abort signal support for cancellable operations
|
||||
*
|
||||
* - **mcpStore**: Reactive business logic facade
|
||||
* - Uses MCPService for all protocol-level operations
|
||||
* - Manages connection lifecycle, health checks, reconnection
|
||||
* - Handles tool name conflict resolution and server coordination
|
||||
*
|
||||
* - **mcpResourceStore**: Reactive resource state
|
||||
* - Receives resource data fetched via MCPService
|
||||
* - Manages resource caching, subscriptions, and attachments
|
||||
*
|
||||
* - **agenticStore**: Agentic loop orchestration
|
||||
* - Executes tool calls via mcpStore → MCPService chain
|
||||
*
|
||||
* **Key Responsibilities:**
|
||||
* - Transport creation with automatic fallback (StreamableHTTP → SSE)
|
||||
* - Server connection with detailed phase tracking and progress callbacks
|
||||
* - Tool discovery (`listTools`) and execution (`callTool`) with abort support
|
||||
* - Prompt listing (`listPrompts`) and retrieval (`getPrompt`) with arguments
|
||||
* - Resource operations: list, read, subscribe/unsubscribe, template support
|
||||
* - Completion suggestions for prompt arguments and resource URI templates
|
||||
* - CORS proxy routing via llama-server for cross-origin MCP servers
|
||||
* - Tool result formatting (text, images, embedded resources)
|
||||
*
|
||||
* **Transport Hierarchy:**
|
||||
* 1. **WebSocket** — bidirectional, no CORS proxy support
|
||||
* 2. **StreamableHTTP** — modern HTTP-based, supports CORS proxy
|
||||
* 3. **SSE** — legacy fallback, supports CORS proxy
|
||||
*
|
||||
* @see mcpStore in stores/mcp.svelte.ts — reactive business logic facade on top of MCPService
|
||||
* @see mcpResourceStore in stores/mcp-resources.svelte.ts — reactive resource state management
|
||||
* @see agenticStore in stores/agentic.svelte.ts — uses MCPService (via mcpStore) for tool execution
|
||||
* @see MCP Protocol Specification: https://modelcontextprotocol.io/specification/2025-06-18
|
||||
*/
|
||||
export { MCPService } from './mcp.service';
|
||||
|
|
|
|||
|
|
@ -1,18 +1,3 @@
|
|||
/**
|
||||
* MCPService - Stateless MCP Protocol Communication Layer
|
||||
*
|
||||
* Low-level MCP operations:
|
||||
* - Transport creation (WebSocket, StreamableHTTP, SSE)
|
||||
* - Server connection/disconnection
|
||||
* - Tool discovery (listTools)
|
||||
* - Tool execution (callTool)
|
||||
*
|
||||
* NO business logic, NO state management, NO orchestration.
|
||||
* This is the protocol layer - pure MCP SDK operations.
|
||||
*
|
||||
* @see mcpStore in stores/mcp.svelte.ts for business logic facade
|
||||
*/
|
||||
|
||||
import { Client } from '@modelcontextprotocol/sdk/client';
|
||||
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
||||
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
|
||||
|
|
@ -70,7 +55,13 @@ interface ToolCallResult {
|
|||
|
||||
export class MCPService {
|
||||
/**
|
||||
* Create a connection log entry
|
||||
* Create a connection log entry for phase tracking.
|
||||
*
|
||||
* @param phase - The connection phase this log belongs to
|
||||
* @param message - Human-readable log message
|
||||
* @param level - Log severity level (default: INFO)
|
||||
* @param details - Optional structured details for debugging
|
||||
* @returns Formatted connection log entry
|
||||
*/
|
||||
private static createLog(
|
||||
phase: MCPConnectionPhase,
|
||||
|
|
@ -90,8 +81,16 @@ export class MCPService {
|
|||
/**
|
||||
* Create transport based on server configuration.
|
||||
* Supports WebSocket, StreamableHTTP (modern), and SSE (legacy) transports.
|
||||
* When useProxy is enabled, routes HTTP requests through llama-server's CORS proxy.
|
||||
* Returns both transport and the type used.
|
||||
* When `useProxy` is enabled, routes HTTP requests through llama-server's CORS proxy.
|
||||
*
|
||||
* **Fallback Order:**
|
||||
* 1. WebSocket — if explicitly configured (no CORS proxy support)
|
||||
* 2. StreamableHTTP — default for HTTP connections
|
||||
* 3. SSE — automatic fallback if StreamableHTTP fails
|
||||
*
|
||||
* @param config - Server configuration with url, transport type, proxy, and auth settings
|
||||
* @returns Object containing the created transport and the transport type used
|
||||
* @throws {Error} If url is missing, WebSocket + proxy combination, or all transports fail
|
||||
*/
|
||||
static createTransport(config: MCPServerConfig): {
|
||||
transport: Transport;
|
||||
|
|
@ -166,7 +165,11 @@ export class MCPService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Extract server info from SDK Implementation type
|
||||
* Extract server info from SDK Implementation type.
|
||||
* Normalizes the SDK's server version response into our MCPServerInfo type.
|
||||
*
|
||||
* @param impl - Raw Implementation object from MCP SDK
|
||||
* @returns Normalized server info or undefined if input is empty
|
||||
*/
|
||||
private static extractServerInfo(impl: Implementation | undefined): MCPServerInfo | undefined {
|
||||
if (!impl) {
|
||||
|
|
@ -189,9 +192,23 @@ export class MCPService {
|
|||
|
||||
/**
|
||||
* Connect to a single MCP server with detailed phase tracking.
|
||||
* Returns connection object with client, transport, discovered tools, and connection details.
|
||||
* @param onPhase - Optional callback for connection phase changes
|
||||
* @param listChangedHandlers - Optional handlers for list changed notifications
|
||||
*
|
||||
* Performs the full MCP connection lifecycle:
|
||||
* 1. Transport creation (with automatic fallback)
|
||||
* 2. Client initialization and capability exchange
|
||||
* 3. Tool discovery via `listTools`
|
||||
*
|
||||
* Reports progress via `onPhase` callback at each step, enabling
|
||||
* UI progress indicators during connection.
|
||||
*
|
||||
* @param serverName - Display name for the server (used in logging)
|
||||
* @param serverConfig - Server URL, transport type, proxy, and auth configuration
|
||||
* @param clientInfo - Optional client identification (defaults to app info)
|
||||
* @param capabilities - Optional client capability declaration
|
||||
* @param onPhase - Optional callback for connection phase progress updates
|
||||
* @param listChangedHandlers - Optional handlers for server-initiated list change notifications
|
||||
* @returns Full connection object with client, transport, tools, server info, and timing
|
||||
* @throws {Error} If transport creation or connection fails
|
||||
*/
|
||||
static async connect(
|
||||
serverName: string,
|
||||
|
|
@ -331,6 +348,9 @@ export class MCPService {
|
|||
|
||||
/**
|
||||
* Disconnect from a server.
|
||||
* Clears the `onclose` handler to prevent reconnection attempts on voluntary disconnect.
|
||||
*
|
||||
* @param connection - The active MCP connection to close
|
||||
*/
|
||||
static async disconnect(connection: MCPConnection): Promise<void> {
|
||||
console.log(`[MCPService][${connection.serverName}] Disconnecting...`);
|
||||
|
|
@ -348,6 +368,10 @@ export class MCPService {
|
|||
|
||||
/**
|
||||
* List tools from a connection.
|
||||
* Silently returns empty array on failure (logged as warning).
|
||||
*
|
||||
* @param connection - The MCP connection to query
|
||||
* @returns Array of available tools, or empty array on error
|
||||
*/
|
||||
static async listTools(connection: MCPConnection): Promise<Tool[]> {
|
||||
try {
|
||||
|
|
@ -363,6 +387,10 @@ export class MCPService {
|
|||
|
||||
/**
|
||||
* List prompts from a connection.
|
||||
* Silently returns empty array on failure (logged as warning).
|
||||
*
|
||||
* @param connection - The MCP connection to query
|
||||
* @returns Array of available prompts, or empty array on error
|
||||
*/
|
||||
static async listPrompts(connection: MCPConnection): Promise<Prompt[]> {
|
||||
try {
|
||||
|
|
@ -378,6 +406,14 @@ export class MCPService {
|
|||
|
||||
/**
|
||||
* Get a specific prompt with arguments.
|
||||
* Unlike list operations, this throws on failure since the caller explicitly
|
||||
* requested a specific prompt and needs to handle the error.
|
||||
*
|
||||
* @param connection - The MCP connection to use
|
||||
* @param name - The prompt name to retrieve
|
||||
* @param args - Optional key-value arguments to pass to the prompt
|
||||
* @returns The prompt result with messages and metadata
|
||||
* @throws {Error} If the prompt retrieval fails
|
||||
*/
|
||||
static async getPrompt(
|
||||
connection: MCPConnection,
|
||||
|
|
@ -395,6 +431,14 @@ export class MCPService {
|
|||
|
||||
/**
|
||||
* Execute a tool call on a connection.
|
||||
* Supports abort signal for cancellable operations (e.g., when user stops generation).
|
||||
* Formats the raw tool result into a string representation.
|
||||
*
|
||||
* @param connection - The MCP connection to execute against
|
||||
* @param params - Tool name and arguments to execute
|
||||
* @param signal - Optional AbortSignal for cancellation support
|
||||
* @returns Formatted tool execution result with content string and error flag
|
||||
* @throws {Error} If tool execution fails or is aborted
|
||||
*/
|
||||
static async callTool(
|
||||
connection: MCPConnection,
|
||||
|
|
@ -426,7 +470,11 @@ export class MCPService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Format tool result content to string.
|
||||
* Format tool result content items to a single string.
|
||||
* Handles text, image (base64 data URL), and embedded resource content types.
|
||||
*
|
||||
* @param result - Raw tool call result from MCP SDK
|
||||
* @returns Concatenated string representation of all content items
|
||||
*/
|
||||
private static formatToolResult(result: ToolCallResult): string {
|
||||
const content = result.content;
|
||||
|
|
@ -661,10 +709,11 @@ export class MCPService {
|
|||
|
||||
/**
|
||||
* Check if a connection supports resources.
|
||||
* Per MCP spec: presence of the `resources` key (even as empty object {}) indicates support.
|
||||
* Per MCP spec: presence of the `resources` key (even as empty object `{}`) indicates support.
|
||||
* Empty object means resources are supported but no sub-features (subscribe, listChanged).
|
||||
*
|
||||
* @param connection - The MCP connection to check
|
||||
* @returns Whether the server supports resources
|
||||
* @returns Whether the server declares the resources capability
|
||||
*/
|
||||
static supportsResources(connection: MCPConnection): boolean {
|
||||
// Per MCP spec: "Servers that support resources MUST declare the resources capability"
|
||||
|
|
|
|||
|
|
@ -1,21 +1,6 @@
|
|||
import { ServerModelStatus } from '$lib/enums';
|
||||
import { apiFetch, apiPost } from '$lib/utils';
|
||||
|
||||
/**
|
||||
* ModelsService - Stateless service for model management API communication
|
||||
*
|
||||
* This service handles communication with model-related endpoints:
|
||||
* - `/v1/models` - OpenAI-compatible model list (MODEL + ROUTER mode)
|
||||
* - `/models/load`, `/models/unload` - Router-specific model management (ROUTER mode only)
|
||||
*
|
||||
* **Responsibilities:**
|
||||
* - List available models
|
||||
* - Load/unload models (ROUTER mode)
|
||||
* - Check model status (ROUTER mode)
|
||||
*
|
||||
* **Used by:**
|
||||
* - modelsStore: Primary consumer for model state management
|
||||
*/
|
||||
export class ModelsService {
|
||||
/**
|
||||
*
|
||||
|
|
@ -26,16 +11,21 @@ export class ModelsService {
|
|||
*/
|
||||
|
||||
/**
|
||||
* Fetch list of models from OpenAI-compatible endpoint
|
||||
* Works in both MODEL and ROUTER modes
|
||||
* Fetch list of models from OpenAI-compatible endpoint.
|
||||
* Works in both MODEL and ROUTER modes.
|
||||
*
|
||||
* @returns List of available models with basic metadata
|
||||
*/
|
||||
static async list(): Promise<ApiModelListResponse> {
|
||||
return apiFetch<ApiModelListResponse>('/v1/models');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch list of all models with detailed metadata (ROUTER mode)
|
||||
* Fetch list of all models with detailed metadata (ROUTER mode).
|
||||
* Returns models with load status, paths, and other metadata
|
||||
* beyond what the OpenAI-compatible endpoint provides.
|
||||
*
|
||||
* @returns List of models with detailed status and configuration info
|
||||
*/
|
||||
static async listRouter(): Promise<ApiRouterModelsListResponse> {
|
||||
return apiFetch<ApiRouterModelsListResponse>('/v1/models');
|
||||
|
|
@ -50,10 +40,13 @@ export class ModelsService {
|
|||
*/
|
||||
|
||||
/**
|
||||
* Load a model (ROUTER mode)
|
||||
* POST /models/load
|
||||
* Load a model (ROUTER mode only).
|
||||
* Sends POST request to `/models/load`. Note: the endpoint returns success
|
||||
* before loading completes — use polling to await actual load status.
|
||||
*
|
||||
* @param modelId - Model identifier to load
|
||||
* @param extraArgs - Optional additional arguments to pass to the model instance
|
||||
* @returns Load response from the server
|
||||
*/
|
||||
static async load(modelId: string, extraArgs?: string[]): Promise<ApiRouterModelsLoadResponse> {
|
||||
const payload: { model: string; extra_args?: string[] } = { model: modelId };
|
||||
|
|
@ -65,9 +58,12 @@ export class ModelsService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Unload a model (ROUTER mode)
|
||||
* POST /models/unload
|
||||
* Unload a model (ROUTER mode only).
|
||||
* Sends POST request to `/models/unload`. Note: the endpoint returns success
|
||||
* before unloading completes — use polling to await actual unload status.
|
||||
*
|
||||
* @param modelId - Model identifier to unload
|
||||
* @returns Unload response from the server
|
||||
*/
|
||||
static async unload(modelId: string): Promise<ApiRouterModelsUnloadResponse> {
|
||||
return apiPost<ApiRouterModelsUnloadResponse>('/models/unload', { model: modelId });
|
||||
|
|
@ -82,14 +78,20 @@ export class ModelsService {
|
|||
*/
|
||||
|
||||
/**
|
||||
* Check if a model is loaded based on its metadata
|
||||
* Check if a model is loaded based on its metadata.
|
||||
*
|
||||
* @param model - Model data entry from the API response
|
||||
* @returns True if the model status is LOADED
|
||||
*/
|
||||
static isModelLoaded(model: ApiModelDataEntry): boolean {
|
||||
return model.status.value === ServerModelStatus.LOADED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a model is currently loading
|
||||
* Check if a model is currently loading.
|
||||
*
|
||||
* @param model - Model data entry from the API response
|
||||
* @returns True if the model status is LOADING
|
||||
*/
|
||||
static isModelLoading(model: ApiModelDataEntry): boolean {
|
||||
return model.status.value === ServerModelStatus.LOADING;
|
||||
|
|
|
|||
|
|
@ -1,24 +1,12 @@
|
|||
/**
|
||||
* ParameterSyncService - Handles synchronization between server defaults and user settings
|
||||
*
|
||||
* This service manages the complex logic of merging server-provided default parameters
|
||||
* with user-configured overrides, ensuring the UI reflects the actual server state
|
||||
* while preserving user customizations.
|
||||
*
|
||||
* **Key Responsibilities:**
|
||||
* - Extract syncable parameters from server props
|
||||
* - Merge server defaults with user overrides
|
||||
* - Track parameter sources (server, user, default)
|
||||
* - Provide sync utilities for settings store integration
|
||||
*/
|
||||
|
||||
import { normalizeFloatingPoint } from '$lib/utils';
|
||||
import type { SyncableParameter, ParameterRecord, ParameterInfo, ParameterValue } from '$lib/types';
|
||||
import { SyncableParameterType, ParameterSource } from '$lib/enums';
|
||||
|
||||
/**
|
||||
* Mapping of webui setting keys to server parameter keys
|
||||
* Only parameters that should be synced from server are included
|
||||
* Mapping of webui setting keys to server parameter keys.
|
||||
* Only parameters listed here can be synced from the server `/props` endpoint.
|
||||
* Each entry defines the webui key, corresponding server key, value type,
|
||||
* and whether sync is enabled.
|
||||
*/
|
||||
export const SYNCABLE_PARAMETERS: SyncableParameter[] = [
|
||||
{
|
||||
|
|
@ -178,14 +166,24 @@ export class ParameterSyncService {
|
|||
*/
|
||||
|
||||
/**
|
||||
* Round floating-point numbers to avoid JavaScript precision issues
|
||||
* Round floating-point numbers to avoid JavaScript precision issues.
|
||||
* E.g., 0.1 + 0.2 = 0.30000000000000004 → 0.3
|
||||
*
|
||||
* @param value - Parameter value to normalize
|
||||
* @returns Precision-normalized value
|
||||
*/
|
||||
private static roundFloatingPoint(value: ParameterValue): ParameterValue {
|
||||
return normalizeFloatingPoint(value) as ParameterValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract server default parameters that can be synced
|
||||
* Extract server default parameters that can be synced from `/props` response.
|
||||
* Handles both generation settings parameters and webui-specific settings.
|
||||
* Converts samplers array to semicolon-delimited string for UI display.
|
||||
*
|
||||
* @param serverParams - Raw generation settings from server `/props` endpoint
|
||||
* @param webuiSettings - Optional webui-specific settings from server
|
||||
* @returns Record of extracted parameter key-value pairs with normalized precision
|
||||
*/
|
||||
static extractServerDefaults(
|
||||
serverParams: ApiLlamaCppServerProps['default_generation_settings']['params'] | null,
|
||||
|
|
@ -235,8 +233,14 @@ export class ParameterSyncService {
|
|||
*/
|
||||
|
||||
/**
|
||||
* Merge server defaults with current user settings
|
||||
* Returns updated settings that respect user overrides while using server defaults
|
||||
* Merge server defaults with current user settings.
|
||||
* User overrides always take priority — only parameters not in `userOverrides`
|
||||
* set will be updated from server defaults.
|
||||
*
|
||||
* @param currentSettings - Current parameter values in the settings store
|
||||
* @param serverDefaults - Default values extracted from server props
|
||||
* @param userOverrides - Set of parameter keys explicitly overridden by the user
|
||||
* @returns Merged parameter record with user overrides preserved
|
||||
*/
|
||||
static mergeWithServerDefaults(
|
||||
currentSettings: ParameterRecord,
|
||||
|
|
@ -264,7 +268,15 @@ export class ParameterSyncService {
|
|||
*/
|
||||
|
||||
/**
|
||||
* Get parameter information including source and values
|
||||
* Get parameter information including source and values.
|
||||
* Used by ChatSettingsParameterSourceIndicator to display the correct badge
|
||||
* (Custom vs Default) for each parameter in the settings UI.
|
||||
*
|
||||
* @param key - The parameter key to get info for
|
||||
* @param currentValue - The current value of the parameter
|
||||
* @param propsDefaults - Server default values from `/props`
|
||||
* @param userOverrides - Set of parameter keys explicitly overridden by the user
|
||||
* @returns Parameter info with source, server default, and user override values
|
||||
*/
|
||||
static getParameterInfo(
|
||||
key: string,
|
||||
|
|
@ -287,21 +299,30 @@ export class ParameterSyncService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if a parameter can be synced from server
|
||||
* Check if a parameter can be synced from server.
|
||||
*
|
||||
* @param key - The parameter key to check
|
||||
* @returns True if the parameter is in the syncable parameters list
|
||||
*/
|
||||
static canSyncParameter(key: string): boolean {
|
||||
return SYNCABLE_PARAMETERS.some((param) => param.key === key && param.canSync);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all syncable parameter keys
|
||||
* Get all syncable parameter keys.
|
||||
*
|
||||
* @returns Array of parameter keys that can be synced from server
|
||||
*/
|
||||
static getSyncableParameterKeys(): string[] {
|
||||
return SYNCABLE_PARAMETERS.filter((param) => param.canSync).map((param) => param.key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate server parameter value
|
||||
* Validate a server parameter value against its expected type.
|
||||
*
|
||||
* @param key - The parameter key to validate
|
||||
* @param value - The value to validate
|
||||
* @returns True if value matches the expected type for this parameter
|
||||
*/
|
||||
static validateServerParameter(key: string, value: ParameterValue): boolean {
|
||||
const param = SYNCABLE_PARAMETERS.find((p) => p.key === key);
|
||||
|
|
@ -328,7 +349,13 @@ export class ParameterSyncService {
|
|||
*/
|
||||
|
||||
/**
|
||||
* Create a diff between current settings and server defaults
|
||||
* Create a diff between current settings and server defaults.
|
||||
* Shows which parameters differ from server values, useful for debugging
|
||||
* and for the "Reset to defaults" functionality.
|
||||
*
|
||||
* @param currentSettings - Current parameter values in the settings store
|
||||
* @param serverDefaults - Default values extracted from server props
|
||||
* @returns Record of parameter diffs with current value, server value, and whether they differ
|
||||
*/
|
||||
static createParameterDiff(
|
||||
currentSettings: ParameterRecord,
|
||||
|
|
|
|||
|
|
@ -1,19 +1,5 @@
|
|||
import { apiFetchWithParams } from '$lib/utils';
|
||||
|
||||
/**
|
||||
* PropsService - Server properties management
|
||||
*
|
||||
* This service handles communication with the /props endpoint to retrieve
|
||||
* server configuration, model information, and capabilities.
|
||||
*
|
||||
* **Responsibilities:**
|
||||
* - Fetch server properties from /props endpoint
|
||||
* - Handle API authentication
|
||||
* - Parse and validate server response
|
||||
*
|
||||
* **Used by:**
|
||||
* - serverStore: Primary consumer for server state management
|
||||
*/
|
||||
export class PropsService {
|
||||
/**
|
||||
*
|
||||
|
|
@ -24,10 +10,12 @@ export class PropsService {
|
|||
*/
|
||||
|
||||
/**
|
||||
* Fetches server properties from the /props endpoint
|
||||
* Fetches global server properties from the `/props` endpoint.
|
||||
* In MODEL mode, returns modalities for the single loaded model.
|
||||
* In ROUTER mode, returns server-wide settings without model-specific modalities.
|
||||
*
|
||||
* @param autoload - If false, prevents automatic model loading (default: false)
|
||||
* @returns {Promise<ApiLlamaCppServerProps>} Server properties
|
||||
* @returns Server properties including default generation settings and capabilities
|
||||
* @throws {Error} If the request fails or returns invalid data
|
||||
*/
|
||||
static async fetch(autoload = false): Promise<ApiLlamaCppServerProps> {
|
||||
|
|
@ -40,12 +28,13 @@ export class PropsService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Fetches server properties for a specific model (ROUTER mode)
|
||||
* Fetches server properties for a specific model (ROUTER mode only).
|
||||
* Required in ROUTER mode because global `/props` does not include per-model modalities.
|
||||
*
|
||||
* @param modelId - The model ID to fetch properties for
|
||||
* @param autoload - If false, prevents automatic model loading (default: false)
|
||||
* @returns {Promise<ApiLlamaCppServerProps>} Server properties for the model
|
||||
* @throws {Error} If the request fails or returns invalid data
|
||||
* @returns Server properties specific to the requested model
|
||||
* @throws {Error} If the request fails, model not found, or model not loaded
|
||||
*/
|
||||
static async fetchForModel(modelId: string, autoload = false): Promise<ApiLlamaCppServerProps> {
|
||||
const params: Record<string, string> = { model: modelId };
|
||||
|
|
|
|||
Loading…
Reference in New Issue