fix(ai): classify Z.ai prompt length, sensitive content, and fair-use errors

This commit is contained in:
Aiden Cline
2026-09-29 10:53:10 -05:00
parent d12f89b9c8
commit 9b4a372c2a
2 changed files with 42 additions and 4 deletions
+5 -4
View File
@@ -33,7 +33,8 @@ const patterns = [
/context[_ ]length[_ ]exceeded/i,
/context length is only \d+ tokens/i,
/input length.*exceeds.*context length/i,
/prompt too long; exceeded (?:max )?context length/i,
// Z.ai code 1261 arrives as `Prompt too long` or `Prompt 超长`.
/prompt (?:too long|超长)/i,
/too large for model with \d+ maximum context length/i,
/prompt has [\d,]+ tokens?, but the configured context size is [\d,]+ tokens?/i,
/model_context_window_exceeded/i,
@@ -145,15 +146,15 @@ const CONTENT_POLICY_CODES = new Set([
const GATEWAY_CODE_LABEL = /^[^:\n]+: \[([A-Za-z0-9_.-]+)\]/
const RATE_LIMIT_TEXT = /rate increased too quickly|rate[-_\s]?limit|too[_\s]?many[_\s]?requests/i
// Only consulted on 429, where throttles and account caps share a status.
// Z.ai reports balance, plan expiry, plan limits, and plan model access on 429.
// Z.ai reports balance, plan expiry, plan limits, plan model access, and fair-use restrictions on 429.
const QUOTA_TEXT =
/insufficient[-_\s]?(?:quota|balance)|quota[-_\s]?exceeded|budget exceeded|usage limit|limit exhausted|package has expired|plan does not yet include/i
/insufficient[-_\s]?(?:quota|balance)|quota[-_\s]?exceeded|budget exceeded|usage limit|limit exhausted|package has expired|plan does not yet include|fair usage policy/i
// Policy rejections without a dedicated code, matched against the provider's own
// explanation only. OpenAI reuses `invalid_prompt` for usage-policy rejections while
// Bedrock Mantle reuses it for schema validation; Anthropic reports blocked output
// under `invalid_request_error`.
const CONTENT_POLICY_TEXT =
/violating our usage policy|blocked by content filtering policy|content[-_\s]?policy|rejected as a result of our safety system/i
/violating our usage policy|blocked by content filtering policy|content[-_\s]?policy|rejected as a result of our safety system|detected potentially unsafe or sensitive content/i
const SERVER_ERROR_TEXT =
/\b(?:try again|(?:please |you can )?retry (?:the |this |your )?request|try (?:the |this |your )?request again|(?:currently |temporarily )?at capacity|overloaded|temporarily unavailable|service[-_\s]?unavailable|(?:server|internal)[-_\s]?error|server (?:is )?busy|provider returned (?:an )?error|resource[-_\s]?exhausted|upstream (?:connect|connection|request)|request buffer limit while retrying upstream)\b/i
+37
View File
@@ -294,6 +294,10 @@ describe("provider error classification", () => {
zai("1310", "Weekly/Monthly Limit Exhausted. Your limit will reset at 2026-10-01 00:00:00"),
zai("1311", "Your current subscription plan does not yet include access to glm-5"),
zai("1314", "Your enterprise package has expired. Please contact your enterprise administrator."),
zai(
"1313",
"Your account's current usage pattern does not comply with the Fair Usage Policy, and your request frequency has been limited. For details, please refer to the Subscription Service Agreement. To restore access, please submit a request.",
),
// Z.ai's Anthropic-compatible endpoint wraps the code and request ID into the message.
{
type: "error",
@@ -313,6 +317,39 @@ describe("provider error classification", () => {
).toEqual(Array(cases.length).fill("QuotaExceeded"))
})
test("classifies Z.ai prompt length rejections as context overflow", () => {
const cases = [
{ error: { code: "1261", message: "Prompt 超长" } },
{ error: { code: "1261", message: "Prompt too long" } },
{
type: "error",
error: { type: "invalid_request_error", code: "1261", message: "[1261][Prompt too long][2026092913]" },
},
]
expect(
cases.map((body) => {
const reason = classifyProviderFailure({
message: body.error.message,
status: 400,
rawBody: JSON.stringify(body),
})
return reason._tag === "InvalidRequest" ? reason.classification : reason._tag
}),
).toEqual(["context-overflow", "context-overflow", "context-overflow"])
})
test("classifies Z.ai sensitive content rejections as content policy", () => {
const message =
"System detected potentially unsafe or sensitive content in input or generation. Please avoid using prompts that may generate sensitive content. Thank you for your cooperation."
expect(
classifyProviderFailure({
message,
status: 400,
rawBody: JSON.stringify({ error: { code: "1301", message } }),
})._tag,
).toBe("ContentPolicy")
})
test("keeps Z.ai throttling and overload retryable", () => {
expect(
[