@mastra/openai 1.0.1-alpha.9 → 1.0.3
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 +126 -0
- package/LICENSE.md +30 -0
- package/README.md +92 -0
- package/dist/docs/SKILL.md +23 -0
- package/dist/docs/assets/SOURCE_MAP.json +6 -0
- package/dist/docs/references/docs-agents-sdk-agents.md +425 -0
- package/dist/docs/references/docs-memory-memory-processors.md +314 -0
- package/dist/index.cjs +1177 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1175 -0
- package/dist/index.js.map +1 -0
- package/dist/utils.d.ts +147 -0
- package/dist/utils.d.ts.map +1 -0
- package/package.json +58 -52
- package/src/Openai.test.ts +0 -61
- package/src/assets/openai.png +0 -0
- package/src/client/index.ts +0 -4
- package/src/client/schemas.gen.ts +0 -9928
- package/src/client/service-comments.ts +0 -390
- package/src/client/services.gen.ts +0 -1481
- package/src/client/types.gen.ts +0 -7500
- package/src/client/zodSchema.ts +0 -3898
- package/src/index.ts +0 -59
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1177 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var crypto = require('crypto');
|
|
4
|
+
var web = require('stream/web');
|
|
5
|
+
var agent = require('@mastra/core/agent');
|
|
6
|
+
var requestContext = require('@mastra/core/request-context');
|
|
7
|
+
var stream = require('@mastra/core/stream');
|
|
8
|
+
var agents = require('@openai/agents');
|
|
9
|
+
var messageList = require('@mastra/core/agent/message-list');
|
|
10
|
+
var observability = require('@mastra/core/observability');
|
|
11
|
+
var schema = require('@mastra/core/schema');
|
|
12
|
+
|
|
13
|
+
// src/index.ts
|
|
14
|
+
function createNoopModel({ modelId, provider }) {
|
|
15
|
+
return {
|
|
16
|
+
modelId,
|
|
17
|
+
provider,
|
|
18
|
+
specificationVersion: "v3",
|
|
19
|
+
supportedUrls: {},
|
|
20
|
+
doGenerate: async () => createNoopStreamResult(),
|
|
21
|
+
doStream: async () => createNoopStreamResult()
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function createNoopStreamResult() {
|
|
25
|
+
return {
|
|
26
|
+
stream: new web.ReadableStream({
|
|
27
|
+
start: (controller) => controller.close()
|
|
28
|
+
})
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function createCompletedMastraStream({
|
|
32
|
+
runId,
|
|
33
|
+
prompt,
|
|
34
|
+
text,
|
|
35
|
+
responseId,
|
|
36
|
+
modelId,
|
|
37
|
+
usage,
|
|
38
|
+
providerMetadata,
|
|
39
|
+
costContext,
|
|
40
|
+
object
|
|
41
|
+
}) {
|
|
42
|
+
return new web.ReadableStream({
|
|
43
|
+
start(controller) {
|
|
44
|
+
const textId = crypto.randomUUID();
|
|
45
|
+
enqueueStartChunks(controller, {
|
|
46
|
+
runId,
|
|
47
|
+
prompt,
|
|
48
|
+
textId,
|
|
49
|
+
responseId,
|
|
50
|
+
modelId,
|
|
51
|
+
providerMetadata
|
|
52
|
+
});
|
|
53
|
+
if (text) {
|
|
54
|
+
enqueueTextDelta(controller, runId, textId, text);
|
|
55
|
+
}
|
|
56
|
+
enqueueFinishChunks(controller, {
|
|
57
|
+
runId,
|
|
58
|
+
prompt,
|
|
59
|
+
textId,
|
|
60
|
+
text,
|
|
61
|
+
responseId,
|
|
62
|
+
modelId,
|
|
63
|
+
usage,
|
|
64
|
+
providerMetadata,
|
|
65
|
+
costContext,
|
|
66
|
+
object
|
|
67
|
+
});
|
|
68
|
+
controller.close();
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function createMastraOutput({
|
|
73
|
+
messages,
|
|
74
|
+
runId,
|
|
75
|
+
modelId,
|
|
76
|
+
provider,
|
|
77
|
+
stream: stream$1,
|
|
78
|
+
options
|
|
79
|
+
}) {
|
|
80
|
+
const messageList$1 = new messageList.MessageList();
|
|
81
|
+
messageList$1.add(messages, "input");
|
|
82
|
+
messageList$1.add([{ role: "assistant", content: "" }], "response");
|
|
83
|
+
return new stream.MastraModelOutput({
|
|
84
|
+
model: {
|
|
85
|
+
modelId,
|
|
86
|
+
provider,
|
|
87
|
+
version: "v3"
|
|
88
|
+
},
|
|
89
|
+
stream: stream$1,
|
|
90
|
+
messageList: messageList$1,
|
|
91
|
+
messageId: crypto.randomUUID(),
|
|
92
|
+
options: {
|
|
93
|
+
...options,
|
|
94
|
+
runId
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function toFullOutput({
|
|
99
|
+
messages,
|
|
100
|
+
runId,
|
|
101
|
+
provider,
|
|
102
|
+
result,
|
|
103
|
+
options
|
|
104
|
+
}) {
|
|
105
|
+
const text = result.content.map((part) => part.text).join("");
|
|
106
|
+
const stream = createCompletedMastraStream({
|
|
107
|
+
runId,
|
|
108
|
+
prompt: promptToText(messages),
|
|
109
|
+
text,
|
|
110
|
+
responseId: result.response.id,
|
|
111
|
+
modelId: result.response.modelId,
|
|
112
|
+
usage: toLanguageModelUsage(result.usage),
|
|
113
|
+
providerMetadata: result.providerMetadata,
|
|
114
|
+
costContext: result.costContext,
|
|
115
|
+
object: result.object
|
|
116
|
+
});
|
|
117
|
+
return createMastraOutput({
|
|
118
|
+
messages,
|
|
119
|
+
runId,
|
|
120
|
+
modelId: result.response.modelId,
|
|
121
|
+
provider,
|
|
122
|
+
stream,
|
|
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 = observability.getOrCreateSpan({
|
|
146
|
+
type: observability.SpanType.AGENT_RUN,
|
|
147
|
+
name: `agent run: '${agentId}'`,
|
|
148
|
+
entityType: observability.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: observability.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: observability.SpanType.MCP_TOOL_CALL,
|
|
201
|
+
name: `mcp_tool: '${toolName}' on '${mcp.serverName}'`,
|
|
202
|
+
input,
|
|
203
|
+
entityType: observability.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: observability.SpanType.TOOL_CALL,
|
|
219
|
+
name: `tool: '${toolName}'`,
|
|
220
|
+
input,
|
|
221
|
+
entityType: observability.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) => observability.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
|
+
};
|
|
364
|
+
}
|
|
365
|
+
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
|
+
};
|
|
374
|
+
}
|
|
375
|
+
function getModelSpanTracker(modelSpan) {
|
|
376
|
+
if (!modelSpan || !("createTracker" in modelSpan)) {
|
|
377
|
+
return void 0;
|
|
378
|
+
}
|
|
379
|
+
return modelSpan.createTracker();
|
|
380
|
+
}
|
|
381
|
+
function wrapStreamForAgentSpan(stream, telemetry) {
|
|
382
|
+
let text = "";
|
|
383
|
+
return stream.pipeThrough(
|
|
384
|
+
new web.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
|
+
);
|
|
410
|
+
}
|
|
411
|
+
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
|
+
};
|
|
424
|
+
}
|
|
425
|
+
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: stream.ChunkFrom.AGENT,
|
|
443
|
+
payload: {}
|
|
444
|
+
});
|
|
445
|
+
controller.enqueue({
|
|
446
|
+
type: "step-start",
|
|
447
|
+
runId,
|
|
448
|
+
from: stream.ChunkFrom.AGENT,
|
|
449
|
+
payload: {
|
|
450
|
+
request: { body: prompt }
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
controller.enqueue({
|
|
454
|
+
type: "response-metadata",
|
|
455
|
+
runId,
|
|
456
|
+
from: stream.ChunkFrom.AGENT,
|
|
457
|
+
payload: {
|
|
458
|
+
...responseId ? { id: responseId } : {},
|
|
459
|
+
modelId,
|
|
460
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
controller.enqueue({
|
|
464
|
+
type: "text-start",
|
|
465
|
+
runId,
|
|
466
|
+
from: stream.ChunkFrom.AGENT,
|
|
467
|
+
payload: {
|
|
468
|
+
id: textId,
|
|
469
|
+
providerMetadata
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
function enqueueTextDelta(controller, runId, textId, text) {
|
|
474
|
+
controller.enqueue({
|
|
475
|
+
type: "text-delta",
|
|
476
|
+
runId,
|
|
477
|
+
from: stream.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
|
+
...responseId ? { 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: stream.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: stream.ChunkFrom.AGENT,
|
|
523
|
+
object
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
controller.enqueue({
|
|
527
|
+
type: "step-finish",
|
|
528
|
+
runId,
|
|
529
|
+
from: stream.ChunkFrom.AGENT,
|
|
530
|
+
payload: {
|
|
531
|
+
...responseId ? { 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: stream.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
|
+
});
|
|
570
|
+
}
|
|
571
|
+
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
|
+
reasoningTokens: usage.outputTokens.reasoning,
|
|
581
|
+
raw: usage
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
function createProviderMetadata(provider, metadata) {
|
|
585
|
+
return {
|
|
586
|
+
[provider]: toJsonRecord(metadata)
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
function toJsonRecord(record) {
|
|
590
|
+
return Object.fromEntries(
|
|
591
|
+
Object.entries(record).filter((entry) => entry[1] !== void 0).map(([key, value]) => [key, toJsonValue(value)])
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
function toJsonValue(value) {
|
|
595
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
596
|
+
return value;
|
|
597
|
+
}
|
|
598
|
+
if (Array.isArray(value)) {
|
|
599
|
+
return value.filter((item) => item !== void 0).map(toJsonValue);
|
|
600
|
+
}
|
|
601
|
+
if (value instanceof Date) {
|
|
602
|
+
return value.toISOString();
|
|
603
|
+
}
|
|
604
|
+
if (typeof value === "object") {
|
|
605
|
+
return toJsonRecord(value);
|
|
606
|
+
}
|
|
607
|
+
return String(value);
|
|
608
|
+
}
|
|
609
|
+
function promptToText(prompt) {
|
|
610
|
+
if (typeof prompt === "string") {
|
|
611
|
+
return prompt;
|
|
612
|
+
}
|
|
613
|
+
if (Array.isArray(prompt)) {
|
|
614
|
+
return prompt.map(promptToText).filter(Boolean).join("\n");
|
|
615
|
+
}
|
|
616
|
+
if (!prompt || typeof prompt !== "object") {
|
|
617
|
+
return "";
|
|
618
|
+
}
|
|
619
|
+
const record = prompt;
|
|
620
|
+
if (typeof record.text === "string") {
|
|
621
|
+
return record.text;
|
|
622
|
+
}
|
|
623
|
+
if (typeof record.content === "string") {
|
|
624
|
+
return record.content;
|
|
625
|
+
}
|
|
626
|
+
if (record.content) {
|
|
627
|
+
return promptToText(record.content);
|
|
628
|
+
}
|
|
629
|
+
return "";
|
|
630
|
+
}
|
|
631
|
+
function getStructuredOutputSchema(structuredOutput) {
|
|
632
|
+
if (!structuredOutput?.schema) {
|
|
633
|
+
return void 0;
|
|
634
|
+
}
|
|
635
|
+
return {
|
|
636
|
+
type: "json_schema",
|
|
637
|
+
name: "mastra_output",
|
|
638
|
+
strict: false,
|
|
639
|
+
schema: schema.standardSchemaToJSONSchema(schema.toStandardSchema(structuredOutput.schema))
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
async function getStructuredOutputFromValue(value, structuredOutput) {
|
|
643
|
+
if (!structuredOutput?.schema) {
|
|
644
|
+
return void 0;
|
|
645
|
+
}
|
|
646
|
+
let parsed;
|
|
647
|
+
if (typeof value === "string") {
|
|
648
|
+
try {
|
|
649
|
+
parsed = JSON.parse(value);
|
|
650
|
+
} catch (error) {
|
|
651
|
+
return handleStructuredOutputError(
|
|
652
|
+
new Error("Structured output must be valid JSON.", { cause: error }),
|
|
653
|
+
structuredOutput
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
} else {
|
|
657
|
+
parsed = value;
|
|
658
|
+
}
|
|
659
|
+
const schema$1 = schema.toStandardSchema(structuredOutput.schema);
|
|
660
|
+
const result = await schema$1["~standard"].validate(parsed);
|
|
661
|
+
if (!result.issues) {
|
|
662
|
+
return result.value;
|
|
663
|
+
}
|
|
664
|
+
const message = result.issues.map((issue) => `- ${issue.path?.join(".") || "root"}: ${issue.message}`).join("\n");
|
|
665
|
+
return handleStructuredOutputError(new Error(`Structured output validation failed:
|
|
666
|
+
${message}`), structuredOutput);
|
|
667
|
+
}
|
|
668
|
+
function handleStructuredOutputError(error, structuredOutput) {
|
|
669
|
+
if (structuredOutput.errorStrategy === "fallback") {
|
|
670
|
+
return structuredOutput.fallbackValue;
|
|
671
|
+
}
|
|
672
|
+
if (structuredOutput.errorStrategy === "warn") {
|
|
673
|
+
structuredOutput.logger?.warn(error.message);
|
|
674
|
+
return void 0;
|
|
675
|
+
}
|
|
676
|
+
throw error;
|
|
677
|
+
}
|
|
678
|
+
function sumDefined(...values) {
|
|
679
|
+
const defined = values.filter((value) => typeof value === "number");
|
|
680
|
+
if (defined.length === 0) {
|
|
681
|
+
return void 0;
|
|
682
|
+
}
|
|
683
|
+
return defined.reduce((sum, value) => sum + value, 0);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// src/index.ts
|
|
687
|
+
var PROVIDER = "@openai/agents";
|
|
688
|
+
var MODEL_ID = "openai-agents-sdk";
|
|
689
|
+
var OpenAISDKAgent = class extends agent.Agent {
|
|
690
|
+
options;
|
|
691
|
+
#mastra;
|
|
692
|
+
#createdAgent;
|
|
693
|
+
constructor(options) {
|
|
694
|
+
super({
|
|
695
|
+
id: options.id,
|
|
696
|
+
name: options.name ?? options.id,
|
|
697
|
+
description: options.description,
|
|
698
|
+
instructions: "",
|
|
699
|
+
model: createNoopModel({
|
|
700
|
+
modelId: getModelId(options),
|
|
701
|
+
provider: PROVIDER
|
|
702
|
+
})
|
|
703
|
+
});
|
|
704
|
+
this.options = options;
|
|
705
|
+
}
|
|
706
|
+
__registerMastra(mastra) {
|
|
707
|
+
super.__registerMastra(mastra);
|
|
708
|
+
this.#mastra = mastra;
|
|
709
|
+
}
|
|
710
|
+
supportsMemory() {
|
|
711
|
+
return false;
|
|
712
|
+
}
|
|
713
|
+
async generate(messages, options) {
|
|
714
|
+
const prompt = promptToText(messages);
|
|
715
|
+
const runId = options?.runId ?? crypto.randomUUID();
|
|
716
|
+
const sdkAgent = getRunOpenAIAgent(this.resolveOpenAIAgent(), options);
|
|
717
|
+
const modelId = getModelId(this.options, sdkAgent);
|
|
718
|
+
const requestContext$1 = options?.requestContext ?? new requestContext.RequestContext();
|
|
719
|
+
const instructions = options?.instructions ? promptToText(options.instructions) : void 0;
|
|
720
|
+
const telemetry = createSDKAgentTelemetry({
|
|
721
|
+
agentId: this.id,
|
|
722
|
+
agentName: this.name,
|
|
723
|
+
provider: PROVIDER,
|
|
724
|
+
modelId,
|
|
725
|
+
messages,
|
|
726
|
+
prompt,
|
|
727
|
+
runId,
|
|
728
|
+
streaming: false,
|
|
729
|
+
method: "generate",
|
|
730
|
+
requestContext: requestContext$1,
|
|
731
|
+
instructions,
|
|
732
|
+
maxSteps: options?.maxSteps,
|
|
733
|
+
tracingOptions: options?.tracingOptions,
|
|
734
|
+
tracingContext: options?.tracingContext,
|
|
735
|
+
onFinish: options?.onFinish,
|
|
736
|
+
onStepFinish: options?.onStepFinish,
|
|
737
|
+
mastra: this.#mastra
|
|
738
|
+
});
|
|
739
|
+
let result;
|
|
740
|
+
try {
|
|
741
|
+
result = await telemetry.execute(() => runOpenAIGenerate(prompt, sdkAgent, runId, telemetry, options));
|
|
742
|
+
telemetry.endGenerate(result);
|
|
743
|
+
} catch (error) {
|
|
744
|
+
telemetry.fail(error);
|
|
745
|
+
throw error;
|
|
746
|
+
}
|
|
747
|
+
return toFullOutput({
|
|
748
|
+
messages,
|
|
749
|
+
runId,
|
|
750
|
+
provider: PROVIDER,
|
|
751
|
+
result,
|
|
752
|
+
options: { ...telemetry.outputOptions(), structuredOutput: getStructuredOutputOption(options) }
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
async stream(messages, options) {
|
|
756
|
+
const prompt = promptToText(messages);
|
|
757
|
+
const runId = options?.runId ?? crypto.randomUUID();
|
|
758
|
+
const sdkAgent = getRunOpenAIAgent(this.resolveOpenAIAgent(), options);
|
|
759
|
+
const modelId = getModelId(this.options, sdkAgent);
|
|
760
|
+
const requestContext$1 = options?.requestContext ?? new requestContext.RequestContext();
|
|
761
|
+
const instructions = options?.instructions ? promptToText(options.instructions) : void 0;
|
|
762
|
+
const telemetry = createSDKAgentTelemetry({
|
|
763
|
+
agentId: this.id,
|
|
764
|
+
agentName: this.name,
|
|
765
|
+
provider: PROVIDER,
|
|
766
|
+
modelId,
|
|
767
|
+
messages,
|
|
768
|
+
prompt,
|
|
769
|
+
runId,
|
|
770
|
+
streaming: true,
|
|
771
|
+
method: "stream",
|
|
772
|
+
requestContext: requestContext$1,
|
|
773
|
+
instructions,
|
|
774
|
+
maxSteps: options?.maxSteps,
|
|
775
|
+
tracingOptions: options?.tracingOptions,
|
|
776
|
+
tracingContext: options?.tracingContext,
|
|
777
|
+
onFinish: options?.onFinish,
|
|
778
|
+
onStepFinish: options?.onStepFinish,
|
|
779
|
+
mastra: this.#mastra
|
|
780
|
+
});
|
|
781
|
+
return createMastraOutput({
|
|
782
|
+
messages,
|
|
783
|
+
runId,
|
|
784
|
+
modelId,
|
|
785
|
+
provider: PROVIDER,
|
|
786
|
+
stream: telemetry.wrapStream(runOpenAIAsMastraStream(prompt, sdkAgent, runId, modelId, telemetry, options)),
|
|
787
|
+
options: { ...telemetry.outputOptions(), structuredOutput: getStructuredOutputOption(options) }
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
async resumeGenerate(resumeData, options) {
|
|
791
|
+
const data = validateOpenAIResumeData(resumeData);
|
|
792
|
+
return this.generate(data.message, createOpenAIResumeRunOptions(data, options));
|
|
793
|
+
}
|
|
794
|
+
async resumeStream(resumeData, options) {
|
|
795
|
+
const data = validateOpenAIResumeData(resumeData);
|
|
796
|
+
return this.stream(data.message, createOpenAIResumeRunOptions(data, options));
|
|
797
|
+
}
|
|
798
|
+
resolveOpenAIAgent() {
|
|
799
|
+
this.#createdAgent ??= this.options.agent ?? new agents.Agent(toOpenAIAgentOptions(this.options));
|
|
800
|
+
return this.#createdAgent;
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
function getStructuredOutputOption(options) {
|
|
804
|
+
return options?.structuredOutput;
|
|
805
|
+
}
|
|
806
|
+
function validateOpenAIResumeData(resumeData) {
|
|
807
|
+
const record = toRecord(resumeData);
|
|
808
|
+
if (!record || !("message" in record)) {
|
|
809
|
+
throw new Error("OpenAISDKAgent resumeData must include a message.");
|
|
810
|
+
}
|
|
811
|
+
if (typeof resumeData.previousResponseId === "string" || typeof resumeData.conversationId === "string" || resumeData.session !== void 0) {
|
|
812
|
+
return resumeData;
|
|
813
|
+
}
|
|
814
|
+
throw new Error("OpenAISDKAgent resumeData must include previousResponseId, conversationId, or session.");
|
|
815
|
+
}
|
|
816
|
+
function createOpenAIResumeRunOptions(resumeData, options) {
|
|
817
|
+
return {
|
|
818
|
+
...options,
|
|
819
|
+
previousResponseId: resumeData.previousResponseId ?? options?.previousResponseId,
|
|
820
|
+
conversationId: resumeData.conversationId ?? options?.conversationId,
|
|
821
|
+
session: resumeData.session ?? options?.session
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
async function runOpenAIGenerate(prompt, agent, runId, telemetry, options) {
|
|
825
|
+
const result = await agents.run(agent, prompt, createOpenAIRunOptions(options, false));
|
|
826
|
+
recordOpenAIToolTelemetry(result.newItems, telemetry);
|
|
827
|
+
const text = getTextFromFinalOutput(result.finalOutput);
|
|
828
|
+
const responseId = result.lastResponseId;
|
|
829
|
+
const modelId = getModelId(void 0, result.lastAgent ?? agent, result.rawResponses.at(-1));
|
|
830
|
+
const usage = createOpenAIUsageTotals(result.state.usage);
|
|
831
|
+
const providerMetadata = getOpenAIProviderMetadata({
|
|
832
|
+
modelId,
|
|
833
|
+
responseId,
|
|
834
|
+
lastResponseId: result.lastResponseId,
|
|
835
|
+
rawResponseCount: result.rawResponses.length,
|
|
836
|
+
itemCount: result.newItems.length,
|
|
837
|
+
usage
|
|
838
|
+
});
|
|
839
|
+
return {
|
|
840
|
+
content: [{ type: "text", text }],
|
|
841
|
+
finishReason: { unified: "stop", raw: "stop" },
|
|
842
|
+
usage: toV3Usage(usage),
|
|
843
|
+
response: {
|
|
844
|
+
id: responseId,
|
|
845
|
+
modelId,
|
|
846
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
847
|
+
},
|
|
848
|
+
providerMetadata,
|
|
849
|
+
object: await getStructuredOutputFromValue(result.finalOutput, options?.structuredOutput)
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
function runOpenAIAsMastraStream(prompt, agent, runId, requestedModelId, telemetry, options) {
|
|
853
|
+
return new web.ReadableStream({
|
|
854
|
+
start: async (controller) => {
|
|
855
|
+
const textId = crypto.randomUUID();
|
|
856
|
+
let text = "";
|
|
857
|
+
let responseId;
|
|
858
|
+
let modelId = requestedModelId;
|
|
859
|
+
try {
|
|
860
|
+
const result = await agents.run(agent, prompt, createOpenAIRunOptions(options, true));
|
|
861
|
+
enqueueStartChunks(controller, {
|
|
862
|
+
runId,
|
|
863
|
+
prompt,
|
|
864
|
+
textId,
|
|
865
|
+
responseId,
|
|
866
|
+
modelId
|
|
867
|
+
});
|
|
868
|
+
for await (const event of result) {
|
|
869
|
+
const delta = getTextDelta(event);
|
|
870
|
+
if (delta) {
|
|
871
|
+
text += delta;
|
|
872
|
+
enqueueTextDelta(controller, runId, textId, delta);
|
|
873
|
+
}
|
|
874
|
+
recordOpenAIStreamToolTelemetry(event, telemetry);
|
|
875
|
+
}
|
|
876
|
+
await result.completed;
|
|
877
|
+
responseId = result.lastResponseId ?? responseId;
|
|
878
|
+
modelId = getModelId(void 0, result.lastAgent ?? agent, result.rawResponses.at(-1));
|
|
879
|
+
if (!text) {
|
|
880
|
+
text = getTextFromFinalOutput(result.finalOutput);
|
|
881
|
+
if (text) {
|
|
882
|
+
enqueueTextDelta(controller, runId, textId, text);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
const usage = createOpenAIUsageTotals(result.state.usage);
|
|
886
|
+
const providerMetadata = getOpenAIProviderMetadata({
|
|
887
|
+
modelId,
|
|
888
|
+
responseId,
|
|
889
|
+
lastResponseId: result.lastResponseId,
|
|
890
|
+
rawResponseCount: result.rawResponses.length,
|
|
891
|
+
itemCount: result.newItems.length,
|
|
892
|
+
usage
|
|
893
|
+
});
|
|
894
|
+
enqueueFinishChunks(controller, {
|
|
895
|
+
runId,
|
|
896
|
+
prompt,
|
|
897
|
+
textId,
|
|
898
|
+
text,
|
|
899
|
+
responseId,
|
|
900
|
+
modelId,
|
|
901
|
+
usage: toLanguageModelUsage(toV3Usage(usage)),
|
|
902
|
+
providerMetadata,
|
|
903
|
+
object: await getStructuredOutputFromValue(result.finalOutput, options?.structuredOutput)
|
|
904
|
+
});
|
|
905
|
+
controller.close();
|
|
906
|
+
} catch (error) {
|
|
907
|
+
controller.enqueue({
|
|
908
|
+
type: "error",
|
|
909
|
+
runId,
|
|
910
|
+
from: stream.ChunkFrom.AGENT,
|
|
911
|
+
payload: { error }
|
|
912
|
+
});
|
|
913
|
+
controller.close();
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
function toOpenAIAgentOptions(options) {
|
|
919
|
+
return {
|
|
920
|
+
name: options.name ?? options.id,
|
|
921
|
+
...options.sdkOptions
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
function getRunOpenAIAgent(agent, options) {
|
|
925
|
+
const outputType = getStructuredOutputSchema(options?.structuredOutput);
|
|
926
|
+
if (!outputType) {
|
|
927
|
+
return agent;
|
|
928
|
+
}
|
|
929
|
+
return agent.clone({ outputType });
|
|
930
|
+
}
|
|
931
|
+
function createOpenAIRunOptions(options, stream) {
|
|
932
|
+
const runOptions = { stream };
|
|
933
|
+
addDefined(runOptions, "maxTurns", options?.maxSteps);
|
|
934
|
+
addDefined(runOptions, "signal", options?.abortSignal ?? options?.signal);
|
|
935
|
+
addDefined(runOptions, "conversationId", options?.conversationId);
|
|
936
|
+
addDefined(runOptions, "previousResponseId", options?.previousResponseId);
|
|
937
|
+
addDefined(runOptions, "session", options?.session);
|
|
938
|
+
return runOptions;
|
|
939
|
+
}
|
|
940
|
+
function addDefined(target, key, value) {
|
|
941
|
+
if (value !== void 0) {
|
|
942
|
+
target[key] = value;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
function getModelId(options, agent, rawResponse) {
|
|
946
|
+
return getModelNameFromUnknown(rawResponse) ?? getModelNameFromUnknown(agent?.model) ?? getModelNameFromUnknown(options?.sdkOptions?.model) ?? MODEL_ID;
|
|
947
|
+
}
|
|
948
|
+
function getModelNameFromUnknown(value) {
|
|
949
|
+
if (typeof value === "string") {
|
|
950
|
+
return value;
|
|
951
|
+
}
|
|
952
|
+
const record = toRecord(value);
|
|
953
|
+
return getString(record, "model") ?? getString(record, "modelId") ?? getString(record, "modelName") ?? getString(toRecord(record?.providerData), "model");
|
|
954
|
+
}
|
|
955
|
+
function getTextFromFinalOutput(output) {
|
|
956
|
+
if (typeof output === "string") {
|
|
957
|
+
return output;
|
|
958
|
+
}
|
|
959
|
+
if (output === void 0 || output === null) {
|
|
960
|
+
return "";
|
|
961
|
+
}
|
|
962
|
+
return JSON.stringify(output);
|
|
963
|
+
}
|
|
964
|
+
function createOpenAIUsageTotals(usage) {
|
|
965
|
+
const record = toRecord(usage);
|
|
966
|
+
if (!record) {
|
|
967
|
+
return {};
|
|
968
|
+
}
|
|
969
|
+
const inputDetails = getDetailRecords(record.inputTokensDetails);
|
|
970
|
+
const outputDetails = getDetailRecords(record.outputTokensDetails);
|
|
971
|
+
const requestUsageEntries = Array.isArray(record.requestUsageEntries) ? record.requestUsageEntries : void 0;
|
|
972
|
+
return {
|
|
973
|
+
inputTokens: getNumber(record.inputTokens),
|
|
974
|
+
outputTokens: getNumber(record.outputTokens),
|
|
975
|
+
cacheReadInputTokens: sumDetails(inputDetails, "cachedTokens", "cached_tokens", "cacheReadInputTokens"),
|
|
976
|
+
cacheCreationInputTokens: sumDetails(inputDetails, "cacheCreationInputTokens", "cache_creation_input_tokens"),
|
|
977
|
+
reasoningTokens: sumDetails(outputDetails, "reasoningTokens", "reasoning_tokens"),
|
|
978
|
+
requests: getNumber(record.requests),
|
|
979
|
+
requestUsageEntries
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
function getDetailRecords(value) {
|
|
983
|
+
if (Array.isArray(value)) {
|
|
984
|
+
return value.filter(isRecord);
|
|
985
|
+
}
|
|
986
|
+
const record = toRecord(value);
|
|
987
|
+
return record ? [record] : [];
|
|
988
|
+
}
|
|
989
|
+
function sumDetails(records, ...keys) {
|
|
990
|
+
let total = 0;
|
|
991
|
+
let found = false;
|
|
992
|
+
for (const record of records) {
|
|
993
|
+
for (const key of keys) {
|
|
994
|
+
const value = getNumber(record[key]);
|
|
995
|
+
if (value !== void 0) {
|
|
996
|
+
total += value;
|
|
997
|
+
found = true;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
return found ? total : void 0;
|
|
1002
|
+
}
|
|
1003
|
+
function toV3Usage(usage) {
|
|
1004
|
+
const totalInputTokens = usage.inputTokens;
|
|
1005
|
+
const cacheRead = usage.cacheReadInputTokens;
|
|
1006
|
+
const cacheWrite = usage.cacheCreationInputTokens;
|
|
1007
|
+
const noCache = totalInputTokens === void 0 ? void 0 : Math.max(totalInputTokens - (sumDefined(cacheRead, cacheWrite) ?? 0), 0);
|
|
1008
|
+
const outputTokens = usage.outputTokens;
|
|
1009
|
+
const reasoningTokens = usage.reasoningTokens;
|
|
1010
|
+
return {
|
|
1011
|
+
inputTokens: {
|
|
1012
|
+
total: totalInputTokens,
|
|
1013
|
+
noCache,
|
|
1014
|
+
cacheRead,
|
|
1015
|
+
cacheWrite
|
|
1016
|
+
},
|
|
1017
|
+
outputTokens: {
|
|
1018
|
+
total: outputTokens,
|
|
1019
|
+
text: outputTokens,
|
|
1020
|
+
reasoning: reasoningTokens
|
|
1021
|
+
}
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
function getOpenAIProviderMetadata({
|
|
1025
|
+
modelId,
|
|
1026
|
+
responseId,
|
|
1027
|
+
lastResponseId,
|
|
1028
|
+
rawResponseCount,
|
|
1029
|
+
itemCount,
|
|
1030
|
+
usage
|
|
1031
|
+
}) {
|
|
1032
|
+
return createProviderMetadata("openai", {
|
|
1033
|
+
model: modelId,
|
|
1034
|
+
responseId,
|
|
1035
|
+
lastResponseId,
|
|
1036
|
+
rawResponseCount,
|
|
1037
|
+
itemCount,
|
|
1038
|
+
usage
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
function recordOpenAIToolTelemetry(items, telemetry) {
|
|
1042
|
+
for (const item of items) {
|
|
1043
|
+
if (item.type === "tool_call_item") {
|
|
1044
|
+
const toolCall = getOpenAIToolCall(item.rawItem);
|
|
1045
|
+
if (toolCall) {
|
|
1046
|
+
telemetry.startToolCall(toolCall);
|
|
1047
|
+
}
|
|
1048
|
+
continue;
|
|
1049
|
+
}
|
|
1050
|
+
if (item.type === "tool_call_output_item") {
|
|
1051
|
+
const toolOutput = getOpenAIToolOutput(item.rawItem, item.output);
|
|
1052
|
+
if (toolOutput) {
|
|
1053
|
+
telemetry.endToolCall(toolOutput);
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
function recordOpenAIStreamToolTelemetry(event, telemetry) {
|
|
1059
|
+
if (event.type !== "run_item_stream_event") {
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
if (event.name === "tool_called") {
|
|
1063
|
+
const toolCall = getOpenAIToolCall(event.item.rawItem);
|
|
1064
|
+
if (toolCall) {
|
|
1065
|
+
telemetry.startToolCall(toolCall);
|
|
1066
|
+
}
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
1069
|
+
if (event.name === "tool_output") {
|
|
1070
|
+
const toolOutput = getOpenAIToolOutput(event.item.rawItem, getObjectValue(event.item, "output"));
|
|
1071
|
+
if (toolOutput) {
|
|
1072
|
+
telemetry.endToolCall(toolOutput);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
function getOpenAIToolCall(rawItem) {
|
|
1077
|
+
const record = toRecord(rawItem);
|
|
1078
|
+
if (!record) {
|
|
1079
|
+
return void 0;
|
|
1080
|
+
}
|
|
1081
|
+
if (record.type === "function_call") {
|
|
1082
|
+
const toolCallId = getString(record, "callId") ?? getString(record, "id");
|
|
1083
|
+
const toolName = getNamespacedToolName(record);
|
|
1084
|
+
if (!toolCallId || !toolName) {
|
|
1085
|
+
return void 0;
|
|
1086
|
+
}
|
|
1087
|
+
return {
|
|
1088
|
+
toolCallId,
|
|
1089
|
+
toolName,
|
|
1090
|
+
input: parseJsonString(record.arguments)
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
if (record.type === "hosted_tool_call") {
|
|
1094
|
+
const toolCallId = getString(record, "id") ?? getString(record, "name");
|
|
1095
|
+
const toolName = getString(record, "name");
|
|
1096
|
+
if (!toolCallId || !toolName) {
|
|
1097
|
+
return void 0;
|
|
1098
|
+
}
|
|
1099
|
+
return {
|
|
1100
|
+
toolCallId,
|
|
1101
|
+
toolName,
|
|
1102
|
+
input: parseJsonString(record.arguments)
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
if (record.type === "shell_call" || record.type === "apply_patch_call") {
|
|
1106
|
+
const toolCallId = getString(record, "callId");
|
|
1107
|
+
if (!toolCallId) {
|
|
1108
|
+
return void 0;
|
|
1109
|
+
}
|
|
1110
|
+
return {
|
|
1111
|
+
toolCallId,
|
|
1112
|
+
toolName: String(record.type),
|
|
1113
|
+
input: record.action ?? record.operation
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
return void 0;
|
|
1117
|
+
}
|
|
1118
|
+
function getOpenAIToolOutput(rawItem, fallbackOutput) {
|
|
1119
|
+
const record = toRecord(rawItem);
|
|
1120
|
+
if (!record) {
|
|
1121
|
+
return void 0;
|
|
1122
|
+
}
|
|
1123
|
+
const toolCallId = getString(record, "callId") ?? getString(record, "id");
|
|
1124
|
+
if (!toolCallId) {
|
|
1125
|
+
return void 0;
|
|
1126
|
+
}
|
|
1127
|
+
return {
|
|
1128
|
+
toolCallId,
|
|
1129
|
+
output: record.output ?? fallbackOutput,
|
|
1130
|
+
isError: record.status === "failed" || record.status === "incomplete"
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
function getNamespacedToolName(record) {
|
|
1134
|
+
const name = getString(record, "name");
|
|
1135
|
+
const namespace = getString(record, "namespace");
|
|
1136
|
+
if (!name) {
|
|
1137
|
+
return void 0;
|
|
1138
|
+
}
|
|
1139
|
+
return namespace ? `${namespace}.${name}` : name;
|
|
1140
|
+
}
|
|
1141
|
+
function getTextDelta(event) {
|
|
1142
|
+
if (event.type !== "raw_model_stream_event") {
|
|
1143
|
+
return "";
|
|
1144
|
+
}
|
|
1145
|
+
const data = toRecord(event.data);
|
|
1146
|
+
return data?.type === "output_text_delta" && typeof data.delta === "string" ? data.delta : "";
|
|
1147
|
+
}
|
|
1148
|
+
function parseJsonString(value) {
|
|
1149
|
+
if (typeof value !== "string") {
|
|
1150
|
+
return value;
|
|
1151
|
+
}
|
|
1152
|
+
try {
|
|
1153
|
+
return JSON.parse(value);
|
|
1154
|
+
} catch {
|
|
1155
|
+
return value;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
function getNumber(value) {
|
|
1159
|
+
return typeof value === "number" ? value : void 0;
|
|
1160
|
+
}
|
|
1161
|
+
function getString(record, key) {
|
|
1162
|
+
const value = record?.[key];
|
|
1163
|
+
return typeof value === "string" ? value : void 0;
|
|
1164
|
+
}
|
|
1165
|
+
function getObjectValue(value, key) {
|
|
1166
|
+
return toRecord(value)?.[key];
|
|
1167
|
+
}
|
|
1168
|
+
function toRecord(value) {
|
|
1169
|
+
return isRecord(value) ? value : void 0;
|
|
1170
|
+
}
|
|
1171
|
+
function isRecord(value) {
|
|
1172
|
+
return value !== null && typeof value === "object";
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
exports.OpenAISDKAgent = OpenAISDKAgent;
|
|
1176
|
+
//# sourceMappingURL=index.cjs.map
|
|
1177
|
+
//# sourceMappingURL=index.cjs.map
|