cursor-opencode-provider 0.3.1 → 0.4.0
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 +29 -4
- package/dist/image-input.d.ts +31 -0
- package/dist/image-input.js +281 -0
- package/dist/language-model.js +68 -1
- package/dist/model-config.js +15 -5
- package/dist/model-metadata.d.ts +10 -0
- package/dist/model-metadata.js +12 -0
- package/dist/models.d.ts +1 -0
- package/dist/models.js +8 -0
- package/dist/opencode2/catalog.js +10 -5
- package/dist/opencode2/types.d.ts +22 -4
- package/dist/opencode2/types.js +1 -1
- package/dist/plugin-opencode2.js +13 -5
- package/dist/pricing-data.d.ts +414 -0
- package/dist/pricing-data.js +414 -0
- package/dist/pricing.d.ts +62 -0
- package/dist/pricing.js +127 -0
- package/dist/protocol/messages.js +21 -0
- package/dist/protocol/request.d.ts +2 -0
- package/dist/protocol/request.js +14 -5
- package/dist/shared.d.ts +1 -1
- package/dist/shared.js +1 -1
- package/package.json +20 -5
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AUTO-GENERATED by scripts/generate-cursor-pricing.ts — do not edit by hand.
|
|
3
|
+
* Pricing source: https://cursor.com/docs/models-and-pricing.md
|
|
4
|
+
* Context source: https://cursor.com/docs.md
|
|
5
|
+
* Regenerate: bun run generate:pricing
|
|
6
|
+
*/
|
|
7
|
+
export const CURSOR_PRICING_SOURCE = "https://cursor.com/docs/models-and-pricing.md";
|
|
8
|
+
export const CURSOR_CONTEXT_SOURCE = "https://cursor.com/docs.md";
|
|
9
|
+
export const CURSOR_MODEL_COSTS = {
|
|
10
|
+
"claude-fable-5": {
|
|
11
|
+
"input": 10,
|
|
12
|
+
"output": 50,
|
|
13
|
+
"cache_read": 1,
|
|
14
|
+
"cache_write": 12.5
|
|
15
|
+
},
|
|
16
|
+
"claude-haiku-4-5": {
|
|
17
|
+
"input": 1,
|
|
18
|
+
"output": 5,
|
|
19
|
+
"cache_read": 0.1,
|
|
20
|
+
"cache_write": 1.25
|
|
21
|
+
},
|
|
22
|
+
"claude-opus-4-5": {
|
|
23
|
+
"input": 5,
|
|
24
|
+
"output": 25,
|
|
25
|
+
"cache_read": 0.5,
|
|
26
|
+
"cache_write": 6.25
|
|
27
|
+
},
|
|
28
|
+
"claude-opus-4-6": {
|
|
29
|
+
"input": 5,
|
|
30
|
+
"output": 25,
|
|
31
|
+
"cache_read": 0.5,
|
|
32
|
+
"cache_write": 6.25
|
|
33
|
+
},
|
|
34
|
+
"claude-opus-4-7": {
|
|
35
|
+
"input": 5,
|
|
36
|
+
"output": 25,
|
|
37
|
+
"cache_read": 0.5,
|
|
38
|
+
"cache_write": 6.25
|
|
39
|
+
},
|
|
40
|
+
"claude-opus-4-8": {
|
|
41
|
+
"input": 5,
|
|
42
|
+
"output": 25,
|
|
43
|
+
"cache_read": 0.5,
|
|
44
|
+
"cache_write": 6.25
|
|
45
|
+
},
|
|
46
|
+
"claude-opus-5": {
|
|
47
|
+
"input": 5,
|
|
48
|
+
"output": 25,
|
|
49
|
+
"cache_read": 0.5,
|
|
50
|
+
"cache_write": 6.25
|
|
51
|
+
},
|
|
52
|
+
"claude-sonnet-4": {
|
|
53
|
+
"input": 3,
|
|
54
|
+
"output": 15,
|
|
55
|
+
"cache_read": 0.3,
|
|
56
|
+
"cache_write": 3.75,
|
|
57
|
+
"context_over_200k": {
|
|
58
|
+
"input": 6,
|
|
59
|
+
"output": 22.5,
|
|
60
|
+
"cache_read": 0.6,
|
|
61
|
+
"cache_write": 7.5
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"claude-sonnet-4-5": {
|
|
65
|
+
"input": 3,
|
|
66
|
+
"output": 15,
|
|
67
|
+
"cache_read": 0.3,
|
|
68
|
+
"cache_write": 3.75
|
|
69
|
+
},
|
|
70
|
+
"claude-sonnet-4-6": {
|
|
71
|
+
"input": 3,
|
|
72
|
+
"output": 15,
|
|
73
|
+
"cache_read": 0.3,
|
|
74
|
+
"cache_write": 3.75
|
|
75
|
+
},
|
|
76
|
+
"claude-sonnet-5": {
|
|
77
|
+
"input": 3,
|
|
78
|
+
"output": 15,
|
|
79
|
+
"cache_read": 0.3,
|
|
80
|
+
"cache_write": 3.75
|
|
81
|
+
},
|
|
82
|
+
"gemini-2.5-flash": {
|
|
83
|
+
"input": 0.3,
|
|
84
|
+
"output": 2.5,
|
|
85
|
+
"cache_read": 0.03
|
|
86
|
+
},
|
|
87
|
+
"gemini-3-flash": {
|
|
88
|
+
"input": 0.5,
|
|
89
|
+
"output": 3,
|
|
90
|
+
"cache_read": 0.05
|
|
91
|
+
},
|
|
92
|
+
"gemini-3.1-pro": {
|
|
93
|
+
"input": 2,
|
|
94
|
+
"output": 12,
|
|
95
|
+
"cache_read": 0.2
|
|
96
|
+
},
|
|
97
|
+
"gemini-3.5-flash": {
|
|
98
|
+
"input": 1.5,
|
|
99
|
+
"output": 9,
|
|
100
|
+
"cache_read": 0.15
|
|
101
|
+
},
|
|
102
|
+
"gemini-3.6-flash": {
|
|
103
|
+
"input": 1.5,
|
|
104
|
+
"output": 7.5,
|
|
105
|
+
"cache_read": 0.15
|
|
106
|
+
},
|
|
107
|
+
"glm-5.2": {
|
|
108
|
+
"input": 1.4,
|
|
109
|
+
"output": 4.4,
|
|
110
|
+
"cache_read": 0.26
|
|
111
|
+
},
|
|
112
|
+
"gpt-5-mini": {
|
|
113
|
+
"input": 0.25,
|
|
114
|
+
"output": 2,
|
|
115
|
+
"cache_read": 0.025
|
|
116
|
+
},
|
|
117
|
+
"gpt-5.1": {
|
|
118
|
+
"input": 1.25,
|
|
119
|
+
"output": 10,
|
|
120
|
+
"cache_read": 0.125
|
|
121
|
+
},
|
|
122
|
+
"gpt-5.2": {
|
|
123
|
+
"input": 1.75,
|
|
124
|
+
"output": 14,
|
|
125
|
+
"cache_read": 0.175
|
|
126
|
+
},
|
|
127
|
+
"gpt-5.3-codex": {
|
|
128
|
+
"input": 1.75,
|
|
129
|
+
"output": 14,
|
|
130
|
+
"cache_read": 0.175
|
|
131
|
+
},
|
|
132
|
+
"gpt-5.4": {
|
|
133
|
+
"input": 2.5,
|
|
134
|
+
"output": 15,
|
|
135
|
+
"cache_read": 0.25,
|
|
136
|
+
"context_over_200k": {
|
|
137
|
+
"input": 5,
|
|
138
|
+
"output": 15,
|
|
139
|
+
"cache_read": 0.5
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"gpt-5.4-mini": {
|
|
143
|
+
"input": 0.75,
|
|
144
|
+
"output": 4.5,
|
|
145
|
+
"cache_read": 0.075
|
|
146
|
+
},
|
|
147
|
+
"gpt-5.4-nano": {
|
|
148
|
+
"input": 0.2,
|
|
149
|
+
"output": 1.25,
|
|
150
|
+
"cache_read": 0.02
|
|
151
|
+
},
|
|
152
|
+
"gpt-5.5": {
|
|
153
|
+
"input": 5,
|
|
154
|
+
"output": 30,
|
|
155
|
+
"cache_read": 0.5,
|
|
156
|
+
"context_over_200k": {
|
|
157
|
+
"input": 10,
|
|
158
|
+
"output": 30,
|
|
159
|
+
"cache_read": 1
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
"gpt-5.6-luna": {
|
|
163
|
+
"input": 0.2,
|
|
164
|
+
"output": 1.2,
|
|
165
|
+
"cache_read": 0.02,
|
|
166
|
+
"cache_write": 0.25
|
|
167
|
+
},
|
|
168
|
+
"gpt-5.6-sol": {
|
|
169
|
+
"input": 5,
|
|
170
|
+
"output": 30,
|
|
171
|
+
"cache_read": 0.5,
|
|
172
|
+
"cache_write": 6.25,
|
|
173
|
+
"context_over_200k": {
|
|
174
|
+
"input": 10,
|
|
175
|
+
"output": 30,
|
|
176
|
+
"cache_read": 1,
|
|
177
|
+
"cache_write": 12.5
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
"gpt-5.6-terra": {
|
|
181
|
+
"input": 2,
|
|
182
|
+
"output": 12,
|
|
183
|
+
"cache_read": 0.2,
|
|
184
|
+
"cache_write": 2.5
|
|
185
|
+
},
|
|
186
|
+
"kimi-k2.7-code": {
|
|
187
|
+
"input": 0.95,
|
|
188
|
+
"output": 4,
|
|
189
|
+
"cache_read": 0.19
|
|
190
|
+
},
|
|
191
|
+
"kimi-k3": {
|
|
192
|
+
"input": 3,
|
|
193
|
+
"output": 15,
|
|
194
|
+
"cache_read": 0.3
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
export const CURSOR_MODEL_CONTEXTS = {
|
|
198
|
+
"claude-fable-5": {
|
|
199
|
+
"maxContext": 300000,
|
|
200
|
+
"maxContextForMaxMode": 1000000
|
|
201
|
+
},
|
|
202
|
+
"claude-haiku-4-5": {
|
|
203
|
+
"maxContext": 200000
|
|
204
|
+
},
|
|
205
|
+
"claude-opus-4-5": {
|
|
206
|
+
"maxContext": 200000,
|
|
207
|
+
"maxContextForMaxMode": 200000
|
|
208
|
+
},
|
|
209
|
+
"claude-opus-4-6": {
|
|
210
|
+
"maxContext": 200000,
|
|
211
|
+
"maxContextForMaxMode": 1000000
|
|
212
|
+
},
|
|
213
|
+
"claude-opus-4-7": {
|
|
214
|
+
"maxContext": 300000,
|
|
215
|
+
"maxContextForMaxMode": 1000000
|
|
216
|
+
},
|
|
217
|
+
"claude-opus-4-8": {
|
|
218
|
+
"maxContext": 300000,
|
|
219
|
+
"maxContextForMaxMode": 1000000
|
|
220
|
+
},
|
|
221
|
+
"claude-opus-5": {
|
|
222
|
+
"maxContext": 300000,
|
|
223
|
+
"maxContextForMaxMode": 1000000
|
|
224
|
+
},
|
|
225
|
+
"claude-sonnet-4": {
|
|
226
|
+
"maxContext": 200000,
|
|
227
|
+
"maxContextForMaxMode": 1000000
|
|
228
|
+
},
|
|
229
|
+
"claude-sonnet-4-5": {
|
|
230
|
+
"maxContext": 200000,
|
|
231
|
+
"maxContextForMaxMode": 1000000
|
|
232
|
+
},
|
|
233
|
+
"claude-sonnet-4-6": {
|
|
234
|
+
"maxContext": 200000,
|
|
235
|
+
"maxContextForMaxMode": 1000000
|
|
236
|
+
},
|
|
237
|
+
"claude-sonnet-5": {
|
|
238
|
+
"maxContext": 200000,
|
|
239
|
+
"maxContextForMaxMode": 1000000
|
|
240
|
+
},
|
|
241
|
+
"composer-2.5": {
|
|
242
|
+
"maxContext": 200000
|
|
243
|
+
},
|
|
244
|
+
"gemini-2.5-flash": {
|
|
245
|
+
"maxContext": 200000,
|
|
246
|
+
"maxContextForMaxMode": 1000000
|
|
247
|
+
},
|
|
248
|
+
"gemini-3-flash": {
|
|
249
|
+
"maxContext": 200000,
|
|
250
|
+
"maxContextForMaxMode": 1000000
|
|
251
|
+
},
|
|
252
|
+
"gemini-3.1-pro": {
|
|
253
|
+
"maxContext": 200000,
|
|
254
|
+
"maxContextForMaxMode": 1000000
|
|
255
|
+
},
|
|
256
|
+
"gemini-3.5-flash": {
|
|
257
|
+
"maxContext": 200000,
|
|
258
|
+
"maxContextForMaxMode": 1000000
|
|
259
|
+
},
|
|
260
|
+
"gemini-3.6-flash": {
|
|
261
|
+
"maxContext": 200000,
|
|
262
|
+
"maxContextForMaxMode": 1000000
|
|
263
|
+
},
|
|
264
|
+
"glm-5.2": {
|
|
265
|
+
"maxContext": 200000
|
|
266
|
+
},
|
|
267
|
+
"gpt-5-mini": {
|
|
268
|
+
"maxContext": 272000
|
|
269
|
+
},
|
|
270
|
+
"gpt-5.1": {
|
|
271
|
+
"maxContext": 272000
|
|
272
|
+
},
|
|
273
|
+
"gpt-5.2": {
|
|
274
|
+
"maxContext": 272000
|
|
275
|
+
},
|
|
276
|
+
"gpt-5.3-codex": {
|
|
277
|
+
"maxContext": 272000
|
|
278
|
+
},
|
|
279
|
+
"gpt-5.4": {
|
|
280
|
+
"maxContext": 272000,
|
|
281
|
+
"maxContextForMaxMode": 1000000
|
|
282
|
+
},
|
|
283
|
+
"gpt-5.4-mini": {
|
|
284
|
+
"maxContext": 272000
|
|
285
|
+
},
|
|
286
|
+
"gpt-5.4-nano": {
|
|
287
|
+
"maxContext": 272000
|
|
288
|
+
},
|
|
289
|
+
"gpt-5.5": {
|
|
290
|
+
"maxContext": 272000,
|
|
291
|
+
"maxContextForMaxMode": 1000000
|
|
292
|
+
},
|
|
293
|
+
"gpt-5.6-luna": {
|
|
294
|
+
"maxContext": 272000
|
|
295
|
+
},
|
|
296
|
+
"gpt-5.6-sol": {
|
|
297
|
+
"maxContext": 272000,
|
|
298
|
+
"maxContextForMaxMode": 1000000
|
|
299
|
+
},
|
|
300
|
+
"gpt-5.6-terra": {
|
|
301
|
+
"maxContext": 272000
|
|
302
|
+
},
|
|
303
|
+
"grok-4.5": {
|
|
304
|
+
"maxContext": 256000
|
|
305
|
+
},
|
|
306
|
+
"kimi-k2.7-code": {
|
|
307
|
+
"maxContext": 262000
|
|
308
|
+
},
|
|
309
|
+
"kimi-k3": {
|
|
310
|
+
"maxContext": 200000,
|
|
311
|
+
"maxContextForMaxMode": 1000000
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
export const CURSOR_MODEL_CAPABILITIES = {
|
|
315
|
+
"claude-fable-5": {
|
|
316
|
+
"supportsImages": true
|
|
317
|
+
},
|
|
318
|
+
"claude-haiku-4-5": {
|
|
319
|
+
"supportsImages": true
|
|
320
|
+
},
|
|
321
|
+
"claude-opus-4-5": {
|
|
322
|
+
"supportsImages": true
|
|
323
|
+
},
|
|
324
|
+
"claude-opus-4-6": {
|
|
325
|
+
"supportsImages": true
|
|
326
|
+
},
|
|
327
|
+
"claude-opus-4-7": {
|
|
328
|
+
"supportsImages": true
|
|
329
|
+
},
|
|
330
|
+
"claude-opus-4-8": {
|
|
331
|
+
"supportsImages": true
|
|
332
|
+
},
|
|
333
|
+
"claude-opus-5": {
|
|
334
|
+
"supportsImages": true
|
|
335
|
+
},
|
|
336
|
+
"claude-sonnet-4": {
|
|
337
|
+
"supportsImages": true
|
|
338
|
+
},
|
|
339
|
+
"claude-sonnet-4-5": {
|
|
340
|
+
"supportsImages": true
|
|
341
|
+
},
|
|
342
|
+
"claude-sonnet-4-6": {
|
|
343
|
+
"supportsImages": true
|
|
344
|
+
},
|
|
345
|
+
"claude-sonnet-5": {
|
|
346
|
+
"supportsImages": true
|
|
347
|
+
},
|
|
348
|
+
"composer-2.5": {
|
|
349
|
+
"supportsImages": true
|
|
350
|
+
},
|
|
351
|
+
"default": {
|
|
352
|
+
"supportsImages": false
|
|
353
|
+
},
|
|
354
|
+
"gemini-2.5-flash": {
|
|
355
|
+
"supportsImages": true
|
|
356
|
+
},
|
|
357
|
+
"gemini-3-flash": {
|
|
358
|
+
"supportsImages": true
|
|
359
|
+
},
|
|
360
|
+
"gemini-3.1-pro": {
|
|
361
|
+
"supportsImages": true
|
|
362
|
+
},
|
|
363
|
+
"gemini-3.5-flash": {
|
|
364
|
+
"supportsImages": true
|
|
365
|
+
},
|
|
366
|
+
"gemini-3.6-flash": {
|
|
367
|
+
"supportsImages": true
|
|
368
|
+
},
|
|
369
|
+
"glm-5.2": {
|
|
370
|
+
"supportsImages": false
|
|
371
|
+
},
|
|
372
|
+
"gpt-5-mini": {
|
|
373
|
+
"supportsImages": true
|
|
374
|
+
},
|
|
375
|
+
"gpt-5.1": {
|
|
376
|
+
"supportsImages": true
|
|
377
|
+
},
|
|
378
|
+
"gpt-5.2": {
|
|
379
|
+
"supportsImages": true
|
|
380
|
+
},
|
|
381
|
+
"gpt-5.3-codex": {
|
|
382
|
+
"supportsImages": true
|
|
383
|
+
},
|
|
384
|
+
"gpt-5.4": {
|
|
385
|
+
"supportsImages": true
|
|
386
|
+
},
|
|
387
|
+
"gpt-5.4-mini": {
|
|
388
|
+
"supportsImages": true
|
|
389
|
+
},
|
|
390
|
+
"gpt-5.4-nano": {
|
|
391
|
+
"supportsImages": true
|
|
392
|
+
},
|
|
393
|
+
"gpt-5.5": {
|
|
394
|
+
"supportsImages": true
|
|
395
|
+
},
|
|
396
|
+
"gpt-5.6-luna": {
|
|
397
|
+
"supportsImages": true
|
|
398
|
+
},
|
|
399
|
+
"gpt-5.6-sol": {
|
|
400
|
+
"supportsImages": true
|
|
401
|
+
},
|
|
402
|
+
"gpt-5.6-terra": {
|
|
403
|
+
"supportsImages": true
|
|
404
|
+
},
|
|
405
|
+
"grok-4.5": {
|
|
406
|
+
"supportsImages": false
|
|
407
|
+
},
|
|
408
|
+
"kimi-k2.7-code": {
|
|
409
|
+
"supportsImages": true
|
|
410
|
+
},
|
|
411
|
+
"kimi-k3": {
|
|
412
|
+
"supportsImages": true
|
|
413
|
+
}
|
|
414
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor model token pricing for OpenCode cost reporting.
|
|
3
|
+
*
|
|
4
|
+
* Rates come from Cursor's public docs (Other Models pool = provider API price).
|
|
5
|
+
* Generated data lives in `pricing-data.ts`; regenerate with
|
|
6
|
+
* `bun run generate:pricing`. Unknown / unpublished models get no `cost`.
|
|
7
|
+
*/
|
|
8
|
+
/** Classic OpenCode / models.dev cost shape used in provider config. */
|
|
9
|
+
export type OpenCodeModelCost = {
|
|
10
|
+
input: number;
|
|
11
|
+
output: number;
|
|
12
|
+
cache_read?: number;
|
|
13
|
+
cache_write?: number;
|
|
14
|
+
context_over_200k?: OpenCodeModelCost;
|
|
15
|
+
};
|
|
16
|
+
/** OpenCode 2.0 `Model.Info.cost` entry (array of tiered rates). */
|
|
17
|
+
export type OpenCode2ModelCost = {
|
|
18
|
+
tier?: {
|
|
19
|
+
type: "context";
|
|
20
|
+
size: number;
|
|
21
|
+
};
|
|
22
|
+
input: number;
|
|
23
|
+
output: number;
|
|
24
|
+
cache: {
|
|
25
|
+
read: number;
|
|
26
|
+
write: number;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export type CursorPricingCoverage = {
|
|
30
|
+
priced: string[];
|
|
31
|
+
missing: string[];
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Models we expose that Cursor does not currently publish numeric rates for
|
|
35
|
+
* on the Other Models table (Auto / first-party Cursor Models pool).
|
|
36
|
+
*/
|
|
37
|
+
export declare const CURSOR_UNPRICED_MODEL_IDS: readonly ["default", "composer-2.5", "grok-4.5"];
|
|
38
|
+
export declare function validateOpenCodeModelCost(value: unknown, path?: string): {
|
|
39
|
+
valid: boolean;
|
|
40
|
+
errors: string[];
|
|
41
|
+
};
|
|
42
|
+
export declare function isOpenCodeModelCost(value: unknown): value is OpenCodeModelCost;
|
|
43
|
+
/** Strip synthetic OpenCode long-context suffix (`…-1m`, `…-1m-2`, …). */
|
|
44
|
+
export declare function wireModelIdForPricing(modelId: string): {
|
|
45
|
+
baseId: string;
|
|
46
|
+
longContextEntry: boolean;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Look up classic OpenCode cost for a catalog / wire model id.
|
|
50
|
+
* Synthetic `-1m` entries retain both base and documented long-context rates.
|
|
51
|
+
*/
|
|
52
|
+
export declare function getCursorModelCost(modelId: string): OpenCodeModelCost | undefined;
|
|
53
|
+
export declare function applyCursorModelCost<T extends Record<string, unknown>>(modelId: string, entry: T): T & {
|
|
54
|
+
cost?: OpenCodeModelCost;
|
|
55
|
+
};
|
|
56
|
+
/** Convert classic cost → OpenCode 2.0 `Model.Info.cost` array. */
|
|
57
|
+
export declare function toOpenCode2Costs(cost: OpenCodeModelCost | undefined): OpenCode2ModelCost[];
|
|
58
|
+
/**
|
|
59
|
+
* Coverage helper for CI / maintainer checks.
|
|
60
|
+
* Intentionally unpriced first-party ids are counted as priced (covered).
|
|
61
|
+
*/
|
|
62
|
+
export declare function checkCursorPricingCoverage(modelIds: string[]): CursorPricingCoverage;
|
package/dist/pricing.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor model token pricing for OpenCode cost reporting.
|
|
3
|
+
*
|
|
4
|
+
* Rates come from Cursor's public docs (Other Models pool = provider API price).
|
|
5
|
+
* Generated data lives in `pricing-data.ts`; regenerate with
|
|
6
|
+
* `bun run generate:pricing`. Unknown / unpublished models get no `cost`.
|
|
7
|
+
*/
|
|
8
|
+
import { CURSOR_MODEL_COSTS } from "./pricing-data.js";
|
|
9
|
+
/**
|
|
10
|
+
* Models we expose that Cursor does not currently publish numeric rates for
|
|
11
|
+
* on the Other Models table (Auto / first-party Cursor Models pool).
|
|
12
|
+
*/
|
|
13
|
+
export const CURSOR_UNPRICED_MODEL_IDS = ["default", "composer-2.5", "grok-4.5"];
|
|
14
|
+
const UNPRICED = new Set(CURSOR_UNPRICED_MODEL_IDS);
|
|
15
|
+
function isRecord(value) {
|
|
16
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17
|
+
}
|
|
18
|
+
function isNonNegativeFiniteNumber(value) {
|
|
19
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
20
|
+
}
|
|
21
|
+
function collectCostValidationErrors(value, path, errors) {
|
|
22
|
+
if (!isRecord(value)) {
|
|
23
|
+
errors.push(`${path} must be an object`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (!isNonNegativeFiniteNumber(value.input)) {
|
|
27
|
+
errors.push(`${path}.input must be a non-negative finite number`);
|
|
28
|
+
}
|
|
29
|
+
if (!isNonNegativeFiniteNumber(value.output)) {
|
|
30
|
+
errors.push(`${path}.output must be a non-negative finite number`);
|
|
31
|
+
}
|
|
32
|
+
if (value.cache_read !== undefined && !isNonNegativeFiniteNumber(value.cache_read)) {
|
|
33
|
+
errors.push(`${path}.cache_read must be a non-negative finite number`);
|
|
34
|
+
}
|
|
35
|
+
if (value.cache_write !== undefined && !isNonNegativeFiniteNumber(value.cache_write)) {
|
|
36
|
+
errors.push(`${path}.cache_write must be a non-negative finite number`);
|
|
37
|
+
}
|
|
38
|
+
if (value.context_over_200k !== undefined) {
|
|
39
|
+
collectCostValidationErrors(value.context_over_200k, `${path}.context_over_200k`, errors);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function validateOpenCodeModelCost(value, path = "cost") {
|
|
43
|
+
const errors = [];
|
|
44
|
+
collectCostValidationErrors(value, path, errors);
|
|
45
|
+
return { valid: errors.length === 0, errors };
|
|
46
|
+
}
|
|
47
|
+
export function isOpenCodeModelCost(value) {
|
|
48
|
+
return validateOpenCodeModelCost(value).valid;
|
|
49
|
+
}
|
|
50
|
+
/** Strip synthetic OpenCode long-context suffix (`…-1m`, `…-1m-2`, …). */
|
|
51
|
+
export function wireModelIdForPricing(modelId) {
|
|
52
|
+
const match = /^(.*)-1m(?:-(\d+))?$/.exec(modelId);
|
|
53
|
+
if (!match)
|
|
54
|
+
return { baseId: modelId, longContextEntry: false };
|
|
55
|
+
return { baseId: match[1], longContextEntry: true };
|
|
56
|
+
}
|
|
57
|
+
function asMutableCost(value) {
|
|
58
|
+
const copy = { input: value.input, output: value.output };
|
|
59
|
+
if (value.cache_read !== undefined)
|
|
60
|
+
copy.cache_read = value.cache_read;
|
|
61
|
+
if (value.cache_write !== undefined)
|
|
62
|
+
copy.cache_write = value.cache_write;
|
|
63
|
+
if (value.context_over_200k) {
|
|
64
|
+
copy.context_over_200k = asMutableCost(value.context_over_200k);
|
|
65
|
+
}
|
|
66
|
+
return copy;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Look up classic OpenCode cost for a catalog / wire model id.
|
|
70
|
+
* Synthetic `-1m` entries retain both base and documented long-context rates.
|
|
71
|
+
*/
|
|
72
|
+
export function getCursorModelCost(modelId) {
|
|
73
|
+
const { baseId } = wireModelIdForPricing(modelId);
|
|
74
|
+
const found = CURSOR_MODEL_COSTS[baseId];
|
|
75
|
+
if (!found)
|
|
76
|
+
return undefined;
|
|
77
|
+
return asMutableCost(found);
|
|
78
|
+
}
|
|
79
|
+
export function applyCursorModelCost(modelId, entry) {
|
|
80
|
+
const modelCost = getCursorModelCost(modelId);
|
|
81
|
+
if (!modelCost)
|
|
82
|
+
return entry;
|
|
83
|
+
return { ...entry, cost: modelCost };
|
|
84
|
+
}
|
|
85
|
+
/** Convert classic cost → OpenCode 2.0 `Model.Info.cost` array. */
|
|
86
|
+
export function toOpenCode2Costs(cost) {
|
|
87
|
+
if (!cost)
|
|
88
|
+
return [];
|
|
89
|
+
const out = [
|
|
90
|
+
{
|
|
91
|
+
input: cost.input,
|
|
92
|
+
output: cost.output,
|
|
93
|
+
cache: {
|
|
94
|
+
read: cost.cache_read ?? 0,
|
|
95
|
+
write: cost.cache_write ?? 0,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
if (cost.context_over_200k) {
|
|
100
|
+
out.push({
|
|
101
|
+
tier: { type: "context", size: 200_000 },
|
|
102
|
+
input: cost.context_over_200k.input,
|
|
103
|
+
output: cost.context_over_200k.output,
|
|
104
|
+
cache: {
|
|
105
|
+
read: cost.context_over_200k.cache_read ?? 0,
|
|
106
|
+
write: cost.context_over_200k.cache_write ?? 0,
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Coverage helper for CI / maintainer checks.
|
|
114
|
+
* Intentionally unpriced first-party ids are counted as priced (covered).
|
|
115
|
+
*/
|
|
116
|
+
export function checkCursorPricingCoverage(modelIds) {
|
|
117
|
+
const priced = [];
|
|
118
|
+
const missing = [];
|
|
119
|
+
for (const modelId of modelIds) {
|
|
120
|
+
const { baseId } = wireModelIdForPricing(modelId);
|
|
121
|
+
if (UNPRICED.has(baseId) || getCursorModelCost(modelId))
|
|
122
|
+
priced.push(modelId);
|
|
123
|
+
else
|
|
124
|
+
missing.push(modelId);
|
|
125
|
+
}
|
|
126
|
+
return { priced, missing };
|
|
127
|
+
}
|
|
@@ -917,9 +917,30 @@ export function createMessageTypes() {
|
|
|
917
917
|
{ id: 2, name: "max_mode", type: "bool" },
|
|
918
918
|
{ id: 3, name: "parameters", type: "ParameterValue", repeated: true },
|
|
919
919
|
]);
|
|
920
|
+
addType(root, "SelectedImageDimension", [
|
|
921
|
+
{ id: 1, name: "width", type: "int32" },
|
|
922
|
+
{ id: 2, name: "height", type: "int32" },
|
|
923
|
+
]);
|
|
924
|
+
addType(root, "SelectedImageBlobIdWithData", [
|
|
925
|
+
{ id: 1, name: "blob_id", type: "bytes" },
|
|
926
|
+
{ id: 2, name: "data", type: "bytes" },
|
|
927
|
+
]);
|
|
928
|
+
addType(root, "SelectedImage", [
|
|
929
|
+
{ id: 1, name: "blob_id", type: "bytes" },
|
|
930
|
+
{ id: 8, name: "data", type: "bytes" },
|
|
931
|
+
{ id: 9, name: "blob_id_with_data", type: "SelectedImageBlobIdWithData" },
|
|
932
|
+
{ id: 2, name: "uuid", type: "string" },
|
|
933
|
+
{ id: 3, name: "path", type: "string" },
|
|
934
|
+
{ id: 4, name: "dimension", type: "SelectedImageDimension" },
|
|
935
|
+
{ id: 7, name: "mime_type", type: "string" },
|
|
936
|
+
], [{ name: "data_or_blob_id", fields: ["blob_id", "data", "blob_id_with_data"] }]);
|
|
937
|
+
addType(root, "SelectedContext", [
|
|
938
|
+
{ id: 1, name: "selected_images", type: "SelectedImage", repeated: true },
|
|
939
|
+
]);
|
|
920
940
|
addType(root, "UserMessage", [
|
|
921
941
|
{ id: 1, name: "text", type: "string" },
|
|
922
942
|
{ id: 2, name: "message_id", type: "string" },
|
|
943
|
+
{ id: 3, name: "selected_context", type: "SelectedContext" },
|
|
923
944
|
]);
|
|
924
945
|
// RequestContext — UserMessageAction #2. Live per-turn tools go here
|
|
925
946
|
// (AgentRunRequest.mcp_tools #4 is prewarm-only / empty on real turns).
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { type OpencodeToolDef } from "./tools.js";
|
|
2
|
+
import type { CursorImageInput } from "../image-input.js";
|
|
2
3
|
export type SeedHistoryMessage = {
|
|
3
4
|
role: "system" | "user" | "assistant";
|
|
4
5
|
content: string;
|
|
5
6
|
};
|
|
6
7
|
export type RunRequestInput = {
|
|
7
8
|
text: string;
|
|
9
|
+
images?: CursorImageInput[];
|
|
8
10
|
modelId: string;
|
|
9
11
|
conversationId: string;
|
|
10
12
|
systemPrompt?: string;
|
package/dist/protocol/request.js
CHANGED
|
@@ -48,12 +48,21 @@ export function buildRunRequest(input) {
|
|
|
48
48
|
const tools = input.tools ?? [];
|
|
49
49
|
const mcpTools = input.toolDescriptors ?? (tools.length > 0 ? toolsToDescriptors(tools) : []);
|
|
50
50
|
const requestContext = input.requestContext;
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
message_id: msgId,
|
|
55
|
-
},
|
|
51
|
+
const userMessage = {
|
|
52
|
+
text: input.text,
|
|
53
|
+
message_id: msgId,
|
|
56
54
|
};
|
|
55
|
+
if (input.images?.length) {
|
|
56
|
+
userMessage.selected_context = {
|
|
57
|
+
selected_images: input.images.map((image) => ({
|
|
58
|
+
data: image.data,
|
|
59
|
+
uuid: crypto.randomUUID(),
|
|
60
|
+
path: image.filename,
|
|
61
|
+
mime_type: image.mimeType,
|
|
62
|
+
})),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const userMessageAction = { user_message: userMessage };
|
|
57
66
|
if (requestContext)
|
|
58
67
|
userMessageAction.request_context = requestContext;
|
|
59
68
|
const action = input.action === "resume"
|
package/dist/shared.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export declare const AVAILABLE_MODELS_PATH = "/aiserver.v1.AiService/AvailableMo
|
|
|
10
10
|
export declare const SERVER_CONFIG_PATH = "/aiserver.v1.ServerConfigService/GetServerConfig";
|
|
11
11
|
export declare const MODEL_CACHE_FILE = "cursor-models.json";
|
|
12
12
|
/** Bumped when the on-disk model cache shape/semantics change (forces refetch). */
|
|
13
|
-
export declare const MODEL_CACHE_SCHEMA_VERSION =
|
|
13
|
+
export declare const MODEL_CACHE_SCHEMA_VERSION = 3;
|
|
14
14
|
export declare const MODEL_CACHE_TTL_MS = 86400000;
|
|
15
15
|
export declare const VERSION_CACHE_FILE = "cursor-client-version.json";
|
|
16
16
|
export declare const CONTENT_TYPE_CONNECT_PROTO = "application/connect+proto";
|
package/dist/shared.js
CHANGED
|
@@ -10,7 +10,7 @@ export const AVAILABLE_MODELS_PATH = "/aiserver.v1.AiService/AvailableModels";
|
|
|
10
10
|
export const SERVER_CONFIG_PATH = "/aiserver.v1.ServerConfigService/GetServerConfig";
|
|
11
11
|
export const MODEL_CACHE_FILE = "cursor-models.json";
|
|
12
12
|
/** Bumped when the on-disk model cache shape/semantics change (forces refetch). */
|
|
13
|
-
export const MODEL_CACHE_SCHEMA_VERSION =
|
|
13
|
+
export const MODEL_CACHE_SCHEMA_VERSION = 3;
|
|
14
14
|
export const MODEL_CACHE_TTL_MS = 86_400_000;
|
|
15
15
|
export const VERSION_CACHE_FILE = "cursor-client-version.json";
|
|
16
16
|
export const CONTENT_TYPE_CONNECT_PROTO = "application/connect+proto";
|