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