mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-03 13:52:09 +03:00
fix(sse): friendly 413 message for ChatGPT web payload-too-large (#4080)
Integrated into release/v3.8.28
This commit is contained in:
committed by
GitHub
parent
df2e6ff410
commit
40f811eb7b
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import { BaseExecutor, type ExecuteInput, type ProviderCredentials } from "./base.ts";
|
||||
import { describeChatGptWebHttpError } from "./chatgptWebErrors.ts";
|
||||
import { createHash, randomUUID, randomBytes } from "node:crypto";
|
||||
import {
|
||||
tlsFetchChatGpt,
|
||||
@@ -2742,16 +2743,9 @@ export class ChatGptWebExecutor extends BaseExecutor {
|
||||
// upstream message is much more useful than our wrapper. Goes through
|
||||
// the executor logger so it respects the application's log config.
|
||||
log?.warn?.("CGPT-WEB", `conv ${status}: ${(response.text || "").slice(0, 400)}`);
|
||||
let errMsg = `ChatGPT returned HTTP ${status}`;
|
||||
const errMsg = describeChatGptWebHttpError(status);
|
||||
if (status === 401 || status === 403) {
|
||||
errMsg =
|
||||
"ChatGPT auth failed — session may have expired. Re-paste your __Secure-next-auth.session-token.";
|
||||
tokenCache.delete(cookieKey(cookie));
|
||||
} else if (status === 404) {
|
||||
errMsg =
|
||||
"ChatGPT returned 404 — usually the model is no longer available on this account or the chat-requirements-token expired. Retry will start a fresh conversation.";
|
||||
} else if (status === 429) {
|
||||
errMsg = "ChatGPT rate limited. Wait a moment and retry.";
|
||||
}
|
||||
log?.warn?.("CGPT-WEB", errMsg);
|
||||
return {
|
||||
|
||||
18
open-sse/executors/chatgptWebErrors.ts
Normal file
18
open-sse/executors/chatgptWebErrors.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* User-facing messages for upstream ChatGPT-web HTTP error statuses.
|
||||
*
|
||||
* Pure mapping with no side effects so it can be unit-tested in isolation — the
|
||||
* caller owns any state mutation (e.g. clearing the token cache on 401/403).
|
||||
* Unmapped statuses fall back to the generic `ChatGPT returned HTTP <status>`.
|
||||
*/
|
||||
const CGPT_WEB_HTTP_ERROR_MESSAGES: Record<number, string> = {
|
||||
401: "ChatGPT auth failed — session may have expired. Re-paste your __Secure-next-auth.session-token.",
|
||||
403: "ChatGPT auth failed — session may have expired. Re-paste your __Secure-next-auth.session-token.",
|
||||
404: "ChatGPT returned 404 — usually the model is no longer available on this account or the chat-requirements-token expired. Retry will start a fresh conversation.",
|
||||
413: "ChatGPT returned 413 — the request payload is too large for ChatGPT web's size limit (often hit by agentic clients like Cline/Kilo that send big system prompts and file context). Reduce the context: enable compression, trim the conversation/files, or use a smaller request.",
|
||||
429: "ChatGPT rate limited. Wait a moment and retry.",
|
||||
};
|
||||
|
||||
export function describeChatGptWebHttpError(status: number): string {
|
||||
return CGPT_WEB_HTTP_ERROR_MESSAGES[status] ?? `ChatGPT returned HTTP ${status}`;
|
||||
}
|
||||
@@ -3,6 +3,9 @@ import assert from "node:assert/strict";
|
||||
|
||||
const { ChatGptWebExecutor, __derivePublicBaseUrlForTesting, __resetChatGptWebCachesForTesting } =
|
||||
await import("../../open-sse/executors/chatgpt-web.ts");
|
||||
const { describeChatGptWebHttpError } = await import(
|
||||
"../../open-sse/executors/chatgptWebErrors.ts"
|
||||
);
|
||||
const { getExecutor, hasSpecializedExecutor } = await import("../../open-sse/executors/index.ts");
|
||||
const { __setTlsFetchOverrideForTesting, looksLikeSse, TlsClientUnavailableError } =
|
||||
await import("../../open-sse/services/chatgptTlsClient.ts");
|
||||
@@ -2772,3 +2775,34 @@ test("Image cache: deleting an entry decrements the byte counter", async () => {
|
||||
"bytes credited back on TTL evict"
|
||||
);
|
||||
});
|
||||
|
||||
// ─── describeChatGptWebHttpError ─────────────────────────────────────────────
|
||||
|
||||
test("describeChatGptWebHttpError maps 413 to a payload-too-large message with guidance", () => {
|
||||
const msg = describeChatGptWebHttpError(413);
|
||||
// Must NOT be the cryptic generic — should explain it's a size limit and how to recover.
|
||||
assert.notEqual(
|
||||
msg,
|
||||
"ChatGPT returned HTTP 413",
|
||||
"413 should get a tailored message, not the generic fallback"
|
||||
);
|
||||
assert.match(msg, /413/, "message keeps the status code");
|
||||
assert.match(msg, /too large|payload|size limit/i, "message explains it's a size/payload limit");
|
||||
assert.match(
|
||||
msg,
|
||||
/context|compress/i,
|
||||
"message points the user at reducing context / compression"
|
||||
);
|
||||
});
|
||||
|
||||
test("describeChatGptWebHttpError preserves the existing 401/403/404/429 mappings", () => {
|
||||
assert.match(describeChatGptWebHttpError(401), /session may have expired/i);
|
||||
assert.match(describeChatGptWebHttpError(403), /session may have expired/i);
|
||||
assert.match(describeChatGptWebHttpError(404), /no longer available|fresh conversation/i);
|
||||
assert.match(describeChatGptWebHttpError(429), /rate limited/i);
|
||||
});
|
||||
|
||||
test("describeChatGptWebHttpError falls back to the generic message for unmapped statuses", () => {
|
||||
assert.equal(describeChatGptWebHttpError(500), "ChatGPT returned HTTP 500");
|
||||
assert.equal(describeChatGptWebHttpError(502), "ChatGPT returned HTTP 502");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user