Skip to content
Draft
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
28 changes: 3 additions & 25 deletions src/adapters/cursor/catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,8 @@ function composeWireId(baseId: string, kind: CursorVariantKind, effort: string |
* Legacy slugs (thinking/fast/-1m variants) keep resolving forever — picker
* rows shrink, routability does not (alias-retention contract, 003).
*
* `liveMaxModeIds` optionally extends the static maxMode evidence with the
* bases the live GetUsableModels roster flags (union semantics).
* `liveMaxModeIds` optionally extends the static maxMode evidence with
* route-scoped bases from the selected account's GetUsableModels roster.
*/
export function resolveCursorSelection(
pickedId: string,
Expand All @@ -465,32 +465,10 @@ export function resolveCursorSelection(
? `${capability.wirePrefix}${canonicalId}`
: canonicalId;
const ultraRequested = parsed.ultra || reasoning?.toLowerCase() === "ultra";
const evidence = liveMaxModeIds ?? liveCursorMaxModeBases;
const maxModeArmed = capability.maxModeVerified === true || evidence.has(parsed.baseId);
const maxModeArmed = capability.maxModeVerified === true || liveMaxModeIds?.has(parsed.baseId) === true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Thread live Max Mode evidence into production requests

For an account whose GetUsableModels response marks an otherwise-unverified model as Max-Mode capable, Ultra requests now silently omit the maxMode wire flag. This resolver's new argument is never supplied by production code: src/adapters/cursor/request-builder.ts:215 still calls it with only two arguments, while this commit also discards liveResult.maxModeModels in provider-fetch.ts, so only the statically verified kimi-k3 can use Max Mode. Preserve the evidence in a provider/credential-scoped store, pass the selected route's set into request construction, and add a focused discovery-to-request regression test.

AGENTS.md reference: AGENTS.md:L336-L339

Useful? React with 👍 / 👎.

return { wireId, canonicalId, maxMode: ultraRequested && maxModeArmed, known: true };
}

/**
* Live Max-Mode evidence (GetUsableModels maxModeModels). Provider discovery
* records the BASES the live roster flags; the resolver unions this with the
* static `maxModeVerified` gate so ultra generalizes automatically as evidence
* arrives — never from window size (devlog 260828 blocker-4 fold).
*/
let liveCursorMaxModeBases: ReadonlySet<string> = new Set();

export function recordLiveCursorMaxModeModels(liveIds: readonly string[]): void {
const bases = new Set<string>();
for (const id of liveIds) {
const parsed = parseCursorVariantId(id);
if (parsed.known) bases.add(parsed.baseId);
}
liveCursorMaxModeBases = bases;
}

export function liveCursorMaxModeBasesForTests(): ReadonlySet<string> {
return liveCursorMaxModeBases;
}

export interface CursorUmbrellaRow {
readonly id: string;
readonly efforts: readonly string[];
Expand Down
4 changes: 0 additions & 4 deletions src/codex/catalog/provider-fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ import { routedSlug, slugEquals, slugEquivalenceKey, slugsEquivalent } from "../
import { CODEX_GPT5_IDENTITY_LINE } from "../../adapters/identity";
import { filterCursorConfiguredModelsByLiveDiscovery } from "../../adapters/cursor/discovery";
import { fetchCursorUsableModels } from "../../adapters/cursor/live-models";
import { recordLiveCursorMaxModeModels } from "../../adapters/cursor/catalog";
import { isCanonicalOpenAiForwardProvider, OPENAI_API_PROVIDER_ID, OPENAI_CODEX_PROVIDER_ID } from "../../providers/openai-tiers";
import {
COMBO_NAMESPACE,
Expand Down Expand Up @@ -1328,9 +1327,6 @@ async function fetchProviderModelsWithAuth(
});
if (liveResult.ok) {
const available = filterCursorConfiguredModelsByLiveDiscovery(configured, liveResult.models);
// Live Max-Mode evidence feeds the umbrella resolver's ultra gate
// (devlog 260828_cursor_umbrella_catalog; union with static evidence).
recordLiveCursorMaxModeModels(liveResult.maxModeModels ?? []);
const result = available.length > 0 ? available : configured;
// Cache the discovery-filtered roster without combo retention so a later
// gather can re-apply the current capture's retain set on read.
Expand Down
14 changes: 3 additions & 11 deletions tests/cursor-umbrella-rows.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { describe, expect, test } from "bun:test";
import {
cursorUmbrellaRows,
recordLiveCursorMaxModeModels,
resolveCursorSelection,
} from "../src/adapters/cursor/catalog";
import { CURSOR_STATIC_MODELS, cursorModelReasoningEfforts } from "../src/adapters/cursor/discovery";
Expand Down Expand Up @@ -81,17 +80,10 @@ describe("cursor umbrella picker rows (devlog 260828_cursor_umbrella_catalog)",
});
});

describe("live Max-Mode evidence generalizes ultra", () => {
test("recorded live maxModeModels arm ultra for their bases and reset cleanly", () => {
recordLiveCursorMaxModeModels(["claude-opus-4-8-high-fast"]);
try {
expect(resolveCursorSelection("claude-opus-4-8", "ultra").maxMode).toBe(true);
expect(resolveCursorSelection("claude-opus-4-7", "ultra").maxMode).toBe(false);
} finally {
recordLiveCursorMaxModeModels([]);
}
describe("Max-Mode evidence stays request-scoped", () => {
test("omitted live evidence cannot arm ultra for an unverified base", () => {
expect(resolveCursorSelection("claude-opus-4-8", "ultra").maxMode).toBe(false);
// Static evidence survives the reset.
// Static evidence remains available without account-local discovery.
expect(resolveCursorSelection("kimi-k3", "ultra").maxMode).toBe(true);
});
});
Expand Down
Loading