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
19 changes: 11 additions & 8 deletions src/adapters/cursor/discovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,18 @@ export function isCursorRouterModelId(modelId: string): boolean {
export function filterCursorConfiguredModelsByLiveDiscovery<T extends { id: string }>(
configured: readonly T[],
liveIds: readonly string[],
maxModeLiveIds: readonly string[] = [],
): T[] {
return configured.filter(model =>
!CURSOR_KNOWN_UNCALLABLE_MODEL_IDS.has(model.id)
&& (
isCursorRouterModelId(model.id)
// Synthetic ultra rows ride their base model's account availability.
|| isCursorModelAvailableForAccount(cursorUltraBaseModelId(model.id) ?? model.id, liveIds)
),
);
return configured.filter(model => {
if (CURSOR_KNOWN_UNCALLABLE_MODEL_IDS.has(model.id)) return false;
if (isCursorRouterModelId(model.id)) return true;
const ultraBase = cursorUltraBaseModelId(model.id);
return isCursorModelAvailableForAccount(ultraBase ?? model.id, liveIds)
// Successful discovery is authoritative: synthetic ultra rows additionally require the
// account-specific Max Mode capability. Discovery failures bypass this filter and retain
// the static seed under the caller's existing degraded-catalog policy.
&& (ultraBase === undefined || isCursorModelAvailableForAccount(ultraBase, maxModeLiveIds));
});
}

/**
Expand Down
6 changes: 5 additions & 1 deletion src/codex/catalog/provider-fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1308,7 +1308,11 @@ async function fetchProviderModelsWithAuth(
...(cursorFetch ? { fetch: cursorFetch } : {}),
});
if (liveResult.ok) {
const available = filterCursorConfiguredModelsByLiveDiscovery(configured, liveResult.models);
const available = filterCursorConfiguredModelsByLiveDiscovery(
configured,
liveResult.models,
liveResult.maxModeModels ?? [],
);
Comment on lines +1311 to +1315

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve capability filtering when every configured row is rejected

When a Cursor provider explicitly configures only kimi-k3-1m and successful discovery returns a Kimi base model without any maxModeModels, this filter correctly produces an empty list, but the immediately following available.length > 0 ? available : configured restores and caches the unsupported synthetic row. The catalog therefore still advertises the 1M selector to accounts lacking the discovered capability; a successful nonempty discovery should remain authoritative even when no configured rows survive, rather than falling back to configured.

Useful? React with 👍 / 👎.

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
11 changes: 9 additions & 2 deletions tests/cursor-ultra-mode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,20 @@ describe("cursor ultra (-1m / Max Mode) toggle (devlog 260826 070)", () => {
expect(decoded.modelDetails?.maxMode ?? false).toBe(false);
});

test("account filter admits the synthetic row through its base availability", () => {
test("account filter admits the synthetic row only with base and Max Mode availability", () => {
const configured = [{ id: "kimi-k3-1m" }, { id: "kimi-k3" }];
const live = ["kimi-k3-high", "kimi-k3-max"];
const filtered = filterCursorConfiguredModelsByLiveDiscovery(configured, live);
const filtered = filterCursorConfiguredModelsByLiveDiscovery(configured, live, ["kimi-k3-max"]);
expect(filtered.map(model => model.id)).toEqual(["kimi-k3-1m", "kimi-k3"]);
});

test("account filter hides the synthetic row without discovered Max Mode capability", () => {
const configured = [{ id: "kimi-k3-1m" }, { id: "kimi-k3" }];
const live = ["kimi-k3-high", "kimi-k3-max"];
const filtered = filterCursorConfiguredModelsByLiveDiscovery(configured, live);
expect(filtered.map(model => model.id)).toEqual(["kimi-k3"]);
});

test("ultra id set stays narrow and every entry has a static row", () => {
for (const id of CURSOR_ULTRA_1M_MODEL_IDS) {
expect(CURSOR_STATIC_MODELS.some(model => model.id === id)).toBe(true);
Expand Down
Loading