refactor: Enums
This commit is contained in:
parent
7f5284d597
commit
ee9efae203
|
|
@ -919,11 +919,11 @@ export class MCPClient {
|
|||
async runHealthCheck(server: HealthCheckParams): Promise<void> {
|
||||
const trimmedUrl = server.url.trim();
|
||||
const logs: MCPConnectionLog[] = [];
|
||||
let currentPhase: MCPConnectionPhase = MCPConnectionPhase.Idle;
|
||||
let currentPhase: MCPConnectionPhase = MCPConnectionPhase.IDLE;
|
||||
|
||||
if (!trimmedUrl) {
|
||||
mcpStore.updateHealthCheck(server.id, {
|
||||
status: HealthCheckStatus.Error,
|
||||
status: HealthCheckStatus.ERROR,
|
||||
message: 'Please enter a server URL first.',
|
||||
logs: []
|
||||
});
|
||||
|
|
@ -932,8 +932,8 @@ export class MCPClient {
|
|||
|
||||
// Initial connecting state
|
||||
mcpStore.updateHealthCheck(server.id, {
|
||||
status: HealthCheckStatus.Connecting,
|
||||
phase: MCPConnectionPhase.TransportCreating,
|
||||
status: HealthCheckStatus.CONNECTING,
|
||||
phase: MCPConnectionPhase.TRANSPORT_CREATING,
|
||||
logs: []
|
||||
});
|
||||
|
||||
|
|
@ -957,7 +957,7 @@ export class MCPClient {
|
|||
currentPhase = phase;
|
||||
logs.push(log);
|
||||
mcpStore.updateHealthCheck(server.id, {
|
||||
status: HealthCheckStatus.Connecting,
|
||||
status: HealthCheckStatus.CONNECTING,
|
||||
phase,
|
||||
logs: [...logs]
|
||||
});
|
||||
|
|
@ -976,7 +976,7 @@ export class MCPClient {
|
|||
);
|
||||
|
||||
mcpStore.updateHealthCheck(server.id, {
|
||||
status: HealthCheckStatus.Success,
|
||||
status: HealthCheckStatus.SUCCESS,
|
||||
tools,
|
||||
serverInfo: connection.serverInfo,
|
||||
capabilities,
|
||||
|
|
@ -992,12 +992,12 @@ export class MCPClient {
|
|||
const message = error instanceof Error ? error.message : 'Unknown error occurred';
|
||||
logs.push({
|
||||
timestamp: new Date(),
|
||||
phase: MCPConnectionPhase.Error,
|
||||
phase: MCPConnectionPhase.ERROR,
|
||||
message: `Connection failed: ${message}`,
|
||||
level: MCPLogLevel.Error
|
||||
level: MCPLogLevel.ERROR
|
||||
});
|
||||
mcpStore.updateHealthCheck(server.id, {
|
||||
status: HealthCheckStatus.Error,
|
||||
status: HealthCheckStatus.ERROR,
|
||||
message,
|
||||
phase: currentPhase,
|
||||
logs
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { ChatMessageMcpPromptContent, RemoveButton } from '$lib/components/app';
|
||||
import type { DatabaseMessageExtraMcpPrompt } from '$lib/types';
|
||||
import { McpPromptVariant } from '$lib/enums';
|
||||
|
||||
interface Props {
|
||||
class?: string;
|
||||
|
|
@ -22,7 +23,12 @@
|
|||
</script>
|
||||
|
||||
<div class="group relative {className}">
|
||||
<ChatMessageMcpPromptContent {prompt} variant="attachment" {isLoading} {loadError} />
|
||||
<ChatMessageMcpPromptContent
|
||||
{prompt}
|
||||
variant={McpPromptVariant.ATTACHMENT}
|
||||
{isLoading}
|
||||
{loadError}
|
||||
/>
|
||||
|
||||
{#if !readonly && onRemove}
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -67,7 +67,10 @@
|
|||
}
|
||||
|
||||
type ReasoningSegment = {
|
||||
type: 'text' | 'reasoning' | 'reasoning_pending';
|
||||
type:
|
||||
| AgenticSectionType.TEXT
|
||||
| AgenticSectionType.REASONING
|
||||
| AgenticSectionType.REASONING_PENDING;
|
||||
content: string;
|
||||
};
|
||||
|
||||
|
|
@ -90,7 +93,7 @@
|
|||
if (startIndex === -1) {
|
||||
const remainingText = rawContent.slice(cursor);
|
||||
if (remainingText) {
|
||||
segments.push({ type: 'text', content: remainingText });
|
||||
segments.push({ type: AgenticSectionType.TEXT, content: remainingText });
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -98,7 +101,7 @@
|
|||
if (startIndex > cursor) {
|
||||
const textBefore = rawContent.slice(cursor, startIndex);
|
||||
if (textBefore) {
|
||||
segments.push({ type: 'text', content: textBefore });
|
||||
segments.push({ type: AgenticSectionType.TEXT, content: textBefore });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,14 +111,14 @@
|
|||
if (endIndex === -1) {
|
||||
const pendingContent = rawContent.slice(contentStart);
|
||||
segments.push({
|
||||
type: 'reasoning_pending',
|
||||
type: AgenticSectionType.REASONING_PENDING,
|
||||
content: stripPartialMarker(pendingContent)
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
const reasoningContent = rawContent.slice(contentStart, endIndex);
|
||||
segments.push({ type: 'reasoning', content: reasoningContent });
|
||||
segments.push({ type: AgenticSectionType.REASONING, content: reasoningContent });
|
||||
cursor = endIndex + REASONING_TAGS.END.length;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { ChatMessageActions, ChatMessageMcpPromptContent } from '$lib/components/app';
|
||||
import { MessageRole } from '$lib/enums';
|
||||
import { MessageRole, McpPromptVariant } from '$lib/enums';
|
||||
import type { DatabaseMessageExtraMcpPrompt } from '$lib/types';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -44,7 +44,11 @@
|
|||
class="group flex flex-col items-end gap-3 md:gap-2 {className}"
|
||||
role="group"
|
||||
>
|
||||
<ChatMessageMcpPromptContent prompt={mcpPrompt} variant="message" class="w-full max-w-[80%]" />
|
||||
<ChatMessageMcpPromptContent
|
||||
prompt={mcpPrompt}
|
||||
variant={McpPromptVariant.MESSAGE}
|
||||
class="w-full max-w-[80%]"
|
||||
/>
|
||||
|
||||
{#if message.timestamp}
|
||||
<div class="max-w-[80%]">
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
import { getFaviconUrl } from '$lib/utils';
|
||||
import { mcpStore } from '$lib/stores/mcp.svelte';
|
||||
import { SvelteMap } from 'svelte/reactivity';
|
||||
import { McpPromptVariant } from '$lib/enums';
|
||||
|
||||
interface ContentPart {
|
||||
text: string;
|
||||
|
|
@ -13,7 +14,7 @@
|
|||
interface Props {
|
||||
class?: string;
|
||||
prompt: DatabaseMessageExtraMcpPrompt;
|
||||
variant?: 'message' | 'attachment';
|
||||
variant?: McpPromptVariant;
|
||||
isLoading?: boolean;
|
||||
loadError?: string;
|
||||
}
|
||||
|
|
@ -21,7 +22,7 @@
|
|||
let {
|
||||
class: className = '',
|
||||
prompt,
|
||||
variant = 'message',
|
||||
variant = McpPromptVariant.MESSAGE,
|
||||
isLoading = false,
|
||||
loadError
|
||||
}: Props = $props();
|
||||
|
|
@ -99,7 +100,7 @@
|
|||
});
|
||||
|
||||
let showArgBadges = $derived(hasArguments && !isLoading && !loadError);
|
||||
let isAttachment = $derived(variant === 'attachment');
|
||||
let isAttachment = $derived(variant === McpPromptVariant.ATTACHMENT);
|
||||
let textSizeClass = $derived(isAttachment ? 'text-sm' : 'text-md');
|
||||
let maxHeightStyle = $derived(
|
||||
isAttachment
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
let healthyEnabledMcpServers = $derived(
|
||||
enabledMcpServersForChat.filter((s) => {
|
||||
const healthState = mcpStore.getHealthCheckState(s.id);
|
||||
return healthState.status !== HealthCheckStatus.Error;
|
||||
return healthState.status !== HealthCheckStatus.ERROR;
|
||||
})
|
||||
);
|
||||
let hasEnabledMcpServers = $derived(enabledMcpServersForChat.length > 0);
|
||||
|
|
|
|||
|
|
@ -27,41 +27,41 @@
|
|||
|
||||
let healthState = $derived<HealthCheckState>(mcpStore.getHealthCheckState(server.id));
|
||||
let displayName = $derived(mcpStore.getServerLabel(server));
|
||||
let isIdle = $derived(healthState.status === HealthCheckStatus.Idle);
|
||||
let isHealthChecking = $derived(healthState.status === HealthCheckStatus.Connecting);
|
||||
let isConnected = $derived(healthState.status === HealthCheckStatus.Success);
|
||||
let isError = $derived(healthState.status === HealthCheckStatus.Error);
|
||||
let isIdle = $derived(healthState.status === HealthCheckStatus.IDLE);
|
||||
let isHealthChecking = $derived(healthState.status === HealthCheckStatus.CONNECTING);
|
||||
let isConnected = $derived(healthState.status === HealthCheckStatus.SUCCESS);
|
||||
let isError = $derived(healthState.status === HealthCheckStatus.ERROR);
|
||||
let showSkeleton = $derived(isIdle || isHealthChecking);
|
||||
let errorMessage = $derived(
|
||||
healthState.status === HealthCheckStatus.Error ? healthState.message : undefined
|
||||
healthState.status === HealthCheckStatus.ERROR ? healthState.message : undefined
|
||||
);
|
||||
let tools = $derived(healthState.status === HealthCheckStatus.Success ? healthState.tools : []);
|
||||
let tools = $derived(healthState.status === HealthCheckStatus.SUCCESS ? healthState.tools : []);
|
||||
|
||||
let connectionLogs = $derived(
|
||||
healthState.status === HealthCheckStatus.Connecting ||
|
||||
healthState.status === HealthCheckStatus.Success ||
|
||||
healthState.status === HealthCheckStatus.Error
|
||||
healthState.status === HealthCheckStatus.CONNECTING ||
|
||||
healthState.status === HealthCheckStatus.SUCCESS ||
|
||||
healthState.status === HealthCheckStatus.ERROR
|
||||
? healthState.logs
|
||||
: []
|
||||
);
|
||||
|
||||
let serverInfo = $derived(
|
||||
healthState.status === HealthCheckStatus.Success ? healthState.serverInfo : undefined
|
||||
healthState.status === HealthCheckStatus.SUCCESS ? healthState.serverInfo : undefined
|
||||
);
|
||||
let capabilities = $derived(
|
||||
healthState.status === HealthCheckStatus.Success ? healthState.capabilities : undefined
|
||||
healthState.status === HealthCheckStatus.SUCCESS ? healthState.capabilities : undefined
|
||||
);
|
||||
let transportType = $derived(
|
||||
healthState.status === HealthCheckStatus.Success ? healthState.transportType : undefined
|
||||
healthState.status === HealthCheckStatus.SUCCESS ? healthState.transportType : undefined
|
||||
);
|
||||
let protocolVersion = $derived(
|
||||
healthState.status === HealthCheckStatus.Success ? healthState.protocolVersion : undefined
|
||||
healthState.status === HealthCheckStatus.SUCCESS ? healthState.protocolVersion : undefined
|
||||
);
|
||||
let connectionTimeMs = $derived(
|
||||
healthState.status === HealthCheckStatus.Success ? healthState.connectionTimeMs : undefined
|
||||
healthState.status === HealthCheckStatus.SUCCESS ? healthState.connectionTimeMs : undefined
|
||||
);
|
||||
let instructions = $derived(
|
||||
healthState.status === HealthCheckStatus.Success ? healthState.instructions : undefined
|
||||
healthState.status === HealthCheckStatus.SUCCESS ? healthState.instructions : undefined
|
||||
);
|
||||
|
||||
let isEditing = $state(!server.url.trim());
|
||||
|
|
|
|||
|
|
@ -27,14 +27,14 @@
|
|||
}: Props = $props();
|
||||
|
||||
const transportLabels: Record<MCPTransportType, string> = {
|
||||
[MCPTransportType.Websocket]: 'WebSocket',
|
||||
[MCPTransportType.StreamableHttp]: 'HTTP',
|
||||
[MCPTransportType.WEBSOCKET]: 'WebSocket',
|
||||
[MCPTransportType.STREAMABLE_HTTP]: 'HTTP',
|
||||
[MCPTransportType.SSE]: 'SSE'
|
||||
};
|
||||
|
||||
const transportIcons: Record<MCPTransportType, typeof Cable> = {
|
||||
[MCPTransportType.Websocket]: Zap,
|
||||
[MCPTransportType.StreamableHttp]: Globe,
|
||||
[MCPTransportType.WEBSOCKET]: Zap,
|
||||
[MCPTransportType.STREAMABLE_HTTP]: Globe,
|
||||
[MCPTransportType.SSE]: Radio
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -26,3 +26,7 @@ export { MCPConnectionPhase, MCPLogLevel, MCPTransportType, HealthCheckStatus }
|
|||
export { ModelModality } from './model';
|
||||
|
||||
export { ServerRole, ServerModelStatus } from './server';
|
||||
|
||||
export { ParameterSource, SyncableParameterType } from './settings';
|
||||
|
||||
export { ColorMode, McpPromptVariant, UrlPrefix } from './ui';
|
||||
|
|
|
|||
|
|
@ -2,32 +2,32 @@
|
|||
* Connection lifecycle phases for MCP protocol
|
||||
*/
|
||||
export enum MCPConnectionPhase {
|
||||
Idle = 'idle',
|
||||
TransportCreating = 'transport_creating',
|
||||
TransportReady = 'transport_ready',
|
||||
Initializing = 'initializing',
|
||||
CapabilitiesExchanged = 'capabilities_exchanged',
|
||||
ListingTools = 'listing_tools',
|
||||
Connected = 'connected',
|
||||
Error = 'error',
|
||||
Disconnected = 'disconnected'
|
||||
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'
|
||||
INFO = 'info',
|
||||
WARN = 'warn',
|
||||
ERROR = 'error'
|
||||
}
|
||||
|
||||
/**
|
||||
* Transport types for MCP connections
|
||||
*/
|
||||
export enum MCPTransportType {
|
||||
Websocket = 'websocket',
|
||||
StreamableHttp = 'streamable_http',
|
||||
WEBSOCKET = 'websocket',
|
||||
STREAMABLE_HTTP = 'streamable_http',
|
||||
SSE = 'sse'
|
||||
}
|
||||
|
||||
|
|
@ -35,8 +35,8 @@ export enum MCPTransportType {
|
|||
* Health check status for MCP servers
|
||||
*/
|
||||
export enum HealthCheckStatus {
|
||||
Idle = 'idle',
|
||||
Connecting = 'connecting',
|
||||
Success = 'success',
|
||||
Error = 'error'
|
||||
IDLE = 'idle',
|
||||
CONNECTING = 'connecting',
|
||||
SUCCESS = 'success',
|
||||
ERROR = 'error'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* 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'
|
||||
}
|
||||
|
|
@ -3,3 +3,22 @@ export enum ColorMode {
|
|||
DARK = 'dark',
|
||||
SYSTEM = 'system'
|
||||
}
|
||||
|
||||
/**
|
||||
* MCP prompt display variant
|
||||
*/
|
||||
export enum McpPromptVariant {
|
||||
MESSAGE = 'message',
|
||||
ATTACHMENT = 'attachment'
|
||||
}
|
||||
|
||||
/**
|
||||
* URL prefixes for protocol detection
|
||||
*/
|
||||
export enum UrlPrefix {
|
||||
DATA = 'data:',
|
||||
HTTP = 'http://',
|
||||
HTTPS = 'https://',
|
||||
WEBSOCKET = 'ws://',
|
||||
WEBSOCKET_SECURE = 'wss://'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type { Root as HastRoot } from 'hast';
|
||||
import { visit } from 'unist-util-visit';
|
||||
import type { DatabaseMessage, DatabaseMessageExtraImageFile } from '$lib/types/database';
|
||||
import { AttachmentType } from '$lib/enums';
|
||||
import { AttachmentType, UrlPrefix } from '$lib/enums';
|
||||
|
||||
/**
|
||||
* Rehype plugin to resolve attachment image sources.
|
||||
|
|
@ -14,7 +14,7 @@ export function rehypeResolveAttachmentImages(options: { message?: DatabaseMessa
|
|||
const src = String(node.properties.src);
|
||||
|
||||
// Skip data URLs and external URLs
|
||||
if (src.startsWith('data:') || src.startsWith('http')) {
|
||||
if (src.startsWith(UrlPrefix.DATA) || src.startsWith(UrlPrefix.HTTP)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export class MCPService {
|
|||
private static createLog(
|
||||
phase: MCPConnectionPhase,
|
||||
message: string,
|
||||
level: MCPLogLevel = MCPLogLevel.Info,
|
||||
level: MCPLogLevel = MCPLogLevel.INFO,
|
||||
details?: unknown
|
||||
): MCPConnectionLog {
|
||||
return {
|
||||
|
|
@ -100,7 +100,7 @@ export class MCPService {
|
|||
|
||||
return {
|
||||
transport: new WebSocketClientTransport(url),
|
||||
type: MCPTransportType.Websocket
|
||||
type: MCPTransportType.WEBSOCKET
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ export class MCPService {
|
|||
requestInit,
|
||||
sessionId: config.sessionId
|
||||
}),
|
||||
type: MCPTransportType.StreamableHttp
|
||||
type: MCPTransportType.STREAMABLE_HTTP
|
||||
};
|
||||
} catch (httpError) {
|
||||
console.warn(`[MCPService] StreamableHTTP failed, trying SSE transport...`, httpError);
|
||||
|
|
@ -169,9 +169,9 @@ export class MCPService {
|
|||
|
||||
// Phase: Creating transport
|
||||
onPhase?.(
|
||||
MCPConnectionPhase.TransportCreating,
|
||||
MCPConnectionPhase.TRANSPORT_CREATING,
|
||||
this.createLog(
|
||||
MCPConnectionPhase.TransportCreating,
|
||||
MCPConnectionPhase.TRANSPORT_CREATING,
|
||||
`Creating transport for ${serverConfig.url}`
|
||||
)
|
||||
);
|
||||
|
|
@ -181,8 +181,8 @@ export class MCPService {
|
|||
|
||||
// Phase: Transport ready
|
||||
onPhase?.(
|
||||
MCPConnectionPhase.TransportReady,
|
||||
this.createLog(MCPConnectionPhase.TransportReady, `Transport ready (${transportType})`),
|
||||
MCPConnectionPhase.TRANSPORT_READY,
|
||||
this.createLog(MCPConnectionPhase.TRANSPORT_READY, `Transport ready (${transportType})`),
|
||||
{ transportType }
|
||||
);
|
||||
|
||||
|
|
@ -199,8 +199,8 @@ export class MCPService {
|
|||
|
||||
// Phase: Initializing
|
||||
onPhase?.(
|
||||
MCPConnectionPhase.Initializing,
|
||||
this.createLog(MCPConnectionPhase.Initializing, 'Sending initialize request...')
|
||||
MCPConnectionPhase.INITIALIZING,
|
||||
this.createLog(MCPConnectionPhase.INITIALIZING, 'Sending initialize request...')
|
||||
);
|
||||
|
||||
console.log(`[MCPService][${serverName}] Connecting to server...`);
|
||||
|
|
@ -213,11 +213,11 @@ export class MCPService {
|
|||
|
||||
// Phase: Capabilities exchanged
|
||||
onPhase?.(
|
||||
MCPConnectionPhase.CapabilitiesExchanged,
|
||||
MCPConnectionPhase.CAPABILITIES_EXCHANGED,
|
||||
this.createLog(
|
||||
MCPConnectionPhase.CapabilitiesExchanged,
|
||||
MCPConnectionPhase.CAPABILITIES_EXCHANGED,
|
||||
'Capabilities exchanged successfully',
|
||||
MCPLogLevel.Info,
|
||||
MCPLogLevel.INFO,
|
||||
{
|
||||
serverCapabilities,
|
||||
serverInfo
|
||||
|
|
@ -233,8 +233,8 @@ export class MCPService {
|
|||
|
||||
// Phase: Listing tools
|
||||
onPhase?.(
|
||||
MCPConnectionPhase.ListingTools,
|
||||
this.createLog(MCPConnectionPhase.ListingTools, 'Listing available tools...')
|
||||
MCPConnectionPhase.LISTING_TOOLS,
|
||||
this.createLog(MCPConnectionPhase.LISTING_TOOLS, 'Listing available tools...')
|
||||
);
|
||||
|
||||
console.log(`[MCPService][${serverName}] Connected, listing tools...`);
|
||||
|
|
@ -251,9 +251,9 @@ export class MCPService {
|
|||
|
||||
// Phase: Connected
|
||||
onPhase?.(
|
||||
MCPConnectionPhase.Connected,
|
||||
MCPConnectionPhase.CONNECTED,
|
||||
this.createLog(
|
||||
MCPConnectionPhase.Connected,
|
||||
MCPConnectionPhase.CONNECTED,
|
||||
`Connection established with ${tools.length} tools (${connectionTimeMs}ms)`
|
||||
)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -13,77 +13,157 @@
|
|||
*/
|
||||
|
||||
import { normalizeFloatingPoint } from '$lib/utils';
|
||||
import type {
|
||||
SyncableParameter,
|
||||
ParameterRecord,
|
||||
ParameterInfo,
|
||||
ParameterValue,
|
||||
ParameterSource
|
||||
} from '$lib/types';
|
||||
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
|
||||
*/
|
||||
export const SYNCABLE_PARAMETERS: SyncableParameter[] = [
|
||||
{ key: 'temperature', serverKey: 'temperature', type: 'number', canSync: true },
|
||||
{ key: 'top_k', serverKey: 'top_k', type: 'number', canSync: true },
|
||||
{ key: 'top_p', serverKey: 'top_p', type: 'number', canSync: true },
|
||||
{ key: 'min_p', serverKey: 'min_p', type: 'number', canSync: true },
|
||||
{ key: 'dynatemp_range', serverKey: 'dynatemp_range', type: 'number', canSync: true },
|
||||
{ key: 'dynatemp_exponent', serverKey: 'dynatemp_exponent', type: 'number', canSync: true },
|
||||
{ key: 'xtc_probability', serverKey: 'xtc_probability', type: 'number', canSync: true },
|
||||
{ key: 'xtc_threshold', serverKey: 'xtc_threshold', type: 'number', canSync: true },
|
||||
{ key: 'typ_p', serverKey: 'typ_p', type: 'number', canSync: true },
|
||||
{ key: 'repeat_last_n', serverKey: 'repeat_last_n', type: 'number', canSync: true },
|
||||
{ key: 'repeat_penalty', serverKey: 'repeat_penalty', type: 'number', canSync: true },
|
||||
{ key: 'presence_penalty', serverKey: 'presence_penalty', type: 'number', canSync: true },
|
||||
{ key: 'frequency_penalty', serverKey: 'frequency_penalty', type: 'number', canSync: true },
|
||||
{ key: 'dry_multiplier', serverKey: 'dry_multiplier', type: 'number', canSync: true },
|
||||
{ key: 'dry_base', serverKey: 'dry_base', type: 'number', canSync: true },
|
||||
{ key: 'dry_allowed_length', serverKey: 'dry_allowed_length', type: 'number', canSync: true },
|
||||
{ key: 'dry_penalty_last_n', serverKey: 'dry_penalty_last_n', type: 'number', canSync: true },
|
||||
{ key: 'max_tokens', serverKey: 'max_tokens', type: 'number', canSync: true },
|
||||
{ key: 'samplers', serverKey: 'samplers', type: 'string', canSync: true },
|
||||
{
|
||||
key: 'temperature',
|
||||
serverKey: 'temperature',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{ key: 'top_k', serverKey: 'top_k', type: SyncableParameterType.NUMBER, canSync: true },
|
||||
{ key: 'top_p', serverKey: 'top_p', type: SyncableParameterType.NUMBER, canSync: true },
|
||||
{ key: 'min_p', serverKey: 'min_p', type: SyncableParameterType.NUMBER, canSync: true },
|
||||
{
|
||||
key: 'dynatemp_range',
|
||||
serverKey: 'dynatemp_range',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'dynatemp_exponent',
|
||||
serverKey: 'dynatemp_exponent',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'xtc_probability',
|
||||
serverKey: 'xtc_probability',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'xtc_threshold',
|
||||
serverKey: 'xtc_threshold',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{ key: 'typ_p', serverKey: 'typ_p', type: SyncableParameterType.NUMBER, canSync: true },
|
||||
{
|
||||
key: 'repeat_last_n',
|
||||
serverKey: 'repeat_last_n',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'repeat_penalty',
|
||||
serverKey: 'repeat_penalty',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'presence_penalty',
|
||||
serverKey: 'presence_penalty',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'frequency_penalty',
|
||||
serverKey: 'frequency_penalty',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'dry_multiplier',
|
||||
serverKey: 'dry_multiplier',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{ key: 'dry_base', serverKey: 'dry_base', type: SyncableParameterType.NUMBER, canSync: true },
|
||||
{
|
||||
key: 'dry_allowed_length',
|
||||
serverKey: 'dry_allowed_length',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'dry_penalty_last_n',
|
||||
serverKey: 'dry_penalty_last_n',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{ key: 'max_tokens', serverKey: 'max_tokens', type: SyncableParameterType.NUMBER, canSync: true },
|
||||
{ key: 'samplers', serverKey: 'samplers', type: SyncableParameterType.STRING, canSync: true },
|
||||
{
|
||||
key: 'pasteLongTextToFileLen',
|
||||
serverKey: 'pasteLongTextToFileLen',
|
||||
type: 'number',
|
||||
type: SyncableParameterType.NUMBER,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'pdfAsImage',
|
||||
serverKey: 'pdfAsImage',
|
||||
type: SyncableParameterType.BOOLEAN,
|
||||
canSync: true
|
||||
},
|
||||
{ key: 'pdfAsImage', serverKey: 'pdfAsImage', type: 'boolean', canSync: true },
|
||||
{
|
||||
key: 'showThoughtInProgress',
|
||||
serverKey: 'showThoughtInProgress',
|
||||
type: 'boolean',
|
||||
type: SyncableParameterType.BOOLEAN,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'keepStatsVisible',
|
||||
serverKey: 'keepStatsVisible',
|
||||
type: SyncableParameterType.BOOLEAN,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'showMessageStats',
|
||||
serverKey: 'showMessageStats',
|
||||
type: SyncableParameterType.BOOLEAN,
|
||||
canSync: true
|
||||
},
|
||||
{ key: 'keepStatsVisible', serverKey: 'keepStatsVisible', type: 'boolean', canSync: true },
|
||||
{ key: 'showMessageStats', serverKey: 'showMessageStats', type: 'boolean', canSync: true },
|
||||
{
|
||||
key: 'askForTitleConfirmation',
|
||||
serverKey: 'askForTitleConfirmation',
|
||||
type: 'boolean',
|
||||
type: SyncableParameterType.BOOLEAN,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'disableAutoScroll',
|
||||
serverKey: 'disableAutoScroll',
|
||||
type: SyncableParameterType.BOOLEAN,
|
||||
canSync: true
|
||||
},
|
||||
{ key: 'disableAutoScroll', serverKey: 'disableAutoScroll', type: 'boolean', canSync: true },
|
||||
{
|
||||
key: 'renderUserContentAsMarkdown',
|
||||
serverKey: 'renderUserContentAsMarkdown',
|
||||
type: 'boolean',
|
||||
type: SyncableParameterType.BOOLEAN,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'autoMicOnEmpty',
|
||||
serverKey: 'autoMicOnEmpty',
|
||||
type: SyncableParameterType.BOOLEAN,
|
||||
canSync: true
|
||||
},
|
||||
{ key: 'autoMicOnEmpty', serverKey: 'autoMicOnEmpty', type: 'boolean', canSync: true },
|
||||
{
|
||||
key: 'pyInterpreterEnabled',
|
||||
serverKey: 'pyInterpreterEnabled',
|
||||
type: 'boolean',
|
||||
type: SyncableParameterType.BOOLEAN,
|
||||
canSync: true
|
||||
},
|
||||
{
|
||||
key: 'enableContinueGeneration',
|
||||
serverKey: 'enableContinueGeneration',
|
||||
type: 'boolean',
|
||||
type: SyncableParameterType.BOOLEAN,
|
||||
canSync: true
|
||||
}
|
||||
];
|
||||
|
|
@ -196,7 +276,7 @@ export class ParameterSyncService {
|
|||
const isUserOverride = userOverrides.has(key);
|
||||
|
||||
// Simple logic: either using default (from props) or custom (user override)
|
||||
const source: ParameterSource = isUserOverride ? 'custom' : 'default';
|
||||
const source = isUserOverride ? ParameterSource.CUSTOM : ParameterSource.DEFAULT;
|
||||
|
||||
return {
|
||||
value: currentValue,
|
||||
|
|
@ -228,11 +308,11 @@ export class ParameterSyncService {
|
|||
if (!param) return false;
|
||||
|
||||
switch (param.type) {
|
||||
case 'number':
|
||||
case SyncableParameterType.NUMBER:
|
||||
return typeof value === 'number' && !isNaN(value);
|
||||
case 'string':
|
||||
case SyncableParameterType.STRING:
|
||||
return typeof value === 'string';
|
||||
case 'boolean':
|
||||
case SyncableParameterType.BOOLEAN:
|
||||
return typeof value === 'boolean';
|
||||
default:
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ class MCPStore {
|
|||
*/
|
||||
getServerLabel(server: MCPServerSettingsEntry): string {
|
||||
const healthState = this.getHealthCheckState(server.id);
|
||||
if (healthState?.status === HealthCheckStatus.Success) {
|
||||
if (healthState?.status === HealthCheckStatus.SUCCESS) {
|
||||
return (
|
||||
healthState.serverInfo?.title || healthState.serverInfo?.name || server.name || server.url
|
||||
);
|
||||
|
|
@ -175,7 +175,7 @@ class MCPStore {
|
|||
return servers.some((s) => {
|
||||
const state = this.getHealthCheckState(s.id);
|
||||
return (
|
||||
state.status === HealthCheckStatus.Idle || state.status === HealthCheckStatus.Connecting
|
||||
state.status === HealthCheckStatus.IDLE || state.status === HealthCheckStatus.CONNECTING
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ export type {
|
|||
SettingsFieldConfig,
|
||||
SettingsChatServiceOptions,
|
||||
SettingsConfigType,
|
||||
ParameterSource,
|
||||
ParameterValue,
|
||||
ParameterRecord,
|
||||
ParameterInfo,
|
||||
|
|
|
|||
|
|
@ -136,20 +136,20 @@ export interface MCPConnection {
|
|||
* Extended health check state with detailed connection info
|
||||
*/
|
||||
export type HealthCheckState =
|
||||
| { status: import('$lib/enums/mcp').HealthCheckStatus.Idle }
|
||||
| { status: import('$lib/enums/mcp').HealthCheckStatus.IDLE }
|
||||
| {
|
||||
status: import('$lib/enums/mcp').HealthCheckStatus.Connecting;
|
||||
status: import('$lib/enums/mcp').HealthCheckStatus.CONNECTING;
|
||||
phase: MCPConnectionPhase;
|
||||
logs: MCPConnectionLog[];
|
||||
}
|
||||
| {
|
||||
status: import('$lib/enums/mcp').HealthCheckStatus.Error;
|
||||
status: import('$lib/enums/mcp').HealthCheckStatus.ERROR;
|
||||
message: string;
|
||||
phase?: MCPConnectionPhase;
|
||||
logs: MCPConnectionLog[];
|
||||
}
|
||||
| {
|
||||
status: import('$lib/enums/mcp').HealthCheckStatus.Success;
|
||||
status: import('$lib/enums/mcp').HealthCheckStatus.SUCCESS;
|
||||
tools: MCPToolInfo[];
|
||||
serverInfo?: MCPServerInfo;
|
||||
capabilities?: MCPCapabilitiesInfo;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import type { SETTING_CONFIG_DEFAULT } from '$lib/constants/settings-config';
|
|||
import type { ChatMessagePromptProgress, ChatMessageTimings } from './chat';
|
||||
import type { OpenAIToolDefinition } from './mcp';
|
||||
import type { DatabaseMessageExtra } from './database';
|
||||
import type { ParameterSource, SyncableParameterType } from '$lib/enums';
|
||||
|
||||
export type SettingsConfigValue = string | number | boolean;
|
||||
|
||||
|
|
@ -72,8 +73,8 @@ export type SettingsConfigType = typeof SETTING_CONFIG_DEFAULT & {
|
|||
|
||||
/**
|
||||
* Parameter synchronization types for server defaults and user overrides
|
||||
* Note: ParameterSource and SyncableParameterType enums are imported from '$lib/enums'
|
||||
*/
|
||||
export type ParameterSource = 'default' | 'custom';
|
||||
export type ParameterValue = string | number | boolean;
|
||||
export type ParameterRecord = Record<string, ParameterValue>;
|
||||
|
||||
|
|
@ -87,6 +88,6 @@ export interface ParameterInfo {
|
|||
export interface SyncableParameter {
|
||||
key: string;
|
||||
serverKey: string;
|
||||
type: 'number' | 'string' | 'boolean';
|
||||
type: SyncableParameterType;
|
||||
canSync: boolean;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { MCPServerSettingsEntry } from '$lib/types';
|
||||
import { MCPTransportType, MCPLogLevel } from '$lib/enums';
|
||||
import { MCPTransportType, MCPLogLevel, UrlPrefix } from '$lib/enums';
|
||||
import { DEFAULT_MCP_CONFIG } from '$lib/constants/mcp';
|
||||
import { Info, AlertTriangle, XCircle } from '@lucide/svelte';
|
||||
import type { Component } from 'svelte';
|
||||
|
|
@ -11,9 +11,10 @@ import type { Component } from 'svelte';
|
|||
export function detectMcpTransportFromUrl(url: string): MCPTransportType {
|
||||
const normalized = url.trim().toLowerCase();
|
||||
|
||||
return normalized.startsWith('ws://') || normalized.startsWith('wss://')
|
||||
? MCPTransportType.Websocket
|
||||
: MCPTransportType.StreamableHttp;
|
||||
return normalized.startsWith(UrlPrefix.WEBSOCKET) ||
|
||||
normalized.startsWith(UrlPrefix.WEBSOCKET_SECURE)
|
||||
? MCPTransportType.WEBSOCKET
|
||||
: MCPTransportType.STREAMABLE_HTTP;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -70,9 +71,9 @@ export function parseMcpServerSettings(rawServers: unknown): MCPServerSettingsEn
|
|||
*/
|
||||
export function getMcpLogLevelIcon(level: MCPLogLevel): Component {
|
||||
switch (level) {
|
||||
case MCPLogLevel.Error:
|
||||
case MCPLogLevel.ERROR:
|
||||
return XCircle;
|
||||
case MCPLogLevel.Warn:
|
||||
case MCPLogLevel.WARN:
|
||||
return AlertTriangle;
|
||||
default:
|
||||
return Info;
|
||||
|
|
@ -87,9 +88,9 @@ export function getMcpLogLevelIcon(level: MCPLogLevel): Component {
|
|||
*/
|
||||
export function getMcpLogLevelClass(level: MCPLogLevel): string {
|
||||
switch (level) {
|
||||
case MCPLogLevel.Error:
|
||||
case MCPLogLevel.ERROR:
|
||||
return 'text-destructive';
|
||||
case MCPLogLevel.Warn:
|
||||
case MCPLogLevel.WARN:
|
||||
return 'text-yellow-600 dark:text-yellow-500';
|
||||
default:
|
||||
return 'text-muted-foreground';
|
||||
|
|
|
|||
Loading…
Reference in New Issue