ai-chatbot/lib/ai/runtime/agent-image-failover.ts

26 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { agentModelFault, type AgentModelFault } from "./agent-model-failover";
export function agentImageFailurePolicy(error: unknown): { retry: boolean; pause: AgentModelFault | null } {
const value = error as { message?: string; providerOutcomeUnknown?: boolean; status?: number; statusCode?: number } | null;
const message = String(value?.message || "").toLowerCase();
// A submitted image job may still succeed. Retain its task and reconcile it;
// never submit another paid job just because a poll/connection timed out.
const unknown = value?.providerOutcomeUnknown || /request_outcome_unknown|may still be running|outcome.unknown|timed out|timeout|超时|fetch failed|econnreset|socket hang up/.test(message);
if (unknown && !/task failed|task.*(?:failed|cancelled|canceled)|任务.*(?:失败|取消)/.test(message)) return { retry: false, pause: null };
if (/content.?policy|moderation|safety|违规|敏感|积分不足|本月.*配额|user cancel|user abort/.test(message)) return { retry: false, pause: null };
const status = Number(value?.statusCode || value?.status) || Number(message.match(/(?:http[\s::]*|status(?:code)?[\s:=]*|api request failed[\s::]*)([45]\d{2})/i)?.[1]) || null;
if (/unauthorized|invalid[ _]?(?:api[ _]?)?key|authentication/.test(message)) return { retry: true, pause: { reason: "authentication", status } };
if (/forbidden|access denied/.test(message)) return { retry: true, pause: { reason: "access_denied", status } };
if (/quota|insufficient.*(?:balance|credit)|credits? insufficient|余额|额度|配额|rate.?limit|too many requests/.test(message))
return { retry: true, pause: { reason: "rate_or_quota", status } };
// Rejected image parameters can be valid on another provider. Keep the
// requested parameters and try a compatible alternate without banning the
// rejected model; these are not evidence of a model outage.
if (status && [400, 413, 415, 422].includes(status)) return { retry: true, pause: null };
const fault = agentModelFault(status ? { message, status } : error);
if (fault) return { retry: true, pause: fault };
if (/task failed|image generation failed|生成失败|任务.*失败|未返回.*图片|no images? (?:in|url)|no valid data|response body is null|empty.result|empty.response|provider.error|上游.*错误|模型.*维护|internal.server.error|service.unavailable|bad.gateway|server.busy|系统繁忙/.test(message))
return { retry: true, pause: { reason: "image_generation_failed", status: Number(value?.statusCode || value?.status) || null } };
return { retry: false, pause: null };
}