From e706e4f26adaae5240069205232db3569f6a103d Mon Sep 17 00:00:00 2001 From: ZIRAN456 <75793045+ZIRAN456@users.noreply.github.com> Date: Mon, 28 Sep 2026 12:35:58 +0700 Subject: [PATCH] feat(codebuddy): parse 6004 rate limit error and extract resetsAtMs --- open-sse/executors/codebuddy-cn.js | 27 +++++++++++++ open-sse/executors/codebuddy-intl.js | 27 +++++++++++++ tests/unit/codebuddy-parse-error.test.js | 50 ++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 tests/unit/codebuddy-parse-error.test.js diff --git a/open-sse/executors/codebuddy-cn.js b/open-sse/executors/codebuddy-cn.js index 76ec52ff..072d055c 100644 --- a/open-sse/executors/codebuddy-cn.js +++ b/open-sse/executors/codebuddy-cn.js @@ -64,6 +64,33 @@ export class CodeBuddyExecutor extends DefaultExecutor { // filter and return an error (#2071). return transformed; } + parseError(response, bodyText) { + if (bodyText) { + try { + const data = JSON.parse(bodyText); + const msg = data?.msg || data?.message || data?.error?.message || ""; + if (data?.code === 6004 || /超出频率限制|frequency limit|限额/i.test(msg)) { + let resetsAtMs = null; + const match = msg.match(/(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})(?:\s*UTC\+?([0-9:]+))?/i); + if (match) { + const dp = match[1]; + const tp = match[2]; + const tz = match[3] + ? (match[3].includes(":") ? (match[3].startsWith("+") ? match[3] : `+${match[3]}`) : `+${match[3].padStart(2, "0")}:00`) + : "+08:00"; + const dt = new Date(`${dp}T${tp}${tz}`); + if (!isNaN(dt.getTime())) resetsAtMs = dt.getTime(); + } + return { + status: 429, + message: msg || "CodeBuddy frequency limit (6004)", + resetsAtMs, + }; + } + } catch {} + } + return super.parseError(response, bodyText); + } } export default CodeBuddyExecutor; diff --git a/open-sse/executors/codebuddy-intl.js b/open-sse/executors/codebuddy-intl.js index bb99ff47..61a58997 100644 --- a/open-sse/executors/codebuddy-intl.js +++ b/open-sse/executors/codebuddy-intl.js @@ -39,6 +39,33 @@ export class CodeBuddyIntlExecutor extends DefaultExecutor { return transformed; } + parseError(response, bodyText) { + if (bodyText) { + try { + const data = JSON.parse(bodyText); + const msg = data?.msg || data?.message || data?.error?.message || ""; + if (data?.code === 6004 || /超出频率限制|frequency limit|限额/i.test(msg)) { + let resetsAtMs = null; + const match = msg.match(/(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})(?:\s*UTC\+?([0-9:]+))?/i); + if (match) { + const dp = match[1]; + const tp = match[2]; + const tz = match[3] + ? (match[3].includes(":") ? (match[3].startsWith("+") ? match[3] : `+${match[3]}`) : `+${match[3].padStart(2, "0")}:00`) + : "+08:00"; + const dt = new Date(`${dp}T${tp}${tz}`); + if (!isNaN(dt.getTime())) resetsAtMs = dt.getTime(); + } + return { + status: 429, + message: msg || "CodeBuddy frequency limit (6004)", + resetsAtMs, + }; + } + } catch {} + } + return super.parseError(response, bodyText); + } } export default CodeBuddyIntlExecutor; diff --git a/tests/unit/codebuddy-parse-error.test.js b/tests/unit/codebuddy-parse-error.test.js new file mode 100644 index 00000000..2d07a06b --- /dev/null +++ b/tests/unit/codebuddy-parse-error.test.js @@ -0,0 +1,50 @@ +import { describe, it, expect } from "vitest"; +import { CodeBuddyExecutor } from "../../open-sse/executors/codebuddy-cn.js"; +import { CodeBuddyIntlExecutor } from "../../open-sse/executors/codebuddy-intl.js"; + +describe("CodeBuddy parseError", () => { + it("parses code 6004 frequency limit with timestamp into 429 and resetsAtMs on codebuddy-cn", () => { + const executor = new CodeBuddyExecutor(); + const bodyText = JSON.stringify({ + code: 6004, + message: "当前模型超出频率限制,请于 2026-09-28 14:30:00 后重试", + }); + + const parsed = executor.parseError({ status: 200 }, bodyText); + expect(parsed.status).toBe(429); + expect(parsed.message).toContain("超出频率限制"); + expect(parsed.resetsAtMs).toBeTruthy(); + expect(typeof parsed.resetsAtMs).toBe("number"); + + // 验证时区解析 (默认 UTC+8) + const expected = new Date("2026-09-28T14:30:00+08:00").getTime(); + expect(parsed.resetsAtMs).toBe(expected); + }); + + it("parses frequency limit text match without code 6004 on codebuddy-intl", () => { + const executor = new CodeBuddyIntlExecutor(); + const bodyText = JSON.stringify({ + code: 11000, + msg: "frequency limit exceeded, please retry after 2026-09-28 12:00:00 UTC+0", + }); + + const parsed = executor.parseError({ status: 400 }, bodyText); + expect(parsed.status).toBe(429); + expect(parsed.message).toContain("frequency limit"); + const expected = new Date("2026-09-28T12:00:00+00:00").getTime(); + expect(parsed.resetsAtMs).toBe(expected); + }); + + it("falls back to super.parseError for unrelated errors", () => { + const executor = new CodeBuddyExecutor(); + const bodyText = JSON.stringify({ + code: 11101, + message: "Non-stream chat request is currently not supported", + }); + + const parsed = executor.parseError({ status: 400 }, bodyText); + expect(parsed.status).toBe(400); + expect(parsed.message).toBe(bodyText); + expect(parsed.resetsAtMs).toBeUndefined(); + }); +});