Skip to content
Closed
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
5 changes: 3 additions & 2 deletions docs-site/src/content/docs/reference/adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,9 @@ advertised effort control on those models as proof of upstream-native reasoning
- Exposes Cursor Router as `cursor/auto` plus explicit `cursor/auto-cost`,
`cursor/auto-balance`, and `cursor/auto-intelligence` entries. Explicit levels are encoded in
`requested_model.parameters` while the legacy `cursor/auto` entry retains the account/team default.
- Keeps `cursor/grok-4.5-fast` as a selectable model while sending Cursor's canonical `grok-4.5`
model with separate `effort` and `fast=true` parameters.
- Sends regular `cursor/grok-4.5` tiers with Cursor's exact live-discovery wire ids
(`cursor-grok-4.5-low`, `-medium`, or `-high`). Keeps `cursor/grok-4.5-fast` selectable while
sending the canonical `grok-4.5` model with separate `effort` and `fast=true` parameters.
- Cursor-native local filesystem/shell/network execution is denied by default. Explicit `mcpServers`
and `desktopExecutor` integrations have separate opt-ins; `nativeLocalExec: "on"` enables the
broader built-in executor and bypasses Codex approval/sandbox semantics, and legacy
Expand Down
11 changes: 11 additions & 0 deletions src/adapters/cursor/effort-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,14 @@ export function cursorWireModelIdWithEffort(baseModelId: string, effortSuffix: s
}
return `${baseModelId}-${effortSuffix}`;
}

/**
* Compose the exact flattened id sent by AgentService/Run. Discovery normalizes Cursor's optional
* `cursor-` prefix only for catalog matching, but regular Grok 4.5 requests require that prefix on
* the wire. Keep this separate from {@link cursorWireModelIdWithEffort} so discovery can continue
* comparing canonical, prefix-free ids. Grok Fast uses requested_model parameters instead.
*/
export function cursorRequestWireModelIdWithEffort(baseModelId: string, effortSuffix: string): string {
const flattened = cursorWireModelIdWithEffort(baseModelId, effortSuffix);
return baseModelId === "grok-4.5" ? `cursor-${flattened}` : flattened;
}
4 changes: 2 additions & 2 deletions src/adapters/cursor/request-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {
import { isAllowedToolChoice, namespacedToolName, toolChoiceAliases, type OcxTool, type OcxToolChoice } from "../../types";
import type { CursorRequestMessage, CursorRequestedModelParameter, CursorRunRequest } from "./types";
import { cursorWireModelSelection, type CursorRoutingLevel } from "./discovery";
import { cursorEffortSuffix, cursorWireModelIdWithEffort } from "./effort-map";
import { cursorEffortSuffix, cursorRequestWireModelIdWithEffort } from "./effort-map";
import {
cursorMcpToolEncodedSize,
cursorMcpToolsEncodedSize,
Expand Down Expand Up @@ -140,7 +140,7 @@ function normalizeCursorModelId(modelId: string, reasoning?: string): {
],
};
}
return { ...selection, modelId: suffix ? cursorWireModelIdWithEffort(id, suffix) : id };
return { ...selection, modelId: suffix ? cursorRequestWireModelIdWithEffort(id, suffix) : id };
}

function contentPartToText(part: OcxContentPart | OcxAssistantContentPart): string | undefined {
Expand Down
29 changes: 23 additions & 6 deletions tests/cursor-effort-suffix.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import { createCursorRequest } from "../src/adapters/cursor/request-builder";
import { cursorEffortSuffix, cursorModelEffortLadder } from "../src/adapters/cursor/effort-map";
import type { OcxParsedRequest } from "../src/types";

// Static fixture recorded from Cursor GetUsableModels on 2026-08-06. This pins the
// exact wire ids observed during the incident; live availability normalization is
// covered separately in cursor-discovery.test.ts.
const RECORDED_CURSOR_GROK_45_DISCOVERY_IDS = [
"cursor-grok-4.5-low",
"cursor-grok-4.5-medium",
"cursor-grok-4.5-high",
] as const;

function modelIdFor(modelId: string, reasoning?: string): string {
const parsed: OcxParsedRequest = {
modelId,
Expand Down Expand Up @@ -84,13 +93,13 @@ describe("Cursor per-model reasoning-effort suffix", () => {
});

test("grok-4.5 uses current tiers and sends Fast as a separate model parameter", () => {
expect(modelIdFor("cursor/grok-4.5", "low")).toBe("grok-4.5-low");
expect(modelIdFor("cursor/grok-4.5", "medium")).toBe("grok-4.5-medium");
expect(modelIdFor("cursor/grok-4.5", "high")).toBe("grok-4.5-high");
expect(modelIdFor("cursor/grok-4.5", "xhigh")).toBe("grok-4.5-high");
expect(modelIdFor("cursor/grok-4.5")).toBe("grok-4.5-high");
expect(modelIdFor("cursor/grok-4.5", "low")).toBe("cursor-grok-4.5-low");
expect(modelIdFor("cursor/grok-4.5", "medium")).toBe("cursor-grok-4.5-medium");
expect(modelIdFor("cursor/grok-4.5", "high")).toBe("cursor-grok-4.5-high");
expect(modelIdFor("cursor/grok-4.5", "xhigh")).toBe("cursor-grok-4.5-high");
expect(modelIdFor("cursor/grok-4.5")).toBe("cursor-grok-4.5-high");
expect(selectionFor("cursor/grok-4.5", "high")).toEqual({
modelId: "grok-4.5-high",
modelId: "cursor-grok-4.5-high",
parameters: undefined,
});
expect(selectionFor("cursor/grok-4.5-fast", "low")).toEqual({
Expand Down Expand Up @@ -118,6 +127,14 @@ describe("Cursor per-model reasoning-effort suffix", () => {
expect(cursorModelEffortLadder("grok-4.5-fast")).toEqual(["low", "medium", "high"]);
});

test("regular grok-4.5 request ids match the recorded discovery fixture", () => {
for (const effort of ["low", "medium", "high"] as const) {
const requestModelId = modelIdFor("cursor/grok-4.5", effort);
expect(requestModelId).toBe(`cursor-grok-4.5-${effort}`);
expect(RECORDED_CURSOR_GROK_45_DISCOVERY_IDS).toContain(requestModelId);
}
});

test("kimi-k3 maps to its live effort-suffixed variants", () => {
expect(modelIdFor("cursor/kimi-k3", "low")).toBe("kimi-k3-low");
expect(modelIdFor("cursor/kimi-k3", "medium")).toBe("kimi-k3-high");
Expand Down
Loading