* fix: drop MCP recommendations auto-popup and silent preloads * feat: Add consent-driven MCP recommendations inside Add New Server dialog * refactor: Drop mcpDefaultServerOverrides for mcpServers[i].enabled * feat: Center the empty state on the MCP settings page * fix: keep existing MCP cards intact when adding a new server * fix: keep MCP cards stable when a new server is added * refactor: keep MCP server list in config insertion order * feat: shrink the recommended-MCP cards to two tools each and fit them in one row * feat: make recommended MCP cards click-to-fill and tighten copy * feat: highlight the selected MCP recommendation and stop auto-focus on dialog open * feat: derive MCP recommendation selection from the form URL * fix: make recommendation MCP cards fully non-focusable * fix: redirect focus from first card to the URL input on consent * chore: Formatting * refactor: Remove Recommended MCP Servers completely * fix: Preserve legacy mcpDefaultServerOverrides key after merge migration for downgrade compatibility
124 lines
4.0 KiB
TypeScript
124 lines
4.0 KiB
TypeScript
import { CLI_FLAGS } from '$lib/constants';
|
|
import { SvelteSet } from 'svelte/reactivity';
|
|
import { ToolSource } from '$lib/enums';
|
|
import { conversationsStore } from '$lib/stores/conversations.svelte';
|
|
import { mcpStore } from '$lib/stores/mcp.svelte';
|
|
import { toolsStore } from '$lib/stores/tools.svelte';
|
|
import type { ToolGroup } from '$lib/types';
|
|
|
|
export interface UseToolsPanelReturn {
|
|
readonly expandedGroups: SvelteSet<string>;
|
|
readonly groups: ToolGroup[];
|
|
readonly activeGroups: ToolGroup[];
|
|
readonly totalToolCount: number;
|
|
readonly noToolsInfoMessage: string | null;
|
|
isGroupChecked(group: ToolGroup): boolean;
|
|
getEnabledToolCount(group: ToolGroup): number;
|
|
getFavicon(group: ToolGroup): string | null;
|
|
isGroupDisabled(group: ToolGroup): boolean;
|
|
toggleGroupExpanded(label: string): void;
|
|
/** Toggle all tools in a group by label (avoids stale group object references). */
|
|
toggleGroupByLabel(label: string): void;
|
|
handleOpen(): void;
|
|
}
|
|
|
|
/**
|
|
* Shared reactive state and helpers for the tools panel UI.
|
|
*
|
|
* Used by both the desktop dropdown (`ChatFormActionAddToolsSubmenu`)
|
|
* and the mobile sheet (`ChatFormActionAddSheet`) to avoid
|
|
* duplicating group filtering, checked-state derivation, and favicon logic.
|
|
*/
|
|
export function useToolsPanel(): UseToolsPanelReturn {
|
|
const expandedGroups = new SvelteSet<string>();
|
|
|
|
const groups = $derived(toolsStore.toolGroups);
|
|
const activeGroups = $derived(
|
|
groups.filter(
|
|
(g) =>
|
|
g.source !== ToolSource.MCP ||
|
|
!g.serverId ||
|
|
conversationsStore.isMcpServerEnabledForChat(g.serverId)
|
|
)
|
|
);
|
|
const totalToolCount = $derived(activeGroups.reduce((n, g) => n + g.tools.length, 0));
|
|
const noToolsInfoMessage = $derived.by(() => {
|
|
if (toolsStore.loading) return null;
|
|
if (toolsStore.toolGroups.length > 0) return null;
|
|
// Tools endpoint is unreachable (404) — server started without --tools
|
|
if (toolsStore.isToolsEndpointUnreachable) {
|
|
return `To enable Built-In Tools you need to run llama-server with ${CLI_FLAGS.TOOLS} all or ${CLI_FLAGS.TOOLS} <name> flag. To see MCP Tools you need to add / enable MCP Server(s).`;
|
|
}
|
|
// Other errors — return null so UI shows "Failed to load tools"
|
|
if (toolsStore.error) return null;
|
|
return `To enable Built-In Tools you need to run llama-server with ${CLI_FLAGS.TOOLS} all or ${CLI_FLAGS.TOOLS} <name> flag. To see MCP Tools you need to add / enable MCP Server(s).`;
|
|
});
|
|
|
|
function isGroupChecked(group: ToolGroup): boolean {
|
|
return toolsStore.isGroupFullyEnabled(group);
|
|
}
|
|
|
|
function getEnabledToolCount(group: ToolGroup): number {
|
|
return group.tools.filter((tool) => toolsStore.isToolEnabled(tool.key)).length;
|
|
}
|
|
|
|
function getFavicon(group: ToolGroup): string | null {
|
|
if (group.source !== ToolSource.MCP || !group.serverId) return null;
|
|
|
|
return mcpStore.getServerFavicon(group.serverId);
|
|
}
|
|
|
|
function isGroupDisabled(group: ToolGroup): boolean {
|
|
return (
|
|
group.source === ToolSource.MCP &&
|
|
!!group.serverId &&
|
|
!conversationsStore.isMcpServerEnabledForChat(group.serverId)
|
|
);
|
|
}
|
|
|
|
function toggleGroupExpanded(label: string): void {
|
|
if (expandedGroups.has(label)) {
|
|
expandedGroups.delete(label);
|
|
} else {
|
|
expandedGroups.add(label);
|
|
}
|
|
}
|
|
|
|
function toggleGroupByLabel(label: string): void {
|
|
// Find current group by label to get up-to-date tool references
|
|
const group = activeGroups.find((g) => g.label === label);
|
|
if (!group) return;
|
|
toolsStore.toggleGroup(group);
|
|
}
|
|
|
|
function handleOpen(): void {
|
|
if (toolsStore.builtinTools.length === 0 && !toolsStore.loading) {
|
|
toolsStore.fetchBuiltinTools();
|
|
}
|
|
mcpStore.runHealthChecksForServers(mcpStore.getServers().filter((s) => s.enabled));
|
|
}
|
|
|
|
return {
|
|
expandedGroups,
|
|
get groups() {
|
|
return groups;
|
|
},
|
|
get activeGroups() {
|
|
return activeGroups;
|
|
},
|
|
get totalToolCount() {
|
|
return totalToolCount;
|
|
},
|
|
get noToolsInfoMessage() {
|
|
return noToolsInfoMessage;
|
|
},
|
|
isGroupChecked,
|
|
getEnabledToolCount,
|
|
getFavicon,
|
|
isGroupDisabled,
|
|
toggleGroupExpanded,
|
|
toggleGroupByLabel,
|
|
handleOpen
|
|
};
|
|
}
|