openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
700 lines (699 loc) • 27.9 kB
JavaScript
import { o as normalizeLowercaseStringOrEmpty } from "./string-coerce-CIXf7egm.js";
import { h as normalizeUniqueStringEntries } from "./string-normalization-DsCfAx8q.js";
import { c as resolveUserPath } from "./home-dir-BPhrG-aM.js";
import "./utils-P__uGsPB.js";
import { t as formatCliCommand } from "./command-format-C7YfyMTd.js";
import { v as resolveDefaultAgentDir } from "./agent-scope-config-DcbEhP0R.js";
import { r as normalizeProviderId } from "./provider-id-DMd-TDFp.js";
import { t as formatErrorMessage } from "./errors-Db3Ymjlb.js";
import { t as createSubsystemLogger } from "./subsystem-Dy2tqXOS.js";
import { o as getRuntimeConfigSnapshot } from "./runtime-snapshot-BaQikjTR.js";
import "./config-Cs0XXL3x.js";
import { s as mintSecretSentinel } from "./sentinel-ZgmfESkJ.js";
import { n as resolveAuthStorePathForDisplay } from "./paths-DLuhw03H.js";
import { n as resolveApiKeyForProfile } from "./oauth-BNreHOU-.js";
import { n as SecretSurfaceUnavailableError } from "./runtime-degraded-state-D5EZZ925.js";
import { t as OAuthRefreshFailureError } from "./oauth-refresh-failure-DP-bO7C0.js";
import { f as resolveOwningPluginIdsForProviderRef } from "./providers-DCe4UB6a.js";
import { i as assertAuthProfileMigrationReady } from "./legacy-source-diagnostic-BNaogmw1.js";
import { r as ensureAuthProfileStore } from "./store-F1B2duCT.js";
import { n as listProfilesForProvider } from "./profile-list-DyfWX-d2.js";
import { a as resolveAuthProfileOrder } from "./order-CC2RBzI5.js";
import { c as isNonSecretApiKeyMarker, g as resolveProviderEnvAuthLookupMaps, n as CUSTOM_LOCAL_AUTH_MARKER } from "./model-auth-markers-jBKQn38x.js";
import { C as resolveProviderDeprecatedAuthProfileIds, I as shouldDeferProviderSyntheticProfileAuthWithPlugin, O as resolveProviderSyntheticAuthWithPlugin, i as buildProviderMissingAuthMessageWithPlugin, y as prepareProviderSyntheticAuthWithPlugin } from "./provider-runtime-BRJDPNgk.js";
import { r as resolveRuntimeSyntheticAuthProviderRefState } from "./synthetic-auth.runtime.js";
import { t as resolveEnvApiKey } from "./model-auth-env-Dq9W4xg9.js";
import { n as externalCliDiscoveryForProviderAuth } from "./external-cli-discovery-CbeZXk1q.js";
import { C as sentinelizeConfigSecretRefEnvApiKey, E as shouldUseImplicitAwsSdkAuth, S as resolveUsableCustomProviderApiKey, T as shouldPreferExplicitConfigApiKeyAuth, _ as resolveProviderConfig, a as hasSyntheticLocalProviderAuthConfig, b as resolveProviderEntryApiKeyProfileReference, c as isManagedSecretRefApiKeyMarker, d as resolveAwsSdkAuthInfo, f as resolveConfigAwareEnvApiKey, g as resolveProviderAuthOverride, h as resolveInlineProviderApiKeyCooldownUntil, i as hasSecretRefProviderApiKey, l as profileTypeToAuthMode, m as resolveDirectProviderCredentialMode, p as resolveConfiguredAwsSdkProfileAuth, s as isConfigBackedInlineProviderApiKey, t as assertInlineProviderApiKeyUsable, w as sentinelizeSecretRefProfileApiKey, y as resolveProviderEntryApiKeyBinding } from "./model-auth-provider-config-C_kr_q2g.js";
import { n as resolveManagedSecretRefRuntimeProviderAuth, t as assertRuntimeProviderSecretOwnerAvailable } from "./model-auth-runtime-config-DpvTPuUl.js";
import { n as ProviderAuthError } from "./model-auth-runtime-shared-C48YoQY0.js";
import "./auth-profiles-BdUEhE7u.js";
//#region src/agents/model-auth-openai.ts
const OPENAI_PROVIDER_ID = "openai";
const OPENAI_CODEX_RESPONSES_API = "openai-chatgpt-responses";
function directOpenAIPlatformModelRequiresApiKey(params) {
return normalizeProviderId(params.provider) === OPENAI_PROVIDER_ID && params.modelApi !== void 0 && normalizeLowercaseStringOrEmpty(params.modelApi) !== OPENAI_CODEX_RESPONSES_API;
}
function openAICodexTransportRequiresOAuth(params) {
return normalizeProviderId(params.provider) === OPENAI_PROVIDER_ID && normalizeLowercaseStringOrEmpty(params.modelApi ?? "") === OPENAI_CODEX_RESPONSES_API;
}
function isAuthModeAllowedForModel(params) {
if (openAICodexTransportRequiresOAuth(params)) return params.mode === "oauth" || params.mode === "token";
return !directOpenAIPlatformModelRequiresApiKey(params) || params.mode === "api-key";
}
function assertAuthModeAllowedForModel(params) {
if (isAuthModeAllowedForModel(params)) return;
if (openAICodexTransportRequiresOAuth(params)) throw new Error(`Auth profile "${params.profileId}" uses ${params.mode} auth, but ${params.provider}/${params.modelApi} requires a ChatGPT subscription (OAuth or token) profile.`);
throw new Error(`Auth profile "${params.profileId}" uses ${params.mode} auth, but ${params.provider}/${params.modelApi} requires an OpenAI API key profile.`);
}
//#endregion
//#region src/agents/model-auth-runtime.ts
/**
* Snapshot-aware and synthetic provider-auth availability.
*/
/** Builds stable env/synthetic auth lookup data for repeated provider checks. */
function createRuntimeProviderAuthLookup(params) {
const env = params.env ?? process.env;
const lookupParams = {
config: params.cfg,
workspaceDir: params.workspaceDir,
env
};
const syntheticAuthProviderRefs = params.includePluginSyntheticAuth === false ? void 0 : resolveRuntimeSyntheticAuthProviderRefState(lookupParams);
const authLookupMaps = resolveProviderEnvAuthLookupMaps(lookupParams);
return {
envApiKey: {
aliasMap: authLookupMaps.aliasMap,
candidateMap: authLookupMaps.envCandidateMap,
authEvidenceMap: authLookupMaps.authEvidenceMap,
skipSetupProviderFallback: true
},
setupProviderFallbackRefs: authLookupMaps.setupProviderFallbackRefs,
syntheticAuthProviderRefs: syntheticAuthProviderRefs?.complete ? syntheticAuthProviderRefs.refs : void 0,
syntheticAuthProviderRefsComplete: syntheticAuthProviderRefs?.complete
};
}
function runtimeLookupAllowsSetupProviderFallback(params) {
const refs = params.runtimeLookup?.setupProviderFallbackRefs;
if (!refs?.length) return false;
const normalizedProvider = normalizeProviderId(params.provider);
const aliasTarget = params.runtimeLookup?.envApiKey.aliasMap?.[normalizedProvider];
return refs.includes(normalizedProvider) || (aliasTarget ? refs.includes(aliasTarget) : false);
}
function resolveRuntimeEnvApiKeyLookupOptions(params) {
const envApiKey = params.runtimeLookup?.envApiKey;
if (!envApiKey) return;
const skipSetupProviderFallback = envApiKey.skipSetupProviderFallback === true ? !runtimeLookupAllowsSetupProviderFallback(params) : envApiKey.skipSetupProviderFallback;
return {
...envApiKey,
...skipSetupProviderFallback !== void 0 ? { skipSetupProviderFallback } : {}
};
}
function listProviderSyntheticAuthRefs(params) {
const refs = [params.provider];
const providerConfig = resolveProviderConfig(params.cfg, params.provider);
if (params.modelApi) refs.push(params.modelApi);
if (providerConfig?.api) refs.push(providerConfig.api);
return normalizeUniqueStringEntries(refs.map((ref) => normalizeProviderId(ref)));
}
function shouldResolvePluginSyntheticAuth(params) {
const syntheticAuthProviderRefs = params.runtimeLookup?.syntheticAuthProviderRefs;
if (!syntheticAuthProviderRefs) return true;
const eligibleRefs = new Set(normalizeUniqueStringEntries(syntheticAuthProviderRefs.map((ref) => normalizeProviderId(ref))));
if (eligibleRefs.size === 0) return false;
return listProviderSyntheticAuthRefs(params).some((ref) => eligibleRefs.has(ref));
}
function resolveRuntimeAvailableProviderAuth(params, resolveSyntheticAuth) {
const provider = normalizeProviderId(params.provider);
if (resolveProviderAuthOverride(params.cfg, provider) === "aws-sdk") return true;
const inlineProviderApiKeyUsable = params.store ? (() => {
const unusableUntil = resolveInlineProviderApiKeyCooldownUntil(params.store, provider);
return unusableUntil === null || unusableUntil <= Date.now();
})() : true;
const envAuth = resolveEnvApiKey(provider, params.env, {
config: params.cfg,
workspaceDir: params.workspaceDir,
...resolveRuntimeEnvApiKeyLookupOptions({
provider,
runtimeLookup: params.runtimeLookup
})
});
if (envAuth && isAuthModeAllowedForModel({
provider,
modelApi: params.modelApi,
mode: envAuth.source.includes("OAUTH_TOKEN") ? "oauth" : "api-key"
}) && (!isConfigBackedInlineProviderApiKey({
cfg: params.cfg,
provider,
source: envAuth.source,
store: params.store
}) || inlineProviderApiKeyUsable)) return true;
if (resolveUsableCustomProviderApiKey({
cfg: params.cfg,
provider,
env: params.env
}) && inlineProviderApiKeyUsable) return true;
const managedRuntimeAuth = resolveManagedSecretRefRuntimeProviderAuth({
cfg: params.cfg,
provider
});
if (managedRuntimeAuth && (!isConfigBackedInlineProviderApiKey({
cfg: params.cfg,
provider,
source: managedRuntimeAuth.source,
store: params.store
}) || inlineProviderApiKeyUsable)) return true;
if (hasSyntheticLocalProviderAuthConfig({
cfg: params.cfg,
provider
})) return true;
if (params.allowPluginSyntheticAuth !== false && shouldResolvePluginSyntheticAuth({
cfg: params.cfg,
provider,
runtimeLookup: params.runtimeLookup
})) return resolveSyntheticAuth(provider);
return false;
}
/** Fast auth-availability check for runtime provider/model selection. */
function hasRuntimeAvailableProviderAuth(params) {
return resolveRuntimeAvailableProviderAuth(params, (provider) => Boolean(resolveSyntheticLocalProviderAuth({
cfg: params.cfg,
provider,
workspaceDir: params.workspaceDir,
env: params.env
})));
}
/** Prepare external auth only after immediate credentials and discovery scope permit it. */
async function prepareRuntimeAvailableProviderAuth(params) {
params.signal?.throwIfAborted();
return resolveRuntimeAvailableProviderAuth(params, async (provider) => Boolean(await prepareSyntheticLocalProviderAuth({
...params,
cfg: params.cfg,
provider
})));
}
function syntheticAuthLookup(params, config) {
return {
provider: params.provider,
config,
workspaceDir: params.workspaceDir,
env: params.env,
modelApi: params.modelApi,
context: {
config,
provider: params.provider,
providerConfig: resolveProviderConfig(config, params.provider)
}
};
}
function resolveProviderSyntheticRuntimeAuth(params, resolveFromConfig = (config) => resolveProviderSyntheticAuthWithPlugin(syntheticAuthLookup(params, config))) {
const runtimeAuth = resolveManagedSecretRefRuntimeProviderAuth(params);
if (runtimeAuth) return { auth: runtimeAuth };
if (hasSecretRefProviderApiKey(params.cfg, params.provider)) return { blockedOnManagedSecretRef: true };
const directAuth = resolveFromConfig(params.cfg);
if (!directAuth) return {};
if (!isManagedSecretRefApiKeyMarker(directAuth.apiKey)) return { auth: directAuth };
const runtimeConfig = getRuntimeConfigSnapshot();
if (!runtimeConfig || runtimeConfig === params.cfg) return { blockedOnManagedSecretRef: true };
const runtimePluginAuth = resolveFromConfig(runtimeConfig);
const runtimeApiKey = runtimePluginAuth?.apiKey;
if (!runtimePluginAuth || !runtimeApiKey || isNonSecretApiKeyMarker(runtimeApiKey)) return { blockedOnManagedSecretRef: true };
return { auth: {
...runtimePluginAuth,
apiKey: params.secretSentinels ? mintSecretSentinel(runtimeApiKey, { label: `model-auth:${params.provider}` }) : runtimeApiKey
} };
}
/** Prepare native readiness without widening explicit managed-credential authority. */
async function prepareSyntheticLocalProviderAuth(params) {
if (params.allowPluginSyntheticAuth === false || hasSecretRefProviderApiKey(params.cfg, params.provider)) return resolveSyntheticLocalProviderAuth(params);
const prepare = (config) => prepareProviderSyntheticAuthWithPlugin({
...syntheticAuthLookup(params, config),
signal: params.signal
});
const direct = await prepare(params.cfg);
const runtimeConfig = getRuntimeConfigSnapshot();
const runtimeAuth = direct && isManagedSecretRefApiKeyMarker(direct.apiKey) && runtimeConfig && runtimeConfig !== params.cfg ? await prepare(runtimeConfig) : void 0;
return resolveSyntheticLocalProviderAuth(params, (config) => config === params.cfg ? direct : config === runtimeConfig ? runtimeAuth : void 0);
}
function resolveSyntheticLocalProviderAuth(params, resolveFromConfig) {
const syntheticProviderAuth = params.allowPluginSyntheticAuth === false ? {} : resolveProviderSyntheticRuntimeAuth(params, resolveFromConfig);
if (syntheticProviderAuth.auth) return syntheticProviderAuth.auth;
if (syntheticProviderAuth.blockedOnManagedSecretRef) return null;
if (hasSyntheticLocalProviderAuthConfig(params)) return {
apiKey: CUSTOM_LOCAL_AUTH_MARKER,
source: `models.providers.${params.provider} (synthetic local key)`,
mode: "api-key"
};
return null;
}
//#endregion
//#region src/agents/model-auth-provider.ts
/**
* Ordered credential resolution for one provider request.
*/
const log = createSubsystemLogger("model-auth");
function assertAuthProfileNotRetired(params) {
if (!params.deprecatedProfileIds.has(params.profileId)) return;
throw new Error(`Auth profile "${params.profileId}" is retired. Run ${formatCliCommand("openclaw doctor --fix")}.`);
}
function shouldDeferSyntheticProfileAuth(params) {
const providerConfig = resolveProviderConfig(params.cfg, params.provider);
return shouldDeferProviderSyntheticProfileAuthWithPlugin({
provider: params.provider,
config: params.cfg,
modelApi: params.modelApi,
context: {
config: params.cfg,
provider: params.provider,
providerConfig,
resolvedApiKey: params.resolvedApiKey
}
}) === true;
}
function resolveScopedAuthProfileStore(params) {
return ensureAuthProfileStore(params.agentDir, {
profileId: params.profileId,
externalCli: externalCliDiscoveryForProviderAuth(params)
});
}
function assertProviderAuthReady(params) {
assertAuthProfileMigrationReady(params.agentDir);
assertRuntimeProviderSecretOwnerAvailable({
cfg: params.cfg,
provider: params.provider
});
}
/** Resolves a stored provider-entry binding without general credential discovery. */
async function resolveProviderEntryApiKeyAuth(params) {
const { provider, cfg } = params;
assertProviderAuthReady(params);
const reference = resolveProviderEntryApiKeyProfileReference(params);
if (!("profileId" in reference)) return;
assertAuthProfileNotRetired({
profileId: reference.profileId,
deprecatedProfileIds: new Set(resolveProviderDeprecatedAuthProfileIds({
provider,
config: cfg
}))
});
const binding = await resolveProviderEntryApiKeyBinding(params);
if (binding.kind === "profile-resolved") {
assertAuthModeAllowedForModel({
provider,
modelApi: params.modelApi,
profileId: binding.auth.profileId ?? provider,
mode: binding.auth.mode
});
return binding.auth;
}
if (binding.kind === "profile-incompatible") {
const reason = binding.reason === "credential-class" ? "which is not a bearer-style auth class" : "which is not compatible with this provider entry's auth binding";
const action = binding.reason === "credential-class" ? "Use an api-key or token profile, or set apiKey to a literal bearer token." : "Use a compatible provider auth alias, configure the referenced provider entry with the same baseUrl, or set apiKey to a literal bearer token.";
throw new Error(`Per-entry apiKey "${binding.profileId}" for provider "${provider}" references a "${binding.credentialType}" credential for provider "${binding.credentialProvider}", ${reason}. ${action}`);
}
if (binding.kind === "profile-unresolved") {
const cause = binding.error ? formatErrorMessage(binding.error) : "credential resolution returned no key";
throw new Error(`Per-entry apiKey "${binding.profileId}" for provider "${provider}" matched a stored profile but failed to resolve: ${cause}. Fix the referenced profile or set apiKey to a literal bearer token.`);
}
}
/** Resolves the credential that should be used for one provider request. */
async function resolveApiKeyForProviderCore(params) {
const { provider, cfg, profileId, preferredProfile } = params;
let deprecatedProfileIds;
const getDeprecatedProfileIds = () => deprecatedProfileIds ??= new Set(resolveProviderDeprecatedAuthProfileIds({
provider,
config: cfg
}));
const agentDir = params.agentDir?.trim() || (cfg ? resolveDefaultAgentDir(cfg) : void 0);
assertProviderAuthReady({
cfg,
provider,
agentDir
});
let scopedStore = params.store;
const getScopedStore = (requestedProfileId) => scopedStore ??= resolveScopedAuthProfileStore({
agentDir,
cfg,
provider,
profileId: requestedProfileId,
preferredProfile
});
if (profileId) {
const awsSdkProfileAuth = resolveConfiguredAwsSdkProfileAuth({
cfg,
provider,
profileId
});
if (awsSdkProfileAuth) return awsSdkProfileAuth;
const store = getScopedStore(profileId);
assertAuthProfileNotRetired({
profileId,
deprecatedProfileIds: getDeprecatedProfileIds()
});
const configuredProfileType = store.profiles[profileId]?.type;
if (configuredProfileType) assertAuthModeAllowedForModel({
provider,
modelApi: params.modelApi,
profileId,
mode: profileTypeToAuthMode(configuredProfileType)
});
const resolved = await resolveApiKeyForProfile({
cfg,
store,
profileId,
agentDir,
forceRefresh: params.forceRefresh
});
if (!resolved) throw new Error(`No credentials found for profile "${profileId}".`);
const resolvedProfileId = resolved.profileId ?? profileId;
const mode = resolved.profileType ?? store.profiles[resolvedProfileId]?.type;
const result = {
apiKey: sentinelizeSecretRefProfileApiKey({
apiKey: resolved.apiKey,
enabled: params.secretSentinels,
profileId: resolvedProfileId,
provider,
store
}),
profileId: resolvedProfileId,
source: `profile:${resolvedProfileId}`,
mode: mode ? profileTypeToAuthMode(mode) : "api-key"
};
assertAuthModeAllowedForModel({
provider,
modelApi: params.modelApi,
profileId: resolvedProfileId,
mode: result.mode
});
if (!params.lockedProfile && shouldDeferSyntheticProfileAuth({
cfg,
provider,
resolvedApiKey: resolved.apiKey,
modelApi: params.modelApi
})) return resolveApiKeyForProviderCore({
...params,
store,
profileId: void 0,
lockedProfile: true
}).catch(() => result);
return result;
}
if (params.allowAuthProfileFallback !== false && (cfg?.auth?.profiles || cfg?.auth?.order)) {
const store = getScopedStore();
const configuredProfileOrder = resolveAuthProfileOrder({
cfg,
store,
provider,
preferredProfile,
forModel: params.modelId
});
for (const candidate of configuredProfileOrder) {
const awsSdkProfileAuth = resolveConfiguredAwsSdkProfileAuth({
cfg,
provider,
profileId: candidate
});
if (awsSdkProfileAuth) return awsSdkProfileAuth;
}
}
if (resolveProviderAuthOverride(cfg, provider) === "aws-sdk") return resolveAwsSdkAuthInfo();
if (shouldUseImplicitAwsSdkAuth({
cfg,
provider,
modelApi: params.modelApi
})) return resolveAwsSdkAuthInfo();
if (params.credentialPrecedence === "env-first") {
const envResolved = resolveConfigAwareEnvApiKey(cfg, provider, params.workspaceDir, params.skipSetupProviderFallback);
if (envResolved) {
const resolvedMode = resolveDirectProviderCredentialMode({
cfg,
provider,
inferredMode: envResolved.source.includes("OAUTH_TOKEN") ? "oauth" : "api-key"
});
if (resolvedMode === "api-key") {
const inlineStore = getScopedStore();
if (isConfigBackedInlineProviderApiKey({
cfg,
provider,
source: envResolved.source,
store: inlineStore
})) assertInlineProviderApiKeyUsable({
store: inlineStore,
provider
});
}
if (!isAuthModeAllowedForModel({
provider,
modelApi: params.modelApi,
mode: resolvedMode
})) return resolveApiKeyForProviderCore({
...params,
credentialPrecedence: "profile-first"
});
return {
apiKey: sentinelizeConfigSecretRefEnvApiKey({
apiKey: envResolved.apiKey,
source: envResolved.source,
cfg,
provider,
enabled: params.secretSentinels
}),
source: envResolved.source,
mode: resolvedMode
};
}
}
const providerEntryAuth = await resolveProviderEntryApiKeyAuth({
cfg,
provider,
store: getScopedStore(),
agentDir,
modelApi: params.modelApi,
secretSentinels: params.secretSentinels
});
if (providerEntryAuth) return providerEntryAuth;
if (shouldPreferExplicitConfigApiKeyAuth(cfg, provider)) {
const runtimeCustomKey = resolveManagedSecretRefRuntimeProviderAuth({
cfg,
provider,
secretSentinels: params.secretSentinels
});
if (runtimeCustomKey) {
assertInlineProviderApiKeyUsable({
store: getScopedStore(),
provider
});
return runtimeCustomKey;
}
const customKey = resolveUsableCustomProviderApiKey({
cfg,
provider,
secretSentinels: params.secretSentinels
});
if (customKey) {
assertInlineProviderApiKeyUsable({
store: getScopedStore(),
provider
});
return {
apiKey: customKey.apiKey,
source: customKey.source,
mode: "api-key"
};
}
}
const providerConfig = resolveProviderConfig(cfg, provider);
const configuredLocalKey = resolveUsableCustomProviderApiKey({
cfg,
provider,
secretSentinels: params.secretSentinels
});
if (configuredLocalKey && isNonSecretApiKeyMarker(configuredLocalKey.apiKey)) return {
apiKey: configuredLocalKey.apiKey,
source: configuredLocalKey.source,
mode: "api-key"
};
const localMarkerEnv = resolveConfigAwareEnvApiKey(cfg, provider, params.workspaceDir, params.skipSetupProviderFallback);
if (localMarkerEnv && isNonSecretApiKeyMarker(localMarkerEnv.apiKey)) return {
apiKey: localMarkerEnv.apiKey,
source: localMarkerEnv.source,
mode: "api-key"
};
const store = getScopedStore();
const order = params.allowAuthProfileFallback === false ? [] : resolveAuthProfileOrder({
cfg,
store,
provider,
preferredProfile,
forModel: params.modelId
});
let deferredAuthProfileResult = null;
let refreshFailure;
for (const candidate of order) {
const candidateType = store.profiles[candidate]?.type;
const candidateMode = candidateType ? profileTypeToAuthMode(candidateType) : void 0;
if (candidateMode && !isAuthModeAllowedForModel({
provider,
modelApi: params.modelApi,
mode: candidateMode
})) continue;
if (getDeprecatedProfileIds().has(candidate)) continue;
try {
const awsSdkProfileAuth = resolveConfiguredAwsSdkProfileAuth({
cfg,
provider,
profileId: candidate
});
if (awsSdkProfileAuth) return awsSdkProfileAuth;
const resolved = await resolveApiKeyForProfile({
cfg,
store,
profileId: candidate,
agentDir,
forceRefresh: params.forceRefresh
});
if (resolved) {
const resolvedProfileId = resolved.profileId ?? candidate;
const mode = resolved.profileType ?? store.profiles[resolvedProfileId]?.type;
const resolvedMode = mode ? profileTypeToAuthMode(mode) : "api-key";
const result = {
apiKey: sentinelizeSecretRefProfileApiKey({
apiKey: resolved.apiKey,
enabled: params.secretSentinels,
profileId: resolvedProfileId,
provider,
store
}),
profileId: resolvedProfileId,
source: `profile:${resolvedProfileId}`,
mode: resolvedMode
};
if (!isAuthModeAllowedForModel({
provider,
modelApi: params.modelApi,
mode: result.mode
})) continue;
if (shouldDeferSyntheticProfileAuth({
cfg,
provider,
resolvedApiKey: resolved.apiKey,
modelApi: params.modelApi
})) {
deferredAuthProfileResult ??= result;
continue;
}
return result;
}
} catch (err) {
if (err instanceof SecretSurfaceUnavailableError) throw err;
if (!refreshFailure && err instanceof OAuthRefreshFailureError && (!candidateMode || isAuthModeAllowedForModel({
provider,
modelApi: params.modelApi,
mode: candidateMode
}))) refreshFailure = err;
log.debug?.(`auth profile "${candidate}" failed for provider "${provider}": ${String(err)}`);
}
}
if (refreshFailure) throw refreshFailure;
const envResolved = resolveConfigAwareEnvApiKey(cfg, provider, params.workspaceDir, params.skipSetupProviderFallback);
if (envResolved) {
const resolvedMode = resolveDirectProviderCredentialMode({
cfg,
provider,
inferredMode: envResolved.source.includes("OAUTH_TOKEN") ? "oauth" : "api-key"
});
if (resolvedMode === "api-key") {
const inlineStore = getScopedStore();
if (isConfigBackedInlineProviderApiKey({
cfg,
provider,
source: envResolved.source,
store: inlineStore
})) assertInlineProviderApiKeyUsable({
store: inlineStore,
provider
});
}
if (isAuthModeAllowedForModel({
provider,
modelApi: params.modelApi,
mode: resolvedMode
})) return {
apiKey: sentinelizeConfigSecretRefEnvApiKey({
apiKey: envResolved.apiKey,
source: envResolved.source,
cfg,
provider,
enabled: params.secretSentinels
}),
source: envResolved.source,
mode: resolvedMode
};
}
const managedRuntimeAuth = resolveManagedSecretRefRuntimeProviderAuth({
cfg,
provider,
secretSentinels: params.secretSentinels
});
if (managedRuntimeAuth && isAuthModeAllowedForModel({
provider,
modelApi: params.modelApi,
mode: managedRuntimeAuth.mode
})) {
const inlineStore = getScopedStore();
if (isConfigBackedInlineProviderApiKey({
cfg,
provider,
source: managedRuntimeAuth.source,
store: inlineStore
})) assertInlineProviderApiKeyUsable({
store: inlineStore,
provider
});
return managedRuntimeAuth;
}
const customKey = resolveUsableCustomProviderApiKey({
cfg,
provider,
secretSentinels: params.secretSentinels
});
if (customKey) {
const mode = resolveDirectProviderCredentialMode({
cfg,
provider,
inferredMode: "api-key"
});
if (isAuthModeAllowedForModel({
provider,
modelApi: params.modelApi,
mode
})) {
assertInlineProviderApiKeyUsable({
store: getScopedStore(),
provider
});
return {
apiKey: customKey.apiKey,
source: customKey.source,
mode
};
}
}
if (deferredAuthProfileResult) return deferredAuthProfileResult;
const syntheticLocalAuth = await prepareSyntheticLocalProviderAuth({
cfg,
provider,
modelApi: params.modelApi,
workspaceDir: params.workspaceDir,
secretSentinels: params.secretSentinels,
allowPluginSyntheticAuth: params.allowAuthProfileFallback !== false
});
if (syntheticLocalAuth) return syntheticLocalAuth;
const hasInlineConfiguredModels = Array.isArray(providerConfig?.models) && providerConfig.models.length > 0;
if ((params.allowAuthProfileFallback !== false && !hasInlineConfiguredModels ? resolveOwningPluginIdsForProviderRef({
provider,
config: cfg
}) : void 0)?.length) {
const pluginMissingAuthMessage = buildProviderMissingAuthMessageWithPlugin({
provider,
config: cfg,
context: {
config: cfg,
agentDir,
env: process.env,
provider,
listProfileIds: (providerId) => listProfilesForProvider(store, providerId)
}
});
if (pluginMissingAuthMessage) throw new ProviderAuthError("missing-provider-auth", provider, pluginMissingAuthMessage, { providerGuidance: true });
}
const authStorePath = resolveAuthStorePathForDisplay(agentDir);
const agentDirContext = agentDir ? ` (agentDir: ${resolveUserPath(agentDir)})` : "";
throw new ProviderAuthError("missing-provider-auth", provider, [
`No API key found for provider "${provider}".`,
`Auth store: ${authStorePath}${agentDirContext}.`,
`Configure an API key (${formatCliCommand(`openclaw models auth paste-api-key --provider ${provider}`)}; add --agent <id> for a non-default agent) or copy only portable static auth profiles from the main agentDir.`
].join(" "));
}
//#endregion
export { hasRuntimeAvailableProviderAuth as a, isAuthModeAllowedForModel as c, createRuntimeProviderAuthLookup as i, resolveProviderEntryApiKeyAuth as n, prepareRuntimeAvailableProviderAuth as o, resolveScopedAuthProfileStore as r, prepareSyntheticLocalProviderAuth as s, resolveApiKeyForProviderCore as t };