UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

434 lines (433 loc) 20 kB
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 };