ggml-org/llama.cpp · #28646
webui: stop re-probing disabled /tools endpoint on every message
tools/ui/src/lib/hooks/use-tools-panel.svelte.ts1 + / 1 −
@@ -47,7 +47,7 @@ export function useToolsPanel(): UseToolsPanelReturn { if (toolsStore.toolGroups.length > 0) return null; - // Tools endpoint is unreachable (404) — server started without --tools+ // Tools endpoint unreachable (403) — server started without tools if (toolsStore.isToolsEndpointUnreachable) { return `To enable Server 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).`; }tools/ui/src/lib/stores/agentic/index.svelte.ts8 + / 2 −
@@ -315,8 +315,14 @@ class AgenticStore { // Clear any pending permissions/continue requests for this conversation when starting a new flow this.gates.clear(conversationId); - // Ensure server tools are fetched before checking if agentic is enabled- if (toolsStore.serverTools.length === 0 && !toolsStore.loading) {+ // Ensure server tools are fetched before checking if agentic is enabled.+ // A disabled /tools endpoint stays disabled for the life of the server,+ // so the tools panel is the only place that probes it again.+ if (+ toolsStore.serverTools.length === 0 &&+ !toolsStore.loading &&+ !toolsStore.isToolsEndpointUnreachable+ ) { await toolsStore.fetchServerTools(); } tools/ui/src/lib/stores/tools.svelte.ts3 + / 6 −
@@ -32,7 +32,7 @@ import { mcpStore } from '$lib/stores/mcp/index.svelte'; import { modelsStore } from '$lib/stores/models/index.svelte'; import { settingsStore } from '$lib/stores/settings/index.svelte'; import type { OpenAIToolDefinition, ToolEntry, ToolGroup } from '$lib/types';-import { buildSandboxToolDefinition } from '$lib/utils';+import { ApiError, buildSandboxToolDefinition } from '$lib/utils'; import { SvelteMap, SvelteSet } from 'svelte/reactivity'; /** Stable selection identity for a tool, shared by the disabled set and the permission store */@@ -246,13 +246,10 @@ class ToolsStore { toolInfos.filter((info) => info.uses_cwd).map((info) => info.tool) ); } catch (err) {- const errorMessage = err instanceof Error ? err.message : String(err);-- this._error = errorMessage;+ this._error = err instanceof Error ? err.message : String(err); // 403 from /tools means the server was started without --tools- // TODO: check status code instead of relying on message- if (errorMessage.includes('this feature is disabled')) {+ if (err instanceof ApiError && err.status === 403) { this._toolsEndpointUnreachable = true; console.info('[ToolsStore] Server tools are disabled on the server'); } else {