mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
fix(codex): handle fast tier and capacity SSE (#2452)
- map service_tier=fast to upstream priority; drop unsupported tiers - normalize reasoning effort max to xhigh (codex-only) - convert 200-SSE model-capacity errors into 503 so account fallback rotates - keep normal SSE output intact after peeking Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
committed by
decolua
co-authored by
Cursor
parent
cfbdf06047
commit
0c55d49ab6
@@ -0,0 +1,71 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { CodexExecutor } from "../../open-sse/executors/codex.js";
|
||||
|
||||
function streamFromText(text) {
|
||||
const encoder = new TextEncoder();
|
||||
return new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(encoder.encode(text));
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
describe("Codex fast tier and capacity handling", () => {
|
||||
it("maps Codex fast tier to priority and max reasoning to xhigh", () => {
|
||||
const executor = new CodexExecutor();
|
||||
const body = executor.transformRequest("gpt-5.5", {
|
||||
model: "gpt-5.5",
|
||||
input: "hi",
|
||||
reasoning_effort: "max",
|
||||
service_tier: "fast",
|
||||
}, true, {});
|
||||
|
||||
expect(body.service_tier).toBe("priority");
|
||||
expect(body.reasoning.effort).toBe("xhigh");
|
||||
});
|
||||
|
||||
it("uses ChatGPT workspace header fallback", () => {
|
||||
const executor = new CodexExecutor();
|
||||
const headers = executor.buildHeaders({
|
||||
accessToken: "token",
|
||||
connectionId: "conn_1",
|
||||
providerSpecificData: { chatgptAccountId: "acct_1" },
|
||||
});
|
||||
|
||||
expect(headers["ChatGPT-Account-ID"]).toBe("acct_1");
|
||||
});
|
||||
|
||||
it("classifies 200-SSE model capacity as account fallback", async () => {
|
||||
const executor = new CodexExecutor();
|
||||
const response = new Response(streamFromText([
|
||||
"event: error",
|
||||
'data: {"error":{"message":"Selected model is at capacity. Please try a different model."}}',
|
||||
"",
|
||||
].join("\n")), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "text/event-stream" },
|
||||
});
|
||||
|
||||
const peek = await executor._peekSseTransientError(response);
|
||||
expect(peek.accountFallback).toBe(true);
|
||||
expect(peek.message).toBe("Selected model is at capacity. Please try a different model.");
|
||||
});
|
||||
|
||||
it("reassembles normal SSE after peeking", async () => {
|
||||
const executor = new CodexExecutor();
|
||||
const text = [
|
||||
"event: response.output_text.delta",
|
||||
'data: {"type":"response.output_text.delta","delta":"OK"}',
|
||||
"",
|
||||
].join("\n");
|
||||
const response = new Response(streamFromText(text), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "text/event-stream" },
|
||||
});
|
||||
|
||||
const peek = await executor._peekSseTransientError(response);
|
||||
expect(peek.matched).toBeNull();
|
||||
await expect(new Response(peek.replacementBody).text()).resolves.toBe(text);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user