diff --git a/src/media-generation/runtime-shared.ts b/src/media-generation/runtime-shared.ts index 76e07e8662b..df408be9055 100644 --- a/src/media-generation/runtime-shared.ts +++ b/src/media-generation/runtime-shared.ts @@ -1,6 +1,7 @@ import { listProfilesForProvider } from "../agents/auth-profiles.js"; import { ensureAuthProfileStore } from "../agents/auth-profiles.js"; import { DEFAULT_PROVIDER } from "../agents/defaults.js"; +import { describeFailoverError, isFailoverError } from "../agents/failover-error.js"; import { resolveEnvApiKey } from "../agents/model-auth-env.js"; import type { FallbackAttempt } from "../agents/model-fallback.types.js"; import { @@ -9,6 +10,7 @@ import { } from "../config/model-input.js"; import type { AgentModelConfig } from "../config/types.agents-shared.js"; import type { OpenClawConfig } from "../config/types.js"; +import { formatErrorMessage } from "../infra/errors.js"; import { getProviderEnvVars } from "../secrets/provider-env-vars.js"; import { normalizeOptionalString } from "../shared/string-coerce.js"; import type { @@ -27,6 +29,23 @@ export type { MediaNormalizationValue, } from "./normalization.types.js"; +export function recordCapabilityCandidateFailure(params: { + attempts: FallbackAttempt[]; + provider: string; + model: string; + error: unknown; +}): void { + const described = isFailoverError(params.error) ? describeFailoverError(params.error) : undefined; + params.attempts.push({ + provider: params.provider, + model: params.model, + error: described?.message ?? formatErrorMessage(params.error), + reason: described?.reason, + status: described?.status, + code: described?.code, + }); +} + export function hasMediaNormalizationEntry( entry: MediaNormalizationEntry | undefined, ): entry is MediaNormalizationEntry { diff --git a/src/music-generation/runtime.ts b/src/music-generation/runtime.ts index 984b6e7e8be..b900acb28ed 100644 --- a/src/music-generation/runtime.ts +++ b/src/music-generation/runtime.ts @@ -1,11 +1,10 @@ -import { describeFailoverError, isFailoverError } from "../agents/failover-error.js"; import type { FallbackAttempt } from "../agents/model-fallback.types.js"; import type { OpenClawConfig } from "../config/types.openclaw.js"; -import { formatErrorMessage } from "../infra/errors.js"; import { createSubsystemLogger } from "../logging/subsystem.js"; import { buildMediaGenerationNormalizationMetadata, buildNoCapabilityModelConfiguredMessage, + recordCapabilityCandidateFailure, resolveCapabilityModelCandidates, throwCapabilityGenerationFailure, } from "../media-generation/runtime-shared.js"; @@ -104,14 +103,11 @@ export async function generateMusic( }; } catch (err) { lastError = err; - const described = isFailoverError(err) ? describeFailoverError(err) : undefined; - attempts.push({ + recordCapabilityCandidateFailure({ + attempts, provider: candidate.provider, model: candidate.model, - error: described?.message ?? formatErrorMessage(err), - reason: described?.reason, - status: described?.status, - code: described?.code, + error: err, }); log.debug(`music-generation candidate failed: ${candidate.provider}/${candidate.model}`); } diff --git a/src/video-generation/runtime.ts b/src/video-generation/runtime.ts index da4f4888510..ce5a93ddf6c 100644 --- a/src/video-generation/runtime.ts +++ b/src/video-generation/runtime.ts @@ -1,11 +1,10 @@ -import { describeFailoverError, isFailoverError } from "../agents/failover-error.js"; import type { FallbackAttempt } from "../agents/model-fallback.types.js"; import type { OpenClawConfig } from "../config/types.openclaw.js"; -import { formatErrorMessage } from "../infra/errors.js"; import { createSubsystemLogger } from "../logging/subsystem.js"; import { buildMediaGenerationNormalizationMetadata, buildNoCapabilityModelConfiguredMessage, + recordCapabilityCandidateFailure, resolveCapabilityModelCandidates, throwCapabilityGenerationFailure, } from "../media-generation/runtime-shared.js"; @@ -290,14 +289,11 @@ export async function generateVideo( }; } catch (err) { lastError = err; - const described = isFailoverError(err) ? describeFailoverError(err) : undefined; - attempts.push({ + recordCapabilityCandidateFailure({ + attempts, provider: candidate.provider, model: candidate.model, - error: described?.message ?? formatErrorMessage(err), - reason: described?.reason, - status: described?.status, - code: described?.code, + error: err, }); log.debug(`video-generation candidate failed: ${candidate.provider}/${candidate.model}`); }