From 143fb2ace4a4ea1b1bde395ea1b445f699ad7bed Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Date: Fri, 5 Jun 2026 02:51:01 -0300 Subject: [PATCH] fix(llama-cpp): fall back to local default base URL when none is set (#3197) (#3210) Residual of #3136: a local connection with an empty baseUrl still resolved to this.config.baseUrl (OpenAI). Fall back to the provider's localDefault (127.0.0.1:8080/v1) before the OpenAI default for the local-provider group. Co-authored-by: tjengbudi --- open-sse/executors/default.ts | 10 +++++++++- tests/unit/llama-cpp-local-url.test.ts | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/open-sse/executors/default.ts b/open-sse/executors/default.ts index 0d0e9989b0..d7f114570d 100644 --- a/open-sse/executors/default.ts +++ b/open-sse/executors/default.ts @@ -28,6 +28,7 @@ import { buildWatsonxChatUrl } from "../config/watsonx.ts"; import { buildOciChatUrl } from "../config/oci.ts"; import { buildSapChatUrl, getSapResourceGroup } from "../config/sap.ts"; import { buildMaritalkChatUrl } from "../config/maritalk.ts"; +import { LOCAL_PROVIDERS } from "@/shared/constants/providers"; import type { PoolConfig } from "../services/sessionPool/types.ts"; @@ -216,7 +217,14 @@ export class DefaultExecutor extends BaseExecutor { case "docker-model-runner": case "xinference": case "oobabooga": { - const baseUrl = credentials?.providerSpecificData?.baseUrl || this.config.baseUrl; + // #3197 (residual of #3136): for self-hosted/local providers, prefer the + // catalog's localDefault when no explicit baseUrl is set. `this.config` + // falls back to PROVIDERS.openai for providers not in the open-sse + // registry (llama-cpp, etc.), so without this guard an empty baseUrl + // silently hits OpenAI's API. Fall back to localDefault BEFORE config. + const localDefault = LOCAL_PROVIDERS[this.provider]?.localDefault; + const baseUrl = + credentials?.providerSpecificData?.baseUrl || localDefault || this.config.baseUrl; return normalizeOpenAIChatUrl(baseUrl); } case "zai": diff --git a/tests/unit/llama-cpp-local-url.test.ts b/tests/unit/llama-cpp-local-url.test.ts index ecd110fe26..45a6e4ea13 100644 --- a/tests/unit/llama-cpp-local-url.test.ts +++ b/tests/unit/llama-cpp-local-url.test.ts @@ -21,3 +21,23 @@ test("llama-cpp buildUrl routes to the configured local baseUrl, not OpenAI", () // is an incomplete URL sanitization pattern: `api.openai.com.evil` would match). assert.equal(new URL(url).hostname, "127.0.0.1", `expected local host, got ${url}`); }); + +// Regression for issue #3197 (residual of #3136): a `llama-cpp` connection with +// an EMPTY base URL (no providerSpecificData.baseUrl) must NOT silently fall back +// to OpenAI's API. The #3136 fix only resolved the local URL when an explicit +// baseUrl was set; with an empty one, `this.config.baseUrl` (= PROVIDERS.openai, +// since llama-cpp is not in the open-sse registry) leaked through, producing +// OpenAI-worded "incorrect api key" errors. Now it must fall back to the +// catalog's localDefault (http://127.0.0.1:8080/v1). +test("llama-cpp buildUrl falls back to the local default when no baseUrl is set", () => { + const executor = new DefaultExecutor("llama-cpp"); + const url = executor.buildUrl("some-model", true, 0, {}); + + assert.equal(url, "http://127.0.0.1:8080/v1/chat/completions"); + assert.equal( + new URL(url).hostname, + "127.0.0.1", + `expected local default host, got ${url}` + ); + assert.notEqual(new URL(url).hostname, "api.openai.com"); +});