mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-24 16:19:35 +00:00
90 lines
3.1 KiB
TypeScript
90 lines
3.1 KiB
TypeScript
/**
|
|
* Shared provider-auth runtime types and errors. Provider calls use these
|
|
* helpers to fail with actionable auth provenance while keeping secret
|
|
* normalization local.
|
|
*/
|
|
import { normalizeSecretInput } from "../utils/normalize-secret-input.js";
|
|
|
|
const AWS_BEARER_ENV = "AWS_BEARER_TOKEN_BEDROCK";
|
|
const AWS_ACCESS_KEY_ENV = "AWS_ACCESS_KEY_ID";
|
|
const AWS_SECRET_KEY_ENV = "AWS_SECRET_ACCESS_KEY";
|
|
const AWS_PROFILE_ENV = "AWS_PROFILE";
|
|
|
|
/** Resolved credential material and provenance for one provider request. */
|
|
export type ResolvedProviderAuth = {
|
|
apiKey?: string;
|
|
profileId?: string;
|
|
source: string;
|
|
mode: "api-key" | "oauth" | "token" | "aws-sdk";
|
|
};
|
|
|
|
/** Stable provider auth error code used by fallback/retry paths. */
|
|
type ProviderAuthErrorCode = "missing-api-key" | "missing-provider-auth";
|
|
|
|
/** Base provider auth error with a stable code for retry/fallback logic. */
|
|
export class ProviderAuthError extends Error {
|
|
readonly code: ProviderAuthErrorCode;
|
|
readonly provider: string;
|
|
|
|
constructor(code: ProviderAuthErrorCode, provider: string, message: string) {
|
|
super(message);
|
|
this.name = "ProviderAuthError";
|
|
this.code = code;
|
|
this.provider = provider;
|
|
}
|
|
}
|
|
|
|
/** Auth error raised when a resolved provider auth source lacks usable material. */
|
|
export class MissingProviderAuthError extends ProviderAuthError {
|
|
readonly mode: ResolvedProviderAuth["mode"];
|
|
readonly source: string;
|
|
|
|
constructor(provider: string, auth: ResolvedProviderAuth) {
|
|
super("missing-api-key", provider, formatMissingAuthError(auth, provider));
|
|
this.name = "MissingProviderAuthError";
|
|
this.mode = auth.mode;
|
|
this.source = auth.source;
|
|
}
|
|
}
|
|
|
|
/** Narrow unknown errors to provider auth errors, optionally by code. */
|
|
export function isProviderAuthError(
|
|
err: unknown,
|
|
code?: ProviderAuthErrorCode,
|
|
): err is ProviderAuthError {
|
|
return err instanceof ProviderAuthError && (!code || err.code === code);
|
|
}
|
|
|
|
/** Narrow unknown errors to missing-provider-auth failures. */
|
|
export function isMissingProviderAuthError(err: unknown): err is MissingProviderAuthError {
|
|
return err instanceof MissingProviderAuthError;
|
|
}
|
|
|
|
/** Return the AWS credential env var that proves SDK auth is configured. */
|
|
export function resolveAwsSdkEnvVarName(env: NodeJS.ProcessEnv = process.env): string | undefined {
|
|
if (env[AWS_BEARER_ENV]?.trim()) {
|
|
return AWS_BEARER_ENV;
|
|
}
|
|
if (env[AWS_ACCESS_KEY_ENV]?.trim() && env[AWS_SECRET_KEY_ENV]?.trim()) {
|
|
return AWS_ACCESS_KEY_ENV;
|
|
}
|
|
if (env[AWS_PROFILE_ENV]?.trim()) {
|
|
return AWS_PROFILE_ENV;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
/** Format the user-facing missing-auth error from auth provenance. */
|
|
export function formatMissingAuthError(auth: ResolvedProviderAuth, provider: string): string {
|
|
return `No API key resolved for provider "${provider}" (auth mode: ${auth.mode}, checked: ${auth.source}).`;
|
|
}
|
|
|
|
/** Require a normalized API key or throw a provider-auth error. */
|
|
export function requireApiKey(auth: ResolvedProviderAuth, provider: string): string {
|
|
const key = normalizeSecretInput(auth.apiKey);
|
|
if (key) {
|
|
return key;
|
|
}
|
|
throw new MissingProviderAuthError(provider, auth);
|
|
}
|