Files
OmniRoute/tests/unit/t28-model-catalog-updates.test.ts
backryun 888c872459 refactor(antigravity): align official clients and callable catalog (#8013)
* fix(antigravity): preserve protocol fidelity and fail closed

* chore: add PR-numbered changelog fragment

* test: split oversized Antigravity suites

* refactor(antigravity): align official IDE and CLI identities

* fix(antigravity): align catalog with callable models

* test(antigravity): update 2 test files to renamed version-cache API (#8013 fix)

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: nguyenha935 <208228297+nguyenha935@users.noreply.github.com>
Co-authored-by: backryun <backryun@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: nguyenha935 <nguyenha935@users.noreply.github.com>
Co-authored-by: Probe Test <probe@example.com>
2026-07-22 20:41:19 -03:00

152 lines
7.0 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import { getModelInfoCore } from "../../open-sse/services/model.ts";
import { REGISTRY } from "../../open-sse/config/providerRegistry.ts";
import { FREE_MODEL_BUDGETS } from "../../open-sse/config/freeModelCatalog.data.ts";
import { getStaticModelsForProvider } from "../../src/lib/providers/staticModels.ts";
test("T28: gemini AI Studio catalog includes current preview models", () => {
// Gemini (AI Studio) carries a small hardcoded fallback for first-run UX when no
// API key has been added yet; the full catalog is populated by API sync via
// /api/providers/:id/models with pageSize=1000 once a key exists.
const geminiIds = REGISTRY.gemini.models.map((m) => m.id);
assert.ok(geminiIds.includes("gemini-3.1-pro-preview"));
assert.ok(geminiIds.includes("gemini-3-flash-preview"));
assert.ok(geminiIds.includes("gemini-3.1-flash-lite"));
assert.ok(geminiIds.includes("gemini-3.5-flash"));
assert.ok(geminiIds.includes("gemini-2.5-flash"));
assert.ok(geminiIds.includes("gemini-2.5-pro"));
assert.equal(geminiIds[0], "gemini-3.1-pro-preview", "preserve the existing Gemini default");
});
test("T28: antigravity static catalog exposes only callable Gemini tier IDs", () => {
const staticIds = (getStaticModelsForProvider("antigravity") || []).map((m) => m.id);
assert.ok(!staticIds.includes("gemini-3-pro-preview"));
assert.ok(staticIds.includes("gemini-3.6-flash-high"));
assert.ok(staticIds.includes("gemini-3.6-flash-medium"));
assert.ok(staticIds.includes("gemini-3.6-flash-low"));
assert.ok(staticIds.includes("gemini-3.5-flash-extra-low"));
assert.ok(staticIds.includes("gemini-3.5-flash-low"));
assert.ok(staticIds.includes("gemini-3-flash-agent"));
assert.ok(!staticIds.includes("gemini-3.5-flash-medium"));
assert.ok(!staticIds.includes("gemini-3.5-flash-high"));
assert.ok(staticIds.includes("gemini-3.1-pro-low"));
assert.ok(!staticIds.includes("gemini-3.1-pro-high"));
assert.ok(staticIds.includes("gemini-pro-agent"));
// Legacy aliases that were never client-visible stay absent.
assert.ok(!staticIds.includes("gemini-3-pro-high"));
assert.ok(!staticIds.includes("gemini-3-flash-preview"));
assert.ok(!staticIds.includes("gemini-claude-sonnet-4-5"));
assert.ok(!staticIds.includes("gemini-claude-sonnet-4-5-thinking"));
assert.ok(!staticIds.includes("gemini-claude-opus-4-5-thinking"));
});
test("T28: agy free-model metadata labels upstream Gemini 3.6 tier IDs", () => {
const flashNames = Object.fromEntries(
FREE_MODEL_BUDGETS.filter(
(entry) =>
entry.provider === "agy" &&
["gemini-3.6-flash-low", "gemini-3.6-flash-medium", "gemini-3.6-flash-high"].includes(
entry.modelId
)
).map((entry) => [entry.modelId, entry.displayName])
);
assert.deepEqual(flashNames, {
"gemini-3.6-flash-low": "Gemini 3.6 Flash (Low)",
"gemini-3.6-flash-medium": "Gemini 3.6 Flash (Medium)",
"gemini-3.6-flash-high": "Gemini 3.6 Flash (High)",
});
});
test("T28: github registry exposes Gemini 3.1 Pro Preview and keeps legacy alias compatibility", async () => {
const githubIds = REGISTRY.github.models.map((m) => m.id);
assert.ok(githubIds.includes("gemini-3.1-pro-preview"));
const canonical = await getModelInfoCore("gh/gemini-3.1-pro-preview", {});
assert.equal(canonical.provider, "github");
assert.equal(canonical.model, "gemini-3.1-pro-preview");
const legacy = await getModelInfoCore("gh/gemini-3-pro", {});
assert.equal(legacy.provider, "github");
assert.equal(legacy.model, "gemini-3.1-pro-preview");
});
test("T28: qwen OAuth registry entry is retired; qwen-web keeps the native chat.qwen.ai URL", () => {
assert.equal(REGISTRY.qwen, undefined);
assert.equal(REGISTRY["qwen-web"].baseUrl, "https://chat.qwen.ai/api/v2/chat/completions");
});
test("T28: lmarena registry seeds Direct-chat Text/search; image models in IMAGE_PROVIDERS", async () => {
const { IMAGE_PROVIDERS } = await import("../../open-sse/config/imageRegistry.ts");
const lmarenaIds = REGISTRY.lmarena.models.map((m) => m.id);
const imageIds = (IMAGE_PROVIDERS.lmarena?.models || []).map((m: { id: string }) => m.id);
// Chat registry: Text + Search only (not Image thrash)
assert.ok(lmarenaIds.length >= 40 && lmarenaIds.length < 60);
assert.ok(lmarenaIds.includes("gemini-3.1-pro-preview"));
assert.ok(lmarenaIds.includes("gemini-3.5-flash-high"));
assert.ok(lmarenaIds.includes("claude-sonnet-5"));
assert.ok(!lmarenaIds.includes("flux-2-pro"), "image models must not live in chat registry");
// Image registry: Direct-chat Image category
assert.ok(imageIds.length >= 20);
assert.ok(imageIds.includes("flux-2-pro") || imageIds.includes("flux-2-dev"));
assert.ok(IMAGE_PROVIDERS.lmarena, "lmarena must be an IMAGE_PROVIDERS key");
// publicName collision → category-suffixed catalog id (chat side)
assert.ok(lmarenaIds.includes("grok-4.3/text") || lmarenaIds.includes("grok-4.3/search"));
const resolved = await getModelInfoCore("lma/gemini-3.1-pro-preview", {});
assert.equal(resolved.provider, "lmarena");
assert.equal(resolved.model, "gemini-3.1-pro-preview");
});
test("T28: vertex catalog includes partner models when vertex executor is available", () => {
const vertexIds = REGISTRY.vertex.models.map((m) => m.id);
assert.ok(vertexIds.includes("DeepSeek-V4-Flash"));
assert.ok(vertexIds.includes("DeepSeek-V4-Pro"));
assert.ok(vertexIds.includes("Qwen3.6-35B-A3B"));
assert.ok(vertexIds.includes("GLM-5.1-FP8"));
});
test("T28: volcengine (Ark) catalog includes DeepSeek V4 models", () => {
const volcengineIds = REGISTRY.volcengine.models.map((m) => m.id);
assert.ok(
volcengineIds.includes("DeepSeek-V4-Flash"),
"volcengine Ark must list DeepSeek-V4-Flash"
);
assert.ok(volcengineIds.includes("DeepSeek-V4-Pro"), "volcengine Ark must list DeepSeek-V4-Pro");
// Existing models must still be present
assert.ok(volcengineIds.includes("deepseek-v3-2-251201"));
assert.ok(volcengineIds.includes("kimi-k2-5-260127"));
assert.ok(volcengineIds.includes("glm-4-7-251222"));
});
test("T28: new catalog models resolve through getModelInfoCore", async () => {
const cerebrasGemma = await getModelInfoCore("cerebras/gemma-4-31b", {});
assert.equal(cerebrasGemma.provider, "cerebras");
assert.equal(cerebrasGemma.model, "gemma-4-31b");
const minimax = await getModelInfoCore("minimax/MiniMax-M2.7", {});
assert.equal(minimax.provider, "minimax");
assert.equal(minimax.model, "MiniMax-M2.7");
const flashLite = await getModelInfoCore("gemini/gemini-3.1-flash-lite-preview", {});
assert.equal(flashLite.provider, "gemini");
assert.equal(flashLite.model, "gemini-3.1-flash-lite-preview");
const flashPreview = await getModelInfoCore("gemini/gemini-3-flash-preview", {});
assert.equal(flashPreview.provider, "gemini");
assert.equal(flashPreview.model, "gemini-3-flash-preview");
const vertexPartner = await getModelInfoCore("vertex/Qwen3.6-35B-A3B", {});
assert.equal(vertexPartner.provider, "vertex");
assert.equal(vertexPartner.model, "Qwen3.6-35B-A3B");
});