openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
241 lines (240 loc) • 10.2 kB
JavaScript
import { l as toErrorObject } from "./error-coercion-D_-xJ90S.js";
import "./errors-Db3Ymjlb.js";
import { s as providerModelRouteAcceptsAuthMode } from "./openai-model-routes-Bte2KVl5.js";
import { n as SecretSurfaceUnavailableError } from "./runtime-degraded-state-D5EZZ925.js";
import { t as OAuthRefreshFailureError } from "./oauth-refresh-failure-DP-bO7C0.js";
import { o as isProfileInCooldown } from "./usage-state-CAKmPrwS.js";
import { i as getApiKeyForModelCore } from "./model-auth-C48_DZ-I.js";
import { i as preparedAgentRuntimeProfileAttemptHasCandidate, n as canRunPreparedAgentRuntimeAuthAttempt } from "./prepare-auth-Ci9igqt8.js";
import { o as shouldForceDirectAuthFallbackModelResolve } from "./credential-scoped-model-dyTrjhuq.js";
//#region src/agents/runtime-plan/model-route.ts
function normalizeRouteBaseUrl(value) {
return value.replace(/\/+$/u, "");
}
function sameCompatibleRuntimeIds(left, right) {
if (left === right) return true;
if (!left || !right) return false;
const leftIds = new Set(left);
const rightIds = new Set(right);
if (leftIds.size !== rightIds.size) return false;
for (const id of leftIds) if (!rightIds.has(id)) return false;
return true;
}
/** Compares the complete secret-free identity of two prepared model routes. */
function sameAgentRuntimeAuthModelRoute(left, right) {
return left.provider.trim().toLowerCase() === right.provider.trim().toLowerCase() && left.modelId === right.modelId && left.api === right.api && left.authRequirement === right.authRequirement && left.requestTransportOverrides === right.requestTransportOverrides && sameCompatibleRuntimeIds(left.runtimePolicy?.compatibleIds, right.runtimePolicy?.compatibleIds) && normalizeRouteBaseUrl(left.baseUrl) === normalizeRouteBaseUrl(right.baseUrl);
}
//#endregion
//#region src/agents/runtime-plan/resolve-auth.ts
/** Resolves credentials for an immutable prepared runtime route. */
function listDistinctPreparedRuntimeAuthAttempts(attempts) {
return attempts.filter((attempt, index) => {
const route = attempt.plan.modelRoute;
return !attempts.slice(0, index).some((previous) => {
if (previous.allowAuthProfileFallback === false !== (attempt.allowAuthProfileFallback === false)) return false;
const previousRoute = previous.plan.modelRoute;
if (!route || !previousRoute) return !route && !previousRoute;
return sameAgentRuntimeAuthModelRoute(route, previousRoute);
});
});
}
/** Resolves one complete prepared route/profile tuple without crossing retries mid-flight. */
async function resolvePreparedRuntimeAuthAttempts(params) {
let firstError;
let priorProfileAttempted = false;
for (const attempt of listDistinctPreparedRuntimeAuthAttempts(params.attempts)) {
if (!canRunPreparedAgentRuntimeAuthAttempt({
attempt,
priorProfileAttempted
})) {
firstError ??= /* @__PURE__ */ new Error("Prepared direct auth cannot bypass unavailable profiles.");
continue;
}
if (attempt.kind === "profile" && !preparedAgentRuntimeProfileAttemptHasCandidate({
attempt,
store: params.store,
modelId: params.modelId
})) {
firstError ??= /* @__PURE__ */ new Error("Prepared runtime auth candidates are temporarily unavailable.");
continue;
}
try {
let model = await params.materializeModel({
plan: attempt.plan,
model: params.model,
forceResolve: params.forceCredentialScopedDirectModelResolve === true && attempt.kind === "direct" && Boolean(attempt.plan.selectedAuthMode) || shouldForceDirectAuthFallbackModelResolve({
attempt,
priorProfileAttempted
})
});
if (attempt.kind === "profile" && !preparedAgentRuntimeProfileAttemptHasCandidate({
attempt,
store: params.store,
modelId: params.modelId
})) throw new Error("Prepared runtime auth candidates are temporarily unavailable.");
const resolution = params.resolveAuth({
attempt,
model
});
priorProfileAttempted ||= attempt.kind === "profile";
const resolved = await resolution;
if (resolved.plan.forwardedAuthProfileId !== attempt.plan.forwardedAuthProfileId) model = await params.materializeModel({
plan: resolved.plan,
model,
forceResolve: true
});
return {
model,
plan: resolved.plan,
auth: resolved.auth
};
} catch (error) {
if (error instanceof SecretSurfaceUnavailableError || error instanceof OAuthRefreshFailureError) throw error;
firstError ??= error;
}
}
throw toErrorObject(firstError, params.errorMessage);
}
function scopeAuthStoreToPreparedCandidates(store, profileIds) {
const profileIdSet = new Set(profileIds);
const profiles = {};
for (const profileId of profileIds) {
const profile = store.profiles[profileId];
if (profile) profiles[profileId] = profile;
}
const order = store.order ? Object.fromEntries(Object.entries(store.order).map(([provider, ids]) => [provider, ids.filter((profileId) => profileIdSet.has(profileId))])) : void 0;
const lastGood = store.lastGood ? Object.fromEntries(Object.entries(store.lastGood).filter(([, profileId]) => profileIdSet.has(profileId))) : void 0;
const usageStats = store.usageStats ? Object.fromEntries(Object.entries(store.usageStats).filter(([profileId]) => profileIdSet.has(profileId))) : void 0;
const runtimePersistedProfileIds = store.runtimePersistedProfileIds?.filter((profileId) => profileIdSet.has(profileId));
const runtimeExternalProfileIds = store.runtimeExternalProfileIds?.filter((profileId) => profileIdSet.has(profileId));
return {
version: store.version,
profiles,
...order ? { order } : {},
...lastGood ? { lastGood } : {},
...usageStats ? { usageStats } : {},
...runtimePersistedProfileIds ? { runtimePersistedProfileIds } : {},
...runtimeExternalProfileIds || store.runtimeExternalProfileIdsAuthoritative === true ? {
runtimeExternalProfileIds: runtimeExternalProfileIds ?? [],
...store.runtimeExternalProfileIdsAuthoritative === true ? { runtimeExternalProfileIdsAuthoritative: true } : {}
} : {}
};
}
/** Restricts a native auth consumer to the profiles selected for one physical route. */
function scopeAuthProfileStoreToPreparedPlan(store, plan) {
return scopeAuthStoreToPreparedCandidates(store, plan.modelRoute?.authRequirement === "api-key" ? [] : [plan.forwardedAuthProfileId, ...plan.forwardedAuthProfileCandidateIds ?? []].filter((profileId, index, values) => {
return Boolean(profileId?.trim()) && values.indexOf(profileId) === index;
}));
}
function applyResolvedAuthToPlan(params) {
const profileId = params.auth.profileId?.trim();
if (!profileId) return {
...params.plan,
forwardedAuthProfileId: void 0,
forwardedAuthProfileSource: void 0,
forwardedAuthProfileCandidateIds: void 0,
selectedAuthMode: params.auth.mode
};
const resolvedIndex = params.candidates.indexOf(profileId);
const remainingCandidates = resolvedIndex >= 0 ? params.candidates.slice(resolvedIndex) : [profileId];
const source = params.plan.forwardedAuthProfileId ? params.plan.forwardedAuthProfileSource : "auto";
return {
...params.plan,
forwardedAuthProfileId: profileId,
forwardedAuthProfileSource: source,
forwardedAuthProfileCandidateIds: source === "auto" ? remainingCandidates : [profileId],
selectedAuthMode: params.auth.mode
};
}
function assertResolvedAuthMatchesPreparedRoute(params) {
const route = params.plan.modelRoute;
if (!route || providerModelRouteAcceptsAuthMode({
requirement: route.authRequirement,
mode: params.auth.mode
})) return;
throw new Error(`Resolved ${params.auth.mode} credentials are incompatible with the selected ${route.authRequirement} route for ${route.provider}.`);
}
/** Resolves prepared same-route candidates without pinning the first unresolved profile. */
async function resolvePreparedRuntimeModelAuth(params) {
const { plan, ...authParams } = params;
const candidates = [plan.forwardedAuthProfileId, ...plan.forwardedAuthProfileCandidateIds ?? []].filter((profileId, index, values) => {
return Boolean(profileId?.trim()) && values.indexOf(profileId) === index;
});
if (candidates.length === 0) {
const auth = await getApiKeyForModelCore({
...authParams,
store: {
version: 1,
profiles: {}
},
lockedProfile: false,
allowAuthProfileFallback: false,
skipSetupProviderFallback: plan.modelRoute?.provider === "openai"
});
assertResolvedAuthMatchesPreparedRoute({
plan,
auth
});
return {
auth,
plan: applyResolvedAuthToPlan({
plan,
auth,
candidates
})
};
}
if (plan.forwardedAuthProfileSource !== "auto") {
const auth = await getApiKeyForModelCore({
...authParams,
profileId: plan.forwardedAuthProfileId,
lockedProfile: Boolean(plan.forwardedAuthProfileId)
});
assertResolvedAuthMatchesPreparedRoute({
plan,
auth
});
return {
auth,
plan: applyResolvedAuthToPlan({
plan,
auth,
candidates
})
};
}
const store = params.store;
const currentCandidates = store ? candidates.filter((profileId) => !isProfileInCooldown(store, profileId, void 0, params.model.id)) : candidates;
if (currentCandidates.length === 0) throw new Error("Prepared runtime auth candidates are temporarily unavailable.");
const candidateStore = store ? scopeAuthStoreToPreparedCandidates(store, currentCandidates) : void 0;
let firstError;
let refreshFailure;
for (const profileId of currentCandidates) try {
const auth = await getApiKeyForModelCore({
...authParams,
profileId,
lockedProfile: true,
...candidateStore ? { store: candidateStore } : {}
});
assertResolvedAuthMatchesPreparedRoute({
plan,
auth
});
return {
auth,
plan: applyResolvedAuthToPlan({
plan,
auth,
candidates: currentCandidates
})
};
} catch (error) {
if (error instanceof SecretSurfaceUnavailableError) throw error;
if (!refreshFailure && error instanceof OAuthRefreshFailureError) refreshFailure = error;
firstError ??= error;
}
if (refreshFailure) throw refreshFailure;
throw toErrorObject(firstError, "Prepared runtime auth candidates could not be resolved.");
}
//#endregion
export { resolvePreparedRuntimeModelAuth as n, scopeAuthProfileStoreToPreparedPlan as r, resolvePreparedRuntimeAuthAttempts as t };