@mastra/claude 0.1.0 → 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -0
- package/dist/docs/SKILL.md +2 -2
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-agents-sdk-agents.md +168 -4
- package/dist/index.cjs +156 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +41 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +156 -21
- package/dist/index.js.map +1 -1
- package/dist/utils.d.ts +13 -4
- package/dist/utils.d.ts.map +1 -1
- package/package.json +7 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# @mastra/claude
|
|
2
2
|
|
|
3
|
+
## 0.2.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Added structured output support for Claude and OpenAI SDK agents using their provider-native structured output APIs. Cursor SDK agent calls now fail clearly when structuredOutput is requested because the Cursor TypeScript SDK does not expose a schema-constrained output API. SDK agents now implement provider-native resume through Mastra's existing resumeGenerate/resumeStream methods by accepting provider-specific resumeData with a message payload. Cursor SDK agent options now use the same clear source split as OpenAI: pass either a pre-created agent or SDK options for wrapper-created agents. ([#17580](https://github.com/mastra-ai/mastra/pull/17580))
|
|
8
|
+
|
|
9
|
+
Example:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
await claudeAgent.resumeGenerate({
|
|
13
|
+
message: 'Continue the task.',
|
|
14
|
+
sessionId: 'claude-session-id',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
await openAIAgent.resumeStream({
|
|
18
|
+
message: 'Continue the task.',
|
|
19
|
+
previousResponseId: 'resp_123',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const result = await openAIAgent.generate('Return the answer as JSON.', {
|
|
23
|
+
structuredOutput: {
|
|
24
|
+
schema: z.object({ answer: z.string() }),
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
// result.object has shape { answer: string }
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Claude and OpenAI SDK agents support `structuredOutput` through their native SDK APIs. `CursorSDKAgent` throws a clear error when `structuredOutput` is requested because the Cursor TypeScript SDK does not expose schema-constrained output.
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- Updated dependencies [[`575f815`](https://github.com/mastra-ai/mastra/commit/575f815c5c3567b71c0b83cbb7fa98c8253a9d9c), [`306909a`](https://github.com/mastra-ai/mastra/commit/306909a693de77d709b38706e2673c9547d24a28), [`5191af8`](https://github.com/mastra-ai/mastra/commit/5191af80c799eea25357c545fc05d91b3883531d), [`43bd3d4`](https://github.com/mastra-ai/mastra/commit/43bd3d421987463fdf35386a45199c49499ed069), [`e6fa79e`](https://github.com/mastra-ai/mastra/commit/e6fa79ec72a2ddffdd25e85270398951e9d552a4), [`904bcdf`](https://github.com/mastra-ai/mastra/commit/904bcdf7b8004aa7be823f9f70ca63580e47e470), [`7f5ee1d`](https://github.com/mastra-ai/mastra/commit/7f5ee1dca46daee8d2817f2ebe49e6335da81956), [`1e9aab5`](https://github.com/mastra-ai/mastra/commit/1e9aab50ff11e6e88fde4d7cbf512c44a9fe8d61), [`bf8eb6d`](https://github.com/mastra-ai/mastra/commit/bf8eb6d0ec213a403eb9265a594ad283c44ab3dc), [`493a328`](https://github.com/mastra-ai/mastra/commit/493a328f4346a1deeb9f1e2e44c8f2a3a4d7591b), [`029a414`](https://github.com/mastra-ai/mastra/commit/029a4141719793bd3e898a39eb5a0466a55f5f3a), [`b147b29`](https://github.com/mastra-ai/mastra/commit/b147b2907f0cd1aa812efe6d6e3f58d22e66fc88), [`d371ac1`](https://github.com/mastra-ai/mastra/commit/d371ac1d9820afaaf7cfdbc380a475946a994d8f), [`cf182b7`](https://github.com/mastra-ai/mastra/commit/cf182b7fb495767946d9840ef29f19cfa906f31f), [`a049c2a`](https://github.com/mastra-ai/mastra/commit/a049c2a9dfb41d0ee2e7a28874a88cd64fd5669f), [`b147b29`](https://github.com/mastra-ai/mastra/commit/b147b2907f0cd1aa812efe6d6e3f58d22e66fc88), [`2a96528`](https://github.com/mastra-ai/mastra/commit/2a9652848dfa3c5a2426f952e9d93554c26fd90f), [`2656d9c`](https://github.com/mastra-ai/mastra/commit/2656d9c2976d4f3354253bfbbbf9b88a1b2bbf34), [`63e3fe1`](https://github.com/mastra-ai/mastra/commit/63e3fe13cc1ea96f91d7c68aea92f400faf9e4da), [`1d4ce8d`](https://github.com/mastra-ai/mastra/commit/1d4ce8daaa54511f325c1b609d31b8e54009d677), [`8c68372`](https://github.com/mastra-ai/mastra/commit/8c68372e85fe0b066ec12c58bd29ffb93e54c552)]:
|
|
35
|
+
- @mastra/core@1.42.0-alpha.4
|
|
36
|
+
|
|
37
|
+
## 0.1.1-alpha.0
|
|
38
|
+
|
|
39
|
+
### Patch Changes
|
|
40
|
+
|
|
41
|
+
- Fixed Claude SDK agent generate responses to include renderable message text. ([#17581](https://github.com/mastra-ai/mastra/pull/17581))
|
|
42
|
+
|
|
43
|
+
- Updated dependencies [[`d468acb`](https://github.com/mastra-ai/mastra/commit/d468acb07aec1bb19a2cb0ada8042b05b46746b2), [`e9be4e7`](https://github.com/mastra-ai/mastra/commit/e9be4e747ec3d8b65548bff92f9377db06105376), [`d53cfc2`](https://github.com/mastra-ai/mastra/commit/d53cfc2c7f8d78343a4aa84ec4e129ba25f3325e), [`65799d4`](https://github.com/mastra-ai/mastra/commit/65799d4d549e5ebb9c848fbe3f51ac090f64becf), [`c268c89`](https://github.com/mastra-ai/mastra/commit/c268c89f4c63a93ee474d3cffdf3ea60bf00d4f2), [`d468acb`](https://github.com/mastra-ai/mastra/commit/d468acb07aec1bb19a2cb0ada8042b05b46746b2), [`0c72f03`](https://github.com/mastra-ai/mastra/commit/0c72f032abb13254df5a7856d64be2f207b8006d), [`3b45ea9`](https://github.com/mastra-ai/mastra/commit/3b45ea95015557a6cb9d70dc5252af54ab1b78ac), [`f084be1`](https://github.com/mastra-ai/mastra/commit/f084be1fcbe33ad7480913e44d6130c421c0976f)]:
|
|
44
|
+
- @mastra/core@1.42.0-alpha.0
|
|
45
|
+
|
|
3
46
|
## 0.1.0
|
|
4
47
|
|
|
5
48
|
### Minor Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-claude
|
|
|
3
3
|
description: Documentation for @mastra/claude. Use when working with @mastra/claude APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/claude"
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.2.0-alpha.1"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -16,7 +16,7 @@ Read the individual reference documents for detailed explanations and code examp
|
|
|
16
16
|
|
|
17
17
|
### Docs
|
|
18
18
|
|
|
19
|
-
- [SDK agents](references/docs-agents-sdk-agents.md) - Use Claude Agent SDK
|
|
19
|
+
- [SDK agents](references/docs-agents-sdk-agents.md) - Use Claude Agent SDK, Cursor Agent SDK, and OpenAI Agents SDK agents from Mastra.
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
Read [assets/SOURCE_MAP.json](assets/SOURCE_MAP.json) for source code references.
|
|
@@ -13,6 +13,7 @@ SDK agents let you use other agent SDK frameworks inside Mastra. Use them to reg
|
|
|
13
13
|
|
|
14
14
|
- [Claude Agent SDK](#claude-agent-sdk): Use `@mastra/claude` to register a Claude SDK agent and call it with Mastra `generate()` and `stream()`.
|
|
15
15
|
- [Cursor Agent SDK](#cursor-agent-sdk): Use `@mastra/cursor` to register a Cursor SDK agent and call it with Mastra `generate()` and `stream()`.
|
|
16
|
+
- [OpenAI Agents SDK](#openai-agents-sdk): Use `@mastra/openai` to register an OpenAI SDK agent and call it with Mastra `generate()` and `stream()`.
|
|
16
17
|
|
|
17
18
|
## Claude Agent SDK
|
|
18
19
|
|
|
@@ -154,7 +155,7 @@ export const cursorSDKAgent = new CursorSDKAgent({
|
|
|
154
155
|
sdkOptions: {
|
|
155
156
|
apiKey: process.env.CURSOR_API_KEY,
|
|
156
157
|
model: {
|
|
157
|
-
id: 'gpt-5
|
|
158
|
+
id: 'gpt-5',
|
|
158
159
|
},
|
|
159
160
|
local: {
|
|
160
161
|
cwd: process.cwd(),
|
|
@@ -176,7 +177,7 @@ import { CursorSDKAgent } from '@mastra/cursor'
|
|
|
176
177
|
const cursorAgent = CursorAgent.create({
|
|
177
178
|
apiKey: process.env.CURSOR_API_KEY,
|
|
178
179
|
model: {
|
|
179
|
-
id: 'gpt-5
|
|
180
|
+
id: 'gpt-5',
|
|
180
181
|
},
|
|
181
182
|
local: {
|
|
182
183
|
cwd: process.cwd(),
|
|
@@ -206,7 +207,7 @@ export const cursorSDKAgent = new CursorSDKAgent({
|
|
|
206
207
|
sdkOptions: {
|
|
207
208
|
apiKey: process.env.CURSOR_API_KEY,
|
|
208
209
|
model: {
|
|
209
|
-
id: 'gpt-5
|
|
210
|
+
id: 'gpt-5',
|
|
210
211
|
},
|
|
211
212
|
local: {
|
|
212
213
|
cwd: process.cwd(),
|
|
@@ -216,6 +217,117 @@ export const cursorSDKAgent = new CursorSDKAgent({
|
|
|
216
217
|
})
|
|
217
218
|
```
|
|
218
219
|
|
|
220
|
+
## OpenAI Agents SDK
|
|
221
|
+
|
|
222
|
+
Use `@mastra/openai` to register an OpenAI Agents SDK agent in Mastra while keeping OpenAI-specific agent settings in OpenAI SDK options.
|
|
223
|
+
|
|
224
|
+
### Install OpenAI packages
|
|
225
|
+
|
|
226
|
+
Install the Mastra package and the OpenAI Agents SDK peer dependency:
|
|
227
|
+
|
|
228
|
+
**npm**:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
npm install @mastra/openai @openai/agents zod
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**pnpm**:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
pnpm add @mastra/openai @openai/agents zod
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Yarn**:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
yarn add @mastra/openai @openai/agents zod
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Bun**:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
bun add @mastra/openai @openai/agents zod
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Set the OpenAI SDK credential:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
export OPENAI_API_KEY="..."
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Create an OpenAI SDK agent
|
|
259
|
+
|
|
260
|
+
Configure OpenAI Agents SDK through `sdkOptions`. `OpenAISDKAgent` creates the OpenAI SDK agent on first use.
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import { OpenAISDKAgent } from '@mastra/openai'
|
|
264
|
+
|
|
265
|
+
export const openaiSDKAgent = new OpenAISDKAgent({
|
|
266
|
+
id: 'openai-sdk-agent',
|
|
267
|
+
name: 'OpenAI SDK Agent',
|
|
268
|
+
description: 'Use OpenAI Agents SDK through Mastra.',
|
|
269
|
+
sdkOptions: {
|
|
270
|
+
name: 'Repository assistant',
|
|
271
|
+
instructions: 'Answer clearly and cite the relevant files.',
|
|
272
|
+
model: 'gpt-5',
|
|
273
|
+
},
|
|
274
|
+
})
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Use an existing OpenAI SDK agent
|
|
278
|
+
|
|
279
|
+
If your app already creates an OpenAI SDK agent, pass that agent to `OpenAISDKAgent` instead:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
import { Agent as OpenAIAgent } from '@openai/agents'
|
|
283
|
+
import { OpenAISDKAgent } from '@mastra/openai'
|
|
284
|
+
|
|
285
|
+
const sdkAgent = new OpenAIAgent({
|
|
286
|
+
name: 'Repository assistant',
|
|
287
|
+
instructions: 'Answer clearly and cite the relevant files.',
|
|
288
|
+
model: 'gpt-5',
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
export const openaiSDKAgent = new OpenAISDKAgent({
|
|
292
|
+
id: 'openai-sdk-agent',
|
|
293
|
+
name: 'OpenAI SDK Agent',
|
|
294
|
+
description: 'Use OpenAI Agents SDK through Mastra.',
|
|
295
|
+
agent: sdkAgent,
|
|
296
|
+
})
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Add OpenAI SDK tools
|
|
300
|
+
|
|
301
|
+
OpenAI Agents SDK tools are configured with OpenAI SDK options. Create tools with the OpenAI SDK, then pass them through `sdkOptions.tools`.
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
import { tool } from '@openai/agents'
|
|
305
|
+
import { OpenAISDKAgent } from '@mastra/openai'
|
|
306
|
+
import { z } from 'zod'
|
|
307
|
+
|
|
308
|
+
const getTemperature = tool({
|
|
309
|
+
name: 'get_temperature',
|
|
310
|
+
description: 'Get the current temperature for a city.',
|
|
311
|
+
parameters: z.object({
|
|
312
|
+
city: z.string(),
|
|
313
|
+
}),
|
|
314
|
+
execute: async ({ city }) => {
|
|
315
|
+
return `${city}: 27 C`
|
|
316
|
+
},
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
export const openaiSDKAgent = new OpenAISDKAgent({
|
|
320
|
+
id: 'openai-sdk-agent',
|
|
321
|
+
name: 'OpenAI SDK Agent',
|
|
322
|
+
description: 'Use OpenAI Agents SDK through Mastra.',
|
|
323
|
+
sdkOptions: {
|
|
324
|
+
name: 'Weather assistant',
|
|
325
|
+
model: 'gpt-5',
|
|
326
|
+
tools: [getTemperature],
|
|
327
|
+
},
|
|
328
|
+
})
|
|
329
|
+
```
|
|
330
|
+
|
|
219
331
|
## Register SDK agents
|
|
220
332
|
|
|
221
333
|
Register SDK agents in the Mastra instance like other agents:
|
|
@@ -224,11 +336,13 @@ Register SDK agents in the Mastra instance like other agents:
|
|
|
224
336
|
import { Mastra } from '@mastra/core'
|
|
225
337
|
import { claudeSDKAgent } from './agents/claude-sdk-agent'
|
|
226
338
|
import { cursorSDKAgent } from './agents/cursor-sdk-agent'
|
|
339
|
+
import { openaiSDKAgent } from './agents/openai-sdk-agent'
|
|
227
340
|
|
|
228
341
|
export const mastra = new Mastra({
|
|
229
342
|
agents: {
|
|
230
343
|
claudeSDKAgent,
|
|
231
344
|
cursorSDKAgent,
|
|
345
|
+
openaiSDKAgent,
|
|
232
346
|
},
|
|
233
347
|
})
|
|
234
348
|
```
|
|
@@ -246,11 +360,61 @@ for await (const chunk of stream.textStream) {
|
|
|
246
360
|
}
|
|
247
361
|
```
|
|
248
362
|
|
|
363
|
+
## Resume SDK runs
|
|
364
|
+
|
|
365
|
+
SDK agents support Mastra `resumeGenerate()` and `resumeStream()` with provider-native resume data. Pass the message to continue with and the resume identifier used by the underlying SDK.
|
|
366
|
+
|
|
367
|
+
Claude SDK agents can resume a known session with `sessionId`:
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
const result = await claudeSDKAgent.resumeGenerate({
|
|
371
|
+
message: 'Continue the previous task.',
|
|
372
|
+
sessionId: 'claude-session-id',
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
console.log(result.text)
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
OpenAI SDK agents can resume with a previous response, conversation, or session:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
const stream = await openaiSDKAgent.resumeStream({
|
|
382
|
+
message: 'Continue the previous task.',
|
|
383
|
+
previousResponseId: 'resp_123',
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
for await (const chunk of stream.textStream) {
|
|
387
|
+
process.stdout.write(chunk)
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Cursor SDK agents can continue with the wrapped SDK agent. If you need to resume a stored Cursor SDK agent by ID, pass `agentId` in `resumeData`.
|
|
392
|
+
|
|
393
|
+
## Structured output
|
|
394
|
+
|
|
395
|
+
Claude and OpenAI SDK agents support Mastra `structuredOutput` through their provider-native structured output APIs. The validated value is available on `result.object`.
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
import { z } from 'zod'
|
|
399
|
+
|
|
400
|
+
const result = await openaiSDKAgent.generate<{ summary: string }>('Summarize this project.', {
|
|
401
|
+
structuredOutput: {
|
|
402
|
+
schema: z.object({
|
|
403
|
+
summary: z.string(),
|
|
404
|
+
}),
|
|
405
|
+
},
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
console.log(result.object.summary)
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
Cursor SDK agents throw a clear error when `structuredOutput` is requested because the Cursor TypeScript SDK doesn't expose a schema-constrained output API.
|
|
412
|
+
|
|
249
413
|
## Observability
|
|
250
414
|
|
|
251
415
|
SDK agents create Mastra agent and model spans for `generate()` and `stream()` calls. Mastra records SDK-provided usage, tool activity, and provider metadata when the vendor SDK exposes those events.
|
|
252
416
|
|
|
253
|
-
Claude SDK runs can include SDK-estimated cost from the Claude result message. Cursor SDK runs include token usage from Cursor interaction updates.
|
|
417
|
+
Claude SDK runs can include SDK-estimated cost from the Claude result message. Cursor SDK runs include token usage from Cursor interaction updates. OpenAI SDK runs include token usage from OpenAI run state.
|
|
254
418
|
|
|
255
419
|
For storage and dashboard setup, see [Observability](https://mastra.ai/docs/observability/overview).
|
|
256
420
|
|
package/dist/index.cjs
CHANGED
|
@@ -8,6 +8,7 @@ var requestContext = require('@mastra/core/request-context');
|
|
|
8
8
|
var stream = require('@mastra/core/stream');
|
|
9
9
|
var messageList = require('@mastra/core/agent/message-list');
|
|
10
10
|
var observability = require('@mastra/core/observability');
|
|
11
|
+
var schema = require('@mastra/core/schema');
|
|
11
12
|
|
|
12
13
|
// src/index.ts
|
|
13
14
|
function createNoopModel({ modelId, provider }) {
|
|
@@ -35,7 +36,8 @@ function createCompletedMastraStream({
|
|
|
35
36
|
modelId,
|
|
36
37
|
usage,
|
|
37
38
|
providerMetadata,
|
|
38
|
-
costContext
|
|
39
|
+
costContext,
|
|
40
|
+
object
|
|
39
41
|
}) {
|
|
40
42
|
return new web.ReadableStream({
|
|
41
43
|
start(controller) {
|
|
@@ -60,7 +62,8 @@ function createCompletedMastraStream({
|
|
|
60
62
|
modelId,
|
|
61
63
|
usage,
|
|
62
64
|
providerMetadata,
|
|
63
|
-
costContext
|
|
65
|
+
costContext,
|
|
66
|
+
object
|
|
64
67
|
});
|
|
65
68
|
controller.close();
|
|
66
69
|
}
|
|
@@ -72,11 +75,12 @@ function createMastraOutput({
|
|
|
72
75
|
modelId,
|
|
73
76
|
provider,
|
|
74
77
|
stream: stream$1,
|
|
78
|
+
responseText = "",
|
|
75
79
|
options
|
|
76
80
|
}) {
|
|
77
81
|
const messageList$1 = new messageList.MessageList();
|
|
78
82
|
messageList$1.add(messages, "input");
|
|
79
|
-
messageList$1.add([{ role: "assistant", content:
|
|
83
|
+
messageList$1.add([{ role: "assistant", content: responseText }], "response");
|
|
80
84
|
return new stream.MastraModelOutput({
|
|
81
85
|
model: {
|
|
82
86
|
modelId,
|
|
@@ -108,7 +112,8 @@ function toFullOutput({
|
|
|
108
112
|
modelId: result.response.modelId,
|
|
109
113
|
usage: toLanguageModelUsage(result.usage),
|
|
110
114
|
providerMetadata: result.providerMetadata,
|
|
111
|
-
costContext: result.costContext
|
|
115
|
+
costContext: result.costContext,
|
|
116
|
+
object: result.object
|
|
112
117
|
});
|
|
113
118
|
return createMastraOutput({
|
|
114
119
|
messages,
|
|
@@ -116,6 +121,7 @@ function toFullOutput({
|
|
|
116
121
|
modelId: result.response.modelId,
|
|
117
122
|
provider,
|
|
118
123
|
stream,
|
|
124
|
+
responseText: text,
|
|
119
125
|
options
|
|
120
126
|
}).getFullOutput();
|
|
121
127
|
}
|
|
@@ -486,7 +492,8 @@ function enqueueFinishChunks(controller, {
|
|
|
486
492
|
modelId,
|
|
487
493
|
usage,
|
|
488
494
|
providerMetadata,
|
|
489
|
-
costContext
|
|
495
|
+
costContext,
|
|
496
|
+
object
|
|
490
497
|
}) {
|
|
491
498
|
const timestamp = /* @__PURE__ */ new Date();
|
|
492
499
|
const response = {
|
|
@@ -510,6 +517,14 @@ function enqueueFinishChunks(controller, {
|
|
|
510
517
|
providerMetadata
|
|
511
518
|
}
|
|
512
519
|
});
|
|
520
|
+
if (object !== void 0) {
|
|
521
|
+
controller.enqueue({
|
|
522
|
+
type: "object-result",
|
|
523
|
+
runId,
|
|
524
|
+
from: stream.ChunkFrom.AGENT,
|
|
525
|
+
object
|
|
526
|
+
});
|
|
527
|
+
}
|
|
513
528
|
controller.enqueue({
|
|
514
529
|
type: "step-finish",
|
|
515
530
|
runId,
|
|
@@ -614,6 +629,48 @@ function promptToText(prompt) {
|
|
|
614
629
|
}
|
|
615
630
|
return "";
|
|
616
631
|
}
|
|
632
|
+
function getStructuredOutputSchema(structuredOutput) {
|
|
633
|
+
if (!structuredOutput?.schema) {
|
|
634
|
+
return void 0;
|
|
635
|
+
}
|
|
636
|
+
return schema.standardSchemaToJSONSchema(schema.toStandardSchema(structuredOutput.schema));
|
|
637
|
+
}
|
|
638
|
+
async function getStructuredOutputFromValue(value, structuredOutput) {
|
|
639
|
+
if (!structuredOutput?.schema) {
|
|
640
|
+
return void 0;
|
|
641
|
+
}
|
|
642
|
+
let parsed;
|
|
643
|
+
if (typeof value === "string") {
|
|
644
|
+
try {
|
|
645
|
+
parsed = JSON.parse(value);
|
|
646
|
+
} catch (error) {
|
|
647
|
+
return handleStructuredOutputError(
|
|
648
|
+
new Error("Structured output must be valid JSON.", { cause: error }),
|
|
649
|
+
structuredOutput
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
} else {
|
|
653
|
+
parsed = value;
|
|
654
|
+
}
|
|
655
|
+
const schema$1 = schema.toStandardSchema(structuredOutput.schema);
|
|
656
|
+
const result = await schema$1["~standard"].validate(parsed);
|
|
657
|
+
if (!result.issues) {
|
|
658
|
+
return result.value;
|
|
659
|
+
}
|
|
660
|
+
const message = result.issues.map((issue) => `- ${issue.path?.join(".") || "root"}: ${issue.message}`).join("\n");
|
|
661
|
+
return handleStructuredOutputError(new Error(`Structured output validation failed:
|
|
662
|
+
${message}`), structuredOutput);
|
|
663
|
+
}
|
|
664
|
+
function handleStructuredOutputError(error, structuredOutput) {
|
|
665
|
+
if (structuredOutput.errorStrategy === "fallback") {
|
|
666
|
+
return structuredOutput.fallbackValue;
|
|
667
|
+
}
|
|
668
|
+
if (structuredOutput.errorStrategy === "warn") {
|
|
669
|
+
structuredOutput.logger?.warn(error.message);
|
|
670
|
+
return void 0;
|
|
671
|
+
}
|
|
672
|
+
throw error;
|
|
673
|
+
}
|
|
617
674
|
function sumDefined(...values) {
|
|
618
675
|
const defined = values.filter((value) => typeof value === "number");
|
|
619
676
|
if (defined.length === 0) {
|
|
@@ -674,9 +731,7 @@ var ClaudeSDKAgent = class extends agent.Agent {
|
|
|
674
731
|
});
|
|
675
732
|
let result;
|
|
676
733
|
try {
|
|
677
|
-
result = await telemetry.execute(
|
|
678
|
-
() => runClaudeGenerate(prompt, this.options, telemetry, options?.abortSignal ?? options?.signal)
|
|
679
|
-
);
|
|
734
|
+
result = await telemetry.execute(() => runClaudeGenerate(prompt, this.options, telemetry, options));
|
|
680
735
|
telemetry.endGenerate(result);
|
|
681
736
|
} catch (error) {
|
|
682
737
|
telemetry.fail(error);
|
|
@@ -687,7 +742,7 @@ var ClaudeSDKAgent = class extends agent.Agent {
|
|
|
687
742
|
runId,
|
|
688
743
|
provider: PROVIDER,
|
|
689
744
|
result,
|
|
690
|
-
options: telemetry.outputOptions()
|
|
745
|
+
options: { ...telemetry.outputOptions(), structuredOutput: options?.structuredOutput }
|
|
691
746
|
});
|
|
692
747
|
}
|
|
693
748
|
async stream(messages, options) {
|
|
@@ -720,26 +775,82 @@ var ClaudeSDKAgent = class extends agent.Agent {
|
|
|
720
775
|
runId,
|
|
721
776
|
modelId,
|
|
722
777
|
provider: PROVIDER,
|
|
723
|
-
stream: telemetry.wrapStream(
|
|
724
|
-
|
|
725
|
-
),
|
|
726
|
-
options: telemetry.outputOptions()
|
|
778
|
+
stream: telemetry.wrapStream(runClaudeAsMastraStream(prompt, this.options, runId, telemetry, options)),
|
|
779
|
+
options: { ...telemetry.outputOptions(), structuredOutput: options?.structuredOutput }
|
|
727
780
|
});
|
|
728
781
|
}
|
|
782
|
+
async resumeGenerate(resumeData, options) {
|
|
783
|
+
const data = validateClaudeResumeData(resumeData);
|
|
784
|
+
return this.generate(data.message, createClaudeResumeRunOptions(data, options));
|
|
785
|
+
}
|
|
786
|
+
async resumeStream(resumeData, options) {
|
|
787
|
+
const data = validateClaudeResumeData(resumeData);
|
|
788
|
+
return this.stream(data.message, createClaudeResumeRunOptions(data, options));
|
|
789
|
+
}
|
|
729
790
|
};
|
|
730
|
-
|
|
791
|
+
function validateClaudeResumeData(resumeData) {
|
|
792
|
+
if (!isRecord(resumeData) || !("message" in resumeData)) {
|
|
793
|
+
throw new Error("ClaudeSDKAgent resumeData must include a message.");
|
|
794
|
+
}
|
|
795
|
+
const hasSessionId = "sessionId" in resumeData;
|
|
796
|
+
const hasContinue = "continue" in resumeData;
|
|
797
|
+
if (hasSessionId && hasContinue) {
|
|
798
|
+
throw new Error("ClaudeSDKAgent resumeData must include either sessionId or continue: true, not both.");
|
|
799
|
+
}
|
|
800
|
+
if (hasSessionId) {
|
|
801
|
+
if (typeof resumeData.sessionId !== "string") {
|
|
802
|
+
throw new Error("ClaudeSDKAgent resumeData.sessionId must be a string.");
|
|
803
|
+
}
|
|
804
|
+
return resumeData;
|
|
805
|
+
}
|
|
806
|
+
if (hasContinue) {
|
|
807
|
+
if (resumeData.continue !== true) {
|
|
808
|
+
throw new Error("ClaudeSDKAgent resumeData.continue must be true when provided.");
|
|
809
|
+
}
|
|
810
|
+
return resumeData;
|
|
811
|
+
}
|
|
812
|
+
throw new Error("ClaudeSDKAgent resumeData must include sessionId or continue: true.");
|
|
813
|
+
}
|
|
814
|
+
function createClaudeResumeRunOptions(resumeData, options) {
|
|
815
|
+
const sdkOptions = { ...options?.sdkOptions };
|
|
816
|
+
if ("sessionId" in resumeData && typeof resumeData.sessionId === "string") {
|
|
817
|
+
sdkOptions.resume = resumeData.sessionId;
|
|
818
|
+
if (resumeData.forkSession !== void 0) {
|
|
819
|
+
sdkOptions.forkSession = resumeData.forkSession;
|
|
820
|
+
}
|
|
821
|
+
if (resumeData.resumeSessionAt !== void 0) {
|
|
822
|
+
sdkOptions.resumeSessionAt = resumeData.resumeSessionAt;
|
|
823
|
+
}
|
|
824
|
+
} else {
|
|
825
|
+
sdkOptions.continue = true;
|
|
826
|
+
}
|
|
827
|
+
return {
|
|
828
|
+
...options,
|
|
829
|
+
sdkOptions
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
async function runClaudeGenerate(prompt, options, telemetry, runOptions) {
|
|
731
833
|
let text = "";
|
|
834
|
+
let structuredOutputValue;
|
|
732
835
|
const usage = createClaudeUsageCollector();
|
|
733
|
-
for await (const message of observeClaudeMessages(
|
|
836
|
+
for await (const message of observeClaudeMessages(
|
|
837
|
+
runClaude(prompt, options, runOptions?.abortSignal ?? runOptions?.signal, runOptions),
|
|
838
|
+
telemetry
|
|
839
|
+
)) {
|
|
734
840
|
usage.record(message);
|
|
735
841
|
if (message.type === "result") {
|
|
736
842
|
if (message.subtype !== "success") {
|
|
737
843
|
throw new Error(message.errors.join("\n") || `Claude Agent SDK failed with ${message.subtype}`);
|
|
738
844
|
}
|
|
739
845
|
text = message.result;
|
|
846
|
+
structuredOutputValue = getClaudeStructuredOutput(message);
|
|
740
847
|
}
|
|
741
848
|
}
|
|
742
849
|
const totals = usage.totals();
|
|
850
|
+
const object = await getStructuredOutputFromValue(
|
|
851
|
+
structuredOutputValue === void 0 ? text : structuredOutputValue,
|
|
852
|
+
runOptions?.structuredOutput
|
|
853
|
+
);
|
|
743
854
|
return {
|
|
744
855
|
content: [{ type: "text", text }],
|
|
745
856
|
finishReason: { unified: "stop", raw: "stop" },
|
|
@@ -750,10 +861,11 @@ async function runClaudeGenerate(prompt, options, telemetry, signal) {
|
|
|
750
861
|
timestamp: /* @__PURE__ */ new Date()
|
|
751
862
|
},
|
|
752
863
|
providerMetadata: getClaudeProviderMetadata(options, totals),
|
|
753
|
-
costContext: getClaudeCostContext(options, totals)
|
|
864
|
+
costContext: getClaudeCostContext(options, totals),
|
|
865
|
+
object
|
|
754
866
|
};
|
|
755
867
|
}
|
|
756
|
-
function runClaudeAsMastraStream(prompt, options, runId, telemetry,
|
|
868
|
+
function runClaudeAsMastraStream(prompt, options, runId, telemetry, runOptions) {
|
|
757
869
|
return new web.ReadableStream({
|
|
758
870
|
start: async (controller) => {
|
|
759
871
|
const textId = crypto.randomUUID();
|
|
@@ -761,6 +873,7 @@ function runClaudeAsMastraStream(prompt, options, runId, telemetry, signal) {
|
|
|
761
873
|
const modelId = getModelId(options);
|
|
762
874
|
const usage = createClaudeUsageCollector();
|
|
763
875
|
let text = "";
|
|
876
|
+
let structuredOutputValue;
|
|
764
877
|
let sawDelta = false;
|
|
765
878
|
try {
|
|
766
879
|
enqueueStartChunks(controller, {
|
|
@@ -771,7 +884,10 @@ function runClaudeAsMastraStream(prompt, options, runId, telemetry, signal) {
|
|
|
771
884
|
modelId,
|
|
772
885
|
providerMetadata: getClaudeProviderMetadata(options, usage.totals())
|
|
773
886
|
});
|
|
774
|
-
for await (const message of observeClaudeMessages(
|
|
887
|
+
for await (const message of observeClaudeMessages(
|
|
888
|
+
runClaude(prompt, options, runOptions?.abortSignal ?? runOptions?.signal, runOptions),
|
|
889
|
+
telemetry
|
|
890
|
+
)) {
|
|
775
891
|
usage.record(message);
|
|
776
892
|
const delta = getTextDelta(message);
|
|
777
893
|
if (delta) {
|
|
@@ -787,6 +903,7 @@ function runClaudeAsMastraStream(prompt, options, runId, telemetry, signal) {
|
|
|
787
903
|
text += message.result;
|
|
788
904
|
enqueueTextDelta(controller, runId, textId, message.result);
|
|
789
905
|
}
|
|
906
|
+
structuredOutputValue = getClaudeStructuredOutput(message);
|
|
790
907
|
}
|
|
791
908
|
}
|
|
792
909
|
const totals = usage.totals();
|
|
@@ -800,7 +917,11 @@ function runClaudeAsMastraStream(prompt, options, runId, telemetry, signal) {
|
|
|
800
917
|
modelId,
|
|
801
918
|
usage: usage.toLanguageModelUsage(),
|
|
802
919
|
providerMetadata,
|
|
803
|
-
costContext: getClaudeCostContext(options, totals)
|
|
920
|
+
costContext: getClaudeCostContext(options, totals),
|
|
921
|
+
object: await getStructuredOutputFromValue(
|
|
922
|
+
structuredOutputValue === void 0 ? text : structuredOutputValue,
|
|
923
|
+
runOptions?.structuredOutput
|
|
924
|
+
)
|
|
804
925
|
});
|
|
805
926
|
controller.close();
|
|
806
927
|
} catch (error) {
|
|
@@ -815,11 +936,19 @@ function runClaudeAsMastraStream(prompt, options, runId, telemetry, signal) {
|
|
|
815
936
|
}
|
|
816
937
|
});
|
|
817
938
|
}
|
|
818
|
-
function runClaude(prompt, options, signal) {
|
|
939
|
+
function runClaude(prompt, options, signal, runOptions) {
|
|
819
940
|
const abortController = createAbortController(signal);
|
|
820
941
|
const queryOptions = {
|
|
821
|
-
...options.sdkOptions
|
|
942
|
+
...options.sdkOptions,
|
|
943
|
+
...runOptions?.sdkOptions
|
|
822
944
|
};
|
|
945
|
+
const outputSchema = getStructuredOutputSchema(runOptions?.structuredOutput);
|
|
946
|
+
if (outputSchema) {
|
|
947
|
+
queryOptions.outputFormat = {
|
|
948
|
+
type: "json_schema",
|
|
949
|
+
schema: outputSchema
|
|
950
|
+
};
|
|
951
|
+
}
|
|
823
952
|
if (abortController) {
|
|
824
953
|
queryOptions.abortController = abortController;
|
|
825
954
|
}
|
|
@@ -828,6 +957,12 @@ function runClaude(prompt, options, signal) {
|
|
|
828
957
|
options: queryOptions
|
|
829
958
|
});
|
|
830
959
|
}
|
|
960
|
+
function getClaudeStructuredOutput(message) {
|
|
961
|
+
if (message.type !== "result") {
|
|
962
|
+
return void 0;
|
|
963
|
+
}
|
|
964
|
+
return message.structured_output;
|
|
965
|
+
}
|
|
831
966
|
async function* observeClaudeMessages(messages, telemetry) {
|
|
832
967
|
for await (const message of messages) {
|
|
833
968
|
recordClaudeToolTelemetry(message, telemetry);
|