Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
28 changes: 22 additions & 6 deletions tests/cursor-effort-suffix.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, expect, test } from "bun:test";
import { createCursorRequest } from "../src/adapters/cursor/request-builder";
import { cursorEffortSuffix, cursorModelEffortLadder } from "../src/adapters/cursor/effort-map";
import { isCursorModelAvailableForAccount } from "../src/adapters/cursor/discovery";
import type { OcxParsedRequest } from "../src/types";

function modelIdFor(modelId: string, reasoning?: string): string {
Expand Down Expand Up @@ -84,13 +85,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 +119,21 @@ describe("Cursor per-model reasoning-effort suffix", () => {
expect(cursorModelEffortLadder("grok-4.5-fast")).toEqual(["low", "medium", "high"]);
});

test("regular grok-4.5 requests exactly match live prefixed discovery ids", () => {
const liveIds = [
"cursor-grok-4.5-low",
"cursor-grok-4.5-medium",
"cursor-grok-4.5-high",
];

expect(isCursorModelAvailableForAccount("grok-4.5", liveIds)).toBe(true);
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(liveIds).toContain(requestModelId);
}
});

Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
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