braintrust 3.4.0 → 3.5.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.
Files changed (50) hide show
  1. package/dev/dist/index.d.mts +45 -5
  2. package/dev/dist/index.d.ts +45 -5
  3. package/dev/dist/index.js +992 -245
  4. package/dev/dist/index.mjs +914 -167
  5. package/dist/auto-instrumentations/bundler/esbuild.cjs +208 -10
  6. package/dist/auto-instrumentations/bundler/esbuild.d.mts +2 -2
  7. package/dist/auto-instrumentations/bundler/esbuild.d.ts +2 -2
  8. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  9. package/dist/auto-instrumentations/bundler/rollup.cjs +208 -10
  10. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  11. package/dist/auto-instrumentations/bundler/vite.cjs +208 -10
  12. package/dist/auto-instrumentations/bundler/vite.d.mts +2 -2
  13. package/dist/auto-instrumentations/bundler/vite.d.ts +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  15. package/dist/auto-instrumentations/bundler/webpack.cjs +208 -10
  16. package/dist/auto-instrumentations/bundler/webpack.d.mts +2 -2
  17. package/dist/auto-instrumentations/bundler/webpack.d.ts +2 -2
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
  19. package/dist/auto-instrumentations/{chunk-LVWWLUMN.mjs → chunk-DQTPSXJB.mjs} +208 -10
  20. package/dist/auto-instrumentations/chunk-EVUKFMHG.mjs +41 -0
  21. package/dist/auto-instrumentations/{chunk-D5ZPIUEL.mjs → chunk-F3TJZ3Z2.mjs} +1 -1
  22. package/dist/auto-instrumentations/chunk-VLEJ5AEK.mjs +41 -0
  23. package/dist/auto-instrumentations/hook.mjs +238 -18
  24. package/dist/auto-instrumentations/index.cjs +208 -10
  25. package/dist/auto-instrumentations/index.mjs +1 -1
  26. package/dist/auto-instrumentations/loader/cjs-patch.cjs +32 -10
  27. package/dist/auto-instrumentations/loader/cjs-patch.mjs +10 -5
  28. package/dist/auto-instrumentations/loader/esm-hook.mjs +4 -4
  29. package/dist/auto-instrumentations/loader/get-package-version.cjs +28 -8
  30. package/dist/auto-instrumentations/loader/get-package-version.d.mts +2 -1
  31. package/dist/auto-instrumentations/loader/get-package-version.d.ts +2 -1
  32. package/dist/auto-instrumentations/loader/get-package-version.mjs +3 -1
  33. package/dist/browser.d.mts +342 -269
  34. package/dist/browser.d.ts +342 -269
  35. package/dist/browser.js +996 -241
  36. package/dist/browser.mjs +996 -241
  37. package/dist/cli.js +1029 -289
  38. package/dist/edge-light.js +1007 -220
  39. package/dist/edge-light.mjs +1007 -220
  40. package/dist/index.d.mts +342 -269
  41. package/dist/index.d.ts +342 -269
  42. package/dist/index.js +1182 -427
  43. package/dist/index.mjs +996 -241
  44. package/dist/instrumentation/index.js +781 -107
  45. package/dist/instrumentation/index.mjs +781 -107
  46. package/dist/workerd.js +1007 -220
  47. package/dist/workerd.mjs +1007 -220
  48. package/package.json +22 -6
  49. package/dist/auto-instrumentations/chunk-XDBPUTVE.mjs +0 -22
  50. package/dist/auto-instrumentations/chunk-ZEC7BCL4.mjs +0 -22
@@ -52,8 +52,54 @@ var DefaultAsyncLocalStorage = class {
52
52
  return void 0;
53
53
  }
54
54
  };
55
- var DefaultTracingChannel = class {
55
+ var DefaultChannel = class {
56
+ constructor(name) {
57
+ this.name = name;
58
+ }
56
59
  hasSubscribers = false;
60
+ subscribe(_subscription) {
61
+ }
62
+ unsubscribe(_subscription) {
63
+ return false;
64
+ }
65
+ bindStore(_store, _transform) {
66
+ }
67
+ unbindStore(_store) {
68
+ return false;
69
+ }
70
+ publish(_message) {
71
+ }
72
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
+ runStores(_message, fn, thisArg, ...args) {
74
+ return fn.apply(thisArg, args);
75
+ }
76
+ };
77
+ var DefaultTracingChannel = class {
78
+ start;
79
+ end;
80
+ asyncStart;
81
+ asyncEnd;
82
+ error;
83
+ constructor(nameOrChannels) {
84
+ if (typeof nameOrChannels === "string") {
85
+ this.start = new DefaultChannel(`tracing:${nameOrChannels}:start`);
86
+ this.end = new DefaultChannel(`tracing:${nameOrChannels}:end`);
87
+ this.asyncStart = new DefaultChannel(
88
+ `tracing:${nameOrChannels}:asyncStart`
89
+ );
90
+ this.asyncEnd = new DefaultChannel(`tracing:${nameOrChannels}:asyncEnd`);
91
+ this.error = new DefaultChannel(`tracing:${nameOrChannels}:error`);
92
+ return;
93
+ }
94
+ this.start = nameOrChannels.start ?? new DefaultChannel("tracing:start");
95
+ this.end = nameOrChannels.end ?? new DefaultChannel("tracing:end");
96
+ this.asyncStart = nameOrChannels.asyncStart ?? new DefaultChannel("tracing:asyncStart");
97
+ this.asyncEnd = nameOrChannels.asyncEnd ?? new DefaultChannel("tracing:asyncEnd");
98
+ this.error = nameOrChannels.error ?? new DefaultChannel("tracing:error");
99
+ }
100
+ get hasSubscribers() {
101
+ return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
102
+ }
57
103
  subscribe(_handlers) {
58
104
  }
59
105
  unsubscribe(_handlers) {
@@ -81,7 +127,7 @@ var iso = {
81
127
  getCallerLocation: () => void 0,
82
128
  newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
83
129
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
84
- newTracingChannel: (_nameOrChannels) => new DefaultTracingChannel(),
130
+ newTracingChannel: (nameOrChannels) => new DefaultTracingChannel(nameOrChannels),
85
131
  processOn: (_0, _1) => {
86
132
  },
87
133
  basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
@@ -2115,6 +2161,8 @@ var Experiment = import_v36.z.object({
2115
2161
  deleted_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2116
2162
  dataset_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2117
2163
  dataset_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2164
+ parameters_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2165
+ parameters_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2118
2166
  public: import_v36.z.boolean(),
2119
2167
  user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2120
2168
  metadata: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
@@ -2137,7 +2185,11 @@ var SpanType = import_v36.z.union([
2137
2185
  import_v36.z.null()
2138
2186
  ]);
2139
2187
  var SpanAttributes = import_v36.z.union([
2140
- import_v36.z.object({ name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]), type: SpanType }).partial().passthrough(),
2188
+ import_v36.z.object({
2189
+ name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
2190
+ type: SpanType,
2191
+ purpose: import_v36.z.union([import_v36.z.literal("scorer"), import_v36.z.null()])
2192
+ }).partial().passthrough(),
2141
2193
  import_v36.z.null()
2142
2194
  ]);
2143
2195
  var ExperimentEvent = import_v36.z.object({
@@ -2577,6 +2629,7 @@ var FunctionId = import_v36.z.union([
2577
2629
  version: import_v36.z.string()
2578
2630
  }),
2579
2631
  code: import_v36.z.string(),
2632
+ function_type: FunctionTypeEnum.and(import_v36.z.unknown()).optional(),
2580
2633
  name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
2581
2634
  }),
2582
2635
  import_v36.z.object({
@@ -2806,7 +2859,12 @@ var TopicAutomationConfig = import_v36.z.object({
2806
2859
  topic_map_functions: import_v36.z.array(TopicMapFunctionAutomation),
2807
2860
  scope: import_v36.z.union([SpanScope, TraceScope, GroupScope, import_v36.z.null()]).optional(),
2808
2861
  data_scope: TopicAutomationDataScope.optional(),
2809
- btql_filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
2862
+ btql_filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2863
+ backfill_time_range: import_v36.z.union([
2864
+ import_v36.z.string(),
2865
+ import_v36.z.object({ from: import_v36.z.string(), to: import_v36.z.string() }),
2866
+ import_v36.z.null()
2867
+ ]).optional()
2810
2868
  });
2811
2869
  var ProjectAutomation = import_v36.z.object({
2812
2870
  id: import_v36.z.string().uuid(),
@@ -4215,6 +4273,12 @@ var parametersRowSchema = import_v38.z.object({
4215
4273
  }),
4216
4274
  metadata: import_v38.z.union([import_v38.z.object({}).partial().passthrough(), import_v38.z.null()]).optional()
4217
4275
  });
4276
+ var InlineAttachmentReferenceSchema = import_v38.z.object({
4277
+ type: import_v38.z.literal("inline_attachment"),
4278
+ src: import_v38.z.string().min(1),
4279
+ content_type: import_v38.z.string().optional(),
4280
+ filename: import_v38.z.string().optional()
4281
+ });
4218
4282
  var LoginInvalidOrgError = class extends Error {
4219
4283
  constructor(message) {
4220
4284
  super(message);
@@ -8017,7 +8081,11 @@ function startSpanForEvent(config, event, channelName) {
8017
8081
  });
8018
8082
  const startTime = getCurrentUnixTimestamp();
8019
8083
  try {
8020
- const { input, metadata } = config.extractInput(event.arguments);
8084
+ const { input, metadata } = config.extractInput(
8085
+ event.arguments,
8086
+ event,
8087
+ span
8088
+ );
8021
8089
  span.log({
8022
8090
  input,
8023
8091
  metadata: mergeInputMetadata(metadata, spanInfoMetadata)
@@ -8181,6 +8249,16 @@ function traceStreamingChannel(channel2, config) {
8181
8249
  });
8182
8250
  return;
8183
8251
  }
8252
+ if (config.patchResult?.({
8253
+ channelName,
8254
+ endEvent: asyncEndEvent,
8255
+ result: asyncEndEvent.result,
8256
+ span,
8257
+ startTime
8258
+ })) {
8259
+ states.delete(event);
8260
+ return;
8261
+ }
8184
8262
  try {
8185
8263
  const output = config.extractOutput(
8186
8264
  asyncEndEvent.result,
@@ -8237,8 +8315,17 @@ function traceSyncStreamChannel(channel2, config) {
8237
8315
  return;
8238
8316
  }
8239
8317
  const { span, startTime } = spanData;
8240
- const resultEvent = event;
8241
- const stream = resultEvent.result;
8318
+ const endEvent = event;
8319
+ if (config.patchResult?.({
8320
+ channelName,
8321
+ endEvent,
8322
+ result: endEvent.result,
8323
+ span,
8324
+ startTime
8325
+ })) {
8326
+ return;
8327
+ }
8328
+ const stream = endEvent.result;
8242
8329
  if (!isSyncStreamLike(stream)) {
8243
8330
  span.end();
8244
8331
  states.delete(event);
@@ -9209,6 +9296,108 @@ function filterFrom(obj, fieldsToRemove) {
9209
9296
  return result;
9210
9297
  }
9211
9298
 
9299
+ // src/wrappers/ai-sdk/normalize-logged-output.ts
9300
+ var REMOVE_NORMALIZED_VALUE = Symbol("braintrust.ai-sdk.remove-normalized");
9301
+ function normalizeAISDKLoggedOutput(value) {
9302
+ const normalized = normalizeAISDKLoggedValue(value);
9303
+ return normalized === REMOVE_NORMALIZED_VALUE ? {} : normalized;
9304
+ }
9305
+ function normalizeAISDKLoggedValue(value, context = {}) {
9306
+ if (Array.isArray(value)) {
9307
+ return value.map((entry) => normalizeAISDKLoggedValue(entry, context)).filter((entry) => entry !== REMOVE_NORMALIZED_VALUE);
9308
+ }
9309
+ if (!value || typeof value !== "object") {
9310
+ return value;
9311
+ }
9312
+ const nextInProviderMetadata = context.inProviderMetadata || context.parentKey === "providerMetadata" || context.parentKey === "experimental_providerMetadata";
9313
+ const normalizedEntries = [];
9314
+ for (const [key, entry] of Object.entries(value)) {
9315
+ if (key === "cachedPromptTokens" && entry === 0) {
9316
+ continue;
9317
+ }
9318
+ if (context.parentKey === "request" && key === "body" && entry === "<omitted>") {
9319
+ continue;
9320
+ }
9321
+ const normalizedEntry = normalizeAISDKLoggedValue(entry, {
9322
+ inProviderMetadata: nextInProviderMetadata,
9323
+ parentKey: key
9324
+ });
9325
+ if (normalizedEntry === REMOVE_NORMALIZED_VALUE) {
9326
+ continue;
9327
+ }
9328
+ normalizedEntries.push([key, normalizedEntry]);
9329
+ }
9330
+ if (normalizedEntries.length === 0) {
9331
+ if (context.parentKey === "request" || nextInProviderMetadata) {
9332
+ return REMOVE_NORMALIZED_VALUE;
9333
+ }
9334
+ return {};
9335
+ }
9336
+ return Object.fromEntries(normalizedEntries);
9337
+ }
9338
+
9339
+ // src/zod/utils.ts
9340
+ var import_zod_to_json_schema = require("zod-to-json-schema");
9341
+ var z42 = __toESM(require("zod/v4"));
9342
+ function isZodV4(zodObject) {
9343
+ return typeof zodObject === "object" && zodObject !== null && "_zod" in zodObject && zodObject._zod !== void 0;
9344
+ }
9345
+ function zodToJsonSchema(schema) {
9346
+ if (isZodV4(schema)) {
9347
+ return z42.toJSONSchema(schema, {
9348
+ target: "draft-7"
9349
+ });
9350
+ }
9351
+ return (0, import_zod_to_json_schema.zodToJsonSchema)(schema);
9352
+ }
9353
+
9354
+ // src/wrappers/ai-sdk/tool-serialization.ts
9355
+ function isZodSchema(value) {
9356
+ return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
9357
+ }
9358
+ function serializeZodSchema(schema) {
9359
+ try {
9360
+ return zodToJsonSchema(schema);
9361
+ } catch {
9362
+ return {
9363
+ type: "object",
9364
+ description: "Zod schema (conversion failed)"
9365
+ };
9366
+ }
9367
+ }
9368
+ function serializeTool(tool) {
9369
+ if (!tool || typeof tool !== "object") {
9370
+ return tool;
9371
+ }
9372
+ const serialized = { ...tool };
9373
+ if (isZodSchema(serialized.inputSchema)) {
9374
+ serialized.inputSchema = serializeZodSchema(serialized.inputSchema);
9375
+ }
9376
+ if (isZodSchema(serialized.parameters)) {
9377
+ serialized.parameters = serializeZodSchema(serialized.parameters);
9378
+ }
9379
+ if ("execute" in serialized) {
9380
+ delete serialized.execute;
9381
+ }
9382
+ if ("render" in serialized) {
9383
+ delete serialized.render;
9384
+ }
9385
+ return serialized;
9386
+ }
9387
+ function serializeAISDKToolsForLogging(tools) {
9388
+ if (!tools || typeof tools !== "object") {
9389
+ return tools;
9390
+ }
9391
+ if (Array.isArray(tools)) {
9392
+ return tools.map(serializeTool);
9393
+ }
9394
+ const serialized = {};
9395
+ for (const [key, tool] of Object.entries(tools)) {
9396
+ serialized[key] = serializeTool(tool);
9397
+ }
9398
+ return serialized;
9399
+ }
9400
+
9212
9401
  // src/instrumentation/plugins/ai-sdk-channels.ts
9213
9402
  var aiSDKChannels = defineChannels("ai", {
9214
9403
  generateText: channel({
@@ -9219,6 +9408,10 @@ var aiSDKChannels = defineChannels("ai", {
9219
9408
  channelName: "streamText",
9220
9409
  kind: "async"
9221
9410
  }),
9411
+ streamTextSync: channel({
9412
+ channelName: "streamText.sync",
9413
+ kind: "sync-stream"
9414
+ }),
9222
9415
  generateObject: channel({
9223
9416
  channelName: "generateObject",
9224
9417
  kind: "async"
@@ -9227,6 +9420,10 @@ var aiSDKChannels = defineChannels("ai", {
9227
9420
  channelName: "streamObject",
9228
9421
  kind: "async"
9229
9422
  }),
9423
+ streamObjectSync: channel({
9424
+ channelName: "streamObject.sync",
9425
+ kind: "sync-stream"
9426
+ }),
9230
9427
  agentGenerate: channel({
9231
9428
  channelName: "Agent.generate",
9232
9429
  kind: "async"
@@ -9234,6 +9431,14 @@ var aiSDKChannels = defineChannels("ai", {
9234
9431
  agentStream: channel({
9235
9432
  channelName: "Agent.stream",
9236
9433
  kind: "async"
9434
+ }),
9435
+ toolLoopAgentGenerate: channel({
9436
+ channelName: "ToolLoopAgent.generate",
9437
+ kind: "async"
9438
+ }),
9439
+ toolLoopAgentStream: channel({
9440
+ channelName: "ToolLoopAgent.stream",
9441
+ kind: "async"
9237
9442
  })
9238
9443
  });
9239
9444
 
@@ -9252,6 +9457,8 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
9252
9457
  "steps[].response.body",
9253
9458
  "steps[].response.headers"
9254
9459
  ];
9460
+ var AUTO_PATCHED_MODEL = Symbol.for("braintrust.ai-sdk.auto-patched-model");
9461
+ var AUTO_PATCHED_TOOL = Symbol.for("braintrust.ai-sdk.auto-patched-tool");
9255
9462
  var AISDKPlugin = class extends BasePlugin {
9256
9463
  config;
9257
9464
  constructor(config = {}) {
@@ -9270,22 +9477,12 @@ var AISDKPlugin = class extends BasePlugin {
9270
9477
  traceStreamingChannel(aiSDKChannels.generateText, {
9271
9478
  name: "generateText",
9272
9479
  type: "llm" /* LLM */,
9273
- extractInput: ([params]) => {
9274
- return {
9275
- input: processAISDKInput(params),
9276
- metadata: extractMetadataFromParams(params)
9277
- };
9278
- },
9279
- extractOutput: (result) => {
9480
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
9481
+ extractOutput: (result, endEvent) => {
9482
+ finalizeAISDKChildTracing(endEvent);
9280
9483
  return processAISDKOutput(result, denyOutputPaths);
9281
9484
  },
9282
- extractMetrics: (result, startTime) => {
9283
- const metrics = extractTokenMetrics(result);
9284
- if (startTime) {
9285
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
9286
- }
9287
- return metrics;
9288
- },
9485
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
9289
9486
  aggregateChunks: aggregateAISDKChunks
9290
9487
  })
9291
9488
  );
@@ -9293,45 +9490,43 @@ var AISDKPlugin = class extends BasePlugin {
9293
9490
  traceStreamingChannel(aiSDKChannels.streamText, {
9294
9491
  name: "streamText",
9295
9492
  type: "llm" /* LLM */,
9296
- extractInput: ([params]) => {
9297
- return {
9298
- input: processAISDKInput(params),
9299
- metadata: extractMetadataFromParams(params)
9300
- };
9301
- },
9302
- extractOutput: (result) => {
9303
- return processAISDKOutput(result, denyOutputPaths);
9304
- },
9305
- extractMetrics: (result, startTime) => {
9306
- const metrics = extractTokenMetrics(result);
9307
- if (startTime) {
9308
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
9309
- }
9310
- return metrics;
9311
- },
9312
- aggregateChunks: aggregateAISDKChunks
9493
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
9494
+ extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
9495
+ extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
9496
+ aggregateChunks: aggregateAISDKChunks,
9497
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
9498
+ denyOutputPaths,
9499
+ endEvent,
9500
+ result,
9501
+ span,
9502
+ startTime
9503
+ })
9504
+ })
9505
+ );
9506
+ this.unsubscribers.push(
9507
+ traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
9508
+ name: "streamText",
9509
+ type: "llm" /* LLM */,
9510
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
9511
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
9512
+ denyOutputPaths,
9513
+ endEvent,
9514
+ result,
9515
+ span,
9516
+ startTime
9517
+ })
9313
9518
  })
9314
9519
  );
9315
9520
  this.unsubscribers.push(
9316
9521
  traceStreamingChannel(aiSDKChannels.generateObject, {
9317
9522
  name: "generateObject",
9318
9523
  type: "llm" /* LLM */,
9319
- extractInput: ([params]) => {
9320
- return {
9321
- input: processAISDKInput(params),
9322
- metadata: extractMetadataFromParams(params)
9323
- };
9324
- },
9325
- extractOutput: (result) => {
9524
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
9525
+ extractOutput: (result, endEvent) => {
9526
+ finalizeAISDKChildTracing(endEvent);
9326
9527
  return processAISDKOutput(result, denyOutputPaths);
9327
9528
  },
9328
- extractMetrics: (result, startTime) => {
9329
- const metrics = extractTokenMetrics(result);
9330
- if (startTime) {
9331
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
9332
- }
9333
- return metrics;
9334
- },
9529
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
9335
9530
  aggregateChunks: aggregateAISDKChunks
9336
9531
  })
9337
9532
  );
@@ -9339,45 +9534,43 @@ var AISDKPlugin = class extends BasePlugin {
9339
9534
  traceStreamingChannel(aiSDKChannels.streamObject, {
9340
9535
  name: "streamObject",
9341
9536
  type: "llm" /* LLM */,
9342
- extractInput: ([params]) => {
9343
- return {
9344
- input: processAISDKInput(params),
9345
- metadata: extractMetadataFromParams(params)
9346
- };
9347
- },
9348
- extractOutput: (result) => {
9349
- return processAISDKOutput(result, denyOutputPaths);
9350
- },
9351
- extractMetrics: (result, startTime) => {
9352
- const metrics = extractTokenMetrics(result);
9353
- if (startTime) {
9354
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
9355
- }
9356
- return metrics;
9357
- },
9358
- aggregateChunks: aggregateAISDKChunks
9537
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
9538
+ extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
9539
+ extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
9540
+ aggregateChunks: aggregateAISDKChunks,
9541
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
9542
+ denyOutputPaths,
9543
+ endEvent,
9544
+ result,
9545
+ span,
9546
+ startTime
9547
+ })
9548
+ })
9549
+ );
9550
+ this.unsubscribers.push(
9551
+ traceSyncStreamChannel(aiSDKChannels.streamObjectSync, {
9552
+ name: "streamObject",
9553
+ type: "llm" /* LLM */,
9554
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
9555
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
9556
+ denyOutputPaths,
9557
+ endEvent,
9558
+ result,
9559
+ span,
9560
+ startTime
9561
+ })
9359
9562
  })
9360
9563
  );
9361
9564
  this.unsubscribers.push(
9362
9565
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
9363
9566
  name: "Agent.generate",
9364
9567
  type: "llm" /* LLM */,
9365
- extractInput: ([params]) => {
9366
- return {
9367
- input: processAISDKInput(params),
9368
- metadata: extractMetadataFromParams(params)
9369
- };
9370
- },
9371
- extractOutput: (result) => {
9568
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
9569
+ extractOutput: (result, endEvent) => {
9570
+ finalizeAISDKChildTracing(endEvent);
9372
9571
  return processAISDKOutput(result, denyOutputPaths);
9373
9572
  },
9374
- extractMetrics: (result, startTime) => {
9375
- const metrics = extractTokenMetrics(result);
9376
- if (startTime) {
9377
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
9378
- }
9379
- return metrics;
9380
- },
9573
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
9381
9574
  aggregateChunks: aggregateAISDKChunks
9382
9575
  })
9383
9576
  );
@@ -9385,52 +9578,470 @@ var AISDKPlugin = class extends BasePlugin {
9385
9578
  traceStreamingChannel(aiSDKChannels.agentStream, {
9386
9579
  name: "Agent.stream",
9387
9580
  type: "llm" /* LLM */,
9388
- extractInput: ([params]) => {
9389
- return {
9390
- input: processAISDKInput(params),
9391
- metadata: extractMetadataFromParams(params)
9392
- };
9393
- },
9394
- extractOutput: (result) => {
9581
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
9582
+ extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
9583
+ extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
9584
+ aggregateChunks: aggregateAISDKChunks,
9585
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
9586
+ denyOutputPaths,
9587
+ endEvent,
9588
+ result,
9589
+ span,
9590
+ startTime
9591
+ })
9592
+ })
9593
+ );
9594
+ this.unsubscribers.push(
9595
+ traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
9596
+ name: "ToolLoopAgent.generate",
9597
+ type: "llm" /* LLM */,
9598
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
9599
+ extractOutput: (result, endEvent) => {
9600
+ finalizeAISDKChildTracing(endEvent);
9395
9601
  return processAISDKOutput(result, denyOutputPaths);
9396
9602
  },
9397
- extractMetrics: (result, startTime) => {
9398
- const metrics = extractTokenMetrics(result);
9399
- if (startTime) {
9400
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
9401
- }
9402
- return metrics;
9403
- },
9603
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
9404
9604
  aggregateChunks: aggregateAISDKChunks
9405
9605
  })
9406
9606
  );
9607
+ this.unsubscribers.push(
9608
+ traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
9609
+ name: "ToolLoopAgent.stream",
9610
+ type: "llm" /* LLM */,
9611
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
9612
+ extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
9613
+ extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
9614
+ aggregateChunks: aggregateAISDKChunks,
9615
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
9616
+ denyOutputPaths,
9617
+ endEvent,
9618
+ result,
9619
+ span,
9620
+ startTime
9621
+ })
9622
+ })
9623
+ );
9407
9624
  }
9408
9625
  };
9409
9626
  function processAISDKInput(params) {
9410
9627
  if (!params) return params;
9411
- return processInputAttachments(params);
9628
+ const input = processInputAttachments(params);
9629
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
9630
+ return input;
9631
+ }
9632
+ const { tools: _tools, ...rest } = input;
9633
+ return rest;
9634
+ }
9635
+ function prepareAISDKInput(params, event, span, denyOutputPaths) {
9636
+ const input = processAISDKInput(params);
9637
+ const metadata = extractMetadataFromParams(params, event.self);
9638
+ const childTracing = prepareAISDKChildTracing(
9639
+ params,
9640
+ event.self,
9641
+ span,
9642
+ denyOutputPaths
9643
+ );
9644
+ event.__braintrust_ai_sdk_model_wrapped = childTracing.modelWrapped;
9645
+ if (childTracing.cleanup) {
9646
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
9647
+ }
9648
+ return {
9649
+ input,
9650
+ metadata
9651
+ };
9412
9652
  }
9413
- function extractMetadataFromParams(params) {
9653
+ function extractTopLevelAISDKMetrics(result, event, startTime) {
9654
+ const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
9655
+ if (startTime) {
9656
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
9657
+ }
9658
+ return metrics;
9659
+ }
9660
+ function hasModelChildTracing(event) {
9661
+ return event?.__braintrust_ai_sdk_model_wrapped === true;
9662
+ }
9663
+ function extractMetadataFromParams(params, self) {
9414
9664
  const metadata = {
9415
9665
  braintrust: {
9416
9666
  integration_name: "ai-sdk",
9417
9667
  sdk_language: "typescript"
9418
9668
  }
9419
9669
  };
9420
- const { model, provider } = serializeModelWithProvider(params.model);
9670
+ const agentModel = self && typeof self === "object" && "model" in self && self.model ? self.model : self && typeof self === "object" && "settings" in self && self.settings?.model ? self.settings?.model : void 0;
9671
+ const { model, provider } = serializeModelWithProvider(
9672
+ params.model ?? agentModel
9673
+ );
9421
9674
  if (model) {
9422
9675
  metadata.model = model;
9423
9676
  }
9424
9677
  if (provider) {
9425
9678
  metadata.provider = provider;
9426
9679
  }
9680
+ const tools = serializeAISDKToolsForLogging(params.tools);
9681
+ if (tools) {
9682
+ metadata.tools = tools;
9683
+ }
9427
9684
  return metadata;
9428
9685
  }
9686
+ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
9687
+ const cleanup = [];
9688
+ const patchedModels = /* @__PURE__ */ new WeakSet();
9689
+ const patchedTools = /* @__PURE__ */ new WeakSet();
9690
+ let modelWrapped = false;
9691
+ const patchModel = (model) => {
9692
+ const resolvedModel = resolveAISDKModel(model);
9693
+ if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
9694
+ return;
9695
+ }
9696
+ patchedModels.add(resolvedModel);
9697
+ resolvedModel[AUTO_PATCHED_MODEL] = true;
9698
+ modelWrapped = true;
9699
+ const originalDoGenerate = resolvedModel.doGenerate;
9700
+ const originalDoStream = resolvedModel.doStream;
9701
+ const baseMetadata = buildAISDKChildMetadata(resolvedModel);
9702
+ resolvedModel.doGenerate = async function doGeneratePatched(options) {
9703
+ return parentSpan.traced(
9704
+ async (span) => {
9705
+ const result = await Reflect.apply(
9706
+ originalDoGenerate,
9707
+ resolvedModel,
9708
+ [options]
9709
+ );
9710
+ span.log({
9711
+ output: processAISDKOutput(result, denyOutputPaths),
9712
+ metrics: extractTokenMetrics(result),
9713
+ ...buildResolvedMetadataPayload(result)
9714
+ });
9715
+ return result;
9716
+ },
9717
+ {
9718
+ name: "doGenerate",
9719
+ spanAttributes: {
9720
+ type: "llm" /* LLM */
9721
+ },
9722
+ event: {
9723
+ input: processAISDKInput(options),
9724
+ metadata: baseMetadata
9725
+ }
9726
+ }
9727
+ );
9728
+ };
9729
+ if (originalDoStream) {
9730
+ resolvedModel.doStream = async function doStreamPatched(options) {
9731
+ const span = parentSpan.startSpan({
9732
+ name: "doStream",
9733
+ spanAttributes: {
9734
+ type: "llm" /* LLM */
9735
+ },
9736
+ event: {
9737
+ input: processAISDKInput(options),
9738
+ metadata: baseMetadata
9739
+ }
9740
+ });
9741
+ const result = await withCurrent(
9742
+ span,
9743
+ () => Reflect.apply(originalDoStream, resolvedModel, [options])
9744
+ );
9745
+ const output = {};
9746
+ let text = "";
9747
+ let reasoning = "";
9748
+ const toolCalls = [];
9749
+ let object = void 0;
9750
+ const transformStream = new TransformStream({
9751
+ transform(chunk, controller) {
9752
+ switch (chunk.type) {
9753
+ case "text-delta":
9754
+ text += extractTextDelta(chunk);
9755
+ break;
9756
+ case "reasoning-delta":
9757
+ if (chunk.delta) {
9758
+ reasoning += chunk.delta;
9759
+ } else if (chunk.text) {
9760
+ reasoning += chunk.text;
9761
+ }
9762
+ break;
9763
+ case "tool-call":
9764
+ toolCalls.push(chunk);
9765
+ break;
9766
+ case "object":
9767
+ object = chunk.object;
9768
+ break;
9769
+ case "raw":
9770
+ if (chunk.rawValue) {
9771
+ const rawVal = chunk.rawValue;
9772
+ if (rawVal.delta?.content) {
9773
+ text += rawVal.delta.content;
9774
+ } else if (rawVal.choices?.[0]?.delta?.content) {
9775
+ text += rawVal.choices[0].delta.content;
9776
+ } else if (typeof rawVal.text === "string") {
9777
+ text += rawVal.text;
9778
+ } else if (typeof rawVal.content === "string") {
9779
+ text += rawVal.content;
9780
+ }
9781
+ }
9782
+ break;
9783
+ case "finish":
9784
+ output.text = text;
9785
+ output.reasoning = reasoning;
9786
+ output.toolCalls = toolCalls;
9787
+ output.finishReason = chunk.finishReason;
9788
+ output.usage = chunk.usage;
9789
+ if (object !== void 0) {
9790
+ output.object = object;
9791
+ }
9792
+ span.log({
9793
+ output: processAISDKOutput(
9794
+ output,
9795
+ denyOutputPaths
9796
+ ),
9797
+ metrics: extractTokenMetrics(output),
9798
+ ...buildResolvedMetadataPayload(output)
9799
+ });
9800
+ span.end();
9801
+ break;
9802
+ }
9803
+ controller.enqueue(chunk);
9804
+ }
9805
+ });
9806
+ return {
9807
+ ...result,
9808
+ stream: result.stream.pipeThrough(transformStream)
9809
+ };
9810
+ };
9811
+ }
9812
+ cleanup.push(() => {
9813
+ resolvedModel.doGenerate = originalDoGenerate;
9814
+ if (originalDoStream) {
9815
+ resolvedModel.doStream = originalDoStream;
9816
+ }
9817
+ delete resolvedModel[AUTO_PATCHED_MODEL];
9818
+ });
9819
+ };
9820
+ const patchTool = (tool, name) => {
9821
+ if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
9822
+ return;
9823
+ }
9824
+ patchedTools.add(tool);
9825
+ tool[AUTO_PATCHED_TOOL] = true;
9826
+ const originalExecute = tool.execute;
9827
+ tool.execute = function executePatched(...args) {
9828
+ const result = Reflect.apply(originalExecute, this, args);
9829
+ if (isAsyncGenerator(result)) {
9830
+ return (async function* () {
9831
+ const span = parentSpan.startSpan({
9832
+ name,
9833
+ spanAttributes: {
9834
+ type: "tool" /* TOOL */
9835
+ }
9836
+ });
9837
+ span.log({ input: args.length === 1 ? args[0] : args });
9838
+ try {
9839
+ let lastValue;
9840
+ for await (const value of result) {
9841
+ lastValue = value;
9842
+ yield value;
9843
+ }
9844
+ span.log({ output: lastValue });
9845
+ } catch (error) {
9846
+ span.log({
9847
+ error: error instanceof Error ? error.message : String(error)
9848
+ });
9849
+ throw error;
9850
+ } finally {
9851
+ span.end();
9852
+ }
9853
+ })();
9854
+ }
9855
+ return parentSpan.traced(
9856
+ async (span) => {
9857
+ span.log({ input: args.length === 1 ? args[0] : args });
9858
+ const awaitedResult = await result;
9859
+ span.log({ output: awaitedResult });
9860
+ return awaitedResult;
9861
+ },
9862
+ {
9863
+ name,
9864
+ spanAttributes: {
9865
+ type: "tool" /* TOOL */
9866
+ }
9867
+ }
9868
+ );
9869
+ };
9870
+ cleanup.push(() => {
9871
+ tool.execute = originalExecute;
9872
+ delete tool[AUTO_PATCHED_TOOL];
9873
+ });
9874
+ };
9875
+ const patchTools = (tools) => {
9876
+ if (!tools) {
9877
+ return;
9878
+ }
9879
+ const inferName = (tool, fallback) => tool && (tool.name || tool.toolName || tool.id) || fallback;
9880
+ if (Array.isArray(tools)) {
9881
+ tools.forEach(
9882
+ (tool, index) => patchTool(tool, inferName(tool, `tool[${index}]`))
9883
+ );
9884
+ return;
9885
+ }
9886
+ for (const [key, tool] of Object.entries(tools)) {
9887
+ patchTool(tool, key);
9888
+ }
9889
+ };
9890
+ if (params && typeof params === "object") {
9891
+ patchModel(params.model);
9892
+ patchTools(params.tools);
9893
+ }
9894
+ if (self && typeof self === "object") {
9895
+ const selfRecord = self;
9896
+ if (selfRecord.model !== void 0) {
9897
+ patchModel(selfRecord.model);
9898
+ }
9899
+ if (selfRecord.settings && typeof selfRecord.settings === "object") {
9900
+ if (selfRecord.settings.model !== void 0) {
9901
+ patchModel(selfRecord.settings.model);
9902
+ }
9903
+ if (selfRecord.settings.tools !== void 0) {
9904
+ patchTools(selfRecord.settings.tools);
9905
+ }
9906
+ }
9907
+ }
9908
+ return {
9909
+ cleanup: cleanup.length > 0 ? () => {
9910
+ while (cleanup.length > 0) {
9911
+ cleanup.pop()?.();
9912
+ }
9913
+ } : void 0,
9914
+ modelWrapped
9915
+ };
9916
+ }
9917
+ function finalizeAISDKChildTracing(event) {
9918
+ const cleanup = event?.__braintrust_ai_sdk_cleanup;
9919
+ if (event && typeof cleanup === "function") {
9920
+ cleanup();
9921
+ delete event.__braintrust_ai_sdk_cleanup;
9922
+ }
9923
+ }
9924
+ function patchAISDKStreamingResult(args) {
9925
+ const { denyOutputPaths, endEvent, result, span, startTime } = args;
9926
+ if (!result || typeof result !== "object") {
9927
+ return false;
9928
+ }
9929
+ const resultRecord = result;
9930
+ if (!isReadableStreamLike(resultRecord.baseStream)) {
9931
+ return false;
9932
+ }
9933
+ let firstChunkTime;
9934
+ const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
9935
+ new TransformStream({
9936
+ transform(chunk, controller) {
9937
+ if (firstChunkTime === void 0) {
9938
+ firstChunkTime = getCurrentUnixTimestamp();
9939
+ }
9940
+ controller.enqueue(chunk);
9941
+ },
9942
+ async flush() {
9943
+ const metrics = extractTopLevelAISDKMetrics(result, endEvent);
9944
+ if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
9945
+ metrics.time_to_first_token = firstChunkTime - startTime;
9946
+ }
9947
+ const output = await processAISDKStreamingOutput(
9948
+ result,
9949
+ denyOutputPaths
9950
+ );
9951
+ const metadata = buildResolvedMetadataPayload(result).metadata;
9952
+ span.log({
9953
+ output,
9954
+ ...metadata ? { metadata } : {},
9955
+ metrics
9956
+ });
9957
+ finalizeAISDKChildTracing(endEvent);
9958
+ span.end();
9959
+ }
9960
+ })
9961
+ );
9962
+ Object.defineProperty(resultRecord, "baseStream", {
9963
+ configurable: true,
9964
+ enumerable: true,
9965
+ value: wrappedBaseStream,
9966
+ writable: true
9967
+ });
9968
+ return true;
9969
+ }
9970
+ function isReadableStreamLike(value) {
9971
+ return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
9972
+ }
9973
+ async function processAISDKStreamingOutput(result, denyOutputPaths) {
9974
+ const output = processAISDKOutput(result, denyOutputPaths);
9975
+ if (!output || typeof output !== "object") {
9976
+ return output;
9977
+ }
9978
+ const outputRecord = output;
9979
+ try {
9980
+ if ("text" in result && typeof result.text === "string") {
9981
+ outputRecord.text = result.text;
9982
+ }
9983
+ } catch {
9984
+ }
9985
+ try {
9986
+ if ("object" in result) {
9987
+ const resolvedObject = await Promise.resolve(result.object);
9988
+ if (resolvedObject !== void 0) {
9989
+ outputRecord.object = resolvedObject;
9990
+ }
9991
+ }
9992
+ } catch {
9993
+ }
9994
+ return outputRecord;
9995
+ }
9996
+ function buildAISDKChildMetadata(model) {
9997
+ const { model: modelId, provider } = serializeModelWithProvider(model);
9998
+ return {
9999
+ ...modelId ? { model: modelId } : {},
10000
+ ...provider ? { provider } : {},
10001
+ braintrust: {
10002
+ integration_name: "ai-sdk",
10003
+ sdk_language: "typescript"
10004
+ }
10005
+ };
10006
+ }
10007
+ function buildResolvedMetadataPayload(result) {
10008
+ const gatewayInfo = extractGatewayRoutingInfo(result);
10009
+ const metadata = {};
10010
+ if (gatewayInfo?.provider) {
10011
+ metadata.provider = gatewayInfo.provider;
10012
+ }
10013
+ if (gatewayInfo?.model) {
10014
+ metadata.model = gatewayInfo.model;
10015
+ }
10016
+ if (result.finishReason !== void 0) {
10017
+ metadata.finish_reason = result.finishReason;
10018
+ }
10019
+ return Object.keys(metadata).length > 0 ? { metadata } : {};
10020
+ }
10021
+ function resolveAISDKModel(model) {
10022
+ if (typeof model !== "string") {
10023
+ return model;
10024
+ }
10025
+ const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? null;
10026
+ if (provider && typeof provider.languageModel === "function") {
10027
+ return provider.languageModel(model);
10028
+ }
10029
+ return model;
10030
+ }
10031
+ function extractTextDelta(chunk) {
10032
+ if (typeof chunk.textDelta === "string") return chunk.textDelta;
10033
+ if (typeof chunk.delta === "string") return chunk.delta;
10034
+ if (typeof chunk.text === "string") return chunk.text;
10035
+ if (typeof chunk.content === "string") return chunk.content;
10036
+ return "";
10037
+ }
10038
+ function isAsyncGenerator(value) {
10039
+ return value != null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function" && typeof value.next === "function" && typeof value.return === "function" && typeof value.throw === "function";
10040
+ }
9429
10041
  function processAISDKOutput(output, denyOutputPaths) {
9430
10042
  if (!output) return output;
9431
- const getterValues = extractGetterValues(output);
9432
- const merged = { ...output, ...getterValues };
9433
- return omit(merged, denyOutputPaths);
10043
+ const merged = extractSerializableOutputFields(output);
10044
+ return normalizeAISDKLoggedOutput(omit(merged, denyOutputPaths));
9434
10045
  }
9435
10046
  function extractTokenMetrics(result) {
9436
10047
  const metrics = {};
@@ -9480,12 +10091,14 @@ function extractTokenMetrics(result) {
9480
10091
  }
9481
10092
  return metrics;
9482
10093
  }
9483
- function aggregateAISDKChunks(chunks) {
10094
+ function aggregateAISDKChunks(chunks, _result, endEvent) {
9484
10095
  const lastChunk = chunks[chunks.length - 1];
9485
10096
  const output = {};
9486
10097
  let metrics = {};
10098
+ let metadata;
9487
10099
  if (lastChunk) {
9488
- metrics = extractTokenMetrics(lastChunk);
10100
+ metrics = hasModelChildTracing(endEvent) ? {} : extractTokenMetrics(lastChunk);
10101
+ metadata = buildResolvedMetadataPayload(lastChunk).metadata;
9489
10102
  if (lastChunk.text !== void 0) {
9490
10103
  output.text = lastChunk.text;
9491
10104
  }
@@ -9499,7 +10112,8 @@ function aggregateAISDKChunks(chunks) {
9499
10112
  output.toolCalls = lastChunk.toolCalls;
9500
10113
  }
9501
10114
  }
9502
- return { output, metrics };
10115
+ finalizeAISDKChildTracing(endEvent);
10116
+ return { output, metrics, metadata };
9503
10117
  }
9504
10118
  function extractGetterValues(obj) {
9505
10119
  const getterValues = {};
@@ -9519,7 +10133,7 @@ function extractGetterValues(obj) {
9519
10133
  ];
9520
10134
  for (const name of getterNames) {
9521
10135
  try {
9522
- if (obj && name in obj && typeof obj[name] !== "function") {
10136
+ if (obj && name in obj && isSerializableOutputValue(obj[name])) {
9523
10137
  getterValues[name] = obj[name];
9524
10138
  }
9525
10139
  } catch {
@@ -9527,6 +10141,47 @@ function extractGetterValues(obj) {
9527
10141
  }
9528
10142
  return getterValues;
9529
10143
  }
10144
+ function extractSerializableOutputFields(output) {
10145
+ const serialized = {};
10146
+ const directFieldNames = [
10147
+ "steps",
10148
+ "request",
10149
+ "responseMessages",
10150
+ "warnings",
10151
+ "rawResponse",
10152
+ "response",
10153
+ "providerMetadata",
10154
+ "experimental_providerMetadata"
10155
+ ];
10156
+ for (const name of directFieldNames) {
10157
+ try {
10158
+ const value = output?.[name];
10159
+ if (isSerializableOutputValue(value)) {
10160
+ serialized[name] = value;
10161
+ }
10162
+ } catch {
10163
+ }
10164
+ }
10165
+ return {
10166
+ ...serialized,
10167
+ ...extractGetterValues(output)
10168
+ };
10169
+ }
10170
+ function isSerializableOutputValue(value) {
10171
+ if (typeof value === "function") {
10172
+ return false;
10173
+ }
10174
+ if (value && typeof value === "object" && typeof value.then === "function") {
10175
+ return false;
10176
+ }
10177
+ if (value && typeof value === "object" && typeof value.getReader === "function") {
10178
+ return false;
10179
+ }
10180
+ if (value && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function") {
10181
+ return false;
10182
+ }
10183
+ return true;
10184
+ }
9530
10185
  function serializeModelWithProvider(model) {
9531
10186
  const modelId = typeof model === "string" ? model : model?.modelId;
9532
10187
  const explicitProvider = typeof model === "object" ? model?.provider : void 0;
@@ -9552,6 +10207,25 @@ function parseGatewayModelString(modelString) {
9552
10207
  }
9553
10208
  return { model: modelString };
9554
10209
  }
10210
+ function extractGatewayRoutingInfo(result) {
10211
+ if (result?.steps && Array.isArray(result.steps) && result.steps.length > 0) {
10212
+ const routing2 = result.steps[0]?.providerMetadata?.gateway?.routing;
10213
+ if (routing2) {
10214
+ return {
10215
+ provider: routing2.resolvedProvider || routing2.finalProvider,
10216
+ model: routing2.resolvedProviderApiModelId
10217
+ };
10218
+ }
10219
+ }
10220
+ const routing = result?.providerMetadata?.gateway?.routing;
10221
+ if (routing) {
10222
+ return {
10223
+ provider: routing.resolvedProvider || routing.finalProvider,
10224
+ model: routing.resolvedProviderApiModelId
10225
+ };
10226
+ }
10227
+ return null;
10228
+ }
9555
10229
  function extractCostFromResult(result) {
9556
10230
  if (result?.steps && Array.isArray(result.steps) && result.steps.length > 0) {
9557
10231
  let totalCost = 0;