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
@@ -22,8 +22,54 @@ var DefaultAsyncLocalStorage = class {
22
22
  return void 0;
23
23
  }
24
24
  };
25
- var DefaultTracingChannel = class {
25
+ var DefaultChannel = class {
26
+ constructor(name) {
27
+ this.name = name;
28
+ }
26
29
  hasSubscribers = false;
30
+ subscribe(_subscription) {
31
+ }
32
+ unsubscribe(_subscription) {
33
+ return false;
34
+ }
35
+ bindStore(_store, _transform) {
36
+ }
37
+ unbindStore(_store) {
38
+ return false;
39
+ }
40
+ publish(_message) {
41
+ }
42
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
+ runStores(_message, fn, thisArg, ...args) {
44
+ return fn.apply(thisArg, args);
45
+ }
46
+ };
47
+ var DefaultTracingChannel = class {
48
+ start;
49
+ end;
50
+ asyncStart;
51
+ asyncEnd;
52
+ error;
53
+ constructor(nameOrChannels) {
54
+ if (typeof nameOrChannels === "string") {
55
+ this.start = new DefaultChannel(`tracing:${nameOrChannels}:start`);
56
+ this.end = new DefaultChannel(`tracing:${nameOrChannels}:end`);
57
+ this.asyncStart = new DefaultChannel(
58
+ `tracing:${nameOrChannels}:asyncStart`
59
+ );
60
+ this.asyncEnd = new DefaultChannel(`tracing:${nameOrChannels}:asyncEnd`);
61
+ this.error = new DefaultChannel(`tracing:${nameOrChannels}:error`);
62
+ return;
63
+ }
64
+ this.start = nameOrChannels.start ?? new DefaultChannel("tracing:start");
65
+ this.end = nameOrChannels.end ?? new DefaultChannel("tracing:end");
66
+ this.asyncStart = nameOrChannels.asyncStart ?? new DefaultChannel("tracing:asyncStart");
67
+ this.asyncEnd = nameOrChannels.asyncEnd ?? new DefaultChannel("tracing:asyncEnd");
68
+ this.error = nameOrChannels.error ?? new DefaultChannel("tracing:error");
69
+ }
70
+ get hasSubscribers() {
71
+ return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
72
+ }
27
73
  subscribe(_handlers) {
28
74
  }
29
75
  unsubscribe(_handlers) {
@@ -51,7 +97,7 @@ var iso = {
51
97
  getCallerLocation: () => void 0,
52
98
  newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
53
99
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
- newTracingChannel: (_nameOrChannels) => new DefaultTracingChannel(),
100
+ newTracingChannel: (nameOrChannels) => new DefaultTracingChannel(nameOrChannels),
55
101
  processOn: (_0, _1) => {
56
102
  },
57
103
  basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
@@ -2334,6 +2380,8 @@ var Experiment = z6.object({
2334
2380
  deleted_at: z6.union([z6.string(), z6.null()]).optional(),
2335
2381
  dataset_id: z6.union([z6.string(), z6.null()]).optional(),
2336
2382
  dataset_version: z6.union([z6.string(), z6.null()]).optional(),
2383
+ parameters_id: z6.union([z6.string(), z6.null()]).optional(),
2384
+ parameters_version: z6.union([z6.string(), z6.null()]).optional(),
2337
2385
  public: z6.boolean(),
2338
2386
  user_id: z6.union([z6.string(), z6.null()]).optional(),
2339
2387
  metadata: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
@@ -2356,7 +2404,11 @@ var SpanType = z6.union([
2356
2404
  z6.null()
2357
2405
  ]);
2358
2406
  var SpanAttributes = z6.union([
2359
- z6.object({ name: z6.union([z6.string(), z6.null()]), type: SpanType }).partial().passthrough(),
2407
+ z6.object({
2408
+ name: z6.union([z6.string(), z6.null()]),
2409
+ type: SpanType,
2410
+ purpose: z6.union([z6.literal("scorer"), z6.null()])
2411
+ }).partial().passthrough(),
2360
2412
  z6.null()
2361
2413
  ]);
2362
2414
  var ExperimentEvent = z6.object({
@@ -2796,6 +2848,7 @@ var FunctionId = z6.union([
2796
2848
  version: z6.string()
2797
2849
  }),
2798
2850
  code: z6.string(),
2851
+ function_type: FunctionTypeEnum.and(z6.unknown()).optional(),
2799
2852
  name: z6.union([z6.string(), z6.null()]).optional()
2800
2853
  }),
2801
2854
  z6.object({
@@ -3025,7 +3078,12 @@ var TopicAutomationConfig = z6.object({
3025
3078
  topic_map_functions: z6.array(TopicMapFunctionAutomation),
3026
3079
  scope: z6.union([SpanScope, TraceScope, GroupScope, z6.null()]).optional(),
3027
3080
  data_scope: TopicAutomationDataScope.optional(),
3028
- btql_filter: z6.union([z6.string(), z6.null()]).optional()
3081
+ btql_filter: z6.union([z6.string(), z6.null()]).optional(),
3082
+ backfill_time_range: z6.union([
3083
+ z6.string(),
3084
+ z6.object({ from: z6.string(), to: z6.string() }),
3085
+ z6.null()
3086
+ ]).optional()
3029
3087
  });
3030
3088
  var ProjectAutomation = z6.object({
3031
3089
  id: z6.string().uuid(),
@@ -4464,6 +4522,12 @@ var parametersRowSchema = z8.object({
4464
4522
  }),
4465
4523
  metadata: z8.union([z8.object({}).partial().passthrough(), z8.null()]).optional()
4466
4524
  });
4525
+ var InlineAttachmentReferenceSchema = z8.object({
4526
+ type: z8.literal("inline_attachment"),
4527
+ src: z8.string().min(1),
4528
+ content_type: z8.string().optional(),
4529
+ filename: z8.string().optional()
4530
+ });
4467
4531
  var LoginInvalidOrgError = class extends Error {
4468
4532
  constructor(message) {
4469
4533
  super(message);
@@ -6453,6 +6517,7 @@ function init(projectOrOptions, optionalOptions) {
6453
6517
  experiment,
6454
6518
  description,
6455
6519
  dataset,
6520
+ parameters,
6456
6521
  baseExperiment,
6457
6522
  isPublic,
6458
6523
  open: open2,
@@ -6570,6 +6635,17 @@ function init(projectOrOptions, optionalOptions) {
6570
6635
  args["dataset_version"] = await dataset.version();
6571
6636
  }
6572
6637
  }
6638
+ if (parameters !== void 0) {
6639
+ if (RemoteEvalParameters.isParameters(parameters)) {
6640
+ args["parameters_id"] = parameters.id;
6641
+ args["parameters_version"] = parameters.version;
6642
+ } else {
6643
+ args["parameters_id"] = parameters.id;
6644
+ if (parameters.version !== void 0) {
6645
+ args["parameters_version"] = parameters.version;
6646
+ }
6647
+ }
6648
+ }
6573
6649
  if (isPublic !== void 0) {
6574
6650
  args["public"] = isPublic;
6575
6651
  }
@@ -8221,40 +8297,82 @@ var Dataset2 = class extends ObjectFetcher {
8221
8297
  return typeof data === "object" && data !== null && "__braintrust_dataset_marker" in data;
8222
8298
  }
8223
8299
  };
8224
- function renderMessage(render, message) {
8300
+ function isAttachmentObject(value) {
8301
+ return BraintrustAttachmentReference.safeParse(value).success || InlineAttachmentReferenceSchema.safeParse(value).success || ExternalAttachmentReference.safeParse(value).success;
8302
+ }
8303
+ function isURL(url) {
8304
+ try {
8305
+ const parsedUrl = new URL(url.trim());
8306
+ return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";
8307
+ } catch {
8308
+ return false;
8309
+ }
8310
+ }
8311
+ function expandAttachmentArrayPreTemplate(content, variables) {
8312
+ if (typeof content !== "string") return null;
8313
+ const match = content.match(/^\{\{\s*([\w.]+)\s*\}\}$/);
8314
+ if (!match) return null;
8315
+ const varPath = match[1];
8316
+ const value = varPath.includes(".") ? getObjValueByPath(variables, varPath.split(".")) : variables[varPath];
8317
+ if (!Array.isArray(value)) return null;
8318
+ const allValid = value.every(
8319
+ (v) => isAttachmentObject(v) || typeof v === "string" && isURL(v)
8320
+ );
8321
+ if (!allValid) return null;
8322
+ return value.map((item) => ({
8323
+ type: "image_url",
8324
+ image_url: { url: item }
8325
+ }));
8326
+ }
8327
+ function renderMessageImpl(render, message, variables) {
8225
8328
  return {
8226
8329
  ...message,
8227
8330
  ..."content" in message ? {
8228
- content: isEmpty2(message.content) ? void 0 : typeof message.content === "string" ? render(message.content) : message.content.map((c) => {
8331
+ content: isEmpty2(message.content) ? void 0 : typeof message.content === "string" ? render(message.content) : message.content.flatMap((c) => {
8229
8332
  switch (c.type) {
8230
8333
  case "text":
8231
- return { ...c, text: render(c.text) };
8334
+ return [{ ...c, text: render(c.text) }];
8232
8335
  case "image_url":
8233
8336
  if (isObject(c.image_url.url)) {
8234
8337
  throw new Error(
8235
8338
  "Attachments must be replaced with URLs before calling `build()`"
8236
8339
  );
8237
8340
  }
8238
- return {
8239
- ...c,
8240
- image_url: {
8241
- ...c.image_url,
8242
- url: render(c.image_url.url)
8341
+ if (variables) {
8342
+ const expanded = expandAttachmentArrayPreTemplate(
8343
+ c.image_url.url,
8344
+ variables
8345
+ );
8346
+ if (expanded) {
8347
+ return expanded;
8243
8348
  }
8244
- };
8349
+ }
8350
+ return [
8351
+ {
8352
+ ...c,
8353
+ image_url: {
8354
+ ...c.image_url,
8355
+ url: render(c.image_url.url)
8356
+ }
8357
+ }
8358
+ ];
8245
8359
  case "file":
8246
- return {
8247
- ...c,
8248
- file: {
8249
- file_data: render(c.file.file_data || ""),
8250
- ...c.file.file_id && {
8251
- file_id: render(c.file.file_id)
8252
- },
8253
- ...c.file.filename && {
8254
- filename: render(c.file.filename)
8360
+ return [
8361
+ {
8362
+ ...c,
8363
+ file: {
8364
+ ...c.file.file_data && {
8365
+ file_data: render(c.file.file_data)
8366
+ },
8367
+ ...c.file.file_id && {
8368
+ file_id: render(c.file.file_id)
8369
+ },
8370
+ ...c.file.filename && {
8371
+ filename: render(c.file.filename)
8372
+ }
8255
8373
  }
8256
8374
  }
8257
- };
8375
+ ];
8258
8376
  default:
8259
8377
  const _exhaustiveCheck = c;
8260
8378
  return _exhaustiveCheck;
@@ -8411,17 +8529,19 @@ var Prompt2 = class _Prompt {
8411
8529
  }
8412
8530
  runBuild(buildArgs, options) {
8413
8531
  const { flavor } = options;
8414
- const params = {
8415
- ...this.defaults,
8416
- ...Object.fromEntries(
8417
- Object.entries(this.options.params || {}).filter(
8418
- ([k, _v]) => !BRAINTRUST_PARAMS.includes(k)
8419
- )
8420
- ),
8421
- ...!isEmpty2(this.options.model) ? {
8422
- model: this.options.model
8423
- } : {}
8424
- };
8532
+ const params = Object.fromEntries(
8533
+ Object.entries({
8534
+ ...this.defaults,
8535
+ ...Object.fromEntries(
8536
+ Object.entries(this.options.params || {}).filter(
8537
+ ([k, _v]) => !BRAINTRUST_PARAMS.includes(k)
8538
+ )
8539
+ ),
8540
+ ...!isEmpty2(this.options.model) ? {
8541
+ model: this.options.model
8542
+ } : {}
8543
+ }).filter(([key, value]) => key !== "response_format" || value !== null)
8544
+ );
8425
8545
  if (!("model" in params) || isEmpty2(params.model)) {
8426
8546
  throw new Error(
8427
8547
  "No model specified. Either specify it in the prompt or as a default"
@@ -8521,7 +8641,7 @@ var Prompt2 = class _Prompt {
8521
8641
  templateFormat
8522
8642
  });
8523
8643
  const baseMessages = (prompt.messages || []).map(
8524
- (m) => renderMessage(render, m)
8644
+ (m) => renderMessageImpl(render, m, variables)
8525
8645
  );
8526
8646
  const hasSystemPrompt = baseMessages.some((m) => m.role === "system");
8527
8647
  const messages = [
@@ -9149,7 +9269,11 @@ function startSpanForEvent(config, event, channelName) {
9149
9269
  });
9150
9270
  const startTime = getCurrentUnixTimestamp();
9151
9271
  try {
9152
- const { input, metadata } = config.extractInput(event.arguments);
9272
+ const { input, metadata } = config.extractInput(
9273
+ event.arguments,
9274
+ event,
9275
+ span
9276
+ );
9153
9277
  span.log({
9154
9278
  input,
9155
9279
  metadata: mergeInputMetadata(metadata, spanInfoMetadata)
@@ -9313,6 +9437,16 @@ function traceStreamingChannel(channel2, config) {
9313
9437
  });
9314
9438
  return;
9315
9439
  }
9440
+ if (config.patchResult?.({
9441
+ channelName,
9442
+ endEvent: asyncEndEvent,
9443
+ result: asyncEndEvent.result,
9444
+ span,
9445
+ startTime
9446
+ })) {
9447
+ states.delete(event);
9448
+ return;
9449
+ }
9316
9450
  try {
9317
9451
  const output = config.extractOutput(
9318
9452
  asyncEndEvent.result,
@@ -9369,8 +9503,17 @@ function traceSyncStreamChannel(channel2, config) {
9369
9503
  return;
9370
9504
  }
9371
9505
  const { span, startTime } = spanData;
9372
- const resultEvent = event;
9373
- const stream = resultEvent.result;
9506
+ const endEvent = event;
9507
+ if (config.patchResult?.({
9508
+ channelName,
9509
+ endEvent,
9510
+ result: endEvent.result,
9511
+ span,
9512
+ startTime
9513
+ })) {
9514
+ return;
9515
+ }
9516
+ const stream = endEvent.result;
9374
9517
  if (!isSyncStreamLike(stream)) {
9375
9518
  span.end();
9376
9519
  states.delete(event);
@@ -10341,6 +10484,108 @@ function filterFrom(obj, fieldsToRemove) {
10341
10484
  return result;
10342
10485
  }
10343
10486
 
10487
+ // src/wrappers/ai-sdk/normalize-logged-output.ts
10488
+ var REMOVE_NORMALIZED_VALUE = Symbol("braintrust.ai-sdk.remove-normalized");
10489
+ function normalizeAISDKLoggedOutput(value) {
10490
+ const normalized = normalizeAISDKLoggedValue(value);
10491
+ return normalized === REMOVE_NORMALIZED_VALUE ? {} : normalized;
10492
+ }
10493
+ function normalizeAISDKLoggedValue(value, context = {}) {
10494
+ if (Array.isArray(value)) {
10495
+ return value.map((entry) => normalizeAISDKLoggedValue(entry, context)).filter((entry) => entry !== REMOVE_NORMALIZED_VALUE);
10496
+ }
10497
+ if (!value || typeof value !== "object") {
10498
+ return value;
10499
+ }
10500
+ const nextInProviderMetadata = context.inProviderMetadata || context.parentKey === "providerMetadata" || context.parentKey === "experimental_providerMetadata";
10501
+ const normalizedEntries = [];
10502
+ for (const [key, entry] of Object.entries(value)) {
10503
+ if (key === "cachedPromptTokens" && entry === 0) {
10504
+ continue;
10505
+ }
10506
+ if (context.parentKey === "request" && key === "body" && entry === "<omitted>") {
10507
+ continue;
10508
+ }
10509
+ const normalizedEntry = normalizeAISDKLoggedValue(entry, {
10510
+ inProviderMetadata: nextInProviderMetadata,
10511
+ parentKey: key
10512
+ });
10513
+ if (normalizedEntry === REMOVE_NORMALIZED_VALUE) {
10514
+ continue;
10515
+ }
10516
+ normalizedEntries.push([key, normalizedEntry]);
10517
+ }
10518
+ if (normalizedEntries.length === 0) {
10519
+ if (context.parentKey === "request" || nextInProviderMetadata) {
10520
+ return REMOVE_NORMALIZED_VALUE;
10521
+ }
10522
+ return {};
10523
+ }
10524
+ return Object.fromEntries(normalizedEntries);
10525
+ }
10526
+
10527
+ // src/zod/utils.ts
10528
+ import { zodToJsonSchema as zodToJsonSchemaV3 } from "zod-to-json-schema";
10529
+ import * as z42 from "zod/v4";
10530
+ function isZodV4(zodObject) {
10531
+ return typeof zodObject === "object" && zodObject !== null && "_zod" in zodObject && zodObject._zod !== void 0;
10532
+ }
10533
+ function zodToJsonSchema(schema) {
10534
+ if (isZodV4(schema)) {
10535
+ return z42.toJSONSchema(schema, {
10536
+ target: "draft-7"
10537
+ });
10538
+ }
10539
+ return zodToJsonSchemaV3(schema);
10540
+ }
10541
+
10542
+ // src/wrappers/ai-sdk/tool-serialization.ts
10543
+ function isZodSchema(value) {
10544
+ return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
10545
+ }
10546
+ function serializeZodSchema(schema) {
10547
+ try {
10548
+ return zodToJsonSchema(schema);
10549
+ } catch {
10550
+ return {
10551
+ type: "object",
10552
+ description: "Zod schema (conversion failed)"
10553
+ };
10554
+ }
10555
+ }
10556
+ function serializeTool(tool) {
10557
+ if (!tool || typeof tool !== "object") {
10558
+ return tool;
10559
+ }
10560
+ const serialized = { ...tool };
10561
+ if (isZodSchema(serialized.inputSchema)) {
10562
+ serialized.inputSchema = serializeZodSchema(serialized.inputSchema);
10563
+ }
10564
+ if (isZodSchema(serialized.parameters)) {
10565
+ serialized.parameters = serializeZodSchema(serialized.parameters);
10566
+ }
10567
+ if ("execute" in serialized) {
10568
+ delete serialized.execute;
10569
+ }
10570
+ if ("render" in serialized) {
10571
+ delete serialized.render;
10572
+ }
10573
+ return serialized;
10574
+ }
10575
+ function serializeAISDKToolsForLogging(tools) {
10576
+ if (!tools || typeof tools !== "object") {
10577
+ return tools;
10578
+ }
10579
+ if (Array.isArray(tools)) {
10580
+ return tools.map(serializeTool);
10581
+ }
10582
+ const serialized = {};
10583
+ for (const [key, tool] of Object.entries(tools)) {
10584
+ serialized[key] = serializeTool(tool);
10585
+ }
10586
+ return serialized;
10587
+ }
10588
+
10344
10589
  // src/instrumentation/plugins/ai-sdk-channels.ts
10345
10590
  var aiSDKChannels = defineChannels("ai", {
10346
10591
  generateText: channel({
@@ -10351,6 +10596,10 @@ var aiSDKChannels = defineChannels("ai", {
10351
10596
  channelName: "streamText",
10352
10597
  kind: "async"
10353
10598
  }),
10599
+ streamTextSync: channel({
10600
+ channelName: "streamText.sync",
10601
+ kind: "sync-stream"
10602
+ }),
10354
10603
  generateObject: channel({
10355
10604
  channelName: "generateObject",
10356
10605
  kind: "async"
@@ -10359,6 +10608,10 @@ var aiSDKChannels = defineChannels("ai", {
10359
10608
  channelName: "streamObject",
10360
10609
  kind: "async"
10361
10610
  }),
10611
+ streamObjectSync: channel({
10612
+ channelName: "streamObject.sync",
10613
+ kind: "sync-stream"
10614
+ }),
10362
10615
  agentGenerate: channel({
10363
10616
  channelName: "Agent.generate",
10364
10617
  kind: "async"
@@ -10366,6 +10619,14 @@ var aiSDKChannels = defineChannels("ai", {
10366
10619
  agentStream: channel({
10367
10620
  channelName: "Agent.stream",
10368
10621
  kind: "async"
10622
+ }),
10623
+ toolLoopAgentGenerate: channel({
10624
+ channelName: "ToolLoopAgent.generate",
10625
+ kind: "async"
10626
+ }),
10627
+ toolLoopAgentStream: channel({
10628
+ channelName: "ToolLoopAgent.stream",
10629
+ kind: "async"
10369
10630
  })
10370
10631
  });
10371
10632
 
@@ -10384,6 +10645,8 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
10384
10645
  "steps[].response.body",
10385
10646
  "steps[].response.headers"
10386
10647
  ];
10648
+ var AUTO_PATCHED_MODEL = Symbol.for("braintrust.ai-sdk.auto-patched-model");
10649
+ var AUTO_PATCHED_TOOL = Symbol.for("braintrust.ai-sdk.auto-patched-tool");
10387
10650
  var AISDKPlugin = class extends BasePlugin {
10388
10651
  config;
10389
10652
  constructor(config = {}) {
@@ -10402,22 +10665,12 @@ var AISDKPlugin = class extends BasePlugin {
10402
10665
  traceStreamingChannel(aiSDKChannels.generateText, {
10403
10666
  name: "generateText",
10404
10667
  type: "llm" /* LLM */,
10405
- extractInput: ([params]) => {
10406
- return {
10407
- input: processAISDKInput(params),
10408
- metadata: extractMetadataFromParams(params)
10409
- };
10410
- },
10411
- extractOutput: (result) => {
10668
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
10669
+ extractOutput: (result, endEvent) => {
10670
+ finalizeAISDKChildTracing(endEvent);
10412
10671
  return processAISDKOutput(result, denyOutputPaths);
10413
10672
  },
10414
- extractMetrics: (result, startTime) => {
10415
- const metrics = extractTokenMetrics(result);
10416
- if (startTime) {
10417
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
10418
- }
10419
- return metrics;
10420
- },
10673
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
10421
10674
  aggregateChunks: aggregateAISDKChunks
10422
10675
  })
10423
10676
  );
@@ -10425,45 +10678,43 @@ var AISDKPlugin = class extends BasePlugin {
10425
10678
  traceStreamingChannel(aiSDKChannels.streamText, {
10426
10679
  name: "streamText",
10427
10680
  type: "llm" /* LLM */,
10428
- extractInput: ([params]) => {
10429
- return {
10430
- input: processAISDKInput(params),
10431
- metadata: extractMetadataFromParams(params)
10432
- };
10433
- },
10434
- extractOutput: (result) => {
10435
- return processAISDKOutput(result, denyOutputPaths);
10436
- },
10437
- extractMetrics: (result, startTime) => {
10438
- const metrics = extractTokenMetrics(result);
10439
- if (startTime) {
10440
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
10441
- }
10442
- return metrics;
10443
- },
10444
- aggregateChunks: aggregateAISDKChunks
10681
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
10682
+ extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
10683
+ extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
10684
+ aggregateChunks: aggregateAISDKChunks,
10685
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
10686
+ denyOutputPaths,
10687
+ endEvent,
10688
+ result,
10689
+ span,
10690
+ startTime
10691
+ })
10692
+ })
10693
+ );
10694
+ this.unsubscribers.push(
10695
+ traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
10696
+ name: "streamText",
10697
+ type: "llm" /* LLM */,
10698
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
10699
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
10700
+ denyOutputPaths,
10701
+ endEvent,
10702
+ result,
10703
+ span,
10704
+ startTime
10705
+ })
10445
10706
  })
10446
10707
  );
10447
10708
  this.unsubscribers.push(
10448
10709
  traceStreamingChannel(aiSDKChannels.generateObject, {
10449
10710
  name: "generateObject",
10450
10711
  type: "llm" /* LLM */,
10451
- extractInput: ([params]) => {
10452
- return {
10453
- input: processAISDKInput(params),
10454
- metadata: extractMetadataFromParams(params)
10455
- };
10456
- },
10457
- extractOutput: (result) => {
10712
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
10713
+ extractOutput: (result, endEvent) => {
10714
+ finalizeAISDKChildTracing(endEvent);
10458
10715
  return processAISDKOutput(result, denyOutputPaths);
10459
10716
  },
10460
- extractMetrics: (result, startTime) => {
10461
- const metrics = extractTokenMetrics(result);
10462
- if (startTime) {
10463
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
10464
- }
10465
- return metrics;
10466
- },
10717
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
10467
10718
  aggregateChunks: aggregateAISDKChunks
10468
10719
  })
10469
10720
  );
@@ -10471,45 +10722,43 @@ var AISDKPlugin = class extends BasePlugin {
10471
10722
  traceStreamingChannel(aiSDKChannels.streamObject, {
10472
10723
  name: "streamObject",
10473
10724
  type: "llm" /* LLM */,
10474
- extractInput: ([params]) => {
10475
- return {
10476
- input: processAISDKInput(params),
10477
- metadata: extractMetadataFromParams(params)
10478
- };
10479
- },
10480
- extractOutput: (result) => {
10481
- return processAISDKOutput(result, denyOutputPaths);
10482
- },
10483
- extractMetrics: (result, startTime) => {
10484
- const metrics = extractTokenMetrics(result);
10485
- if (startTime) {
10486
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
10487
- }
10488
- return metrics;
10489
- },
10490
- aggregateChunks: aggregateAISDKChunks
10725
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
10726
+ extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
10727
+ extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
10728
+ aggregateChunks: aggregateAISDKChunks,
10729
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
10730
+ denyOutputPaths,
10731
+ endEvent,
10732
+ result,
10733
+ span,
10734
+ startTime
10735
+ })
10736
+ })
10737
+ );
10738
+ this.unsubscribers.push(
10739
+ traceSyncStreamChannel(aiSDKChannels.streamObjectSync, {
10740
+ name: "streamObject",
10741
+ type: "llm" /* LLM */,
10742
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
10743
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
10744
+ denyOutputPaths,
10745
+ endEvent,
10746
+ result,
10747
+ span,
10748
+ startTime
10749
+ })
10491
10750
  })
10492
10751
  );
10493
10752
  this.unsubscribers.push(
10494
10753
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
10495
10754
  name: "Agent.generate",
10496
10755
  type: "llm" /* LLM */,
10497
- extractInput: ([params]) => {
10498
- return {
10499
- input: processAISDKInput(params),
10500
- metadata: extractMetadataFromParams(params)
10501
- };
10502
- },
10503
- extractOutput: (result) => {
10756
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
10757
+ extractOutput: (result, endEvent) => {
10758
+ finalizeAISDKChildTracing(endEvent);
10504
10759
  return processAISDKOutput(result, denyOutputPaths);
10505
10760
  },
10506
- extractMetrics: (result, startTime) => {
10507
- const metrics = extractTokenMetrics(result);
10508
- if (startTime) {
10509
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
10510
- }
10511
- return metrics;
10512
- },
10761
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
10513
10762
  aggregateChunks: aggregateAISDKChunks
10514
10763
  })
10515
10764
  );
@@ -10517,52 +10766,470 @@ var AISDKPlugin = class extends BasePlugin {
10517
10766
  traceStreamingChannel(aiSDKChannels.agentStream, {
10518
10767
  name: "Agent.stream",
10519
10768
  type: "llm" /* LLM */,
10520
- extractInput: ([params]) => {
10521
- return {
10522
- input: processAISDKInput(params),
10523
- metadata: extractMetadataFromParams(params)
10524
- };
10525
- },
10526
- extractOutput: (result) => {
10769
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
10770
+ extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
10771
+ extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
10772
+ aggregateChunks: aggregateAISDKChunks,
10773
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
10774
+ denyOutputPaths,
10775
+ endEvent,
10776
+ result,
10777
+ span,
10778
+ startTime
10779
+ })
10780
+ })
10781
+ );
10782
+ this.unsubscribers.push(
10783
+ traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
10784
+ name: "ToolLoopAgent.generate",
10785
+ type: "llm" /* LLM */,
10786
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
10787
+ extractOutput: (result, endEvent) => {
10788
+ finalizeAISDKChildTracing(endEvent);
10527
10789
  return processAISDKOutput(result, denyOutputPaths);
10528
10790
  },
10529
- extractMetrics: (result, startTime) => {
10530
- const metrics = extractTokenMetrics(result);
10531
- if (startTime) {
10532
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
10533
- }
10534
- return metrics;
10535
- },
10791
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
10536
10792
  aggregateChunks: aggregateAISDKChunks
10537
10793
  })
10538
10794
  );
10795
+ this.unsubscribers.push(
10796
+ traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
10797
+ name: "ToolLoopAgent.stream",
10798
+ type: "llm" /* LLM */,
10799
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
10800
+ extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
10801
+ extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
10802
+ aggregateChunks: aggregateAISDKChunks,
10803
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
10804
+ denyOutputPaths,
10805
+ endEvent,
10806
+ result,
10807
+ span,
10808
+ startTime
10809
+ })
10810
+ })
10811
+ );
10539
10812
  }
10540
10813
  };
10541
10814
  function processAISDKInput(params) {
10542
10815
  if (!params) return params;
10543
- return processInputAttachments(params);
10816
+ const input = processInputAttachments(params);
10817
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
10818
+ return input;
10819
+ }
10820
+ const { tools: _tools, ...rest } = input;
10821
+ return rest;
10822
+ }
10823
+ function prepareAISDKInput(params, event, span, denyOutputPaths) {
10824
+ const input = processAISDKInput(params);
10825
+ const metadata = extractMetadataFromParams(params, event.self);
10826
+ const childTracing = prepareAISDKChildTracing(
10827
+ params,
10828
+ event.self,
10829
+ span,
10830
+ denyOutputPaths
10831
+ );
10832
+ event.__braintrust_ai_sdk_model_wrapped = childTracing.modelWrapped;
10833
+ if (childTracing.cleanup) {
10834
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
10835
+ }
10836
+ return {
10837
+ input,
10838
+ metadata
10839
+ };
10840
+ }
10841
+ function extractTopLevelAISDKMetrics(result, event, startTime) {
10842
+ const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
10843
+ if (startTime) {
10844
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
10845
+ }
10846
+ return metrics;
10544
10847
  }
10545
- function extractMetadataFromParams(params) {
10848
+ function hasModelChildTracing(event) {
10849
+ return event?.__braintrust_ai_sdk_model_wrapped === true;
10850
+ }
10851
+ function extractMetadataFromParams(params, self) {
10546
10852
  const metadata = {
10547
10853
  braintrust: {
10548
10854
  integration_name: "ai-sdk",
10549
10855
  sdk_language: "typescript"
10550
10856
  }
10551
10857
  };
10552
- const { model, provider } = serializeModelWithProvider(params.model);
10858
+ 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;
10859
+ const { model, provider } = serializeModelWithProvider(
10860
+ params.model ?? agentModel
10861
+ );
10553
10862
  if (model) {
10554
10863
  metadata.model = model;
10555
10864
  }
10556
10865
  if (provider) {
10557
10866
  metadata.provider = provider;
10558
10867
  }
10868
+ const tools = serializeAISDKToolsForLogging(params.tools);
10869
+ if (tools) {
10870
+ metadata.tools = tools;
10871
+ }
10559
10872
  return metadata;
10560
10873
  }
10874
+ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
10875
+ const cleanup = [];
10876
+ const patchedModels = /* @__PURE__ */ new WeakSet();
10877
+ const patchedTools = /* @__PURE__ */ new WeakSet();
10878
+ let modelWrapped = false;
10879
+ const patchModel = (model) => {
10880
+ const resolvedModel = resolveAISDKModel(model);
10881
+ if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
10882
+ return;
10883
+ }
10884
+ patchedModels.add(resolvedModel);
10885
+ resolvedModel[AUTO_PATCHED_MODEL] = true;
10886
+ modelWrapped = true;
10887
+ const originalDoGenerate = resolvedModel.doGenerate;
10888
+ const originalDoStream = resolvedModel.doStream;
10889
+ const baseMetadata = buildAISDKChildMetadata(resolvedModel);
10890
+ resolvedModel.doGenerate = async function doGeneratePatched(options) {
10891
+ return parentSpan.traced(
10892
+ async (span) => {
10893
+ const result = await Reflect.apply(
10894
+ originalDoGenerate,
10895
+ resolvedModel,
10896
+ [options]
10897
+ );
10898
+ span.log({
10899
+ output: processAISDKOutput(result, denyOutputPaths),
10900
+ metrics: extractTokenMetrics(result),
10901
+ ...buildResolvedMetadataPayload(result)
10902
+ });
10903
+ return result;
10904
+ },
10905
+ {
10906
+ name: "doGenerate",
10907
+ spanAttributes: {
10908
+ type: "llm" /* LLM */
10909
+ },
10910
+ event: {
10911
+ input: processAISDKInput(options),
10912
+ metadata: baseMetadata
10913
+ }
10914
+ }
10915
+ );
10916
+ };
10917
+ if (originalDoStream) {
10918
+ resolvedModel.doStream = async function doStreamPatched(options) {
10919
+ const span = parentSpan.startSpan({
10920
+ name: "doStream",
10921
+ spanAttributes: {
10922
+ type: "llm" /* LLM */
10923
+ },
10924
+ event: {
10925
+ input: processAISDKInput(options),
10926
+ metadata: baseMetadata
10927
+ }
10928
+ });
10929
+ const result = await withCurrent(
10930
+ span,
10931
+ () => Reflect.apply(originalDoStream, resolvedModel, [options])
10932
+ );
10933
+ const output = {};
10934
+ let text = "";
10935
+ let reasoning = "";
10936
+ const toolCalls = [];
10937
+ let object = void 0;
10938
+ const transformStream = new TransformStream({
10939
+ transform(chunk, controller) {
10940
+ switch (chunk.type) {
10941
+ case "text-delta":
10942
+ text += extractTextDelta(chunk);
10943
+ break;
10944
+ case "reasoning-delta":
10945
+ if (chunk.delta) {
10946
+ reasoning += chunk.delta;
10947
+ } else if (chunk.text) {
10948
+ reasoning += chunk.text;
10949
+ }
10950
+ break;
10951
+ case "tool-call":
10952
+ toolCalls.push(chunk);
10953
+ break;
10954
+ case "object":
10955
+ object = chunk.object;
10956
+ break;
10957
+ case "raw":
10958
+ if (chunk.rawValue) {
10959
+ const rawVal = chunk.rawValue;
10960
+ if (rawVal.delta?.content) {
10961
+ text += rawVal.delta.content;
10962
+ } else if (rawVal.choices?.[0]?.delta?.content) {
10963
+ text += rawVal.choices[0].delta.content;
10964
+ } else if (typeof rawVal.text === "string") {
10965
+ text += rawVal.text;
10966
+ } else if (typeof rawVal.content === "string") {
10967
+ text += rawVal.content;
10968
+ }
10969
+ }
10970
+ break;
10971
+ case "finish":
10972
+ output.text = text;
10973
+ output.reasoning = reasoning;
10974
+ output.toolCalls = toolCalls;
10975
+ output.finishReason = chunk.finishReason;
10976
+ output.usage = chunk.usage;
10977
+ if (object !== void 0) {
10978
+ output.object = object;
10979
+ }
10980
+ span.log({
10981
+ output: processAISDKOutput(
10982
+ output,
10983
+ denyOutputPaths
10984
+ ),
10985
+ metrics: extractTokenMetrics(output),
10986
+ ...buildResolvedMetadataPayload(output)
10987
+ });
10988
+ span.end();
10989
+ break;
10990
+ }
10991
+ controller.enqueue(chunk);
10992
+ }
10993
+ });
10994
+ return {
10995
+ ...result,
10996
+ stream: result.stream.pipeThrough(transformStream)
10997
+ };
10998
+ };
10999
+ }
11000
+ cleanup.push(() => {
11001
+ resolvedModel.doGenerate = originalDoGenerate;
11002
+ if (originalDoStream) {
11003
+ resolvedModel.doStream = originalDoStream;
11004
+ }
11005
+ delete resolvedModel[AUTO_PATCHED_MODEL];
11006
+ });
11007
+ };
11008
+ const patchTool = (tool, name) => {
11009
+ if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
11010
+ return;
11011
+ }
11012
+ patchedTools.add(tool);
11013
+ tool[AUTO_PATCHED_TOOL] = true;
11014
+ const originalExecute = tool.execute;
11015
+ tool.execute = function executePatched(...args) {
11016
+ const result = Reflect.apply(originalExecute, this, args);
11017
+ if (isAsyncGenerator(result)) {
11018
+ return (async function* () {
11019
+ const span = parentSpan.startSpan({
11020
+ name,
11021
+ spanAttributes: {
11022
+ type: "tool" /* TOOL */
11023
+ }
11024
+ });
11025
+ span.log({ input: args.length === 1 ? args[0] : args });
11026
+ try {
11027
+ let lastValue;
11028
+ for await (const value of result) {
11029
+ lastValue = value;
11030
+ yield value;
11031
+ }
11032
+ span.log({ output: lastValue });
11033
+ } catch (error) {
11034
+ span.log({
11035
+ error: error instanceof Error ? error.message : String(error)
11036
+ });
11037
+ throw error;
11038
+ } finally {
11039
+ span.end();
11040
+ }
11041
+ })();
11042
+ }
11043
+ return parentSpan.traced(
11044
+ async (span) => {
11045
+ span.log({ input: args.length === 1 ? args[0] : args });
11046
+ const awaitedResult = await result;
11047
+ span.log({ output: awaitedResult });
11048
+ return awaitedResult;
11049
+ },
11050
+ {
11051
+ name,
11052
+ spanAttributes: {
11053
+ type: "tool" /* TOOL */
11054
+ }
11055
+ }
11056
+ );
11057
+ };
11058
+ cleanup.push(() => {
11059
+ tool.execute = originalExecute;
11060
+ delete tool[AUTO_PATCHED_TOOL];
11061
+ });
11062
+ };
11063
+ const patchTools = (tools) => {
11064
+ if (!tools) {
11065
+ return;
11066
+ }
11067
+ const inferName = (tool, fallback2) => tool && (tool.name || tool.toolName || tool.id) || fallback2;
11068
+ if (Array.isArray(tools)) {
11069
+ tools.forEach(
11070
+ (tool, index) => patchTool(tool, inferName(tool, `tool[${index}]`))
11071
+ );
11072
+ return;
11073
+ }
11074
+ for (const [key, tool] of Object.entries(tools)) {
11075
+ patchTool(tool, key);
11076
+ }
11077
+ };
11078
+ if (params && typeof params === "object") {
11079
+ patchModel(params.model);
11080
+ patchTools(params.tools);
11081
+ }
11082
+ if (self && typeof self === "object") {
11083
+ const selfRecord = self;
11084
+ if (selfRecord.model !== void 0) {
11085
+ patchModel(selfRecord.model);
11086
+ }
11087
+ if (selfRecord.settings && typeof selfRecord.settings === "object") {
11088
+ if (selfRecord.settings.model !== void 0) {
11089
+ patchModel(selfRecord.settings.model);
11090
+ }
11091
+ if (selfRecord.settings.tools !== void 0) {
11092
+ patchTools(selfRecord.settings.tools);
11093
+ }
11094
+ }
11095
+ }
11096
+ return {
11097
+ cleanup: cleanup.length > 0 ? () => {
11098
+ while (cleanup.length > 0) {
11099
+ cleanup.pop()?.();
11100
+ }
11101
+ } : void 0,
11102
+ modelWrapped
11103
+ };
11104
+ }
11105
+ function finalizeAISDKChildTracing(event) {
11106
+ const cleanup = event?.__braintrust_ai_sdk_cleanup;
11107
+ if (event && typeof cleanup === "function") {
11108
+ cleanup();
11109
+ delete event.__braintrust_ai_sdk_cleanup;
11110
+ }
11111
+ }
11112
+ function patchAISDKStreamingResult(args) {
11113
+ const { denyOutputPaths, endEvent, result, span, startTime } = args;
11114
+ if (!result || typeof result !== "object") {
11115
+ return false;
11116
+ }
11117
+ const resultRecord = result;
11118
+ if (!isReadableStreamLike(resultRecord.baseStream)) {
11119
+ return false;
11120
+ }
11121
+ let firstChunkTime;
11122
+ const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
11123
+ new TransformStream({
11124
+ transform(chunk, controller) {
11125
+ if (firstChunkTime === void 0) {
11126
+ firstChunkTime = getCurrentUnixTimestamp();
11127
+ }
11128
+ controller.enqueue(chunk);
11129
+ },
11130
+ async flush() {
11131
+ const metrics = extractTopLevelAISDKMetrics(result, endEvent);
11132
+ if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
11133
+ metrics.time_to_first_token = firstChunkTime - startTime;
11134
+ }
11135
+ const output = await processAISDKStreamingOutput(
11136
+ result,
11137
+ denyOutputPaths
11138
+ );
11139
+ const metadata = buildResolvedMetadataPayload(result).metadata;
11140
+ span.log({
11141
+ output,
11142
+ ...metadata ? { metadata } : {},
11143
+ metrics
11144
+ });
11145
+ finalizeAISDKChildTracing(endEvent);
11146
+ span.end();
11147
+ }
11148
+ })
11149
+ );
11150
+ Object.defineProperty(resultRecord, "baseStream", {
11151
+ configurable: true,
11152
+ enumerable: true,
11153
+ value: wrappedBaseStream,
11154
+ writable: true
11155
+ });
11156
+ return true;
11157
+ }
11158
+ function isReadableStreamLike(value) {
11159
+ return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
11160
+ }
11161
+ async function processAISDKStreamingOutput(result, denyOutputPaths) {
11162
+ const output = processAISDKOutput(result, denyOutputPaths);
11163
+ if (!output || typeof output !== "object") {
11164
+ return output;
11165
+ }
11166
+ const outputRecord = output;
11167
+ try {
11168
+ if ("text" in result && typeof result.text === "string") {
11169
+ outputRecord.text = result.text;
11170
+ }
11171
+ } catch {
11172
+ }
11173
+ try {
11174
+ if ("object" in result) {
11175
+ const resolvedObject = await Promise.resolve(result.object);
11176
+ if (resolvedObject !== void 0) {
11177
+ outputRecord.object = resolvedObject;
11178
+ }
11179
+ }
11180
+ } catch {
11181
+ }
11182
+ return outputRecord;
11183
+ }
11184
+ function buildAISDKChildMetadata(model) {
11185
+ const { model: modelId, provider } = serializeModelWithProvider(model);
11186
+ return {
11187
+ ...modelId ? { model: modelId } : {},
11188
+ ...provider ? { provider } : {},
11189
+ braintrust: {
11190
+ integration_name: "ai-sdk",
11191
+ sdk_language: "typescript"
11192
+ }
11193
+ };
11194
+ }
11195
+ function buildResolvedMetadataPayload(result) {
11196
+ const gatewayInfo = extractGatewayRoutingInfo(result);
11197
+ const metadata = {};
11198
+ if (gatewayInfo?.provider) {
11199
+ metadata.provider = gatewayInfo.provider;
11200
+ }
11201
+ if (gatewayInfo?.model) {
11202
+ metadata.model = gatewayInfo.model;
11203
+ }
11204
+ if (result.finishReason !== void 0) {
11205
+ metadata.finish_reason = result.finishReason;
11206
+ }
11207
+ return Object.keys(metadata).length > 0 ? { metadata } : {};
11208
+ }
11209
+ function resolveAISDKModel(model) {
11210
+ if (typeof model !== "string") {
11211
+ return model;
11212
+ }
11213
+ const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? null;
11214
+ if (provider && typeof provider.languageModel === "function") {
11215
+ return provider.languageModel(model);
11216
+ }
11217
+ return model;
11218
+ }
11219
+ function extractTextDelta(chunk) {
11220
+ if (typeof chunk.textDelta === "string") return chunk.textDelta;
11221
+ if (typeof chunk.delta === "string") return chunk.delta;
11222
+ if (typeof chunk.text === "string") return chunk.text;
11223
+ if (typeof chunk.content === "string") return chunk.content;
11224
+ return "";
11225
+ }
11226
+ function isAsyncGenerator(value) {
11227
+ return value != null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function" && typeof value.next === "function" && typeof value.return === "function" && typeof value.throw === "function";
11228
+ }
10561
11229
  function processAISDKOutput(output, denyOutputPaths) {
10562
11230
  if (!output) return output;
10563
- const getterValues = extractGetterValues(output);
10564
- const merged = { ...output, ...getterValues };
10565
- return omit(merged, denyOutputPaths);
11231
+ const merged = extractSerializableOutputFields(output);
11232
+ return normalizeAISDKLoggedOutput(omit(merged, denyOutputPaths));
10566
11233
  }
10567
11234
  function extractTokenMetrics(result) {
10568
11235
  const metrics = {};
@@ -10612,12 +11279,14 @@ function extractTokenMetrics(result) {
10612
11279
  }
10613
11280
  return metrics;
10614
11281
  }
10615
- function aggregateAISDKChunks(chunks) {
11282
+ function aggregateAISDKChunks(chunks, _result, endEvent) {
10616
11283
  const lastChunk = chunks[chunks.length - 1];
10617
11284
  const output = {};
10618
11285
  let metrics = {};
11286
+ let metadata;
10619
11287
  if (lastChunk) {
10620
- metrics = extractTokenMetrics(lastChunk);
11288
+ metrics = hasModelChildTracing(endEvent) ? {} : extractTokenMetrics(lastChunk);
11289
+ metadata = buildResolvedMetadataPayload(lastChunk).metadata;
10621
11290
  if (lastChunk.text !== void 0) {
10622
11291
  output.text = lastChunk.text;
10623
11292
  }
@@ -10631,7 +11300,8 @@ function aggregateAISDKChunks(chunks) {
10631
11300
  output.toolCalls = lastChunk.toolCalls;
10632
11301
  }
10633
11302
  }
10634
- return { output, metrics };
11303
+ finalizeAISDKChildTracing(endEvent);
11304
+ return { output, metrics, metadata };
10635
11305
  }
10636
11306
  function extractGetterValues(obj) {
10637
11307
  const getterValues = {};
@@ -10651,7 +11321,7 @@ function extractGetterValues(obj) {
10651
11321
  ];
10652
11322
  for (const name of getterNames) {
10653
11323
  try {
10654
- if (obj && name in obj && typeof obj[name] !== "function") {
11324
+ if (obj && name in obj && isSerializableOutputValue(obj[name])) {
10655
11325
  getterValues[name] = obj[name];
10656
11326
  }
10657
11327
  } catch {
@@ -10659,6 +11329,47 @@ function extractGetterValues(obj) {
10659
11329
  }
10660
11330
  return getterValues;
10661
11331
  }
11332
+ function extractSerializableOutputFields(output) {
11333
+ const serialized = {};
11334
+ const directFieldNames = [
11335
+ "steps",
11336
+ "request",
11337
+ "responseMessages",
11338
+ "warnings",
11339
+ "rawResponse",
11340
+ "response",
11341
+ "providerMetadata",
11342
+ "experimental_providerMetadata"
11343
+ ];
11344
+ for (const name of directFieldNames) {
11345
+ try {
11346
+ const value = output?.[name];
11347
+ if (isSerializableOutputValue(value)) {
11348
+ serialized[name] = value;
11349
+ }
11350
+ } catch {
11351
+ }
11352
+ }
11353
+ return {
11354
+ ...serialized,
11355
+ ...extractGetterValues(output)
11356
+ };
11357
+ }
11358
+ function isSerializableOutputValue(value) {
11359
+ if (typeof value === "function") {
11360
+ return false;
11361
+ }
11362
+ if (value && typeof value === "object" && typeof value.then === "function") {
11363
+ return false;
11364
+ }
11365
+ if (value && typeof value === "object" && typeof value.getReader === "function") {
11366
+ return false;
11367
+ }
11368
+ if (value && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function") {
11369
+ return false;
11370
+ }
11371
+ return true;
11372
+ }
10662
11373
  function serializeModelWithProvider(model) {
10663
11374
  const modelId = typeof model === "string" ? model : model?.modelId;
10664
11375
  const explicitProvider = typeof model === "object" ? model?.provider : void 0;
@@ -10684,6 +11395,25 @@ function parseGatewayModelString(modelString) {
10684
11395
  }
10685
11396
  return { model: modelString };
10686
11397
  }
11398
+ function extractGatewayRoutingInfo(result) {
11399
+ if (result?.steps && Array.isArray(result.steps) && result.steps.length > 0) {
11400
+ const routing2 = result.steps[0]?.providerMetadata?.gateway?.routing;
11401
+ if (routing2) {
11402
+ return {
11403
+ provider: routing2.resolvedProvider || routing2.finalProvider,
11404
+ model: routing2.resolvedProviderApiModelId
11405
+ };
11406
+ }
11407
+ }
11408
+ const routing = result?.providerMetadata?.gateway?.routing;
11409
+ if (routing) {
11410
+ return {
11411
+ provider: routing.resolvedProvider || routing.finalProvider,
11412
+ model: routing.resolvedProviderApiModelId
11413
+ };
11414
+ }
11415
+ return null;
11416
+ }
10687
11417
  function extractCostFromResult(result) {
10688
11418
  if (result?.steps && Array.isArray(result.steps) && result.steps.length > 0) {
10689
11419
  let totalCost = 0;
@@ -11604,7 +12334,7 @@ function configureNode() {
11604
12334
  import express from "express";
11605
12335
  import cors from "cors";
11606
12336
 
11607
- // ../node_modules/async/dist/async.mjs
12337
+ // ../node_modules/.pnpm/async@3.2.5/node_modules/async/dist/async.mjs
11608
12338
  function initialParams(fn) {
11609
12339
  return function(...args) {
11610
12340
  var callback = args.pop();
@@ -11672,7 +12402,7 @@ function invokeCallback(callback, error, value) {
11672
12402
  function isAsync(fn) {
11673
12403
  return fn[Symbol.toStringTag] === "AsyncFunction";
11674
12404
  }
11675
- function isAsyncGenerator(fn) {
12405
+ function isAsyncGenerator2(fn) {
11676
12406
  return fn[Symbol.toStringTag] === "AsyncGenerator";
11677
12407
  }
11678
12408
  function isAsyncIterable2(obj) {
@@ -11729,6 +12459,7 @@ function isArrayLike(value) {
11729
12459
  return value && typeof value.length === "number" && value.length >= 0 && value.length % 1 === 0;
11730
12460
  }
11731
12461
  var breakLoop = {};
12462
+ var breakLoop$1 = breakLoop;
11732
12463
  function once(fn) {
11733
12464
  function wrapper(...args) {
11734
12465
  if (fn === null) return;
@@ -11820,7 +12551,7 @@ function asyncEachOfLimit(generator, limit, iteratee, callback) {
11820
12551
  canceled = true;
11821
12552
  return;
11822
12553
  }
11823
- if (result === breakLoop || done && running <= 0) {
12554
+ if (result === breakLoop$1 || done && running <= 0) {
11824
12555
  done = true;
11825
12556
  return callback(null);
11826
12557
  }
@@ -11843,7 +12574,7 @@ var eachOfLimit$2 = (limit) => {
11843
12574
  if (!obj) {
11844
12575
  return callback(null);
11845
12576
  }
11846
- if (isAsyncGenerator(obj)) {
12577
+ if (isAsyncGenerator2(obj)) {
11847
12578
  return asyncEachOfLimit(obj, limit, iteratee, callback);
11848
12579
  }
11849
12580
  if (isAsyncIterable2(obj)) {
@@ -11863,7 +12594,7 @@ var eachOfLimit$2 = (limit) => {
11863
12594
  } else if (err === false) {
11864
12595
  done = true;
11865
12596
  canceled = true;
11866
- } else if (value === breakLoop || done && running <= 0) {
12597
+ } else if (value === breakLoop$1 || done && running <= 0) {
11867
12598
  done = true;
11868
12599
  return callback(null);
11869
12600
  } else if (!looping) {
@@ -11906,7 +12637,7 @@ function eachOfArrayLike(coll, iteratee, callback) {
11906
12637
  if (canceled === true) return;
11907
12638
  if (err) {
11908
12639
  callback(err);
11909
- } else if (++completed === length || value === breakLoop) {
12640
+ } else if (++completed === length || value === breakLoop$1) {
11910
12641
  callback(null);
11911
12642
  }
11912
12643
  }
@@ -12302,7 +13033,7 @@ function _createTester(check, getResult) {
12302
13033
  if (check(result) && !testResult) {
12303
13034
  testPassed = true;
12304
13035
  testResult = getResult(true, value);
12305
- return callback(null, breakLoop);
13036
+ return callback(null, breakLoop$1);
12306
13037
  }
12307
13038
  callback();
12308
13039
  });
@@ -13005,7 +13736,8 @@ var promptDefinitionSchema = promptContentsSchema.and(
13005
13736
  z9.object({
13006
13737
  model: z9.string(),
13007
13738
  params: ModelParams.optional(),
13008
- templateFormat: z9.enum(["mustache", "nunjucks", "none"]).optional()
13739
+ templateFormat: z9.enum(["mustache", "nunjucks", "none"]).optional(),
13740
+ environments: z9.array(z9.string()).optional()
13009
13741
  })
13010
13742
  );
13011
13743
  var promptDefinitionWithToolsSchema = promptDefinitionSchema.and(
@@ -13161,6 +13893,22 @@ function initExperiment(state, options = {}) {
13161
13893
  setCurrent: false
13162
13894
  });
13163
13895
  }
13896
+ async function getExperimentParametersRef(parameters) {
13897
+ if (!parameters) {
13898
+ return void 0;
13899
+ }
13900
+ const resolvedParameters = parameters instanceof Promise ? await parameters : parameters;
13901
+ if (!RemoteEvalParameters.isParameters(resolvedParameters)) {
13902
+ return void 0;
13903
+ }
13904
+ if (resolvedParameters.id === void 0) {
13905
+ return void 0;
13906
+ }
13907
+ return {
13908
+ id: resolvedParameters.id,
13909
+ version: resolvedParameters.version
13910
+ };
13911
+ }
13164
13912
  function callEvaluatorData(data) {
13165
13913
  const dataResult = typeof data === "function" ? data() : data;
13166
13914
  let baseExperiment = void 0;
@@ -13227,6 +13975,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
13227
13975
  const { data, baseExperiment: defaultBaseExperiment } = callEvaluatorData(
13228
13976
  evaluator.data
13229
13977
  );
13978
+ const parameters = await getExperimentParametersRef(evaluator.parameters);
13230
13979
  const experiment = options.parent || options.noSendLogs ? null : initExperiment(evaluator.state, {
13231
13980
  ...evaluator.projectId ? { projectId: evaluator.projectId } : { project: name },
13232
13981
  experiment: evaluator.experimentName,
@@ -13239,7 +13988,8 @@ async function Eval(name, evaluator, reporterOrOpts) {
13239
13988
  baseExperimentId: evaluator.baseExperimentId,
13240
13989
  gitMetadataSettings: evaluator.gitMetadataSettings,
13241
13990
  repoInfo: evaluator.repoInfo,
13242
- dataset: Dataset2.isDataset(data) ? data : void 0
13991
+ dataset: Dataset2.isDataset(data) ? data : void 0,
13992
+ parameters
13243
13993
  });
13244
13994
  if (experiment && typeof process !== "undefined" && globalThis.BRAINTRUST_CONTEXT_MANAGER !== void 0) {
13245
13995
  await experiment._waitForId();
@@ -13294,7 +14044,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
13294
14044
  if (experiment) {
13295
14045
  await experiment.flush().catch(console.error);
13296
14046
  } else if (options.parent) {
13297
- await flush().catch(console.error);
14047
+ await flush({ state: evaluator.state }).catch(console.error);
13298
14048
  }
13299
14049
  }
13300
14050
  } finally {
@@ -13663,6 +14413,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
13663
14413
  },
13664
14414
  Math.max(evaluator.maxConcurrency ?? Number.MAX_SAFE_INTEGER, 1)
13665
14415
  );
14416
+ const queueErrors = [];
13666
14417
  const enqueuePromise = (async () => {
13667
14418
  for await (const datum of dataIterable) {
13668
14419
  if (cancelled) {
@@ -13678,7 +14429,11 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
13678
14429
  }
13679
14430
  scheduledTrials++;
13680
14431
  progressReporter.setTotal?.(evaluator.evalName, scheduledTrials);
13681
- q.push({ datum, trialIndex });
14432
+ q.pushAsync({ datum, trialIndex }).catch((e) => {
14433
+ if (queueErrors.length < 5) {
14434
+ queueErrors.push(e);
14435
+ }
14436
+ });
13682
14437
  }
13683
14438
  }
13684
14439
  })();
@@ -13726,6 +14481,12 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
13726
14481
  })();
13727
14482
  try {
13728
14483
  await Promise.race([waitForQueue, cancel()]);
14484
+ if (queueErrors.length > 0) {
14485
+ throw new AggregateError(
14486
+ queueErrors,
14487
+ `Encountered ${queueErrors.length} unhandled task errors`
14488
+ );
14489
+ }
13729
14490
  } catch (e) {
13730
14491
  q.kill();
13731
14492
  if (e instanceof InternalAbortError) {
@@ -14187,23 +14948,6 @@ import { ValidationError } from "ajv";
14187
14948
 
14188
14949
  // src/framework2.ts
14189
14950
  import { z as z13 } from "zod/v3";
14190
-
14191
- // src/zod/utils.ts
14192
- import { zodToJsonSchema as zodToJsonSchemaV3 } from "zod-to-json-schema";
14193
- import * as z42 from "zod/v4";
14194
- function isZodV4(zodObject) {
14195
- return typeof zodObject === "object" && zodObject !== null && "_zod" in zodObject && zodObject._zod !== void 0;
14196
- }
14197
- function zodToJsonSchema(schema) {
14198
- if (isZodV4(schema)) {
14199
- return z42.toJSONSchema(schema, {
14200
- target: "draft-7"
14201
- });
14202
- }
14203
- return zodToJsonSchemaV3(schema);
14204
- }
14205
-
14206
- // src/framework2.ts
14207
14951
  var currentFilename = typeof __filename !== "undefined" ? __filename : "unknown";
14208
14952
  var ProjectBuilder = class {
14209
14953
  create(opts) {
@@ -14409,6 +15153,7 @@ var CodePrompt = class {
14409
15153
  toolFunctions;
14410
15154
  tags;
14411
15155
  metadata;
15156
+ environmentSlugs;
14412
15157
  constructor(project, prompt, toolFunctions, opts, functionType) {
14413
15158
  this.project = project;
14414
15159
  this.name = opts.name;
@@ -14421,6 +15166,7 @@ var CodePrompt = class {
14421
15166
  this.functionType = functionType;
14422
15167
  this.tags = opts.tags;
14423
15168
  this.metadata = opts.metadata;
15169
+ this.environmentSlugs = opts.environments;
14424
15170
  }
14425
15171
  async toFunctionDefinition(projectNameToId) {
14426
15172
  const prompt_data = {
@@ -14455,7 +15201,8 @@ var CodePrompt = class {
14455
15201
  prompt_data,
14456
15202
  if_exists: this.ifExists,
14457
15203
  tags: this.tags,
14458
- metadata: this.metadata
15204
+ metadata: this.metadata,
15205
+ environments: this.environmentSlugs && this.environmentSlugs.length > 0 ? this.environmentSlugs.map((slug) => ({ slug })) : void 0
14459
15206
  };
14460
15207
  }
14461
15208
  };