From f5a5b93b281986fd875e28f2ece2ca15004bc7da Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Tue, 6 Oct 2026 16:20:18 +0200 Subject: [PATCH] ui : resolve the layout probes through the providers api url The key check reads the providers api url and waits for the server capabilities, and the model status feed survives tab switches instead of tearing down on every one. Split from the shell polish: the layout depends on the providers layer. Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash --- tools/ui/src/routes/+layout.svelte | 37 +++++++++--------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/tools/ui/src/routes/+layout.svelte b/tools/ui/src/routes/+layout.svelte index 5de4f82c1c..3e6a5a430f 100644 --- a/tools/ui/src/routes/+layout.svelte +++ b/tools/ui/src/routes/+layout.svelte @@ -2,7 +2,6 @@ import '../app.css'; import { browser } from '$app/environment'; import { goto } from '$app/navigation'; - import { base } from '$app/paths'; import { page } from '$app/state'; import { SidebarNavigation } from '$lib/components/app'; import { PwaMetaTags, PwaRefreshAlert } from '$lib/components/pwa'; @@ -31,6 +30,7 @@ versionStore } from '$lib/stores'; import { initStores } from '$lib/stores/init'; + import { apiUrl } from '$lib/utils/api-base'; import { ModeWatcher } from 'mode-watcher'; import { untrack } from 'svelte'; import { onMount } from 'svelte'; @@ -147,6 +147,11 @@ }); function checkApiKey() { + // the stored key authenticates the llama.cpp server serving this UI + if (!serverStore.capabilities.props) { + return; + } + const apiKey = settingsStore.config.apiKey; // Without a stored key there is nothing to re-validate here; the keyless @@ -167,7 +172,7 @@ [HEADERS.AUTHORIZATION]: `${HEADERS.BEARER}${apiKey.trim()}` }; - fetch(`${base}/props`, { headers }) + fetch(apiUrl('/props'), { headers }) .then((response) => { if (response.status === 401 || response.status === 403) { window.location.reload(); @@ -230,37 +235,17 @@ }); } - // Fetch router models when in router mode (for status and modalities) - // Wait for models to be loaded first, run only once - let routerModelsFetched = false; - - $effect(() => { - const isRouter = serverStore.isRouterMode; - const modelsCount = modelsStore.models.length; - - // Only fetch router models once when we have models loaded and in router mode - if (isRouter && modelsCount > 0 && !routerModelsFetched) { - routerModelsFetched = true; - - untrack(() => { - modelsStore.fetchRouterModels(); - }); - } - }); - - // Live model status and load progress via the /models/sse feed (router mode) + // Live model status and load progress via the /models/sse feed (router mode). + // The feed is kept for the session: switching to an external backend and back + // must not tear it down and reconnect on every tab switch. $effect(() => { if (!browser) return; - if (!serverStore.isRouterMode) return; + if (!serverStore.localIsRouter) return; untrack(() => { modelsStore.status.subscribe(); }); - - return () => { - modelsStore.status.unsubscribe(); - }; }); // Background MCP server health checks on app load.