Merge PR #8988: fix(catalog): collapse Cursor Grok 4.5/4.6 effort siblings (@roboomp)
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
|
||||
### Added
|
||||
|
||||
- Added a Cursor variant-collapse table folding the per-effort Grok siblings (`cursor-grok-4.5` low/medium/high and `cursor-grok-4.6` low/medium/high/xhigh, plus their `-fast` service-tier lanes) into one logical model per lane with effort routing onto the live wire ids, matching Devin's `grok-4-5` collapse ([#8803](https://github.com/can1357/oh-my-pi/issues/8803)).
|
||||
|
||||
- Regenerated the Cursor agent protobufs to model hosted WebFetch permission queries (`interaction_query` / `interaction_response` field 9) and the matching `ToolCall` variant (field 37).
|
||||
|
||||
### Fixed
|
||||
@@ -17,6 +19,7 @@
|
||||
- ChatGPT Codex discovery that advertises only worker `-wm` SKUs now also registers the plain model route, so a configured `openai-codex/<model>` keeps resolving instead of fuzzy-falling-back to the `-wm` SKU some accounts reject.
|
||||
- Fixed `opencode-go/muse-spark-1.2` (and `muse-spark-1.2-contributor`) failing every tool-call turn with `OpenAI completions stream closed before a finish_reason was received`. The Go gateway serves these ids only at `/zen/go/v1/responses`, but the `/zen/go/v1/models` discovery omits the `provider.npm` hint, so the resolver fell through to `openai-completions`; both ids are now pinned to `openai-responses` like `deepseek-v4-flash` ([#8957](https://github.com/can1357/oh-my-pi/issues/8957)).
|
||||
- Fixed GitHub Copilot `grok-4.6` / `grok-4.6-1m` failing with HTTP 400 `unsupported_api_for_model` by routing them through the OpenAI Responses API (`/responses`) instead of `/chat/completions`, matching `grok-4.5`. Stale cached completion routes are invalidated on refresh ([#8807](https://github.com/can1357/oh-my-pi/issues/8807)).
|
||||
- Fixed Cursor Grok 4.5/4.6 discovery classifying the versioned ids as non-reasoning: `GetUsableModels` ships no `thinkingDetails` and the bundled references read `reasoning: false`, so the picker hid the effort ladder. Discovery now marks `cursor-grok-<version>` ids as reasoning models (the non-reasoning `grok-code-*` ids stay out) ([#8803](https://github.com/can1357/oh-my-pi/issues/8803)).
|
||||
|
||||
## [17.3.6] - 2026-08-17
|
||||
|
||||
|
||||
@@ -28,6 +28,15 @@ const CURSOR_MAX_MODE_1M_ID_PATTERN = /claude|gemini/;
|
||||
/** Kimi's official bare K3 id (`k3`, `kimi/k3`); `k3-256k` is the 256k SKU and stays out. */
|
||||
const CURSOR_KIMI_K3_BARE_ID_PATTERN = /(^|\/)k3$/i;
|
||||
|
||||
/**
|
||||
* Versioned Cursor Grok ids (`cursor-grok-4.5`, `cursor-grok-4.6-high`) are
|
||||
* reasoning models whose effort is carried in the per-tier sibling id.
|
||||
* `GetUsableModels` ships no `thinkingDetails` and the bundled references read
|
||||
* `reasoning: false`, so classification falls back to the id. The non-reasoning
|
||||
* `grok-code-*` coding models lack the version digit and stay out.
|
||||
*/
|
||||
const CURSOR_GROK_REASONING_ID_PATTERN = /^cursor-grok-\d/i;
|
||||
|
||||
/**
|
||||
* Model-id families whose native catalogs (anthropic, openai/openai-codex,
|
||||
* google) are multimodal. Cursor-only or text-only families (`composer-*`,
|
||||
@@ -297,7 +306,11 @@ function normalizeCursorModel(
|
||||
|
||||
const name = pickModelDisplayName(details, id);
|
||||
const reference = references.get(id);
|
||||
const reasoning = isKimiK3ModelId(id) || Boolean(details.thinkingDetails) || reference?.reasoning === true;
|
||||
const reasoning =
|
||||
isKimiK3ModelId(id) ||
|
||||
CURSOR_GROK_REASONING_ID_PATTERN.test(id) ||
|
||||
Boolean(details.thinkingDetails) ||
|
||||
reference?.reasoning === true;
|
||||
|
||||
if (reference) {
|
||||
return {
|
||||
|
||||
@@ -111,19 +111,20 @@ function thinkingPair(baseId: string, name: string): EffortVariantFamily {
|
||||
};
|
||||
}
|
||||
|
||||
type DevinTierRoutes = Partial<Record<"off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max", string>>;
|
||||
type TierRoutes = Partial<Record<"off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max", string>>;
|
||||
|
||||
/** Devin families with a `-max` sibling: five wire tiers, `low` floor. */
|
||||
const DEVIN_FIVE_TIER_EFFORTS: readonly Effort[] = [Effort.Low, Effort.Medium, Effort.High, Effort.XHigh, Effort.Max];
|
||||
/** Pre-5.6 Devin GPT families top out at `-xhigh`: four wire tiers, `low` floor. */
|
||||
const DEVIN_FOUR_TIER_EFFORTS: readonly Effort[] = [Effort.Low, Effort.Medium, Effort.High, Effort.XHigh];
|
||||
|
||||
function devinTierFamily(
|
||||
id: string,
|
||||
name: string,
|
||||
routes: DevinTierRoutes,
|
||||
efforts: readonly Effort[],
|
||||
): EffortVariantFamily {
|
||||
/**
|
||||
* Build one effort-tier family from a tier→wire-id map: routing keeps only the
|
||||
* listed efforts, `members` dedupes the targets in tier order, and thinking is
|
||||
* `mode: "effort"` (mandatory when the family has no `off` route). Shared by the
|
||||
* Devin and Cursor tables, whose per-effort siblings follow the same shape.
|
||||
*/
|
||||
function tierFamily(id: string, name: string, routes: TierRoutes, efforts: readonly Effort[]): EffortVariantFamily {
|
||||
const routing: Partial<Record<Effort | "off", string>> = {};
|
||||
if (routes.off) routing.off = routes.off;
|
||||
for (const effort of efforts) {
|
||||
@@ -177,7 +178,7 @@ function devinTierFamily(
|
||||
function devinGpt56Families(variant: "luna" | "sol" | "terra", name: string): readonly EffortVariantFamily[] {
|
||||
const base = `gpt-5-6-${variant}`;
|
||||
return [
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
base,
|
||||
name,
|
||||
{
|
||||
@@ -190,7 +191,7 @@ function devinGpt56Families(variant: "luna" | "sol" | "terra", name: string): re
|
||||
},
|
||||
DEVIN_FIVE_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
`${base}-fast`,
|
||||
`${name} Fast`,
|
||||
{
|
||||
@@ -395,7 +396,7 @@ export const GEMINI_CLI_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
};
|
||||
export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
families: [
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"claude-opus-5",
|
||||
"Claude Opus 5",
|
||||
{
|
||||
@@ -407,7 +408,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FIVE_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"claude-opus-5-fast",
|
||||
"Claude Opus 5 Fast",
|
||||
{
|
||||
@@ -419,7 +420,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FIVE_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"claude-fable-5",
|
||||
"Claude Fable 5",
|
||||
{
|
||||
@@ -431,7 +432,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FIVE_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"claude-sonnet-5",
|
||||
"Claude Sonnet 5",
|
||||
{
|
||||
@@ -443,7 +444,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FIVE_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"claude-opus-4-7",
|
||||
"Claude Opus 4.7",
|
||||
{
|
||||
@@ -455,7 +456,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FIVE_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"claude-opus-4-7-fast",
|
||||
"Claude Opus 4.7 Fast",
|
||||
{
|
||||
@@ -467,7 +468,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FIVE_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"claude-opus-4-8",
|
||||
"Claude Opus 4.8",
|
||||
{
|
||||
@@ -479,7 +480,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FIVE_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"claude-opus-4-8-fast",
|
||||
"Claude Opus 4.8 Fast",
|
||||
{
|
||||
@@ -491,7 +492,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FIVE_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"gpt-5-2",
|
||||
"GPT-5.2",
|
||||
{
|
||||
@@ -503,7 +504,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FOUR_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"gpt-5-3-codex",
|
||||
"GPT-5.3 Codex",
|
||||
{
|
||||
@@ -514,7 +515,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FOUR_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"gpt-5-3-codex-fast",
|
||||
"GPT-5.3 Codex Fast",
|
||||
{
|
||||
@@ -525,7 +526,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FOUR_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"gpt-5-4",
|
||||
"GPT-5.4",
|
||||
{
|
||||
@@ -537,7 +538,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FOUR_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"gpt-5-4-fast",
|
||||
"GPT-5.4 Fast",
|
||||
{
|
||||
@@ -549,7 +550,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FOUR_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"gpt-5-4-mini",
|
||||
"GPT-5.4 Mini",
|
||||
{
|
||||
@@ -560,7 +561,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FOUR_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"gpt-5-5",
|
||||
"GPT-5.5",
|
||||
{
|
||||
@@ -572,7 +573,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FOUR_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"gpt-5-5-fast",
|
||||
"GPT-5.5 Fast",
|
||||
{
|
||||
@@ -587,7 +588,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
...devinGpt56Families("luna", "GPT-5.6 Luna"),
|
||||
...devinGpt56Families("sol", "GPT-5.6 Sol"),
|
||||
...devinGpt56Families("terra", "GPT-5.6 Terra"),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"kimi-k3",
|
||||
"Kimi K3",
|
||||
{
|
||||
@@ -597,7 +598,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
[Effort.Low, Effort.High, Effort.Max],
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"swe-1-7",
|
||||
"SWE-1.7",
|
||||
{
|
||||
@@ -606,7 +607,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
[Effort.Medium, Effort.Max],
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"grok-4-5",
|
||||
"Grok 4.5",
|
||||
{
|
||||
@@ -616,7 +617,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
[Effort.Low, Effort.Medium, Effort.High],
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"inkling",
|
||||
"Inkling",
|
||||
{
|
||||
@@ -629,7 +630,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
DEVIN_FIVE_TIER_EFFORTS,
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"gemini-3-1-pro",
|
||||
"Gemini 3.1 Pro",
|
||||
{
|
||||
@@ -638,7 +639,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
[Effort.Low, Effort.High],
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"gemini-3-5-flash",
|
||||
"Gemini 3.5 Flash",
|
||||
{
|
||||
@@ -649,7 +650,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
[Effort.Minimal, Effort.Low, Effort.Medium, Effort.High],
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"gemini-3-6-flash",
|
||||
"Gemini 3.6 Flash",
|
||||
{
|
||||
@@ -660,7 +661,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
[Effort.Minimal, Effort.Low, Effort.Medium, Effort.High],
|
||||
),
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"gemini-3-flash",
|
||||
"Gemini 3 Flash",
|
||||
{
|
||||
@@ -694,7 +695,7 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
},
|
||||
// GLM-5.2 1M — paid variants that consume weekly quota. Collapse the
|
||||
// three 1M-context variants into one entry with proper effort routing.
|
||||
devinTierFamily(
|
||||
tierFamily(
|
||||
"glm-5-2-1m",
|
||||
"GLM-5.2 1M",
|
||||
{
|
||||
@@ -707,11 +708,43 @@ export const DEVIN_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
],
|
||||
};
|
||||
|
||||
/** Cursor's Grok tier tokens equal the effort id, so routing is a direct map. */
|
||||
const CURSOR_GROK_45_EFFORTS: readonly Effort[] = [Effort.Low, Effort.Medium, Effort.High];
|
||||
const CURSOR_GROK_46_EFFORTS: readonly Effort[] = [Effort.Low, Effort.Medium, Effort.High, Effort.XHigh];
|
||||
|
||||
/**
|
||||
* Cursor serves Grok 4.5/4.6 as per-effort sibling ids
|
||||
* (`cursor-grok-4.6-low|-medium|-high|-xhigh`) alongside a parallel `-fast`
|
||||
* service-tier lane (`-low-fast`, …). Each lane collapses into its own logical
|
||||
* model — the `-fast` axis is a sibling family, never a second routing
|
||||
* dimension — with effort routing onto the live sibling wire ids.
|
||||
*/
|
||||
function cursorGrokFamilies(version: "4.5" | "4.6", efforts: readonly Effort[]): readonly EffortVariantFamily[] {
|
||||
const build = (fast: boolean): EffortVariantFamily => {
|
||||
const suffix = fast ? "-fast" : "";
|
||||
const routes: TierRoutes = {};
|
||||
for (const effort of efforts) {
|
||||
routes[effort] = `cursor-grok-${version}-${effort}${suffix}`;
|
||||
}
|
||||
return tierFamily(`cursor-grok-${version}${suffix}`, `Grok ${version}${fast ? " Fast" : ""}`, routes, efforts);
|
||||
};
|
||||
return [build(false), build(true)];
|
||||
}
|
||||
|
||||
/** `cursor` Grok families: per-effort siblings collapsed per service-tier lane. */
|
||||
export const CURSOR_VARIANT_COLLAPSE_TABLE: VariantCollapseTable = {
|
||||
families: [
|
||||
...cursorGrokFamilies("4.5", CURSOR_GROK_45_EFFORTS),
|
||||
...cursorGrokFamilies("4.6", CURSOR_GROK_46_EFFORTS),
|
||||
],
|
||||
};
|
||||
|
||||
/** Provider id → hand collapse table. The CCA providers diverge on thinking transport. */
|
||||
export const VARIANT_COLLAPSE_TABLES: Readonly<Record<string, VariantCollapseTable>> = {
|
||||
"google-antigravity": ANTIGRAVITY_VARIANT_COLLAPSE_TABLE,
|
||||
"google-gemini-cli": GEMINI_CLI_VARIANT_COLLAPSE_TABLE,
|
||||
devin: DEVIN_VARIANT_COLLAPSE_TABLE,
|
||||
cursor: CURSOR_VARIANT_COLLAPSE_TABLE,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,10 @@ const FIXTURE_MODEL_IDS = [
|
||||
"kimi-k3-low",
|
||||
"kimi-k3-max",
|
||||
"grok-code-fast-2",
|
||||
// Versioned Cursor Grok siblings: bundled references read reasoning:false,
|
||||
// but the id marks them reasoning.
|
||||
"cursor-grok-4.5-high",
|
||||
"cursor-grok-4.6-xhigh",
|
||||
// Bundled-reference ids: the reference stays authoritative.
|
||||
"claude-4.5-opus-high",
|
||||
"claude-4.6-opus-high",
|
||||
@@ -92,6 +96,14 @@ describe("cursor discovery input modalities (issue #4726)", () => {
|
||||
expect(byId.get("kimi-k3-max")?.reasoning).toBe(true);
|
||||
});
|
||||
|
||||
it("marks versioned Cursor Grok ids as reasoning despite reasoning:false references (issue #8803)", async () => {
|
||||
const byId = await discover();
|
||||
expect(byId.get("cursor-grok-4.5-high")?.reasoning).toBe(true);
|
||||
expect(byId.get("cursor-grok-4.6-xhigh")?.reasoning).toBe(true);
|
||||
// grok-code-* coding models lack the version digit and stay non-reasoning.
|
||||
expect(byId.get("grok-code-fast-2")?.reasoning).toBe(false);
|
||||
});
|
||||
|
||||
it("keeps bundled references authoritative for input modalities", async () => {
|
||||
const byId = await discover();
|
||||
// Bundled cursor references carry their own input classification; the
|
||||
|
||||
@@ -15,6 +15,7 @@ import { googleGeminiCliModelManagerOptions } from "@oh-my-pi/pi-catalog/provide
|
||||
import type { ModelSpec } from "@oh-my-pi/pi-catalog/types";
|
||||
import {
|
||||
ANTIGRAVITY_VARIANT_COLLAPSE_TABLE,
|
||||
CURSOR_VARIANT_COLLAPSE_TABLE,
|
||||
collapseEffortVariants,
|
||||
collapseEffortVariantsAcrossProviders,
|
||||
DEVIN_VARIANT_COLLAPSE_TABLE,
|
||||
@@ -656,6 +657,77 @@ describe("Devin tier routing", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("Cursor Grok tier routing (issue #8803)", () => {
|
||||
function cursorMemberSpec(id: string): ModelSpec<"cursor-agent"> {
|
||||
return {
|
||||
id,
|
||||
name: id,
|
||||
api: "cursor-agent",
|
||||
provider: "cursor",
|
||||
baseUrl: "https://api2.cursor.sh",
|
||||
// Live GetUsableModels + bundled references mark these reasoning:false;
|
||||
// collapse must still recognize the effort ladder.
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 200_000,
|
||||
maxTokens: 64_000,
|
||||
};
|
||||
}
|
||||
|
||||
const RAW_SIBLINGS = [
|
||||
"cursor-grok-4.5-high",
|
||||
"cursor-grok-4.5-high-fast",
|
||||
"cursor-grok-4.5-low",
|
||||
"cursor-grok-4.5-low-fast",
|
||||
"cursor-grok-4.5-medium",
|
||||
"cursor-grok-4.5-medium-fast",
|
||||
"cursor-grok-4.6-high",
|
||||
"cursor-grok-4.6-high-fast",
|
||||
"cursor-grok-4.6-low",
|
||||
"cursor-grok-4.6-low-fast",
|
||||
"cursor-grok-4.6-medium",
|
||||
"cursor-grok-4.6-medium-fast",
|
||||
"cursor-grok-4.6-xhigh",
|
||||
"cursor-grok-4.6-xhigh-fast",
|
||||
];
|
||||
|
||||
it("collapses the 14 effort siblings into four logical models, split by the -fast lane", () => {
|
||||
const collapsed = collapseEffortVariants(RAW_SIBLINGS.map(cursorMemberSpec), CURSOR_VARIANT_COLLAPSE_TABLE);
|
||||
expect(collapsed.map(model => model.id).sort()).toEqual([
|
||||
"cursor-grok-4.5",
|
||||
"cursor-grok-4.5-fast",
|
||||
"cursor-grok-4.6",
|
||||
"cursor-grok-4.6-fast",
|
||||
]);
|
||||
|
||||
const g46 = collapsed.find(model => model.id === "cursor-grok-4.6");
|
||||
if (!g46) throw new Error("cursor-grok-4.6 did not collapse");
|
||||
expect(g46.name).toBe("Grok 4.6");
|
||||
// Effort route forces reasoning even though every member said false.
|
||||
expect(g46.reasoning).toBe(true);
|
||||
expect(g46.thinking?.mode).toBe("effort");
|
||||
expect(g46.thinking?.efforts).toEqual([Effort.Low, Effort.Medium, Effort.High, Effort.XHigh]);
|
||||
expect(g46.thinking?.requiresEffort).toBe(true);
|
||||
});
|
||||
|
||||
it("routes each user effort onto the live sibling wire id per service-tier lane", () => {
|
||||
const collapsed = collapseEffortVariants(RAW_SIBLINGS.map(cursorMemberSpec), CURSOR_VARIANT_COLLAPSE_TABLE);
|
||||
const model = (id: string) => {
|
||||
const found = collapsed.find(m => m.id === id);
|
||||
if (!found) throw new Error(`${id} did not collapse`);
|
||||
return buildModel(found as ModelSpec<"cursor-agent">);
|
||||
};
|
||||
|
||||
expect(resolveWireModelId(model("cursor-grok-4.6"), Effort.XHigh)).toBe("cursor-grok-4.6-xhigh");
|
||||
expect(resolveWireModelId(model("cursor-grok-4.6"), Effort.Low)).toBe("cursor-grok-4.6-low");
|
||||
expect(resolveWireModelId(model("cursor-grok-4.6-fast"), Effort.High)).toBe("cursor-grok-4.6-high-fast");
|
||||
expect(resolveWireModelId(model("cursor-grok-4.5"), Effort.Medium)).toBe("cursor-grok-4.5-medium");
|
||||
// 4.5 has no xhigh sibling: the ceiling stays at high.
|
||||
expect(model("cursor-grok-4.5").thinking?.efforts).toEqual([Effort.Low, Effort.Medium, Effort.High]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("variant aliases", () => {
|
||||
it("resolves members and recycled ids per provider", () => {
|
||||
expect(resolveVariantAlias("google-antigravity", "gemini-3.5-flash-low")).toBe("gemini-3.5-flash");
|
||||
|
||||
Reference in New Issue
Block a user