Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions open-sse/config/providers/registry/chatgpt-web/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ export const chatgpt_webProvider: RegistryEntry = {
authType: "apikey",
authHeader: "cookie",
models: [
{ id: "gpt-5-5-pro", name: "GPT-5.5 Pro" }, // pro tier only, standard effort
{ id: "gpt-5-5-pro-extended", name: "GPT-5.5 Pro Extended" }, // pro tier only, extended effort
{ id: "gpt-5-5-thinking", name: "GPT-5.5 Thinking" }, // plus, pro tier
{ id: "gpt-5-5", name: "GPT-5.5 Instant" }, // free, plus, pro tier
{ id: "gpt-5-4-pro", name: "GPT-5.4 Pro" }, // pro tier only
{ id: "gpt-5-4-thinking", name: "GPT-5.4 Thinking" }, // plus, pro tier
{ id: "gpt-5-4-t-mini", name: "GPT-5.4 Thinking Mini" }, // free-login only
{ id: "gpt-5-3", name: "GPT-5.3 Instant" }, // free, free-login, plus, pro tier
{ id: "gpt-5-3-mini", name: "GPT-5.3 Mini" }, // limit fallback
{ id: "gpt-5.5-pro", name: "GPT-5.5 Pro" }, // pro tier only, standard effort
{ id: "gpt-5.5-pro-extended", name: "GPT-5.5 Pro Extended" }, // pro tier only, extended effort
{ id: "gpt-5.5-thinking", name: "GPT-5.5 Thinking" }, // plus, pro tier
{ id: "gpt-5.5", name: "GPT-5.5 Instant" }, // free, plus, pro tier
{ id: "gpt-5.4-pro", name: "GPT-5.4 Pro" }, // pro tier only
{ id: "gpt-5.4-thinking", name: "GPT-5.4 Thinking" }, // plus, pro tier
{ id: "gpt-5.4-thinking-mini", name: "GPT-5.4 Thinking Mini" }, // free-login only
{ id: "gpt-5.3", name: "GPT-5.3 Instant" }, // free, free-login, plus, pro tier
{ id: "gpt-5.3-mini", name: "GPT-5.3 Mini" }, // limit fallback
{ id: "o3", name: "o3" }, // plus ~ tier
],
};
14 changes: 7 additions & 7 deletions open-sse/executors/chatgpt-web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ function deviceIdFor(cookie: string): string {
return id;
}

// OmniRoute model ID → ChatGPT internal slug. OmniRoute uses dot-form IDs
// (e.g. "gpt-5.3-instant"), ChatGPT's web routes use dash-form
// (e.g. "gpt-5-3-instant"). The slug catalog comes from
// /backend-api/models on a logged-in account; "gpt-5-4-t-mini" is ChatGPT's
// abbreviated slug for "GPT-5.4 Thinking Mini".
// OmniRoute model ID → ChatGPT internal slug. The public ChatGPT Web catalog
// keeps OmniRoute's historical dot-form IDs (e.g. "gpt-5.5-pro"), while
// ChatGPT's backend routes use dash-form slugs (e.g. "gpt-5-5-pro"). The slug
// catalog comes from /backend-api/models on a logged-in account;
// "gpt-5-4-t-mini" is ChatGPT's abbreviated slug for "GPT-5.4 Thinking Mini".
const MODEL_MAP: Record<string, string> = {
// Current ChatGPT Web slugs (these are what the provider catalog exposes).
// ChatGPT backend slugs are also accepted directly for power users / tests.
"gpt-5-5-pro": "gpt-5-5-pro",
"gpt-5-5-pro-extended": "gpt-5-5-pro",
"gpt-5-5-thinking": "gpt-5-5-thinking",
Expand All @@ -96,7 +96,7 @@ const MODEL_MAP: Record<string, string> = {
"gpt-5-3": "gpt-5-3",
"gpt-5-3-mini": "gpt-5-3-mini",

// Legacy OmniRoute dot-form aliases kept for direct provider/model callers.
// Public OmniRoute dot-form ids exposed by the provider catalog.
"gpt-5.5-pro": "gpt-5-5-pro",
"gpt-5.5-pro-extended": "gpt-5-5-pro",
"gpt-5.5-thinking": "gpt-5-5-thinking",
Expand Down
67 changes: 39 additions & 28 deletions tests/unit/chatgpt-web.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,7 @@ test("GPT-5.5 Pro non-streaming: stream_handoff polls conversation detail for fi
try {
const executor = new ChatGptWebExecutor();
const result = await executor.execute({
model: "gpt-5-5-pro-extended",
model: "gpt-5.5-pro-extended",
body: { messages: [{ role: "user", content: "hard problem" }] },
stream: false,
credentials: { apiKey: "cookie-pro-poll" },
Expand Down Expand Up @@ -904,7 +904,7 @@ test("GPT-5.5 Pro streaming: preserves interim reasoning and appends final polle
try {
const executor = new ChatGptWebExecutor();
const result = await executor.execute({
model: "gpt-5-5-pro-extended",
model: "gpt-5.5-pro-extended",
body: { messages: [{ role: "user", content: "hard problem" }], stream: true },
stream: true,
credentials: { apiKey: "cookie-pro-stream" },
Expand Down Expand Up @@ -1271,18 +1271,19 @@ test("Provider registry: chatgpt-web exposes the current ChatGPT Web model catal
assert.equal(entry.authHeader, "cookie");

const ids = (entry.models || []).map((m) => m.id);
// Mirrors /backend-api/models for ChatGPT Web. Retired GPT-5/GPT-5.1
// entries should stay out of this list.
// Public OmniRoute ids stay in historical dot form even though ChatGPT's
// backend routes use dash-form slugs. Retired GPT-5/GPT-5.1 entries should
// stay out of this list.
assert.deepEqual(ids, [
"gpt-5-5-pro",
"gpt-5-5-pro-extended",
"gpt-5-5-thinking",
"gpt-5-5",
"gpt-5-4-pro",
"gpt-5-4-thinking",
"gpt-5-4-t-mini",
"gpt-5-3",
"gpt-5-3-mini",
"gpt-5.5-pro",
"gpt-5.5-pro-extended",
"gpt-5.5-thinking",
"gpt-5.5",
"gpt-5.4-pro",
"gpt-5.4-thinking",
"gpt-5.4-thinking-mini",
"gpt-5.3",
"gpt-5.3-mini",
"o3",
]);
});
Expand All @@ -1292,19 +1293,21 @@ test("Executor MODEL_MAP: OmniRoute IDs translate to ChatGPT backend slugs", asy
const m = installMockFetch();
try {
const cases: Array<[string, string]> = [
["gpt-5-3", "gpt-5-3"],
["gpt-5-5-thinking", "gpt-5-5-thinking"],
["gpt-5-4-t-mini", "gpt-5-4-t-mini"],
["gpt-5-5-pro", "gpt-5-5-pro"],
["gpt-5-5-pro-extended", "gpt-5-5-pro"],
["o3", "o3"],
// Legacy dot-form ids are still accepted for direct provider/model callers.
// Public catalog ids.
["gpt-5.3", "gpt-5-3"],
["gpt-5.5-thinking", "gpt-5-5-thinking"],
["gpt-5.4-thinking-mini", "gpt-5-4-t-mini"],
["gpt-5.5", "gpt-5-5"],
["gpt-5.5-pro", "gpt-5-5-pro"],
["gpt-5.5-pro-extended", "gpt-5-5-pro"],
["gpt-5.4-pro", "gpt-5-4-pro"],
["o3", "o3"],
// Backend dash-form slugs are still accepted for direct provider/model callers.
["gpt-5-3", "gpt-5-3"],
["gpt-5-5-thinking", "gpt-5-5-thinking"],
["gpt-5-4-t-mini", "gpt-5-4-t-mini"],
["gpt-5-5-pro", "gpt-5-5-pro"],
["gpt-5-5-pro-extended", "gpt-5-5-pro"],
];
for (const [omniId, expectedSlug] of cases) {
m.calls.urls.length = 0;
Expand All @@ -1331,6 +1334,18 @@ test("MODEL_MAP drift guard: every advertised catalog id reaches ChatGPT as a ba
reset();
const { getRegistryEntry } = await import("../../open-sse/config/providerRegistry.ts");
const ids = (getRegistryEntry("chatgpt-web")?.models || []).map((m) => m.id);
const expectedSlugById: Record<string, string> = {
"gpt-5.5-pro": "gpt-5-5-pro",
"gpt-5.5-pro-extended": "gpt-5-5-pro",
"gpt-5.5-thinking": "gpt-5-5-thinking",
"gpt-5.5": "gpt-5-5",
"gpt-5.4-pro": "gpt-5-4-pro",
"gpt-5.4-thinking": "gpt-5-4-thinking",
"gpt-5.4-thinking-mini": "gpt-5-4-t-mini",
"gpt-5.3": "gpt-5-3",
"gpt-5.3-mini": "gpt-5-3-mini",
o3: "o3",
};
const m = installMockFetch();
try {
for (const omniId of ids) {
Expand All @@ -1351,11 +1366,7 @@ test("MODEL_MAP drift guard: every advertised catalog id reaches ChatGPT as a ba
!body.model.includes("."),
`${omniId} reached the backend as "${body.model}" (still dot-form)`
);
if (omniId.endsWith("-extended")) {
assert.equal(body.model, "gpt-5-5-pro", `${omniId} should select the base Pro slug`);
} else {
assert.equal(body.model, omniId, `${omniId} should pass through as its backend slug`);
}
assert.equal(body.model, expectedSlugById[omniId], `${omniId} should map to backend slug`);
}
} finally {
m.restore();
Expand All @@ -1370,7 +1381,7 @@ test("GPT-5.5 Pro Extended sends base slug with extended effort and Temporary Ch
try {
const executor = new ChatGptWebExecutor();
const result = await executor.execute({
model: "gpt-5-5-pro-extended",
model: "gpt-5.5-pro-extended",
body: { messages: [{ role: "user", content: "hi" }] },
stream: false,
credentials: { apiKey: "cookie-pro-extended" },
Expand Down Expand Up @@ -1399,7 +1410,7 @@ test("GPT-5.5 Pro standard sends standard effort", async () => {
try {
const executor = new ChatGptWebExecutor();
await executor.execute({
model: "gpt-5-5-pro",
model: "gpt-5.5-pro",
body: { messages: [{ role: "user", content: "hi" }] },
stream: false,
credentials: { apiKey: "cookie-pro-standard" },
Expand All @@ -1422,7 +1433,7 @@ test("GPT-5.5 Pro store:false keeps Temporary Chat enabled for background utilit
try {
const executor = new ChatGptWebExecutor();
const result = await executor.execute({
model: "gpt-5-5-pro-extended",
model: "gpt-5.5-pro-extended",
body: {
store: false,
messages: [
Expand Down
Loading