mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-01 01:22:37 +02:00
fix: use configured base URL for Ollama model discovery
discoverOllamaModels() was hardcoded to fetch from http://127.0.0.1:11434 regardless of the user's configured Ollama baseUrl. Users running Ollama on a remote server or custom port would see "Failed to discover Ollama models: TypeError: fetch failed" even though completions worked fine. Thread the user-configured baseUrl from the explicit provider config down through resolveImplicitProviders -> buildOllamaProvider -> discoverOllamaModels, falling back to the default localhost URL when no custom URL is set. A new resolveOllamaApiBase() helper strips the /v1 suffix that the OpenAI- compatible endpoint uses, since the native Ollama /api/tags endpoint lives at the root. Fixes #14053
This commit is contained in:
committed by
Gustavo Madeira Santana
parent
3ed06c6f36
commit
5dd910dd1e
@@ -111,13 +111,31 @@ interface OllamaTagsResponse {
|
||||
models: OllamaModel[];
|
||||
}
|
||||
|
||||
async function discoverOllamaModels(): Promise<ModelDefinitionConfig[]> {
|
||||
/**
|
||||
* Derive the Ollama native API base URL from a configured base URL.
|
||||
*
|
||||
* Users typically configure `baseUrl` with a `/v1` suffix (e.g.
|
||||
* `http://192.168.20.14:11434/v1`) for the OpenAI-compatible endpoint.
|
||||
* The native Ollama API lives at the root (e.g. `/api/tags`), so we
|
||||
* strip the `/v1` suffix when present.
|
||||
*/
|
||||
function resolveOllamaApiBase(configuredBaseUrl?: string): string {
|
||||
if (!configuredBaseUrl) {
|
||||
return OLLAMA_API_BASE_URL;
|
||||
}
|
||||
// Strip trailing slash, then strip /v1 suffix if present
|
||||
const trimmed = configuredBaseUrl.replace(/\/+$/, "");
|
||||
return trimmed.replace(/\/v1$/i, "");
|
||||
}
|
||||
|
||||
async function discoverOllamaModels(baseUrl?: string): Promise<ModelDefinitionConfig[]> {
|
||||
// Skip Ollama discovery in test environments
|
||||
if (process.env.VITEST || process.env.NODE_ENV === "test") {
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const response = await fetch(`${OLLAMA_API_BASE_URL}/api/tags`, {
|
||||
const apiBase = resolveOllamaApiBase(baseUrl);
|
||||
const response = await fetch(`${apiBase}/api/tags`, {
|
||||
signal: AbortSignal.timeout(5000),
|
||||
});
|
||||
if (!response.ok) {
|
||||
@@ -410,10 +428,10 @@ async function buildVeniceProvider(): Promise<ProviderConfig> {
|
||||
};
|
||||
}
|
||||
|
||||
async function buildOllamaProvider(): Promise<ProviderConfig> {
|
||||
const models = await discoverOllamaModels();
|
||||
async function buildOllamaProvider(configuredBaseUrl?: string): Promise<ProviderConfig> {
|
||||
const models = await discoverOllamaModels(configuredBaseUrl);
|
||||
return {
|
||||
baseUrl: OLLAMA_BASE_URL,
|
||||
baseUrl: configuredBaseUrl ?? OLLAMA_BASE_URL,
|
||||
api: "openai-completions",
|
||||
models,
|
||||
};
|
||||
@@ -456,6 +474,7 @@ export function buildQianfanProvider(): ProviderConfig {
|
||||
|
||||
export async function resolveImplicitProviders(params: {
|
||||
agentDir: string;
|
||||
explicitProviders?: Record<string, ProviderConfig> | null;
|
||||
}): Promise<ModelsConfig["providers"]> {
|
||||
const providers: Record<string, ProviderConfig> = {};
|
||||
const authStore = ensureAuthProfileStore(params.agentDir, {
|
||||
@@ -541,12 +560,15 @@ export async function resolveImplicitProviders(params: {
|
||||
break;
|
||||
}
|
||||
|
||||
// Ollama provider - only add if explicitly configured
|
||||
// Ollama provider - only add if explicitly configured.
|
||||
// Use the user's configured baseUrl (from explicit providers) for model
|
||||
// discovery so that remote / non-default Ollama instances are reachable.
|
||||
const ollamaKey =
|
||||
resolveEnvApiKeyVarName("ollama") ??
|
||||
resolveApiKeyFromProfiles({ provider: "ollama", store: authStore });
|
||||
if (ollamaKey) {
|
||||
providers.ollama = { ...(await buildOllamaProvider()), apiKey: ollamaKey };
|
||||
const ollamaBaseUrl = params.explicitProviders?.ollama?.baseUrl;
|
||||
providers.ollama = { ...(await buildOllamaProvider(ollamaBaseUrl)), apiKey: ollamaKey };
|
||||
}
|
||||
|
||||
const togetherKey =
|
||||
|
||||
@@ -86,7 +86,7 @@ export async function ensureOpenClawModelsJson(
|
||||
const agentDir = agentDirOverride?.trim() ? agentDirOverride.trim() : resolveOpenClawAgentDir();
|
||||
|
||||
const explicitProviders = cfg.models?.providers ?? {};
|
||||
const implicitProviders = await resolveImplicitProviders({ agentDir });
|
||||
const implicitProviders = await resolveImplicitProviders({ agentDir, explicitProviders });
|
||||
const providers: Record<string, ProviderConfig> = mergeProviders({
|
||||
implicit: implicitProviders,
|
||||
explicit: explicitProviders,
|
||||
|
||||
Reference in New Issue
Block a user