@mastra/cursor 0.0.0-agent-learning-fetch-again-20260701152039

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