openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
177 lines (176 loc) • 7.7 kB
JavaScript
import { c as normalizeOptionalString } from "./string-coerce-mnp54Vah.js";
import "./string-coerce-runtime-CEGJWkQ_.js";
import { i as getCachedLiveCatalogValue } from "./provider-catalog-shared-DZr41kLr.js";
import { i as OLLAMA_DEFAULT_BASE_URL } from "./defaults-CPlCYE-I.js";
import { t as readProviderBaseUrl, u as resolveOllamaApiBase } from "./provider-base-url-BEd2ujfU.js";
//#region extensions/ollama/src/discovery-shared.ts
const OLLAMA_PROVIDER_ID = "ollama";
const OLLAMA_DEFAULT_API_KEY = "ollama-local";
function readStringValue(value) {
if (typeof value === "string") return normalizeOptionalString(value);
if (value && typeof value === "object" && "value" in value) return normalizeOptionalString(value.value);
}
function isOllamaApiKeyMarker(value) {
return value === "OLLAMA_API_KEY" || value === "ollama-local";
}
function resolveOllamaDiscoveryApiKey(params) {
const envValue = normalizeOptionalString(params.env.OLLAMA_API_KEY);
const resolvedApiKey = normalizeOptionalString(params.resolvedApiKey);
const resolvedDiscoveryApiKey = normalizeOptionalString(params.resolvedDiscoveryApiKey);
const explicitApiKey = normalizeOptionalString(params.explicitApiKey);
if (explicitApiKey && !isOllamaApiKeyMarker(explicitApiKey)) return explicitApiKey;
if (!isLocalOllamaBaseUrl(params.baseUrl)) {
if (resolvedDiscoveryApiKey) return resolvedDiscoveryApiKey;
if (resolvedApiKey && !isOllamaApiKeyMarker(resolvedApiKey)) return resolvedApiKey;
return envValue && envValue !== "ollama-local" ? envValue : void 0;
}
if (resolvedApiKey && resolvedApiKey !== envValue && !isOllamaApiKeyMarker(resolvedApiKey)) return resolvedApiKey;
return OLLAMA_DEFAULT_API_KEY;
}
function shouldSkipAmbientOllamaDiscovery(env) {
return Boolean(env.VITEST) || env.NODE_ENV === "test";
}
const LOCAL_OLLAMA_HOSTNAMES = new Set([
"localhost",
"127.0.0.1",
"0.0.0.0",
"::1",
"::",
"docker.orb.internal",
"host.docker.internal",
"host.orb.internal"
]);
const LOOPBACK_OLLAMA_HOSTNAMES = new Set([
"localhost",
"127.0.0.1",
"0.0.0.0",
"::1",
"::"
]);
function isIpv4Loopback(host) {
if (!/^\d+\.\d+\.\d+\.\d+$/.test(host)) return false;
const octets = host.split(".").map((part) => Number.parseInt(part, 10));
if (octets.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) return false;
return octets[0] === 127;
}
function isIpv4PrivateRange(host) {
if (!/^\d+\.\d+\.\d+\.\d+$/.test(host)) return false;
const octets = host.split(".").map((part) => Number.parseInt(part, 10));
if (octets.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) return false;
const [a, b] = octets;
return a === 10 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168;
}
function isIpv6LocalRange(host) {
const lower = host.toLowerCase();
return /^fe[89ab][0-9a-f]:/.test(lower) || /^f[cd][0-9a-f]{2}:/.test(lower);
}
function isLocalOllamaBaseUrl(baseUrl) {
if (!baseUrl) return true;
let parsed;
try {
parsed = new URL(baseUrl);
} catch {
return false;
}
let host = parsed.hostname.toLowerCase();
if (host.startsWith("[") && host.endsWith("]")) host = host.slice(1, -1);
return LOCAL_OLLAMA_HOSTNAMES.has(host) || host.endsWith(".local") || isIpv4PrivateRange(host) || isIpv6LocalRange(host) || !host.includes(".") && !host.includes(":");
}
function isLoopbackOllamaBaseUrl(baseUrl) {
if (!baseUrl) return true;
let parsed;
try {
parsed = new URL(baseUrl);
} catch {
return false;
}
let host = parsed.hostname.toLowerCase();
if (host.startsWith("[") && host.endsWith("]")) host = host.slice(1, -1);
return LOOPBACK_OLLAMA_HOSTNAMES.has(host) || isIpv4Loopback(host);
}
function hasExplicitRemoteOllamaApiProvider(providers) {
if (!providers) return false;
for (const [providerId, provider] of Object.entries(providers)) {
if (providerId === "ollama" || !provider) continue;
if (normalizeOptionalString(provider.api)?.toLowerCase() !== "ollama") continue;
const baseUrl = readProviderBaseUrl(provider);
if (baseUrl && !isLoopbackOllamaBaseUrl(baseUrl)) return true;
}
return false;
}
function shouldUseSyntheticOllamaAuth(providerConfig) {
if (!hasMeaningfulExplicitOllamaConfig(providerConfig)) return false;
return isLocalOllamaBaseUrl(readProviderBaseUrl(providerConfig));
}
function hasMeaningfulExplicitOllamaConfig(providerConfig) {
if (!providerConfig) return false;
if (Array.isArray(providerConfig.models) && providerConfig.models.length > 0) return true;
const baseUrl = readProviderBaseUrl(providerConfig);
if (baseUrl) return resolveOllamaApiBase(baseUrl) !== OLLAMA_DEFAULT_BASE_URL;
if (readStringValue(providerConfig.apiKey)) return true;
if (providerConfig.auth) return true;
if (typeof providerConfig.authHeader === "boolean") return true;
if (providerConfig.headers && typeof providerConfig.headers === "object" && Object.keys(providerConfig.headers).length > 0) return true;
if (providerConfig.request) return true;
if (typeof providerConfig.injectNumCtxForOpenAICompat === "boolean") return true;
return false;
}
async function resolveOllamaDiscoveryResult(params) {
const explicit = params.ctx.config.models?.providers?.ollama;
const hasExplicitModels = Array.isArray(explicit?.models) && explicit.models.length > 0;
const hasMeaningfulExplicitConfig = hasMeaningfulExplicitOllamaConfig(explicit);
const hasRemoteOllamaApiProvider = hasExplicitRemoteOllamaApiProvider(params.ctx.config.models?.providers);
const discoveryEnabled = params.pluginConfig.discovery?.enabled;
if (!hasExplicitModels && discoveryEnabled === false) return null;
const resolvedOllamaAuth = params.ctx.resolveProviderApiKey(OLLAMA_PROVIDER_ID);
const ollamaKey = resolvedOllamaAuth.apiKey;
const ollamaDiscoveryKey = resolvedOllamaAuth.discoveryApiKey;
const hasOllamaDiscoveryOptIn = typeof ollamaKey === "string" && ollamaKey.trim().length > 0;
const hasRealOllamaKey = typeof ollamaKey === "string" && ollamaKey.trim().length > 0 && ollamaKey.trim() !== "ollama-local";
const explicitApiKey = readStringValue(explicit?.apiKey);
if (hasExplicitModels && explicit) {
const baseUrl = resolveOllamaApiBase(readProviderBaseUrl(explicit) ?? "http://127.0.0.1:11434");
const apiKey = resolveOllamaDiscoveryApiKey({
env: params.ctx.env,
baseUrl,
explicitApiKey,
resolvedApiKey: ollamaKey,
resolvedDiscoveryApiKey: ollamaDiscoveryKey
});
return { provider: {
...explicit,
baseUrl,
api: explicit.api ?? "ollama",
...apiKey ? { apiKey } : {}
} };
}
if (!hasMeaningfulExplicitConfig && hasRemoteOllamaApiProvider) return null;
if (!hasOllamaDiscoveryOptIn && !hasMeaningfulExplicitConfig) return null;
if (!hasRealOllamaKey && !hasMeaningfulExplicitConfig && shouldSkipAmbientOllamaDiscovery(params.ctx.env)) return null;
const configuredBaseUrl = readProviderBaseUrl(explicit);
const quiet = !hasRealOllamaKey && !hasMeaningfulExplicitConfig;
const provider = await getCachedLiveCatalogValue({
keyParts: [
OLLAMA_PROVIDER_ID,
"models",
configuredBaseUrl ?? "http://127.0.0.1:11434",
ollamaKey,
quiet
],
load: async () => await params.buildProvider(configuredBaseUrl, { quiet })
});
if (provider.models?.length === 0 && !ollamaKey && !explicit?.apiKey) return null;
const apiKey = resolveOllamaDiscoveryApiKey({
env: params.ctx.env,
baseUrl: provider.baseUrl ?? configuredBaseUrl,
explicitApiKey,
resolvedApiKey: ollamaKey,
resolvedDiscoveryApiKey: ollamaDiscoveryKey
});
return { provider: {
...provider,
...apiKey ? { apiKey } : {}
} };
}
//#endregion
export { shouldUseSyntheticOllamaAuth as a, resolveOllamaDiscoveryResult as i, OLLAMA_PROVIDER_ID as n, isLocalOllamaBaseUrl as r, OLLAMA_DEFAULT_API_KEY as t };