mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 02:24:10 +08:00
fix(ai): classify xAI invalid API keys as authentication errors
This commit is contained in:
@@ -147,6 +147,8 @@ const CONTENT_POLICY_CODES = new Set([
|
|||||||
// OpenCode Zen replaces upstream codes outside its allow-list but keeps the original
|
// OpenCode Zen replaces upstream codes outside its allow-list but keeps the original
|
||||||
// as a `[code]` label at the start of the rewritten message.
|
// as a `[code]` label at the start of the rewritten message.
|
||||||
const GATEWAY_CODE_LABEL = /^[^:\n]+: \[([A-Za-z0-9_.-]+)\]/
|
const GATEWAY_CODE_LABEL = /^[^:\n]+: \[([A-Za-z0-9_.-]+)\]/
|
||||||
|
// xAI reports an invalid API key as HTTP 400 with the generic `invalid-argument` code.
|
||||||
|
const AUTH_TEXT = /incorrect api key provided/i
|
||||||
const RATE_LIMIT_TEXT = /rate increased too quickly|rate[-_\s]?limit|too[_\s]?many[_\s]?requests/i
|
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.
|
// Only consulted on 429, where throttles and account caps share a status.
|
||||||
const QUOTA_TEXT = /insufficient[-_\s]?quota|quota[-_\s]?exceeded|budget exceeded|usage limit/i
|
const QUOTA_TEXT = /insufficient[-_\s]?quota|quota[-_\s]?exceeded|budget exceeded|usage limit/i
|
||||||
@@ -246,7 +248,12 @@ export function classifyProviderFailure(input: ProviderFailure): AIError["reason
|
|||||||
(input.status === 429 && QUOTA_TEXT.test(text))
|
(input.status === 429 && QUOTA_TEXT.test(text))
|
||||||
)
|
)
|
||||||
return new QuotaExceededError(details)
|
return new QuotaExceededError(details)
|
||||||
if (input.status === 401 || input.status === 403 || codes.some((code) => AUTH_CODES.has(code)))
|
if (
|
||||||
|
input.status === 401 ||
|
||||||
|
input.status === 403 ||
|
||||||
|
codes.some((code) => AUTH_CODES.has(code)) ||
|
||||||
|
(input.status === 400 && AUTH_TEXT.test(text))
|
||||||
|
)
|
||||||
return new AuthenticationError(details)
|
return new AuthenticationError(details)
|
||||||
if (
|
if (
|
||||||
input.status === 429 ||
|
input.status === 429 ||
|
||||||
|
|||||||
@@ -383,7 +383,7 @@ describe("provider error rawBody classification", () => {
|
|||||||
expect(reason._tag === "InvalidRequest" ? reason.classification : reason._tag).toBe("context-overflow")
|
expect(reason._tag === "InvalidRequest" ? reason.classification : reason._tag).toBe("context-overflow")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("classifies Google invalid API keys as authentication failures", () => {
|
test("classifies invalid API keys reported as HTTP 400 as authentication failures", () => {
|
||||||
const rawBody = JSON.stringify({
|
const rawBody = JSON.stringify({
|
||||||
error: {
|
error: {
|
||||||
code: 400,
|
code: 400,
|
||||||
@@ -407,6 +407,14 @@ describe("provider error rawBody classification", () => {
|
|||||||
classifyProviderFailure({ message: "API key not valid. Please pass a valid API key.", status: 400, rawBody })
|
classifyProviderFailure({ message: "API key not valid. Please pass a valid API key.", status: 400, rawBody })
|
||||||
._tag,
|
._tag,
|
||||||
).toBe("Authentication")
|
).toBe("Authentication")
|
||||||
|
// xAI
|
||||||
|
expect(
|
||||||
|
classifyProviderFailure({
|
||||||
|
message: "Incorrect API key provided. You can obtain an API key from https://console.x.ai.",
|
||||||
|
status: 400,
|
||||||
|
rawBody: '{"code":"invalid-argument","error":"Incorrect API key provided."}',
|
||||||
|
})._tag,
|
||||||
|
).toBe("Authentication")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("classifies overflow signals buried in the raw payload when the summary is vague", () => {
|
test("classifies overflow signals buried in the raw payload when the summary is vague", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user