WebUI: Persist the on/off state of the MCP servers for new conversations (#20750)
* webui: add persistent storage for MCP server on/off state in new chats * webui: simplify MCP enabled checks, remove dead server.enabled fallback * chore: update webui build output * chore: update webui build output --------- Co-authored-by: Aleksander Grygier <aleksander.grygier@gmail.com>
This commit is contained in:
parent
512bba6ee0
commit
cd708db0cc
Binary file not shown.
|
|
@ -1,3 +1,4 @@
|
||||||
export const CONFIG_LOCALSTORAGE_KEY = 'LlamaCppWebui.config';
|
export const CONFIG_LOCALSTORAGE_KEY = 'LlamaCppWebui.config';
|
||||||
export const USER_OVERRIDES_LOCALSTORAGE_KEY = 'LlamaCppWebui.userOverrides';
|
export const USER_OVERRIDES_LOCALSTORAGE_KEY = 'LlamaCppWebui.userOverrides';
|
||||||
export const FAVOURITE_MODELS_LOCALSTORAGE_KEY = 'LlamaCppWebui.favouriteModels';
|
export const FAVOURITE_MODELS_LOCALSTORAGE_KEY = 'LlamaCppWebui.favouriteModels';
|
||||||
|
export const MCP_DEFAULT_ENABLED_LOCALSTORAGE_KEY = 'LlamaCppWebui.mcpDefaultEnabled';
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ import {
|
||||||
ISO_TIME_SEPARATOR,
|
ISO_TIME_SEPARATOR,
|
||||||
ISO_TIME_SEPARATOR_REPLACEMENT,
|
ISO_TIME_SEPARATOR_REPLACEMENT,
|
||||||
NON_ALPHANUMERIC_REGEX,
|
NON_ALPHANUMERIC_REGEX,
|
||||||
MULTIPLE_UNDERSCORE_REGEX
|
MULTIPLE_UNDERSCORE_REGEX,
|
||||||
|
MCP_DEFAULT_ENABLED_LOCALSTORAGE_KEY
|
||||||
} from '$lib/constants';
|
} from '$lib/constants';
|
||||||
|
|
||||||
class ConversationsStore {
|
class ConversationsStore {
|
||||||
|
|
@ -61,7 +62,37 @@ class ConversationsStore {
|
||||||
isInitialized = $state(false);
|
isInitialized = $state(false);
|
||||||
|
|
||||||
/** Pending MCP server overrides for new conversations (before first message) */
|
/** Pending MCP server overrides for new conversations (before first message) */
|
||||||
pendingMcpServerOverrides = $state<McpServerOverride[]>([]);
|
pendingMcpServerOverrides = $state<McpServerOverride[]>(ConversationsStore.loadMcpDefaults());
|
||||||
|
|
||||||
|
/** Load MCP default overrides from localStorage */
|
||||||
|
private static loadMcpDefaults(): McpServerOverride[] {
|
||||||
|
if (typeof globalThis.localStorage === 'undefined') return [];
|
||||||
|
try {
|
||||||
|
const raw = localStorage.getItem(MCP_DEFAULT_ENABLED_LOCALSTORAGE_KEY);
|
||||||
|
if (!raw) return [];
|
||||||
|
const parsed = JSON.parse(raw);
|
||||||
|
if (!Array.isArray(parsed)) return [];
|
||||||
|
return parsed.filter(
|
||||||
|
(o: unknown) => typeof o === 'object' && o !== null && 'serverId' in o && 'enabled' in o
|
||||||
|
) as McpServerOverride[];
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Persist MCP default overrides to localStorage */
|
||||||
|
private saveMcpDefaults(): void {
|
||||||
|
if (typeof globalThis.localStorage === 'undefined') return;
|
||||||
|
const plain = this.pendingMcpServerOverrides.map((o) => ({
|
||||||
|
serverId: o.serverId,
|
||||||
|
enabled: o.enabled
|
||||||
|
}));
|
||||||
|
if (plain.length > 0) {
|
||||||
|
localStorage.setItem(MCP_DEFAULT_ENABLED_LOCALSTORAGE_KEY, JSON.stringify(plain));
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(MCP_DEFAULT_ENABLED_LOCALSTORAGE_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Callback for title update confirmation dialog */
|
/** Callback for title update confirmation dialog */
|
||||||
titleUpdateConfirmationCallback?: (currentTitle: string, newTitle: string) => Promise<boolean>;
|
titleUpdateConfirmationCallback?: (currentTitle: string, newTitle: string) => Promise<boolean>;
|
||||||
|
|
@ -261,6 +292,8 @@ class ConversationsStore {
|
||||||
clearActiveConversation(): void {
|
clearActiveConversation(): void {
|
||||||
this.activeConversation = null;
|
this.activeConversation = null;
|
||||||
this.activeMessages = [];
|
this.activeMessages = [];
|
||||||
|
// reload MCP defaults so new chats inherit persisted state
|
||||||
|
this.pendingMcpServerOverrides = ConversationsStore.loadMcpDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -597,6 +630,7 @@ class ConversationsStore {
|
||||||
this.pendingMcpServerOverrides = [...this.pendingMcpServerOverrides, { serverId, enabled }];
|
this.pendingMcpServerOverrides = [...this.pendingMcpServerOverrides, { serverId, enabled }];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.saveMcpDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -621,6 +655,7 @@ class ConversationsStore {
|
||||||
*/
|
*/
|
||||||
clearPendingMcpServerOverrides(): void {
|
clearPendingMcpServerOverrides(): void {
|
||||||
this.pendingMcpServerOverrides = [];
|
this.pendingMcpServerOverrides = [];
|
||||||
|
this.saveMcpDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -208,23 +208,16 @@ class MCPStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a server is enabled, considering per-chat overrides.
|
* Checks if a server is enabled for a given chat.
|
||||||
|
* Only per-chat overrides (persisted in localStorage for new chats,
|
||||||
|
* or in IndexedDB for existing conversations) control enabled state.
|
||||||
*/
|
*/
|
||||||
#checkServerEnabled(
|
#checkServerEnabled(
|
||||||
server: MCPServerSettingsEntry,
|
server: MCPServerSettingsEntry,
|
||||||
perChatOverrides?: McpServerOverride[]
|
perChatOverrides?: McpServerOverride[]
|
||||||
): boolean {
|
): boolean {
|
||||||
if (!server.enabled) {
|
const override = perChatOverrides?.find((o) => o.serverId === server.id);
|
||||||
return false;
|
return override?.enabled ?? false;
|
||||||
}
|
|
||||||
|
|
||||||
if (perChatOverrides) {
|
|
||||||
const override = perChatOverrides.find((o) => o.serverId === server.id);
|
|
||||||
|
|
||||||
return override?.enabled ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -570,18 +563,8 @@ class MCPStore {
|
||||||
getEnabledServersForConversation(
|
getEnabledServersForConversation(
|
||||||
perChatOverrides?: McpServerOverride[]
|
perChatOverrides?: McpServerOverride[]
|
||||||
): MCPServerSettingsEntry[] {
|
): MCPServerSettingsEntry[] {
|
||||||
if (!perChatOverrides?.length) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.getServers().filter((server) => {
|
return this.getServers().filter((server) => {
|
||||||
if (!server.enabled) {
|
return this.#checkServerEnabled(server, perChatOverrides);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const override = perChatOverrides.find((o) => o.serverId === server.id);
|
|
||||||
|
|
||||||
return override?.enabled ?? false;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue