UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

361 lines (360 loc) • 20.2 kB
import { a as resolveMergedModelProviderConfig } from "./model-provider-config-C5LPYz3z.mjs"; import { a as selectProviderModelAuthSources, c as buildProviderModelAuthSourcePlan, l as classifyProviderModelAuthSource, r as resolveProviderModelRouteAuthRequirement, s as buildProviderModelAuthDirectSource } from "./provider-model-route-auth-Cbwct-ZM.mjs"; import { o as resolveProviderModelAuthPolicy } from "./model-runtime-policy-BbLedg6-.mjs"; import { o as resolveOpenAIModelRoutes, s as selectOpenAIModelRouteAuth } from "./openai-model-routes-C1mdGNT1.mjs"; import { t as resolveDefaultModelForAgent } from "./model-selection-config-BdeHEviO.mjs"; import { h as resolveProfilesUnavailableReason, l as isProfileInCooldown } from "./profile-usage-stats-BLwxBqRR.mjs"; import { u as isPendingOAuthRefreshFence } from "./credential-state-WXO5HScp.mjs"; import { h as resolveStoredCredentialReadOnlyAvailability } from "./loader-runtime-load-BrZtlYge.mjs"; import { i as resolveAuthProfileEligibility, o as resolveAuthProfileOrderWithMetadata, r as prependAuthProfilePin } from "./order-BJ9-s7yV.mjs"; import { n as resolveProviderDirectAuthPlanningEvidence } from "./model-auth-env-RKKDA1-c.mjs"; import { C as shouldPreferExplicitConfigApiKeyAuth, _ as resolveProviderConfigSecretInput, o as hasUsableCustomProviderApiKey, y as resolveProviderEntryApiKeyProfileReference } from "./model-auth-provider-config-C6nCoXKi.mjs"; import { t as FailoverError } from "./error-B1Zb0HrJ.mjs"; import { t as createSelectedAuthProfileUnavailableError } from "./selection-error-D0XBw2ov.mjs"; import { t as resolveModelProviderAuthConfig } from "./model-auth-provider-route-CuvN_iXR.mjs"; import { m as resolveFailoverStatus } from "./failover-error-CYuKSasF.mjs"; import { t as buildAgentRuntimeAuthPlan } from "./auth-DmrninKH.mjs"; //#region src/agents/runtime-plan/prepare-auth.ts /** * Prepares route-aware auth forwarding for auxiliary agent-runtime calls. * Callers supply an already loaded credential snapshot; this module never * resolves secrets or loads a provider runtime. */ function createAuthProfileCooldownError(params, profileId) { const reason = (params.authProfileStore && resolveProfilesUnavailableReason({ store: params.authProfileStore, profileIds: [profileId] })) ?? "unknown"; return new FailoverError(`Auth profile "${profileId}" is temporarily unavailable for ${params.provider}/${params.modelId}.`, { reason, status: resolveFailoverStatus(reason), provider: params.provider, model: params.modelId, profileId }); } /** Prevents a direct fallback from bypassing a prepared profile tier. */ function canRunPreparedAgentRuntimeAuthAttempt(params) { return params.attempt.kind !== "direct" || !params.attempt.requiresPriorProfileAttempt || params.priorProfileAttempted; } /** Rechecks automatic cooldowns immediately before a prepared profile attempt. */ function preparedAgentRuntimeProfileAttemptHasCandidate(params) { if (params.attempt.kind !== "profile") return false; return (params.attempt.plan.forwardedAuthProfileCandidateIds ?? [params.attempt.profileId]).some((profileId) => !isProfileInCooldown(params.store, profileId, void 0, params.modelId)); } /** True when a prepared auth tuple can be reused for this exact compaction target. */ function agentRuntimeAuthPlanMatchesTarget(plan, target) { const route = plan.modelRoute; const provider = route?.provider ?? plan.providerForAuth; const modelId = route?.modelId ?? plan.modelId; return modelId !== void 0 && provider.trim().toLowerCase() === target.provider.trim().toLowerCase() && modelId === target.modelId; } function resolveProfile(params, profileId, options = {}) { const credential = params.authProfileStore?.profiles[profileId]; const configured = params.config?.auth?.profiles?.[profileId]; const availability = credential ? resolveStoredCredentialReadOnlyAvailability({ credential, cfg: params.config ?? {}, env: params.env ?? process.env }) : void 0; const authFlow = credential?.type === "oauth" ? credential.authFlow : void 0; const policy = credential?.type === "oauth" && authFlow ? resolveProviderModelAuthPolicy({ provider: credential.provider, mode: credential.type, authFlow }) : void 0; const pendingOAuthRefresh = credential?.type === "oauth" && isPendingOAuthRefreshFence(credential); return { kind: "profile", profileId, provider: credential?.provider ?? configured?.provider, mode: credential?.type ?? configured?.mode, ...authFlow ? { authFlow, authRequirement: policy?.authRequirement } : {}, readiness: policy?.compatible === false || availability === false && !pendingOAuthRefresh ? "unavailable" : "unknown", cooldown: !options.ignoreCooldown && params.authProfileStore && isProfileInCooldown(params.authProfileStore, profileId, void 0, params.modelId) ? "active" : "clear" }; } /** Applies terminal provider-entry credential policy before route selection. */ function resolvePreparedProviderEntryApiKeyProfileReference(params) { const reference = resolveProviderEntryApiKeyProfileReference({ cfg: params.config, authAliasLookupParams: params, provider: params.provider, store: params.store }); if (reference.kind !== "profile") return reference; if (!resolveAuthProfileEligibility({ cfg: params.config, authAliasLookupParams: params, store: params.store, provider: params.provider, profileId: reference.profileId }).eligible) throw new Error(`Per-entry apiKey profile "${reference.profileId}" has no usable credentials for ${params.provider}.`); if (isProfileInCooldown(params.store, reference.profileId, void 0, params.modelId)) throw createAuthProfileCooldownError({ ...params, authProfileStore: params.store }, reference.profileId); return reference; } /** Selects concrete provider routes and ordered credentials as one immutable preparation. */ function prepareAgentRuntimeAuth(input) { const params = { ...input, config: resolveModelProviderAuthConfig(input) }; const requestedProfileId = params.sessionAuthProfileId?.trim() || void 0; const userPinnedProfileId = params.sessionAuthProfileSource === "user" || params.sessionAuthProfileSource === "user-link" ? requestedProfileId : void 0; const harnessOwnsOpenAIAuth = params.harnessId?.trim().toLowerCase() === "codex" || params.harnessRuntime?.trim().toLowerCase() === "codex"; const harnessAuthOwnerId = params.harnessId?.trim() || params.harnessRuntime?.trim(); const runtimeAuthOwner = harnessOwnsOpenAIAuth && params.harnessAuthBootstrap === "harness" && harnessAuthOwnerId ? { id: harnessAuthOwnerId } : void 0; const harnessAllowsAuthProfileForwarding = params.allowHarnessAuthProfileForwarding !== false; if (userPinnedProfileId && !harnessAllowsAuthProfileForwarding) throw new Error(`Auth profile "${userPinnedProfileId}" cannot be forwarded to the selected agent harness. Configure that harness's native account instead.`); const store = params.authProfileStore; const authProfileSelectionProvider = harnessOwnsOpenAIAuth ? "openai" : params.provider; if (userPinnedProfileId) { if (!(store ? resolveAuthProfileEligibility({ cfg: params.config, authAliasLookupParams: params, store, provider: authProfileSelectionProvider, profileId: userPinnedProfileId, includePendingOAuthRefresh: true }) : { eligible: false }).eligible) { if (!store?.profiles[userPinnedProfileId] && params.config?.auth?.profiles?.[userPinnedProfileId]?.mode !== "aws-sdk") throw createSelectedAuthProfileUnavailableError({ profileId: userPinnedProfileId, provider: authProfileSelectionProvider, modelId: params.modelId }); throw new Error(`Auth profile "${userPinnedProfileId}" is not configured for ${authProfileSelectionProvider}.`); } } const configuredProvider = resolveMergedModelProviderConfig(params.config, params.provider); const configuredAuthMode = userPinnedProfileId || !harnessAllowsAuthProfileForwarding ? void 0 : configuredProvider?.auth; const configuredAwsSdkAuth = configuredAuthMode === "aws-sdk"; const providerApiKeySecretRef = harnessAllowsAuthProfileForwarding ? resolveProviderConfigSecretInput(params.config, params.provider).ref : void 0; const providerHasApiKeySecretRef = Boolean(providerApiKeySecretRef); const providerBinding = harnessAllowsAuthProfileForwarding && !userPinnedProfileId && store && !configuredAwsSdkAuth ? resolvePreparedProviderEntryApiKeyProfileReference({ ...params, store }) : { kind: "none" }; if (providerBinding.kind === "profile-incompatible") throw new Error(`Per-entry apiKey "${providerBinding.profileId}" is not a compatible bearer profile for ${params.provider}.`); const boundProfileId = providerBinding.kind === "profile" ? providerBinding.profileId : void 0; const providerHasUsableMarker = providerBinding.kind === "marker" && hasUsableCustomProviderApiKey(params.config, params.provider, params.env); const providerHasDirectMaterial = !configuredAwsSdkAuth && (providerBinding.kind === "literal" || providerHasUsableMarker || providerHasApiKeySecretRef); const explicitConfigApiKeyAuth = shouldPreferExplicitConfigApiKeyAuth(params.config, params.provider); const providerBindingSuppressesProfiles = providerBinding.kind === "literal" && explicitConfigApiKeyAuth || providerHasUsableMarker || providerHasApiKeySecretRef; const providerBindingNeedsNonProfileFallback = providerHasDirectMaterial && !providerBindingSuppressesProfiles; const selectedConfiguredAuthMode = configuredAuthMode ?? (providerHasDirectMaterial ? "api-key" : void 0); const selectedProfileId = boundProfileId ?? (params.allowAuthProfileFallback === false ? userPinnedProfileId : void 0); const resolvedAutomaticOrder = !harnessAllowsAuthProfileForwarding || selectedProfileId || providerBindingSuppressesProfiles || configuredAwsSdkAuth || !store ? { profileIds: selectedProfileId ? [selectedProfileId] : [], hasExplicitOrder: false } : resolveAuthProfileOrderWithMetadata({ cfg: params.config, authAliasLookupParams: params, store, provider: authProfileSelectionProvider, preferredProfile: requestedProfileId, forModel: params.modelId, readinessMode: "read-only", includePendingOAuthRefresh: true }); const automaticOrderResolution = prependAuthProfilePin(resolvedAutomaticOrder, userPinnedProfileId); const providerPreferredProfileId = harnessAllowsAuthProfileForwarding && !selectedProfileId && !userPinnedProfileId && !providerBindingSuppressesProfiles && !configuredAwsSdkAuth && store ? params.resolveProviderPreferredProfileId?.({ config: params.config, agentDir: params.agentDir, workspaceDir: params.workspaceDir, provider: params.provider, modelId: params.modelId, preferredProfileId: requestedProfileId, lockedProfileId: void 0, profileOrder: automaticOrderResolution.profileIds, authStore: store }) : void 0; const resolvedOrderedProfileIds = providerPreferredProfileId && automaticOrderResolution.profileIds.includes(providerPreferredProfileId) ? [providerPreferredProfileId, ...automaticOrderResolution.profileIds.filter((profileId) => profileId !== providerPreferredProfileId)] : automaticOrderResolution.profileIds; const directSource = (mode, evidence = providerBinding.kind === "marker" && providerHasUsableMarker ? providerBinding.evidence : providerApiKeySecretRef?.source === "env" ? "environment" : "provider-config", availability, authorization = "declared") => buildProviderModelAuthDirectSource({ mode, evidence, availability, authorization }); const directPlanningCandidate = harnessAllowsAuthProfileForwarding ? resolveProviderDirectAuthPlanningEvidence(authProfileSelectionProvider, params.env ?? process.env, { config: params.config, workspaceDir: params.workspaceDir, metadataSnapshot: params.metadataSnapshot }) : null; const directPlanningEvidence = directPlanningCandidate?.kind === "setup-provider" && (params.harnessAuthBootstrap === "harness" || authProfileSelectionProvider.trim().toLowerCase() === "openai") ? null : directPlanningCandidate; const directPlanningMode = directPlanningEvidence ? configuredAuthMode ?? directPlanningEvidence.mode : void 0; const fallbackIsAmbientCredential = directPlanningEvidence?.kind === "environment" && !providerHasDirectMaterial; const fallbackDirectSource = directPlanningMode ? directSource(directPlanningMode, directPlanningEvidence?.kind === "environment" ? "environment" : "runtime", directPlanningEvidence?.kind === "environment" ? true : void 0, fallbackIsAmbientCredential ? "ambient" : "declared") : providerBindingNeedsNonProfileFallback ? directSource(selectedConfiguredAuthMode) : void 0; const automaticRouteAuthMode = fallbackDirectSource && !providerBindingSuppressesProfiles && !configuredAuthMode ? void 0 : selectedConfiguredAuthMode; const ownership = selectedProfileId ? { reason: selectedProfileId === userPinnedProfileId ? "runtime-binding" : "provider-binding", source: resolveProfile(params, selectedProfileId, { ignoreCooldown: true }) } : configuredAwsSdkAuth ? { reason: "configured-auth", source: directSource("aws-sdk", "aws-sdk") } : providerBindingSuppressesProfiles ? { reason: "configured-auth", source: directSource(selectedConfiguredAuthMode) } : void 0; const sourcePlan = buildProviderModelAuthSourcePlan({ ...ownership ? { ownership } : {}, profiles: resolvedOrderedProfileIds.map((profileId) => resolveProfile(params, profileId)), ...userPinnedProfileId || providerPreferredProfileId ? { preferredProfileId: userPinnedProfileId ?? providerPreferredProfileId } : {}, explicitOrder: automaticOrderResolution.hasExplicitOrder, preserveProfilePriority: Boolean(userPinnedProfileId), ...fallbackDirectSource ? { fallback: fallbackDirectSource } : {}, allowCooldown: params.allowTransientCooldownProbe }); const pinnedSource = sourcePlan.kind === "required" ? sourcePlan.source : sourcePlan.orderedProfiles.find((source) => source.profileId === userPinnedProfileId); const resolution = resolveOpenAIModelRoutes({ provider: params.provider, modelId: params.modelId, api: params.modelApi, baseUrl: params.modelBaseUrl, config: params.config, agentId: params.agentId, primaryModel: !params.routeIntent && params.config ? resolveDefaultModelForAgent({ cfg: params.config, agentId: params.agentId, allowManifestNormalization: false, allowPluginNormalization: false }) : void 0, resolveProfileAuthMode: (profileId) => params.authProfileStore?.profiles[profileId]?.type, resolveProfileAuthFlow: (profileId) => { const credential = params.authProfileStore?.profiles[profileId]; return credential?.type === "oauth" ? credential.authFlow : void 0; }, routeIntent: params.routeIntent, pinnedAuthRequirement: resolveProviderModelRouteAuthRequirement(sourcePlan.kind === "required" ? sourcePlan.source.mode : pinnedSource?.mode ?? configuredAuthMode, pinnedSource?.kind === "profile" ? pinnedSource.authRequirement : void 0), env: params.env, requestTransportOverrides: params.requestTransportOverrides }); const authPlanParams = { provider: params.provider, modelId: params.modelId, config: params.config, env: params.env, workspaceDir: params.workspaceDir, metadataSnapshot: params.metadataSnapshot, harnessId: params.harnessId, harnessRuntime: params.harnessRuntime, allowHarnessAuthProfileForwarding: harnessAllowsAuthProfileForwarding }; const buildAttemptPlan = (source, candidateIds, modelRoute) => { const profile = source?.kind === "profile" ? source : void 0; return buildAgentRuntimeAuthPlan({ ...authPlanParams, authProfileProvider: profile?.provider, authProfileFlow: profile?.authFlow, authProfileMode: profile?.mode ?? (source?.kind === "direct" ? source.mode : selectedConfiguredAuthMode), sessionAuthProfileId: profile?.profileId, sessionAuthProfileSource: profile ? profile.profileId === userPinnedProfileId ? "user" : "auto" : void 0, sessionAuthProfileCandidateIds: candidateIds, credentialSource: source ? classifyProviderModelAuthSource(source) : { kind: "none" }, modelRoute }); }; if (!resolution || resolution.kind === "indeterminate") { const sourceDecision = selectProviderModelAuthSources({ provider: authProfileSelectionProvider, plan: sourcePlan }); if (sourceDecision.kind === "rejected") { if (sourceDecision.reason === "all-cooldown" && sourceDecision.source) throw createAuthProfileCooldownError(params, sourceDecision.source.profileId); throw new Error(sourceDecision.message); } const buildGenericPlan = (attempt, candidateIndex) => { const candidateIds = sourceDecision.attempts.slice(candidateIndex).flatMap((candidate) => candidate.kind === "profile" ? [candidate.source.profileId] : []); return buildAttemptPlan(attempt?.source, candidateIds.length > 0 ? candidateIds : void 0); }; const attempts = sourceDecision.attempts.map((attempt, index) => { const plan = buildGenericPlan(attempt, index); return attempt.kind === "profile" ? { kind: "profile", plan, profileId: attempt.source.profileId } : { kind: "direct", plan, allowAuthProfileFallback: attempt.allowAuthProfileFallback, requiresPriorProfileAttempt: sourceDecision.attempts.slice(0, index).some((candidate) => candidate.kind === "profile") }; }); const plan = attempts[0]?.plan ?? buildGenericPlan(void 0, 0); if (selectedProfileId && harnessOwnsOpenAIAuth && plan.forwardedAuthProfileId !== selectedProfileId) throw new Error(`Auth profile "${selectedProfileId}" cannot be forwarded to the codex runtime.`); return { plan, attempts: attempts.length > 0 ? attempts : [{ kind: "implicit", plan }] }; } if (resolution.kind === "incompatible") throw new Error(resolution.message); const toPreparedRoute = (route) => ({ provider: params.provider, modelId: params.modelId, api: route.api, baseUrl: route.baseUrl, authRequirement: route.authRequirement, requestTransportOverrides: route.requestTransportOverrides, runtimePolicy: route.runtimePolicy }); const routeAuthDecision = selectOpenAIModelRouteAuth({ resolution, sourcePlan, configuredAuthMode: automaticRouteAuthMode, ...runtimeAuthOwner ? { runtimeAuthOwner } : {}, ...runtimeAuthOwner && configuredProvider === void 0 ? { allowNativeAuthOnSingleRoute: true } : {} }); if (routeAuthDecision.kind === "deferred") { const plan = buildAgentRuntimeAuthPlan({ ...authPlanParams, deferredRouteSupport: routeAuthDecision.routeSupport }); return { plan, attempts: [{ kind: "implicit", plan }] }; } if (routeAuthDecision.kind !== "selected") { if (routeAuthDecision.kind === "rejected" && routeAuthDecision.reason === "all-cooldown" && routeAuthDecision.source) throw createAuthProfileCooldownError(params, routeAuthDecision.source.profileId); throw new Error(routeAuthDecision.message); } const buildRoutedPlan = (attempt) => { const route = attempt?.route ?? routeAuthDecision.selection.route; return buildAttemptPlan(attempt?.source, attempt?.kind === "profile" ? [...attempt.sameRouteProfileIds] : void 0, toPreparedRoute(route)); }; const attempts = routeAuthDecision.attempts.map((attempt, index) => { const plan = buildRoutedPlan(attempt); return attempt.kind === "profile" ? { kind: "profile", plan, profileId: attempt.source.profileId } : { kind: "direct", plan, allowAuthProfileFallback: attempt.allowAuthProfileFallback, requiresPriorProfileAttempt: routeAuthDecision.attempts.slice(0, index).some((candidate) => candidate.kind === "profile") }; }); const plan = attempts[0]?.plan ?? buildRoutedPlan(void 0); for (const attempt of attempts) if (attempt.profileId && harnessOwnsOpenAIAuth && attempt.plan.forwardedAuthProfileId !== attempt.profileId) throw new Error(`Auth profile "${attempt.profileId}" cannot be forwarded to the codex runtime.`); return { plan, attempts: attempts.length > 0 ? attempts : [{ kind: "implicit", plan }] }; } //#endregion export { preparedAgentRuntimeProfileAttemptHasCandidate as i, canRunPreparedAgentRuntimeAuthAttempt as n, prepareAgentRuntimeAuth as r, agentRuntimeAuthPlanMatchesTarget as t };