mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-25 16:42:16 +03:00
Compare commits
2 Commits
release/v3
...
chore/reco
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fec7f40fd | ||
|
|
fa7ccaf679 |
@@ -12,5 +12,15 @@
|
||||
export const OPENCODE_ZEN_GO_SHARED_MODELS = Object.freeze([
|
||||
{ id: "kimi-k2.7-code", name: "Kimi K2.7 Code" },
|
||||
{ id: "qwen3.5-plus", name: "Qwen3.5 Plus", targetFormat: "claude", supportsVision: false },
|
||||
{ id: "qwen3.6-plus", name: "Qwen3.6 Plus", targetFormat: "claude", supportsVision: false },
|
||||
{
|
||||
id: "qwen3.6-plus",
|
||||
name: "Qwen3.6 Plus",
|
||||
targetFormat: "claude",
|
||||
supportsVision: false,
|
||||
// #10788: effort-tier aliases exist as explicit registry rows; declare the
|
||||
// vocabulary on the shared base row so variant synthesis and the sanitizer
|
||||
// agree on it for both opencode-go and opencode-zen.
|
||||
supportsReasoning: true,
|
||||
supportedThinkingEfforts: ["high", "max"],
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -18,7 +18,17 @@ export const nvidiaProvider: RegistryEntry = {
|
||||
passthroughModels: true,
|
||||
models: [
|
||||
// #6108: z-ai/glm-5.1 EOL'd 2026-07-02 (direct probe returns 410) — dropped.
|
||||
{ id: "z-ai/glm-5.2", name: "GLM 5.2" },
|
||||
// #10788: NVIDIA's hosted GLM-5.2 exposes a BINARY thinking switch
|
||||
// (chat_template_kwargs.enable_thinking), not effort tiers — see
|
||||
// mapNvidiaGlm52ReasoningParams. Declaring an empty tier list keeps the
|
||||
// catalog from synthesizing unresolvable -low/-high/-max variant ids while
|
||||
// still marking the model reasoning-capable.
|
||||
{
|
||||
id: "z-ai/glm-5.2",
|
||||
name: "GLM 5.2",
|
||||
supportsReasoning: true,
|
||||
supportedThinkingEfforts: [],
|
||||
},
|
||||
// #3329/#6108: minimaxai/minimax-m3 stays excluded from the nvidia tier — it
|
||||
// still 404s here for most callers; the single 200 probe in #6108 was not
|
||||
// reproducible enough to override the #3329 guard. Re-add only once NVIDIA
|
||||
|
||||
@@ -19,9 +19,15 @@ export const opencode_goProvider: RegistryEntry = {
|
||||
// `kimi-k2.7-code` (the live API rejects the plain `kimi-k2.7` alias for
|
||||
// `/chat/completions`, even though the docs config example uses it).
|
||||
// GLM-5.2 — base model + effort-tier aliases (#6922).
|
||||
// OpencodeExecutor rewrites the alias to the canonical id and injects
|
||||
// reasoning_effort, mirroring the deepseek-v4-pro-* pattern.
|
||||
{ id: "glm-5.2", name: "GLM-5.2", supportsReasoning: true },
|
||||
// #10788: the tier vocabulary is declared on the base row so the catalog's
|
||||
// variant synthesis (#9485) and the effort sanitizer share one source of
|
||||
// truth with OpencodeExecutor's EFFORT_TIERS.
|
||||
{
|
||||
id: "glm-5.2",
|
||||
name: "GLM-5.2",
|
||||
supportsReasoning: true,
|
||||
supportedThinkingEfforts: ["high", "max"],
|
||||
},
|
||||
{ id: "glm-5.2-high", name: "GLM-5.2 (high effort)", supportsReasoning: true },
|
||||
{ id: "glm-5.2-max", name: "GLM-5.2 (max effort)", supportsReasoning: true },
|
||||
|
||||
@@ -34,11 +40,16 @@ export const opencode_goProvider: RegistryEntry = {
|
||||
{ id: "kimi-k2.6", name: "Kimi K2.6" },
|
||||
{ id: "kimi-k2.5", name: "Kimi K2.5" },
|
||||
// #8353: Kimi K3 base + max-effort alias from the OpenCode Go registry.
|
||||
{ id: "kimi-k3", name: "Kimi K3", supportsReasoning: true },
|
||||
{ id: "kimi-k3", name: "Kimi K3", supportsReasoning: true, supportedThinkingEfforts: ["max"] },
|
||||
{ id: "kimi-k3-max", name: "Kimi K3 (max effort)", supportsReasoning: true },
|
||||
// MiMo-V2.5 — base model + effort-tier aliases (#6922).
|
||||
{ id: "mimo-v2.5-pro", name: "MiMo-V2.5-Pro", supportsReasoning: true },
|
||||
{ id: "mimo-v2.5", name: "MiMo-V2.5", supportsReasoning: true },
|
||||
{
|
||||
id: "mimo-v2.5",
|
||||
name: "MiMo-V2.5",
|
||||
supportsReasoning: true,
|
||||
supportedThinkingEfforts: ["high", "max"],
|
||||
},
|
||||
{ id: "mimo-v2.5-high", name: "MiMo-V2.5 (high effort)", supportsReasoning: true },
|
||||
{ id: "mimo-v2.5-max", name: "MiMo-V2.5 (max effort)", supportsReasoning: true },
|
||||
// #3110: MiniMax M3 via OpenCode Go tier
|
||||
@@ -59,7 +70,14 @@ export const opencode_goProvider: RegistryEntry = {
|
||||
// so combo routing skips them when the request contains image blocks,
|
||||
// preventing image content from reaching a vision-incapable upstream.
|
||||
// #8353: effort-tier aliases from the OpenCode Go registry.
|
||||
{ id: "qwen3.7-max", name: "Qwen3.7 Max", targetFormat: "claude", supportsVision: false },
|
||||
{
|
||||
id: "qwen3.7-max",
|
||||
name: "Qwen3.7 Max",
|
||||
targetFormat: "claude",
|
||||
supportsVision: false,
|
||||
supportsReasoning: true,
|
||||
supportedThinkingEfforts: ["high", "max"],
|
||||
},
|
||||
{
|
||||
id: "qwen3.7-max-high",
|
||||
name: "Qwen3.7 Max (high effort)",
|
||||
@@ -79,6 +97,8 @@ export const opencode_goProvider: RegistryEntry = {
|
||||
name: "Qwen3.7 Plus",
|
||||
targetFormat: "claude",
|
||||
supportsVision: false,
|
||||
supportsReasoning: true,
|
||||
supportedThinkingEfforts: ["high", "max"],
|
||||
},
|
||||
{
|
||||
id: "qwen3.7-plus-high",
|
||||
@@ -111,7 +131,13 @@ export const opencode_goProvider: RegistryEntry = {
|
||||
supportsReasoning: true,
|
||||
},
|
||||
// #8353: hy3 is the Go-tier base id (distinct from hy3-preview / hy3-free).
|
||||
{ id: "hy3", name: "Hunyuan3", contextLength: 256000, supportsReasoning: true },
|
||||
{
|
||||
id: "hy3",
|
||||
name: "Hunyuan3",
|
||||
contextLength: 256000,
|
||||
supportsReasoning: true,
|
||||
supportedThinkingEfforts: ["none", "low", "high"],
|
||||
},
|
||||
{
|
||||
id: "hy3-none",
|
||||
name: "Hunyuan3 (none effort)",
|
||||
@@ -201,7 +227,12 @@ export const opencode_goProvider: RegistryEntry = {
|
||||
targetFormat: "openai-responses",
|
||||
},
|
||||
// #8353: Grok 4.5 + effort tiers from the OpenCode Go registry.
|
||||
{ id: "grok-4.5", name: "Grok 4.5", supportsReasoning: true },
|
||||
{
|
||||
id: "grok-4.5",
|
||||
name: "Grok 4.5",
|
||||
supportsReasoning: true,
|
||||
supportedThinkingEfforts: ["low", "medium", "high"],
|
||||
},
|
||||
{ id: "grok-4.5-low", name: "Grok 4.5 (low effort)", supportsReasoning: true },
|
||||
{ id: "grok-4.5-medium", name: "Grok 4.5 (medium effort)", supportsReasoning: true },
|
||||
{ id: "grok-4.5-high", name: "Grok 4.5 (high effort)", supportsReasoning: true },
|
||||
|
||||
@@ -79,18 +79,35 @@ export const opencode_zenProvider: RegistryEntry = {
|
||||
},
|
||||
|
||||
// ── DeepSeek ────────────────────────────────────────────────
|
||||
{ id: "deepseek-v4-pro", name: "DeepSeek V4 Pro" },
|
||||
{ id: "deepseek-v4-flash", name: "DeepSeek V4 Flash" },
|
||||
// #10788: same tier vocabulary as opencode-go's DeepSeek rows — the Zen
|
||||
// upstream accepts the identical effort set on these models.
|
||||
{
|
||||
id: "deepseek-v4-pro",
|
||||
name: "DeepSeek V4 Pro",
|
||||
supportsReasoning: true,
|
||||
supportedThinkingEfforts: ["none", "low", "high", "max"],
|
||||
},
|
||||
{
|
||||
id: "deepseek-v4-flash",
|
||||
name: "DeepSeek V4 Flash",
|
||||
supportsReasoning: true,
|
||||
supportedThinkingEfforts: ["none", "low", "high", "max"],
|
||||
},
|
||||
|
||||
// ── GLM / Z.AI ─────────────────────────────────────────────
|
||||
{ id: "glm-5.2", name: "GLM-5.2" },
|
||||
{
|
||||
id: "glm-5.2",
|
||||
name: "GLM-5.2",
|
||||
supportsReasoning: true,
|
||||
supportedThinkingEfforts: ["high", "max"],
|
||||
},
|
||||
|
||||
// ── MiniMax ────────────────────────────────────────────────
|
||||
// #3110: MiniMax M3 — frontier coding model with 1M context
|
||||
{ id: "minimax-m3", name: "MiniMax M3", contextLength: 1048576, supportsVision: true },
|
||||
|
||||
// ── Kimi / Moonshot ────────────────────────────────────────
|
||||
{ id: "kimi-k3", name: "Kimi K3" },
|
||||
{ id: "kimi-k3", name: "Kimi K3", supportsReasoning: true, supportedThinkingEfforts: ["max"] },
|
||||
// kimi-k2.7-code declared identically on opencode-go — see OPENCODE_ZEN_GO_SHARED_MODELS.
|
||||
|
||||
// ── Qwen ───────────────────────────────────────────────────
|
||||
|
||||
@@ -450,7 +450,10 @@ export class OpencodeExecutor extends BaseExecutor {
|
||||
// 200s ("Provider returned empty content"). Raise tiny budgets to the
|
||||
// floor before dispatch (see MUSE_SPARK_MIN_OUTPUT_TOKENS).
|
||||
if (input.body && typeof input.body === "object" && !Array.isArray(input.body)) {
|
||||
applyMuseSparkMinOutputTokens(String(input.model ?? ""), input.body as Record<string, unknown>);
|
||||
applyMuseSparkMinOutputTokens(
|
||||
String(input.model ?? ""),
|
||||
input.body as Record<string, unknown>
|
||||
);
|
||||
}
|
||||
|
||||
this.syncAccountsFromCredentials(input.credentials);
|
||||
@@ -630,10 +633,7 @@ export class OpencodeExecutor extends BaseExecutor {
|
||||
}
|
||||
|
||||
// All accounts returned 429 (or errored) — surface the last response.
|
||||
return this.normalizeMuseSparkResponse(
|
||||
input,
|
||||
lastResult ?? (await super.execute(input))
|
||||
);
|
||||
return this.normalizeMuseSparkResponse(input, lastResult ?? (await super.execute(input)));
|
||||
} finally {
|
||||
this._requestFormat = null;
|
||||
}
|
||||
@@ -842,10 +842,21 @@ export class OpencodeExecutor extends BaseExecutor {
|
||||
const mb = modifiedBody as Record<string, unknown>;
|
||||
const parsed = parseEffortLevel(model);
|
||||
if (parsed) {
|
||||
mb.model = parsed.baseModel;
|
||||
if (mb.reasoning_effort === undefined) {
|
||||
mb.reasoning_effort = parsed.effort;
|
||||
const deepseekFamily =
|
||||
parsed.baseModel === "deepseek-v4-pro" || parsed.baseModel === "deepseek-v4-flash";
|
||||
if (deepseekFamily) {
|
||||
// DeepSeek via opencode-go proxies the native DeepSeek contract, which
|
||||
// accepts a flat reasoning_effort field (#4647).
|
||||
mb.model = parsed.baseModel;
|
||||
if (mb.reasoning_effort === undefined) {
|
||||
mb.reasoning_effort = parsed.effort;
|
||||
}
|
||||
}
|
||||
// #10788: every other family's ONLY native effort mechanism is the
|
||||
// -<tier> suffix in the model id itself (the ids `opencode models
|
||||
// opencode-go --verbose` lists). The opencode-go ChatCompletionRequest
|
||||
// carries no flat reasoning_effort field, so rewriting to the base id
|
||||
// silently dropped the tier — forward the aliased id verbatim instead.
|
||||
}
|
||||
}
|
||||
// #1543 / upstream PR #1099: thinking-mode upstreams routed through OpenCode
|
||||
|
||||
@@ -179,7 +179,12 @@ test("Codex Responses routing keeps reasoning effort while dropping GPT-only ver
|
||||
credentials: null,
|
||||
});
|
||||
|
||||
assert.equal(outbound.reasoning_effort, "low");
|
||||
// #11409 reconciliation: opencode-go advertises ONLY glm-5.2-high/-max variants
|
||||
// (providerRegistry go/index.ts), so the #11295/#11305 nearest-tier capability
|
||||
// clamp legitimately upgrades the unsupported "low" request to the smallest
|
||||
// declared tier ("high"). The #7533 no-mutation guarantee still holds for any
|
||||
// tier the resolved target actually declares (covered by the z.ai/Claude cases).
|
||||
assert.equal(outbound.reasoning_effort, "high");
|
||||
assert.equal(outbound.verbosity, undefined);
|
||||
});
|
||||
|
||||
|
||||
@@ -96,35 +96,43 @@ test("#6922 parseEffortLevel: base model without tier → null", () => {
|
||||
assert.strictEqual(parseEffortLevel("glm-5.2"), null);
|
||||
});
|
||||
|
||||
// ─── transformRequest: end-to-end model-id rewrite + reasoning_effort inject ──
|
||||
// ─── transformRequest: #6922 wiring, updated by #10788 ─────────────────────
|
||||
//
|
||||
// parseEffortLevel is a pure function, but the actual bug (#6922) surfaces
|
||||
// through OpencodeExecutor.transformRequest — the caller that rewrites the
|
||||
// outbound model id and injects reasoning_effort. These tests exercise that
|
||||
// public entry point directly so a broken wiring (e.g. parseEffortLevel
|
||||
// correct but never called, or its result dropped) would fail here even if
|
||||
// the parseEffortLevel-only tests above stayed green.
|
||||
// parseEffortLevel is a pure function, but the original bug (#6922) surfaces
|
||||
// through OpencodeExecutor.transformRequest. Since #10788, glm-5.2 / mimo-v2.5
|
||||
// (non-DeepSeek families) forward the effort-suffixed alias VERBATIM — the
|
||||
// suffix is their only native effort mechanism and opencode-go has no flat
|
||||
// reasoning_effort field to receive a rewritten tier. Only DeepSeek V4 keeps
|
||||
// the base-rewrite + field-injection contract.
|
||||
|
||||
const CREDENTIALS = { apiKey: "k" } as Record<string, unknown>;
|
||||
|
||||
test("#6922 transformRequest: glm-5.2-high → model rewritten to glm-5.2, reasoning_effort injected", () => {
|
||||
test("#6922/#10788 transformRequest: glm-5.2-high forwards the alias verbatim", () => {
|
||||
const executor = new OpencodeExecutor("opencode-go");
|
||||
const body = { model: "glm-5.2-high", messages: [{ role: "user", content: "hi" }] };
|
||||
|
||||
const out = executor.transformRequest("glm-5.2-high", body, true, CREDENTIALS);
|
||||
|
||||
assert.equal(out.model, "glm-5.2", "model id must be rewritten to the base id");
|
||||
assert.equal(out.reasoning_effort, "high", "reasoning_effort must be injected from the alias");
|
||||
assert.equal(out.model, "glm-5.2-high", "alias id must reach the wire untouched");
|
||||
assert.equal(
|
||||
out.reasoning_effort,
|
||||
undefined,
|
||||
"no flat reasoning_effort may be injected for non-DeepSeek families"
|
||||
);
|
||||
});
|
||||
|
||||
test("#6922 transformRequest: mimo-v2.5-max → model rewritten to mimo-v2.5, reasoning_effort injected", () => {
|
||||
test("#6922/#10788 transformRequest: mimo-v2.5-max forwards the alias verbatim", () => {
|
||||
const executor = new OpencodeExecutor("opencode-go");
|
||||
const body = { model: "mimo-v2.5-max", messages: [{ role: "user", content: "hi" }] };
|
||||
|
||||
const out = executor.transformRequest("mimo-v2.5-max", body, true, CREDENTIALS);
|
||||
|
||||
assert.equal(out.model, "mimo-v2.5", "model id must be rewritten to the base id");
|
||||
assert.equal(out.reasoning_effort, "max", "reasoning_effort must be injected from the alias");
|
||||
assert.equal(out.model, "mimo-v2.5-max", "alias id must reach the wire untouched");
|
||||
assert.equal(
|
||||
out.reasoning_effort,
|
||||
undefined,
|
||||
"no flat reasoning_effort may be injected for non-DeepSeek families"
|
||||
);
|
||||
});
|
||||
|
||||
test("#6922 transformRequest: does not clobber an already-set reasoning_effort", () => {
|
||||
@@ -137,7 +145,7 @@ test("#6922 transformRequest: does not clobber an already-set reasoning_effort",
|
||||
|
||||
const out = executor.transformRequest("glm-5.2-high", body, true, CREDENTIALS);
|
||||
|
||||
assert.equal(out.model, "glm-5.2", "model id is still rewritten to the base id");
|
||||
assert.equal(out.model, "glm-5.2-high", "non-DeepSeek alias id is left untouched");
|
||||
assert.equal(
|
||||
out.reasoning_effort,
|
||||
"caller-supplied",
|
||||
|
||||
@@ -27,7 +27,15 @@ const { parseEffortLevel, OpencodeExecutor } =
|
||||
const { REGISTRY } = (await import("../../open-sse/config/providerRegistry.ts")) as {
|
||||
REGISTRY: Record<
|
||||
string,
|
||||
{ models?: Array<{ id: string; name?: string; targetFormat?: string }> }
|
||||
{
|
||||
models?: Array<{
|
||||
id: string;
|
||||
name?: string;
|
||||
targetFormat?: string;
|
||||
supportsReasoning?: boolean;
|
||||
supportedThinkingEfforts?: string[];
|
||||
}>;
|
||||
}
|
||||
>;
|
||||
};
|
||||
|
||||
@@ -189,29 +197,46 @@ test("#8353 parseEffortLevel: MiniMax M3 has no effort-tier aliases", () => {
|
||||
|
||||
const CREDENTIALS = { apiKey: "k" } as Record<string, unknown>;
|
||||
|
||||
// #10788: DeepSeek V4 keeps the base-rewrite + reasoning_effort injection (the
|
||||
// opencode-go DeepSeek contract accepts the flat field); every other family
|
||||
// must receive the effort-suffixed alias VERBATIM, because the suffix is their
|
||||
// only native effort mechanism and opencode-go has no flat reasoning_effort.
|
||||
const TRANSFORM_SAMPLES = [
|
||||
{ alias: "deepseek-v4-flash-low", base: "deepseek-v4-flash", effort: "low" },
|
||||
{ alias: "grok-4.5-medium", base: "grok-4.5", effort: "medium" },
|
||||
{ alias: "hy3-none", base: "hy3", effort: "none" },
|
||||
{ alias: "kimi-k3-max", base: "kimi-k3", effort: "max" },
|
||||
{ alias: "qwen3.7-plus-max", base: "qwen3.7-plus", effort: "max" },
|
||||
{ alias: "qwen3.7-max-high", base: "qwen3.7-max", effort: "high" },
|
||||
{
|
||||
alias: "deepseek-v4-flash-low",
|
||||
wireModel: "deepseek-v4-flash",
|
||||
effort: "low" as const,
|
||||
note: "DeepSeek rewrites to base + reasoning_effort (#4647)",
|
||||
},
|
||||
{ alias: "grok-4.5-medium", wireModel: "grok-4.5-medium", effort: null },
|
||||
{ alias: "hy3-none", wireModel: "hy3-none", effort: null },
|
||||
{ alias: "kimi-k3-max", wireModel: "kimi-k3-max", effort: null },
|
||||
{ alias: "qwen3.7-plus-max", wireModel: "qwen3.7-plus-max", effort: null },
|
||||
{ alias: "qwen3.7-max-high", wireModel: "qwen3.7-max-high", effort: null },
|
||||
{
|
||||
alias: "muse-spark-1.2-contributor-xhigh",
|
||||
base: "muse-spark-1.2-contributor",
|
||||
effort: "xhigh",
|
||||
wireModel: "muse-spark-1.2-contributor-xhigh",
|
||||
effort: null,
|
||||
},
|
||||
] as const;
|
||||
|
||||
for (const { alias, base, effort } of TRANSFORM_SAMPLES) {
|
||||
test(`#8353 transformRequest: ${alias} → model=${base}, reasoning_effort=${effort}`, () => {
|
||||
for (const { alias, wireModel, effort, note } of TRANSFORM_SAMPLES) {
|
||||
test(`#8353/#10788 transformRequest: ${alias} → model=${wireModel}`, () => {
|
||||
const executor = new OpencodeExecutor("opencode-go");
|
||||
const body = { model: alias, messages: [{ role: "user", content: "hi" }] };
|
||||
|
||||
const out = executor.transformRequest(alias, body, true, CREDENTIALS);
|
||||
|
||||
assert.equal(out.model, base, "model id must be rewritten to the base id");
|
||||
assert.equal(out.reasoning_effort, effort, "reasoning_effort must be injected from the alias");
|
||||
assert.equal(out.model, wireModel);
|
||||
if (effort === null) {
|
||||
assert.equal(
|
||||
out.reasoning_effort,
|
||||
undefined,
|
||||
"non-DeepSeek families must not receive a flat reasoning_effort field"
|
||||
);
|
||||
} else {
|
||||
assert.equal(out.reasoning_effort, effort, note);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -228,3 +253,42 @@ test("#8353 transformRequest: does not clobber an already-set reasoning_effort",
|
||||
assert.equal(out.model, "deepseek-v4-flash");
|
||||
assert.equal(out.reasoning_effort, "caller-supplied");
|
||||
});
|
||||
|
||||
// ─── #10788: base-model tier declarations match the executor vocabulary ────
|
||||
|
||||
test("#10788 registry base rows declare the same tiers EFFORT_TIERS parses", () => {
|
||||
const expectedTiers: Record<string, string[]> = {
|
||||
"glm-5.2": ["high", "max"],
|
||||
"mimo-v2.5": ["high", "max"],
|
||||
"grok-4.5": ["low", "medium", "high"],
|
||||
hy3: ["none", "low", "high"],
|
||||
"kimi-k3": ["max"],
|
||||
"qwen3.6-plus": ["high", "max"],
|
||||
"qwen3.7-max": ["high", "max"],
|
||||
"qwen3.7-plus": ["high", "max"],
|
||||
};
|
||||
for (const providerId of ["opencode-go", "opencode-zen"]) {
|
||||
const entry = REGISTRY[providerId];
|
||||
assert.ok(entry?.models, `${providerId} must expose models`);
|
||||
for (const [base, tiers] of Object.entries(expectedTiers)) {
|
||||
if (providerId === "opencode-zen" && !entry.models.some((m) => m.id === base)) continue;
|
||||
const row = entry.models.find((m) => m.id === base);
|
||||
assert.ok(row, `${providerId} must declare base model ${base}`);
|
||||
assert.ok(row.supportsReasoning, `${providerId}/${base} must be reasoning-capable`);
|
||||
assert.deepEqual(
|
||||
[...(row.supportedThinkingEfforts ?? [])].sort(),
|
||||
[...tiers].sort(),
|
||||
`${providerId}/${base} tier vocabulary must match EFFORT_TIERS`
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("#10788 nvidia z-ai/glm-5.2 declares reasoning with an empty tier list (binary switch)", () => {
|
||||
const entry = REGISTRY["nvidia"];
|
||||
assert.ok(entry?.models, "nvidia must expose models");
|
||||
const row = entry.models.find((m) => m.id === "z-ai/glm-5.2");
|
||||
assert.ok(row, "nvidia z-ai/glm-5.2 must exist");
|
||||
assert.equal(row.supportsReasoning, true);
|
||||
assert.deepEqual(row.supportedThinkingEfforts, []);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user