fix(agent): recover image parameter compatibility errors without false model bans
This commit is contained in:
parent
54700b3ebb
commit
4768758dd9
@ -13,6 +13,10 @@ export function agentImageFailurePolicy(error: unknown): { retry: boolean; pause
|
||||
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))
|
||||
|
||||
@ -5874,7 +5874,7 @@ export async function generateCanvasImage(
|
||||
throw new Error("图片任务的结果暂未确认,已保留任务记录,请先确认原任务结果,避免重复生成。");
|
||||
throw new Error(request.agentImageMode === "pinned"
|
||||
? "你指定的生图模型本次未能完成,请稍后重试或手动更换模型;系统未自动切换。"
|
||||
: "当前图片通道暂时未能完成任务,已尝试可用的备用模型,请稍后继续;已有结果会保留。");
|
||||
: "暂时未能完成本次出图,请检查描述、参考图或稍后继续;已有结果会保留。");
|
||||
}
|
||||
throw caughtError;
|
||||
}
|
||||
|
||||
@ -44,8 +44,8 @@ test("a submitted task with an unknown outcome is not submitted again through a
|
||||
expect(agentImageFailurePolicy(new Error("VIP98K task failed: timeout")).retry).toBe(true);
|
||||
});
|
||||
|
||||
test("content restrictions and user input problems cannot be bypassed by switching services", () => {
|
||||
for (const error of [new Error("content policy rejection"), Object.assign(new Error("bad input"), { status: 400 }), new Error("用户积分不足")]) expect(agentImageFailurePolicy(error)).toEqual({ retry: false, pause: null });
|
||||
test("content restrictions and account limits cannot be bypassed by switching services", () => {
|
||||
for (const error of [new Error("content policy rejection"), new Error("用户积分不足")]) expect(agentImageFailurePolicy(error)).toEqual({ retry: false, pause: null });
|
||||
});
|
||||
|
||||
|
||||
@ -74,12 +74,21 @@ test("provider adapters that include HTTP status or quota only in their message
|
||||
for (const message of ["API request failed: 503", "Internal server error", "Service Unavailable", "Unauthorized", "API request failed: HTTP 503", "server busy(HTTP 429)", "insufficient balance", "模型配额不足", "No images in response", "BananaImage 生成失败"]) {
|
||||
expect(agentImageFailurePolicy(new Error(message)).retry).toBe(true);
|
||||
}
|
||||
expect(agentImageFailurePolicy(new Error("invalid input (HTTP 400)")).retry).toBe(false);
|
||||
expect(agentImageFailurePolicy(new Error("invalid input (HTTP 400)"))).toEqual({ retry: true, pause: null });
|
||||
});
|
||||
|
||||
|
||||
test("exhausted automatic channels and pinned failures show useful messages without provider diagnostics", async () => {
|
||||
const h = harness({ generate: () => { throw Object.assign(new Error("provider-internal-trace HTTP 503"), { status: 503 }); } });
|
||||
await expect(h.generate(h.request)).rejects.toThrow("已尝试可用的备用模型");
|
||||
await expect(h.generate(h.request)).rejects.toThrow("暂时未能完成本次出图");
|
||||
await expect(h.generate({ ...h.request, agentImageMode: "pinned" })).rejects.toThrow("系统未自动切换");
|
||||
});
|
||||
|
||||
|
||||
test("a parameter rejection can recover on a compatible alternate without pausing the first model", async () => {
|
||||
const h = harness({ generate: id => { if (id === "primary") throw Object.assign(new Error("parameter not supported (HTTP 400)"), { status: 400 }); return ""; } });
|
||||
const result = await h.generate(h.request);
|
||||
expect(result.modelRef).toBe("backup"); expect(h.calls.map(c => c.id)).toEqual(["primary", "backup"]);
|
||||
expect(h.paused.size).toBe(0);
|
||||
expect(h.calls[1].imageParams.aspectRatio).toBe("3:4");
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user