cursor-opencode-provider 0.6.3 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -6
- package/dist/auth.js +28 -11
- package/dist/language-model.d.ts +2 -0
- package/dist/language-model.js +280 -69
- package/dist/model-config.d.ts +3 -1
- package/dist/model-config.js +83 -19
- package/dist/models.d.ts +8 -0
- package/dist/models.js +8 -4
- package/dist/opencode2/catalog.js +4 -3
- package/dist/pricing-data.d.ts +51 -11
- package/dist/pricing-data.js +51 -11
- package/dist/pricing.d.ts +10 -4
- package/dist/pricing.js +17 -8
- package/dist/protocol/exec-variants.d.ts +5 -0
- package/dist/protocol/exec-variants.js +17 -2
- package/dist/protocol/git-diff.d.ts +33 -0
- package/dist/protocol/git-diff.js +372 -0
- package/dist/protocol/messages.js +229 -6
- package/dist/protocol/progress-continuation.d.ts +25 -0
- package/dist/protocol/progress-continuation.js +92 -0
- package/dist/protocol/tools.d.ts +6 -0
- package/dist/protocol/tools.js +216 -3
- package/dist/protocol/workspace-grounding.d.ts +1 -0
- package/dist/protocol/workspace-grounding.js +8 -0
- package/dist/session.d.ts +11 -2
- package/dist/session.js +34 -5
- package/dist/usage.d.ts +14 -0
- package/dist/usage.js +26 -0
- package/package.json +1 -1
package/dist/model-config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CURSOR_VARIANT_PARAMETERS_KEY, CURSOR_WIRE_MODEL_ID_KEY, parseCursorContextLimit, } from "./models.js";
|
|
2
|
-
import { applyCursorModelCost } from "./pricing.js";
|
|
2
|
+
import { applyCursorModelCost, hasCursorFastPricing } from "./pricing.js";
|
|
3
3
|
import { getDocumentedCursorModelContext, resolveCursorModelSupportsImages, } from "./model-metadata.js";
|
|
4
4
|
/**
|
|
5
5
|
* Cursor `ModelInfo` → OpenCode model-config mapping.
|
|
@@ -109,6 +109,9 @@ function modelInfoVariants(mi, variants) {
|
|
|
109
109
|
function isLongContextVariant(v) {
|
|
110
110
|
return v.parameterValues.some((p) => p.id === "context" && parseCursorContextLimit(p.value) === 1_000_000);
|
|
111
111
|
}
|
|
112
|
+
function isFastVariant(v) {
|
|
113
|
+
return v.parameterValues.some((p) => p.id === "fast" && p.value === "true");
|
|
114
|
+
}
|
|
112
115
|
function variantsForTier(mi, tier) {
|
|
113
116
|
return mi.variants.filter((v) => isLongContextVariant(v) === (tier === "long"));
|
|
114
117
|
}
|
|
@@ -139,10 +142,12 @@ export function thinkingSuffixBaseNames(models) {
|
|
|
139
142
|
}
|
|
140
143
|
export function modelInfoToConfig(mi, options = {}) {
|
|
141
144
|
const contextTier = options.contextTier ?? "base";
|
|
142
|
-
const variants = variantsForTier(mi, contextTier);
|
|
145
|
+
const variants = options.variants ?? variantsForTier(mi, contextTier);
|
|
143
146
|
let name = baseName(mi);
|
|
144
147
|
if (options.thinkingSuffix)
|
|
145
148
|
name += " Thinking";
|
|
149
|
+
if (options.fast)
|
|
150
|
+
name += " Fast";
|
|
146
151
|
if (contextTier === "long")
|
|
147
152
|
name += " 1M";
|
|
148
153
|
// OpenCode's context limit is static per model entry, while Cursor's context
|
|
@@ -176,8 +181,10 @@ export function modelInfoToConfig(mi, options = {}) {
|
|
|
176
181
|
const variantConfig = modelInfoVariants(mi, variants);
|
|
177
182
|
if (variantConfig)
|
|
178
183
|
config.variants = variantConfig;
|
|
179
|
-
if (contextTier === "long") {
|
|
180
|
-
const defaultVariant =
|
|
184
|
+
if (contextTier === "long" || options.fast) {
|
|
185
|
+
const defaultVariant = contextTier === "long"
|
|
186
|
+
? (variants.find((v) => v.isDefaultMax) ?? variants[0])
|
|
187
|
+
: (variants.find((v) => v.isDefaultNonMax) ?? variants[0]);
|
|
181
188
|
if (defaultVariant) {
|
|
182
189
|
config.options = {
|
|
183
190
|
[CURSOR_WIRE_MODEL_ID_KEY]: mi.id,
|
|
@@ -187,30 +194,87 @@ export function modelInfoToConfig(mi, options = {}) {
|
|
|
187
194
|
}
|
|
188
195
|
return config;
|
|
189
196
|
}
|
|
197
|
+
function speedGroups(variants, splitFast) {
|
|
198
|
+
if (!splitFast)
|
|
199
|
+
return variants.length > 0 ? [{ fast: false, variants }] : [];
|
|
200
|
+
const slow = variants.filter((variant) => !isFastVariant(variant));
|
|
201
|
+
const fast = variants.filter((variant) => isFastVariant(variant));
|
|
202
|
+
const groups = [];
|
|
203
|
+
if (slow.length > 0)
|
|
204
|
+
groups.push({ fast: false, variants: slow });
|
|
205
|
+
if (fast.length > 0)
|
|
206
|
+
groups.push({ fast: true, variants: fast });
|
|
207
|
+
return groups;
|
|
208
|
+
}
|
|
209
|
+
function uniqueCatalogId(usedIds, modelId, suffix) {
|
|
210
|
+
let id = `${modelId}${suffix}`;
|
|
211
|
+
if (!usedIds.has(id)) {
|
|
212
|
+
usedIds.add(id);
|
|
213
|
+
return id;
|
|
214
|
+
}
|
|
215
|
+
let n = 2;
|
|
216
|
+
while (true) {
|
|
217
|
+
const candidate = suffix === "-fast"
|
|
218
|
+
? `${modelId}-fast-${n}`
|
|
219
|
+
: suffix === "-1m-fast"
|
|
220
|
+
? `${modelId}-1m-${n}-fast`
|
|
221
|
+
: `${modelId}-1m-${n}`;
|
|
222
|
+
if (!usedIds.has(candidate)) {
|
|
223
|
+
usedIds.add(candidate);
|
|
224
|
+
return candidate;
|
|
225
|
+
}
|
|
226
|
+
n++;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
190
229
|
export function modelsToConfig(models) {
|
|
191
230
|
const ambiguous = thinkingSuffixBaseNames(models);
|
|
192
231
|
const out = {};
|
|
193
232
|
const usedIds = new Set(models.map((m) => m.id));
|
|
194
233
|
for (const m of models) {
|
|
195
234
|
const thinkingSuffix = !!m.supportsThinking && ambiguous.has(baseName(m));
|
|
196
|
-
const
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
235
|
+
const splitFast = hasCursorFastPricing(m.id);
|
|
236
|
+
const groups = [];
|
|
237
|
+
for (const contextTier of ["base", "long"]) {
|
|
238
|
+
const suffixFor = (fast) => contextTier === "long" ? (fast ? "-1m-fast" : "-1m") : (fast ? "-fast" : "");
|
|
239
|
+
for (const group of speedGroups(variantsForTier(m, contextTier), splitFast)) {
|
|
240
|
+
groups.push({
|
|
241
|
+
contextTier,
|
|
242
|
+
fast: group.fast,
|
|
243
|
+
variants: group.variants,
|
|
244
|
+
suffix: suffixFor(group.fast),
|
|
245
|
+
});
|
|
246
|
+
}
|
|
200
247
|
}
|
|
201
|
-
if (
|
|
202
|
-
|
|
203
|
-
if (baseVariants.length === 0) {
|
|
204
|
-
// No separate base tier — the wire id itself is the long-context entry.
|
|
205
|
-
out[m.id] = applyCursorModelCost(`${m.id}-1m`, modelInfoToConfig(m, { thinkingSuffix, contextTier: "long" }));
|
|
248
|
+
if (groups.length === 0) {
|
|
249
|
+
out[m.id] = applyCursorModelCost(m.id, modelInfoToConfig(m, { thinkingSuffix, contextTier: "base" }));
|
|
206
250
|
continue;
|
|
207
251
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
252
|
+
const primaryIndex = groups.findIndex((group) => group.suffix === "");
|
|
253
|
+
const primary = primaryIndex >= 0 ? primaryIndex : 0;
|
|
254
|
+
for (const [index, group] of groups.entries()) {
|
|
255
|
+
const catalogId = index === primary
|
|
256
|
+
? m.id
|
|
257
|
+
: uniqueCatalogId(usedIds, m.id, group.suffix || "-fast");
|
|
258
|
+
const pricingId = group.fast ? `${m.id}-fast` : (group.contextTier === "long" ? `${m.id}-1m` : m.id);
|
|
259
|
+
const config = modelInfoToConfig(m, {
|
|
260
|
+
thinkingSuffix,
|
|
261
|
+
contextTier: group.contextTier,
|
|
262
|
+
variants: group.variants,
|
|
263
|
+
fast: group.fast,
|
|
264
|
+
});
|
|
265
|
+
if (catalogId !== m.id && !config.options) {
|
|
266
|
+
const defaultVariant = (group.contextTier === "long"
|
|
267
|
+
? group.variants.find((v) => v.isDefaultMax)
|
|
268
|
+
: group.variants.find((v) => v.isDefaultNonMax)) ?? group.variants[0];
|
|
269
|
+
if (defaultVariant) {
|
|
270
|
+
config.options = {
|
|
271
|
+
[CURSOR_WIRE_MODEL_ID_KEY]: m.id,
|
|
272
|
+
[CURSOR_VARIANT_PARAMETERS_KEY]: defaultVariant.parameterValues.map((p) => ({ ...p })),
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
out[catalogId] = applyCursorModelCost(pricingId, config);
|
|
277
|
+
}
|
|
214
278
|
}
|
|
215
279
|
return out;
|
|
216
280
|
}
|
package/dist/models.d.ts
CHANGED
|
@@ -47,6 +47,14 @@ export declare function extractCursorVariantParameters(providerOptions: Record<s
|
|
|
47
47
|
export declare function resolveCursorWireModelId(providerOptions: Record<string, unknown> | undefined, fallback: string): string;
|
|
48
48
|
/** True when resolved params select the long-context (1m) tier. */
|
|
49
49
|
export declare function paramsImplyMaxMode(params: ModelParameterValue[]): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Resolve the request-level max_mode bit. An explicit variant pick owns the
|
|
52
|
+
* context tier; otherwise a standalone maxMode hint may select max mode.
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveVariantMaxMode(params: ModelParameterValue[], opts?: {
|
|
55
|
+
picked?: ModelParameterValue[];
|
|
56
|
+
maxMode?: boolean;
|
|
57
|
+
}): boolean;
|
|
50
58
|
export declare function parseCursorContextLimit(value: unknown): number | undefined;
|
|
51
59
|
export declare function isCacheFresh(cache: ModelCache, ttlMs?: number): boolean;
|
|
52
60
|
export declare function cacheFilePath(cacheDir: string): string;
|
package/dist/models.js
CHANGED
|
@@ -181,6 +181,13 @@ export function paramsImplyMaxMode(params) {
|
|
|
181
181
|
return params.some((parameter) => parameter.id === "context" &&
|
|
182
182
|
parseCursorContextLimit(parameter.value) === 1_000_000);
|
|
183
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Resolve the request-level max_mode bit. An explicit variant pick owns the
|
|
186
|
+
* context tier; otherwise a standalone maxMode hint may select max mode.
|
|
187
|
+
*/
|
|
188
|
+
export function resolveVariantMaxMode(params, opts = {}) {
|
|
189
|
+
return paramsImplyMaxMode(params) || (opts.picked === undefined && opts.maxMode === true);
|
|
190
|
+
}
|
|
184
191
|
// Cursor encodes a model's context window as a variant parameter `id: "context"`
|
|
185
192
|
// whose value is a tier string — the same 200k / 272k / 300k / 1m the IDE's
|
|
186
193
|
// picker shows. The base tier rides on the default non-max variant; the 1M
|
|
@@ -352,10 +359,7 @@ export function resolveVariantParameters(model, opts = {}) {
|
|
|
352
359
|
pickedById.size === picked.length &&
|
|
353
360
|
v.parameterValues.every((parameter) => pickedById.get(parameter.id) === parameter.value));
|
|
354
361
|
if (exact) {
|
|
355
|
-
return buildRequestedModelParams(exact.parameterValues
|
|
356
|
-
reasoningEffort: opts.reasoningEffort,
|
|
357
|
-
maxMode: wantMax,
|
|
358
|
-
});
|
|
362
|
+
return buildRequestedModelParams(exact.parameterValues);
|
|
359
363
|
}
|
|
360
364
|
throw new CursorVariantSelectionError(`is stale for model ${JSON.stringify(model.id)}: its exact parameter tuple is unavailable`);
|
|
361
365
|
}
|
|
@@ -46,9 +46,10 @@ export function applyCursorProvider(draft) {
|
|
|
46
46
|
/** Translate one `modelsToConfig` entry into the 2.0 `Model.Info` shape. */
|
|
47
47
|
function applyModelEntry(draft, id, entry) {
|
|
48
48
|
const options = entry.options;
|
|
49
|
-
// Long-context entries get
|
|
50
|
-
// addressing the same Cursor model
|
|
51
|
-
// provider options; 2.0 has a
|
|
49
|
+
// Long-context and Fast entries get synthetic OpenCode ids (`<id>-1m`,
|
|
50
|
+
// `<id>-fast`, `<id>-1m-fast`) while still addressing the same Cursor model
|
|
51
|
+
// on the wire. V1 smuggled that through provider options; 2.0 has a
|
|
52
|
+
// first-class `modelID` for exactly this.
|
|
52
53
|
const wireId = typeof options?.[CURSOR_WIRE_MODEL_ID_KEY] === "string"
|
|
53
54
|
? options[CURSOR_WIRE_MODEL_ID_KEY]
|
|
54
55
|
: id;
|
package/dist/pricing-data.d.ts
CHANGED
|
@@ -13,6 +13,12 @@ export declare const CURSOR_MODEL_COSTS: {
|
|
|
13
13
|
readonly cache_read: 1;
|
|
14
14
|
readonly cache_write: 12.5;
|
|
15
15
|
};
|
|
16
|
+
readonly "claude-fable-5-1": {
|
|
17
|
+
readonly input: 10;
|
|
18
|
+
readonly output: 50;
|
|
19
|
+
readonly cache_read: 0.25;
|
|
20
|
+
readonly cache_write: 12.5;
|
|
21
|
+
};
|
|
16
22
|
readonly "claude-haiku-4-5": {
|
|
17
23
|
readonly input: 1;
|
|
18
24
|
readonly output: 5;
|
|
@@ -79,6 +85,16 @@ export declare const CURSOR_MODEL_COSTS: {
|
|
|
79
85
|
readonly cache_read: 0.2;
|
|
80
86
|
readonly cache_write: 2.5;
|
|
81
87
|
};
|
|
88
|
+
readonly "composer-2.5": {
|
|
89
|
+
readonly input: 0.5;
|
|
90
|
+
readonly output: 2.5;
|
|
91
|
+
readonly cache_read: 0.2;
|
|
92
|
+
};
|
|
93
|
+
readonly "composer-2.5-fast": {
|
|
94
|
+
readonly input: 3;
|
|
95
|
+
readonly output: 15;
|
|
96
|
+
readonly cache_read: 0.5;
|
|
97
|
+
};
|
|
82
98
|
readonly "gemini-2.5-flash": {
|
|
83
99
|
readonly input: 0.3;
|
|
84
100
|
readonly output: 2.5;
|
|
@@ -171,15 +187,15 @@ export declare const CURSOR_MODEL_COSTS: {
|
|
|
171
187
|
readonly cache_write: 0.25;
|
|
172
188
|
};
|
|
173
189
|
readonly "gpt-5.6-sol": {
|
|
174
|
-
readonly input:
|
|
175
|
-
readonly output:
|
|
176
|
-
readonly cache_read: 0.
|
|
177
|
-
readonly cache_write:
|
|
190
|
+
readonly input: 4;
|
|
191
|
+
readonly output: 20;
|
|
192
|
+
readonly cache_read: 0.4;
|
|
193
|
+
readonly cache_write: 5;
|
|
178
194
|
readonly context_over_200k: {
|
|
179
|
-
readonly input:
|
|
180
|
-
readonly output:
|
|
181
|
-
readonly cache_read:
|
|
182
|
-
readonly cache_write:
|
|
195
|
+
readonly input: 8;
|
|
196
|
+
readonly output: 20;
|
|
197
|
+
readonly cache_read: 0.8;
|
|
198
|
+
readonly cache_write: 10;
|
|
183
199
|
};
|
|
184
200
|
};
|
|
185
201
|
readonly "gpt-5.6-terra": {
|
|
@@ -188,6 +204,26 @@ export declare const CURSOR_MODEL_COSTS: {
|
|
|
188
204
|
readonly cache_read: 0.2;
|
|
189
205
|
readonly cache_write: 2.5;
|
|
190
206
|
};
|
|
207
|
+
readonly "grok-4.5": {
|
|
208
|
+
readonly input: 2;
|
|
209
|
+
readonly output: 6;
|
|
210
|
+
readonly cache_read: 0.5;
|
|
211
|
+
};
|
|
212
|
+
readonly "grok-4.5-fast": {
|
|
213
|
+
readonly input: 4;
|
|
214
|
+
readonly output: 18;
|
|
215
|
+
readonly cache_read: 1;
|
|
216
|
+
};
|
|
217
|
+
readonly "grok-4.6": {
|
|
218
|
+
readonly input: 2;
|
|
219
|
+
readonly output: 6;
|
|
220
|
+
readonly cache_read: 0.5;
|
|
221
|
+
};
|
|
222
|
+
readonly "grok-4.6-fast": {
|
|
223
|
+
readonly input: 4;
|
|
224
|
+
readonly output: 12;
|
|
225
|
+
readonly cache_read: 1;
|
|
226
|
+
};
|
|
191
227
|
readonly "kimi-k2.7-code": {
|
|
192
228
|
readonly input: 0.95;
|
|
193
229
|
readonly output: 4;
|
|
@@ -204,6 +240,10 @@ export declare const CURSOR_MODEL_CONTEXTS: {
|
|
|
204
240
|
readonly maxContext: 300000;
|
|
205
241
|
readonly maxContextForMaxMode: 1000000;
|
|
206
242
|
};
|
|
243
|
+
readonly "claude-fable-5-1": {
|
|
244
|
+
readonly maxContext: 300000;
|
|
245
|
+
readonly maxContextForMaxMode: 1000000;
|
|
246
|
+
};
|
|
207
247
|
readonly "claude-haiku-4-5": {
|
|
208
248
|
readonly maxContext: 200000;
|
|
209
249
|
};
|
|
@@ -327,6 +367,9 @@ export declare const CURSOR_MODEL_CAPABILITIES: {
|
|
|
327
367
|
readonly "claude-fable-5": {
|
|
328
368
|
readonly supportsImages: true;
|
|
329
369
|
};
|
|
370
|
+
readonly "claude-fable-5-1": {
|
|
371
|
+
readonly supportsImages: true;
|
|
372
|
+
};
|
|
330
373
|
readonly "claude-haiku-4-5": {
|
|
331
374
|
readonly supportsImages: true;
|
|
332
375
|
};
|
|
@@ -360,9 +403,6 @@ export declare const CURSOR_MODEL_CAPABILITIES: {
|
|
|
360
403
|
readonly "composer-2.5": {
|
|
361
404
|
readonly supportsImages: true;
|
|
362
405
|
};
|
|
363
|
-
readonly default: {
|
|
364
|
-
readonly supportsImages: false;
|
|
365
|
-
};
|
|
366
406
|
readonly "gemini-2.5-flash": {
|
|
367
407
|
readonly supportsImages: true;
|
|
368
408
|
};
|
package/dist/pricing-data.js
CHANGED
|
@@ -13,6 +13,12 @@ export const CURSOR_MODEL_COSTS = {
|
|
|
13
13
|
"cache_read": 1,
|
|
14
14
|
"cache_write": 12.5
|
|
15
15
|
},
|
|
16
|
+
"claude-fable-5-1": {
|
|
17
|
+
"input": 10,
|
|
18
|
+
"output": 50,
|
|
19
|
+
"cache_read": 0.25,
|
|
20
|
+
"cache_write": 12.5
|
|
21
|
+
},
|
|
16
22
|
"claude-haiku-4-5": {
|
|
17
23
|
"input": 1,
|
|
18
24
|
"output": 5,
|
|
@@ -79,6 +85,16 @@ export const CURSOR_MODEL_COSTS = {
|
|
|
79
85
|
"cache_read": 0.2,
|
|
80
86
|
"cache_write": 2.5
|
|
81
87
|
},
|
|
88
|
+
"composer-2.5": {
|
|
89
|
+
"input": 0.5,
|
|
90
|
+
"output": 2.5,
|
|
91
|
+
"cache_read": 0.2
|
|
92
|
+
},
|
|
93
|
+
"composer-2.5-fast": {
|
|
94
|
+
"input": 3,
|
|
95
|
+
"output": 15,
|
|
96
|
+
"cache_read": 0.5
|
|
97
|
+
},
|
|
82
98
|
"gemini-2.5-flash": {
|
|
83
99
|
"input": 0.3,
|
|
84
100
|
"output": 2.5,
|
|
@@ -171,15 +187,15 @@ export const CURSOR_MODEL_COSTS = {
|
|
|
171
187
|
"cache_write": 0.25
|
|
172
188
|
},
|
|
173
189
|
"gpt-5.6-sol": {
|
|
174
|
-
"input":
|
|
175
|
-
"output":
|
|
176
|
-
"cache_read": 0.
|
|
177
|
-
"cache_write":
|
|
190
|
+
"input": 4,
|
|
191
|
+
"output": 20,
|
|
192
|
+
"cache_read": 0.4,
|
|
193
|
+
"cache_write": 5,
|
|
178
194
|
"context_over_200k": {
|
|
179
|
-
"input":
|
|
180
|
-
"output":
|
|
181
|
-
"cache_read":
|
|
182
|
-
"cache_write":
|
|
195
|
+
"input": 8,
|
|
196
|
+
"output": 20,
|
|
197
|
+
"cache_read": 0.8,
|
|
198
|
+
"cache_write": 10
|
|
183
199
|
}
|
|
184
200
|
},
|
|
185
201
|
"gpt-5.6-terra": {
|
|
@@ -188,6 +204,26 @@ export const CURSOR_MODEL_COSTS = {
|
|
|
188
204
|
"cache_read": 0.2,
|
|
189
205
|
"cache_write": 2.5
|
|
190
206
|
},
|
|
207
|
+
"grok-4.5": {
|
|
208
|
+
"input": 2,
|
|
209
|
+
"output": 6,
|
|
210
|
+
"cache_read": 0.5
|
|
211
|
+
},
|
|
212
|
+
"grok-4.5-fast": {
|
|
213
|
+
"input": 4,
|
|
214
|
+
"output": 18,
|
|
215
|
+
"cache_read": 1
|
|
216
|
+
},
|
|
217
|
+
"grok-4.6": {
|
|
218
|
+
"input": 2,
|
|
219
|
+
"output": 6,
|
|
220
|
+
"cache_read": 0.5
|
|
221
|
+
},
|
|
222
|
+
"grok-4.6-fast": {
|
|
223
|
+
"input": 4,
|
|
224
|
+
"output": 12,
|
|
225
|
+
"cache_read": 1
|
|
226
|
+
},
|
|
191
227
|
"kimi-k2.7-code": {
|
|
192
228
|
"input": 0.95,
|
|
193
229
|
"output": 4,
|
|
@@ -204,6 +240,10 @@ export const CURSOR_MODEL_CONTEXTS = {
|
|
|
204
240
|
"maxContext": 300000,
|
|
205
241
|
"maxContextForMaxMode": 1000000
|
|
206
242
|
},
|
|
243
|
+
"claude-fable-5-1": {
|
|
244
|
+
"maxContext": 300000,
|
|
245
|
+
"maxContextForMaxMode": 1000000
|
|
246
|
+
},
|
|
207
247
|
"claude-haiku-4-5": {
|
|
208
248
|
"maxContext": 200000
|
|
209
249
|
},
|
|
@@ -327,6 +367,9 @@ export const CURSOR_MODEL_CAPABILITIES = {
|
|
|
327
367
|
"claude-fable-5": {
|
|
328
368
|
"supportsImages": true
|
|
329
369
|
},
|
|
370
|
+
"claude-fable-5-1": {
|
|
371
|
+
"supportsImages": true
|
|
372
|
+
},
|
|
330
373
|
"claude-haiku-4-5": {
|
|
331
374
|
"supportsImages": true
|
|
332
375
|
},
|
|
@@ -360,9 +403,6 @@ export const CURSOR_MODEL_CAPABILITIES = {
|
|
|
360
403
|
"composer-2.5": {
|
|
361
404
|
"supportsImages": true
|
|
362
405
|
},
|
|
363
|
-
"default": {
|
|
364
|
-
"supportsImages": false
|
|
365
|
-
},
|
|
366
406
|
"gemini-2.5-flash": {
|
|
367
407
|
"supportsImages": true
|
|
368
408
|
},
|
package/dist/pricing.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cursor model token pricing for OpenCode cost reporting.
|
|
3
3
|
*
|
|
4
|
-
* Rates come from Cursor's public docs (
|
|
4
|
+
* Rates come from Cursor's public docs (Cursor Models + Other Models tables).
|
|
5
5
|
* Generated data lives in `pricing-data.ts`; regenerate with
|
|
6
6
|
* `bun run generate:pricing`. Unknown / unpublished models get no `cost`.
|
|
7
7
|
*/
|
|
@@ -32,22 +32,28 @@ export type CursorPricingCoverage = {
|
|
|
32
32
|
};
|
|
33
33
|
/**
|
|
34
34
|
* Models we expose that Cursor does not currently publish numeric rates for
|
|
35
|
-
*
|
|
35
|
+
* (Auto is billed at the routed model's list price).
|
|
36
36
|
*/
|
|
37
|
-
export declare const CURSOR_UNPRICED_MODEL_IDS: readonly ["default"
|
|
37
|
+
export declare const CURSOR_UNPRICED_MODEL_IDS: readonly ["default"];
|
|
38
38
|
export declare function validateOpenCodeModelCost(value: unknown, path?: string): {
|
|
39
39
|
valid: boolean;
|
|
40
40
|
errors: string[];
|
|
41
41
|
};
|
|
42
42
|
export declare function isOpenCodeModelCost(value: unknown): value is OpenCodeModelCost;
|
|
43
|
-
/** Strip synthetic OpenCode
|
|
43
|
+
/** Strip synthetic OpenCode suffixes (`…-1m`, `…-1m-2`, `…-1m-fast`, …). */
|
|
44
44
|
export declare function wireModelIdForPricing(modelId: string): {
|
|
45
45
|
baseId: string;
|
|
46
46
|
longContextEntry: boolean;
|
|
47
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* True when Cursor publishes a distinct Fast rate for this wire model id.
|
|
50
|
+
* Catalog code uses this to split Fast variants into a `-fast` entry.
|
|
51
|
+
*/
|
|
52
|
+
export declare function hasCursorFastPricing(modelId: string): boolean;
|
|
48
53
|
/**
|
|
49
54
|
* Look up classic OpenCode cost for a catalog / wire model id.
|
|
50
55
|
* Synthetic `-1m` entries retain both base and documented long-context rates.
|
|
56
|
+
* Synthetic `-fast` entries are stored as their own keys.
|
|
51
57
|
*/
|
|
52
58
|
export declare function getCursorModelCost(modelId: string): OpenCodeModelCost | undefined;
|
|
53
59
|
export declare function applyCursorModelCost<T extends Record<string, unknown>>(modelId: string, entry: T): T & {
|
package/dist/pricing.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cursor model token pricing for OpenCode cost reporting.
|
|
3
3
|
*
|
|
4
|
-
* Rates come from Cursor's public docs (
|
|
4
|
+
* Rates come from Cursor's public docs (Cursor Models + Other Models tables).
|
|
5
5
|
* Generated data lives in `pricing-data.ts`; regenerate with
|
|
6
6
|
* `bun run generate:pricing`. Unknown / unpublished models get no `cost`.
|
|
7
7
|
*/
|
|
8
8
|
import { CURSOR_MODEL_COSTS } from "./pricing-data.js";
|
|
9
9
|
/**
|
|
10
10
|
* Models we expose that Cursor does not currently publish numeric rates for
|
|
11
|
-
*
|
|
11
|
+
* (Auto is billed at the routed model's list price).
|
|
12
12
|
*/
|
|
13
|
-
export const CURSOR_UNPRICED_MODEL_IDS = ["default"
|
|
13
|
+
export const CURSOR_UNPRICED_MODEL_IDS = ["default"];
|
|
14
14
|
const UNPRICED = new Set(CURSOR_UNPRICED_MODEL_IDS);
|
|
15
15
|
function isRecord(value) {
|
|
16
16
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -47,12 +47,20 @@ export function validateOpenCodeModelCost(value, path = "cost") {
|
|
|
47
47
|
export function isOpenCodeModelCost(value) {
|
|
48
48
|
return validateOpenCodeModelCost(value).valid;
|
|
49
49
|
}
|
|
50
|
-
/** Strip synthetic OpenCode
|
|
50
|
+
/** Strip synthetic OpenCode suffixes (`…-1m`, `…-1m-2`, `…-1m-fast`, …). */
|
|
51
51
|
export function wireModelIdForPricing(modelId) {
|
|
52
|
-
const match = /^(.*)-1m(
|
|
53
|
-
if (
|
|
54
|
-
return { baseId:
|
|
55
|
-
|
|
52
|
+
const match = /^(.*)-1m(?:-\d+)?(-fast)?$/.exec(modelId);
|
|
53
|
+
if (match) {
|
|
54
|
+
return { baseId: `${match[1]}${match[2] ?? ""}`, longContextEntry: true };
|
|
55
|
+
}
|
|
56
|
+
return { baseId: modelId, longContextEntry: false };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* True when Cursor publishes a distinct Fast rate for this wire model id.
|
|
60
|
+
* Catalog code uses this to split Fast variants into a `-fast` entry.
|
|
61
|
+
*/
|
|
62
|
+
export function hasCursorFastPricing(modelId) {
|
|
63
|
+
return Object.prototype.hasOwnProperty.call(CURSOR_MODEL_COSTS, `${modelId}-fast`);
|
|
56
64
|
}
|
|
57
65
|
function asMutableCost(value) {
|
|
58
66
|
const copy = { input: value.input, output: value.output };
|
|
@@ -68,6 +76,7 @@ function asMutableCost(value) {
|
|
|
68
76
|
/**
|
|
69
77
|
* Look up classic OpenCode cost for a catalog / wire model id.
|
|
70
78
|
* Synthetic `-1m` entries retain both base and documented long-context rates.
|
|
79
|
+
* Synthetic `-fast` entries are stored as their own keys.
|
|
71
80
|
*/
|
|
72
81
|
export function getCursorModelCost(modelId) {
|
|
73
82
|
const { baseId } = wireModelIdForPricing(modelId);
|
|
@@ -22,3 +22,8 @@ export declare const CURSOR_EXEC_VARIANTS: readonly CursorExecVariant[];
|
|
|
22
22
|
export declare function cursorExecVariantByRequestField(field: number): CursorExecVariant | undefined;
|
|
23
23
|
export declare function cursorExecVariantByRequestName(name: string): CursorExecVariant | undefined;
|
|
24
24
|
export declare function describeCursorExecVariant(field: number | undefined): string;
|
|
25
|
+
/**
|
|
26
|
+
* `ForceBackgroundShellResult` / `ForceBackgroundSubagentResult` status.
|
|
27
|
+
* Cursor CLI `ForceBackgroundStatus`: 0 unspecified, 1 ok, 2 error.
|
|
28
|
+
*/
|
|
29
|
+
export declare const FORCE_BACKGROUND_STATUS_ERROR = 2;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export const CURSOR_EXEC_VARIANTS = [
|
|
2
|
-
{ requestField: 2, requestName: "shell_args", resultField: 2, resultName: "shell_result", handling: "
|
|
2
|
+
{ requestField: 2, requestName: "shell_args", resultField: 2, resultName: "shell_result", handling: "opencode-tool" },
|
|
3
3
|
{ requestField: 3, requestName: "write_args", resultField: 3, resultName: "write_result", handling: "opencode-tool" },
|
|
4
4
|
{ requestField: 4, requestName: "delete_args", resultField: 4, resultName: "delete_result", handling: "opencode-tool" },
|
|
5
5
|
{ requestField: 5, requestName: "grep_args", resultField: 5, resultName: "grep_result", handling: "opencode-tool" },
|
|
6
6
|
{ requestField: 7, requestName: "read_args", resultField: 7, resultName: "read_result", handling: "opencode-tool" },
|
|
7
7
|
{ requestField: 8, requestName: "ls_args", resultField: 8, resultName: "ls_result", handling: "opencode-tool" },
|
|
8
|
+
// Dedicated Cursor read_lints (#9) is not planned. OpenCode only presents
|
|
9
|
+
// LSP errors on write/edit/apply_patch output plus GET /lsp status / navigation.
|
|
8
10
|
{ requestField: 9, requestName: "diagnostics_args", resultField: 9, resultName: "diagnostics_result", handling: "unsupported" },
|
|
9
11
|
{ requestField: 10, requestName: "request_context_args", resultField: 10, resultName: "request_context_result", handling: "provider-control" },
|
|
10
12
|
{ requestField: 11, requestName: "mcp_args", resultField: 11, resultName: "mcp_result", handling: "opencode-tool" },
|
|
@@ -23,12 +25,13 @@ export const CURSOR_EXEC_VARIANTS = [
|
|
|
23
25
|
{ requestField: 31, requestName: "force_background_subagent_args", resultField: 31, resultName: "force_background_subagent_result", handling: "unsupported" },
|
|
24
26
|
{ requestField: 36, requestName: "mcp_state_exec_args", resultField: 36, resultName: "mcp_state_exec_result", handling: "provider-control" },
|
|
25
27
|
{ requestField: 37, requestName: "subagent_await_args", resultField: 37, resultName: "subagent_await_result", handling: "unsupported" },
|
|
28
|
+
// OpenCode has no Auto-review / `--auto-review` mode. Not planned: keep the typed soft-deny.
|
|
26
29
|
{ requestField: 38, requestName: "smart_mode_classifier_args", resultField: 38, resultName: "smart_mode_classifier_result", handling: "unsupported" },
|
|
27
30
|
{ requestField: 40, requestName: "canvas_diagnostics_args", resultField: 40, resultName: "canvas_diagnostics_result", handling: "unsupported" },
|
|
28
31
|
{ requestField: 41, requestName: "shell_allowlist_precheck_args", resultField: 41, resultName: "shell_allowlist_precheck_result", handling: "unsupported" },
|
|
29
32
|
{ requestField: 42, requestName: "mcp_allowlist_precheck_args", resultField: 42, resultName: "mcp_allowlist_precheck_result", handling: "unsupported" },
|
|
30
33
|
{ requestField: 43, requestName: "web_fetch_allowlist_precheck_args", resultField: 43, resultName: "web_fetch_allowlist_precheck_result", handling: "unsupported" },
|
|
31
|
-
{ requestField: 44, requestName: "git_diff_request", resultField: 44, resultName: "git_diff_response", handling: "
|
|
34
|
+
{ requestField: 44, requestName: "git_diff_request", resultField: 44, resultName: "git_diff_response", handling: "provider-control" },
|
|
32
35
|
{ requestField: 45, requestName: "pi_read_args", resultField: 46, resultName: "pi_read_result", handling: "opencode-tool" },
|
|
33
36
|
{ requestField: 46, requestName: "pi_bash_args", resultField: 47, resultName: "pi_bash_result", handling: "opencode-tool" },
|
|
34
37
|
{ requestField: 47, requestName: "pi_edit_args", resultField: 48, resultName: "pi_edit_result", handling: "opencode-tool" },
|
|
@@ -36,6 +39,13 @@ export const CURSOR_EXEC_VARIANTS = [
|
|
|
36
39
|
{ requestField: 49, requestName: "pi_grep_args", resultField: 50, resultName: "pi_grep_result", handling: "opencode-tool" },
|
|
37
40
|
{ requestField: 50, requestName: "pi_find_args", resultField: 51, resultName: "pi_find_result", handling: "opencode-tool" },
|
|
38
41
|
{ requestField: 51, requestName: "pi_ls_args", resultField: 52, resultName: "pi_ls_result", handling: "opencode-tool" },
|
|
42
|
+
// Mini-SWE request #52 pairs with ShellResult at #55 (Pi-style offset; #55
|
|
43
|
+
// request is accept_hook_additional_contexts, not a variant).
|
|
44
|
+
// Mini-SWE / SWE-agent bash is not planned (same surface as Auto-review). Keep the typed soft-deny.
|
|
45
|
+
{ requestField: 52, requestName: "mini_swe_agent_bash_args", resultField: 55, resultName: "mini_swe_agent_bash_result", handling: "unsupported" },
|
|
46
|
+
{ requestField: 53, requestName: "conversation_search_args", resultField: 53, resultName: "conversation_search_result", handling: "unsupported" },
|
|
47
|
+
{ requestField: 54, requestName: "agent_store_conflict_args", resultField: 54, resultName: "agent_store_conflict_result", handling: "unsupported" },
|
|
48
|
+
{ requestField: 56, requestName: "adopt_args", resultField: 56, resultName: "adopt_result", handling: "unsupported" },
|
|
39
49
|
];
|
|
40
50
|
const BY_REQUEST_FIELD = new Map(CURSOR_EXEC_VARIANTS.map((variant) => [variant.requestField, variant]));
|
|
41
51
|
const BY_REQUEST_NAME = new Map(CURSOR_EXEC_VARIANTS.map((variant) => [variant.requestName, variant]));
|
|
@@ -53,3 +63,8 @@ export function describeCursorExecVariant(field) {
|
|
|
53
63
|
return `unknown request field #${field}`;
|
|
54
64
|
return `${variant.requestName} (request field #${variant.requestField}, expected result ${variant.resultName} field #${variant.resultField}, handling=${variant.handling})`;
|
|
55
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* `ForceBackgroundShellResult` / `ForceBackgroundSubagentResult` status.
|
|
68
|
+
* Cursor CLI `ForceBackgroundStatus`: 0 unspecified, 1 ok, 2 error.
|
|
69
|
+
*/
|
|
70
|
+
export const FORCE_BACKGROUND_STATUS_ERROR = 2;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** aiserver.v1.GetDiffRequest.OutputFormat */
|
|
2
|
+
export declare const GIT_DIFF_FORMAT_UNSPECIFIED = 0;
|
|
3
|
+
export declare const GIT_DIFF_FORMAT_NAME_STATUS = 1;
|
|
4
|
+
export declare const GIT_DIFF_FORMAT_NAME_STATUS_AND_NUMSTAT = 2;
|
|
5
|
+
export declare const GIT_DIFF_FORMAT_FILE_DIFFS = 3;
|
|
6
|
+
export declare const GIT_DIFF_FORMAT_DIFFS_WITH_BEFORE_AND_AFTER = 4;
|
|
7
|
+
export type GitDiffChunk = {
|
|
8
|
+
content: string;
|
|
9
|
+
lines: string[];
|
|
10
|
+
old_start: number;
|
|
11
|
+
old_lines: number;
|
|
12
|
+
new_start: number;
|
|
13
|
+
new_lines: number;
|
|
14
|
+
};
|
|
15
|
+
export type GitFileDiff = {
|
|
16
|
+
from: string;
|
|
17
|
+
to: string;
|
|
18
|
+
chunks: GitDiffChunk[];
|
|
19
|
+
added: number;
|
|
20
|
+
removed: number;
|
|
21
|
+
};
|
|
22
|
+
/** Parse `git diff --no-color` into aiserver.v1.FileDiff rows (CLI `Oc` / `FR`). */
|
|
23
|
+
export declare function parseUnifiedDiff(text: string): GitFileDiff[];
|
|
24
|
+
export declare function executeGitDiff(request: Record<string, unknown>, workspaceRoot: string): Promise<Record<string, unknown>>;
|
|
25
|
+
/**
|
|
26
|
+
* Answer exec #44. GetDiffResponse has no error oneof — failures use
|
|
27
|
+
* exec_client_control_message.throw, matching Cursor CLI `class Dc`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildGitDiffExecMessages(input: {
|
|
30
|
+
execId: number;
|
|
31
|
+
request: Record<string, unknown>;
|
|
32
|
+
workspaceRoot: string;
|
|
33
|
+
}): Promise<Uint8Array[]>;
|