mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
@@ -11,15 +11,41 @@ export const theoldllmProvider: RegistryEntry = {
|
||||
authType: "none",
|
||||
authHeader: "none",
|
||||
defaultContextLength: 200000,
|
||||
// Catalog seed. `passthroughModels: true` means live /api/chatgpt discovery is
|
||||
// authoritative; this list is the curated display/fallback set. The upstream IDs
|
||||
// (GPT_5_*, gemini_*, CLAUDE_4_*, openrouter_*, etc.) mirror the site's free
|
||||
// "chatgpt" tier and MUST match `CHATGPT_UPSTREAM_MODELS` in the executor so they
|
||||
// route unchanged. Legacy alias IDs (GPT_4o, claude_opus_4, …) are kept for
|
||||
// backward compatibility with saved model preferences (mapped in the executor).
|
||||
models: [
|
||||
// ── Current free tier (refreshed for #5181) ──
|
||||
{ id: "GPT_5_4", name: "GPT-5.4 (The Old LLM 🆓)", contextLength: 400000 },
|
||||
{ id: "GPT_5_3", name: "GPT-5.3 (The Old LLM 🆓)", contextLength: 400000 },
|
||||
{ id: "GPT_5_2", name: "GPT-5.2 (The Old LLM 🆓)", contextLength: 400000 },
|
||||
{ id: "GPT_5_1", name: "GPT-5.1 (The Old LLM 🆓)", contextLength: 400000 },
|
||||
{ id: "GPT_5", name: "GPT-5 (The Old LLM 🆓)", contextLength: 400000 },
|
||||
{ id: "GPT_o4_mini", name: "o4-mini (The Old LLM 🆓)" },
|
||||
{ id: "GPT_o3_mini", name: "o3-mini (The Old LLM 🆓)" },
|
||||
{ id: "gemini_3_pro", name: "Gemini 3 Pro (The Old LLM 🆓)", contextLength: 1000000 },
|
||||
{ id: "gemini_2_5_pro", name: "Gemini 2.5 Pro (The Old LLM 🆓)", contextLength: 1000000 },
|
||||
{ id: "gemini_2_0_flash", name: "Gemini 2.0 Flash (The Old LLM 🆓)", contextLength: 1000000 },
|
||||
{ id: "gemini_1_5_flash", name: "Gemini 1.5 Flash (The Old LLM 🆓)", contextLength: 1000000 },
|
||||
{ id: "CLAUDE_4_6_OPUS", name: "Claude 4.6 Opus (The Old LLM 🆓)", contextLength: 200000 },
|
||||
{ id: "CLAUDE_4_6_SONNET", name: "Claude 4.6 Sonnet (The Old LLM 🆓)", contextLength: 200000 },
|
||||
{ id: "CLAUDE_4_5_HAIKU", name: "Claude 4.5 Haiku (The Old LLM 🆓)", contextLength: 200000 },
|
||||
{ id: "openrouter_gpt_4_o", name: "GPT-4o (The Old LLM 🆓)" },
|
||||
{ id: "openrouter_gpt_4_o_mini", name: "GPT-4o mini (The Old LLM 🆓)" },
|
||||
{ id: "openrouter_grok_4", name: "Grok 4 (The Old LLM 🆓)" },
|
||||
{ id: "together_deepseek_v3", name: "DeepSeek V3 (The Old LLM 🆓)" },
|
||||
{ id: "openrouter_deepseek_r1", name: "DeepSeek R1 (The Old LLM 🆓)" },
|
||||
{ id: "sonar-pro", name: "Sonar Pro (The Old LLM 🆓)" },
|
||||
// ── Legacy alias IDs (kept for saved-preference backward compatibility) ──
|
||||
{ id: "GPT_4o", name: "GPT-4o (The Old LLM 🆓)" },
|
||||
{ id: "claude_opus_4", name: "Claude Opus 4 (The Old LLM 🆓)", contextLength: 200000 },
|
||||
{ id: "claude_sonnet_4", name: "Claude Sonnet 4 (The Old LLM 🆓)", contextLength: 200000 },
|
||||
{ id: "claude_haiku_3_5", name: "Claude Haiku 3.5 (The Old LLM 🆓)", contextLength: 200000 },
|
||||
{ id: "deepseek_v4", name: "DeepSeek V4 (The Old LLM 🆓)", contextLength: 200000 },
|
||||
{ id: "gemini_3_flash", name: "Gemini 3 Flash (The Old LLM 🆓)", contextLength: 1000000 },
|
||||
{ id: "gemini_3_pro", name: "Gemini 3 Pro (The Old LLM 🆓)", contextLength: 1000000 },
|
||||
],
|
||||
passthroughModels: true,
|
||||
};
|
||||
|
||||
@@ -39,7 +39,44 @@ const CLAUDE_NAMES: Record<string, string> = {
|
||||
"claude haiku 3.5": "CLAUDE_4_5_HAIKU",
|
||||
};
|
||||
|
||||
function mapModel(model: string): string {
|
||||
// Canonical upstream model IDs served by theoldllm's /api/chatgpt proxy
|
||||
// (apiProvider "chatgpt" in the site's model catalog — the free, reachable tier).
|
||||
// Source: https://theoldllm.vercel.app model list (reported in #5181).
|
||||
// These pass through mapModel() UNCHANGED — critical for non-GPT/Claude models
|
||||
// (Gemini, o-series, Grok, DeepSeek, Sonar) which would otherwise fall through
|
||||
// to the GPT_5_4 default and silently misroute.
|
||||
export const CHATGPT_UPSTREAM_MODELS: ReadonlySet<string> = new Set<string>([
|
||||
"GPT_5_4",
|
||||
"GPT_5_3",
|
||||
"GPT_5_2",
|
||||
"GPT_5_1",
|
||||
"GPT_5",
|
||||
"GPT_o4_mini",
|
||||
"GPT_o3_mini",
|
||||
"gemini_3_pro",
|
||||
"gemini_2_5_pro",
|
||||
"gemini_2_0_flash",
|
||||
"gemini_1_5_flash",
|
||||
"CLAUDE_4_6_OPUS",
|
||||
"CLAUDE_4_6_SONNET",
|
||||
"CLAUDE_4_5_HAIKU",
|
||||
"openrouter_gpt_4_o",
|
||||
"openrouter_gpt_4_o_mini",
|
||||
"openrouter_gpt_4",
|
||||
"openrouter_grok_4",
|
||||
"together_deepseek_r1",
|
||||
"openrouter_deepseek_r1",
|
||||
"together_deepseek_v3",
|
||||
"openrouter_deepseek_v3",
|
||||
"sonar-deep-research",
|
||||
"sonar-pro",
|
||||
"openrouter_web_search",
|
||||
]);
|
||||
|
||||
export function mapModel(model: string): string {
|
||||
const trimmed = model.trim();
|
||||
// Known upstream IDs (from live discovery / refreshed catalog) route as-is.
|
||||
if (CHATGPT_UPSTREAM_MODELS.has(trimmed)) return trimmed;
|
||||
const n = model.toLowerCase().trim();
|
||||
const gptKey = n.replace(/[_\s]+/g, "-");
|
||||
if (GPT_MODELS[gptKey]) return GPT_MODELS[gptKey];
|
||||
|
||||
90
tests/unit/theoldllm-model-refresh-5181.test.ts
Normal file
90
tests/unit/theoldllm-model-refresh-5181.test.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
// Feature guard for #5181 — "Update The Old LLM (Free) model list".
|
||||
//
|
||||
// Two things this proves, both of which fail on the pre-#5181 code:
|
||||
// 1. mapModel() now passes KNOWN upstream IDs through UNCHANGED. Before the fix,
|
||||
// any non-GPT/Claude id (Gemini, o-series, Grok, DeepSeek, Sonar) fell through
|
||||
// to the `return "GPT_5_4"` default and silently misrouted every request.
|
||||
// 2. The registry catalog is refreshed with the current free-tier models while
|
||||
// keeping the legacy alias IDs for saved-preference backward compatibility.
|
||||
const { mapModel, CHATGPT_UPSTREAM_MODELS } = await import(
|
||||
"../../open-sse/executors/theoldllm.ts"
|
||||
);
|
||||
const { getRegistryEntry } = await import("../../open-sse/config/providerRegistry.ts");
|
||||
|
||||
function catalogIds(): string[] {
|
||||
const entry = getRegistryEntry("theoldllm");
|
||||
assert.ok(entry, "theoldllm registry entry must exist");
|
||||
return (entry.models ?? []).map((m) => m.id);
|
||||
}
|
||||
|
||||
test("#5181 known upstream IDs pass through mapModel unchanged (Gemini no longer misroutes to GPT_5_4)", () => {
|
||||
// These are the exact cases the old default clause broke.
|
||||
assert.equal(mapModel("gemini_3_pro"), "gemini_3_pro");
|
||||
assert.equal(mapModel("gemini_2_5_pro"), "gemini_2_5_pro");
|
||||
assert.equal(mapModel("gemini_2_0_flash"), "gemini_2_0_flash");
|
||||
assert.equal(mapModel("openrouter_grok_4"), "openrouter_grok_4");
|
||||
assert.equal(mapModel("together_deepseek_v3"), "together_deepseek_v3");
|
||||
assert.equal(mapModel("sonar-pro"), "sonar-pro");
|
||||
assert.equal(mapModel("GPT_o4_mini"), "GPT_o4_mini");
|
||||
// Every declared upstream id must round-trip through mapModel unchanged.
|
||||
for (const id of CHATGPT_UPSTREAM_MODELS) {
|
||||
assert.equal(mapModel(id), id, `${id} must route unchanged`);
|
||||
}
|
||||
});
|
||||
|
||||
test("#5181 legacy alias IDs still map to available upstream models (backward compatibility)", () => {
|
||||
assert.equal(mapModel("claude_opus_4"), "CLAUDE_4_6_OPUS");
|
||||
assert.equal(mapModel("claude_sonnet_4"), "CLAUDE_4_6_SONNET");
|
||||
assert.equal(mapModel("claude_haiku_3_5"), "CLAUDE_4_5_HAIKU");
|
||||
assert.equal(mapModel("gpt-5.4"), "GPT_5_4");
|
||||
assert.equal(mapModel("gpt-4o"), "GPT_4O");
|
||||
});
|
||||
|
||||
test("#5181 catalog is refreshed with the current free-tier models", () => {
|
||||
const ids = catalogIds();
|
||||
for (const id of [
|
||||
"GPT_5_3",
|
||||
"GPT_5_2",
|
||||
"GPT_5_1",
|
||||
"GPT_5",
|
||||
"GPT_o4_mini",
|
||||
"GPT_o3_mini",
|
||||
"gemini_2_5_pro",
|
||||
"gemini_2_0_flash",
|
||||
"gemini_1_5_flash",
|
||||
"CLAUDE_4_6_OPUS",
|
||||
"CLAUDE_4_6_SONNET",
|
||||
"CLAUDE_4_5_HAIKU",
|
||||
"openrouter_grok_4",
|
||||
"sonar-pro",
|
||||
]) {
|
||||
assert.ok(ids.includes(id), `catalog must include refreshed model ${id}`);
|
||||
}
|
||||
});
|
||||
|
||||
test("#5181 legacy catalog entries are preserved (no breaking removal of saved-preference IDs)", () => {
|
||||
const ids = catalogIds();
|
||||
for (const id of ["GPT_5_4", "GPT_4o", "claude_opus_4", "gemini_3_pro"]) {
|
||||
assert.ok(ids.includes(id), `legacy catalog id ${id} must be preserved`);
|
||||
}
|
||||
});
|
||||
|
||||
test("#5181 every refreshed catalog id routes to a valid upstream model", () => {
|
||||
// No catalog id may fall through to the GPT_5_4 default unless it is genuinely a
|
||||
// GPT-5 alias — Gemini/Grok/DeepSeek/Sonar/Claude entries must resolve to their
|
||||
// own upstream id, not silently collapse onto GPT_5_4.
|
||||
const nonGptExpectations: Record<string, string> = {
|
||||
gemini_2_5_pro: "gemini_2_5_pro",
|
||||
gemini_2_0_flash: "gemini_2_0_flash",
|
||||
gemini_1_5_flash: "gemini_1_5_flash",
|
||||
CLAUDE_4_6_OPUS: "CLAUDE_4_6_OPUS",
|
||||
openrouter_grok_4: "openrouter_grok_4",
|
||||
"sonar-pro": "sonar-pro",
|
||||
};
|
||||
for (const [id, expected] of Object.entries(nonGptExpectations)) {
|
||||
assert.equal(mapModel(id), expected);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user