mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-08 15:53:56 +00:00
docs: document auth redaction helpers
This commit is contained in:
@@ -20,6 +20,10 @@ import {
|
||||
} from "./model-auth.js";
|
||||
import { normalizeProviderId } from "./model-selection.js";
|
||||
|
||||
// Builds concise auth labels for UI/status surfaces without exposing credential
|
||||
// values. Resolution follows profile override, provider profiles, env, CLI, then
|
||||
// custom provider config.
|
||||
/** Resolve the display label that describes how a provider is authenticated. */
|
||||
export function resolveModelAuthLabel(params: {
|
||||
provider?: string;
|
||||
cfg?: OpenClawConfig;
|
||||
@@ -106,6 +110,8 @@ export function resolveModelAuthLabel(params: {
|
||||
return `api-key${label ? ` (${label})` : ""}`;
|
||||
}
|
||||
if (providerEntryProfileRef.kind === "profile-incompatible") {
|
||||
// Preserve the fact that config pointed at a profile while avoiding a
|
||||
// misleading auth mode for an incompatible provider/profile pairing.
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { normalizeSecretInput } from "../utils/normalize-secret-input.js";
|
||||
|
||||
// Shared provider-auth runtime types and errors. Provider calls use these helpers
|
||||
// to fail with actionable auth provenance while keeping secret normalization local.
|
||||
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";
|
||||
@@ -14,6 +16,7 @@ export type ResolvedProviderAuth = {
|
||||
|
||||
export 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;
|
||||
@@ -26,6 +29,7 @@ export class ProviderAuthError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
/** Auth error raised when a resolved provider auth source lacks usable material. */
|
||||
export class MissingProviderAuthError extends ProviderAuthError {
|
||||
readonly mode: ResolvedProviderAuth["mode"];
|
||||
readonly source: string;
|
||||
@@ -38,6 +42,7 @@ export class MissingProviderAuthError extends ProviderAuthError {
|
||||
}
|
||||
}
|
||||
|
||||
/** Narrow unknown errors to provider auth errors, optionally by code. */
|
||||
export function isProviderAuthError(
|
||||
err: unknown,
|
||||
code?: ProviderAuthErrorCode,
|
||||
@@ -45,10 +50,12 @@ export function isProviderAuthError(
|
||||
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;
|
||||
@@ -62,10 +69,12 @@ export function resolveAwsSdkEnvVarName(env: NodeJS.ProcessEnv = process.env): s
|
||||
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) {
|
||||
|
||||
@@ -4,8 +4,11 @@ import { buildTextObservationFields } from "./embedded-agent-error-observation.j
|
||||
import type { FailoverReason } from "./embedded-agent-helpers.js";
|
||||
import type { FallbackAttempt, ModelCandidate } from "./model-fallback.types.js";
|
||||
|
||||
// Structured logging for model fallback decisions. The log payload carries
|
||||
// sanitized error observations plus step fields that make fallback chains auditable.
|
||||
const decisionLog = createSubsystemLogger("model-fallback").child("decision");
|
||||
|
||||
/** Return whether fallback decision logging is enabled for warn-level events. */
|
||||
export function isModelFallbackDecisionLogEnabled(): boolean {
|
||||
return decisionLog.isEnabled("warn");
|
||||
}
|
||||
@@ -85,6 +88,8 @@ function buildFallbackStepFields(params: {
|
||||
}): ModelFallbackStepFields | undefined {
|
||||
const lastPreviousAttempt = params.previousAttempts?.at(-1);
|
||||
if (params.decision === "candidate_succeeded") {
|
||||
// Success records the previous failed candidate as the source and the current
|
||||
// candidate as the successful fallback destination.
|
||||
if (!lastPreviousAttempt) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -120,6 +125,7 @@ function buildFallbackStepFields(params: {
|
||||
};
|
||||
}
|
||||
|
||||
/** Log one model fallback decision and return structured fallback-step fields. */
|
||||
export function logModelFallbackDecision(
|
||||
params: ModelFallbackDecisionParams,
|
||||
): ModelFallbackStepFields | undefined {
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { normalizeStringEntries } from "@openclaw/normalization-core/string-normalization";
|
||||
import { normalizeToolList, normalizeToolName } from "./tool-policy.js";
|
||||
|
||||
// Guardrails for explicit tool allowlists. They collect user/operator sources and
|
||||
// explain when allowlist resolution leaves no callable tools.
|
||||
type ExplicitToolAllowlistSource = {
|
||||
label: string;
|
||||
entries: string[];
|
||||
enforceWhenToolsDisabled?: boolean;
|
||||
};
|
||||
|
||||
/** Normalize explicit allowlist sources, dropping empty source entries. */
|
||||
export function collectExplicitToolAllowlistSources(
|
||||
sources: Array<{ label: string; allow?: string[]; enforceWhenToolsDisabled?: boolean }>,
|
||||
): ExplicitToolAllowlistSource[] {
|
||||
@@ -25,6 +28,7 @@ export function collectExplicitToolAllowlistSources(
|
||||
});
|
||||
}
|
||||
|
||||
/** Build an actionable error when explicit allowlists remove every callable tool. */
|
||||
export function buildEmptyExplicitToolAllowlistError(params: {
|
||||
sources: ExplicitToolAllowlistSource[];
|
||||
callableToolNames: string[];
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Common trace fields copied into provider/model diagnostic events.
|
||||
type AgentTraceBase = {
|
||||
runId?: string;
|
||||
sessionId?: string;
|
||||
@@ -8,6 +9,7 @@ type AgentTraceBase = {
|
||||
workspaceDir?: string;
|
||||
};
|
||||
|
||||
/** Build a trace base object while preserving undefined optional fields. */
|
||||
export function buildAgentTraceBase(params: AgentTraceBase): AgentTraceBase {
|
||||
return {
|
||||
runId: params.runId,
|
||||
|
||||
@@ -7,6 +7,9 @@ import {
|
||||
} from "../logging/redact.js";
|
||||
import type { AgentMessage } from "./runtime/index.js";
|
||||
|
||||
// Transcript redaction helpers for persisted agent messages. Text and structured
|
||||
// fields share logging redaction config while preserving object identity when no
|
||||
// redaction changes are needed.
|
||||
function resolveTranscriptRedactPatterns(patterns?: string[]) {
|
||||
return patterns && patterns.length > 0 ? [...patterns, ...getDefaultRedactPatterns()] : undefined;
|
||||
}
|
||||
@@ -79,9 +82,13 @@ function redactTranscriptStructuredValue(
|
||||
return value;
|
||||
}
|
||||
if (seen.has(value)) {
|
||||
// Avoid recursive transcript payloads from escaping redaction or crashing
|
||||
// persistence; circular refs serialize as a stable marker.
|
||||
return "[Circular]";
|
||||
}
|
||||
if (!isPlainTranscriptObject(value)) {
|
||||
// Non-plain instances can carry runtime state; leave them untouched instead
|
||||
// of cloning unexpected prototypes into transcripts.
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -100,6 +107,7 @@ function redactTranscriptStructuredValue(
|
||||
return next ?? value;
|
||||
}
|
||||
|
||||
/** Return a redacted transcript message according to logging config. */
|
||||
export function redactTranscriptMessage(message: AgentMessage, cfg?: OpenClawConfig): AgentMessage {
|
||||
if (cfg?.logging?.redactSensitive === "off") {
|
||||
return message;
|
||||
|
||||
Reference in New Issue
Block a user