openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
434 lines (433 loc) • 20 kB
JavaScript
import { F as resolveTimerTimeoutMs } from "./number-coercion-CLj0HTDM.js";
import { c as isRecord } from "./record-coerce-DItp3I4t.js";
import { m as resolveAgentWorkspaceDir, o as listAgentIds, u as resolveAgentDir, y as resolveDefaultAgentId } from "./agent-scope-config-DcbEhP0R.js";
import { n as resolveDefaultAgentWorkspaceDir } from "./workspace-default-DPT1Dhad.js";
import { r as resolveRuntimeWorkerUrl } from "./runtime-worker-url-CpdriB1D.js";
import { u as restorePluginMetadataSnapshot } from "./plugin-metadata-snapshot-w-4EjxI4.js";
import { c as normalizeProviderId } from "./model-ref-shared-Dz7QU0Lx.js";
import { d as hashRuntimeConfigValue } from "./runtime-snapshot-BaQikjTR.js";
import { n as withPluginRuntimeGenerationScope } from "./generation-scope-Cf83d_iq.js";
import { a as ensureAuthProfileStoreWithoutExternalProfiles, c as getRuntimeAuthProfileStoreSnapshot, r as ensureAuthProfileStore } from "./store-F1B2duCT.js";
import { n as listProfilesForProvider } from "./profile-list-DyfWX-d2.js";
import { o as captureProviderSyntheticAuthFacts } from "./provider-runtime-BRJDPNgk.js";
import { t as listManifestSyntheticAuthProviderRefs } from "./synthetic-auth.runtime.js";
import { n as WorkerTaskPool, t as WorkerTaskError } from "./worker-task-pool-BNbf5LmH.js";
import "./workspace-ConDEamr.js";
import { n as externalCliDiscoveryForProviderAuth, r as externalCliDiscoveryForProviders } from "./external-cli-discovery-CbeZXk1q.js";
import { t as prepareOwnedPluginLoadContext } from "./prepared-model-runtime.plugin-context-Cfpk1nYL.js";
import "./auth-profiles-BdUEhE7u.js";
import { n as createModelAuthAvailabilityResolver } from "./model-auth-availability-CRH5-dWY.js";
import { i as createRuntimeProviderAuthLookup, o as prepareRuntimeAvailableProviderAuth } from "./model-auth-provider-Dd_3dXeY.js";
import { a as hasAvailableAuthForProvider } from "./model-auth-C48_DZ-I.js";
import { a as getCurrentProviderAuthStates, c as setCurrentProviderAuthWarmWorker, i as clearCurrentProviderAuthWarmWorker, n as claimCurrentProviderAuthStateGeneration, o as isCurrentProviderAuthStateGeneration, s as publishProviderAuthWarmSnapshot, t as cancelCurrentProviderAuthWarmWorker } from "./model-provider-auth-state-Bn1pG368.js";
import "./model-selection-di2kjKCB.js";
//#region src/agents/model-provider-auth-warm.ts
/** Parent-owned native auth preparation and compute-worker lifetime for provider warmup. */
const PROVIDER_AUTH_WARM_CANCEL_POLL_MS = 25;
function isProviderAuthWarmSnapshot(value) {
if (!isRecord(value) || !Array.isArray(value.agents)) return false;
return value.agents.every((agent) => isRecord(agent) && typeof agent.agentId === "string" && typeof agent.configFingerprint === "string" && Array.isArray(agent.providers) && agent.providers.every((entry) => Array.isArray(entry) && entry.length === 2 && typeof entry[0] === "string" && typeof entry[1] === "boolean"));
}
function isProviderAuthWarmWorkerResult(value) {
if (!isRecord(value)) return false;
if (value.status === "failed") return typeof value.error === "string";
return value.status === "ok" && isProviderAuthWarmSnapshot(value.snapshot);
}
const runProviderAuthWarmWorker = async (params) => {
const workerUrl = params.workerUrl ?? resolveRuntimeWorkerUrl({
currentModuleUrl: import.meta.url,
sourceWorkerName: "model-provider-auth.worker",
distWorkerPath: "agents/model-provider-auth.worker.js"
});
const env = { ...process.env };
const pool = new WorkerTaskPool({
workerUrl,
maxWorkers: 1,
workerOptions: { env }
});
const handle = new AbortController();
const deadline = new AbortController();
const signal = AbortSignal.any([handle.signal, deadline.signal]);
const timeout = setTimeout(() => deadline.abort(new WorkerTaskError("worker task timed out", "timeout")), resolveTimerTimeoutMs(params.timeoutMs, 6e4));
setCurrentProviderAuthWarmWorker(handle);
const cancelTimer = setInterval(() => {
if (params.isCancelled()) handle.abort();
}, PROVIDER_AUTH_WARM_CANCEL_POLL_MS);
cancelTimer.unref();
try {
if (params.isCancelled()) handle.abort();
const { getPreparedModelCatalogOwnerSnapshot } = await import("./prepared-model-catalog-BH7NC_p8.js");
const syntheticAuth = [];
for (const agentId of listAgentIds(params.cfg)) {
if (params.isCancelled()) handle.abort();
signal.throwIfAborted();
const workspaceDir = resolveAgentWorkspaceDir(params.cfg, agentId);
const owner = getPreparedModelCatalogOwnerSnapshot({
config: params.cfg,
agentId,
workspaceDir
});
const metadata = owner?.metadataSnapshot ?? prepareOwnedPluginLoadContext({
config: params.cfg,
workspaceDir
}, env, void 0);
const facts = await withPluginRuntimeGenerationScope({
metadataSnapshot: metadata,
pluginRegistry: owner?.pluginRegistry
}, () => captureProviderSyntheticAuthFacts({
config: params.cfg,
env,
workspaceDir,
providerRefs: [...listManifestSyntheticAuthProviderRefs(metadata.index), ...Object.keys(params.cfg.models?.providers ?? {})],
signal
}));
signal.throwIfAborted();
const { normalizePluginId: _normalizePluginId, ...metadataSnapshot } = metadata;
syntheticAuth.push({
agentId,
workspaceDir,
metadataSnapshot,
...owner ? { modelCatalog: owner.modelCatalog } : {},
facts: facts.map((fact) => ({
providerRef: fact.providerRef,
result: fact.result?.apiKey.trim() ? {
apiKey: "synthetic-auth-present",
source: "prepared synthetic auth",
mode: fact.result.mode,
...fact.result.expiresAt === void 0 ? {} : { expiresAt: fact.result.expiresAt }
} : null
}))
});
}
const message = await pool.run({
cfg: params.cfg,
syntheticAuth,
...params.runtimeAuthStores?.length ? { runtimeAuthStores: params.runtimeAuthStores } : {},
...params.runtimeAuthLookups?.length ? { runtimeAuthLookups: params.runtimeAuthLookups } : {},
...params.omitFalseProviderAuth ? { omitFalseProviderAuth: true } : {}
}, {
timeoutMs: params.timeoutMs,
signal
});
if (handle.signal.aborted || params.isCancelled()) return { agents: [] };
if (!isProviderAuthWarmWorkerResult(message)) throw new Error("invalid provider auth warm worker response");
if (message.status === "failed") throw new Error(message.error);
return message.snapshot;
} catch (error) {
if (handle.signal.aborted) return { agents: [] };
if (error instanceof WorkerTaskError && error.code === "timeout") throw new Error("provider auth warm worker timed out", { cause: error });
throw error;
} finally {
clearTimeout(timeout);
clearInterval(cancelTimer);
clearCurrentProviderAuthWarmWorker(handle);
await pool.close();
}
};
//#endregion
//#region src/agents/model-provider-auth.ts
/**
* Warms and queries provider-auth availability for model catalogs. The module
* keeps per-agent auth snapshots process-current so model listing can avoid
* repeated env/profile/plugin discovery on hot paths.
*/
const PROVIDER_AUTH_WARM_WORKER_TIMEOUT_MS = 12e4;
const configFingerprintCache = /* @__PURE__ */ new WeakMap();
function resolvePreparedStateForCaller(params) {
if (!params.states) return null;
if (params.callerAgentId !== void 0) return params.states.get(params.callerAgentId) ?? null;
if (!params.cfg) return null;
return params.states.get(resolveDefaultAgentId(params.cfg)) ?? null;
}
function resolveProviderAuthConfigFingerprint(cfg) {
if (!cfg) return null;
const cached = configFingerprintCache.get(cfg);
if (cached !== void 0) return cached;
const fingerprint = hashRuntimeConfigValue(cfg);
configFingerprintCache.set(cfg, fingerprint);
return fingerprint;
}
/** Resolves whether auth is available for a model provider in the caller's runtime scope. */
async function hasAuthForModelProvider(params) {
const provider = normalizeProviderId(params.provider);
const preparedStates = getCurrentProviderAuthStates();
const workspaceDir = params.workspaceDir ?? resolveDefaultAgentWorkspaceDir();
const configFingerprint = resolveProviderAuthConfigFingerprint(params.cfg);
const preparedState = resolvePreparedStateForCaller({
states: preparedStates,
cfg: params.cfg,
callerAgentId: params.agentId
});
const expectedWorkspaceDir = preparedState !== null && params.cfg ? resolveAgentWorkspaceDir(params.cfg, preparedState.agentId) : null;
const expectedAgentDir = preparedState !== null && params.cfg ? resolveAgentDir(params.cfg, preparedState.agentId) : null;
if (preparedState !== null && configFingerprint === preparedState.configFingerprint && workspaceDir === expectedWorkspaceDir && (params.agentDir === void 0 || params.agentDir === expectedAgentDir) && (params.allowPreparedRuntimeAuth === true || params.discoverExternalCliAuth !== false && params.allowPluginSyntheticAuth !== false) && params.env === void 0 && params.store === void 0 && params.modelApi === void 0) {
const preparedAnswer = preparedState.providers.get(provider);
if (preparedAnswer !== void 0) return preparedAnswer;
}
await new Promise((resolve) => {
setImmediate(resolve);
});
const slowPathAgentDir = params.agentDir ?? (params.agentId && params.cfg ? resolveAgentDir(params.cfg, params.agentId, params.env) : void 0);
const store = params.store ?? (params.discoverExternalCliAuth === false ? ensureAuthProfileStoreWithoutExternalProfiles(slowPathAgentDir, { allowKeychainPrompt: false }) : ensureAuthProfileStore(slowPathAgentDir, { externalCli: externalCliDiscoveryForProviderAuth({
cfg: params.cfg,
provider
}) }));
if (await prepareRuntimeAvailableProviderAuth({
provider,
cfg: params.cfg,
workspaceDir,
env: params.env,
allowPluginSyntheticAuth: params.allowPluginSyntheticAuth,
runtimeLookup: params.runtimeAuthLookup ?? params.resolveRuntimeAuthLookup?.(),
modelApi: params.modelApi,
store,
signal: params.signal
})) return true;
if (listProfilesForProvider(store, provider).length > 0) return params.modelApi === void 0 ? true : await hasAvailableAuthForProvider({
provider,
modelApi: params.modelApi,
cfg: params.cfg,
workspaceDir,
agentDir: slowPathAgentDir,
store
});
return false;
}
/** Creates a cached provider-auth evaluator bound to one agent/runtime context. */
function createProviderAuthChecker(params) {
const authCache = /* @__PURE__ */ new Map();
let runtimeAuthLookup;
let modelAuthResolver;
const resolveModelAuthResolver = () => {
if (modelAuthResolver) return modelAuthResolver;
const agentDir = params.agentDir ?? (params.agentId && params.cfg ? resolveAgentDir(params.cfg, params.agentId, params.env) : void 0);
const authStore = params.preparedAuth?.authStore ?? ensureAuthProfileStoreWithoutExternalProfiles(agentDir, { allowKeychainPrompt: false });
runtimeAuthLookup ??= createRuntimeProviderAuthLookup({
cfg: params.cfg,
workspaceDir: params.workspaceDir,
env: params.env,
includePluginSyntheticAuth: params.allowPluginSyntheticAuth !== false
});
modelAuthResolver = createModelAuthAvailabilityResolver({
cfg: params.cfg ?? {},
authStore,
preparedRuntimeAuthStore: params.preparedAuth?.authStore,
preparedRuntimeAuthModes: params.preparedAuth?.authModes,
metadataSnapshot: params.metadataSnapshot,
agentDir,
workspaceDir: params.workspaceDir,
env: params.env,
skipSetupProviderFallback: true,
allowPreparedRuntimeAuth: params.allowPreparedRuntimeAuth === true || params.discoverExternalCliAuth !== false && params.allowPluginSyntheticAuth !== false,
syntheticAuthProviderRefs: runtimeAuthLookup.syntheticAuthProviderRefs,
...params.discoverExternalCliAuth === false ? {} : { externalCliProviderIds: ["openai"] }
});
return modelAuthResolver;
};
const evaluateModelAuth = (provider, ref = {}) => {
const key = normalizeProviderId(provider);
const hasRouteFacts = ref.modelId !== void 0 || ref.api !== void 0 || ref.baseUrl !== void 0 || ref.observedRoutes !== void 0;
const cacheKey = hasRouteFacts ? `${key}\0${hashRuntimeConfigValue(ref)}` : key;
const cached = authCache.get(cacheKey);
if (cached) return cached;
const resolveLegacyProviderAuth = () => hasAuthForModelProvider({
provider: key,
modelApi: typeof ref.api === "string" ? ref.api : void 0,
cfg: params.cfg,
workspaceDir: params.workspaceDir,
agentDir: params.agentDir,
agentId: params.agentId,
env: params.env,
store: params.preparedAuth?.authStore,
allowPluginSyntheticAuth: params.allowPluginSyntheticAuth,
discoverExternalCliAuth: params.discoverExternalCliAuth,
allowPreparedRuntimeAuth: params.allowPreparedRuntimeAuth,
resolveRuntimeAuthLookup: () => runtimeAuthLookup ??= createRuntimeProviderAuthLookup({
cfg: params.cfg,
workspaceDir: params.workspaceDir,
env: params.env,
includePluginSyntheticAuth: params.allowPluginSyntheticAuth !== false
})
});
const evaluation = Promise.resolve().then(async () => {
if (hasRouteFacts) return resolveModelAuthResolver().evaluateModelAuth(key, ref);
return {
availability: await resolveLegacyProviderAuth(),
routeResolution: null
};
});
authCache.set(cacheKey, evaluation);
evaluation.catch(() => {
if (authCache.get(cacheKey) === evaluation) authCache.delete(cacheKey);
});
return evaluation;
};
return Object.assign(async (provider, ref = {}) => (await evaluateModelAuth(provider, ref)).availability === true, { evaluateModelAuth });
}
function serializeProviderAuthStates(states) {
return { agents: [...states.values()].map((state) => ({
agentId: state.agentId,
configFingerprint: state.configFingerprint,
providers: [...state.providers.entries()]
})) };
}
function resolveProviderConfigApi(cfg, provider) {
const providers = cfg?.models?.providers ?? {};
const direct = providers[provider];
if (direct?.api) return direct.api;
const normalized = normalizeProviderId(provider);
return (Object.entries(providers).find(([key]) => normalizeProviderId(key) === normalized)?.[1])?.api;
}
function shouldOmitFalsePreparedAuthForProcessSyntheticProvider(params) {
const syntheticRefs = params.runtimeAuthLookup.syntheticAuthProviderRefs;
if (!syntheticRefs?.length) return false;
const eligibleRefs = new Set(syntheticRefs.map((ref) => normalizeProviderId(ref)));
const providerApi = resolveProviderConfigApi(params.cfg, params.provider);
return [params.provider, providerApi].filter((ref) => typeof ref === "string" && ref.trim().length > 0).some((ref) => eligibleRefs.has(normalizeProviderId(ref)));
}
/** Builds a provider auth snapshot for every configured agent. */
async function buildCurrentProviderAuthStateSnapshot(cfg, options = {}) {
const isWarmStale = () => options.isCancelled?.() === true;
const configFingerprint = resolveProviderAuthConfigFingerprint(cfg) ?? "";
const states = /* @__PURE__ */ new Map();
for (const agentId of listAgentIds(cfg)) {
if (isWarmStale()) return { agents: [] };
const syntheticAuth = options.syntheticAuth?.get(agentId);
const prepareState = async () => {
const agentDir = resolveAgentDir(cfg, agentId);
const preparedOwner = syntheticAuth?.modelCatalog ? {
workspaceDir: syntheticAuth.workspaceDir,
modelCatalog: syntheticAuth.modelCatalog
} : await (await import("./prepared-model-catalog-BH7NC_p8.js")).loadPreparedModelCatalogOwnerSnapshot({
config: cfg,
agentId,
agentDir,
...syntheticAuth ? { workspaceDir: syntheticAuth.workspaceDir } : {},
readOnly: true
});
const workspaceDir = preparedOwner.workspaceDir ?? resolveAgentWorkspaceDir(cfg, agentId);
const catalog = preparedOwner.modelCatalog.entries;
if (isWarmStale()) return;
const providers = new Set(catalog.map((entry) => normalizeProviderId(entry.provider)));
const capturedSyntheticRefs = new Set(syntheticAuth?.facts.map(({ providerRef }) => normalizeProviderId(providerRef)));
const providerList = [...providers];
const runtimeAuthLookup = options.runtimeAuthLookups?.get(agentId) ?? createRuntimeProviderAuthLookup({
cfg,
workspaceDir
});
const externalCli = externalCliDiscoveryForProviders({
cfg,
providers: providerList
});
const store = options.readOnlyAuthStore ? ensureAuthProfileStore(agentDir, {
config: cfg,
externalCli,
readOnly: true,
syncExternalCli: false
}) : ensureAuthProfileStore(agentDir, {
config: cfg,
externalCli
});
const state = /* @__PURE__ */ new Map();
for (const provider of providers) {
if (isWarmStale()) return;
const value = await hasAuthForModelProvider({
provider,
cfg,
workspaceDir,
agentId,
store,
runtimeAuthLookup
});
if (!value && !capturedSyntheticRefs.has(provider) && (options.omitFalseProviderAuth || shouldOmitFalsePreparedAuthForProcessSyntheticProvider({
cfg,
provider,
runtimeAuthLookup
}))) continue;
state.set(provider, value);
}
states.set(agentId, {
agentId,
configFingerprint,
providers: state
});
};
await (syntheticAuth ? withPluginRuntimeGenerationScope({ metadataSnapshot: restorePluginMetadataSnapshot(syntheticAuth.metadataSnapshot) }, prepareState) : prepareState());
if (isWarmStale()) return { agents: [] };
}
return serializeProviderAuthStates(states);
}
function createProviderAuthWarmPresenceStore(store) {
const profiles = {};
for (const [profileId, credential] of Object.entries(store.profiles)) profiles[profileId] = {
type: "api_key",
provider: credential.provider
};
const usageStats = {};
if (store.usageStats) {
for (const [id, stats] of Object.entries(store.usageStats)) if (id.startsWith("inline-api-key:")) usageStats[id] = stats;
}
return {
version: store.version,
profiles,
usageStats
};
}
function collectProviderAuthWarmRuntimeAuthStores(cfg) {
const entries = [];
const seen = /* @__PURE__ */ new Set();
const addStore = (agentDir) => {
if (seen.has(agentDir)) return;
seen.add(agentDir);
const store = getRuntimeAuthProfileStoreSnapshot(agentDir);
if (!store) return;
entries.push({
...agentDir === void 0 ? {} : { agentDir },
store: createProviderAuthWarmPresenceStore(store)
});
};
addStore();
for (const agentId of listAgentIds(cfg)) addStore(resolveAgentDir(cfg, agentId));
return entries;
}
function collectProviderAuthWarmRuntimeAuthLookups(cfg) {
const entries = [];
let omitFalseProviderAuth = false;
for (const agentId of listAgentIds(cfg)) {
const lookup = createRuntimeProviderAuthLookup({
cfg,
workspaceDir: resolveAgentWorkspaceDir(cfg, agentId)
});
if (lookup.syntheticAuthProviderRefsComplete === false) omitFalseProviderAuth = true;
entries.push({
agentId,
lookup
});
}
return {
entries,
omitFalseProviderAuth
};
}
/** Warms process-current provider auth state in a worker thread. */
async function warmCurrentProviderAuthStateOffMainThread(cfg, options = {}) {
const ownGeneration = claimCurrentProviderAuthStateGeneration();
cancelCurrentProviderAuthWarmWorker();
const isWarmStale = () => options.isCancelled?.() === true || !isCurrentProviderAuthStateGeneration(ownGeneration);
if (isWarmStale()) return;
const runtimeAuthStores = collectProviderAuthWarmRuntimeAuthStores(cfg);
const runtimeAuthLookups = collectProviderAuthWarmRuntimeAuthLookups(cfg);
const snapshot = await (options.runWorker ?? runProviderAuthWarmWorker)({
cfg,
...runtimeAuthStores.length ? { runtimeAuthStores } : {},
...runtimeAuthLookups.entries.length ? { runtimeAuthLookups: runtimeAuthLookups.entries } : {},
...runtimeAuthLookups.omitFalseProviderAuth ? { omitFalseProviderAuth: true } : {},
timeoutMs: options.timeoutMs ?? PROVIDER_AUTH_WARM_WORKER_TIMEOUT_MS,
isCancelled: isWarmStale,
workerUrl: options.workerUrl
});
if (isWarmStale()) return;
publishProviderAuthWarmSnapshot(snapshot);
}
//#endregion
export { warmCurrentProviderAuthStateOffMainThread as i, createProviderAuthChecker as n, hasAuthForModelProvider as r, buildCurrentProviderAuthStateSnapshot as t };