openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
218 lines (217 loc) • 9.11 kB
JavaScript
import { l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js";
import { s as coerceSecretRef } from "./types.secrets-kC0nOetj.js";
import { s as isLoopbackHost } from "./net-DbNPs6Xm.js";
import "./string-coerce-runtime-GQa0ehRA.js";
import "./ssrf-runtime-Bum5C6NN.js";
import { r as getCachedLiveCatalogValue } from "./provider-catalog-shared-B4jeC2Nd.js";
import "./secret-input-runtime-Clavxxg-.js";
import { a as OLLAMA_DEFAULT_API_KEY, o as OLLAMA_DEFAULT_BASE_URL } from "./defaults-BiE2_Zq0.js";
import { t as readProviderBaseUrl } from "./provider-base-url-E6aWTKii.js";
import { y as resolveOllamaApiBase } from "./provider-models-BK60TdeT.js";
//#region extensions/ollama/src/discovery-shared.ts
const OLLAMA_PROVIDER_ID = "ollama";
function readOllamaStringValue(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 resolveOllamaRuntimeBaseUrl(params) {
if (params.configuredBaseUrl && params.api && params.api !== "ollama") return params.configuredBaseUrl;
return params.discoveredBaseUrl;
}
function resolveOllamaDiscoveryAuth(params) {
const envValue = normalizeOptionalString(params.env.OLLAMA_API_KEY);
const resolvedApiKey = normalizeOptionalString(params.resolvedAuth.apiKey);
const resolvedDiscoveryApiKey = normalizeOptionalString(params.resolvedAuth.discoveryApiKey);
const explicitRef = coerceSecretRef(params.explicitApiKey);
const explicitApiKey = explicitRef ? resolvedDiscoveryApiKey : readOllamaStringValue(params.explicitApiKey);
if (explicitRef && !explicitApiKey) return null;
if (explicitApiKey && (explicitRef || !isOllamaApiKeyMarker(explicitApiKey))) return {
apiKey: explicitRef ?? explicitApiKey,
discoveryApiKey: explicitApiKey
};
if (!isLocalOllamaBaseUrl(params.baseUrl)) {
if (resolvedDiscoveryApiKey) return {
apiKey: resolvedApiKey,
discoveryApiKey: resolvedDiscoveryApiKey
};
if (resolvedApiKey && !isOllamaApiKeyMarker(resolvedApiKey)) return {
apiKey: resolvedApiKey,
discoveryApiKey: resolvedApiKey
};
return envValue && envValue !== "ollama-local" ? {
apiKey: "OLLAMA_API_KEY",
discoveryApiKey: envValue
} : {};
}
if (resolvedApiKey && resolvedApiKey !== envValue && !isOllamaApiKeyMarker(resolvedApiKey)) return {
apiKey: resolvedApiKey,
discoveryApiKey: resolvedDiscoveryApiKey ?? resolvedApiKey
};
return { apiKey: OLLAMA_DEFAULT_API_KEY };
}
function shouldSkipAmbientOllamaDiscovery(env) {
return Boolean(env.VITEST) || env.NODE_ENV === "test";
}
const LOCAL_OLLAMA_HOSTNAMES = /* @__PURE__ */ new Set([
"localhost",
"0.0.0.0",
"::1",
"::",
"docker.orb.internal",
"host.docker.internal",
"host.orb.internal"
]);
const LOOPBACK_OLLAMA_HOSTNAMES = /* @__PURE__ */ new Set([
"localhost",
"127.0.0.1",
"0.0.0.0",
"::1",
"::"
]);
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;
if (a === void 0 || b === void 0) return false;
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) || isLoopbackHost(host) || host.endsWith(".local") || isIpv4PrivateRange(host) || isIpv6LocalRange(host) || !host.includes(".") && !host.includes(":");
}
const HOSTED_OLLAMA_CLOUD_HOSTNAMES = /* @__PURE__ */ new Set(["ollama.com", "api.ollama.com"]);
function isHostedOllamaCloud(baseUrl) {
if (!baseUrl) return false;
let parsed;
try {
parsed = new URL(baseUrl);
} catch {
return false;
}
const host = parsed.hostname.toLowerCase();
return HOSTED_OLLAMA_CLOUD_HOSTNAMES.has(host) || host.endsWith(".ollama.com");
}
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) || isLoopbackHost(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) {
const apiKey = readOllamaStringValue(providerConfig?.apiKey);
if (coerceSecretRef(providerConfig?.apiKey) || apiKey && !isOllamaApiKeyMarker(apiKey) || !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 (readOllamaStringValue(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 configuredBaseUrl = readProviderBaseUrl(explicit);
if (!hasExplicitModels && configuredBaseUrl && isHostedOllamaCloud(configuredBaseUrl)) return null;
const resolvedOllamaAuth = params.ctx.resolveProviderApiKey(OLLAMA_PROVIDER_ID);
const ollamaKey = resolvedOllamaAuth.apiKey;
const hasOllamaDiscoveryOptIn = typeof ollamaKey === "string" && ollamaKey.trim().length > 0;
const hasRealOllamaKey = typeof ollamaKey === "string" && ollamaKey.trim().length > 0 && ollamaKey.trim() !== "ollama-local";
const auth = resolveOllamaDiscoveryAuth({
env: params.ctx.env,
baseUrl: configuredBaseUrl,
explicitApiKey: explicit?.apiKey,
resolvedAuth: resolvedOllamaAuth
});
if (!auth) return null;
const { apiKey, discoveryApiKey } = auth;
if (hasExplicitModels && explicit) {
const discoveredBaseUrl = resolveOllamaApiBase(configuredBaseUrl);
const api = explicit.api ?? "ollama";
return { provider: {
...explicit,
models: explicit.models ?? [],
baseUrl: resolveOllamaRuntimeBaseUrl({
api,
configuredBaseUrl,
discoveredBaseUrl
}),
api,
...apiKey ? { apiKey } : {}
} };
}
if (!hasMeaningfulExplicitConfig && hasRemoteOllamaApiProvider) return null;
if (!hasOllamaDiscoveryOptIn && !hasMeaningfulExplicitConfig) return null;
if (!hasRealOllamaKey && !hasMeaningfulExplicitConfig && shouldSkipAmbientOllamaDiscovery(params.ctx.env)) return null;
const quiet = !hasRealOllamaKey && !hasMeaningfulExplicitConfig;
const provider = await getCachedLiveCatalogValue({
keyParts: [
OLLAMA_PROVIDER_ID,
"models",
resolveOllamaApiBase(configuredBaseUrl),
discoveryApiKey,
quiet
],
load: async () => await params.buildProvider(configuredBaseUrl, {
quiet,
...discoveryApiKey ? { apiKey: discoveryApiKey } : {}
})
});
if (provider.models?.length === 0 && !ollamaKey && !explicit?.apiKey) return null;
const api = explicit?.api ?? provider.api;
return { provider: {
...provider,
baseUrl: resolveOllamaRuntimeBaseUrl({
api,
configuredBaseUrl,
discoveredBaseUrl: provider.baseUrl
}),
api,
...apiKey ? { apiKey } : {}
} };
}
//#endregion
export { shouldUseSyntheticOllamaAuth as a, resolveOllamaRuntimeBaseUrl as i, isLocalOllamaBaseUrl as n, resolveOllamaDiscoveryResult as r, OLLAMA_PROVIDER_ID as t };