@mastra/cursor 0.3.0 → 0.3.1-alpha.1

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/dist/index.js CHANGED
@@ -1,1097 +1,896 @@
1
- import { randomUUID } from 'crypto';
2
- import { ReadableStream, TransformStream } from 'stream/web';
3
- import { Agent as Agent$1 } from '@cursor/sdk';
4
- import { Agent } from '@mastra/core/agent';
5
- import { RequestContext } from '@mastra/core/request-context';
6
- import { ChunkFrom, MastraModelOutput } from '@mastra/core/stream';
7
- import { MessageList } from '@mastra/core/agent/message-list';
8
- import { getOrCreateSpan, EntityType, SpanType, executeWithContext } from '@mastra/core/observability';
9
-
10
- // src/index.ts
1
+ import { randomUUID } from "crypto";
2
+ import { ReadableStream, TransformStream } from "stream/web";
3
+ import { Agent } from "@cursor/sdk";
4
+ import { Agent as Agent$1 } from "@mastra/core/agent";
5
+ import { RequestContext } from "@mastra/core/request-context";
6
+ import { ChunkFrom, MastraModelOutput } from "@mastra/core/stream";
7
+ import { MessageList } from "@mastra/core/agent/message-list";
8
+ import { EntityType, SpanType, executeWithContext, getOrCreateSpan } from "@mastra/core/observability";
9
+ //#region src/utils.ts
11
10
  function createNoopModel({ modelId, provider }) {
12
- return {
13
- modelId,
14
- provider,
15
- specificationVersion: "v3",
16
- supportedUrls: {},
17
- doGenerate: async () => createNoopStreamResult(),
18
- doStream: async () => createNoopStreamResult()
19
- };
11
+ return {
12
+ modelId,
13
+ provider,
14
+ specificationVersion: "v3",
15
+ supportedUrls: {},
16
+ doGenerate: async () => createNoopStreamResult(),
17
+ doStream: async () => createNoopStreamResult()
18
+ };
20
19
  }
21
20
  function createNoopStreamResult() {
22
- return {
23
- stream: new ReadableStream({
24
- start: (controller) => controller.close()
25
- })
26
- };
27
- }
28
- function createCompletedMastraStream({
29
- runId,
30
- prompt,
31
- text,
32
- responseId,
33
- modelId,
34
- usage,
35
- providerMetadata,
36
- costContext,
37
- object
38
- }) {
39
- return new ReadableStream({
40
- start(controller) {
41
- const textId = randomUUID();
42
- enqueueStartChunks(controller, {
43
- runId,
44
- prompt,
45
- textId,
46
- responseId,
47
- modelId,
48
- providerMetadata
49
- });
50
- if (text) {
51
- enqueueTextDelta(controller, runId, textId, text);
52
- }
53
- enqueueFinishChunks(controller, {
54
- runId,
55
- prompt,
56
- textId,
57
- text,
58
- responseId,
59
- modelId,
60
- usage,
61
- providerMetadata,
62
- costContext,
63
- object
64
- });
65
- controller.close();
66
- }
67
- });
68
- }
69
- function createMastraOutput({
70
- messages,
71
- runId,
72
- modelId,
73
- provider,
74
- stream,
75
- options
76
- }) {
77
- const messageList = new MessageList();
78
- messageList.add(messages, "input");
79
- messageList.add([{ role: "assistant", content: "" }], "response");
80
- return new MastraModelOutput({
81
- model: {
82
- modelId,
83
- provider,
84
- version: "v3"
85
- },
86
- stream,
87
- messageList,
88
- messageId: randomUUID(),
89
- options: {
90
- ...options,
91
- runId
92
- }
93
- });
94
- }
95
- function toFullOutput({
96
- messages,
97
- runId,
98
- provider,
99
- result,
100
- options
101
- }) {
102
- const text = result.content.map((part) => part.text).join("");
103
- const stream = createCompletedMastraStream({
104
- runId,
105
- prompt: promptToText(messages),
106
- text,
107
- responseId: result.response.id,
108
- modelId: result.response.modelId,
109
- usage: toLanguageModelUsage(result.usage),
110
- providerMetadata: result.providerMetadata,
111
- costContext: result.costContext,
112
- object: result.object
113
- });
114
- return createMastraOutput({
115
- messages,
116
- runId,
117
- modelId: result.response.modelId,
118
- provider,
119
- stream,
120
- options
121
- }).getFullOutput();
122
- }
123
- function createSDKAgentTelemetry({
124
- agentId,
125
- agentName,
126
- provider,
127
- modelId,
128
- messages,
129
- prompt,
130
- runId,
131
- streaming,
132
- method,
133
- requestContext,
134
- instructions,
135
- maxSteps,
136
- tracingOptions,
137
- tracingContext,
138
- onFinish,
139
- onStepFinish,
140
- mastra
141
- }) {
142
- const agentSpan = getOrCreateSpan({
143
- type: SpanType.AGENT_RUN,
144
- name: `agent run: '${agentId}'`,
145
- entityType: EntityType.AGENT,
146
- entityId: agentId,
147
- entityName: agentName,
148
- input: messages,
149
- attributes: {
150
- prompt,
151
- instructions,
152
- maxSteps
153
- },
154
- metadata: {
155
- runId,
156
- sdkAgent: true,
157
- sdkProvider: provider,
158
- sdkMethod: method
159
- },
160
- tracingOptions,
161
- tracingContext,
162
- requestContext,
163
- mastra
164
- });
165
- const modelSpan = agentSpan?.createChildSpan({
166
- type: SpanType.MODEL_GENERATION,
167
- name: `llm: '${modelId}'`,
168
- input: {
169
- messages
170
- },
171
- attributes: {
172
- model: modelId,
173
- provider,
174
- streaming
175
- },
176
- metadata: {
177
- runId,
178
- sdkAgent: true,
179
- sdkProvider: provider,
180
- sdkMethod: method
181
- },
182
- requestContext
183
- });
184
- const modelSpanTracker = getModelSpanTracker(modelSpan);
185
- const toolSpans = /* @__PURE__ */ new Map();
186
- let ended = false;
187
- const startToolCall = ({ toolCallId, toolName, input }) => {
188
- if (toolSpans.has(toolCallId)) {
189
- return;
190
- }
191
- const parentSpan = agentSpan ?? modelSpan;
192
- if (!parentSpan) {
193
- return;
194
- }
195
- const mcp = parseMcpToolName(toolName);
196
- const span = mcp ? parentSpan.createChildSpan({
197
- type: SpanType.MCP_TOOL_CALL,
198
- name: `mcp_tool: '${toolName}' on '${mcp.serverName}'`,
199
- input,
200
- entityType: EntityType.TOOL,
201
- entityId: toolName,
202
- entityName: toolName,
203
- attributes: {
204
- mcpServer: mcp.serverName
205
- },
206
- metadata: {
207
- runId,
208
- sdkAgent: true,
209
- sdkProvider: provider,
210
- sdkMethod: method,
211
- toolCallId
212
- },
213
- requestContext
214
- }) : parentSpan.createChildSpan({
215
- type: SpanType.TOOL_CALL,
216
- name: `tool: '${toolName}'`,
217
- input,
218
- entityType: EntityType.TOOL,
219
- entityId: toolName,
220
- entityName: toolName,
221
- attributes: {
222
- toolType: "tool"
223
- },
224
- metadata: {
225
- runId,
226
- sdkAgent: true,
227
- sdkProvider: provider,
228
- sdkMethod: method,
229
- toolCallId
230
- },
231
- requestContext
232
- });
233
- toolSpans.set(toolCallId, span);
234
- };
235
- const endToolCall = ({ toolCallId, output, isError }) => {
236
- const span = toolSpans.get(toolCallId);
237
- if (!span) {
238
- return;
239
- }
240
- toolSpans.delete(toolCallId);
241
- if (isError) {
242
- span.error({
243
- error: output instanceof Error ? output : new Error(typeof output === "string" ? output : "SDK tool call failed"),
244
- attributes: { success: false }
245
- });
246
- return;
247
- }
248
- span.end({
249
- output,
250
- attributes: { success: true }
251
- });
252
- };
253
- const closeOpenToolSpans = (success, error) => {
254
- for (const [toolCallId, span] of toolSpans) {
255
- toolSpans.delete(toolCallId);
256
- if (success) {
257
- span.end({ attributes: { success: true } });
258
- continue;
259
- }
260
- const normalized = error instanceof Error ? error : new Error(String(error ?? "SDK agent run failed"));
261
- span.error({ error: normalized, attributes: { success: false } });
262
- }
263
- };
264
- const endModel = ({
265
- text,
266
- usage,
267
- providerMetadata,
268
- finishReason = "stop",
269
- responseId,
270
- responseModel,
271
- costContext
272
- }) => {
273
- if (modelSpanTracker) {
274
- modelSpanTracker.endGeneration({
275
- output: {
276
- text
277
- },
278
- attributes: {
279
- finishReason,
280
- responseId,
281
- responseModel,
282
- costContext
283
- },
284
- usage,
285
- providerMetadata
286
- });
287
- return;
288
- }
289
- modelSpan?.end({
290
- output: {
291
- text
292
- },
293
- attributes: {
294
- finishReason,
295
- responseId,
296
- responseModel,
297
- usage: usage ? toUsageStats(usage) : void 0,
298
- costContext
299
- }
300
- });
301
- };
302
- const end = (result) => {
303
- if (ended) {
304
- return;
305
- }
306
- ended = true;
307
- closeOpenToolSpans(true);
308
- endModel(result);
309
- agentSpan?.end({
310
- output: {
311
- text: result.text
312
- }
313
- });
314
- };
315
- const fail = (error) => {
316
- if (ended) {
317
- return;
318
- }
319
- ended = true;
320
- const normalized = error instanceof Error ? error : new Error(String(error));
321
- closeOpenToolSpans(false, normalized);
322
- if (modelSpanTracker) {
323
- modelSpanTracker.reportGenerationError({ error: normalized });
324
- } else {
325
- modelSpan?.error({ error: normalized });
326
- }
327
- agentSpan?.error({ error: normalized });
328
- };
329
- return {
330
- execute: (fn) => executeWithContext({ span: modelSpan ?? agentSpan, fn }),
331
- endGenerate(result) {
332
- end({
333
- text: result.content.map((part) => part.text).join(""),
334
- usage: toLanguageModelUsage(result.usage),
335
- providerMetadata: result.providerMetadata,
336
- finishReason: result.finishReason.unified,
337
- responseId: result.response.id,
338
- responseModel: result.response.modelId,
339
- costContext: result.costContext
340
- });
341
- },
342
- fail,
343
- startToolCall,
344
- endToolCall,
345
- wrapStream(stream) {
346
- const trackedStream = modelSpanTracker?.wrapStream(stream) ?? stream;
347
- return wrapStreamForAgentSpan(trackedStream, {
348
- end,
349
- fail
350
- });
351
- },
352
- outputOptions() {
353
- return {
354
- onFinish,
355
- onStepFinish,
356
- requestContext,
357
- tracingContext: agentSpan ? { currentSpan: agentSpan } : tracingContext
358
- };
359
- }
360
- };
21
+ return { stream: new ReadableStream({ start: (controller) => controller.close() }) };
22
+ }
23
+ function createCompletedMastraStream({ runId, prompt, text, responseId, modelId, usage, providerMetadata, costContext, object }) {
24
+ return new ReadableStream({ start(controller) {
25
+ const textId = randomUUID();
26
+ enqueueStartChunks(controller, {
27
+ runId,
28
+ prompt,
29
+ textId,
30
+ responseId,
31
+ modelId,
32
+ providerMetadata
33
+ });
34
+ if (text) enqueueTextDelta(controller, runId, textId, text);
35
+ enqueueFinishChunks(controller, {
36
+ runId,
37
+ prompt,
38
+ textId,
39
+ text,
40
+ responseId,
41
+ modelId,
42
+ usage,
43
+ providerMetadata,
44
+ costContext,
45
+ object
46
+ });
47
+ controller.close();
48
+ } });
49
+ }
50
+ function createMastraOutput({ messages, runId, modelId, provider, stream, options }) {
51
+ const messageList = new MessageList();
52
+ messageList.add(messages, "input");
53
+ messageList.add([{
54
+ role: "assistant",
55
+ content: ""
56
+ }], "response");
57
+ return new MastraModelOutput({
58
+ model: {
59
+ modelId,
60
+ provider,
61
+ version: "v3"
62
+ },
63
+ stream,
64
+ messageList,
65
+ messageId: randomUUID(),
66
+ options: {
67
+ ...options,
68
+ runId
69
+ }
70
+ });
71
+ }
72
+ function toFullOutput({ messages, runId, provider, result, options }) {
73
+ const text = result.content.map((part) => part.text).join("");
74
+ const stream = createCompletedMastraStream({
75
+ runId,
76
+ prompt: promptToText(messages),
77
+ text,
78
+ responseId: result.response.id,
79
+ modelId: result.response.modelId,
80
+ usage: toLanguageModelUsage(result.usage),
81
+ providerMetadata: result.providerMetadata,
82
+ costContext: result.costContext,
83
+ object: result.object
84
+ });
85
+ return createMastraOutput({
86
+ messages,
87
+ runId,
88
+ modelId: result.response.modelId,
89
+ provider,
90
+ stream,
91
+ options
92
+ }).getFullOutput();
93
+ }
94
+ function createSDKAgentTelemetry({ agentId, agentName, provider, modelId, messages, prompt, runId, streaming, method, requestContext, instructions, maxSteps, tracingOptions, tracingContext, onFinish, onStepFinish, mastra }) {
95
+ const agentSpan = getOrCreateSpan({
96
+ type: SpanType.AGENT_RUN,
97
+ name: `agent run: '${agentId}'`,
98
+ entityType: EntityType.AGENT,
99
+ entityId: agentId,
100
+ entityName: agentName,
101
+ input: messages,
102
+ attributes: {
103
+ prompt,
104
+ instructions,
105
+ maxSteps
106
+ },
107
+ metadata: {
108
+ runId,
109
+ sdkAgent: true,
110
+ sdkProvider: provider,
111
+ sdkMethod: method
112
+ },
113
+ tracingOptions,
114
+ tracingContext,
115
+ requestContext,
116
+ mastra
117
+ });
118
+ const modelSpan = agentSpan?.createChildSpan({
119
+ type: SpanType.MODEL_GENERATION,
120
+ name: `llm: '${modelId}'`,
121
+ input: { messages },
122
+ attributes: {
123
+ model: modelId,
124
+ provider,
125
+ streaming
126
+ },
127
+ metadata: {
128
+ runId,
129
+ sdkAgent: true,
130
+ sdkProvider: provider,
131
+ sdkMethod: method
132
+ },
133
+ requestContext
134
+ });
135
+ const modelSpanTracker = getModelSpanTracker(modelSpan);
136
+ const toolSpans = /* @__PURE__ */ new Map();
137
+ let ended = false;
138
+ const startToolCall = ({ toolCallId, toolName, input }) => {
139
+ if (toolSpans.has(toolCallId)) return;
140
+ const parentSpan = agentSpan ?? modelSpan;
141
+ if (!parentSpan) return;
142
+ const mcp = parseMcpToolName(toolName);
143
+ const span = mcp ? parentSpan.createChildSpan({
144
+ type: SpanType.MCP_TOOL_CALL,
145
+ name: `mcp_tool: '${toolName}' on '${mcp.serverName}'`,
146
+ input,
147
+ entityType: EntityType.TOOL,
148
+ entityId: toolName,
149
+ entityName: toolName,
150
+ attributes: { mcpServer: mcp.serverName },
151
+ metadata: {
152
+ runId,
153
+ sdkAgent: true,
154
+ sdkProvider: provider,
155
+ sdkMethod: method,
156
+ toolCallId
157
+ },
158
+ requestContext
159
+ }) : parentSpan.createChildSpan({
160
+ type: SpanType.TOOL_CALL,
161
+ name: `tool: '${toolName}'`,
162
+ input,
163
+ entityType: EntityType.TOOL,
164
+ entityId: toolName,
165
+ entityName: toolName,
166
+ attributes: { toolType: "tool" },
167
+ metadata: {
168
+ runId,
169
+ sdkAgent: true,
170
+ sdkProvider: provider,
171
+ sdkMethod: method,
172
+ toolCallId
173
+ },
174
+ requestContext
175
+ });
176
+ toolSpans.set(toolCallId, span);
177
+ };
178
+ const endToolCall = ({ toolCallId, output, isError }) => {
179
+ const span = toolSpans.get(toolCallId);
180
+ if (!span) return;
181
+ toolSpans.delete(toolCallId);
182
+ if (isError) {
183
+ span.error({
184
+ error: output instanceof Error ? output : new Error(typeof output === "string" ? output : "SDK tool call failed"),
185
+ attributes: { success: false }
186
+ });
187
+ return;
188
+ }
189
+ span.end({
190
+ output,
191
+ attributes: { success: true }
192
+ });
193
+ };
194
+ const closeOpenToolSpans = (success, error) => {
195
+ for (const [toolCallId, span] of toolSpans) {
196
+ toolSpans.delete(toolCallId);
197
+ if (success) {
198
+ span.end({ attributes: { success: true } });
199
+ continue;
200
+ }
201
+ const normalized = error instanceof Error ? error : new Error(String(error ?? "SDK agent run failed"));
202
+ span.error({
203
+ error: normalized,
204
+ attributes: { success: false }
205
+ });
206
+ }
207
+ };
208
+ const endModel = ({ text, usage, providerMetadata, finishReason = "stop", responseId, responseModel, costContext }) => {
209
+ if (modelSpanTracker) {
210
+ modelSpanTracker.endGeneration({
211
+ output: { text },
212
+ attributes: {
213
+ finishReason,
214
+ responseId,
215
+ responseModel,
216
+ costContext
217
+ },
218
+ usage,
219
+ providerMetadata
220
+ });
221
+ return;
222
+ }
223
+ modelSpan?.end({
224
+ output: { text },
225
+ attributes: {
226
+ finishReason,
227
+ responseId,
228
+ responseModel,
229
+ usage: usage ? toUsageStats(usage) : void 0,
230
+ costContext
231
+ }
232
+ });
233
+ };
234
+ const end = (result) => {
235
+ if (ended) return;
236
+ ended = true;
237
+ closeOpenToolSpans(true);
238
+ endModel(result);
239
+ agentSpan?.end({ output: { text: result.text } });
240
+ };
241
+ const fail = (error) => {
242
+ if (ended) return;
243
+ ended = true;
244
+ const normalized = error instanceof Error ? error : new Error(String(error));
245
+ closeOpenToolSpans(false, normalized);
246
+ if (modelSpanTracker) modelSpanTracker.reportGenerationError({ error: normalized });
247
+ else modelSpan?.error({ error: normalized });
248
+ agentSpan?.error({ error: normalized });
249
+ };
250
+ return {
251
+ execute: (fn) => executeWithContext({
252
+ span: modelSpan ?? agentSpan,
253
+ fn
254
+ }),
255
+ endGenerate(result) {
256
+ end({
257
+ text: result.content.map((part) => part.text).join(""),
258
+ usage: toLanguageModelUsage(result.usage),
259
+ providerMetadata: result.providerMetadata,
260
+ finishReason: result.finishReason.unified,
261
+ responseId: result.response.id,
262
+ responseModel: result.response.modelId,
263
+ costContext: result.costContext
264
+ });
265
+ },
266
+ fail,
267
+ startToolCall,
268
+ endToolCall,
269
+ wrapStream(stream) {
270
+ return wrapStreamForAgentSpan(modelSpanTracker?.wrapStream(stream) ?? stream, {
271
+ end,
272
+ fail
273
+ });
274
+ },
275
+ outputOptions() {
276
+ return {
277
+ onFinish,
278
+ onStepFinish,
279
+ requestContext,
280
+ tracingContext: agentSpan ? { currentSpan: agentSpan } : tracingContext
281
+ };
282
+ }
283
+ };
361
284
  }
362
285
  function parseMcpToolName(toolName) {
363
- const match = /^mcp__([^_].*?)__(.+)$/.exec(toolName);
364
- if (!match?.[1] || !match[2]) {
365
- return void 0;
366
- }
367
- return {
368
- serverName: match[1],
369
- toolName: match[2]
370
- };
286
+ const match = /^mcp__([^_].*?)__(.+)$/.exec(toolName);
287
+ if (!match?.[1] || !match[2]) return;
288
+ return {
289
+ serverName: match[1],
290
+ toolName: match[2]
291
+ };
371
292
  }
372
293
  function getModelSpanTracker(modelSpan) {
373
- if (!modelSpan || !("createTracker" in modelSpan)) {
374
- return void 0;
375
- }
376
- return modelSpan.createTracker();
294
+ if (!modelSpan || !("createTracker" in modelSpan)) return;
295
+ return modelSpan.createTracker();
377
296
  }
378
297
  function wrapStreamForAgentSpan(stream, telemetry) {
379
- let text = "";
380
- return stream.pipeThrough(
381
- new TransformStream({
382
- transform(chunk, controller) {
383
- if (chunk.type === "text-delta") {
384
- text += chunk.payload.text;
385
- }
386
- if (chunk.type === "finish") {
387
- telemetry.end({
388
- text,
389
- usage: chunk.payload.output.usage,
390
- providerMetadata: chunk.payload.providerMetadata,
391
- finishReason: chunk.payload.stepResult.reason,
392
- responseId: chunk.payload.response?.id,
393
- responseModel: chunk.payload.response?.modelId,
394
- costContext: getCostContext(chunk.payload.metadata?.costContext)
395
- });
396
- }
397
- if (chunk.type === "error") {
398
- telemetry.fail(chunk.payload.error);
399
- }
400
- controller.enqueue(chunk);
401
- },
402
- flush() {
403
- telemetry.end({ text });
404
- }
405
- })
406
- );
298
+ let text = "";
299
+ return stream.pipeThrough(new TransformStream({
300
+ transform(chunk, controller) {
301
+ if (chunk.type === "text-delta") text += chunk.payload.text;
302
+ if (chunk.type === "finish") telemetry.end({
303
+ text,
304
+ usage: chunk.payload.output.usage,
305
+ providerMetadata: chunk.payload.providerMetadata,
306
+ finishReason: chunk.payload.stepResult.reason,
307
+ responseId: chunk.payload.response?.id,
308
+ responseModel: chunk.payload.response?.modelId,
309
+ costContext: getCostContext(chunk.payload.metadata?.costContext)
310
+ });
311
+ if (chunk.type === "error") telemetry.fail(chunk.payload.error);
312
+ controller.enqueue(chunk);
313
+ },
314
+ flush() {
315
+ telemetry.end({ text });
316
+ }
317
+ }));
407
318
  }
408
319
  function toUsageStats(usage) {
409
- return {
410
- inputTokens: usage.inputTokens,
411
- outputTokens: usage.outputTokens,
412
- inputDetails: {
413
- cacheRead: usage.cachedInputTokens,
414
- cacheWrite: usage.cacheCreationInputTokens
415
- },
416
- outputDetails: {
417
- text: usage.outputTokens,
418
- reasoning: usage.reasoningTokens
419
- }
420
- };
320
+ return {
321
+ inputTokens: usage.inputTokens,
322
+ outputTokens: usage.outputTokens,
323
+ inputDetails: {
324
+ cacheRead: usage.cachedInputTokens,
325
+ cacheWrite: usage.cacheCreationInputTokens
326
+ },
327
+ outputDetails: {
328
+ text: usage.outputTokens,
329
+ reasoning: usage.reasoningTokens
330
+ }
331
+ };
421
332
  }
422
333
  function getCostContext(value) {
423
- if (!value || typeof value !== "object") {
424
- return void 0;
425
- }
426
- return value;
427
- }
428
- function enqueueStartChunks(controller, {
429
- runId,
430
- prompt,
431
- textId,
432
- responseId,
433
- modelId,
434
- providerMetadata
435
- }) {
436
- controller.enqueue({
437
- type: "start",
438
- runId,
439
- from: ChunkFrom.AGENT,
440
- payload: {}
441
- });
442
- controller.enqueue({
443
- type: "step-start",
444
- runId,
445
- from: ChunkFrom.AGENT,
446
- payload: {
447
- request: { body: prompt }
448
- }
449
- });
450
- controller.enqueue({
451
- type: "response-metadata",
452
- runId,
453
- from: ChunkFrom.AGENT,
454
- payload: {
455
- id: responseId,
456
- modelId,
457
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
458
- }
459
- });
460
- controller.enqueue({
461
- type: "text-start",
462
- runId,
463
- from: ChunkFrom.AGENT,
464
- payload: {
465
- id: textId,
466
- providerMetadata
467
- }
468
- });
334
+ if (!value || typeof value !== "object") return;
335
+ return value;
336
+ }
337
+ function enqueueStartChunks(controller, { runId, prompt, textId, responseId, modelId, providerMetadata }) {
338
+ controller.enqueue({
339
+ type: "start",
340
+ runId,
341
+ from: ChunkFrom.AGENT,
342
+ payload: {}
343
+ });
344
+ controller.enqueue({
345
+ type: "step-start",
346
+ runId,
347
+ from: ChunkFrom.AGENT,
348
+ payload: { request: { body: prompt } }
349
+ });
350
+ controller.enqueue({
351
+ type: "response-metadata",
352
+ runId,
353
+ from: ChunkFrom.AGENT,
354
+ payload: {
355
+ id: responseId,
356
+ modelId,
357
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
358
+ }
359
+ });
360
+ controller.enqueue({
361
+ type: "text-start",
362
+ runId,
363
+ from: ChunkFrom.AGENT,
364
+ payload: {
365
+ id: textId,
366
+ providerMetadata
367
+ }
368
+ });
469
369
  }
470
370
  function enqueueTextDelta(controller, runId, textId, text) {
471
- controller.enqueue({
472
- type: "text-delta",
473
- runId,
474
- from: ChunkFrom.AGENT,
475
- payload: {
476
- id: textId,
477
- text
478
- }
479
- });
480
- }
481
- function enqueueFinishChunks(controller, {
482
- runId,
483
- prompt,
484
- textId,
485
- text,
486
- responseId,
487
- modelId,
488
- usage,
489
- providerMetadata,
490
- costContext,
491
- object
492
- }) {
493
- const timestamp = /* @__PURE__ */ new Date();
494
- const response = {
495
- id: responseId,
496
- modelId,
497
- timestamp
498
- };
499
- const metadata = {
500
- providerMetadata,
501
- costContext,
502
- request: { body: prompt },
503
- modelId,
504
- timestamp
505
- };
506
- controller.enqueue({
507
- type: "text-end",
508
- runId,
509
- from: ChunkFrom.AGENT,
510
- payload: {
511
- id: textId,
512
- providerMetadata
513
- }
514
- });
515
- if (object !== void 0) {
516
- controller.enqueue({
517
- type: "object-result",
518
- runId,
519
- from: ChunkFrom.AGENT,
520
- object
521
- });
522
- }
523
- controller.enqueue({
524
- type: "step-finish",
525
- runId,
526
- from: ChunkFrom.AGENT,
527
- payload: {
528
- id: responseId,
529
- providerMetadata,
530
- totalUsage: usage,
531
- response,
532
- stepResult: {
533
- reason: "stop",
534
- warnings: []
535
- },
536
- output: {
537
- text,
538
- usage,
539
- steps: []
540
- },
541
- metadata
542
- }
543
- });
544
- controller.enqueue({
545
- type: "finish",
546
- runId,
547
- from: ChunkFrom.AGENT,
548
- payload: {
549
- stepResult: {
550
- reason: "stop",
551
- warnings: []
552
- },
553
- output: {
554
- usage,
555
- steps: []
556
- },
557
- metadata,
558
- providerMetadata,
559
- messages: {
560
- all: [],
561
- user: [],
562
- nonUser: []
563
- },
564
- response
565
- }
566
- });
371
+ controller.enqueue({
372
+ type: "text-delta",
373
+ runId,
374
+ from: ChunkFrom.AGENT,
375
+ payload: {
376
+ id: textId,
377
+ text
378
+ }
379
+ });
380
+ }
381
+ function enqueueFinishChunks(controller, { runId, prompt, textId, text, responseId, modelId, usage, providerMetadata, costContext, object }) {
382
+ const timestamp = /* @__PURE__ */ new Date();
383
+ const response = {
384
+ id: responseId,
385
+ modelId,
386
+ timestamp
387
+ };
388
+ const metadata = {
389
+ providerMetadata,
390
+ costContext,
391
+ request: { body: prompt },
392
+ modelId,
393
+ timestamp
394
+ };
395
+ controller.enqueue({
396
+ type: "text-end",
397
+ runId,
398
+ from: ChunkFrom.AGENT,
399
+ payload: {
400
+ id: textId,
401
+ providerMetadata
402
+ }
403
+ });
404
+ if (object !== void 0) controller.enqueue({
405
+ type: "object-result",
406
+ runId,
407
+ from: ChunkFrom.AGENT,
408
+ object
409
+ });
410
+ controller.enqueue({
411
+ type: "step-finish",
412
+ runId,
413
+ from: ChunkFrom.AGENT,
414
+ payload: {
415
+ id: responseId,
416
+ providerMetadata,
417
+ totalUsage: usage,
418
+ response,
419
+ stepResult: {
420
+ reason: "stop",
421
+ warnings: []
422
+ },
423
+ output: {
424
+ text,
425
+ usage,
426
+ steps: []
427
+ },
428
+ metadata
429
+ }
430
+ });
431
+ controller.enqueue({
432
+ type: "finish",
433
+ runId,
434
+ from: ChunkFrom.AGENT,
435
+ payload: {
436
+ stepResult: {
437
+ reason: "stop",
438
+ warnings: []
439
+ },
440
+ output: {
441
+ usage,
442
+ steps: []
443
+ },
444
+ metadata,
445
+ providerMetadata,
446
+ messages: {
447
+ all: [],
448
+ user: [],
449
+ nonUser: []
450
+ },
451
+ response
452
+ }
453
+ });
567
454
  }
568
455
  function toLanguageModelUsage(usage) {
569
- const inputTokens = usage.inputTokens.total ?? 0;
570
- const outputTokens = usage.outputTokens.total ?? 0;
571
- return {
572
- inputTokens,
573
- outputTokens,
574
- totalTokens: inputTokens + outputTokens,
575
- cachedInputTokens: usage.inputTokens.cacheRead,
576
- cacheCreationInputTokens: usage.inputTokens.cacheWrite,
577
- raw: usage
578
- };
456
+ const inputTokens = usage.inputTokens.total ?? 0;
457
+ const outputTokens = usage.outputTokens.total ?? 0;
458
+ return {
459
+ inputTokens,
460
+ outputTokens,
461
+ totalTokens: inputTokens + outputTokens,
462
+ cachedInputTokens: usage.inputTokens.cacheRead,
463
+ cacheCreationInputTokens: usage.inputTokens.cacheWrite,
464
+ raw: usage
465
+ };
579
466
  }
580
467
  function createProviderMetadata(provider, metadata) {
581
- return {
582
- [provider]: toJsonRecord(metadata)
583
- };
468
+ return { [provider]: toJsonRecord(metadata) };
584
469
  }
585
470
  function toJsonRecord(record) {
586
- return Object.fromEntries(
587
- Object.entries(record).filter((entry) => entry[1] !== void 0).map(([key, value]) => [key, toJsonValue(value)])
588
- );
471
+ return Object.fromEntries(Object.entries(record).filter((entry) => entry[1] !== void 0).map(([key, value]) => [key, toJsonValue(value)]));
589
472
  }
590
473
  function toJsonValue(value) {
591
- if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
592
- return value;
593
- }
594
- if (Array.isArray(value)) {
595
- return value.filter((item) => item !== void 0).map(toJsonValue);
596
- }
597
- if (value instanceof Date) {
598
- return value.toISOString();
599
- }
600
- if (typeof value === "object") {
601
- return toJsonRecord(value);
602
- }
603
- return String(value);
474
+ if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
475
+ if (Array.isArray(value)) return value.filter((item) => item !== void 0).map(toJsonValue);
476
+ if (value instanceof Date) return value.toISOString();
477
+ if (typeof value === "object") return toJsonRecord(value);
478
+ return String(value);
604
479
  }
605
480
  function promptToText(prompt) {
606
- if (typeof prompt === "string") {
607
- return prompt;
608
- }
609
- if (Array.isArray(prompt)) {
610
- return prompt.map(promptToText).filter(Boolean).join("\n");
611
- }
612
- if (!prompt || typeof prompt !== "object") {
613
- return "";
614
- }
615
- const record = prompt;
616
- if (typeof record.text === "string") {
617
- return record.text;
618
- }
619
- if (typeof record.content === "string") {
620
- return record.content;
621
- }
622
- if (record.content) {
623
- return promptToText(record.content);
624
- }
625
- return "";
481
+ if (typeof prompt === "string") return prompt;
482
+ if (Array.isArray(prompt)) return prompt.map(promptToText).filter(Boolean).join("\n");
483
+ if (!prompt || typeof prompt !== "object") return "";
484
+ const record = prompt;
485
+ if (typeof record.text === "string") return record.text;
486
+ if (typeof record.content === "string") return record.content;
487
+ if (record.content) return promptToText(record.content);
488
+ return "";
626
489
  }
627
490
  function sumDefined(...values) {
628
- const defined = values.filter((value) => typeof value === "number");
629
- if (defined.length === 0) {
630
- return void 0;
631
- }
632
- return defined.reduce((sum, value) => sum + value, 0);
633
- }
634
-
635
- // src/index.ts
636
- var PROVIDER = "@cursor/sdk";
637
- var MODEL_ID = "cursor-agent-sdk";
638
- var CursorSDKAgent = class extends Agent {
639
- options;
640
- #mastra;
641
- #createdAgent;
642
- constructor(options) {
643
- super({
644
- id: options.id,
645
- name: options.name ?? options.id,
646
- description: options.description,
647
- instructions: "",
648
- model: createNoopModel({
649
- modelId: getModelId(getRequestedModel(options)),
650
- provider: PROVIDER
651
- })
652
- });
653
- this.options = options;
654
- }
655
- __registerMastra(mastra) {
656
- super.__registerMastra(mastra);
657
- this.#mastra = mastra;
658
- }
659
- supportsMemory() {
660
- return false;
661
- }
662
- async generate(messages, options) {
663
- assertStructuredOutputUnsupported(options);
664
- const sdkAgent = await this.resolveCursorAgent();
665
- return this.generateWithAgent(messages, sdkAgent, options);
666
- }
667
- async generateWithAgent(messages, sdkAgent, options) {
668
- const prompt = promptToText(messages);
669
- const runId = options?.runId ?? randomUUID();
670
- const modelId = getCursorModelId(this.options, sdkAgent);
671
- const requestContext = options?.requestContext ?? new RequestContext();
672
- const instructions = options?.instructions ? promptToText(options.instructions) : void 0;
673
- const telemetry = createSDKAgentTelemetry({
674
- agentId: this.id,
675
- agentName: this.name,
676
- provider: PROVIDER,
677
- modelId,
678
- messages,
679
- prompt,
680
- runId,
681
- streaming: false,
682
- method: "generate",
683
- requestContext,
684
- instructions,
685
- maxSteps: options?.maxSteps,
686
- tracingOptions: options?.tracingOptions,
687
- tracingContext: options?.tracingContext,
688
- onFinish: options?.onFinish,
689
- onStepFinish: options?.onStepFinish,
690
- mastra: this.#mastra
691
- });
692
- let result;
693
- try {
694
- result = await telemetry.execute(() => runCursorGenerate(prompt, this.options, sdkAgent, telemetry));
695
- telemetry.endGenerate(result);
696
- } catch (error) {
697
- telemetry.fail(error);
698
- throw error;
699
- }
700
- return toFullOutput({
701
- messages,
702
- runId,
703
- provider: PROVIDER,
704
- result,
705
- options: telemetry.outputOptions()
706
- });
707
- }
708
- async stream(messages, options) {
709
- assertStructuredOutputUnsupported(options);
710
- const sdkAgent = await this.resolveCursorAgent();
711
- return this.streamWithAgent(messages, sdkAgent, options);
712
- }
713
- async streamWithAgent(messages, sdkAgent, options) {
714
- const runId = options?.runId ?? randomUUID();
715
- const prompt = promptToText(messages);
716
- const modelId = getCursorModelId(this.options, sdkAgent);
717
- const requestContext = options?.requestContext ?? new RequestContext();
718
- const instructions = options?.instructions ? promptToText(options.instructions) : void 0;
719
- const telemetry = createSDKAgentTelemetry({
720
- agentId: this.id,
721
- agentName: this.name,
722
- provider: PROVIDER,
723
- modelId,
724
- messages,
725
- prompt,
726
- runId,
727
- streaming: true,
728
- method: "stream",
729
- requestContext,
730
- instructions,
731
- maxSteps: options?.maxSteps,
732
- tracingOptions: options?.tracingOptions,
733
- tracingContext: options?.tracingContext,
734
- onFinish: options?.onFinish,
735
- onStepFinish: options?.onStepFinish,
736
- mastra: this.#mastra
737
- });
738
- return createMastraOutput({
739
- messages,
740
- runId,
741
- modelId,
742
- provider: PROVIDER,
743
- stream: telemetry.wrapStream(runCursorAsMastraStream(prompt, this.options, sdkAgent, runId, telemetry)),
744
- options: telemetry.outputOptions()
745
- });
746
- }
747
- async resumeGenerate(resumeData, options) {
748
- assertStructuredOutputUnsupported(options);
749
- const data = validateCursorResumeData(resumeData);
750
- const sdkAgent = await this.resolveResumeCursorAgent(data);
751
- return this.generateWithAgent(data.message, sdkAgent, options);
752
- }
753
- async resumeStream(resumeData, options) {
754
- assertStructuredOutputUnsupported(options);
755
- const data = validateCursorResumeData(resumeData);
756
- const sdkAgent = await this.resolveResumeCursorAgent(data);
757
- return this.streamWithAgent(data.message, sdkAgent, options);
758
- }
759
- resolveCursorAgent() {
760
- this.#createdAgent ??= resolveCursorAgent(this.options.agent, this.options).catch((error) => {
761
- this.#createdAgent = void 0;
762
- throw error;
763
- });
764
- return this.#createdAgent;
765
- }
766
- async resolveResumeCursorAgent(resumeData) {
767
- if (!resumeData.agentId) {
768
- return this.resolveCursorAgent();
769
- }
770
- return Agent$1.resume(resumeData.agentId, {
771
- ...toCursorCreateOptions(this.options),
772
- ...resumeData.sdkOptions
773
- });
774
- }
491
+ const defined = values.filter((value) => typeof value === "number");
492
+ if (defined.length === 0) return;
493
+ return defined.reduce((sum, value) => sum + value, 0);
494
+ }
495
+ //#endregion
496
+ //#region src/index.ts
497
+ const PROVIDER = "@cursor/sdk";
498
+ const MODEL_ID = "cursor-agent-sdk";
499
+ var CursorSDKAgent = class extends Agent$1 {
500
+ options;
501
+ #mastra;
502
+ #createdAgent;
503
+ constructor(options) {
504
+ super({
505
+ id: options.id,
506
+ name: options.name ?? options.id,
507
+ description: options.description,
508
+ instructions: "",
509
+ model: createNoopModel({
510
+ modelId: getModelId(getRequestedModel(options)),
511
+ provider: PROVIDER
512
+ })
513
+ });
514
+ this.options = options;
515
+ }
516
+ __registerMastra(mastra) {
517
+ super.__registerMastra(mastra);
518
+ this.#mastra = mastra;
519
+ }
520
+ supportsMemory() {
521
+ return false;
522
+ }
523
+ async generate(messages, options) {
524
+ assertStructuredOutputUnsupported(options);
525
+ const sdkAgent = await this.resolveCursorAgent();
526
+ return this.generateWithAgent(messages, sdkAgent, options);
527
+ }
528
+ async generateWithAgent(messages, sdkAgent, options) {
529
+ const prompt = promptToText(messages);
530
+ const runId = options?.runId ?? randomUUID();
531
+ const modelId = getCursorModelId(this.options, sdkAgent);
532
+ const requestContext = options?.requestContext ?? new RequestContext();
533
+ const instructions = options?.instructions ? promptToText(options.instructions) : void 0;
534
+ const telemetry = createSDKAgentTelemetry({
535
+ agentId: this.id,
536
+ agentName: this.name,
537
+ provider: PROVIDER,
538
+ modelId,
539
+ messages,
540
+ prompt,
541
+ runId,
542
+ streaming: false,
543
+ method: "generate",
544
+ requestContext,
545
+ instructions,
546
+ maxSteps: options?.maxSteps,
547
+ tracingOptions: options?.tracingOptions,
548
+ tracingContext: options?.tracingContext,
549
+ onFinish: options?.onFinish,
550
+ onStepFinish: options?.onStepFinish,
551
+ mastra: this.#mastra
552
+ });
553
+ let result;
554
+ try {
555
+ result = await telemetry.execute(() => runCursorGenerate(prompt, this.options, sdkAgent, telemetry));
556
+ telemetry.endGenerate(result);
557
+ } catch (error) {
558
+ telemetry.fail(error);
559
+ throw error;
560
+ }
561
+ return toFullOutput({
562
+ messages,
563
+ runId,
564
+ provider: PROVIDER,
565
+ result,
566
+ options: telemetry.outputOptions()
567
+ });
568
+ }
569
+ async stream(messages, options) {
570
+ assertStructuredOutputUnsupported(options);
571
+ const sdkAgent = await this.resolveCursorAgent();
572
+ return this.streamWithAgent(messages, sdkAgent, options);
573
+ }
574
+ async streamWithAgent(messages, sdkAgent, options) {
575
+ const runId = options?.runId ?? randomUUID();
576
+ const prompt = promptToText(messages);
577
+ const modelId = getCursorModelId(this.options, sdkAgent);
578
+ const requestContext = options?.requestContext ?? new RequestContext();
579
+ const instructions = options?.instructions ? promptToText(options.instructions) : void 0;
580
+ const telemetry = createSDKAgentTelemetry({
581
+ agentId: this.id,
582
+ agentName: this.name,
583
+ provider: PROVIDER,
584
+ modelId,
585
+ messages,
586
+ prompt,
587
+ runId,
588
+ streaming: true,
589
+ method: "stream",
590
+ requestContext,
591
+ instructions,
592
+ maxSteps: options?.maxSteps,
593
+ tracingOptions: options?.tracingOptions,
594
+ tracingContext: options?.tracingContext,
595
+ onFinish: options?.onFinish,
596
+ onStepFinish: options?.onStepFinish,
597
+ mastra: this.#mastra
598
+ });
599
+ return createMastraOutput({
600
+ messages,
601
+ runId,
602
+ modelId,
603
+ provider: PROVIDER,
604
+ stream: telemetry.wrapStream(runCursorAsMastraStream(prompt, this.options, sdkAgent, runId, telemetry)),
605
+ options: telemetry.outputOptions()
606
+ });
607
+ }
608
+ async resumeGenerate(resumeData, options) {
609
+ assertStructuredOutputUnsupported(options);
610
+ const data = validateCursorResumeData(resumeData);
611
+ const sdkAgent = await this.resolveResumeCursorAgent(data);
612
+ return this.generateWithAgent(data.message, sdkAgent, options);
613
+ }
614
+ async resumeStream(resumeData, options) {
615
+ assertStructuredOutputUnsupported(options);
616
+ const data = validateCursorResumeData(resumeData);
617
+ const sdkAgent = await this.resolveResumeCursorAgent(data);
618
+ return this.streamWithAgent(data.message, sdkAgent, options);
619
+ }
620
+ resolveCursorAgent() {
621
+ this.#createdAgent ??= resolveCursorAgent(this.options.agent, this.options).catch((error) => {
622
+ this.#createdAgent = void 0;
623
+ throw error;
624
+ });
625
+ return this.#createdAgent;
626
+ }
627
+ async resolveResumeCursorAgent(resumeData) {
628
+ if (!resumeData.agentId) return this.resolveCursorAgent();
629
+ return Agent.resume(resumeData.agentId, {
630
+ ...toCursorCreateOptions(this.options),
631
+ ...resumeData.sdkOptions
632
+ });
633
+ }
775
634
  };
776
635
  function validateCursorResumeData(resumeData) {
777
- if (!toRecord(resumeData) || !("message" in resumeData)) {
778
- throw new Error("CursorSDKAgent resumeData must include a message.");
779
- }
780
- if (resumeData.agentId !== void 0 && typeof resumeData.agentId !== "string") {
781
- throw new Error("CursorSDKAgent resumeData.agentId must be a string when provided.");
782
- }
783
- return resumeData;
636
+ if (!toRecord(resumeData) || !("message" in resumeData)) throw new Error("CursorSDKAgent resumeData must include a message.");
637
+ if (resumeData.agentId !== void 0 && typeof resumeData.agentId !== "string") throw new Error("CursorSDKAgent resumeData.agentId must be a string when provided.");
638
+ return resumeData;
784
639
  }
785
640
  function assertStructuredOutputUnsupported(options) {
786
- const structuredOutput = toRecord(toRecord(options)?.structuredOutput);
787
- if (structuredOutput && "schema" in structuredOutput) {
788
- throw new Error(
789
- "CursorSDKAgent does not support structuredOutput because the Cursor TypeScript SDK does not expose a schema-constrained output API."
790
- );
791
- }
641
+ const structuredOutput = toRecord(toRecord(options)?.structuredOutput);
642
+ if (structuredOutput && "schema" in structuredOutput) throw new Error("CursorSDKAgent does not support structuredOutput because the Cursor TypeScript SDK does not expose a schema-constrained output API.");
792
643
  }
793
644
  async function runCursorGenerate(prompt, options, agent, telemetry) {
794
- const usage = createCursorUsageCollector();
795
- const run = await agent.send(prompt, createCursorSendOptions(options, usage, telemetry));
796
- const result = await run.wait();
797
- if (result.status === "error" || result.status === "cancelled") {
798
- throw new Error(`Cursor run ${result.id} ended with status ${result.status}`);
799
- }
800
- const responseModel = getModelId(result.model ?? run.model ?? getRequestedModel(options) ?? agent.model);
801
- const providerMetadata = getCursorProviderMetadata(
802
- options,
803
- agent.agentId,
804
- result.id,
805
- result.status,
806
- result.durationMs,
807
- usage.totals(),
808
- responseModel
809
- );
810
- return {
811
- content: [{ type: "text", text: result.result ?? "" }],
812
- finishReason: { unified: "stop", raw: "stop" },
813
- usage: usage.toV3Usage(),
814
- response: {
815
- id: result.id,
816
- modelId: responseModel,
817
- timestamp: /* @__PURE__ */ new Date()
818
- },
819
- providerMetadata
820
- };
645
+ const usage = createCursorUsageCollector();
646
+ const run = await agent.send(prompt, createCursorSendOptions(options, usage, telemetry));
647
+ const result = await run.wait();
648
+ if (result.status === "error" || result.status === "cancelled") throw new Error(`Cursor run ${result.id} ended with status ${result.status}`);
649
+ const responseModel = getModelId(result.model ?? run.model ?? getRequestedModel(options) ?? agent.model);
650
+ const providerMetadata = getCursorProviderMetadata(options, agent.agentId, result.id, result.status, result.durationMs, usage.totals(), responseModel);
651
+ return {
652
+ content: [{
653
+ type: "text",
654
+ text: result.result ?? ""
655
+ }],
656
+ finishReason: {
657
+ unified: "stop",
658
+ raw: "stop"
659
+ },
660
+ usage: usage.toV3Usage(),
661
+ response: {
662
+ id: result.id,
663
+ modelId: responseModel,
664
+ timestamp: /* @__PURE__ */ new Date()
665
+ },
666
+ providerMetadata
667
+ };
821
668
  }
822
669
  function runCursorAsMastraStream(prompt, options, agent, runId, telemetry) {
823
- return new ReadableStream({
824
- start: async (controller) => {
825
- const textId = randomUUID();
826
- const usage = createCursorUsageCollector();
827
- let text = "";
828
- try {
829
- const run = await agent.send(prompt, createCursorSendOptions(options, usage, telemetry));
830
- const responseId = run.id;
831
- const responseModel = getModelId(run.model ?? getRequestedModel(options) ?? agent.model);
832
- enqueueStartChunks(controller, {
833
- runId,
834
- prompt,
835
- textId,
836
- responseId,
837
- modelId: responseModel,
838
- providerMetadata: getCursorProviderMetadata(
839
- options,
840
- agent.agentId,
841
- run.id,
842
- run.status,
843
- run.durationMs,
844
- usage.totals(),
845
- responseModel
846
- )
847
- });
848
- let result;
849
- if (run.supports("stream")) {
850
- for await (const message of run.stream()) {
851
- const delta = getTextFromCursorMessage(message);
852
- if (delta) {
853
- text += delta;
854
- enqueueTextDelta(controller, runId, textId, delta);
855
- }
856
- }
857
- result = await run.wait();
858
- } else {
859
- result = await run.wait();
860
- if (result.status === "error" || result.status === "cancelled") {
861
- throw new Error(`Cursor run ${result.id} ended with status ${result.status}`);
862
- }
863
- if (result.result) {
864
- text += result.result;
865
- enqueueTextDelta(controller, runId, textId, result.result);
866
- }
867
- }
868
- if (result.status === "error" || result.status === "cancelled") {
869
- throw new Error(`Cursor run ${result.id} ended with status ${result.status}`);
870
- }
871
- if (!text && result.result) {
872
- text = result.result;
873
- enqueueTextDelta(controller, runId, textId, result.result);
874
- }
875
- const providerMetadata = getCursorProviderMetadata(
876
- options,
877
- agent.agentId,
878
- run.id,
879
- result.status,
880
- result.durationMs,
881
- usage.totals(),
882
- getModelId(result.model ?? run.model ?? getRequestedModel(options) ?? agent.model)
883
- );
884
- enqueueFinishChunks(controller, {
885
- runId,
886
- prompt,
887
- textId,
888
- text,
889
- responseId,
890
- modelId: getModelId(result.model ?? run.model ?? getRequestedModel(options) ?? agent.model),
891
- usage: usage.toLanguageModelUsage(),
892
- providerMetadata
893
- });
894
- controller.close();
895
- } catch (error) {
896
- controller.enqueue({
897
- type: "error",
898
- runId,
899
- from: ChunkFrom.AGENT,
900
- payload: { error }
901
- });
902
- controller.close();
903
- }
904
- }
905
- });
670
+ return new ReadableStream({ start: async (controller) => {
671
+ const textId = randomUUID();
672
+ const usage = createCursorUsageCollector();
673
+ let text = "";
674
+ try {
675
+ const run = await agent.send(prompt, createCursorSendOptions(options, usage, telemetry));
676
+ const responseId = run.id;
677
+ const responseModel = getModelId(run.model ?? getRequestedModel(options) ?? agent.model);
678
+ enqueueStartChunks(controller, {
679
+ runId,
680
+ prompt,
681
+ textId,
682
+ responseId,
683
+ modelId: responseModel,
684
+ providerMetadata: getCursorProviderMetadata(options, agent.agentId, run.id, run.status, run.durationMs, usage.totals(), responseModel)
685
+ });
686
+ let result;
687
+ if (run.supports("stream")) {
688
+ for await (const message of run.stream()) {
689
+ const delta = getTextFromCursorMessage(message);
690
+ if (delta) {
691
+ text += delta;
692
+ enqueueTextDelta(controller, runId, textId, delta);
693
+ }
694
+ }
695
+ result = await run.wait();
696
+ } else {
697
+ result = await run.wait();
698
+ if (result.status === "error" || result.status === "cancelled") throw new Error(`Cursor run ${result.id} ended with status ${result.status}`);
699
+ if (result.result) {
700
+ text += result.result;
701
+ enqueueTextDelta(controller, runId, textId, result.result);
702
+ }
703
+ }
704
+ if (result.status === "error" || result.status === "cancelled") throw new Error(`Cursor run ${result.id} ended with status ${result.status}`);
705
+ if (!text && result.result) {
706
+ text = result.result;
707
+ enqueueTextDelta(controller, runId, textId, result.result);
708
+ }
709
+ const providerMetadata = getCursorProviderMetadata(options, agent.agentId, run.id, result.status, result.durationMs, usage.totals(), getModelId(result.model ?? run.model ?? getRequestedModel(options) ?? agent.model));
710
+ enqueueFinishChunks(controller, {
711
+ runId,
712
+ prompt,
713
+ textId,
714
+ text,
715
+ responseId,
716
+ modelId: getModelId(result.model ?? run.model ?? getRequestedModel(options) ?? agent.model),
717
+ usage: usage.toLanguageModelUsage(),
718
+ providerMetadata
719
+ });
720
+ controller.close();
721
+ } catch (error) {
722
+ controller.enqueue({
723
+ type: "error",
724
+ runId,
725
+ from: ChunkFrom.AGENT,
726
+ payload: { error }
727
+ });
728
+ controller.close();
729
+ }
730
+ } });
906
731
  }
907
732
  async function resolveCursorAgent(agent, options) {
908
- if (!agent) {
909
- return Agent$1.create(toCursorCreateOptions(options));
910
- }
911
- return typeof agent === "function" ? agent(toCursorCreateOptions(options)) : agent;
733
+ if (!agent) return Agent.create(toCursorCreateOptions(options));
734
+ return typeof agent === "function" ? agent(toCursorCreateOptions(options)) : agent;
912
735
  }
913
736
  function toCursorCreateOptions(options) {
914
- const createOptions = { ...options.sdkOptions };
915
- const apiKey = createOptions.apiKey ?? process.env["CURSOR_API_KEY"];
916
- if (apiKey) createOptions.apiKey = apiKey;
917
- if (options.name && !createOptions.name) createOptions.name = options.name;
918
- return createOptions;
737
+ const createOptions = { ...options.sdkOptions };
738
+ const apiKey = createOptions.apiKey ?? process.env["CURSOR_API_KEY"];
739
+ if (apiKey) createOptions.apiKey = apiKey;
740
+ if (options.name && !createOptions.name) createOptions.name = options.name;
741
+ return createOptions;
919
742
  }
920
743
  function createCursorSendOptions(options, usage, telemetry) {
921
- return {
922
- mcpServers: options.sdkOptions?.mcpServers,
923
- onDelta: async (args) => {
924
- usage.record(args.update);
925
- recordCursorToolTelemetry(args.update, telemetry);
926
- }
927
- };
744
+ return {
745
+ mcpServers: options.sdkOptions?.mcpServers,
746
+ onDelta: async (args) => {
747
+ usage.record(args.update);
748
+ recordCursorToolTelemetry(args.update, telemetry);
749
+ }
750
+ };
928
751
  }
929
752
  function createCursorUsageCollector() {
930
- const totals = {
931
- inputTokens: 0,
932
- outputTokens: 0,
933
- cacheReadTokens: 0,
934
- cacheWriteTokens: 0
935
- };
936
- return {
937
- record(update) {
938
- if (update.type !== "turn-ended" || !update.usage) {
939
- return;
940
- }
941
- totals.inputTokens += update.usage.inputTokens;
942
- totals.outputTokens += update.usage.outputTokens;
943
- totals.cacheReadTokens += update.usage.cacheReadTokens;
944
- totals.cacheWriteTokens += update.usage.cacheWriteTokens;
945
- },
946
- totals() {
947
- return {
948
- inputTokens: totals.inputTokens || void 0,
949
- outputTokens: totals.outputTokens || void 0,
950
- cacheReadTokens: totals.cacheReadTokens || void 0,
951
- cacheWriteTokens: totals.cacheWriteTokens || void 0
952
- };
953
- },
954
- toV3Usage() {
955
- return toV3Usage(totals);
956
- },
957
- toLanguageModelUsage() {
958
- return toLanguageModelUsage(toV3Usage(totals));
959
- }
960
- };
753
+ const totals = {
754
+ inputTokens: 0,
755
+ outputTokens: 0,
756
+ cacheReadTokens: 0,
757
+ cacheWriteTokens: 0
758
+ };
759
+ return {
760
+ record(update) {
761
+ if (update.type !== "turn-ended" || !update.usage) return;
762
+ totals.inputTokens += update.usage.inputTokens;
763
+ totals.outputTokens += update.usage.outputTokens;
764
+ totals.cacheReadTokens += update.usage.cacheReadTokens;
765
+ totals.cacheWriteTokens += update.usage.cacheWriteTokens;
766
+ },
767
+ totals() {
768
+ return {
769
+ inputTokens: totals.inputTokens || void 0,
770
+ outputTokens: totals.outputTokens || void 0,
771
+ cacheReadTokens: totals.cacheReadTokens || void 0,
772
+ cacheWriteTokens: totals.cacheWriteTokens || void 0
773
+ };
774
+ },
775
+ toV3Usage() {
776
+ return toV3Usage(totals);
777
+ },
778
+ toLanguageModelUsage() {
779
+ return toLanguageModelUsage(toV3Usage(totals));
780
+ }
781
+ };
961
782
  }
962
783
  function toV3Usage(usage) {
963
- const noCache = usage.inputTokens;
964
- const cacheRead = usage.cacheReadTokens;
965
- const cacheWrite = usage.cacheWriteTokens;
966
- const totalInputTokens = sumDefined(noCache, cacheRead, cacheWrite);
967
- const outputTokens = usage.outputTokens;
968
- return {
969
- inputTokens: {
970
- total: totalInputTokens,
971
- noCache,
972
- cacheRead,
973
- cacheWrite
974
- },
975
- outputTokens: {
976
- total: outputTokens,
977
- text: outputTokens
978
- }
979
- };
784
+ const noCache = usage.inputTokens;
785
+ const cacheRead = usage.cacheReadTokens;
786
+ const cacheWrite = usage.cacheWriteTokens;
787
+ const totalInputTokens = sumDefined(noCache, cacheRead, cacheWrite);
788
+ const outputTokens = usage.outputTokens;
789
+ return {
790
+ inputTokens: {
791
+ total: totalInputTokens,
792
+ noCache,
793
+ cacheRead,
794
+ cacheWrite
795
+ },
796
+ outputTokens: {
797
+ total: outputTokens,
798
+ text: outputTokens
799
+ }
800
+ };
980
801
  }
981
802
  function getRequestedModel(options) {
982
- return options.sdkOptions?.model;
803
+ return options.sdkOptions?.model;
983
804
  }
984
805
  function getModelId(model) {
985
- if (!model) {
986
- return MODEL_ID;
987
- }
988
- return typeof model === "string" ? model : model.id;
806
+ if (!model) return MODEL_ID;
807
+ return typeof model === "string" ? model : model.id;
989
808
  }
990
809
  function getCursorModelId(options, agent) {
991
- return getModelId(getRequestedModel(options) ?? agent.model);
810
+ return getModelId(getRequestedModel(options) ?? agent.model);
992
811
  }
993
812
  function getCursorProviderMetadata(options, agentId, runId, status, durationMs, usage, requestedModel) {
994
- return createProviderMetadata("cursor", {
995
- agentId,
996
- runId,
997
- status,
998
- requestedModel: requestedModel ?? getModelId(getRequestedModel(options)),
999
- durationMs,
1000
- mcpServerNames: getMcpServerNames(options),
1001
- usage
1002
- });
813
+ return createProviderMetadata("cursor", {
814
+ agentId,
815
+ runId,
816
+ status,
817
+ requestedModel: requestedModel ?? getModelId(getRequestedModel(options)),
818
+ durationMs,
819
+ mcpServerNames: getMcpServerNames(options),
820
+ usage
821
+ });
1003
822
  }
1004
823
  function getMcpServerNames(options) {
1005
- const servers = options.sdkOptions?.mcpServers;
1006
- return servers ? Object.keys(servers) : void 0;
824
+ const servers = options.sdkOptions?.mcpServers;
825
+ return servers ? Object.keys(servers) : void 0;
1007
826
  }
1008
827
  function getTextFromCursorMessage(message) {
1009
- if (message.type === "assistant") {
1010
- return message.message.content.map((block) => {
1011
- if (block.type === "text") {
1012
- return block.text;
1013
- }
1014
- return "";
1015
- }).filter(Boolean).join("");
1016
- }
1017
- if (message.type === "task") {
1018
- return message.text ?? "";
1019
- }
1020
- return "";
828
+ if (message.type === "assistant") return message.message.content.map((block) => {
829
+ if (block.type === "text") return block.text;
830
+ return "";
831
+ }).filter(Boolean).join("");
832
+ if (message.type === "task") return message.text ?? "";
833
+ return "";
1021
834
  }
1022
835
  function recordCursorToolTelemetry(update, telemetry) {
1023
- const updateRecord = toRecord(update);
1024
- if (!updateRecord) {
1025
- return;
1026
- }
1027
- const updateType = typeof updateRecord?.type === "string" ? updateRecord.type : void 0;
1028
- if (updateType !== "tool-call-started" && updateType !== "partial-tool-call" && updateType !== "tool-call-completed") {
1029
- return;
1030
- }
1031
- const toolCall = getCursorToolCall(updateRecord);
1032
- if (!toolCall) {
1033
- return;
1034
- }
1035
- if (updateType === "tool-call-started" || updateType === "partial-tool-call") {
1036
- telemetry.startToolCall({
1037
- toolCallId: toolCall.toolCallId,
1038
- toolName: toolCall.toolName,
1039
- input: toolCall.input
1040
- });
1041
- return;
1042
- }
1043
- telemetry.startToolCall({
1044
- toolCallId: toolCall.toolCallId,
1045
- toolName: toolCall.toolName,
1046
- input: toolCall.input
1047
- });
1048
- telemetry.endToolCall({
1049
- toolCallId: toolCall.toolCallId,
1050
- output: toolCall.output,
1051
- isError: toolCall.isError
1052
- });
836
+ const updateRecord = toRecord(update);
837
+ if (!updateRecord) return;
838
+ const updateType = typeof updateRecord?.type === "string" ? updateRecord.type : void 0;
839
+ if (updateType !== "tool-call-started" && updateType !== "partial-tool-call" && updateType !== "tool-call-completed") return;
840
+ const toolCall = getCursorToolCall(updateRecord);
841
+ if (!toolCall) return;
842
+ if (updateType === "tool-call-started" || updateType === "partial-tool-call") {
843
+ telemetry.startToolCall({
844
+ toolCallId: toolCall.toolCallId,
845
+ toolName: toolCall.toolName,
846
+ input: toolCall.input
847
+ });
848
+ return;
849
+ }
850
+ telemetry.startToolCall({
851
+ toolCallId: toolCall.toolCallId,
852
+ toolName: toolCall.toolName,
853
+ input: toolCall.input
854
+ });
855
+ telemetry.endToolCall({
856
+ toolCallId: toolCall.toolCallId,
857
+ output: toolCall.output,
858
+ isError: toolCall.isError
859
+ });
1053
860
  }
1054
861
  function getCursorToolCall(update) {
1055
- const toolCallId = typeof update.callId === "string" ? update.callId : void 0;
1056
- const toolCall = toRecord(update.toolCall);
1057
- if (!toolCallId || !toolCall) {
1058
- return void 0;
1059
- }
1060
- if (toolCall.type === "mcp") {
1061
- const args = toRecord(toolCall.args);
1062
- if (!args) {
1063
- return void 0;
1064
- }
1065
- const providerIdentifier = typeof args?.providerIdentifier === "string" ? args.providerIdentifier : void 0;
1066
- const toolName2 = typeof args?.toolName === "string" ? args.toolName : void 0;
1067
- if (!providerIdentifier || !toolName2) {
1068
- return void 0;
1069
- }
1070
- const result = toRecord(toolCall.result);
1071
- return {
1072
- toolCallId,
1073
- toolName: `mcp__${providerIdentifier}__${toolName2}`,
1074
- input: args.args,
1075
- output: result?.value ?? toolCall.result,
1076
- isError: result?.status === "error" || result?.status === "failed"
1077
- };
1078
- }
1079
- const toolName = typeof toolCall.name === "string" ? toolCall.name : typeof toolCall.type === "string" ? toolCall.type : void 0;
1080
- if (!toolName) {
1081
- return void 0;
1082
- }
1083
- return {
1084
- toolCallId,
1085
- toolName,
1086
- input: "args" in toolCall ? toolCall.args : void 0,
1087
- output: "result" in toolCall ? toolCall.result : void 0,
1088
- isError: toolCall.status === "error"
1089
- };
862
+ const toolCallId = typeof update.callId === "string" ? update.callId : void 0;
863
+ const toolCall = toRecord(update.toolCall);
864
+ if (!toolCallId || !toolCall) return;
865
+ if (toolCall.type === "mcp") {
866
+ const args = toRecord(toolCall.args);
867
+ if (!args) return;
868
+ const providerIdentifier = typeof args?.providerIdentifier === "string" ? args.providerIdentifier : void 0;
869
+ const toolName = typeof args?.toolName === "string" ? args.toolName : void 0;
870
+ if (!providerIdentifier || !toolName) return;
871
+ const result = toRecord(toolCall.result);
872
+ return {
873
+ toolCallId,
874
+ toolName: `mcp__${providerIdentifier}__${toolName}`,
875
+ input: args.args,
876
+ output: result?.value ?? toolCall.result,
877
+ isError: result?.status === "error" || result?.status === "failed"
878
+ };
879
+ }
880
+ const toolName = typeof toolCall.name === "string" ? toolCall.name : typeof toolCall.type === "string" ? toolCall.type : void 0;
881
+ if (!toolName) return;
882
+ return {
883
+ toolCallId,
884
+ toolName,
885
+ input: "args" in toolCall ? toolCall.args : void 0,
886
+ output: "result" in toolCall ? toolCall.result : void 0,
887
+ isError: toolCall.status === "error"
888
+ };
1090
889
  }
1091
890
  function toRecord(value) {
1092
- return value !== null && typeof value === "object" ? value : void 0;
891
+ return value !== null && typeof value === "object" ? value : void 0;
1093
892
  }
1094
-
893
+ //#endregion
1095
894
  export { CursorSDKAgent };
1096
- //# sourceMappingURL=index.js.map
895
+
1097
896
  //# sourceMappingURL=index.js.map