]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/commitdiff
webui: Add MCP CORS Proxy detection logic & UI (#20167)
authorAleksander Grygier <redacted>
Mon, 16 Mar 2026 12:05:36 +0000 (13:05 +0100)
committerGitHub <redacted>
Mon, 16 Mar 2026 12:05:36 +0000 (13:05 +0100)
* refactor: MCP store cleanup

* feat: Add MCP proxy availability detection

* fix: Sidebar icon

* chore: update webui build output

* chore: Formatting

* chore: update webui build output

* chore: Update package lock

* chore: update webui build output

* chore: update webui build output

* chore: update webui build output

tools/server/public/index.html.gz
tools/server/webui/package-lock.json
tools/server/webui/src/lib/components/app/mcp/McpServerForm.svelte
tools/server/webui/src/lib/stores/mcp.svelte.ts
tools/server/webui/src/lib/utils/favicon.ts
tools/server/webui/src/routes/+layout.svelte

index 0da8083b5039949833274c8bd4b729e59d33f529..9cff8a01267bd945e034dffa76bfb7b881769cf9 100644 (file)
Binary files a/tools/server/public/index.html.gz and b/tools/server/public/index.html.gz differ
index 361144915f0d37d174bb0152988a20dd8846fdb9..957fddabaa72ac970b1e40717ea487147b7e3b8d 100644 (file)
                        "integrity": "sha512-oJrXtQiAXLvT9clCf1K4kxp3eKsQhIaZqxEyowkBcsvZDdZkbWrVmnGknxs5flTD0VGsxrxKgBCZty1EzoiMzA==",
                        "dev": true,
                        "license": "Apache-2.0",
-                       "peer": true,
                        "dependencies": {
                                "@swc/helpers": "^0.5.0"
                        }
                        "integrity": "sha512-W9R51zUCd2iHOQBg/D93+bdpYv6kbtFx+kft5X8lPKQl6yEu0aKs9i5N5GyCASOhIApgx/tkqZIJ7vgM4cqrHA==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "ts-dedent": "^2.0.0",
                                "type-fest": "~2.19"
                        "integrity": "sha512-875hTUkEbz+MyJIxWbQjfMaekqdmEKUUfR7JyKcpfMRZqcGyrO9Gd+iS1D/Dx8LpE5FEtutWGOtlAh4ReSAiOA==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "@standard-schema/spec": "^1.0.0",
                                "@sveltejs/acorn-typescript": "^1.0.5",
                        "integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0",
                                "debug": "^4.4.1",
                        "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "@babel/code-frame": "^7.10.4",
                                "@babel/runtime": "^7.12.5",
                        "integrity": "sha512-+0/4J266CBGPUq/ELg7QUHhN25WYjE0wYTPSQJn1xeu8DOlIOPxXxrNGiLmfAWl7HMMgWFWXpt9IDjMWrF5Iow==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "undici-types": "~7.16.0"
                        }
                        "integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "@typescript-eslint/scope-manager": "8.56.0",
                                "@typescript-eslint/types": "8.56.0",
                        "integrity": "sha512-tJxiPrWmzH8a+w9nLKlQMzAKX/7VjFs50MWgcAj7p9XQ7AQ9/35fByFYptgPELyLw+0aixTnC4pUWV+APcZ/kw==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "@testing-library/dom": "^10.4.0",
                                "@testing-library/user-event": "^14.6.1",
                        "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "@vitest/utils": "3.2.4",
                                "pathe": "^2.0.3",
                        "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
                        "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
                        "license": "MIT",
-                       "peer": true,
                        "bin": {
                                "acorn": "bin/acorn"
                        },
                        "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
                        "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
                        "dev": true,
-                       "license": "MIT"
+                       "license": "MIT",
+                       "peer": true
                },
                "node_modules/debug": {
                        "version": "4.4.3",
                        "dev": true,
                        "hasInstallScript": true,
                        "license": "MIT",
-                       "peer": true,
                        "bin": {
                                "esbuild": "bin/esbuild"
                        },
                        "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "@eslint-community/eslint-utils": "^4.8.0",
                                "@eslint-community/regexpp": "^4.12.1",
                        "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz",
                        "integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==",
                        "license": "MIT",
-                       "peer": true,
                        "engines": {
                                "node": ">=16.9.0"
                        }
                                }
                        ],
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "nanoid": "^3.3.11",
                                "picocolors": "^1.1.1",
                        "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "bin": {
                                "prettier": "bin/prettier.cjs"
                        },
                        "integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "peerDependencies": {
                                "prettier": "^3.0.0",
                                "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
                        "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "engines": {
                                "node": ">=0.10.0"
                        }
                        "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "scheduler": "^0.26.0"
                        },
                        "integrity": "sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "@types/estree": "1.0.8"
                        },
                        "integrity": "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "chokidar": "^4.0.0",
                                "immutable": "^5.0.2",
                        "integrity": "sha512-LwF0VZsT4qkgx66Ad/q0QgZZrU2a5WftaADDEcJ3bGq3O2fHvwWPlSZjM1HiXD4vqP9U5JiMqQkV1gkyH0XJkw==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "@storybook/global": "^5.0.0",
                                "@storybook/icons": "^2.0.1",
                        "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.48.3.tgz",
                        "integrity": "sha512-w7QZ398cdNherTdiQ/v3SYLLGOO4948Jgjh04PYqtTYVohmBvbmFwLmo7pp8gp4/1tceRWfSTjHgjtfpCVNJmQ==",
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "@jridgewell/remapping": "^2.3.4",
                                "@jridgewell/sourcemap-codec": "^1.5.0",
                        "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "funding": {
                                "type": "github",
                                "url": "https://github.com/sponsors/dcastil"
                        "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz",
                        "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==",
                        "dev": true,
-                       "license": "MIT",
-                       "peer": true
+                       "license": "MIT"
                },
                "node_modules/tapable": {
                        "version": "2.2.2",
                        "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
                        "dev": true,
                        "license": "Apache-2.0",
-                       "peer": true,
                        "bin": {
                                "tsc": "bin/tsc",
                                "tsserver": "bin/tsserver"
                        "integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "esbuild": "^0.25.0",
                                "fdir": "^6.5.0",
                        "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
                        "dev": true,
                        "license": "MIT",
-                       "peer": true,
                        "dependencies": {
                                "@types/chai": "^5.2.2",
                                "@vitest/expect": "3.2.4",
                        "resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz",
                        "integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
                        "license": "MIT",
-                       "peer": true,
                        "funding": {
                                "url": "https://github.com/sponsors/colinhacks"
                        }
index 518311f6ec4ba758e82288eb28429781eb77eda9..52d7573756439d8f0e4ed46e08cefeda39b84f7a 100644 (file)
@@ -6,6 +6,7 @@
        import { parseHeadersToArray, serializeHeaders } from '$lib/utils';
        import { UrlProtocol } from '$lib/enums';
        import { MCP_SERVER_URL_PLACEHOLDER } from '$lib/constants';
+       import { mcpStore } from '$lib/stores/mcp.svelte';
 
        interface Props {
                url: string;
                {/if}
 
                {#if !isWebSocket && onUseProxyChange}
-                       <label class="mt-3 flex cursor-pointer items-center gap-2">
+                       <label
+                               class="mt-3 flex items-start gap-2"
+                               class:cursor-pointer={mcpStore.isProxyAvailable}
+                               class:opacity-80={!mcpStore.isProxyAvailable}
+                       >
                                <Switch
+                                       class="mt-1"
                                        id="use-proxy-{id}"
                                        checked={useProxy}
+                                       disabled={!mcpStore.isProxyAvailable}
                                        onCheckedChange={(checked) => onUseProxyChange?.(checked)}
                                />
 
-                               <span class="text-xs text-muted-foreground">Use llama-server proxy</span>
+                               <span>
+                                       <span class="text-xs text-muted-foreground">Use llama-server proxy</span>
+
+                                       <br />
+
+                                       {#if !mcpStore.isProxyAvailable}
+                                               <span class="inline-flex gap-0.75 text-xs text-muted-foreground/60"
+                                                       >(Run <pre>llama-server</pre>
+                                                       with
+                                                       <pre>--webui-mcp-proxy</pre>
+                                                       flag)</span
+                                               >
+                                       {/if}
+                               </span>
                        </label>
                {/if}
        </div>
index f87789d7ab6e322c8109244fbfda0774f1b82af3..dadf8fda62496696e36403c1ffd8c38ed7e29ae3 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 import { browser } from '$app/environment';
+import { base } from '$app/paths';
 import { MCPService } from '$lib/services/mcp.service';
 import { config, settingsStore } from '$lib/stores/settings.svelte';
 import { mcpResourceStore } from '$lib/stores/mcp-resources.svelte';
@@ -42,6 +43,7 @@ import {
        ToolCallType
 } from '$lib/enums';
 import {
+       CORS_PROXY_ENDPOINT,
        DEFAULT_CACHE_TTL_MS,
        DEFAULT_MCP_CONFIG,
        EXPECTED_THEMED_ICON_PAIR_COUNT,
@@ -78,165 +80,13 @@ import type { ListChangedHandlers } from '@modelcontextprotocol/sdk/types.js';
 import type { DatabaseMessageExtraMcpResource, McpServerOverride } from '$lib/types/database';
 import type { SettingsConfigType } from '$lib/types/settings';
 
-export function buildMcpClientConfig(
-       cfg: SettingsConfigType,
-       perChatOverrides?: McpServerOverride[]
-): MCPClientConfig | undefined {
-       return buildMcpClientConfigInternal(cfg, perChatOverrides);
-}
-
-/**
- * Internal helper to build MCP client config.
- * Kept as standalone function for external use and tests.
- */
-export function buildMcpClientConfigInternal(
-       cfg: SettingsConfigType,
-       perChatOverrides?: McpServerOverride[]
-): MCPClientConfig | undefined {
-       const rawServers = parseServerSettings(cfg.mcpServers);
-       if (!rawServers.length) {
-               return undefined;
-       }
-
-       const servers: Record<string, MCPServerConfig> = {};
-
-       for (const [index, entry] of rawServers.entries()) {
-               if (!checkServerEnabled(entry, perChatOverrides)) continue;
-               const normalized = buildServerConfig(entry);
-               if (normalized) servers[generateMcpServerId(entry.id, index)] = normalized;
-       }
-
-       if (Object.keys(servers).length === 0) {
-               return undefined;
-       }
-
-       return {
-               protocolVersion: DEFAULT_MCP_CONFIG.protocolVersion,
-               capabilities: DEFAULT_MCP_CONFIG.capabilities,
-               clientInfo: DEFAULT_MCP_CONFIG.clientInfo,
-               requestTimeoutMs: Math.round(DEFAULT_MCP_CONFIG.requestTimeoutSeconds * 1000),
-               servers
-       };
-}
-
-/**
- * Generates a unique server ID from an optional ID string or index.
- * @deprecated Use MCPStore.#generateServerId instead
- */
-function generateMcpServerId(id: unknown, index: number): string {
-       if (typeof id === 'string' && id.trim()) {
-               return id.trim();
-       }
-
-       return `${MCP_SERVER_ID_PREFIX}-${index + 1}`;
-}
-
-/**
- * Parses raw server settings from config into MCPServerSettingsEntry array.
- * @deprecated Use MCPStore.#parseServerSettings instead
- */
-function parseServerSettings(rawServers: unknown): MCPServerSettingsEntry[] {
-       if (!rawServers) {
-               return [];
-       }
-
-       let parsed: unknown;
-       if (typeof rawServers === 'string') {
-               const trimmed = rawServers.trim();
-               if (!trimmed) {
-                       return [];
-               }
-
-               try {
-                       parsed = JSON.parse(trimmed);
-               } catch (error) {
-                       console.warn('[MCP] Failed to parse mcpServers JSON:', error);
-
-                       return [];
-               }
-       } else {
-               parsed = rawServers;
-       }
-       if (!Array.isArray(parsed)) {
-               return [];
-       }
-
-       return parsed.map((entry, index) => {
-               const url = typeof entry?.url === 'string' ? entry.url.trim() : '';
-               const headers = typeof entry?.headers === 'string' ? entry.headers.trim() : undefined;
-
-               return {
-                       id: generateMcpServerId((entry as { id?: unknown })?.id, index),
-                       enabled: Boolean((entry as { enabled?: unknown })?.enabled),
-                       url,
-                       name: (entry as { name?: string })?.name,
-                       requestTimeoutSeconds: DEFAULT_MCP_CONFIG.requestTimeoutSeconds,
-                       headers: headers || undefined,
-                       useProxy: Boolean((entry as { useProxy?: unknown })?.useProxy)
-               } satisfies MCPServerSettingsEntry;
-       });
-}
-
-/**
- * Builds server configuration from a settings entry.
- * @deprecated Use MCPStore.#buildServerConfig instead
- */
-function buildServerConfig(
-       entry: MCPServerSettingsEntry,
-       connectionTimeoutMs = DEFAULT_MCP_CONFIG.connectionTimeoutMs
-): MCPServerConfig | undefined {
-       if (!entry?.url) {
-               return undefined;
-       }
-
-       let headers: Record<string, string> | undefined;
-       if (entry.headers) {
-               try {
-                       const parsed = JSON.parse(entry.headers);
-                       if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed))
-                               headers = parsed as Record<string, string>;
-               } catch {
-                       console.warn('[MCP] Failed to parse custom headers JSON:', entry.headers);
-               }
-       }
-
-       return {
-               url: entry.url,
-               transport: detectMcpTransportFromUrl(entry.url),
-               handshakeTimeoutMs: connectionTimeoutMs,
-               requestTimeoutMs: Math.round(entry.requestTimeoutSeconds * 1000),
-               headers,
-               useProxy: entry.useProxy
-       };
-}
-
-/**
- * Checks if a server is enabled, considering per-chat overrides.
- * @deprecated Use MCPStore.#checkServerEnabled instead
- */
-function checkServerEnabled(
-       server: MCPServerSettingsEntry,
-       perChatOverrides?: McpServerOverride[]
-): boolean {
-       if (!server.enabled) {
-               return false;
-       }
-
-       if (perChatOverrides) {
-               const override = perChatOverrides.find((o) => o.serverId === server.id);
-
-               return override?.enabled ?? false;
-       }
-
-       return false;
-}
-
 class MCPStore {
        private _isInitializing = $state(false);
        private _error = $state<string | null>(null);
        private _toolCount = $state(0);
        private _connectedServers = $state<string[]>([]);
        private _healthChecks = $state<Record<string, HealthCheckState>>({});
+       private _proxyAvailable = $state(false);
 
        private connections = new Map<string, MCPConnection>();
        private toolsIndex = new Map<string, string>();
@@ -246,6 +96,29 @@ class MCPStore {
        private initPromise: Promise<boolean> | null = null;
        private activeFlowCount = 0;
 
+       constructor() {
+               if (browser) {
+                       this.probeProxy();
+               }
+       }
+
+       /**
+        * Probes the CORS proxy endpoint to determine availability.
+        * The endpoint is only registered when llama-server runs with --webui-mcp-proxy.
+        */
+       async probeProxy(): Promise<void> {
+               try {
+                       const response = await fetch(`${base}${CORS_PROXY_ENDPOINT}`, { method: 'HEAD' });
+                       this._proxyAvailable = response.status !== 404;
+               } catch {
+                       this._proxyAvailable = false;
+               }
+       }
+
+       get isProxyAvailable(): boolean {
+               return this._proxyAvailable;
+       }
+
        /**
         * Generates a unique server ID from an optional ID string or index.
         */
@@ -520,6 +393,7 @@ class MCPStore {
 
        getServerLabel(server: MCPServerSettingsEntry): string {
                const healthState = this.getHealthCheckState(server.id);
+
                if (healthState?.status === HealthCheckStatus.SUCCESS)
                        return (
                                healthState.serverInfo?.title || healthState.serverInfo?.name || server.name || server.url
@@ -603,6 +477,7 @@ class MCPStore {
         */
        #proxyIconSrc(src: string): string {
                if (src.startsWith('data:')) return src;
+               if (!this._proxyAvailable) return src;
 
                return getProxiedUrlString(src);
        }
@@ -629,7 +504,7 @@ class MCPStore {
                        }
                }
 
-               return getFaviconUrl(server.url);
+               return getFaviconUrl(server.url, this._proxyAvailable);
        }
 
        isAnyServerLoading(): boolean {
@@ -2072,6 +1947,7 @@ export const mcpIsInitializing = () => mcpStore.isInitializing;
 export const mcpIsInitialized = () => mcpStore.isInitialized;
 export const mcpError = () => mcpStore.error;
 export const mcpIsEnabled = () => mcpStore.isEnabled;
+export const mcpIsProxyAvailable = () => mcpStore.isProxyAvailable;
 export const mcpAvailableTools = () => mcpStore.availableTools;
 export const mcpConnectedServerCount = () => mcpStore.connectedServerCount;
 export const mcpConnectedServerNames = () => mcpStore.connectedServerNames;
index 4c75299178319abe73f5b480940c6988af00d09f..a1afa1643da9d0b6a521587efc8dbe79efeb41ab 100644 (file)
@@ -17,7 +17,7 @@ import {
  * @param urlString - The URL to get the favicon for
  * @returns The favicon URL or null if invalid
  */
-export function getFaviconUrl(urlString: string): string | null {
+export function getFaviconUrl(urlString: string, useProxy = true): string | null {
        try {
                const url = new URL(urlString);
                const hostnameParts = url.hostname.split(DOMAIN_SEPARATOR);
@@ -27,7 +27,7 @@ export function getFaviconUrl(urlString: string): string | null {
                                : url.hostname;
 
                const googleFaviconUrl = `${GOOGLE_FAVICON_BASE_URL}?domain=${rootDomain}&sz=${DEFAULT_FAVICON_SIZE}`;
-               return getProxiedUrlString(googleFaviconUrl);
+               return useProxy ? getProxiedUrlString(googleFaviconUrl) : googleFaviconUrl;
        } catch {
                return null;
        }
index ef27276a3c8264cf68d1296b9e116274b037627d..9093fc2197c763bdca7a83d128b20f3b340d9cbe 100644 (file)
                                <Sidebar.Trigger
                                        class="transition-left absolute left-0 z-[900] duration-200 ease-linear {sidebarOpen
                                                ? 'md:left-[var(--sidebar-width)]'
-                                               : ''}"
+                                               : 'md:left-0!'}"
                                        style="translate: 1rem 1rem;"
                                />
                        {/if}