braintrust 3.20.0 → 3.21.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 (88) hide show
  1. package/NOTICE +20 -0
  2. package/README.md +2 -0
  3. package/dev/dist/index.d.mts +309 -199
  4. package/dev/dist/index.d.ts +309 -199
  5. package/dev/dist/index.js +2826 -983
  6. package/dev/dist/index.mjs +2286 -443
  7. package/dist/apply-auto-instrumentation.js +781 -199
  8. package/dist/apply-auto-instrumentation.mjs +588 -6
  9. package/dist/auto-instrumentations/bundler/esbuild.cjs +594 -2
  10. package/dist/auto-instrumentations/bundler/esbuild.d.mts +2 -2
  11. package/dist/auto-instrumentations/bundler/esbuild.d.ts +2 -2
  12. package/dist/auto-instrumentations/bundler/esbuild.mjs +3 -3
  13. package/dist/auto-instrumentations/bundler/next.cjs +594 -2
  14. package/dist/auto-instrumentations/bundler/next.mjs +4 -4
  15. package/dist/auto-instrumentations/bundler/rollup.cjs +594 -2
  16. package/dist/auto-instrumentations/bundler/rollup.d.mts +2 -2
  17. package/dist/auto-instrumentations/bundler/rollup.d.ts +2 -2
  18. package/dist/auto-instrumentations/bundler/rollup.mjs +3 -3
  19. package/dist/auto-instrumentations/bundler/vite.cjs +594 -2
  20. package/dist/auto-instrumentations/bundler/vite.d.mts +2 -2
  21. package/dist/auto-instrumentations/bundler/vite.d.ts +2 -2
  22. package/dist/auto-instrumentations/bundler/vite.mjs +3 -3
  23. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +593 -9
  24. package/dist/auto-instrumentations/bundler/webpack-loader.d.ts +68 -1
  25. package/dist/auto-instrumentations/bundler/webpack.cjs +594 -2
  26. package/dist/auto-instrumentations/bundler/webpack.d.mts +2 -2
  27. package/dist/auto-instrumentations/bundler/webpack.d.ts +2 -2
  28. package/dist/auto-instrumentations/bundler/webpack.mjs +4 -4
  29. package/dist/auto-instrumentations/{chunk-W4E36GIW.mjs → chunk-BRQX23KL.mjs} +16 -0
  30. package/dist/auto-instrumentations/chunk-M6DLIJ2Z.mjs +784 -0
  31. package/dist/auto-instrumentations/{chunk-K74TZGGM.mjs → chunk-T6J4C7LX.mjs} +1 -1
  32. package/dist/auto-instrumentations/{chunk-S4374IP6.mjs → chunk-TKRPRPGD.mjs} +4 -6
  33. package/dist/auto-instrumentations/chunk-VT6DDNKM.mjs +856 -0
  34. package/dist/auto-instrumentations/hook.mjs +749 -45
  35. package/dist/auto-instrumentations/index.cjs +16 -0
  36. package/dist/auto-instrumentations/index.d.mts +2 -3
  37. package/dist/auto-instrumentations/index.d.ts +2 -3
  38. package/dist/auto-instrumentations/index.mjs +1 -1
  39. package/dist/auto-instrumentations/loader/cjs-patch.cjs +578 -4
  40. package/dist/auto-instrumentations/loader/cjs-patch.d.mts +1 -1
  41. package/dist/auto-instrumentations/loader/cjs-patch.d.ts +1 -1
  42. package/dist/auto-instrumentations/loader/cjs-patch.mjs +3 -7
  43. package/dist/auto-instrumentations/loader/esm-hook.mjs +2 -6
  44. package/dist/auto-instrumentations/{plugin-D7nDswtC.d.mts → plugin-D0KHwSJv.d.mts} +1 -1
  45. package/dist/auto-instrumentations/{plugin-D7nDswtC.d.ts → plugin-G6fgxk1b.d.ts} +1 -1
  46. package/dist/auto-instrumentations/types-RNPaKi9o.d.mts +70 -0
  47. package/dist/auto-instrumentations/types-RNPaKi9o.d.ts +70 -0
  48. package/dist/browser.d.mts +1357 -847
  49. package/dist/browser.d.ts +1357 -847
  50. package/dist/browser.js +2726 -469
  51. package/dist/browser.mjs +2726 -469
  52. package/dist/{chunk-LPC4W2WX.js → chunk-BFGIH2ZJ.js} +4 -0
  53. package/dist/{chunk-POCCIJAL.js → chunk-FY7DAKA5.js} +3141 -1269
  54. package/dist/{chunk-Y7W7WP6H.mjs → chunk-KMGUTPB7.mjs} +4 -0
  55. package/dist/{chunk-F73OMF66.mjs → chunk-O2P765XK.mjs} +2391 -519
  56. package/dist/cli.js +2260 -408
  57. package/dist/edge-light.d.mts +1 -1
  58. package/dist/edge-light.d.ts +1 -1
  59. package/dist/edge-light.js +2726 -469
  60. package/dist/edge-light.mjs +2726 -469
  61. package/dist/index.d.mts +1837 -1327
  62. package/dist/index.d.ts +1837 -1327
  63. package/dist/index.js +752 -353
  64. package/dist/index.mjs +445 -46
  65. package/dist/instrumentation/index.d.mts +107 -19
  66. package/dist/instrumentation/index.d.ts +107 -19
  67. package/dist/instrumentation/index.js +2337 -509
  68. package/dist/instrumentation/index.mjs +2337 -509
  69. package/dist/vitest-evals-reporter.js +16 -16
  70. package/dist/vitest-evals-reporter.mjs +2 -2
  71. package/dist/workerd.d.mts +1 -1
  72. package/dist/workerd.d.ts +1 -1
  73. package/dist/workerd.js +2726 -469
  74. package/dist/workerd.mjs +2726 -469
  75. package/licenses/import-in-the-middle/LICENSE +201 -0
  76. package/licenses/import-in-the-middle/LICENSE-3rdparty.csv +4 -0
  77. package/licenses/import-in-the-middle/NOTICE +34 -0
  78. package/licenses/orchestrion-js/LICENSE +202 -0
  79. package/licenses/orchestrion-js/LICENSE-3rdparty.csv +8 -0
  80. package/licenses/orchestrion-js/NOTICE +3 -0
  81. package/licenses/require-in-the-middle/LICENSE +23 -0
  82. package/package.json +13 -4
  83. package/util/dist/index.d.mts +1 -0
  84. package/util/dist/index.d.ts +1 -0
  85. package/util/dist/index.js +4 -4
  86. package/util/dist/index.mjs +2 -2
  87. package/dist/auto-instrumentations/chunk-J57YF7WS.mjs +0 -208
  88. package/dist/auto-instrumentations/chunk-QFMACSOL.mjs +0 -280
package/dist/browser.mjs CHANGED
@@ -288,8 +288,291 @@ var UUIDGenerator = class extends IDGenerator {
288
288
  return true;
289
289
  }
290
290
  };
291
+ function generateHexId(bytes) {
292
+ let result = "";
293
+ for (let i = 0; i < bytes; i++) {
294
+ result += Math.floor(Math.random() * 256).toString(16).padStart(2, "0");
295
+ }
296
+ return result;
297
+ }
298
+ var OTELIDGenerator = class extends IDGenerator {
299
+ getSpanId() {
300
+ return generateHexId(8);
301
+ }
302
+ getTraceId() {
303
+ return generateHexId(16);
304
+ }
305
+ shareRootSpanId() {
306
+ return false;
307
+ }
308
+ };
309
+ function parseEnvBool(name) {
310
+ const raw = isomorph_default.getEnv(name);
311
+ if (raw === void 0 || raw === null) {
312
+ return false;
313
+ }
314
+ const normalized = raw.trim().toLowerCase();
315
+ return normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "y" || normalized === "on";
316
+ }
317
+ var _warnedLegacyUuidConflict = false;
318
+ function resolveUseLegacyUuidIds() {
319
+ const legacy = parseEnvBool("BRAINTRUST_LEGACY_IDS");
320
+ if (parseEnvBool("BRAINTRUST_OTEL_COMPAT")) {
321
+ if (legacy && !_warnedLegacyUuidConflict) {
322
+ _warnedLegacyUuidConflict = true;
323
+ debugLogger.warn(
324
+ "BRAINTRUST_LEGACY_IDS is ignored because BRAINTRUST_OTEL_COMPAT requires OpenTelemetry-compatible hex span IDs. Using hex IDs."
325
+ );
326
+ }
327
+ return false;
328
+ }
329
+ return legacy;
330
+ }
291
331
  function getIdGenerator() {
292
- return globalThis.BRAINTRUST_ID_GENERATOR !== void 0 ? new globalThis.BRAINTRUST_ID_GENERATOR() : new UUIDGenerator();
332
+ if (globalThis.BRAINTRUST_ID_GENERATOR !== void 0) {
333
+ return new globalThis.BRAINTRUST_ID_GENERATOR();
334
+ }
335
+ return resolveUseLegacyUuidIds() ? new UUIDGenerator() : new OTELIDGenerator();
336
+ }
337
+
338
+ // src/propagation.ts
339
+ var TRACEPARENT_HEADER = "traceparent";
340
+ var TRACESTATE_HEADER = "tracestate";
341
+ var BAGGAGE_HEADER = "baggage";
342
+ var BRAINTRUST_PARENT_KEY = "braintrust.parent";
343
+ var DEFAULT_TRACE_FLAGS = "01";
344
+ var TRACEPARENT_RE = /^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;
345
+ var ZERO_TRACE_ID = "0".repeat(32);
346
+ var ZERO_SPAN_ID = "0".repeat(16);
347
+ var MAX_BAGGAGE_LENGTH = 8192;
348
+ var MAX_BAGGAGE_MEMBERS = 64;
349
+ var _utf8Encoder = new TextEncoder();
350
+ function utf8ByteLength(value) {
351
+ return _utf8Encoder.encode(value).length;
352
+ }
353
+ function capBaggageToMemberBoundary(value) {
354
+ const totalBytes = utf8ByteLength(value);
355
+ const withinBytes = totalBytes <= MAX_BAGGAGE_LENGTH;
356
+ let commaCount = 0;
357
+ for (let i = 0; i < value.length; i++) {
358
+ if (value.charCodeAt(i) === 44) {
359
+ commaCount++;
360
+ }
361
+ }
362
+ const withinMembers = commaCount < MAX_BAGGAGE_MEMBERS;
363
+ if (withinBytes && withinMembers) {
364
+ return value;
365
+ }
366
+ const kept = [];
367
+ let length = 0;
368
+ for (const rawMember of value.split(",")) {
369
+ if (kept.length >= MAX_BAGGAGE_MEMBERS) {
370
+ break;
371
+ }
372
+ const cost = utf8ByteLength(rawMember) + (kept.length ? 1 : 0);
373
+ if (length + cost > MAX_BAGGAGE_LENGTH) {
374
+ break;
375
+ }
376
+ kept.push(rawMember);
377
+ length += cost;
378
+ }
379
+ if (!kept.length) {
380
+ return "";
381
+ }
382
+ return kept.join(",");
383
+ }
384
+ function isTraceContextHeaderTupleArray(value) {
385
+ return Array.isArray(value) && value.every(
386
+ (item) => Array.isArray(item) && typeof item[0] === "string" && typeof item[1] === "string"
387
+ );
388
+ }
389
+ function isListHeader(name) {
390
+ const lowered = name.toLowerCase();
391
+ return lowered === BAGGAGE_HEADER || lowered === TRACESTATE_HEADER;
392
+ }
393
+ function headerValueToString(value, name) {
394
+ if (value === void 0 || value === null) {
395
+ return void 0;
396
+ }
397
+ if (Array.isArray(value)) {
398
+ const stringValues = value.filter((item) => {
399
+ return typeof item === "string";
400
+ });
401
+ if (!stringValues.length) {
402
+ return void 0;
403
+ }
404
+ return isListHeader(name) ? stringValues.join(",") : stringValues[0];
405
+ }
406
+ return typeof value === "string" ? value : String(value);
407
+ }
408
+ function getHeader(headers, name) {
409
+ if (!headers) {
410
+ return void 0;
411
+ }
412
+ if (isTraceContextHeaderTupleArray(headers)) {
413
+ const lowered2 = name.toLowerCase();
414
+ const matches = headers.filter(([key]) => key.toLowerCase() === lowered2).map(([, value]) => value);
415
+ if (!matches.length) {
416
+ return void 0;
417
+ }
418
+ return headerValueToString(matches, name);
419
+ }
420
+ const getter = headers.get;
421
+ if (typeof getter === "function") {
422
+ try {
423
+ const value = headerValueToString(getter.call(headers, name), name);
424
+ if (value !== void 0) {
425
+ return value;
426
+ }
427
+ } catch {
428
+ }
429
+ }
430
+ const nodeGetter = headers.getHeader;
431
+ if (typeof nodeGetter === "function") {
432
+ try {
433
+ const value = headerValueToString(nodeGetter.call(headers, name), name);
434
+ if (value !== void 0) {
435
+ return value;
436
+ }
437
+ } catch {
438
+ }
439
+ }
440
+ const headerBag = headers;
441
+ const exact = headerValueToString(headerBag[name], name);
442
+ if (exact !== void 0) {
443
+ return exact;
444
+ }
445
+ const lowered = name.toLowerCase();
446
+ for (const key of Object.keys(headers)) {
447
+ if (key !== name && key.toLowerCase() === lowered) {
448
+ const value = headerValueToString(headerBag[key], name);
449
+ if (value !== void 0) {
450
+ return value;
451
+ }
452
+ }
453
+ }
454
+ return void 0;
455
+ }
456
+ function isHex(value, length) {
457
+ if (typeof value !== "string" || value.length !== length) {
458
+ return false;
459
+ }
460
+ for (let i = 0; i < value.length; i++) {
461
+ const c = value[i];
462
+ const isDigit = c >= "0" && c <= "9";
463
+ const isLowerHex = c >= "a" && c <= "f";
464
+ if (!isDigit && !isLowerHex) {
465
+ return false;
466
+ }
467
+ }
468
+ return true;
469
+ }
470
+ function parseTraceparent(value) {
471
+ if (!value || typeof value !== "string") {
472
+ return void 0;
473
+ }
474
+ const match = TRACEPARENT_RE.exec(value.trim());
475
+ if (!match) {
476
+ return void 0;
477
+ }
478
+ const traceId = match[1];
479
+ const spanId = match[2];
480
+ const traceFlags = match[3];
481
+ if (traceId === ZERO_TRACE_ID || spanId === ZERO_SPAN_ID) {
482
+ return void 0;
483
+ }
484
+ return { traceId, spanId, traceFlags };
485
+ }
486
+ function formatTraceparent(traceId, spanId, traceFlags = DEFAULT_TRACE_FLAGS) {
487
+ if (!isHex(traceId, 32) || traceId === ZERO_TRACE_ID) {
488
+ return void 0;
489
+ }
490
+ if (!isHex(spanId, 16) || spanId === ZERO_SPAN_ID) {
491
+ return void 0;
492
+ }
493
+ const flags = isHex(traceFlags, 2) ? traceFlags : DEFAULT_TRACE_FLAGS;
494
+ return `00-${traceId}-${spanId}-${flags}`;
495
+ }
496
+ function percentEncode(value) {
497
+ return encodeURIComponent(value);
498
+ }
499
+ function percentDecode(value) {
500
+ if (!value.includes("%")) {
501
+ return value;
502
+ }
503
+ try {
504
+ return decodeURIComponent(value);
505
+ } catch {
506
+ return value;
507
+ }
508
+ }
509
+ function parseBaggage(value) {
510
+ const result = {};
511
+ if (!value || typeof value !== "string") {
512
+ return result;
513
+ }
514
+ const bounded = capBaggageToMemberBoundary(value);
515
+ for (let member of bounded.split(",")) {
516
+ member = member.trim();
517
+ if (!member || !member.includes("=")) {
518
+ continue;
519
+ }
520
+ member = member.split(";", 1)[0];
521
+ const eq = member.indexOf("=");
522
+ const key = percentDecode(member.slice(0, eq).trim());
523
+ const val = member.slice(eq + 1).trim();
524
+ if (!key) {
525
+ continue;
526
+ }
527
+ result[key] = percentDecode(val);
528
+ }
529
+ return result;
530
+ }
531
+ function mergeBaggage(existing, braintrustParent) {
532
+ let btMember = void 0;
533
+ if (braintrustParent) {
534
+ const encodedKey = percentEncode(BRAINTRUST_PARENT_KEY);
535
+ const encodedVal = percentEncode(String(braintrustParent));
536
+ btMember = `${encodedKey}=${encodedVal}`;
537
+ if (utf8ByteLength(btMember) > MAX_BAGGAGE_LENGTH) {
538
+ btMember = void 0;
539
+ }
540
+ }
541
+ let byteBudget = MAX_BAGGAGE_LENGTH;
542
+ let memberBudget = MAX_BAGGAGE_MEMBERS;
543
+ if (btMember !== void 0) {
544
+ byteBudget -= utf8ByteLength(btMember) + 1;
545
+ memberBudget -= 1;
546
+ }
547
+ const relayed = [];
548
+ let length = 0;
549
+ if (existing && typeof existing === "string") {
550
+ for (const rawMember of existing.split(",")) {
551
+ const member = rawMember.trim();
552
+ if (!member || !member.includes("=")) {
553
+ continue;
554
+ }
555
+ const keyPart = member.split(";", 1)[0].split("=", 1)[0];
556
+ const key = percentDecode(keyPart.trim());
557
+ if (key === BRAINTRUST_PARENT_KEY) {
558
+ continue;
559
+ }
560
+ if (relayed.length >= memberBudget) {
561
+ break;
562
+ }
563
+ const cost = utf8ByteLength(member) + (relayed.length ? 1 : 0);
564
+ if (length + cost > byteBudget) {
565
+ break;
566
+ }
567
+ relayed.push(member);
568
+ length += cost;
569
+ }
570
+ }
571
+ const members = btMember !== void 0 ? [...relayed, btMember] : relayed;
572
+ if (!members.length) {
573
+ return void 0;
574
+ }
575
+ return members.join(",");
293
576
  }
294
577
 
295
578
  // util/db_fields.ts
@@ -897,7 +1180,7 @@ var SpanComponentsV3 = class _SpanComponentsV3 {
897
1180
  case 3 /* PLAYGROUND_LOGS */:
898
1181
  return { prompt_session_id: this.data.object_id, log_id: "x" };
899
1182
  default:
900
- const _ = this.data.object_type;
1183
+ this.data.object_type;
901
1184
  throw new Error("Impossible");
902
1185
  }
903
1186
  }
@@ -1426,7 +1709,7 @@ var SpanComponentsV4 = class _SpanComponentsV4 {
1426
1709
  case 3 /* PLAYGROUND_LOGS */:
1427
1710
  return { prompt_session_id: this.data.object_id, log_id: "x" };
1428
1711
  default:
1429
- const _ = this.data.object_type;
1712
+ this.data.object_type;
1430
1713
  throw new Error(`Invalid object_type ${this.data.object_type}`);
1431
1714
  }
1432
1715
  }
@@ -1605,7 +1888,8 @@ var AclObjectType = z6.union([
1605
1888
  "role",
1606
1889
  "org_member",
1607
1890
  "project_log",
1608
- "org_project"
1891
+ "org_project",
1892
+ "org_audit_logs"
1609
1893
  ]),
1610
1894
  z6.null()
1611
1895
  ]);
@@ -1631,6 +1915,17 @@ var Acl = z6.object({
1631
1915
  _object_org_id: z6.string().uuid(),
1632
1916
  created: z6.union([z6.string(), z6.null()]).optional()
1633
1917
  });
1918
+ var Agent = z6.object({
1919
+ id: z6.string().uuid(),
1920
+ project_id: z6.string().uuid(),
1921
+ user_id: z6.string().uuid(),
1922
+ created: z6.union([z6.string(), z6.null()]).optional(),
1923
+ name: z6.string(),
1924
+ slug: z6.string(),
1925
+ kind: z6.string(),
1926
+ description: z6.union([z6.string(), z6.null()]).optional(),
1927
+ metadata: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional()
1928
+ });
1634
1929
  var AISecret = z6.object({
1635
1930
  id: z6.string().uuid(),
1636
1931
  created: z6.union([z6.string(), z6.null()]).optional(),
@@ -1777,6 +2072,7 @@ var AttachmentStatus = z6.object({
1777
2072
  upload_status: UploadStatus,
1778
2073
  error_message: z6.string().optional()
1779
2074
  });
2075
+ var AutomationStatus = z6.enum(["active", "paused"]);
1780
2076
  var FunctionTypeEnum = z6.enum([
1781
2077
  "llm",
1782
2078
  "scorer",
@@ -1822,7 +2118,9 @@ var TopicMapData = z6.object({
1822
2118
  topic_names: z6.record(z6.string()).optional(),
1823
2119
  generation_settings: TopicMapGenerationSettings.optional(),
1824
2120
  disable_reconciliation: z6.boolean().optional(),
1825
- distance_threshold: z6.number().optional()
2121
+ distance_threshold: z6.number().optional(),
2122
+ btql_filter: z6.string().optional(),
2123
+ automation_btql_filter: z6.string().optional()
1826
2124
  });
1827
2125
  var BatchedFacetData = z6.object({
1828
2126
  type: z6.literal("batched_facet"),
@@ -2105,7 +2403,7 @@ var DatasetEvent = z6.object({
2105
2403
  origin: ObjectReferenceNullish.optional(),
2106
2404
  comments: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
2107
2405
  audit_data: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
2108
- facets: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
2406
+ facets: z6.union([z6.record(z6.union([z6.string(), z6.null()])), z6.null()]).optional(),
2109
2407
  classifications: z6.union([
2110
2408
  z6.record(
2111
2409
  z6.array(
@@ -2257,7 +2555,7 @@ var ExperimentEvent = z6.object({
2257
2555
  origin: ObjectReferenceNullish.optional(),
2258
2556
  comments: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
2259
2557
  audit_data: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
2260
- facets: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
2558
+ facets: z6.union([z6.record(z6.union([z6.string(), z6.null()])), z6.null()]).optional(),
2261
2559
  classifications: z6.union([
2262
2560
  z6.record(
2263
2561
  z6.array(
@@ -2395,7 +2693,8 @@ var PromptParserNullish = z6.union([
2395
2693
  use_cot: z6.boolean(),
2396
2694
  choice_scores: z6.record(z6.number().gte(0).lte(1)).optional(),
2397
2695
  choice: z6.array(z6.string()).optional(),
2398
- allow_no_match: z6.boolean().optional()
2696
+ allow_no_match: z6.boolean().optional(),
2697
+ allow_skip: z6.boolean().optional()
2399
2698
  }),
2400
2699
  z6.null()
2401
2700
  ]);
@@ -2725,6 +3024,9 @@ var Group = z6.object({
2725
3024
  var GroupScope = z6.object({
2726
3025
  type: z6.literal("group"),
2727
3026
  group_by: z6.string(),
3027
+ interval_seconds: z6.number().gte(1).optional(),
3028
+ max_traces: z6.number().int().gte(1).lte(64).optional(),
3029
+ placement: z6.enum(["first", "each"]),
2728
3030
  idle_seconds: z6.number().optional()
2729
3031
  });
2730
3032
  var IfExists = z6.enum(["error", "ignore", "replace"]);
@@ -2873,6 +3175,10 @@ var RetentionObjectType = z6.enum([
2873
3175
  "experiment",
2874
3176
  "dataset"
2875
3177
  ]);
3178
+ var TopicAutomationFacetModel = z6.union([
3179
+ z6.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3180
+ z6.null()
3181
+ ]);
2876
3182
  var TopicMapFunctionAutomation = z6.object({
2877
3183
  function: SavedFunctionId.and(z6.unknown()),
2878
3184
  btql_filter: z6.union([z6.string(), z6.null()]).optional()
@@ -2885,7 +3191,9 @@ var TopicAutomationDataScope = z6.union([
2885
3191
  ]);
2886
3192
  var TopicAutomationConfig = z6.object({
2887
3193
  event_type: z6.literal("topic"),
3194
+ status: AutomationStatus.optional(),
2888
3195
  sampling_rate: z6.number().gte(0).lte(1),
3196
+ facet_model: TopicAutomationFacetModel.optional(),
2889
3197
  facet_functions: z6.array(SavedFunctionId),
2890
3198
  topic_map_functions: z6.array(TopicMapFunctionAutomation),
2891
3199
  scope: z6.union([SpanScope, TraceScope, GroupScope, z6.null()]).optional(),
@@ -2899,6 +3207,19 @@ var TopicAutomationConfig = z6.object({
2899
3207
  z6.null()
2900
3208
  ]).optional()
2901
3209
  });
3210
+ var TopicDigestAutomationConfig = z6.object({
3211
+ event_type: z6.literal("topic_digest"),
3212
+ status: AutomationStatus.optional(),
3213
+ window_seconds: z6.number().int().gte(3600).lte(2592e3).optional().default(86400),
3214
+ scheduled_time_minutes_utc: z6.number().int().gte(0).lte(1439),
3215
+ action: z6.object({
3216
+ type: z6.literal("slack"),
3217
+ workspace_id: z6.string(),
3218
+ channel: z6.string(),
3219
+ message_template: z6.string().optional()
3220
+ }),
3221
+ topic_map_function_ids: z6.array(z6.string()).max(10).optional()
3222
+ });
2902
3223
  var ProjectAutomation = z6.object({
2903
3224
  id: z6.string().uuid(),
2904
3225
  project_id: z6.string().uuid(),
@@ -2923,6 +3244,7 @@ var ProjectAutomation = z6.object({
2923
3244
  }),
2924
3245
  z6.object({
2925
3246
  event_type: z6.literal("btql_export"),
3247
+ status: AutomationStatus.optional(),
2926
3248
  export_definition: z6.union([
2927
3249
  z6.object({ type: z6.literal("log_traces") }),
2928
3250
  z6.object({ type: z6.literal("log_spans") }),
@@ -2945,6 +3267,21 @@ var ProjectAutomation = z6.object({
2945
3267
  ]),
2946
3268
  batch_size: z6.union([z6.number(), z6.null()]).optional()
2947
3269
  }),
3270
+ z6.object({
3271
+ event_type: z6.literal("async_query"),
3272
+ status: AutomationStatus.optional(),
3273
+ created_by_user_id: z6.string().uuid(),
3274
+ object_type: z6.enum([
3275
+ "project_logs",
3276
+ "experiment",
3277
+ "dataset",
3278
+ "playground_logs"
3279
+ ]),
3280
+ object_id: z6.string(),
3281
+ query: z6.string(),
3282
+ format: z6.literal("jsonl"),
3283
+ batch_size: z6.union([z6.number(), z6.null()]).optional()
3284
+ }),
2948
3285
  z6.object({
2949
3286
  event_type: z6.literal("retention"),
2950
3287
  object_type: RetentionObjectType,
@@ -2963,7 +3300,8 @@ var ProjectAutomation = z6.object({
2963
3300
  })
2964
3301
  ])
2965
3302
  }),
2966
- TopicAutomationConfig
3303
+ TopicAutomationConfig,
3304
+ TopicDigestAutomationConfig
2967
3305
  ])
2968
3306
  });
2969
3307
  var ProjectLogsEvent = z6.object({
@@ -3002,7 +3340,7 @@ var ProjectLogsEvent = z6.object({
3002
3340
  comments: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
3003
3341
  audit_data: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
3004
3342
  _async_scoring_state: z6.unknown().optional(),
3005
- facets: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
3343
+ facets: z6.union([z6.record(z6.union([z6.string(), z6.null()])), z6.null()]).optional(),
3006
3344
  classifications: z6.union([
3007
3345
  z6.record(
3008
3346
  z6.array(
@@ -3051,11 +3389,34 @@ var ProjectScoreCategories = z6.union([
3051
3389
  z6.array(z6.string()),
3052
3390
  z6.null()
3053
3391
  ]);
3392
+ var ProjectScoreCondition = z6.union([
3393
+ z6.object({
3394
+ when: z6.object({
3395
+ clauses: z6.union([z6.array(z6.string()), z6.null()]),
3396
+ subspan_clauses: z6.union([z6.array(z6.string()), z6.null()]),
3397
+ trace_clauses: z6.union([z6.array(z6.string()), z6.null()])
3398
+ }).partial(),
3399
+ behavior: z6.literal("hidden").optional().default("hidden")
3400
+ }),
3401
+ z6.null()
3402
+ ]);
3054
3403
  var ProjectScoreConfig = z6.union([
3055
3404
  z6.object({
3056
3405
  multi_select: z6.union([z6.boolean(), z6.null()]),
3057
3406
  destination: z6.union([z6.string(), z6.null()]),
3058
- online: OnlineScoreConfig
3407
+ visibility: z6.union([
3408
+ z6.object({
3409
+ users: z6.union([z6.array(z6.string()), z6.null()]),
3410
+ groups: z6.union([z6.array(z6.string()), z6.null()])
3411
+ }).partial(),
3412
+ z6.null()
3413
+ ]),
3414
+ online: OnlineScoreConfig,
3415
+ condition: ProjectScoreCondition,
3416
+ object_types: z6.union([
3417
+ z6.array(z6.enum(["project_logs", "dataset", "experiment"])),
3418
+ z6.null()
3419
+ ])
3059
3420
  }).partial(),
3060
3421
  z6.null()
3061
3422
  ]);
@@ -3240,8 +3601,7 @@ var User = z6.object({
3240
3601
  family_name: z6.union([z6.string(), z6.null()]).optional(),
3241
3602
  email: z6.union([z6.string(), z6.null()]).optional(),
3242
3603
  avatar_url: z6.union([z6.string(), z6.null()]).optional(),
3243
- created: z6.union([z6.string(), z6.null()]).optional(),
3244
- last_active_at: z6.union([z6.number(), z6.null()]).optional()
3604
+ created: z6.union([z6.string(), z6.null()]).optional()
3245
3605
  });
3246
3606
  var ViewDataSearch = z6.union([
3247
3607
  z6.object({
@@ -4530,7 +4890,10 @@ var BraintrustContextManager = class extends ContextManager {
4530
4890
  }
4531
4891
  };
4532
4892
  function getSpanComponentsClass() {
4533
- return globalThis.BRAINTRUST_SPAN_COMPONENT ? globalThis.BRAINTRUST_SPAN_COMPONENT : SpanComponentsV3;
4893
+ if (globalThis.BRAINTRUST_SPAN_COMPONENT) {
4894
+ return globalThis.BRAINTRUST_SPAN_COMPONENT;
4895
+ }
4896
+ return resolveUseLegacyUuidIds() ? SpanComponentsV3 : SpanComponentsV4;
4534
4897
  }
4535
4898
  function getContextManager() {
4536
4899
  return globalThis.BRAINTRUST_CONTEXT_MANAGER ? new globalThis.BRAINTRUST_CONTEXT_MANAGER() : new BraintrustContextManager();
@@ -4566,6 +4929,9 @@ var NoopSpan = class {
4566
4929
  async export() {
4567
4930
  return "";
4568
4931
  }
4932
+ inject(carrier) {
4933
+ return carrier ?? {};
4934
+ }
4569
4935
  async permalink() {
4570
4936
  return NOOP_SPAN_PERMALINK;
4571
4937
  }
@@ -4616,6 +4982,10 @@ var loginSchema = z8.strictObject({
4616
4982
  debugLogLevelDisabled: z8.boolean().optional()
4617
4983
  });
4618
4984
  var stateNonce = 0;
4985
+ var V1_PROXY_SUFFIX = "/v1/proxy";
4986
+ function normalizeProxyConnUrl(proxyUrl) {
4987
+ return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
4988
+ }
4619
4989
  var BraintrustState = class _BraintrustState {
4620
4990
  constructor(loginParams) {
4621
4991
  this.loginParams = loginParams;
@@ -4886,7 +5256,10 @@ var BraintrustState = class _BraintrustState {
4886
5256
  if (!this.proxyUrl) {
4887
5257
  throw new Error("Must initialize proxyUrl before requesting proxyConn");
4888
5258
  }
4889
- this._proxyConn = new HTTPConnection(this.proxyUrl, this.fetch);
5259
+ this._proxyConn = new HTTPConnection(
5260
+ normalizeProxyConnUrl(this.proxyUrl),
5261
+ this.fetch
5262
+ );
4890
5263
  }
4891
5264
  return this._proxyConn;
4892
5265
  }
@@ -5644,7 +6017,7 @@ function updateSpan({
5644
6017
  ...event
5645
6018
  }) {
5646
6019
  const resolvedState = state ?? _globalState;
5647
- const components = getSpanComponentsClass().fromStr(exported);
6020
+ const components = SpanComponentsV4.fromStr(exported);
5648
6021
  if (!components.data.row_id) {
5649
6022
  throw new Error("Exported span must have a row id");
5650
6023
  }
@@ -5744,7 +6117,7 @@ async function permalink(slug, opts) {
5744
6117
  return state.appUrl;
5745
6118
  };
5746
6119
  try {
5747
- const components = getSpanComponentsClass().fromStr(slug);
6120
+ const components = SpanComponentsV4.fromStr(slug);
5748
6121
  const object_type = spanObjectTypeV3ToString(components.data.object_type);
5749
6122
  const [orgName, appUrl, object_id] = await Promise.all([
5750
6123
  getOrgName(),
@@ -5768,35 +6141,47 @@ function startSpanParentArgs(args) {
5768
6141
  let argParentObjectId = void 0;
5769
6142
  let argParentSpanIds = void 0;
5770
6143
  let argPropagatedEvent = void 0;
5771
- if (args.parent) {
6144
+ let argPropagatedState = void 0;
6145
+ const { parentSlug, propagatedState: parentPropagatedState } = normalizeParent(args.parent, args.state);
6146
+ if (parentSlug) {
5772
6147
  if (args.parentSpanIds) {
5773
6148
  throw new Error("Cannot specify both parent and parentSpanIds");
5774
6149
  }
5775
- const parentComponents = getSpanComponentsClass().fromStr(args.parent);
6150
+ const parentComponents = SpanComponentsV4.fromStr(parentSlug);
5776
6151
  if (args.parentObjectType !== parentComponents.data.object_type) {
5777
6152
  throw new Error(
5778
6153
  `Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
5779
6154
  );
5780
6155
  }
5781
6156
  argParentObjectId = args.parentObjectId;
5782
- if (parentComponents.data.row_id) {
6157
+ if (parentComponents.data.row_id && parentSpanIdsUsable(
6158
+ parentComponents.data.span_id,
6159
+ parentComponents.data.root_span_id
6160
+ )) {
5783
6161
  argParentSpanIds = {
5784
6162
  spanId: parentComponents.data.span_id,
5785
6163
  rootSpanId: parentComponents.data.root_span_id
5786
6164
  };
5787
6165
  }
5788
6166
  argPropagatedEvent = args.propagatedEvent ?? (parentComponents.data.propagated_event ?? void 0);
6167
+ const propagatedState = args.propagatedState ?? parentPropagatedState;
6168
+ if (propagatedState) {
6169
+ const { braintrustParent: _ignoredBraintrustParent, ...w3cState } = propagatedState;
6170
+ argPropagatedState = w3cState;
6171
+ }
5789
6172
  } else {
5790
6173
  argParentObjectId = args.parentObjectId;
5791
6174
  argParentSpanIds = args.parentSpanIds;
5792
6175
  argPropagatedEvent = args.propagatedEvent;
6176
+ argPropagatedState = args.propagatedState;
5793
6177
  }
5794
6178
  return {
5795
6179
  parentObjectType: args.parentObjectType,
5796
6180
  parentObjectId: argParentObjectId,
5797
6181
  parentComputeObjectMetadataArgs: args.parentComputeObjectMetadataArgs,
5798
6182
  parentSpanIds: argParentSpanIds,
5799
- propagatedEvent: argPropagatedEvent
6183
+ propagatedEvent: argPropagatedEvent,
6184
+ propagatedState: argPropagatedState
5800
6185
  };
5801
6186
  }
5802
6187
  var Logger = class {
@@ -5997,6 +6382,22 @@ var Logger = class {
5997
6382
  _getLinkBaseUrl() {
5998
6383
  return _getLinkBaseUrl(this.state, this._linkArgs);
5999
6384
  }
6385
+ /**
6386
+ * Return this logger's Braintrust parent string (`project_id:<id>` or
6387
+ * `project_name:<name>`) for the `braintrust.parent` baggage entry, or
6388
+ * undefined when it cannot be determined synchronously.
6389
+ */
6390
+ _getOtelParent() {
6391
+ const id = this.computeMetadataArgs?.project_id || this.lazyId.getSync().value;
6392
+ if (id) {
6393
+ return `project_id:${id}`;
6394
+ }
6395
+ const name = this.computeMetadataArgs?.project_name;
6396
+ if (name) {
6397
+ return `project_name:${name}`;
6398
+ }
6399
+ return void 0;
6400
+ }
6000
6401
  };
6001
6402
  function castLogger(logger, asyncFlush) {
6002
6403
  if (logger === void 0) return void 0;
@@ -6091,12 +6492,12 @@ function stringifyWithOverflowMeta(item) {
6091
6492
  object_ids: pickLogs3OverflowObjectIds(record),
6092
6493
  is_delete: record[OBJECT_DELETE_FIELD] === true,
6093
6494
  input_row: {
6094
- byte_size: utf8ByteLength(str)
6495
+ byte_size: utf8ByteLength2(str)
6095
6496
  }
6096
6497
  }
6097
6498
  };
6098
6499
  }
6099
- function utf8ByteLength(value) {
6500
+ function utf8ByteLength2(value) {
6100
6501
  if (typeof TextEncoder !== "undefined") {
6101
6502
  return new TextEncoder().encode(value).length;
6102
6503
  }
@@ -6484,7 +6885,7 @@ var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
6484
6885
  }) {
6485
6886
  const conn = await this.apiConn.get();
6486
6887
  const dataStr = constructLogs3Data(items);
6487
- const payloadBytes = utf8ByteLength(dataStr);
6888
+ const payloadBytes = utf8ByteLength2(dataStr);
6488
6889
  const useOverflow = canUseOverflow && payloadBytes > maxRequestSize;
6489
6890
  if (this.allPublishPayloadsDir) {
6490
6891
  await _HTTPBackgroundLogger.writePayloadToDir({
@@ -7105,6 +7506,8 @@ function initDataset(projectOrOptions, optionalOptions) {
7105
7506
  const normalizedVersion = selection.version;
7106
7507
  const normalizedEnvironment = selection.environment;
7107
7508
  const normalizedSnapshotName = selection.snapshotName;
7509
+ const cliInternalBtql = globalThis.__bt_eval_internal_btql;
7510
+ const internalBtql = cliInternalBtql === void 0 ? _internal_btql : _internal_btql === void 0 ? cliInternalBtql : isObject(_internal_btql) ? { ...cliInternalBtql, ..._internal_btql } : _internal_btql;
7108
7511
  const state = stateArg ?? _globalState;
7109
7512
  const lazyMetadata = new LazyValue(
7110
7513
  async () => {
@@ -7156,7 +7559,7 @@ function initDataset(projectOrOptions, optionalOptions) {
7156
7559
  lazyMetadata,
7157
7560
  typeof resolvedVersion === "string" ? resolvedVersion : void 0,
7158
7561
  legacy,
7159
- _internal_btql,
7562
+ internalBtql,
7160
7563
  resolvedVersion instanceof LazyValue || normalizedEnvironment !== void 0 || normalizedSnapshotName !== void 0 ? {
7161
7564
  ...resolvedVersion instanceof LazyValue ? {
7162
7565
  lazyPinnedVersion: resolvedVersion
@@ -7620,23 +8023,285 @@ function currentSpan(options) {
7620
8023
  const state = options?.state ?? _globalState;
7621
8024
  return state.contextManager.getCurrentSpan() ?? NOOP_SPAN;
7622
8025
  }
7623
- function getSpanParentObject(options) {
8026
+ function getSpanParentObjectAndPropagatedState(options) {
7624
8027
  const state = options?.state ?? _globalState;
7625
8028
  const parentSpan = currentSpan({ state });
7626
8029
  if (!Object.is(parentSpan, NOOP_SPAN)) {
7627
- return parentSpan;
8030
+ return { parentObject: parentSpan, propagatedState: void 0 };
8031
+ }
8032
+ const parent = options?.parent ?? state.currentParent.getStore();
8033
+ const { parentSlug, propagatedState } = normalizeParent(parent, state);
8034
+ if (parentSlug) {
8035
+ return {
8036
+ parentObject: SpanComponentsV4.fromStr(parentSlug),
8037
+ propagatedState
8038
+ };
7628
8039
  }
7629
- const parentStr = options?.parent ?? state.currentParent.getStore();
7630
- if (parentStr) return getSpanComponentsClass().fromStr(parentStr);
7631
8040
  const experiment = currentExperiment();
7632
8041
  if (experiment) {
7633
- return experiment;
8042
+ return { parentObject: experiment, propagatedState: void 0 };
7634
8043
  }
7635
8044
  const logger = currentLogger(options);
7636
8045
  if (logger) {
7637
- return logger;
8046
+ return { parentObject: logger, propagatedState: void 0 };
8047
+ }
8048
+ return { parentObject: NOOP_SPAN, propagatedState: void 0 };
8049
+ }
8050
+ function getSpanParentObject(options) {
8051
+ return getSpanParentObjectAndPropagatedState(options).parentObject;
8052
+ }
8053
+ function currentBraintrustParent(state) {
8054
+ const resolvedState = state ?? _globalState;
8055
+ const experiment = currentExperiment({ state: resolvedState });
8056
+ if (experiment) {
8057
+ try {
8058
+ return experiment._getOtelParent() ?? void 0;
8059
+ } catch {
8060
+ return void 0;
8061
+ }
8062
+ }
8063
+ const logger = currentLogger({ state: resolvedState });
8064
+ if (logger) {
8065
+ try {
8066
+ return logger._getOtelParent() ?? void 0;
8067
+ } catch {
8068
+ return void 0;
8069
+ }
8070
+ }
8071
+ return void 0;
8072
+ }
8073
+ function braintrustParentToComponents(braintrustParent) {
8074
+ if (!braintrustParent) {
8075
+ return void 0;
8076
+ }
8077
+ if (braintrustParent.startsWith("project_id:")) {
8078
+ const objectId = braintrustParent.slice("project_id:".length);
8079
+ return objectId ? {
8080
+ objectType: 2 /* PROJECT_LOGS */,
8081
+ objectId,
8082
+ computeArgs: void 0
8083
+ } : void 0;
8084
+ }
8085
+ if (braintrustParent.startsWith("project_name:")) {
8086
+ const name = braintrustParent.slice("project_name:".length);
8087
+ return name ? {
8088
+ objectType: 2 /* PROJECT_LOGS */,
8089
+ objectId: void 0,
8090
+ computeArgs: { project_name: name }
8091
+ } : void 0;
8092
+ }
8093
+ if (braintrustParent.startsWith("experiment_id:")) {
8094
+ const objectId = braintrustParent.slice("experiment_id:".length);
8095
+ return objectId ? {
8096
+ objectType: 1 /* EXPERIMENT */,
8097
+ objectId,
8098
+ computeArgs: void 0
8099
+ } : void 0;
8100
+ }
8101
+ return void 0;
8102
+ }
8103
+ function isMutableHeaderTupleArray(carrier) {
8104
+ return Array.isArray(carrier) && carrier.every((item) => Array.isArray(item) && typeof item[0] === "string");
8105
+ }
8106
+ function setHeader(carrier, name, value) {
8107
+ if (isMutableHeaderTupleArray(carrier)) {
8108
+ const lowered2 = name.toLowerCase();
8109
+ for (let i = carrier.length - 1; i >= 0; i--) {
8110
+ if (carrier[i][0].toLowerCase() === lowered2) {
8111
+ carrier.splice(i, 1);
8112
+ }
8113
+ }
8114
+ carrier.push([name, value]);
8115
+ return;
8116
+ }
8117
+ const setter = carrier.set;
8118
+ if (typeof setter === "function") {
8119
+ const deleter = carrier.delete;
8120
+ if (typeof deleter === "function") {
8121
+ try {
8122
+ deleter.call(carrier, name);
8123
+ } catch {
8124
+ }
8125
+ }
8126
+ setter.call(carrier, name, value);
8127
+ return;
8128
+ }
8129
+ const nodeSetter = carrier.setHeader;
8130
+ if (typeof nodeSetter === "function") {
8131
+ const remover = carrier.removeHeader;
8132
+ if (typeof remover === "function") {
8133
+ try {
8134
+ remover.call(carrier, name);
8135
+ } catch {
8136
+ }
8137
+ }
8138
+ nodeSetter.call(carrier, name, value);
8139
+ return;
8140
+ }
8141
+ const headerSetter = carrier.header;
8142
+ if (typeof headerSetter === "function") {
8143
+ const deleter = carrier.delete;
8144
+ if (typeof deleter === "function") {
8145
+ try {
8146
+ deleter.call(carrier, name);
8147
+ } catch {
8148
+ }
8149
+ }
8150
+ const remover = carrier.removeHeader;
8151
+ if (typeof remover === "function") {
8152
+ try {
8153
+ remover.call(carrier, name);
8154
+ } catch {
8155
+ }
8156
+ }
8157
+ headerSetter.call(carrier, name, value);
8158
+ return;
8159
+ }
8160
+ const headerBag = carrier;
8161
+ const lowered = name.toLowerCase();
8162
+ for (const key of Object.keys(headerBag)) {
8163
+ if (key !== name && key.toLowerCase() === lowered) {
8164
+ delete headerBag[key];
8165
+ }
8166
+ }
8167
+ headerBag[name] = value;
8168
+ }
8169
+ function deleteHeader(carrier, name) {
8170
+ const lowered = name.toLowerCase();
8171
+ if (isMutableHeaderTupleArray(carrier)) {
8172
+ for (let i = carrier.length - 1; i >= 0; i--) {
8173
+ if (carrier[i][0].toLowerCase() === lowered) {
8174
+ carrier.splice(i, 1);
8175
+ }
8176
+ }
8177
+ return;
8178
+ }
8179
+ const deleter = carrier.delete;
8180
+ if (typeof deleter === "function") {
8181
+ try {
8182
+ deleter.call(carrier, name);
8183
+ return;
8184
+ } catch {
8185
+ }
8186
+ }
8187
+ const remover = carrier.removeHeader;
8188
+ if (typeof remover === "function") {
8189
+ try {
8190
+ remover.call(carrier, name);
8191
+ return;
8192
+ } catch {
8193
+ }
7638
8194
  }
7639
- return NOOP_SPAN;
8195
+ const headerBag = carrier;
8196
+ for (const key of Object.keys(headerBag)) {
8197
+ if (key.toLowerCase() === lowered) {
8198
+ delete headerBag[key];
8199
+ }
8200
+ }
8201
+ }
8202
+ function _injectIntoCarrier(carrier, args) {
8203
+ const traceFlags = args.propagatedState?.traceFlags;
8204
+ const traceparent = traceFlags ? formatTraceparent(args.traceId, args.spanId, traceFlags) : formatTraceparent(args.traceId, args.spanId);
8205
+ if (traceparent === void 0) {
8206
+ return;
8207
+ }
8208
+ setHeader(carrier, TRACEPARENT_HEADER, traceparent);
8209
+ const tracestate = args.propagatedState?.tracestate;
8210
+ if (tracestate) {
8211
+ setHeader(carrier, TRACESTATE_HEADER, tracestate);
8212
+ }
8213
+ const existing = getHeader(carrier, BAGGAGE_HEADER);
8214
+ const baggageValue = mergeBaggage(existing, args.braintrustParent);
8215
+ if (baggageValue !== void 0) {
8216
+ setHeader(carrier, BAGGAGE_HEADER, baggageValue);
8217
+ } else if (existing !== void 0) {
8218
+ deleteHeader(carrier, BAGGAGE_HEADER);
8219
+ }
8220
+ }
8221
+ function injectTraceContext(carrier, options) {
8222
+ const resolvedCarrier = carrier ?? {};
8223
+ const span = options?.span ?? currentSpan({ state: options?.state });
8224
+ try {
8225
+ return span.inject(resolvedCarrier);
8226
+ } catch (e) {
8227
+ debugLogger.warn(`Error injecting trace context: ${e}`);
8228
+ return resolvedCarrier;
8229
+ }
8230
+ }
8231
+ function extractTraceContextFromHeaders(headers) {
8232
+ if (!headers) {
8233
+ return void 0;
8234
+ }
8235
+ const traceparent = getHeader(headers, TRACEPARENT_HEADER);
8236
+ if (!traceparent || parseTraceparent(traceparent) === void 0) {
8237
+ return void 0;
8238
+ }
8239
+ const context = { [TRACEPARENT_HEADER]: traceparent };
8240
+ const baggageValue = getHeader(headers, BAGGAGE_HEADER);
8241
+ if (baggageValue) {
8242
+ context[BAGGAGE_HEADER] = baggageValue;
8243
+ }
8244
+ const tracestate = getHeader(headers, TRACESTATE_HEADER);
8245
+ if (tracestate) {
8246
+ context[TRACESTATE_HEADER] = tracestate;
8247
+ }
8248
+ return context;
8249
+ }
8250
+ function resolveW3cParent(context, state) {
8251
+ const traceparent = getHeader(context, TRACEPARENT_HEADER);
8252
+ const parsed = traceparent ? parseTraceparent(traceparent) : void 0;
8253
+ if (parsed === void 0) {
8254
+ return { parentSlug: void 0, propagatedState: void 0 };
8255
+ }
8256
+ const { traceId, spanId, traceFlags } = parsed;
8257
+ let braintrustParent = void 0;
8258
+ const baggageValue = getHeader(context, BAGGAGE_HEADER);
8259
+ if (baggageValue) {
8260
+ braintrustParent = parseBaggage(baggageValue)[BRAINTRUST_PARENT_KEY];
8261
+ }
8262
+ if (!braintrustParent) {
8263
+ braintrustParent = currentBraintrustParent(state);
8264
+ }
8265
+ if (!braintrustParent) {
8266
+ debugLogger.warn(
8267
+ "Received traceparent without a braintrust.parent and no active logger/experiment; cannot route the trace. Starting a fresh local span instead."
8268
+ );
8269
+ return { parentSlug: void 0, propagatedState: void 0 };
8270
+ }
8271
+ const parsedParent = braintrustParentToComponents(braintrustParent);
8272
+ if (parsedParent === void 0) {
8273
+ debugLogger.warn(
8274
+ `Invalid braintrust.parent: ${JSON.stringify(braintrustParent)}`
8275
+ );
8276
+ return { parentSlug: void 0, propagatedState: void 0 };
8277
+ }
8278
+ const { objectType, objectId, computeArgs } = parsedParent;
8279
+ const tracestate = getHeader(context, TRACESTATE_HEADER);
8280
+ const slug = new SpanComponentsV4({
8281
+ object_type: objectType,
8282
+ ...computeArgs ? { compute_object_metadata_args: computeArgs } : { object_id: objectId },
8283
+ row_id: "bt-propagation",
8284
+ // non-empty to enable span_id/root_span_id
8285
+ span_id: spanId,
8286
+ root_span_id: traceId
8287
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
8288
+ }).toStr();
8289
+ return {
8290
+ parentSlug: slug,
8291
+ propagatedState: { tracestate, traceFlags, braintrustParent }
8292
+ };
8293
+ }
8294
+ function normalizeParent(parent, state) {
8295
+ if (parent && typeof parent === "object") {
8296
+ return resolveW3cParent(parent, state);
8297
+ }
8298
+ return {
8299
+ parentSlug: parent ?? void 0,
8300
+ propagatedState: void 0
8301
+ };
8302
+ }
8303
+ function parentSpanIdsUsable(spanId, rootSpanId) {
8304
+ return Boolean(spanId) && Boolean(rootSpanId);
7640
8305
  }
7641
8306
  function logError(span, error) {
7642
8307
  let errorMessage = "<error>";
@@ -7844,19 +8509,23 @@ function setFetch(fetch2) {
7844
8509
  }
7845
8510
  function startSpanAndIsLogger(args) {
7846
8511
  const state = args?.state ?? _globalState;
7847
- const parentObject = getSpanParentObject({
8512
+ const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
7848
8513
  asyncFlush: args?.asyncFlush,
7849
8514
  parent: args?.parent,
7850
8515
  state
7851
8516
  });
7852
8517
  if (parentObject instanceof SpanComponentsV3 || parentObject instanceof SpanComponentsV4) {
7853
- const parentSpanIds = parentObject.data.row_id ? {
8518
+ const parentSpanIds = parentObject.data.row_id && parentSpanIdsUsable(
8519
+ parentObject.data.span_id,
8520
+ parentObject.data.root_span_id
8521
+ ) ? {
7854
8522
  spanId: parentObject.data.span_id,
7855
8523
  rootSpanId: parentObject.data.root_span_id
7856
8524
  } : void 0;
8525
+ const { parent: _ignoredParent, ...spanArgs } = args ?? {};
7857
8526
  const span = new SpanImpl({
7858
8527
  state,
7859
- ...args,
8528
+ ...spanArgs,
7860
8529
  parentObjectType: parentObject.data.object_type,
7861
8530
  parentObjectId: new LazyValue(
7862
8531
  spanComponentsToObjectIdLambda(state, parentObject)
@@ -7864,7 +8533,8 @@ function startSpanAndIsLogger(args) {
7864
8533
  parentComputeObjectMetadataArgs: parentObject.data.compute_object_metadata_args ?? void 0,
7865
8534
  parentSpanIds,
7866
8535
  propagatedEvent: args?.propagatedEvent ?? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
7867
- (parentObject.data.propagated_event ?? void 0)
8536
+ (parentObject.data.propagated_event ?? void 0),
8537
+ propagatedState
7868
8538
  });
7869
8539
  return {
7870
8540
  span,
@@ -8153,11 +8823,12 @@ function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
8153
8823
  var DEFAULT_FETCH_BATCH_SIZE = 1e3;
8154
8824
  var MAX_BTQL_ITERATIONS = 1e4;
8155
8825
  var ObjectFetcher = class {
8156
- constructor(objectType, pinnedVersion, mutateRecord, _internal_btql) {
8826
+ constructor(objectType, pinnedVersion, mutateRecord, _internal_btql, _internalBrainstoreRealtime = true) {
8157
8827
  this.objectType = objectType;
8158
8828
  this.pinnedVersion = pinnedVersion;
8159
8829
  this.mutateRecord = mutateRecord;
8160
8830
  this._internal_btql = _internal_btql;
8831
+ this._internalBrainstoreRealtime = _internalBrainstoreRealtime;
8161
8832
  }
8162
8833
  _fetchedData = void 0;
8163
8834
  get id() {
@@ -8216,7 +8887,7 @@ var ObjectFetcher = class {
8216
8887
  ...internalBtqlWithoutReservedQueryKeys
8217
8888
  },
8218
8889
  use_columnstore: false,
8219
- brainstore_realtime: true,
8890
+ brainstore_realtime: this._internalBrainstoreRealtime,
8220
8891
  query_source: `js_sdk_object_fetcher_${this.objectType}`,
8221
8892
  ...this.pinnedVersion !== void 0 ? {
8222
8893
  version: this.pinnedVersion
@@ -8565,6 +9236,15 @@ View complete results in Braintrust or run experiment.summarize() again.`
8565
9236
  object_id: await this.id
8566
9237
  }).toStr();
8567
9238
  }
9239
+ /**
9240
+ * Return this experiment's Braintrust parent string (`experiment_id:<id>`) for
9241
+ * the `braintrust.parent` baggage entry, or undefined when it cannot be
9242
+ * determined synchronously.
9243
+ */
9244
+ _getOtelParent() {
9245
+ const id = this.lazyId.getSync().value;
9246
+ return id ? `experiment_id:${id}` : void 0;
9247
+ }
8568
9248
  /**
8569
9249
  * Flush any pending rows to the server.
8570
9250
  */
@@ -8607,7 +9287,8 @@ var ReadonlyExperiment = class extends ObjectFetcher {
8607
9287
  async *asDataset(options) {
8608
9288
  const records = this.fetch(options);
8609
9289
  for await (const record of records) {
8610
- if (record.root_span_id !== record.span_id) {
9290
+ const isRoot = record.is_root ?? record.root_span_id === record.span_id;
9291
+ if (!isRoot) {
8611
9292
  continue;
8612
9293
  }
8613
9294
  const { output, expected: expectedRecord, metadata } = record;
@@ -8669,9 +9350,16 @@ var SpanImpl = class _SpanImpl {
8669
9350
  _spanId;
8670
9351
  _rootSpanId;
8671
9352
  _spanParents;
9353
+ // Inbound W3C trace-context state (tracestate + raw traceparent flags) to
9354
+ // forward on outbound propagation. Captured at the span that received it (via
9355
+ // extractTraceContextFromHeaders) and inherited by all subspans, so that any
9356
+ // inject() within the trace re-emits the upstream state unchanged, per the W3C
9357
+ // Trace Context spec. Not interpreted.
9358
+ _propagatedState;
8672
9359
  kind = "span";
8673
9360
  constructor(args) {
8674
9361
  this._state = args.state;
9362
+ this._propagatedState = args.propagatedState;
8675
9363
  const spanAttributes = args.spanAttributes ?? {};
8676
9364
  const rawEvent = args.event ?? {};
8677
9365
  const type = args.type ?? (args.parentSpanIds ? void 0 : args.defaultRootType);
@@ -8787,7 +9475,7 @@ var SpanImpl = class _SpanImpl {
8787
9475
  tags: partialRecord.tags,
8788
9476
  span_id: this._spanId,
8789
9477
  span_parents: this._spanParents,
8790
- is_root: this._spanId === this._rootSpanId,
9478
+ is_root: !this._spanParents || this._spanParents.length === 0,
8791
9479
  span_attributes: partialRecord.span_attributes
8792
9480
  };
8793
9481
  this._state.spanCache.queueWrite(
@@ -8849,7 +9537,8 @@ var SpanImpl = class _SpanImpl {
8849
9537
  parentObjectId: this.parentObjectId,
8850
9538
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
8851
9539
  parentSpanIds,
8852
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
9540
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
9541
+ propagatedState: this._propagatedState
8853
9542
  })
8854
9543
  });
8855
9544
  }
@@ -8868,7 +9557,8 @@ var SpanImpl = class _SpanImpl {
8868
9557
  parentObjectId: this.parentObjectId,
8869
9558
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
8870
9559
  parentSpanIds,
8871
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
9560
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
9561
+ propagatedState: this._propagatedState
8872
9562
  }),
8873
9563
  spanId
8874
9564
  });
@@ -8896,6 +9586,42 @@ var SpanImpl = class _SpanImpl {
8896
9586
  propagated_event: this.propagatedEvent
8897
9587
  }).toStr();
8898
9588
  }
9589
+ /**
9590
+ * Return this span's Braintrust parent string (`project_id:<id>`,
9591
+ * `project_name:<name>`, or `experiment_id:<id>`) for the `braintrust.parent`
9592
+ * baggage entry, or undefined when it cannot be determined synchronously.
9593
+ */
9594
+ _getOtelParent() {
9595
+ if (this.parentObjectType === 2 /* PROJECT_LOGS */) {
9596
+ const id = this.parentComputeObjectMetadataArgs?.project_id || this.parentObjectId.getSync().value;
9597
+ const name = this.parentComputeObjectMetadataArgs?.project_name;
9598
+ if (id) {
9599
+ return `project_id:${id}`;
9600
+ } else if (name) {
9601
+ return `project_name:${name}`;
9602
+ }
9603
+ } else if (this.parentObjectType === 1 /* EXPERIMENT */) {
9604
+ const id = this.parentComputeObjectMetadataArgs?.experiment_id || this.parentObjectId.getSync().value;
9605
+ if (id) {
9606
+ return `experiment_id:${id}`;
9607
+ }
9608
+ }
9609
+ return void 0;
9610
+ }
9611
+ inject(carrier) {
9612
+ const resolvedCarrier = carrier ?? {};
9613
+ try {
9614
+ _injectIntoCarrier(resolvedCarrier, {
9615
+ traceId: this._rootSpanId,
9616
+ spanId: this._spanId,
9617
+ braintrustParent: this._getOtelParent() ?? this._propagatedState?.braintrustParent,
9618
+ propagatedState: this._propagatedState
9619
+ });
9620
+ } catch (e) {
9621
+ debugLogger.warn(`Error injecting trace context: ${e}`);
9622
+ }
9623
+ return resolvedCarrier;
9624
+ }
8899
9625
  async permalink() {
8900
9626
  return await permalink(await this.export(), {
8901
9627
  state: this._state
@@ -9031,6 +9757,7 @@ var Dataset2 = class extends ObjectFetcher {
9031
9757
  _internal_btql
9032
9758
  );
9033
9759
  this.state = state;
9760
+ void this.__braintrust_dataset_marker;
9034
9761
  this.lazyMetadata = lazyMetadata;
9035
9762
  this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
9036
9763
  this.pinnedEnvironment = pinState?.pinnedEnvironment;
@@ -9548,6 +10275,7 @@ var Prompt2 = class _Prompt {
9548
10275
  this.metadata = metadata;
9549
10276
  this.defaults = defaults;
9550
10277
  this.noTrace = noTrace;
10278
+ void this.__braintrust_prompt_marker;
9551
10279
  }
9552
10280
  parsedPromptData;
9553
10281
  hasParsedPromptData = false;
@@ -9784,6 +10512,7 @@ var Prompt2 = class _Prompt {
9784
10512
  var RemoteEvalParameters = class {
9785
10513
  constructor(metadata) {
9786
10514
  this.metadata = metadata;
10515
+ void this.__braintrust_parameters_marker;
9787
10516
  }
9788
10517
  __braintrust_parameters_marker = true;
9789
10518
  get id() {
@@ -9920,6 +10649,7 @@ var _exportsForTestingOnly = {
9920
10649
  isAsyncGeneratorFunction,
9921
10650
  resetIdGenStateForTests,
9922
10651
  validateTags,
10652
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9923
10653
  isomorph: isomorph_default
9924
10654
  // Expose isomorph for build type detection
9925
10655
  };
@@ -10748,6 +11478,22 @@ function runStreamingCompletionHook(args) {
10748
11478
  );
10749
11479
  }
10750
11480
  }
11481
+ function runStreamingErrorHook(args) {
11482
+ if (!args.config.onError) {
11483
+ return;
11484
+ }
11485
+ try {
11486
+ args.config.onError({
11487
+ channelName: args.channelName,
11488
+ error: args.error,
11489
+ event: args.event,
11490
+ span: args.span,
11491
+ startTime: args.startTime
11492
+ });
11493
+ } catch (error) {
11494
+ debugLogger.error(`Error in onError hook for ${args.channelName}:`, error);
11495
+ }
11496
+ }
10751
11497
  function traceAsyncChannel(channel2, config) {
10752
11498
  const tracingChannel2 = channel2.tracingChannel();
10753
11499
  const states = /* @__PURE__ */ new WeakMap();
@@ -10909,6 +11655,14 @@ function traceStreamingChannel(channel2, config) {
10909
11655
  }
10910
11656
  },
10911
11657
  onError: (error) => {
11658
+ runStreamingErrorHook({
11659
+ channelName,
11660
+ config,
11661
+ error,
11662
+ event: asyncEndEvent,
11663
+ span,
11664
+ startTime
11665
+ });
10912
11666
  span.log({
10913
11667
  error: error.message
10914
11668
  });
@@ -10966,6 +11720,17 @@ function traceStreamingChannel(channel2, config) {
10966
11720
  }
10967
11721
  },
10968
11722
  error: (event) => {
11723
+ const spanData = states.get(event);
11724
+ if (spanData) {
11725
+ runStreamingErrorHook({
11726
+ channelName,
11727
+ config,
11728
+ error: event.error,
11729
+ event,
11730
+ span: spanData.span,
11731
+ startTime: spanData.startTime
11732
+ });
11733
+ }
10969
11734
  logErrorAndEnd(states, event);
10970
11735
  }
10971
11736
  };
@@ -13328,14 +14093,45 @@ function serializeAISDKToolsForLogging(tools) {
13328
14093
  return serialized;
13329
14094
  }
13330
14095
 
14096
+ // src/vendor-sdk-types/ai-sdk-v7-telemetry.ts
14097
+ var BRAINTRUST_AI_SDK_V7_OPERATION_KEY = /* @__PURE__ */ Symbol.for(
14098
+ "braintrust.ai-sdk.v7.telemetry-operation-key"
14099
+ );
14100
+
14101
+ // src/wrappers/ai-sdk/workflow-agent-context.ts
14102
+ var workflowAgentWrapperSpans = /* @__PURE__ */ new Map();
14103
+ function registerWorkflowAgentWrapperSpan(span) {
14104
+ if (span.spanId) {
14105
+ workflowAgentWrapperSpans.set(span.spanId, span);
14106
+ }
14107
+ }
14108
+ function unregisterWorkflowAgentWrapperSpan(span) {
14109
+ if (span.spanId) {
14110
+ workflowAgentWrapperSpans.delete(span.spanId);
14111
+ }
14112
+ }
14113
+ function currentWorkflowAgentWrapperSpan() {
14114
+ const parentSpanIds = _internalGetGlobalState().contextManager.getParentSpanIds()?.spanParents ?? [];
14115
+ for (const parentSpanId of parentSpanIds) {
14116
+ const span = workflowAgentWrapperSpans.get(parentSpanId);
14117
+ if (span) {
14118
+ return span;
14119
+ }
14120
+ }
14121
+ return void 0;
14122
+ }
14123
+
13331
14124
  // src/wrappers/ai-sdk/telemetry.ts
13332
14125
  function braintrustAISDKTelemetry() {
13333
14126
  const operations = /* @__PURE__ */ new Map();
14127
+ const operationKeysByCallId = /* @__PURE__ */ new Map();
14128
+ const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
13334
14129
  const modelSpans = /* @__PURE__ */ new Map();
13335
14130
  const objectSpans = /* @__PURE__ */ new Map();
13336
14131
  const embedSpans = /* @__PURE__ */ new Map();
13337
14132
  const rerankSpans = /* @__PURE__ */ new Map();
13338
14133
  const toolSpans = /* @__PURE__ */ new Map();
14134
+ let workflowAgentOperationCounter = 0;
13339
14135
  const runSafely = (name, callback) => {
13340
14136
  try {
13341
14137
  callback();
@@ -13343,42 +14139,333 @@ function braintrustAISDKTelemetry() {
13343
14139
  console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error);
13344
14140
  }
13345
14141
  };
13346
- const startChildSpan = (callId, name, type, event) => {
13347
- const parent = operations.get(callId)?.span;
14142
+ const startChildSpan = (operationKey, name, type, event) => {
14143
+ const parent = operations.get(operationKey)?.span;
13348
14144
  const spanArgs = {
13349
14145
  name,
13350
14146
  spanAttributes: { type },
13351
14147
  ...event ? { event } : {}
13352
14148
  };
13353
14149
  const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
13354
- const state = operations.get(callId);
14150
+ const state = operations.get(operationKey);
13355
14151
  if (state && type === "llm" /* LLM */) {
13356
14152
  state.hadModelChild = true;
13357
14153
  }
13358
14154
  return span;
13359
14155
  };
14156
+ const registerOperation = (state) => {
14157
+ operations.set(state.operationKey, state);
14158
+ const keys = operationKeysByCallId.get(state.callId) ?? [];
14159
+ keys.push(state.operationKey);
14160
+ operationKeysByCallId.set(state.callId, keys);
14161
+ };
14162
+ const deleteOperation = (operationKey) => {
14163
+ const state = operations.get(operationKey);
14164
+ if (!state) {
14165
+ return;
14166
+ }
14167
+ operations.delete(operationKey);
14168
+ if (workflowOperationKeyStore.getStore() === operationKey) {
14169
+ workflowOperationKeyStore.enterWith(void 0);
14170
+ }
14171
+ const keys = operationKeysByCallId.get(state.callId);
14172
+ if (!keys) {
14173
+ return;
14174
+ }
14175
+ const index = keys.indexOf(operationKey);
14176
+ if (index >= 0) {
14177
+ keys.splice(index, 1);
14178
+ }
14179
+ if (keys.length === 0) {
14180
+ operationKeysByCallId.delete(state.callId);
14181
+ }
14182
+ };
14183
+ const explicitOperationKey = (event) => {
14184
+ if (!isObject(event)) {
14185
+ return void 0;
14186
+ }
14187
+ const key = event[BRAINTRUST_AI_SDK_V7_OPERATION_KEY];
14188
+ return typeof key === "string" ? key : void 0;
14189
+ };
14190
+ const createOperationKey = (event, operationName) => {
14191
+ const explicit = explicitOperationKey(event);
14192
+ if (explicit) {
14193
+ return explicit;
14194
+ }
14195
+ if (operationName === "WorkflowAgent.stream") {
14196
+ workflowAgentOperationCounter += 1;
14197
+ return `${event.callId}:${workflowAgentOperationCounter}`;
14198
+ }
14199
+ return event.callId;
14200
+ };
14201
+ const operationKeyForCallId = (callId, mode = "active") => {
14202
+ const keys = operationKeysByCallId.get(callId);
14203
+ if (!keys || keys.length === 0) {
14204
+ return operations.has(callId) ? callId : void 0;
14205
+ }
14206
+ if (keys.length === 1) {
14207
+ return keys[0];
14208
+ }
14209
+ const wrapperSpan = currentWorkflowAgentWrapperSpan();
14210
+ if (wrapperSpan?.spanId) {
14211
+ const key = keys.find(
14212
+ (candidate) => operations.get(candidate)?.span.spanId === wrapperSpan.spanId
14213
+ );
14214
+ if (key) {
14215
+ return key;
14216
+ }
14217
+ }
14218
+ const workflowOperationKey = workflowOperationKeyStore.getStore();
14219
+ if (workflowOperationKey && keys.includes(workflowOperationKey)) {
14220
+ return workflowOperationKey;
14221
+ }
14222
+ if (callId === "workflow-agent") {
14223
+ return void 0;
14224
+ }
14225
+ return mode === "finish" ? keys[0] : keys[keys.length - 1];
14226
+ };
14227
+ const operationKeyFromEvent = (event, mode = "active") => {
14228
+ const explicit = explicitOperationKey(event);
14229
+ if (explicit && operations.has(explicit)) {
14230
+ return explicit;
14231
+ }
14232
+ if (isObject(event)) {
14233
+ const callId = event.callId;
14234
+ if (typeof callId === "string") {
14235
+ const operationKey = operationKeyForCallId(callId, mode);
14236
+ if (operationKey) {
14237
+ return operationKey;
14238
+ }
14239
+ const workflowOperationKey2 = workflowOperationKeyStore.getStore();
14240
+ if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
14241
+ return workflowOperationKey2;
14242
+ }
14243
+ return callId === "workflow-agent" ? void 0 : callId;
14244
+ }
14245
+ }
14246
+ const workflowOperationKey = workflowOperationKeyStore.getStore();
14247
+ if (workflowOperationKey && operations.has(workflowOperationKey)) {
14248
+ return workflowOperationKey;
14249
+ }
14250
+ const wrapperSpan = currentWorkflowAgentWrapperSpan();
14251
+ if (wrapperSpan?.spanId) {
14252
+ for (const [operationKey, state] of operations) {
14253
+ if (state.operationName === "WorkflowAgent.stream" && state.span.spanId === wrapperSpan.spanId) {
14254
+ return operationKey;
14255
+ }
14256
+ }
14257
+ }
14258
+ const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
14259
+ if (workflowAgentKeys?.length === 1) {
14260
+ return workflowAgentKeys[0];
14261
+ }
14262
+ if (operations.size === 1) {
14263
+ return operations.keys().next().value;
14264
+ }
14265
+ return void 0;
14266
+ };
14267
+ const closeOpenChildSpans = (operationKey, error) => {
14268
+ const openModelSpans = modelSpans.get(operationKey);
14269
+ if (openModelSpans) {
14270
+ for (const span of openModelSpans) {
14271
+ if (error !== void 0) {
14272
+ logError(span, error);
14273
+ }
14274
+ span.end();
14275
+ }
14276
+ modelSpans.delete(operationKey);
14277
+ }
14278
+ const openObjectSpan = objectSpans.get(operationKey);
14279
+ if (openObjectSpan) {
14280
+ if (error !== void 0) {
14281
+ logError(openObjectSpan, error);
14282
+ }
14283
+ openObjectSpan.end();
14284
+ objectSpans.delete(operationKey);
14285
+ }
14286
+ for (const [embedCallId, embedState] of embedSpans) {
14287
+ if (embedState.operationKey === operationKey) {
14288
+ if (error !== void 0) {
14289
+ logError(embedState.span, error);
14290
+ }
14291
+ embedState.span.end();
14292
+ embedSpans.delete(embedCallId);
14293
+ }
14294
+ }
14295
+ const openRerankSpan = rerankSpans.get(operationKey);
14296
+ if (openRerankSpan) {
14297
+ if (error !== void 0) {
14298
+ logError(openRerankSpan, error);
14299
+ }
14300
+ openRerankSpan.end();
14301
+ rerankSpans.delete(operationKey);
14302
+ }
14303
+ for (const [toolCallId, toolState] of toolSpans) {
14304
+ if (toolState.operationKey === operationKey) {
14305
+ if (error !== void 0) {
14306
+ logError(toolState.span, error);
14307
+ }
14308
+ toolState.span.end();
14309
+ toolSpans.delete(toolCallId);
14310
+ }
14311
+ }
14312
+ };
14313
+ const abortReasonFromEvent = (event) => {
14314
+ if (isObject(event)) {
14315
+ const abortEvent = event;
14316
+ if (abortEvent.error !== void 0) {
14317
+ return abortEvent.error;
14318
+ }
14319
+ if (abortEvent.reason !== void 0) {
14320
+ return abortEvent.reason;
14321
+ }
14322
+ }
14323
+ return new Error("AI SDK operation aborted");
14324
+ };
14325
+ const shouldSkipTelemetryChildren = (state) => state?.operationName === "WorkflowAgent.stream" && !state.ownsSpan;
14326
+ const onObjectStepEnd = (event) => {
14327
+ runSafely("onObjectStepEnd", () => {
14328
+ const operationKey = operationKeyFromEvent(event);
14329
+ const span = operationKey ? objectSpans.get(operationKey) : void 0;
14330
+ if (!operationKey || !span) {
14331
+ return;
14332
+ }
14333
+ const result = {
14334
+ ...event,
14335
+ text: event.objectText
14336
+ };
14337
+ span.log({
14338
+ ...shouldRecordOutputs(event) ? {
14339
+ output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
14340
+ } : {},
14341
+ metrics: extractTokenMetrics(result)
14342
+ });
14343
+ span.end();
14344
+ objectSpans.delete(operationKey);
14345
+ });
14346
+ };
14347
+ const onEmbedEnd = (event) => {
14348
+ runSafely("onEmbedEnd", () => {
14349
+ const state = embedSpans.get(event.embedCallId);
14350
+ if (!state) {
14351
+ return;
14352
+ }
14353
+ const result = {
14354
+ ...event,
14355
+ embeddings: event.embeddings
14356
+ };
14357
+ state.span.log({
14358
+ ...shouldRecordOutputs(event) ? {
14359
+ output: processAISDKEmbeddingOutput(
14360
+ result,
14361
+ DEFAULT_DENY_OUTPUT_PATHS
14362
+ )
14363
+ } : {},
14364
+ metrics: extractTokenMetrics(result)
14365
+ });
14366
+ state.span.end();
14367
+ embedSpans.delete(event.embedCallId);
14368
+ });
14369
+ };
14370
+ const onRerankEnd = (event) => {
14371
+ runSafely("onRerankEnd", () => {
14372
+ const operationKey = operationKeyFromEvent(event);
14373
+ const span = operationKey ? rerankSpans.get(operationKey) : void 0;
14374
+ if (!operationKey || !span) {
14375
+ return;
14376
+ }
14377
+ const result = {
14378
+ ranking: event.ranking?.map((entry) => ({
14379
+ originalIndex: entry.index,
14380
+ score: entry.relevanceScore
14381
+ }))
14382
+ };
14383
+ span.log({
14384
+ ...shouldRecordOutputs(event) ? {
14385
+ output: processAISDKRerankOutput(
14386
+ result,
14387
+ DEFAULT_DENY_OUTPUT_PATHS
14388
+ )
14389
+ } : {}
14390
+ });
14391
+ span.end();
14392
+ rerankSpans.delete(operationKey);
14393
+ });
14394
+ };
14395
+ const onEnd = (event) => {
14396
+ runSafely("onEnd", () => {
14397
+ const operationKey = operationKeyFromEvent(event, "finish");
14398
+ const state = operationKey ? operations.get(operationKey) : void 0;
14399
+ if (!state) {
14400
+ return;
14401
+ }
14402
+ if (!state.ownsSpan) {
14403
+ deleteOperation(state.operationKey);
14404
+ return;
14405
+ }
14406
+ const result = finishResult(event, state.operationName);
14407
+ const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
14408
+ const timeToFirstToken = state.operationName === "WorkflowAgent.stream" ? void 0 : extractTimeToFirstToken(result, state);
14409
+ if (timeToFirstToken !== void 0) {
14410
+ metrics.time_to_first_token = timeToFirstToken;
14411
+ }
14412
+ state.span.log({
14413
+ ...shouldRecordOutputs(event) ? {
14414
+ output: finishOutput(result, state.operationName)
14415
+ } : {},
14416
+ metrics
14417
+ });
14418
+ state.span.end();
14419
+ deleteOperation(state.operationKey);
14420
+ });
14421
+ };
13360
14422
  return {
13361
14423
  onStart(event) {
13362
14424
  runSafely("onStart", () => {
13363
14425
  const operationName = operationNameFromId(event.operationId);
13364
- const span = startSpan({
14426
+ const workflowAgent = operationName === "WorkflowAgent.stream";
14427
+ const wrapperSpan = workflowAgent ? currentWorkflowAgentWrapperSpan() : void 0;
14428
+ const ownsSpan = !wrapperSpan;
14429
+ const span = ownsSpan ? startSpan({
13365
14430
  name: operationName,
13366
14431
  spanAttributes: { type: "function" /* FUNCTION */ }
13367
- });
13368
- operations.set(event.callId, {
14432
+ }) : wrapperSpan;
14433
+ const operationKey = createOperationKey(event, operationName);
14434
+ registerOperation({
14435
+ callId: event.callId,
13369
14436
  hadModelChild: false,
14437
+ loggedInput: false,
13370
14438
  operationName,
14439
+ operationKey,
14440
+ ownsSpan,
13371
14441
  span,
13372
14442
  startTime: getCurrentUnixTimestamp()
13373
14443
  });
13374
- const metadata = metadataFromEvent(event);
14444
+ if (!ownsSpan) {
14445
+ return;
14446
+ }
14447
+ if (workflowAgent) {
14448
+ workflowOperationKeyStore.enterWith(operationKey);
14449
+ }
14450
+ let metadata = metadataFromEvent(event);
13375
14451
  const logPayload = { metadata };
14452
+ const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
14453
+ if (workflowAgentCallInput) {
14454
+ metadata = {
14455
+ ...metadata,
14456
+ ...extractWorkflowMetadataFromCallParams(workflowAgentCallInput)
14457
+ };
14458
+ logPayload.metadata = metadata;
14459
+ }
13376
14460
  if (shouldRecordInputs(event)) {
13377
- const { input, outputPromise } = processAISDKCallInput(
13378
- operationInput(event, operationName)
13379
- );
14461
+ const callInput = workflowAgentCallInput ?? operationInput(event, operationName);
14462
+ const { input, outputPromise } = workflowAgent ? processAISDKWorkflowAgentCallInput(callInput) : processAISDKCallInput(callInput);
13380
14463
  logPayload.input = input;
13381
- if (outputPromise && input && typeof input === "object") {
14464
+ const state = operations.get(operationKey);
14465
+ if (state) {
14466
+ state.loggedInput = hasPromptLikeInput(input);
14467
+ }
14468
+ if (outputPromise && !workflowAgent && input && typeof input === "object") {
13382
14469
  outputPromise.then((resolvedData) => {
13383
14470
  span.log({
13384
14471
  input: {
@@ -13395,41 +14482,67 @@ function braintrustAISDKTelemetry() {
13395
14482
  },
13396
14483
  onLanguageModelCallStart(event) {
13397
14484
  runSafely("onLanguageModelCallStart", () => {
13398
- const state = operations.get(event.callId);
13399
- const openSpans = modelSpans.get(event.callId);
13400
- if (openSpans) {
14485
+ const operationKey = operationKeyFromEvent(event);
14486
+ const state = operationKey ? operations.get(operationKey) : void 0;
14487
+ if (shouldSkipTelemetryChildren(state)) {
14488
+ return;
14489
+ }
14490
+ const operationName = state?.operationName ?? "generateText";
14491
+ const callInput = operationInput(event, operationName);
14492
+ const workflowAgent = operationName === "WorkflowAgent.stream";
14493
+ const processedInput = shouldRecordInputs(event) && workflowAgent ? processAISDKWorkflowAgentModelCallInput(callInput).input : shouldRecordInputs(event) ? processAISDKCallInput(callInput).input : void 0;
14494
+ if (workflowAgent && state?.ownsSpan && !state.loggedInput && hasPromptLikeInput(processedInput)) {
14495
+ state.span.log({
14496
+ input: processedInput,
14497
+ metadata: {
14498
+ ...metadataFromEvent(event),
14499
+ ...extractWorkflowMetadataFromCallParams(callInput)
14500
+ }
14501
+ });
14502
+ state.loggedInput = true;
14503
+ }
14504
+ const openSpans = operationKey ? modelSpans.get(operationKey) : void 0;
14505
+ if (operationKey && openSpans) {
13401
14506
  for (const span2 of openSpans) {
13402
14507
  span2.end();
13403
14508
  }
13404
- modelSpans.delete(event.callId);
14509
+ modelSpans.delete(operationKey);
13405
14510
  }
13406
14511
  const span = startChildSpan(
13407
- event.callId,
13408
- state?.operationName === "streamText" ? "doStream" : "doGenerate",
14512
+ operationKey ?? event.callId,
14513
+ operationName === "streamText" ? "doStream" : "doGenerate",
13409
14514
  "llm" /* LLM */,
13410
14515
  {
13411
14516
  ...shouldRecordInputs(event) ? {
13412
- input: processAISDKCallInput(
13413
- operationInput(
13414
- event,
13415
- state?.operationName ?? "generateText"
13416
- )
13417
- ).input
14517
+ input: processedInput
13418
14518
  } : {},
13419
- metadata: metadataFromEvent(event)
14519
+ metadata: workflowAgent ? {
14520
+ ...metadataFromEvent(event),
14521
+ ...extractWorkflowMetadataFromCallParams(callInput)
14522
+ } : metadataFromEvent(event)
13420
14523
  }
13421
14524
  );
13422
- const spans = modelSpans.get(event.callId) ?? [];
14525
+ const spanKey = operationKey ?? event.callId;
14526
+ const spans = modelSpans.get(spanKey) ?? [];
13423
14527
  spans.push(span);
13424
- modelSpans.set(event.callId, spans);
14528
+ modelSpans.set(spanKey, spans);
13425
14529
  });
13426
14530
  },
13427
14531
  onLanguageModelCallEnd(event) {
13428
14532
  runSafely("onLanguageModelCallEnd", () => {
13429
- const span = shiftModelSpan(modelSpans, event.callId);
14533
+ const operationKey = operationKeyFromEvent(event);
14534
+ const state = operationKey ? operations.get(operationKey) : void 0;
14535
+ if (shouldSkipTelemetryChildren(state)) {
14536
+ return;
14537
+ }
14538
+ const span = operationKey ? shiftModelSpan(modelSpans, operationKey) : void 0;
13430
14539
  if (!span) {
13431
14540
  return;
13432
14541
  }
14542
+ const timeToFirstOutputMs = safePerformance(event)?.timeToFirstOutputMs;
14543
+ if (state?.operationName === "streamText" && state.firstChunkTime === void 0 && typeof timeToFirstOutputMs === "number") {
14544
+ state.firstChunkTime = state.startTime + timeToFirstOutputMs / 1e3;
14545
+ }
13433
14546
  const result = {
13434
14547
  ...event,
13435
14548
  response: event.responseId ? { id: event.responseId } : void 0
@@ -13445,14 +14558,18 @@ function braintrustAISDKTelemetry() {
13445
14558
  },
13446
14559
  onObjectStepStart(event) {
13447
14560
  runSafely("onObjectStepStart", () => {
13448
- const state = operations.get(event.callId);
13449
- const openSpan = objectSpans.get(event.callId);
13450
- if (openSpan) {
14561
+ const operationKey = operationKeyFromEvent(event);
14562
+ const state = operationKey ? operations.get(operationKey) : void 0;
14563
+ if (shouldSkipTelemetryChildren(state)) {
14564
+ return;
14565
+ }
14566
+ const openSpan = operationKey ? objectSpans.get(operationKey) : void 0;
14567
+ if (operationKey && openSpan) {
13451
14568
  openSpan.end();
13452
- objectSpans.delete(event.callId);
14569
+ objectSpans.delete(operationKey);
13453
14570
  }
13454
14571
  const span = startChildSpan(
13455
- event.callId,
14572
+ operationKey ?? event.callId,
13456
14573
  state?.operationName === "streamObject" ? "doStream" : "doGenerate",
13457
14574
  "llm" /* LLM */,
13458
14575
  {
@@ -13464,40 +14581,25 @@ function braintrustAISDKTelemetry() {
13464
14581
  metadata: metadataFromEvent(event)
13465
14582
  }
13466
14583
  );
13467
- objectSpans.set(event.callId, span);
13468
- });
13469
- },
13470
- onObjectStepFinish(event) {
13471
- runSafely("onObjectStepFinish", () => {
13472
- const span = objectSpans.get(event.callId);
13473
- if (!span) {
13474
- return;
13475
- }
13476
- const result = {
13477
- ...event,
13478
- text: event.objectText
13479
- };
13480
- span.log({
13481
- ...shouldRecordOutputs(event) ? {
13482
- output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
13483
- } : {},
13484
- metrics: extractTokenMetrics(result)
13485
- });
13486
- span.end();
13487
- objectSpans.delete(event.callId);
14584
+ objectSpans.set(operationKey ?? event.callId, span);
13488
14585
  });
13489
14586
  },
14587
+ onObjectStepEnd,
13490
14588
  onEmbedStart(event) {
13491
14589
  runSafely("onEmbedStart", () => {
13492
- const state = operations.get(event.callId);
14590
+ const operationKey = operationKeyFromEvent(event);
14591
+ const state = operationKey ? operations.get(operationKey) : void 0;
14592
+ if (shouldSkipTelemetryChildren(state)) {
14593
+ return;
14594
+ }
13493
14595
  for (const [embedCallId, embedState] of embedSpans) {
13494
- if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
14596
+ if (embedState.operationKey === operationKey && (state?.operationName === "embed" || embedState.values === event.values)) {
13495
14597
  embedState.span.end();
13496
14598
  embedSpans.delete(embedCallId);
13497
14599
  }
13498
14600
  }
13499
14601
  const span = startChildSpan(
13500
- event.callId,
14602
+ operationKey ?? event.callId,
13501
14603
  "doEmbed",
13502
14604
  "llm" /* LLM */,
13503
14605
  {
@@ -13510,44 +14612,27 @@ function braintrustAISDKTelemetry() {
13510
14612
  }
13511
14613
  );
13512
14614
  embedSpans.set(event.embedCallId, {
13513
- callId: event.callId,
14615
+ operationKey: operationKey ?? event.callId,
13514
14616
  span,
13515
14617
  values: event.values
13516
14618
  });
13517
14619
  });
13518
14620
  },
13519
- onEmbedFinish(event) {
13520
- runSafely("onEmbedFinish", () => {
13521
- const state = embedSpans.get(event.embedCallId);
13522
- if (!state) {
13523
- return;
13524
- }
13525
- const result = {
13526
- ...event,
13527
- embeddings: event.embeddings
13528
- };
13529
- state.span.log({
13530
- ...shouldRecordOutputs(event) ? {
13531
- output: processAISDKEmbeddingOutput(
13532
- result,
13533
- DEFAULT_DENY_OUTPUT_PATHS
13534
- )
13535
- } : {},
13536
- metrics: extractTokenMetrics(result)
13537
- });
13538
- state.span.end();
13539
- embedSpans.delete(event.embedCallId);
13540
- });
13541
- },
14621
+ onEmbedEnd,
13542
14622
  onRerankStart(event) {
13543
14623
  runSafely("onRerankStart", () => {
13544
- const openSpan = rerankSpans.get(event.callId);
13545
- if (openSpan) {
14624
+ const operationKey = operationKeyFromEvent(event);
14625
+ const state = operationKey ? operations.get(operationKey) : void 0;
14626
+ if (shouldSkipTelemetryChildren(state)) {
14627
+ return;
14628
+ }
14629
+ const openSpan = operationKey ? rerankSpans.get(operationKey) : void 0;
14630
+ if (operationKey && openSpan) {
13546
14631
  openSpan.end();
13547
- rerankSpans.delete(event.callId);
14632
+ rerankSpans.delete(operationKey);
13548
14633
  }
13549
14634
  const span = startChildSpan(
13550
- event.callId,
14635
+ operationKey ?? event.callId,
13551
14636
  "doRerank",
13552
14637
  "llm" /* LLM */,
13553
14638
  {
@@ -13561,41 +14646,23 @@ function braintrustAISDKTelemetry() {
13561
14646
  metadata: metadataFromEvent(event)
13562
14647
  }
13563
14648
  );
13564
- rerankSpans.set(event.callId, span);
13565
- });
13566
- },
13567
- onRerankFinish(event) {
13568
- runSafely("onRerankFinish", () => {
13569
- const span = rerankSpans.get(event.callId);
13570
- if (!span) {
13571
- return;
13572
- }
13573
- const result = {
13574
- ranking: event.ranking?.map((entry) => ({
13575
- originalIndex: entry.index,
13576
- score: entry.relevanceScore
13577
- }))
13578
- };
13579
- span.log({
13580
- ...shouldRecordOutputs(event) ? {
13581
- output: processAISDKRerankOutput(
13582
- result,
13583
- DEFAULT_DENY_OUTPUT_PATHS
13584
- )
13585
- } : {}
13586
- });
13587
- span.end();
13588
- rerankSpans.delete(event.callId);
14649
+ rerankSpans.set(operationKey ?? event.callId, span);
13589
14650
  });
13590
14651
  },
14652
+ onRerankEnd,
13591
14653
  onToolExecutionStart(event) {
13592
14654
  runSafely("onToolExecutionStart", () => {
14655
+ const operationKey = operationKeyFromEvent(event);
14656
+ const state = operationKey ? operations.get(operationKey) : void 0;
14657
+ if (shouldSkipTelemetryChildren(state)) {
14658
+ return;
14659
+ }
13593
14660
  const toolCallId = event.toolCall.toolCallId;
13594
- if (!toolCallId) {
14661
+ if (!operationKey || !toolCallId) {
13595
14662
  return;
13596
14663
  }
13597
14664
  const span = startChildSpan(
13598
- event.callId,
14665
+ operationKey,
13599
14666
  event.toolCall.toolName || "tool",
13600
14667
  "tool" /* TOOL */,
13601
14668
  {
@@ -13609,7 +14676,7 @@ function braintrustAISDKTelemetry() {
13609
14676
  }
13610
14677
  }
13611
14678
  );
13612
- toolSpans.set(toolCallId, { callId: event.callId, span });
14679
+ toolSpans.set(toolCallId, { operationKey, span });
13613
14680
  });
13614
14681
  },
13615
14682
  onToolExecutionEnd(event) {
@@ -13620,14 +14687,17 @@ function braintrustAISDKTelemetry() {
13620
14687
  return;
13621
14688
  }
13622
14689
  const toolOutput = event.toolOutput;
13623
- if (toolOutput?.type === "tool-error") {
14690
+ const workflowToolError = event.success === false && "error" in event ? event.error : void 0;
14691
+ if (toolOutput?.type === "tool-error" || workflowToolError !== void 0) {
14692
+ const error = toolOutput?.error ?? workflowToolError;
13624
14693
  state.span.log({
13625
- error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
14694
+ error: error instanceof Error ? error.message : String(error),
13626
14695
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
13627
14696
  });
13628
14697
  } else {
14698
+ const output = toolOutput && "output" in toolOutput ? toolOutput.output : event.output;
13629
14699
  state.span.log({
13630
- ...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
14700
+ ...shouldRecordOutputs(event) ? { output } : {},
13631
14701
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
13632
14702
  });
13633
14703
  }
@@ -13641,83 +14711,46 @@ function braintrustAISDKTelemetry() {
13641
14711
  if (!callId) {
13642
14712
  return;
13643
14713
  }
13644
- const state = operations.get(callId);
14714
+ const operationKey = operationKeyForCallId(callId);
14715
+ const state = operationKey ? operations.get(operationKey) : void 0;
13645
14716
  if (!state || state.firstChunkTime !== void 0) {
13646
14717
  return;
13647
14718
  }
13648
14719
  state.firstChunkTime = getCurrentUnixTimestamp();
13649
14720
  });
13650
14721
  },
13651
- onFinish(event) {
13652
- runSafely("onFinish", () => {
13653
- const state = operations.get(event.callId);
13654
- if (!state) {
14722
+ onEnd,
14723
+ onAbort(event) {
14724
+ runSafely("onAbort", () => {
14725
+ const operationKey = operationKeyFromEvent(event, "finish");
14726
+ const state = operationKey ? operations.get(operationKey) : void 0;
14727
+ if (!operationKey || !state) {
13655
14728
  return;
13656
14729
  }
13657
- const result = finishResult(event, state.operationName);
13658
- const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
13659
- if (state.firstChunkTime !== void 0) {
13660
- metrics.time_to_first_token = state.firstChunkTime - state.startTime;
14730
+ const error = abortReasonFromEvent(event);
14731
+ closeOpenChildSpans(operationKey, error);
14732
+ if (state.ownsSpan) {
14733
+ logError(state.span, error);
14734
+ state.span.end();
13661
14735
  }
13662
- state.span.log({
13663
- ...shouldRecordOutputs(event) ? {
13664
- output: finishOutput(result, state.operationName)
13665
- } : {},
13666
- metrics
13667
- });
13668
- state.span.end();
13669
- operations.delete(event.callId);
14736
+ deleteOperation(operationKey);
13670
14737
  });
13671
14738
  },
13672
14739
  onError(event) {
13673
14740
  runSafely("onError", () => {
13674
14741
  const errorEvent = isObject(event) ? event : {};
13675
- const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
13676
- if (!callId) {
13677
- return;
13678
- }
13679
- const state = operations.get(callId);
13680
- if (!state) {
14742
+ const operationKey = operationKeyFromEvent(errorEvent, "finish");
14743
+ const state = operationKey ? operations.get(operationKey) : void 0;
14744
+ if (!operationKey || !state) {
13681
14745
  return;
13682
14746
  }
13683
14747
  const error = errorEvent.error ?? event;
13684
- const openModelSpans = modelSpans.get(callId);
13685
- if (openModelSpans) {
13686
- for (const span of openModelSpans) {
13687
- logError(span, error);
13688
- span.end();
13689
- }
13690
- modelSpans.delete(callId);
13691
- }
13692
- const openObjectSpan = objectSpans.get(callId);
13693
- if (openObjectSpan) {
13694
- logError(openObjectSpan, error);
13695
- openObjectSpan.end();
13696
- objectSpans.delete(callId);
13697
- }
13698
- for (const [embedCallId, embedState] of embedSpans) {
13699
- if (embedState.callId === callId) {
13700
- logError(embedState.span, error);
13701
- embedState.span.end();
13702
- embedSpans.delete(embedCallId);
13703
- }
13704
- }
13705
- const openRerankSpan = rerankSpans.get(callId);
13706
- if (openRerankSpan) {
13707
- logError(openRerankSpan, error);
13708
- openRerankSpan.end();
13709
- rerankSpans.delete(callId);
13710
- }
13711
- for (const [toolCallId, toolState] of toolSpans) {
13712
- if (toolState.callId === callId) {
13713
- logError(toolState.span, error);
13714
- toolState.span.end();
13715
- toolSpans.delete(toolCallId);
13716
- }
14748
+ closeOpenChildSpans(operationKey, error);
14749
+ if (state.ownsSpan) {
14750
+ logError(state.span, error);
14751
+ state.span.end();
13717
14752
  }
13718
- logError(state.span, error);
13719
- state.span.end();
13720
- operations.delete(callId);
14753
+ deleteOperation(operationKey);
13721
14754
  });
13722
14755
  },
13723
14756
  executeTool({ toolCallId, execute }) {
@@ -13732,7 +14765,16 @@ function shouldRecordInputs(event) {
13732
14765
  function shouldRecordOutputs(event) {
13733
14766
  return event.recordOutputs !== false;
13734
14767
  }
14768
+ function hasPromptLikeInput(input) {
14769
+ if (!isObject(input)) {
14770
+ return false;
14771
+ }
14772
+ return input.prompt !== void 0 || input.messages !== void 0;
14773
+ }
13735
14774
  function operationNameFromId(operationId) {
14775
+ if (operationId === "ai.workflowAgent.stream") {
14776
+ return "WorkflowAgent.stream";
14777
+ }
13736
14778
  return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
13737
14779
  }
13738
14780
  function modelFromEvent(event) {
@@ -13778,6 +14820,7 @@ function operationInput(event, operationName) {
13778
14820
  }
13779
14821
  return {
13780
14822
  model: modelFromEvent(event),
14823
+ instructions: event.instructions,
13781
14824
  system: event.system,
13782
14825
  prompt: event.prompt,
13783
14826
  messages: event.messages,
@@ -13826,6 +14869,30 @@ function finishResult(event, operationName) {
13826
14869
  }
13827
14870
  return event;
13828
14871
  }
14872
+ function extractTimeToFirstToken(result, state) {
14873
+ if (state.firstChunkTime !== void 0) {
14874
+ return state.firstChunkTime - state.startTime;
14875
+ }
14876
+ const performanceCandidates = [
14877
+ safePerformance(result),
14878
+ safePerformance(result.finalStep),
14879
+ ...Array.isArray(result.steps) ? (result.steps ?? []).map(safePerformance) : []
14880
+ ];
14881
+ for (const performance2 of performanceCandidates) {
14882
+ const timeToFirstOutputMs = performance2?.timeToFirstOutputMs;
14883
+ if (typeof timeToFirstOutputMs === "number") {
14884
+ return timeToFirstOutputMs / 1e3;
14885
+ }
14886
+ }
14887
+ return void 0;
14888
+ }
14889
+ function safePerformance(value) {
14890
+ if (!isObject(value)) {
14891
+ return void 0;
14892
+ }
14893
+ const performance2 = value.performance;
14894
+ return isObject(performance2) ? performance2 : void 0;
14895
+ }
13829
14896
  function finishOutput(result, operationName) {
13830
14897
  if (operationName === "embed" || operationName === "embedMany") {
13831
14898
  return processAISDKEmbeddingOutput(
@@ -13902,6 +14969,10 @@ var aiSDKChannels = defineChannels("ai", {
13902
14969
  channelName: "ToolLoopAgent.stream",
13903
14970
  kind: "async"
13904
14971
  }),
14972
+ workflowAgentStream: channel({
14973
+ channelName: "WorkflowAgent.stream",
14974
+ kind: "async"
14975
+ }),
13905
14976
  v7CreateTelemetryDispatcher: channel({
13906
14977
  channelName: "createTelemetryDispatcher",
13907
14978
  kind: "sync-stream"
@@ -13912,14 +14983,19 @@ var aiSDKChannels = defineChannels("ai", {
13912
14983
  var DEFAULT_DENY_OUTPUT_PATHS = [
13913
14984
  // v3
13914
14985
  "roundtrips[].request.body",
14986
+ "roundtrips[].request.headers",
13915
14987
  "roundtrips[].response.headers",
13916
14988
  "rawResponse.headers",
13917
14989
  "responseMessages",
13918
14990
  // v5
13919
14991
  "request.body",
14992
+ "request.headers",
14993
+ "responses[].headers",
13920
14994
  "response.body",
13921
14995
  "response.headers",
13922
14996
  "steps[].request.body",
14997
+ "steps[].request.headers",
14998
+ "steps[].responses[].headers",
13923
14999
  "steps[].response.body",
13924
15000
  "steps[].response.headers"
13925
15001
  ];
@@ -13931,6 +15007,18 @@ var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
13931
15007
  var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
13932
15008
  "braintrust.ai-sdk.deny-output-paths"
13933
15009
  );
15010
+ var aiSDKV7TelemetryOperationCounter = 0;
15011
+ var TRANSPORT_PAYLOAD_ROOT_PATHS = [
15012
+ "rawResponse",
15013
+ "request",
15014
+ "response",
15015
+ "responses[]",
15016
+ "roundtrips[].request",
15017
+ "roundtrips[].response",
15018
+ "steps[].request",
15019
+ "steps[].response",
15020
+ "steps[].responses[]"
15021
+ ];
13934
15022
  var AI_SDK_V7_TELEMETRY_CALLBACKS = [
13935
15023
  "onStart",
13936
15024
  "onStepStart",
@@ -13939,14 +15027,16 @@ var AI_SDK_V7_TELEMETRY_CALLBACKS = [
13939
15027
  "onToolExecutionStart",
13940
15028
  "onToolExecutionEnd",
13941
15029
  "onChunk",
15030
+ "onStepEnd",
13942
15031
  "onStepFinish",
13943
15032
  "onObjectStepStart",
13944
- "onObjectStepFinish",
15033
+ "onObjectStepEnd",
13945
15034
  "onEmbedStart",
13946
- "onEmbedFinish",
15035
+ "onEmbedEnd",
13947
15036
  "onRerankStart",
13948
- "onRerankFinish",
13949
- "onFinish",
15037
+ "onRerankEnd",
15038
+ "onEnd",
15039
+ "onAbort",
13950
15040
  "onError"
13951
15041
  ];
13952
15042
  var AISDKPlugin = class extends BasePlugin {
@@ -14104,7 +15194,9 @@ var AISDKPlugin = class extends BasePlugin {
14104
15194
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
14105
15195
  name: "Agent.generate",
14106
15196
  type: "function" /* FUNCTION */,
14107
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15197
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15198
+ agentOwner: true
15199
+ }),
14108
15200
  extractOutput: (result, endEvent) => {
14109
15201
  finalizeAISDKChildTracing(endEvent);
14110
15202
  return processAISDKOutput(
@@ -14120,7 +15212,9 @@ var AISDKPlugin = class extends BasePlugin {
14120
15212
  traceStreamingChannel(aiSDKChannels.agentStream, {
14121
15213
  name: "Agent.stream",
14122
15214
  type: "function" /* FUNCTION */,
14123
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15215
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15216
+ agentOwner: true
15217
+ }),
14124
15218
  extractOutput: (result, endEvent) => processAISDKOutput(
14125
15219
  result,
14126
15220
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -14140,7 +15234,9 @@ var AISDKPlugin = class extends BasePlugin {
14140
15234
  traceSyncStreamChannel(aiSDKChannels.agentStreamSync, {
14141
15235
  name: "Agent.stream",
14142
15236
  type: "function" /* FUNCTION */,
14143
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15237
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15238
+ agentOwner: true
15239
+ }),
14144
15240
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
14145
15241
  defaultDenyOutputPaths: denyOutputPaths,
14146
15242
  endEvent,
@@ -14154,7 +15250,9 @@ var AISDKPlugin = class extends BasePlugin {
14154
15250
  traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
14155
15251
  name: "ToolLoopAgent.generate",
14156
15252
  type: "function" /* FUNCTION */,
14157
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15253
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15254
+ agentOwner: true
15255
+ }),
14158
15256
  extractOutput: (result, endEvent) => {
14159
15257
  finalizeAISDKChildTracing(endEvent);
14160
15258
  return processAISDKOutput(
@@ -14170,7 +15268,9 @@ var AISDKPlugin = class extends BasePlugin {
14170
15268
  traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
14171
15269
  name: "ToolLoopAgent.stream",
14172
15270
  type: "function" /* FUNCTION */,
14173
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15271
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
15272
+ agentOwner: true
15273
+ }),
14174
15274
  extractOutput: (result, endEvent) => processAISDKOutput(
14175
15275
  result,
14176
15276
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -14186,6 +15286,42 @@ var AISDKPlugin = class extends BasePlugin {
14186
15286
  })
14187
15287
  })
14188
15288
  );
15289
+ this.unsubscribers.push(
15290
+ traceStreamingChannel(aiSDKChannels.workflowAgentStream, {
15291
+ name: "WorkflowAgent.stream",
15292
+ type: "function" /* FUNCTION */,
15293
+ extractInput: ([params], event, span) => prepareAISDKWorkflowAgentStreamInput(
15294
+ params,
15295
+ event,
15296
+ span,
15297
+ denyOutputPaths
15298
+ ),
15299
+ extractOutput: (result, endEvent) => {
15300
+ finalizeAISDKChildTracing(endEvent);
15301
+ return processAISDKOutput(
15302
+ result,
15303
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
15304
+ );
15305
+ },
15306
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
15307
+ aggregateChunks: aggregateAISDKChunks,
15308
+ onComplete: ({ span }) => {
15309
+ unregisterWorkflowAgentWrapperSpan(span);
15310
+ },
15311
+ onError: ({ event, span }) => {
15312
+ finalizeAISDKChildTracing(event);
15313
+ unregisterWorkflowAgentWrapperSpan(span);
15314
+ },
15315
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
15316
+ defaultDenyOutputPaths: denyOutputPaths,
15317
+ endEvent,
15318
+ onComplete: () => unregisterWorkflowAgentWrapperSpan(span),
15319
+ result,
15320
+ span,
15321
+ startTime
15322
+ })
15323
+ })
15324
+ );
14189
15325
  }
14190
15326
  };
14191
15327
  function subscribeToAISDKV7TelemetryDispatcher() {
@@ -14197,7 +15333,11 @@ function subscribeToAISDKV7TelemetryDispatcher() {
14197
15333
  if (telemetryOptions?.isEnabled === false) {
14198
15334
  return;
14199
15335
  }
14200
- patchAISDKV7TelemetryDispatcher(event.result, telemetry);
15336
+ patchAISDKV7TelemetryDispatcher(
15337
+ event.result,
15338
+ telemetry,
15339
+ telemetryOptions
15340
+ );
14201
15341
  }
14202
15342
  };
14203
15343
  channel2.subscribe(handlers);
@@ -14205,7 +15345,7 @@ function subscribeToAISDKV7TelemetryDispatcher() {
14205
15345
  channel2.unsubscribe(handlers);
14206
15346
  };
14207
15347
  }
14208
- function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
15348
+ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
14209
15349
  if (!isObject(dispatcher)) {
14210
15350
  return;
14211
15351
  }
@@ -14214,6 +15354,54 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14214
15354
  return;
14215
15355
  }
14216
15356
  dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true;
15357
+ let operationKey;
15358
+ const telemetryEventFields = {};
15359
+ if (typeof telemetryOptions?.recordInputs === "boolean") {
15360
+ telemetryEventFields.recordInputs = telemetryOptions.recordInputs;
15361
+ }
15362
+ if (typeof telemetryOptions?.recordOutputs === "boolean") {
15363
+ telemetryEventFields.recordOutputs = telemetryOptions.recordOutputs;
15364
+ }
15365
+ if (typeof telemetryOptions?.functionId === "string") {
15366
+ telemetryEventFields.functionId = telemetryOptions.functionId;
15367
+ }
15368
+ const eventWithOperationKey = (event) => {
15369
+ if (!isObject(event)) {
15370
+ return event;
15371
+ }
15372
+ const eventRecord = event;
15373
+ const callId = typeof eventRecord.callId === "string" ? eventRecord.callId : "unknown";
15374
+ operationKey ??= `${callId}:${++aiSDKV7TelemetryOperationCounter}`;
15375
+ if (Object.keys(telemetryEventFields).length > 0) {
15376
+ const augmentedEvent = {
15377
+ ...telemetryEventFields,
15378
+ ...event
15379
+ };
15380
+ try {
15381
+ Object.defineProperty(augmentedEvent, BRAINTRUST_AI_SDK_V7_OPERATION_KEY, {
15382
+ configurable: true,
15383
+ enumerable: false,
15384
+ value: operationKey
15385
+ });
15386
+ } catch {
15387
+ augmentedEvent[BRAINTRUST_AI_SDK_V7_OPERATION_KEY] = operationKey;
15388
+ }
15389
+ return augmentedEvent;
15390
+ }
15391
+ try {
15392
+ Object.defineProperty(eventRecord, BRAINTRUST_AI_SDK_V7_OPERATION_KEY, {
15393
+ configurable: true,
15394
+ enumerable: false,
15395
+ value: operationKey
15396
+ });
15397
+ return event;
15398
+ } catch {
15399
+ return {
15400
+ ...event,
15401
+ [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey
15402
+ };
15403
+ }
15404
+ };
14217
15405
  for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
14218
15406
  const braintrustCallback = telemetry[key];
14219
15407
  if (typeof braintrustCallback !== "function") {
@@ -14222,11 +15410,17 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14222
15410
  const existingCallback = dispatcherRecord[key];
14223
15411
  dispatcherRecord[key] = (event) => {
14224
15412
  const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
14225
- const braintrustResult = braintrustCallback.call(telemetry, event);
14226
- const pending = [existingResult, braintrustResult].filter(isPromiseLike);
14227
- if (pending.length > 0) {
14228
- return Promise.allSettled(pending).then(() => void 0);
15413
+ try {
15414
+ const braintrustResult = braintrustCallback.call(
15415
+ telemetry,
15416
+ eventWithOperationKey(event)
15417
+ );
15418
+ if (isPromiseLike(braintrustResult)) {
15419
+ void Promise.resolve(braintrustResult).catch(() => void 0);
15420
+ }
15421
+ } catch {
14229
15422
  }
15423
+ return existingResult;
14230
15424
  };
14231
15425
  }
14232
15426
  const braintrustExecuteTool = telemetry.executeTool;
@@ -14236,6 +15430,7 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
14236
15430
  const existingExecuteTool = dispatcherRecord.executeTool;
14237
15431
  dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
14238
15432
  ...args,
15433
+ ...operationKey ? { [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey } : {},
14239
15434
  execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
14240
15435
  });
14241
15436
  }
@@ -14334,6 +15529,8 @@ var serializeOutputObject = (output, model) => {
14334
15529
  var processInputAttachmentsSync = (input) => {
14335
15530
  if (!input) return { input };
14336
15531
  const processed = { ...input };
15532
+ delete processed.headers;
15533
+ delete processed.experimental_output;
14337
15534
  if (input.messages && Array.isArray(input.messages)) {
14338
15535
  processed.messages = input.messages.map(processMessage);
14339
15536
  }
@@ -14367,10 +15564,10 @@ var processInputAttachmentsSync = (input) => {
14367
15564
  processed.output = serialized;
14368
15565
  }
14369
15566
  }
14370
- if ("prepareCall" in processed && typeof processed.prepareCall === "function") {
14371
- processed.prepareCall = "[Function]";
14372
- }
14373
- return { input: processed, outputPromise };
15567
+ return {
15568
+ input: sanitizeAISDKCallInputValue(processed),
15569
+ outputPromise
15570
+ };
14374
15571
  };
14375
15572
  var processMessage = (message) => {
14376
15573
  if (!message || typeof message !== "object") return message;
@@ -14534,7 +15731,21 @@ var convertDataToAttachment = (data, mimeType, filename) => {
14534
15731
  function processAISDKCallInput(params) {
14535
15732
  return processInputAttachmentsSync(params);
14536
15733
  }
14537
- function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
15734
+ function processAISDKWorkflowAgentCallInput(params) {
15735
+ const processed = processAISDKCallInput(params);
15736
+ return {
15737
+ ...processed,
15738
+ input: extractWorkflowAgentInput(processed.input)
15739
+ };
15740
+ }
15741
+ function processAISDKWorkflowAgentModelCallInput(params) {
15742
+ const processed = processAISDKCallInput(params);
15743
+ return {
15744
+ ...processed,
15745
+ input: extractWorkflowAgentModelInput(processed.input)
15746
+ };
15747
+ }
15748
+ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths, childTracingOptions = {}) {
14538
15749
  const { input, outputPromise } = processAISDKCallInput(params);
14539
15750
  if (outputPromise && input && typeof input === "object") {
14540
15751
  outputPromise.then((resolvedData) => {
@@ -14553,7 +15764,29 @@ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
14553
15764
  event.self,
14554
15765
  span,
14555
15766
  defaultDenyOutputPaths,
14556
- event.aiSDK
15767
+ event.aiSDK,
15768
+ childTracingOptions
15769
+ );
15770
+ event.modelWrapped = childTracing.modelWrapped;
15771
+ if (childTracing.cleanup) {
15772
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
15773
+ }
15774
+ return {
15775
+ input,
15776
+ metadata
15777
+ };
15778
+ }
15779
+ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOutputPaths) {
15780
+ registerWorkflowAgentWrapperSpan(span);
15781
+ const { input } = processAISDKWorkflowAgentCallInput(params);
15782
+ const metadata = extractWorkflowMetadataFromCallParams(params, event.self);
15783
+ const childTracing = prepareAISDKChildTracing(
15784
+ params,
15785
+ event.self,
15786
+ span,
15787
+ defaultDenyOutputPaths,
15788
+ event.aiSDK,
15789
+ { agentOwner: true, workflowAgent: true }
14557
15790
  );
14558
15791
  event.modelWrapped = childTracing.modelWrapped;
14559
15792
  if (childTracing.cleanup) {
@@ -14590,6 +15823,9 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
14590
15823
  function hasModelChildTracing(event) {
14591
15824
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
14592
15825
  }
15826
+ function serializeToolExecutionInput(args) {
15827
+ return args.length > 0 ? args[0] : args;
15828
+ }
14593
15829
  function createAISDKIntegrationMetadata() {
14594
15830
  return {
14595
15831
  braintrust: {
@@ -14601,6 +15837,13 @@ function createAISDKIntegrationMetadata() {
14601
15837
  function resolveModelFromSelf(self) {
14602
15838
  return 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;
14603
15839
  }
15840
+ function resolveToolsFromSelf(self) {
15841
+ if (!self || typeof self !== "object") {
15842
+ return void 0;
15843
+ }
15844
+ const selfRecord = self;
15845
+ return selfRecord.tools ?? selfRecord.settings?.tools;
15846
+ }
14604
15847
  function extractBaseMetadata(model, self) {
14605
15848
  const metadata = createAISDKIntegrationMetadata();
14606
15849
  const { model: modelId, provider } = serializeModelWithProvider(
@@ -14616,12 +15859,175 @@ function extractBaseMetadata(model, self) {
14616
15859
  }
14617
15860
  function extractMetadataFromCallParams(params, self) {
14618
15861
  const metadata = extractBaseMetadata(params.model, self);
14619
- const tools = serializeAISDKToolsForLogging(params.tools);
15862
+ const tools = serializeAISDKToolsForLogging(
15863
+ params.tools ?? resolveToolsFromSelf(self)
15864
+ );
14620
15865
  if (tools) {
14621
15866
  metadata.tools = tools;
14622
15867
  }
14623
15868
  return metadata;
14624
15869
  }
15870
+ function extractWorkflowMetadataFromCallParams(params, self) {
15871
+ const metadata = extractMetadataFromCallParams(params, self);
15872
+ const options = extractAISDKCallOptionsForMetadata(params);
15873
+ if (Object.keys(options).length > 0) {
15874
+ metadata.options = options;
15875
+ }
15876
+ return metadata;
15877
+ }
15878
+ function extractWorkflowAgentInput(params) {
15879
+ const input = {};
15880
+ if (params.instructions !== void 0) {
15881
+ input.instructions = params.instructions;
15882
+ }
15883
+ if (params.system !== void 0) {
15884
+ input.system = params.system;
15885
+ }
15886
+ if (Array.isArray(params.messages)) {
15887
+ return { ...input, messages: params.messages };
15888
+ }
15889
+ if (typeof params.prompt === "string") {
15890
+ return { ...input, prompt: params.prompt };
15891
+ }
15892
+ if (Array.isArray(params.prompt)) {
15893
+ return { ...input, prompt: params.prompt };
15894
+ }
15895
+ return input;
15896
+ }
15897
+ function extractWorkflowAgentModelInput(params) {
15898
+ const input = {};
15899
+ if (params.instructions !== void 0) {
15900
+ input.instructions = params.instructions;
15901
+ }
15902
+ if (params.system !== void 0) {
15903
+ input.system = params.system;
15904
+ }
15905
+ if (Array.isArray(params.messages)) {
15906
+ return { ...input, messages: params.messages };
15907
+ }
15908
+ if (typeof params.prompt === "string") {
15909
+ return { ...input, prompt: params.prompt };
15910
+ }
15911
+ if (Array.isArray(params.prompt)) {
15912
+ return { ...input, messages: params.prompt };
15913
+ }
15914
+ return input;
15915
+ }
15916
+ function sanitizeAISDKCallInputValue(value, depth = 0) {
15917
+ if (value === void 0 || typeof value === "function") {
15918
+ return void 0;
15919
+ }
15920
+ if (value === null || typeof value !== "object") {
15921
+ return value;
15922
+ }
15923
+ if (isPromiseLike(value)) {
15924
+ return "[Promise]";
15925
+ }
15926
+ if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) {
15927
+ return "[AbortSignal]";
15928
+ }
15929
+ if (depth >= 8) {
15930
+ return "[Object]";
15931
+ }
15932
+ if (Array.isArray(value)) {
15933
+ return value.map((item) => sanitizeAISDKCallInputValue(item, depth + 1)).filter((item) => item !== void 0);
15934
+ }
15935
+ if (!isObject(value)) {
15936
+ return value;
15937
+ }
15938
+ const prototype = Object.getPrototypeOf(value);
15939
+ if (prototype !== Object.prototype && prototype !== null) {
15940
+ return value;
15941
+ }
15942
+ const sanitized = {};
15943
+ for (const [key, nested] of Object.entries(value)) {
15944
+ if (key === "__proto__" || key === "constructor" || key === "prototype" || key.toLowerCase() === "headers") {
15945
+ continue;
15946
+ }
15947
+ const sanitizedNested = sanitizeAISDKCallInputValue(nested, depth + 1);
15948
+ if (sanitizedNested !== void 0) {
15949
+ sanitized[key] = sanitizedNested;
15950
+ }
15951
+ }
15952
+ return sanitized;
15953
+ }
15954
+ function extractAISDKCallOptionsForMetadata(params) {
15955
+ const options = {};
15956
+ const inputOrTopLevelKeys = /* @__PURE__ */ new Set([
15957
+ "model",
15958
+ "instructions",
15959
+ "messages",
15960
+ "prompt",
15961
+ "system",
15962
+ "tools",
15963
+ "headers",
15964
+ "abortSignal",
15965
+ "signal",
15966
+ "experimental_output"
15967
+ ]);
15968
+ for (const [key, value] of Object.entries(params)) {
15969
+ if (inputOrTopLevelKeys.has(key) || key === "__proto__" || key === "constructor" || key === "prototype" || /^on[A-Z]/.test(key) && typeof value === "function") {
15970
+ continue;
15971
+ }
15972
+ const sanitized = sanitizeAISDKMetadataValue(value);
15973
+ if (sanitized !== void 0) {
15974
+ options[key] = sanitized;
15975
+ }
15976
+ }
15977
+ return options;
15978
+ }
15979
+ function sanitizeAISDKMetadataValue(value, depth = 0) {
15980
+ if (value === void 0) {
15981
+ return void 0;
15982
+ }
15983
+ if (typeof value === "function") {
15984
+ return "[Function]";
15985
+ }
15986
+ if (value === null || typeof value !== "object") {
15987
+ return value;
15988
+ }
15989
+ if (isPromiseLike(value)) {
15990
+ return "[Promise]";
15991
+ }
15992
+ if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) {
15993
+ return "[AbortSignal]";
15994
+ }
15995
+ if (depth >= 8) {
15996
+ return "[Object]";
15997
+ }
15998
+ if (Array.isArray(value)) {
15999
+ return value.map((item) => sanitizeAISDKMetadataValue(item, depth + 1)).filter((item) => item !== void 0);
16000
+ }
16001
+ if (!isObject(value)) {
16002
+ return value;
16003
+ }
16004
+ const sanitized = {};
16005
+ for (const [key, nested] of Object.entries(value)) {
16006
+ if (key === "__proto__" || key === "constructor" || key === "prototype" || key.toLowerCase() === "headers") {
16007
+ continue;
16008
+ }
16009
+ const sanitizedNested = sanitizeAISDKMetadataValue(nested, depth + 1);
16010
+ if (sanitizedNested !== void 0) {
16011
+ sanitized[key] = sanitizedNested;
16012
+ }
16013
+ }
16014
+ return sanitized;
16015
+ }
16016
+ function buildAISDKModelStartEvent(callOptions, baseMetadata, options) {
16017
+ if (!options.workflowAgent) {
16018
+ return {
16019
+ input: processAISDKCallInput(callOptions).input,
16020
+ metadata: baseMetadata
16021
+ };
16022
+ }
16023
+ return {
16024
+ input: processAISDKWorkflowAgentModelCallInput(callOptions).input,
16025
+ metadata: {
16026
+ ...baseMetadata,
16027
+ ...extractWorkflowMetadataFromCallParams(callOptions)
16028
+ }
16029
+ };
16030
+ }
14625
16031
  function extractMetadataFromEmbedParams(params, self) {
14626
16032
  return extractBaseMetadata(params.model, self);
14627
16033
  }
@@ -14635,72 +16041,273 @@ function extractMetadataFromRerankParams(params, self) {
14635
16041
  }
14636
16042
  return metadata;
14637
16043
  }
14638
- function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
16044
+ function activeAISDKChildPatchEntry(entries) {
16045
+ const activeSpan = currentSpan();
16046
+ const activeSpanId = activeSpan.spanId;
16047
+ if (activeSpanId) {
16048
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16049
+ const entry = entries[index];
16050
+ if (entry?.activeSpanIds.has(activeSpanId)) {
16051
+ return entry;
16052
+ }
16053
+ }
16054
+ }
16055
+ const activeParentSpanIds = activeSpan.spanParents ?? [];
16056
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16057
+ const entry = entries[index];
16058
+ if (entry?.parentSpan.spanId && activeParentSpanIds.includes(entry.parentSpan.spanId)) {
16059
+ return entry;
16060
+ }
16061
+ }
16062
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16063
+ const entry = entries[index];
16064
+ if (entry?.parentSpan.spanId === activeSpanId) {
16065
+ return entry;
16066
+ }
16067
+ }
16068
+ return entries[entries.length - 1];
16069
+ }
16070
+ function attachNestedAISDKChildPatchEntry(entries, nestedSpan, cleanup) {
16071
+ const activeSpanId = currentSpan().spanId;
16072
+ if (!activeSpanId || activeSpanId === nestedSpan.spanId) {
16073
+ return false;
16074
+ }
16075
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16076
+ const entry = entries[index];
16077
+ if (entry?.parentSpan.spanId === activeSpanId || entry?.activeSpanIds.has(activeSpanId)) {
16078
+ entry.activeSpanIds.add(nestedSpan.spanId);
16079
+ cleanup.push(() => {
16080
+ entry.activeSpanIds.delete(nestedSpan.spanId);
16081
+ });
16082
+ return true;
16083
+ }
16084
+ }
16085
+ return false;
16086
+ }
16087
+ function shadowActiveAISDKChildPatchEntry(entries, entry, nestedSpan, cleanup) {
16088
+ const activeSpanId = currentSpan().spanId;
16089
+ if (!activeSpanId || activeSpanId === nestedSpan.spanId) {
16090
+ return;
16091
+ }
16092
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
16093
+ const existingEntry = entries[index];
16094
+ if (existingEntry?.parentSpan.spanId === activeSpanId || existingEntry?.activeSpanIds.has(activeSpanId)) {
16095
+ entry.activeSpanIds.add(activeSpanId);
16096
+ cleanup.push(() => {
16097
+ entry.activeSpanIds.delete(activeSpanId);
16098
+ });
16099
+ return;
16100
+ }
16101
+ }
16102
+ }
16103
+ function closeOpenAISDKModelPatchSpans(entry) {
16104
+ for (const span of entry.openSpans) {
16105
+ span.end();
16106
+ }
16107
+ entry.openSpans.clear();
16108
+ }
16109
+ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK, childTracingOptions = {}) {
14639
16110
  const cleanup = [];
14640
- const patchedModels = /* @__PURE__ */ new WeakSet();
16111
+ const patchedModels = /* @__PURE__ */ new WeakMap();
14641
16112
  const patchedTools = /* @__PURE__ */ new WeakSet();
14642
16113
  let modelWrapped = false;
14643
16114
  const patchModel = (model) => {
14644
16115
  const resolvedModel = resolveAISDKModel(model, aiSDK);
14645
- if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
16116
+ if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function") {
14646
16117
  return resolvedModel;
14647
16118
  }
14648
- patchedModels.add(resolvedModel);
14649
- resolvedModel[AUTO_PATCHED_MODEL] = true;
16119
+ const existingWrappedModel = patchedModels.get(resolvedModel);
16120
+ if (existingWrappedModel) {
16121
+ modelWrapped = true;
16122
+ return existingWrappedModel;
16123
+ }
14650
16124
  modelWrapped = true;
16125
+ const modelRecord = resolvedModel;
16126
+ const entry = {
16127
+ activeSpanIds: /* @__PURE__ */ new Set([parentSpan.spanId]),
16128
+ baseMetadata: buildAISDKChildMetadata(resolvedModel),
16129
+ childTracingOptions,
16130
+ denyOutputPaths,
16131
+ openSpans: /* @__PURE__ */ new Set(),
16132
+ parentSpan
16133
+ };
16134
+ const cleanupModelEntry = (state2, patchedModel) => {
16135
+ closeOpenAISDKModelPatchSpans(entry);
16136
+ const index = state2.entries.indexOf(entry);
16137
+ if (index >= 0) {
16138
+ state2.entries.splice(index, 1);
16139
+ }
16140
+ if (state2.entries.length > 0) {
16141
+ return;
16142
+ }
16143
+ patchedModel.doGenerate = state2.originalDoGenerate;
16144
+ patchedModel.doStream = state2.originalDoStream;
16145
+ delete patchedModel[AUTO_PATCHED_MODEL];
16146
+ };
16147
+ const existingState = modelRecord[AUTO_PATCHED_MODEL];
16148
+ if (existingState) {
16149
+ patchedModels.set(resolvedModel, resolvedModel);
16150
+ if (childTracingOptions.agentOwner && attachNestedAISDKChildPatchEntry(
16151
+ existingState.entries,
16152
+ parentSpan,
16153
+ cleanup
16154
+ )) {
16155
+ return resolvedModel;
16156
+ }
16157
+ if (!childTracingOptions.agentOwner) {
16158
+ shadowActiveAISDKChildPatchEntry(
16159
+ existingState.entries,
16160
+ entry,
16161
+ parentSpan,
16162
+ cleanup
16163
+ );
16164
+ }
16165
+ existingState.entries.push(entry);
16166
+ cleanup.push(() => {
16167
+ cleanupModelEntry(existingState, modelRecord);
16168
+ });
16169
+ return resolvedModel;
16170
+ }
14651
16171
  const originalDoGenerate = resolvedModel.doGenerate;
14652
16172
  const originalDoStream = resolvedModel.doStream;
14653
- const baseMetadata = buildAISDKChildMetadata(resolvedModel);
14654
- resolvedModel.doGenerate = async function doGeneratePatched(options) {
14655
- return parentSpan.traced(
16173
+ const wrappedModel = Object.create(
16174
+ Object.getPrototypeOf(resolvedModel)
16175
+ );
16176
+ Object.defineProperties(
16177
+ wrappedModel,
16178
+ Object.getOwnPropertyDescriptors(resolvedModel)
16179
+ );
16180
+ const wrappedModelRecord = wrappedModel;
16181
+ const state = {
16182
+ entries: [entry],
16183
+ originalDoGenerate,
16184
+ originalDoStream
16185
+ };
16186
+ Object.defineProperty(wrappedModel, AUTO_PATCHED_MODEL, {
16187
+ configurable: true,
16188
+ value: state
16189
+ });
16190
+ wrappedModel.doGenerate = async function doGeneratePatched(callOptions) {
16191
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
16192
+ if (!activeEntry) {
16193
+ return Reflect.apply(originalDoGenerate, resolvedModel, [callOptions]);
16194
+ }
16195
+ closeOpenAISDKModelPatchSpans(activeEntry);
16196
+ return activeEntry.parentSpan.traced(
14656
16197
  async (span) => {
14657
- const result = await Reflect.apply(
14658
- originalDoGenerate,
14659
- resolvedModel,
14660
- [options]
14661
- );
14662
- span.log({
14663
- output: processAISDKOutput(result, denyOutputPaths),
14664
- metrics: extractTokenMetrics(result),
14665
- ...buildResolvedMetadataPayload(result)
14666
- });
14667
- return result;
16198
+ activeEntry.openSpans.add(span);
16199
+ try {
16200
+ const result = await Reflect.apply(
16201
+ originalDoGenerate,
16202
+ resolvedModel,
16203
+ [callOptions]
16204
+ );
16205
+ const output = processAISDKOutput(
16206
+ result,
16207
+ activeEntry.denyOutputPaths
16208
+ );
16209
+ const metrics = extractTokenMetrics(result);
16210
+ const metadataPayload = buildResolvedMetadataPayload(result);
16211
+ const missingUsageMetadata = buildMissingUsageMetadata(
16212
+ output,
16213
+ metrics,
16214
+ "ai_sdk_result_missing_usage"
16215
+ );
16216
+ span.log({
16217
+ output,
16218
+ metrics,
16219
+ ...mergeMetadataPayload(metadataPayload, missingUsageMetadata)
16220
+ });
16221
+ return result;
16222
+ } finally {
16223
+ activeEntry.openSpans.delete(span);
16224
+ }
14668
16225
  },
14669
16226
  {
14670
16227
  name: "doGenerate",
14671
16228
  spanAttributes: {
14672
16229
  type: "llm" /* LLM */
14673
16230
  },
14674
- event: {
14675
- input: processAISDKCallInput(options).input,
14676
- metadata: baseMetadata
14677
- }
16231
+ event: buildAISDKModelStartEvent(
16232
+ callOptions,
16233
+ activeEntry.baseMetadata,
16234
+ {
16235
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
16236
+ }
16237
+ )
14678
16238
  }
14679
16239
  );
14680
16240
  };
14681
16241
  if (originalDoStream) {
14682
- resolvedModel.doStream = async function doStreamPatched(options) {
14683
- const span = parentSpan.startSpan({
16242
+ wrappedModel.doStream = async function doStreamPatched(callOptions) {
16243
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
16244
+ if (!activeEntry) {
16245
+ return Reflect.apply(originalDoStream, resolvedModel, [callOptions]);
16246
+ }
16247
+ closeOpenAISDKModelPatchSpans(activeEntry);
16248
+ const span = activeEntry.parentSpan.startSpan({
14684
16249
  name: "doStream",
14685
16250
  spanAttributes: {
14686
16251
  type: "llm" /* LLM */
14687
16252
  },
14688
- event: {
14689
- input: processAISDKCallInput(options).input,
14690
- metadata: baseMetadata
14691
- }
16253
+ event: buildAISDKModelStartEvent(
16254
+ callOptions,
16255
+ activeEntry.baseMetadata,
16256
+ {
16257
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
16258
+ }
16259
+ )
14692
16260
  });
16261
+ activeEntry.openSpans.add(span);
14693
16262
  const streamStartTime = getCurrentUnixTimestamp();
14694
16263
  const result = await withCurrent(
14695
16264
  span,
14696
- () => Reflect.apply(originalDoStream, resolvedModel, [options])
16265
+ () => Reflect.apply(originalDoStream, resolvedModel, [callOptions])
14697
16266
  );
14698
16267
  let firstChunkTime;
14699
16268
  const output = {};
14700
16269
  let text = "";
14701
16270
  let reasoning = "";
14702
- const toolCalls = [];
16271
+ const toolCalls2 = [];
14703
16272
  let object = void 0;
16273
+ let streamSpanEnded = false;
16274
+ const logAndEndStreamSpan = (usageUnavailableReason) => {
16275
+ if (streamSpanEnded) {
16276
+ return;
16277
+ }
16278
+ output.text = text;
16279
+ output.reasoning = reasoning;
16280
+ output.toolCalls = toolCalls2;
16281
+ if (object !== void 0) {
16282
+ output.object = object;
16283
+ }
16284
+ const metrics = extractTokenMetrics(output);
16285
+ if (firstChunkTime !== void 0 && !activeEntry.childTracingOptions.workflowAgent) {
16286
+ metrics.time_to_first_token = Math.max(
16287
+ firstChunkTime - streamStartTime,
16288
+ 1e-6
16289
+ );
16290
+ }
16291
+ const metadataPayload = buildResolvedMetadataPayload(
16292
+ output
16293
+ );
16294
+ const missingUsageMetadata = usageUnavailableReason ? { usage_unavailable_reason: usageUnavailableReason } : buildMissingUsageMetadata(
16295
+ output,
16296
+ metrics,
16297
+ "ai_sdk_result_missing_usage"
16298
+ );
16299
+ span.log({
16300
+ output: processAISDKOutput(
16301
+ output,
16302
+ activeEntry.denyOutputPaths
16303
+ ),
16304
+ metrics,
16305
+ ...mergeMetadataPayload(metadataPayload, missingUsageMetadata)
16306
+ });
16307
+ activeEntry.openSpans.delete(span);
16308
+ span.end();
16309
+ streamSpanEnded = true;
16310
+ };
14704
16311
  const transformStream = new TransformStream({
14705
16312
  transform(chunk, controller) {
14706
16313
  if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
@@ -14718,7 +16325,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14718
16325
  }
14719
16326
  break;
14720
16327
  case "tool-call":
14721
- toolCalls.push(chunk);
16328
+ toolCalls2.push(chunk);
14722
16329
  break;
14723
16330
  case "object":
14724
16331
  object = chunk.object;
@@ -14738,33 +16345,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14738
16345
  }
14739
16346
  break;
14740
16347
  case "finish":
14741
- output.text = text;
14742
- output.reasoning = reasoning;
14743
- output.toolCalls = toolCalls;
14744
16348
  output.finishReason = chunk.finishReason;
14745
16349
  output.usage = chunk.usage;
14746
- if (object !== void 0) {
14747
- output.object = object;
14748
- }
14749
- const metrics = extractTokenMetrics(output);
14750
- if (firstChunkTime !== void 0) {
14751
- metrics.time_to_first_token = Math.max(
14752
- firstChunkTime - streamStartTime,
14753
- 1e-6
14754
- );
14755
- }
14756
- span.log({
14757
- output: processAISDKOutput(
14758
- output,
14759
- denyOutputPaths
14760
- ),
14761
- metrics,
14762
- ...buildResolvedMetadataPayload(output)
14763
- });
14764
- span.end();
16350
+ logAndEndStreamSpan();
14765
16351
  break;
14766
16352
  }
14767
16353
  controller.enqueue(chunk);
16354
+ },
16355
+ flush() {
16356
+ logAndEndStreamSpan("ai_sdk_stream_finished_without_usage");
14768
16357
  }
14769
16358
  });
14770
16359
  return {
@@ -14774,32 +16363,79 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14774
16363
  };
14775
16364
  }
14776
16365
  cleanup.push(() => {
14777
- resolvedModel.doGenerate = originalDoGenerate;
14778
- if (originalDoStream) {
14779
- resolvedModel.doStream = originalDoStream;
14780
- }
14781
- delete resolvedModel[AUTO_PATCHED_MODEL];
16366
+ cleanupModelEntry(state, wrappedModelRecord);
14782
16367
  });
14783
- return resolvedModel;
16368
+ patchedModels.set(resolvedModel, wrappedModel);
16369
+ patchedModels.set(wrappedModel, wrappedModel);
16370
+ return wrappedModel;
14784
16371
  };
14785
16372
  const patchTool = (tool, name) => {
14786
- if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
16373
+ if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool)) {
14787
16374
  return;
14788
16375
  }
14789
16376
  patchedTools.add(tool);
14790
- tool[AUTO_PATCHED_TOOL] = true;
14791
- const originalExecute = tool.execute;
16377
+ const toolRecord = tool;
16378
+ const entry = {
16379
+ activeSpanIds: /* @__PURE__ */ new Set([parentSpan.spanId]),
16380
+ childTracingOptions,
16381
+ name,
16382
+ parentSpan
16383
+ };
16384
+ const cleanupToolEntry = (state2) => {
16385
+ const index = state2.entries.indexOf(entry);
16386
+ if (index >= 0) {
16387
+ state2.entries.splice(index, 1);
16388
+ }
16389
+ if (state2.entries.length > 0) {
16390
+ return;
16391
+ }
16392
+ tool.execute = state2.originalExecute;
16393
+ delete toolRecord[AUTO_PATCHED_TOOL];
16394
+ };
16395
+ const existingState = toolRecord[AUTO_PATCHED_TOOL];
16396
+ if (existingState) {
16397
+ if (childTracingOptions.agentOwner && attachNestedAISDKChildPatchEntry(
16398
+ existingState.entries,
16399
+ parentSpan,
16400
+ cleanup
16401
+ )) {
16402
+ return;
16403
+ }
16404
+ if (!childTracingOptions.agentOwner) {
16405
+ shadowActiveAISDKChildPatchEntry(
16406
+ existingState.entries,
16407
+ entry,
16408
+ parentSpan,
16409
+ cleanup
16410
+ );
16411
+ }
16412
+ existingState.entries.push(entry);
16413
+ cleanup.push(() => {
16414
+ cleanupToolEntry(existingState);
16415
+ });
16416
+ return;
16417
+ }
16418
+ const originalExecute = toolRecord.execute;
16419
+ const state = {
16420
+ entries: [entry],
16421
+ originalExecute
16422
+ };
16423
+ toolRecord[AUTO_PATCHED_TOOL] = state;
14792
16424
  tool.execute = function executePatched(...args) {
16425
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
14793
16426
  const result = Reflect.apply(originalExecute, this, args);
16427
+ if (!activeEntry) {
16428
+ return result;
16429
+ }
14794
16430
  if (isAsyncGenerator(result)) {
14795
16431
  return (async function* () {
14796
- const span = parentSpan.startSpan({
14797
- name,
16432
+ const span = activeEntry.parentSpan.startSpan({
16433
+ name: activeEntry.name,
14798
16434
  spanAttributes: {
14799
16435
  type: "tool" /* TOOL */
14800
16436
  }
14801
16437
  });
14802
- span.log({ input: args.length === 1 ? args[0] : args });
16438
+ span.log({ input: serializeToolExecutionInput(args) });
14803
16439
  try {
14804
16440
  let lastValue;
14805
16441
  for await (const value of result) {
@@ -14815,15 +16451,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14815
16451
  }
14816
16452
  })();
14817
16453
  }
14818
- return parentSpan.traced(
16454
+ return activeEntry.parentSpan.traced(
14819
16455
  async (span) => {
14820
- span.log({ input: args.length === 1 ? args[0] : args });
16456
+ span.log({ input: serializeToolExecutionInput(args) });
14821
16457
  const awaitedResult = await result;
14822
16458
  span.log({ output: awaitedResult });
14823
16459
  return awaitedResult;
14824
16460
  },
14825
16461
  {
14826
- name,
16462
+ name: activeEntry.name,
14827
16463
  spanAttributes: {
14828
16464
  type: "tool" /* TOOL */
14829
16465
  }
@@ -14831,8 +16467,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14831
16467
  );
14832
16468
  };
14833
16469
  cleanup.push(() => {
14834
- tool.execute = originalExecute;
14835
- delete tool[AUTO_PATCHED_TOOL];
16470
+ cleanupToolEntry(state);
14836
16471
  });
14837
16472
  };
14838
16473
  const patchTools = (tools) => {
@@ -14851,25 +16486,42 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
14851
16486
  }
14852
16487
  };
14853
16488
  if (params && typeof params === "object") {
14854
- const patchedParamModel = patchModel(params.model);
14855
- if (typeof params.model === "string" && patchedParamModel && typeof patchedParamModel === "object") {
16489
+ const originalParamModel = params.model;
16490
+ const patchedParamModel = patchModel(originalParamModel);
16491
+ if (patchedParamModel && patchedParamModel !== originalParamModel) {
14856
16492
  params.model = patchedParamModel;
16493
+ cleanup.push(() => {
16494
+ params.model = originalParamModel;
16495
+ });
14857
16496
  }
14858
16497
  patchTools(params.tools);
14859
16498
  }
14860
16499
  if (self && typeof self === "object") {
14861
16500
  const selfRecord = self;
14862
16501
  if (selfRecord.model !== void 0) {
14863
- const patchedSelfModel = patchModel(selfRecord.model);
14864
- if (typeof selfRecord.model === "string" && patchedSelfModel && typeof patchedSelfModel === "object") {
16502
+ const originalSelfModel = selfRecord.model;
16503
+ const patchedSelfModel = patchModel(originalSelfModel);
16504
+ if (patchedSelfModel && patchedSelfModel !== originalSelfModel) {
14865
16505
  selfRecord.model = patchedSelfModel;
16506
+ cleanup.push(() => {
16507
+ selfRecord.model = originalSelfModel;
16508
+ });
14866
16509
  }
14867
16510
  }
16511
+ if (selfRecord.tools !== void 0) {
16512
+ patchTools(selfRecord.tools);
16513
+ }
14868
16514
  if (selfRecord.settings && typeof selfRecord.settings === "object") {
14869
16515
  if (selfRecord.settings.model !== void 0) {
14870
- const patchedSettingsModel = patchModel(selfRecord.settings.model);
14871
- if (typeof selfRecord.settings.model === "string" && patchedSettingsModel && typeof patchedSettingsModel === "object") {
16516
+ const originalSettingsModel = selfRecord.settings.model;
16517
+ const patchedSettingsModel = patchModel(originalSettingsModel);
16518
+ if (patchedSettingsModel && patchedSettingsModel !== originalSettingsModel) {
14872
16519
  selfRecord.settings.model = patchedSettingsModel;
16520
+ cleanup.push(() => {
16521
+ if (selfRecord.settings) {
16522
+ selfRecord.settings.model = originalSettingsModel;
16523
+ }
16524
+ });
14873
16525
  }
14874
16526
  }
14875
16527
  if (selfRecord.settings.tools !== void 0) {
@@ -14966,99 +16618,190 @@ function isAISDKContentAsyncIterableChunk(chunk) {
14966
16618
  return isObject(part) && typeof part.type !== "string";
14967
16619
  }
14968
16620
  function patchAISDKStreamingResult(args) {
14969
- const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
16621
+ const {
16622
+ defaultDenyOutputPaths,
16623
+ endEvent,
16624
+ onComplete,
16625
+ result,
16626
+ span,
16627
+ startTime
16628
+ } = args;
14970
16629
  if (!result || typeof result !== "object") {
14971
16630
  return false;
14972
16631
  }
14973
16632
  const resultRecord = result;
14974
16633
  attachKnownResultPromiseHandlers(resultRecord);
16634
+ let finalized = false;
16635
+ const finalize = () => {
16636
+ if (finalized) {
16637
+ return;
16638
+ }
16639
+ finalized = true;
16640
+ finalizeAISDKChildTracing(endEvent);
16641
+ span.end();
16642
+ onComplete?.();
16643
+ };
16644
+ let outputLogged = false;
16645
+ const logStreamingOutput = async (firstChunkTime) => {
16646
+ if (outputLogged) {
16647
+ return;
16648
+ }
16649
+ outputLogged = true;
16650
+ try {
16651
+ const metrics = extractTopLevelAISDKMetrics(result, endEvent);
16652
+ if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
16653
+ metrics.time_to_first_token = firstChunkTime - startTime;
16654
+ }
16655
+ const output = await processAISDKStreamingOutput(
16656
+ result,
16657
+ resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
16658
+ );
16659
+ const metadata = buildResolvedMetadataPayload(result).metadata;
16660
+ span.log({
16661
+ output,
16662
+ ...metadata ? { metadata } : {},
16663
+ metrics
16664
+ });
16665
+ } catch (error) {
16666
+ span.log({ error: toLoggedError(error) });
16667
+ } finally {
16668
+ finalize();
16669
+ }
16670
+ };
16671
+ const createAsyncIterableHooks = () => {
16672
+ let firstChunkTime;
16673
+ return {
16674
+ onChunk: (chunk) => {
16675
+ if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
16676
+ firstChunkTime = getCurrentUnixTimestamp();
16677
+ }
16678
+ },
16679
+ onComplete: async () => {
16680
+ await logStreamingOutput(firstChunkTime);
16681
+ },
16682
+ onError: (error) => {
16683
+ if (!outputLogged) {
16684
+ outputLogged = true;
16685
+ span.log({
16686
+ error: error.message
16687
+ });
16688
+ }
16689
+ finalize();
16690
+ },
16691
+ onCancel: finalize
16692
+ };
16693
+ };
16694
+ const patchAsyncIterable = (stream) => isReadableStreamLike(stream) ? createPatchedReadableStream(stream, createAsyncIterableHooks()) : createPatchedAsyncIterable(stream, createAsyncIterableHooks());
16695
+ const patchAsyncIterableField = (field) => {
16696
+ let descriptorOwner = resultRecord;
16697
+ let descriptor;
16698
+ while (descriptorOwner) {
16699
+ descriptor = Object.getOwnPropertyDescriptor(descriptorOwner, field);
16700
+ if (descriptor) {
16701
+ break;
16702
+ }
16703
+ descriptorOwner = Object.getPrototypeOf(descriptorOwner);
16704
+ }
16705
+ if (!descriptor || descriptorOwner === resultRecord && !descriptor.configurable) {
16706
+ return false;
16707
+ }
16708
+ if ("value" in descriptor) {
16709
+ if (!isAsyncIterable(descriptor.value)) {
16710
+ return false;
16711
+ }
16712
+ try {
16713
+ Object.defineProperty(resultRecord, field, {
16714
+ configurable: descriptorOwner === resultRecord ? descriptor.configurable : true,
16715
+ enumerable: descriptor.enumerable,
16716
+ value: patchAsyncIterable(descriptor.value),
16717
+ writable: descriptor.writable
16718
+ });
16719
+ return true;
16720
+ } catch {
16721
+ return false;
16722
+ }
16723
+ }
16724
+ if (typeof descriptor.get !== "function") {
16725
+ return false;
16726
+ }
16727
+ const originalGet = descriptor.get;
16728
+ const originalSet = descriptor.set;
16729
+ try {
16730
+ Object.defineProperty(resultRecord, field, {
16731
+ configurable: descriptorOwner === resultRecord ? descriptor.configurable : true,
16732
+ enumerable: descriptor.enumerable,
16733
+ get() {
16734
+ const stream = originalGet.call(this);
16735
+ return isAsyncIterable(stream) ? patchAsyncIterable(stream) : stream;
16736
+ },
16737
+ ...originalSet ? {
16738
+ set(value) {
16739
+ originalSet.call(this, value);
16740
+ }
16741
+ } : {}
16742
+ });
16743
+ return true;
16744
+ } catch {
16745
+ return false;
16746
+ }
16747
+ };
16748
+ let patched = false;
14975
16749
  if (isReadableStreamLike(resultRecord.baseStream)) {
14976
- let firstChunkTime2;
14977
- const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
16750
+ let firstChunkTime;
16751
+ const transformedBaseStream = resultRecord.baseStream.pipeThrough(
14978
16752
  new TransformStream({
14979
16753
  transform(chunk, controller) {
14980
- if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
14981
- firstChunkTime2 = getCurrentUnixTimestamp();
16754
+ if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
16755
+ firstChunkTime = getCurrentUnixTimestamp();
14982
16756
  }
14983
16757
  controller.enqueue(chunk);
14984
16758
  },
14985
16759
  async flush() {
14986
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
14987
- if (metrics.time_to_first_token === void 0 && firstChunkTime2 !== void 0) {
14988
- metrics.time_to_first_token = firstChunkTime2 - startTime;
14989
- }
14990
- const output = await processAISDKStreamingOutput(
14991
- result,
14992
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
14993
- );
14994
- const metadata = buildResolvedMetadataPayload(result).metadata;
14995
- span.log({
14996
- output,
14997
- ...metadata ? { metadata } : {},
14998
- metrics
14999
- });
15000
- finalizeAISDKChildTracing(endEvent);
15001
- span.end();
16760
+ await logStreamingOutput(firstChunkTime);
15002
16761
  }
15003
16762
  })
15004
16763
  );
16764
+ const reader = transformedBaseStream.getReader();
16765
+ const wrappedBaseStream = new ReadableStream({
16766
+ async pull(controller) {
16767
+ try {
16768
+ const { done, value } = await reader.read();
16769
+ if (done) {
16770
+ controller.close();
16771
+ return;
16772
+ }
16773
+ controller.enqueue(value);
16774
+ } catch (error) {
16775
+ span.log({ error: toLoggedError(error) });
16776
+ finalize();
16777
+ controller.error(error);
16778
+ }
16779
+ },
16780
+ async cancel(reason) {
16781
+ try {
16782
+ finalize();
16783
+ } finally {
16784
+ await reader.cancel(reason);
16785
+ }
16786
+ }
16787
+ });
15005
16788
  Object.defineProperty(resultRecord, "baseStream", {
15006
16789
  configurable: true,
15007
16790
  enumerable: true,
15008
16791
  value: wrappedBaseStream,
15009
16792
  writable: true
15010
16793
  });
15011
- return true;
16794
+ patched = true;
15012
16795
  }
15013
- const streamField = findAsyncIterableField(resultRecord, [
16796
+ for (const field of [
15014
16797
  "partialObjectStream",
15015
16798
  "textStream",
15016
16799
  "fullStream",
15017
16800
  "stream"
15018
- ]);
15019
- if (!streamField) {
15020
- return false;
16801
+ ]) {
16802
+ patched = patchAsyncIterableField(field) || patched;
15021
16803
  }
15022
- let firstChunkTime;
15023
- const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
15024
- onChunk: (chunk) => {
15025
- if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
15026
- firstChunkTime = getCurrentUnixTimestamp();
15027
- }
15028
- },
15029
- onComplete: async () => {
15030
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
15031
- if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
15032
- metrics.time_to_first_token = firstChunkTime - startTime;
15033
- }
15034
- const output = await processAISDKStreamingOutput(
15035
- result,
15036
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
15037
- );
15038
- const metadata = buildResolvedMetadataPayload(result).metadata;
15039
- span.log({
15040
- output,
15041
- ...metadata ? { metadata } : {},
15042
- metrics
15043
- });
15044
- finalizeAISDKChildTracing(endEvent);
15045
- span.end();
15046
- },
15047
- onError: (error) => {
15048
- span.log({
15049
- error: error.message
15050
- });
15051
- finalizeAISDKChildTracing(endEvent);
15052
- span.end();
15053
- }
15054
- });
15055
- Object.defineProperty(resultRecord, streamField.field, {
15056
- configurable: true,
15057
- enumerable: true,
15058
- value: wrappedStream,
15059
- writable: true
15060
- });
15061
- return true;
16804
+ return patched;
15062
16805
  }
15063
16806
  function attachKnownResultPromiseHandlers(result) {
15064
16807
  const promiseLikeFields = [
@@ -15090,34 +16833,72 @@ function attachKnownResultPromiseHandlers(result) {
15090
16833
  }
15091
16834
  }
15092
16835
  function isReadableStreamLike(value) {
15093
- return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
15094
- }
15095
- function findAsyncIterableField(result, candidateFields) {
15096
- for (const field of candidateFields) {
15097
- try {
15098
- const stream = result[field];
15099
- if (isAsyncIterable(stream)) {
15100
- return { field, stream };
16836
+ return value != null && typeof value === "object" && typeof value.getReader === "function" && typeof value.pipeThrough === "function";
16837
+ }
16838
+ function createPatchedReadableStream(stream, hooks) {
16839
+ let reader;
16840
+ let completed = false;
16841
+ return new ReadableStream({
16842
+ async pull(controller) {
16843
+ reader ??= stream.getReader();
16844
+ try {
16845
+ const { done, value } = await reader.read();
16846
+ if (done) {
16847
+ completed = true;
16848
+ await hooks.onComplete();
16849
+ controller.close();
16850
+ return;
16851
+ }
16852
+ hooks.onChunk(value);
16853
+ controller.enqueue(value);
16854
+ } catch (error) {
16855
+ completed = true;
16856
+ hooks.onError(
16857
+ error instanceof Error ? error : new Error(String(error))
16858
+ );
16859
+ controller.error(error);
16860
+ }
16861
+ },
16862
+ async cancel(reason) {
16863
+ if (!completed) {
16864
+ completed = true;
16865
+ try {
16866
+ await hooks.onCancel?.();
16867
+ } catch {
16868
+ }
16869
+ }
16870
+ if (reader) {
16871
+ await reader.cancel(reason);
16872
+ } else if (stream.cancel) {
16873
+ await stream.cancel(reason);
15101
16874
  }
15102
- } catch {
15103
16875
  }
15104
- }
15105
- return null;
16876
+ });
15106
16877
  }
15107
16878
  function createPatchedAsyncIterable(stream, hooks) {
15108
16879
  return {
15109
16880
  async *[Symbol.asyncIterator]() {
16881
+ let completed = false;
15110
16882
  try {
15111
16883
  for await (const chunk of stream) {
15112
16884
  hooks.onChunk(chunk);
15113
16885
  yield chunk;
15114
16886
  }
16887
+ completed = true;
15115
16888
  await hooks.onComplete();
15116
16889
  } catch (error) {
16890
+ completed = true;
15117
16891
  hooks.onError(
15118
16892
  error instanceof Error ? error : new Error(String(error))
15119
16893
  );
15120
16894
  throw error;
16895
+ } finally {
16896
+ if (!completed) {
16897
+ try {
16898
+ await hooks.onCancel?.();
16899
+ } catch {
16900
+ }
16901
+ }
15121
16902
  }
15122
16903
  }
15123
16904
  };
@@ -15192,6 +16973,40 @@ function buildResolvedMetadataPayload(result) {
15192
16973
  }
15193
16974
  return Object.keys(metadata).length > 0 ? { metadata } : {};
15194
16975
  }
16976
+ function mergeMetadataPayload(metadataPayload, extraMetadata) {
16977
+ if (!extraMetadata || Object.keys(extraMetadata).length === 0) {
16978
+ return metadataPayload;
16979
+ }
16980
+ return {
16981
+ metadata: {
16982
+ ...metadataPayload.metadata ?? {},
16983
+ ...extraMetadata
16984
+ }
16985
+ };
16986
+ }
16987
+ function buildMissingUsageMetadata(output, metrics, reason) {
16988
+ if (!hasLoggedOutput(output) || hasTokenUsageMetrics(metrics)) {
16989
+ return void 0;
16990
+ }
16991
+ return { usage_unavailable_reason: reason };
16992
+ }
16993
+ function hasLoggedOutput(output) {
16994
+ if (output === null || output === void 0) {
16995
+ return false;
16996
+ }
16997
+ if (Array.isArray(output)) {
16998
+ return output.length > 0;
16999
+ }
17000
+ if (typeof output === "object") {
17001
+ return Object.keys(output).length > 0;
17002
+ }
17003
+ return true;
17004
+ }
17005
+ function hasTokenUsageMetrics(metrics) {
17006
+ return Object.keys(metrics).some(
17007
+ (key) => key !== "estimated_cost" && key !== "time_to_first_token"
17008
+ );
17009
+ }
15195
17010
  function resolveAISDKModel(model, aiSDK) {
15196
17011
  if (typeof model !== "string") {
15197
17012
  return model;
@@ -15215,7 +17030,45 @@ function isAsyncGenerator(value) {
15215
17030
  function processAISDKOutput(output, denyOutputPaths) {
15216
17031
  if (!output) return output;
15217
17032
  const merged = extractSerializableOutputFields(output);
15218
- return normalizeAISDKLoggedOutput(omit(merged, denyOutputPaths));
17033
+ const deleteOutputPaths = denyOutputPaths.filter(
17034
+ (path) => path.toLowerCase().endsWith("headers")
17035
+ );
17036
+ const sanitized = omit(merged, denyOutputPaths, deleteOutputPaths);
17037
+ for (const path of TRANSPORT_PAYLOAD_ROOT_PATHS) {
17038
+ const stack = [{ obj: sanitized, keys: parsePath(path) }];
17039
+ while (stack.length > 0) {
17040
+ const entry = stack.pop();
17041
+ if (!entry || entry.keys.length === 0) {
17042
+ continue;
17043
+ }
17044
+ const firstKey = entry.keys[0];
17045
+ const remainingKeys = entry.keys.slice(1);
17046
+ if (firstKey === "[]") {
17047
+ if (Array.isArray(entry.obj)) {
17048
+ for (const item of entry.obj) {
17049
+ stack.push({
17050
+ obj: item,
17051
+ keys: remainingKeys
17052
+ });
17053
+ }
17054
+ }
17055
+ continue;
17056
+ }
17057
+ if (!entry.obj || typeof entry.obj !== "object" || !(firstKey in entry.obj)) {
17058
+ continue;
17059
+ }
17060
+ const record = entry.obj;
17061
+ if (remainingKeys.length === 0) {
17062
+ record[firstKey] = sanitizeAISDKMetadataValue(record[firstKey]);
17063
+ continue;
17064
+ }
17065
+ stack.push({
17066
+ obj: record[firstKey],
17067
+ keys: remainingKeys
17068
+ });
17069
+ }
17070
+ }
17071
+ return normalizeAISDKLoggedOutput(sanitized);
15219
17072
  }
15220
17073
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
15221
17074
  if (!output || typeof output !== "object") {
@@ -15306,6 +17159,8 @@ function extractTokenMetrics(result) {
15306
17159
  );
15307
17160
  if (totalTokens !== void 0) {
15308
17161
  metrics.tokens = totalTokens;
17162
+ } else if (promptTokens !== void 0 && completionTokens !== void 0) {
17163
+ metrics.tokens = promptTokens + completionTokens;
15309
17164
  }
15310
17165
  const promptCachedTokens = firstNumber2(
15311
17166
  usage.inputTokens?.cacheRead,
@@ -15417,9 +17272,9 @@ function aggregateAISDKChunks(chunks, _result, endEvent) {
15417
17272
  if (finishReason !== void 0) {
15418
17273
  output.finishReason = finishReason;
15419
17274
  }
15420
- const toolCalls = safeSerializableFieldRead(lastChunk, "toolCalls");
15421
- if (toolCalls !== void 0) {
15422
- output.toolCalls = toolCalls;
17275
+ const toolCalls2 = safeSerializableFieldRead(lastChunk, "toolCalls");
17276
+ if (toolCalls2 !== void 0) {
17277
+ output.toolCalls = toolCalls2;
15423
17278
  }
15424
17279
  }
15425
17280
  finalizeAISDKChildTracing(endEvent);
@@ -15429,7 +17284,9 @@ function extractGetterValues(obj) {
15429
17284
  const getterValues = {};
15430
17285
  const getterNames = [
15431
17286
  "content",
17287
+ "messages",
15432
17288
  "text",
17289
+ "output",
15433
17290
  "object",
15434
17291
  "value",
15435
17292
  "values",
@@ -15469,7 +17326,9 @@ function extractGetterValues(obj) {
15469
17326
  function extractSerializableOutputFields(output) {
15470
17327
  const serialized = {};
15471
17328
  const directFieldNames = [
17329
+ "messages",
15472
17330
  "steps",
17331
+ "output",
15473
17332
  "request",
15474
17333
  "responseMessages",
15475
17334
  "warnings",
@@ -15651,7 +17510,7 @@ function parsePath(path) {
15651
17510
  }
15652
17511
  return keys;
15653
17512
  }
15654
- function omitAtPath(obj, keys) {
17513
+ function omitAtPath(obj, keys, deleteLeaf = false) {
15655
17514
  if (keys.length === 0) return;
15656
17515
  const firstKey = keys[0];
15657
17516
  const remainingKeys = keys.slice(1);
@@ -15661,29 +17520,36 @@ function omitAtPath(obj, keys) {
15661
17520
  if (remainingKeys.length > 0) {
15662
17521
  omitAtPath(
15663
17522
  item,
15664
- remainingKeys
17523
+ remainingKeys,
17524
+ deleteLeaf
15665
17525
  );
15666
17526
  }
15667
17527
  });
15668
17528
  }
15669
17529
  } else if (remainingKeys.length === 0) {
15670
17530
  if (obj && typeof obj === "object" && firstKey in obj) {
15671
- obj[firstKey] = "<omitted>";
17531
+ if (deleteLeaf) {
17532
+ delete obj[firstKey];
17533
+ } else {
17534
+ obj[firstKey] = "<omitted>";
17535
+ }
15672
17536
  }
15673
17537
  } else {
15674
17538
  if (obj && typeof obj === "object" && firstKey in obj) {
15675
17539
  omitAtPath(
15676
17540
  obj[firstKey],
15677
- remainingKeys
17541
+ remainingKeys,
17542
+ deleteLeaf
15678
17543
  );
15679
17544
  }
15680
17545
  }
15681
17546
  }
15682
- function omit(obj, paths) {
17547
+ function omit(obj, paths, deletePaths = []) {
15683
17548
  const result = deepCopy(obj);
17549
+ const deletePathSet = new Set(deletePaths);
15684
17550
  for (const path of paths) {
15685
17551
  const keys = parsePath(path);
15686
- omitAtPath(result, keys);
17552
+ omitAtPath(result, keys, deletePathSet.has(path));
15687
17553
  }
15688
17554
  return result;
15689
17555
  }
@@ -19892,8 +21758,8 @@ function getChatToolCallDeltas(value) {
19892
21758
  if (!Array.isArray(value?.tool_calls)) {
19893
21759
  return void 0;
19894
21760
  }
19895
- const toolCalls = value.tool_calls.filter((toolCall) => isObject(toolCall));
19896
- return toolCalls.length > 0 ? toolCalls : void 0;
21761
+ const toolCalls2 = value.tool_calls.filter((toolCall) => isObject(toolCall));
21762
+ return toolCalls2.length > 0 ? toolCalls2 : void 0;
19897
21763
  }
19898
21764
  function mergeChatToolCallDeltas(toolCallsByIndex, toolCallDeltas) {
19899
21765
  for (const toolDelta of toolCallDeltas) {
@@ -21382,7 +23248,7 @@ function aggregateOpenRouterChatChunks(chunks) {
21382
23248
  let reasoningContent = "";
21383
23249
  let hasReasoningContent = false;
21384
23250
  let reasoningDetails;
21385
- let toolCalls;
23251
+ let toolCalls2;
21386
23252
  let finishReason;
21387
23253
  let metrics = {};
21388
23254
  for (const chunk of chunks) {
@@ -21435,9 +23301,9 @@ function aggregateOpenRouterChatChunks(chunks) {
21435
23301
  continue;
21436
23302
  }
21437
23303
  const toolIndex = toolDelta.index ?? 0;
21438
- const existingToolCall = toolCalls?.[toolIndex];
23304
+ const existingToolCall = toolCalls2?.[toolIndex];
21439
23305
  if (!existingToolCall || toolDelta.id && existingToolCall.id !== void 0 && existingToolCall.id !== toolDelta.id) {
21440
- const nextToolCalls = [...toolCalls || []];
23306
+ const nextToolCalls = [...toolCalls2 || []];
21441
23307
  nextToolCalls[toolIndex] = {
21442
23308
  index: toolIndex,
21443
23309
  id: toolDelta.id,
@@ -21447,7 +23313,7 @@ function aggregateOpenRouterChatChunks(chunks) {
21447
23313
  arguments: toolDelta.function.arguments || ""
21448
23314
  }
21449
23315
  };
21450
- toolCalls = nextToolCalls;
23316
+ toolCalls2 = nextToolCalls;
21451
23317
  continue;
21452
23318
  }
21453
23319
  const current = existingToolCall;
@@ -21473,7 +23339,7 @@ function aggregateOpenRouterChatChunks(chunks) {
21473
23339
  ...hasReasoning || hasReasoningContent ? { reasoning } : {},
21474
23340
  ...hasReasoningContent ? { reasoning_content: reasoningContent } : {},
21475
23341
  ...reasoningDetails ? { reasoning_details: reasoningDetails } : {},
21476
- ...toolCalls ? { tool_calls: toolCalls } : {}
23342
+ ...toolCalls2 ? { tool_calls: toolCalls2 } : {}
21477
23343
  },
21478
23344
  logprobs: null,
21479
23345
  finish_reason: finishReason
@@ -22318,8 +24184,8 @@ function appendMistralContent(accumulator, content) {
22318
24184
  delete accumulator.content;
22319
24185
  }
22320
24186
  function getDeltaToolCalls(delta) {
22321
- const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
22322
- return toolCalls.filter((toolCall) => isObject(toolCall));
24187
+ const toolCalls2 = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
24188
+ return toolCalls2.filter((toolCall) => isObject(toolCall));
22323
24189
  }
22324
24190
  function getToolCallIndex(toolCall) {
22325
24191
  return typeof toolCall.index === "number" && toolCall.index >= 0 ? toolCall.index : void 0;
@@ -22346,11 +24212,11 @@ function mergeToolCallDeltaPair(current, delta) {
22346
24212
  }
22347
24213
  };
22348
24214
  }
22349
- function mergeToolCallDeltas(toolCalls, deltas) {
24215
+ function mergeToolCallDeltas(toolCalls2, deltas) {
22350
24216
  if (deltas.length === 0) {
22351
- return toolCalls;
24217
+ return toolCalls2;
22352
24218
  }
22353
- const merged = toolCalls ? [...toolCalls] : [];
24219
+ const merged = toolCalls2 ? [...toolCalls2] : [];
22354
24220
  const indexToPosition = /* @__PURE__ */ new Map();
22355
24221
  const idToPosition = /* @__PURE__ */ new Map();
22356
24222
  for (const [position, toolCall] of merged.entries()) {
@@ -23421,12 +25287,12 @@ function extractCohereChatOutput(result) {
23421
25287
  if (typeof result.text !== "string") {
23422
25288
  return void 0;
23423
25289
  }
23424
- const toolCalls = Array.isArray(result.toolCalls) ? result.toolCalls : Array.isArray(result.tool_calls) ? result.tool_calls : void 0;
23425
- if (toolCalls && toolCalls.length > 0) {
25290
+ const toolCalls2 = Array.isArray(result.toolCalls) ? result.toolCalls : Array.isArray(result.tool_calls) ? result.tool_calls : void 0;
25291
+ if (toolCalls2 && toolCalls2.length > 0) {
23426
25292
  return {
23427
25293
  content: result.text,
23428
25294
  role: "assistant",
23429
- toolCalls
25295
+ toolCalls: toolCalls2
23430
25296
  };
23431
25297
  }
23432
25298
  return result.text;
@@ -23759,10 +25625,10 @@ function aggregateCohereChatStreamChunks(chunks) {
23759
25625
  continue;
23760
25626
  }
23761
25627
  if (eventType === "tool-call-start") {
23762
- const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
25628
+ const toolCalls2 = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
23763
25629
  Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
23764
25630
  ) : [];
23765
- for (const [index, toolCall] of toolCalls.entries()) {
25631
+ for (const [index, toolCall] of toolCalls2.entries()) {
23766
25632
  const normalizedIndex = getToolCallIndex2(
23767
25633
  toolCall,
23768
25634
  typeof chunk.index === "number" ? chunk.index : index
@@ -27837,14 +29703,14 @@ function normalizeAssistantMessage(message) {
27837
29703
  const thinking = message.content.flatMap(
27838
29704
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
27839
29705
  ).join("");
27840
- const toolCalls = message.content.flatMap(
29706
+ const toolCalls2 = message.content.flatMap(
27841
29707
  (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
27842
29708
  );
27843
29709
  return {
27844
29710
  role: "assistant",
27845
- content: text || (toolCalls.length > 0 ? null : ""),
29711
+ content: text || (toolCalls2.length > 0 ? null : ""),
27846
29712
  ...thinking ? { reasoning: thinking } : {},
27847
- ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
29713
+ ...toolCalls2.length > 0 ? { tool_calls: toolCalls2 } : {}
27848
29714
  };
27849
29715
  }
27850
29716
  function normalizeToolResultMessage(message) {
@@ -29427,8 +31293,10 @@ var exports_exports = {};
29427
31293
  __export(exports_exports, {
29428
31294
  Attachment: () => Attachment,
29429
31295
  AttachmentReference: () => AttachmentReference,
31296
+ BAGGAGE_HEADER: () => BAGGAGE_HEADER,
29430
31297
  BRAINTRUST_CURRENT_SPAN_STORE: () => BRAINTRUST_CURRENT_SPAN_STORE,
29431
31298
  BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME: () => BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
31299
+ BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
29432
31300
  BaseAttachment: () => BaseAttachment,
29433
31301
  BaseExperiment: () => BaseExperiment,
29434
31302
  BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
@@ -29461,6 +31329,7 @@ __export(exports_exports, {
29461
31329
  NOOP_SPAN: () => NOOP_SPAN,
29462
31330
  NOOP_SPAN_PERMALINK: () => NOOP_SPAN_PERMALINK,
29463
31331
  NoopSpan: () => NoopSpan,
31332
+ OTELIDGenerator: () => OTELIDGenerator,
29464
31333
  ObjectFetcher: () => ObjectFetcher,
29465
31334
  Project: () => Project2,
29466
31335
  ProjectNameIdMap: () => ProjectNameIdMap,
@@ -29472,6 +31341,8 @@ __export(exports_exports, {
29472
31341
  ScorerBuilder: () => ScorerBuilder,
29473
31342
  SpanFetcher: () => SpanFetcher,
29474
31343
  SpanImpl: () => SpanImpl,
31344
+ TRACEPARENT_HEADER: () => TRACEPARENT_HEADER,
31345
+ TRACESTATE_HEADER: () => TRACESTATE_HEADER,
29475
31346
  TestBackgroundLogger: () => TestBackgroundLogger,
29476
31347
  ToolBuilder: () => ToolBuilder,
29477
31348
  UUIDGenerator: () => UUIDGenerator,
@@ -29481,6 +31352,7 @@ __export(exports_exports, {
29481
31352
  _internalIso: () => isomorph_default,
29482
31353
  _internalSetInitialState: () => _internalSetInitialState,
29483
31354
  addAzureBlobHeaders: () => addAzureBlobHeaders,
31355
+ agentAssertionScorer: () => agentAssertionScorer,
29484
31356
  braintrustAISDKTelemetry: () => braintrustAISDKTelemetry,
29485
31357
  braintrustFlueInstrumentation: () => braintrustFlueInstrumentation,
29486
31358
  braintrustFlueObserver: () => braintrustFlueObserver,
@@ -29498,6 +31370,7 @@ __export(exports_exports, {
29498
31370
  devNullWritableStream: () => devNullWritableStream,
29499
31371
  evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
29500
31372
  evaluatorDefinitionsSchema: () => evaluatorDefinitionsSchema,
31373
+ extractTraceContextFromHeaders: () => extractTraceContextFromHeaders,
29501
31374
  flush: () => flush,
29502
31375
  getContextManager: () => getContextManager,
29503
31376
  getIdGenerator: () => getIdGenerator,
@@ -29511,6 +31384,7 @@ __export(exports_exports, {
29511
31384
  initFunction: () => initFunction,
29512
31385
  initLogger: () => initLogger,
29513
31386
  initNodeTestSuite: () => initNodeTestSuite,
31387
+ injectTraceContext: () => injectTraceContext,
29514
31388
  invoke: () => invoke,
29515
31389
  isTemplateFormat: () => isTemplateFormat,
29516
31390
  loadParameters: () => loadParameters,
@@ -29549,7 +31423,7 @@ __export(exports_exports, {
29549
31423
  traced: () => traced,
29550
31424
  updateSpan: () => updateSpan,
29551
31425
  uploadLogs3OverflowPayload: () => uploadLogs3OverflowPayload,
29552
- utf8ByteLength: () => utf8ByteLength,
31426
+ utf8ByteLength: () => utf8ByteLength2,
29553
31427
  withCurrent: () => withCurrent,
29554
31428
  withDataset: () => withDataset,
29555
31429
  withExperiment: () => withExperiment,
@@ -30142,6 +32016,7 @@ function wrapAISDK(aiSDK, options = {}) {
30142
32016
  case "Agent":
30143
32017
  case "Experimental_Agent":
30144
32018
  case "ToolLoopAgent":
32019
+ case "WorkflowAgent":
30145
32020
  return original ? wrapAgentClass(original, options) : original;
30146
32021
  }
30147
32022
  return original;
@@ -30160,10 +32035,10 @@ var wrapAgentClass = (AgentClass, options = {}) => {
30160
32035
  return new Proxy(instance, {
30161
32036
  get(instanceTarget, prop, instanceReceiver) {
30162
32037
  const original = Reflect.get(instanceTarget, prop, instanceTarget);
30163
- if (prop === "generate") {
32038
+ if (prop === "generate" && typeof original === "function" && instanceTarget.constructor.name !== "WorkflowAgent") {
30164
32039
  return wrapAgentGenerate(original, instanceTarget, options);
30165
32040
  }
30166
- if (prop === "stream") {
32041
+ if (prop === "stream" && typeof original === "function") {
30167
32042
  return wrapAgentStream(original, instanceTarget, options);
30168
32043
  }
30169
32044
  if (typeof original === "function") {
@@ -30178,7 +32053,7 @@ var wrapAgentClass = (AgentClass, options = {}) => {
30178
32053
  var wrapAgentGenerate = (generate, instance, options = {}) => {
30179
32054
  const defaultName = `${instance.constructor.name}.generate`;
30180
32055
  return async (params) => makeGenerateTextWrapper(
30181
- aiSDKChannels.generateText,
32056
+ generateChannelForAgent(instance.constructor.name),
30182
32057
  defaultName,
30183
32058
  generate.bind(instance),
30184
32059
  {
@@ -30188,19 +32063,42 @@ var wrapAgentGenerate = (generate, instance, options = {}) => {
30188
32063
  options
30189
32064
  )({ ...instance.settings, ...params });
30190
32065
  };
32066
+ function generateChannelForAgent(agentName) {
32067
+ if (agentName === "ToolLoopAgent") {
32068
+ return aiSDKChannels.toolLoopAgentGenerate;
32069
+ }
32070
+ return aiSDKChannels.agentGenerate;
32071
+ }
30191
32072
  var wrapAgentStream = (stream, instance, options = {}) => {
30192
32073
  const defaultName = `${instance.constructor.name}.stream`;
30193
- return (params) => makeStreamWrapper(
30194
- aiSDKChannels.agentStream,
30195
- defaultName,
30196
- stream.bind(instance),
30197
- {
30198
- self: instance,
30199
- spanType: "function" /* FUNCTION */
30200
- },
30201
- options
30202
- )({ ...instance.settings, ...params });
32074
+ return (params) => {
32075
+ const workflowAgent = instance.constructor.name === "WorkflowAgent";
32076
+ if (workflowAgent && currentWorkflowAgentWrapperSpan()) {
32077
+ const { span_info: _spanInfo, ...cleanParams } = params;
32078
+ return stream.call(instance, { ...instance.settings, ...cleanParams });
32079
+ }
32080
+ const trace = () => makeStreamWrapper(
32081
+ streamChannelForAgent(instance.constructor.name),
32082
+ defaultName,
32083
+ stream.bind(instance),
32084
+ {
32085
+ self: instance,
32086
+ spanType: "function" /* FUNCTION */
32087
+ },
32088
+ options
32089
+ )({ ...instance.settings, ...params });
32090
+ return trace();
32091
+ };
30203
32092
  };
32093
+ function streamChannelForAgent(agentName) {
32094
+ if (agentName === "ToolLoopAgent") {
32095
+ return aiSDKChannels.toolLoopAgentStream;
32096
+ }
32097
+ if (agentName === "WorkflowAgent") {
32098
+ return aiSDKChannels.workflowAgentStream;
32099
+ }
32100
+ return aiSDKChannels.agentStream;
32101
+ }
30204
32102
  var makeGenerateTextWrapper = (channel2, name, generateText, contextOptions = {}, options = {}) => {
30205
32103
  const wrapper = async function(allParams) {
30206
32104
  const { span_info, ...params } = allParams;
@@ -30462,7 +32360,7 @@ var BraintrustLanguageModelWrapper = class {
30462
32360
  let time_to_first_token = void 0;
30463
32361
  let usage = void 0;
30464
32362
  let fullText = void 0;
30465
- const toolCalls = {};
32363
+ const toolCalls2 = {};
30466
32364
  let finishReason = void 0;
30467
32365
  return {
30468
32366
  ...ret,
@@ -30481,7 +32379,7 @@ var BraintrustLanguageModelWrapper = class {
30481
32379
  fullText += chunk.textDelta;
30482
32380
  break;
30483
32381
  case "tool-call":
30484
- toolCalls[chunk.toolCallId] = {
32382
+ toolCalls2[chunk.toolCallId] = {
30485
32383
  toolCallType: chunk.toolCallType,
30486
32384
  toolCallId: chunk.toolCallId,
30487
32385
  toolName: chunk.toolName,
@@ -30489,15 +32387,15 @@ var BraintrustLanguageModelWrapper = class {
30489
32387
  };
30490
32388
  break;
30491
32389
  case "tool-call-delta":
30492
- if (toolCalls[chunk.toolCallId] === void 0) {
30493
- toolCalls[chunk.toolCallId] = {
32390
+ if (toolCalls2[chunk.toolCallId] === void 0) {
32391
+ toolCalls2[chunk.toolCallId] = {
30494
32392
  toolCallType: chunk.toolCallType,
30495
32393
  toolCallId: chunk.toolCallId,
30496
32394
  toolName: chunk.toolName,
30497
32395
  args: ""
30498
32396
  };
30499
32397
  }
30500
- toolCalls[chunk.toolCallId].args += chunk.argsTextDelta;
32398
+ toolCalls2[chunk.toolCallId].args += chunk.argsTextDelta;
30501
32399
  break;
30502
32400
  case "finish":
30503
32401
  usage = chunk.usage;
@@ -30510,7 +32408,7 @@ var BraintrustLanguageModelWrapper = class {
30510
32408
  span.log({
30511
32409
  output: postProcessOutput(
30512
32410
  fullText,
30513
- Object.keys(toolCalls).length > 0 ? Object.values(toolCalls) : void 0,
32411
+ Object.keys(toolCalls2).length > 0 ? Object.values(toolCalls2) : void 0,
30514
32412
  finishReason
30515
32413
  ),
30516
32414
  metrics: {
@@ -30611,15 +32509,15 @@ function postProcessPrompt(prompt) {
30611
32509
  }
30612
32510
  });
30613
32511
  }
30614
- function postProcessOutput(text, toolCalls, finishReason) {
32512
+ function postProcessOutput(text, toolCalls2, finishReason) {
30615
32513
  return [
30616
32514
  {
30617
32515
  index: 0,
30618
32516
  message: {
30619
32517
  role: "assistant",
30620
32518
  content: text ?? "",
30621
- ...toolCalls && toolCalls.length > 0 ? {
30622
- tool_calls: toolCalls.map((toolCall) => ({
32519
+ ...toolCalls2 && toolCalls2.length > 0 ? {
32520
+ tool_calls: toolCalls2.map((toolCall) => ({
30623
32521
  id: toolCall.toolCallId,
30624
32522
  function: {
30625
32523
  name: toolCall.toolName,
@@ -30718,29 +32616,29 @@ function normalizeFinishReason(reason) {
30718
32616
  if (typeof reason !== "string") return void 0;
30719
32617
  return reason.replace(/-/g, "_");
30720
32618
  }
30721
- function buildAssistantOutputWithToolCalls(result, toolCalls) {
32619
+ function buildAssistantOutputWithToolCalls(result, toolCalls2) {
30722
32620
  return [
30723
32621
  {
30724
32622
  index: 0,
30725
32623
  logprobs: null,
30726
- finish_reason: normalizeFinishReason(result?.finishReason) ?? (toolCalls.length ? "tool_calls" : void 0),
32624
+ finish_reason: normalizeFinishReason(result?.finishReason) ?? (toolCalls2.length ? "tool_calls" : void 0),
30727
32625
  message: {
30728
32626
  role: "assistant",
30729
- tool_calls: toolCalls.length > 0 ? toolCalls : void 0
32627
+ tool_calls: toolCalls2.length > 0 ? toolCalls2 : void 0
30730
32628
  }
30731
32629
  }
30732
32630
  ];
30733
32631
  }
30734
32632
  function extractToolCallsFromSteps(steps) {
30735
- const toolCalls = [];
30736
- if (!Array.isArray(steps)) return toolCalls;
32633
+ const toolCalls2 = [];
32634
+ if (!Array.isArray(steps)) return toolCalls2;
30737
32635
  let idx = 0;
30738
32636
  for (const step of steps) {
30739
32637
  const blocks = step?.content;
30740
32638
  if (!Array.isArray(blocks)) continue;
30741
32639
  for (const block of blocks) {
30742
32640
  if (block && typeof block === "object" && block.type === "tool-call") {
30743
- toolCalls.push({
32641
+ toolCalls2.push({
30744
32642
  id: block.toolCallId,
30745
32643
  type: "function",
30746
32644
  index: idx++,
@@ -30752,7 +32650,7 @@ function extractToolCallsFromSteps(steps) {
30752
32650
  }
30753
32651
  }
30754
32652
  }
30755
- return toolCalls;
32653
+ return toolCalls2;
30756
32654
  }
30757
32655
  function extractToolCallsFromBlocks(blocks) {
30758
32656
  if (!Array.isArray(blocks)) return [];
@@ -30818,12 +32716,12 @@ function BraintrustMiddleware(config = {}) {
30818
32716
  metadata.model = modelId;
30819
32717
  }
30820
32718
  }
30821
- let toolCalls = extractToolCallsFromSteps(result?.steps);
30822
- if (!toolCalls || toolCalls.length === 0) {
30823
- toolCalls = extractToolCallsFromBlocks(result?.content);
32719
+ let toolCalls2 = extractToolCallsFromSteps(result?.steps);
32720
+ if (!toolCalls2 || toolCalls2.length === 0) {
32721
+ toolCalls2 = extractToolCallsFromBlocks(result?.content);
30824
32722
  }
30825
32723
  span.log({
30826
- output: toolCalls.length > 0 ? buildAssistantOutputWithToolCalls(result, toolCalls) : result?.content,
32724
+ output: toolCalls2.length > 0 ? buildAssistantOutputWithToolCalls(result, toolCalls2) : result?.content,
30827
32725
  metadata,
30828
32726
  metrics: normalizeUsageMetrics(
30829
32727
  result.usage,
@@ -30912,13 +32810,13 @@ function BraintrustMiddleware(config = {}) {
30912
32810
  metadata.model = model;
30913
32811
  }
30914
32812
  if (toolBlocks.length > 0) {
30915
- const toolCalls = extractToolCallsFromSteps([
32813
+ const toolCalls2 = extractToolCallsFromSteps([
30916
32814
  { content: toolBlocks }
30917
32815
  ]);
30918
- if (toolCalls.length > 0) {
32816
+ if (toolCalls2.length > 0) {
30919
32817
  output = buildAssistantOutputWithToolCalls(
30920
32818
  resultForDetection,
30921
- toolCalls
32819
+ toolCalls2
30922
32820
  );
30923
32821
  }
30924
32822
  }
@@ -31553,9 +33451,9 @@ function isModuleNamespace3(obj) {
31553
33451
  const descriptor = Object.getOwnPropertyDescriptor(obj, keys[0]);
31554
33452
  return descriptor ? !descriptor.configurable && !descriptor.writable : false;
31555
33453
  }
31556
- function wrapCursorAgentClass(Agent) {
33454
+ function wrapCursorAgentClass(Agent2) {
31557
33455
  const cache = /* @__PURE__ */ new Map();
31558
- return new Proxy(Agent, {
33456
+ return new Proxy(Agent2, {
31559
33457
  get(target, prop, receiver) {
31560
33458
  if (cache.has(prop)) {
31561
33459
  return cache.get(prop);
@@ -35103,15 +37001,21 @@ var waterfall$1 = awaitify(waterfall);
35103
37001
 
35104
37002
  // src/trace.ts
35105
37003
  var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
35106
- constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false) {
37004
+ constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true) {
35107
37005
  const filterExpr = _SpanFetcher.buildFilter(
35108
37006
  rootSpanId,
35109
37007
  spanTypeFilter,
35110
37008
  includeScorers
35111
37009
  );
35112
- super(objectType, void 0, void 0, {
35113
- filter: filterExpr
35114
- });
37010
+ super(
37011
+ objectType,
37012
+ void 0,
37013
+ void 0,
37014
+ {
37015
+ filter: filterExpr
37016
+ },
37017
+ brainstoreRealtime
37018
+ );
35115
37019
  this._objectId = _objectId;
35116
37020
  this.rootSpanId = rootSpanId;
35117
37021
  this._state = _state;
@@ -35165,7 +37069,7 @@ var CachedSpanFetcher = class {
35165
37069
  spanCache = /* @__PURE__ */ new Map();
35166
37070
  allFetched = false;
35167
37071
  fetchFn;
35168
- constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState) {
37072
+ constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState, brainstoreRealtime = true) {
35169
37073
  if (typeof objectTypeOrFetchFn === "function") {
35170
37074
  this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
35171
37075
  } else {
@@ -35178,7 +37082,8 @@ var CachedSpanFetcher = class {
35178
37082
  rootSpanId,
35179
37083
  state,
35180
37084
  spanType,
35181
- includeScorers
37085
+ includeScorers,
37086
+ brainstoreRealtime
35182
37087
  );
35183
37088
  const rows = await fetcher.fetchedData();
35184
37089
  return rows.map((row) => ({
@@ -36008,7 +37913,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
36008
37913
  }
36009
37914
  };
36010
37915
  const parentStr = state.currentParent.getStore();
36011
- const parentComponents = parentStr ? SpanComponentsV3.fromStr(parentStr) : null;
37916
+ const parentComponents = typeof parentStr === "string" ? SpanComponentsV4.fromStr(parentStr) : null;
36012
37917
  const trace = state ? new LocalTrace({
36013
37918
  objectType: parentComponents ? spanObjectTypeV3ToTypedString(
36014
37919
  parentComponents.data.object_type
@@ -36534,6 +38439,350 @@ var defaultReporter = {
36534
38439
  }
36535
38440
  };
36536
38441
 
38442
+ // src/agent-assertions.ts
38443
+ function agentAssertionScorer(callback, options = {}) {
38444
+ return async (args) => {
38445
+ const { trace: _trace, ...callbackArgs } = args;
38446
+ const callbackMetadata = callbackArgs.metadata ?? {};
38447
+ const assertions = await callback({
38448
+ ...callbackArgs,
38449
+ metadata: callbackMetadata,
38450
+ assert: agentAssertionHelpers
38451
+ });
38452
+ const resources = {};
38453
+ if (assertions.some((assertion) => assertion.requiresTrace)) {
38454
+ resources.spans = await args.trace?.getSpans({ spanType: ["tool"] });
38455
+ }
38456
+ const results = await Promise.all(
38457
+ assertions.map(async (assertion) => {
38458
+ const result = await assertion.evaluate(resources);
38459
+ return {
38460
+ name: assertion.name,
38461
+ passed: result.passed,
38462
+ failure: result.failure
38463
+ };
38464
+ })
38465
+ );
38466
+ const passed = results.filter((result) => result.passed).length;
38467
+ const total = results.length;
38468
+ const failed = results.filter((result) => !result.passed).map(
38469
+ (result) => `${result.name}: ${result.failure ?? "assertion did not pass"}`
38470
+ );
38471
+ return {
38472
+ name: options.name ?? "assertions",
38473
+ score: total === 0 ? 1 : passed / total,
38474
+ metadata: {
38475
+ assertions: results.map(({ name, passed: passed2 }) => ({ name, passed: passed2 })),
38476
+ failed
38477
+ }
38478
+ };
38479
+ };
38480
+ }
38481
+ var agentAssertionHelpers = {
38482
+ equals: (actual, expected, name = "equals") => ({
38483
+ name,
38484
+ evaluate: () => {
38485
+ const passed = deepEqual(actual, expected);
38486
+ return {
38487
+ passed,
38488
+ failure: passed ? void 0 : `expected ${formatValue(actual)} to equal ${formatValue(expected)}`
38489
+ };
38490
+ }
38491
+ }),
38492
+ notEquals: (actual, expected, name = "not equals") => ({
38493
+ name,
38494
+ evaluate: () => {
38495
+ const passed = !deepEqual(actual, expected);
38496
+ return {
38497
+ passed,
38498
+ failure: passed ? void 0 : `expected ${formatValue(actual)} not to equal ${formatValue(expected)}`
38499
+ };
38500
+ }
38501
+ }),
38502
+ contains: (value, expected, name = "contains") => ({
38503
+ name,
38504
+ evaluate: () => {
38505
+ const searchedValue = typeof value === "string" ? value : formatValue(value);
38506
+ const passed = expected instanceof RegExp ? testRegex(expected, value) : searchedValue.includes(expected);
38507
+ return {
38508
+ passed,
38509
+ failure: passed ? void 0 : `expected ${formatValue(value)} to contain ${formatValue(expected)}`
38510
+ };
38511
+ }
38512
+ }),
38513
+ matches: (value, schema, name = "matches schema") => ({
38514
+ name,
38515
+ evaluate: async () => {
38516
+ const result = await validateSchema(schema, value);
38517
+ return {
38518
+ passed: result.passed,
38519
+ failure: result.passed ? void 0 : `expected value to match schema: ${result.message}`
38520
+ };
38521
+ }
38522
+ }),
38523
+ calledTool: (toolName, options = {}, name = `called tool ${toolName}`) => ({
38524
+ name,
38525
+ requiresTrace: true,
38526
+ evaluate: ({ spans }) => {
38527
+ const calls = matchingToolCalls(spans ?? [], toolName, options);
38528
+ const passed = options.times === void 0 ? calls.length > 0 : calls.length === options.times;
38529
+ return {
38530
+ passed,
38531
+ failure: passed ? void 0 : options.times === void 0 ? `expected tool "${toolName}" to be called; found ${calls.length} matching call${calls.length === 1 ? "" : "s"}` : `expected tool "${toolName}" to be called ${options.times} time${options.times === 1 ? "" : "s"}; found ${calls.length} matching call${calls.length === 1 ? "" : "s"}`
38532
+ };
38533
+ }
38534
+ }),
38535
+ notCalledTool: (toolName, name = `did not call tool ${toolName}`) => ({
38536
+ name,
38537
+ requiresTrace: true,
38538
+ evaluate: ({ spans }) => {
38539
+ const calls = toolCalls(spans ?? []).filter(
38540
+ (span) => getToolName(span) === toolName
38541
+ );
38542
+ const passed = calls.length === 0;
38543
+ return {
38544
+ passed,
38545
+ failure: passed ? void 0 : `expected tool "${toolName}" not to be called; found ${calls.length} call${calls.length === 1 ? "" : "s"}`
38546
+ };
38547
+ }
38548
+ }),
38549
+ toolOrder: (toolNames, name = "tool order") => ({
38550
+ name,
38551
+ requiresTrace: true,
38552
+ evaluate: ({ spans }) => {
38553
+ const observed = toolCalls(spans ?? []).map(getToolName).filter((toolName) => toolName !== void 0);
38554
+ let fromIndex = 0;
38555
+ const passed = toolNames.every((toolName) => {
38556
+ const index = observed.indexOf(toolName, fromIndex);
38557
+ if (index === -1) return false;
38558
+ fromIndex = index + 1;
38559
+ return true;
38560
+ });
38561
+ return {
38562
+ passed,
38563
+ failure: passed ? void 0 : `expected tool order ${toolNames.join(" -> ")}; observed ${observed.join(" -> ") || "no tools"}`
38564
+ };
38565
+ }
38566
+ }),
38567
+ usedNoTools: (name = "used no tools") => ({
38568
+ name,
38569
+ requiresTrace: true,
38570
+ evaluate: ({ spans }) => {
38571
+ const calls = toolCalls(spans ?? []);
38572
+ const passed = calls.length === 0;
38573
+ return {
38574
+ passed,
38575
+ failure: passed ? void 0 : `expected no tool calls; found ${calls.length}`
38576
+ };
38577
+ }
38578
+ }),
38579
+ maxToolCalls: (max, name = `at most ${max} tool calls`) => ({
38580
+ name,
38581
+ requiresTrace: true,
38582
+ evaluate: ({ spans }) => {
38583
+ const calls = toolCalls(spans ?? []);
38584
+ const passed = calls.length <= max;
38585
+ return {
38586
+ passed,
38587
+ failure: passed ? void 0 : `expected at most ${max} tool call${max === 1 ? "" : "s"}; found ${calls.length}`
38588
+ };
38589
+ }
38590
+ })
38591
+ };
38592
+ async function validateSchema(schema, value) {
38593
+ try {
38594
+ if ("safeParse" in schema) {
38595
+ const result2 = schema.safeParse(value);
38596
+ return result2.success ? { passed: true, message: "" } : { passed: false, message: formatSchemaError(result2.error) };
38597
+ }
38598
+ if ("parse" in schema) {
38599
+ schema.parse(value);
38600
+ return { passed: true, message: "" };
38601
+ }
38602
+ const result = await schema["~standard"].validate(value);
38603
+ if (typeof result === "object" && result !== null && "issues" in result && Array.isArray(result.issues) && result.issues.length > 0) {
38604
+ return { passed: false, message: formatValue(result.issues) };
38605
+ }
38606
+ return { passed: true, message: "" };
38607
+ } catch (e) {
38608
+ return { passed: false, message: formatSchemaError(e) };
38609
+ }
38610
+ }
38611
+ function toolCalls(spans) {
38612
+ return spans.filter((span) => span.span_attributes?.type === "tool");
38613
+ }
38614
+ function matchingToolCalls(spans, toolName, options) {
38615
+ return toolCalls(spans).filter((span) => {
38616
+ if (getToolName(span) !== toolName) return false;
38617
+ if (Object.prototype.hasOwnProperty.call(options, "input") && !matchesValue(span.input, options.input)) {
38618
+ return false;
38619
+ }
38620
+ if (Object.prototype.hasOwnProperty.call(options, "output") && !matchesValue(span.output, options.output)) {
38621
+ return false;
38622
+ }
38623
+ if (options.isError !== void 0 && Boolean(span.error) !== options.isError) {
38624
+ return false;
38625
+ }
38626
+ return true;
38627
+ });
38628
+ }
38629
+ function getToolName(span) {
38630
+ const spanName = [span.span_attributes?.name, span.name].map(normalizeToolName).find((value) => value !== void 0);
38631
+ if (spanName?.includes("/")) {
38632
+ return spanName;
38633
+ }
38634
+ const metadataName = [
38635
+ span.metadata?.tool_name,
38636
+ span.metadata?.["gen_ai.tool.name"]
38637
+ ].map(normalizeToolName).find((value) => value !== void 0);
38638
+ const mcpServer = [
38639
+ span.metadata?.["mcp.server"],
38640
+ span.metadata?.["openai_codex.mcp.server"]
38641
+ ].find((value) => typeof value === "string" && value !== "");
38642
+ if (metadataName && mcpServer) {
38643
+ return `${mcpServer}/${metadataName}`;
38644
+ }
38645
+ return metadataName ?? spanName;
38646
+ }
38647
+ function normalizeToolName(value) {
38648
+ if (typeof value !== "string" || value === "") {
38649
+ return void 0;
38650
+ }
38651
+ return value.startsWith("tool:") ? value.slice("tool:".length).trim() : value;
38652
+ }
38653
+ function matchesValue(actual, matcher) {
38654
+ if (matcher instanceof RegExp) {
38655
+ return testRegex(matcher, actual);
38656
+ }
38657
+ if (typeof matcher === "function") {
38658
+ return matcher(actual);
38659
+ }
38660
+ if (Array.isArray(matcher)) {
38661
+ return Array.isArray(actual) && actual.length === matcher.length && matcher.every((value, index) => matchesValue(actual[index], value));
38662
+ }
38663
+ if (isPlainObject(matcher) && isPlainObject(actual)) {
38664
+ return Object.entries(matcher).every(
38665
+ ([key, value]) => Object.prototype.hasOwnProperty.call(actual, key) && matchesValue(actual[key], value)
38666
+ );
38667
+ }
38668
+ return deepEqual(actual, matcher);
38669
+ }
38670
+ function testRegex(matcher, value) {
38671
+ matcher.lastIndex = 0;
38672
+ return matcher.test(typeof value === "string" ? value : formatValue(value));
38673
+ }
38674
+ function deepEqual(left, right) {
38675
+ if (Object.is(left, right)) return true;
38676
+ if (Array.isArray(left) && Array.isArray(right)) {
38677
+ return left.length === right.length && left.every((item, index) => deepEqual(item, right[index]));
38678
+ }
38679
+ if (isPlainObject(left) && isPlainObject(right)) {
38680
+ const leftKeys = Object.keys(left);
38681
+ const rightKeys = Object.keys(right);
38682
+ return leftKeys.length === rightKeys.length && leftKeys.every(
38683
+ (key) => Object.prototype.hasOwnProperty.call(right, key) && deepEqual(left[key], right[key])
38684
+ );
38685
+ }
38686
+ return false;
38687
+ }
38688
+ function isPlainObject(value) {
38689
+ return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
38690
+ }
38691
+ function formatSchemaError(error) {
38692
+ if (error instanceof Error) {
38693
+ return error.message;
38694
+ }
38695
+ return formatValue(error);
38696
+ }
38697
+ function formatValue(value) {
38698
+ if (value instanceof RegExp) {
38699
+ return value.toString();
38700
+ }
38701
+ if (typeof value === "string") {
38702
+ return JSON.stringify(value);
38703
+ }
38704
+ try {
38705
+ const serialized = JSON.stringify(value);
38706
+ if (serialized !== void 0 && !hasUndefinedJsonValue(value)) {
38707
+ return serialized;
38708
+ }
38709
+ return formatValueWithUndefined(value, /* @__PURE__ */ new Set());
38710
+ } catch {
38711
+ return String(value);
38712
+ }
38713
+ }
38714
+ function hasUndefinedJsonValue(value, seen = /* @__PURE__ */ new Set()) {
38715
+ if (value === void 0) {
38716
+ return true;
38717
+ }
38718
+ if (typeof value !== "object" || value === null) {
38719
+ return false;
38720
+ }
38721
+ if (seen.has(value)) {
38722
+ return false;
38723
+ }
38724
+ seen.add(value);
38725
+ if (Array.isArray(value)) {
38726
+ return Array.from({ length: value.length }).some(
38727
+ (_, index) => hasUndefinedJsonValue(value[index], seen)
38728
+ );
38729
+ }
38730
+ return Object.keys(value).some(
38731
+ (key) => hasUndefinedJsonValue(value[key], seen)
38732
+ );
38733
+ }
38734
+ function formatValueWithUndefined(value, seen) {
38735
+ if (value === void 0) {
38736
+ return "undefined";
38737
+ }
38738
+ if (value === null) {
38739
+ return "null";
38740
+ }
38741
+ if (typeof value === "string") {
38742
+ return JSON.stringify(value);
38743
+ }
38744
+ if (typeof value === "number" || typeof value === "boolean") {
38745
+ return JSON.stringify(value);
38746
+ }
38747
+ if (typeof value === "bigint" || typeof value === "function") {
38748
+ return String(value);
38749
+ }
38750
+ if (typeof value === "symbol") {
38751
+ return String(value);
38752
+ }
38753
+ if (value instanceof RegExp) {
38754
+ return value.toString();
38755
+ }
38756
+ if (typeof value !== "object") {
38757
+ return String(value);
38758
+ }
38759
+ if (seen.has(value)) {
38760
+ return '"[Circular]"';
38761
+ }
38762
+ seen.add(value);
38763
+ if (typeof value.toJSON === "function") {
38764
+ const jsonValue = value.toJSON();
38765
+ seen.delete(value);
38766
+ return formatValueWithUndefined(jsonValue, seen);
38767
+ }
38768
+ if (Array.isArray(value)) {
38769
+ const formatted2 = Array.from(
38770
+ { length: value.length },
38771
+ (_, index) => formatValueWithUndefined(value[index], seen)
38772
+ );
38773
+ seen.delete(value);
38774
+ return `[${formatted2.join(",")}]`;
38775
+ }
38776
+ const formatted = Object.keys(value).map(
38777
+ (key) => `${JSON.stringify(key)}:${formatValueWithUndefined(
38778
+ value[key],
38779
+ seen
38780
+ )}`
38781
+ );
38782
+ seen.delete(value);
38783
+ return `{${formatted.join(",")}}`;
38784
+ }
38785
+
36537
38786
  // src/dataset-pipeline.ts
36538
38787
  function DatasetPipeline(definition) {
36539
38788
  if (!globalThis.__braintrust_dataset_pipelines) {
@@ -37110,8 +39359,10 @@ configureBrowser();
37110
39359
  export {
37111
39360
  Attachment,
37112
39361
  AttachmentReference,
39362
+ BAGGAGE_HEADER,
37113
39363
  BRAINTRUST_CURRENT_SPAN_STORE,
37114
39364
  BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
39365
+ BRAINTRUST_PARENT_KEY,
37115
39366
  BaseAttachment,
37116
39367
  BaseExperiment,
37117
39368
  BraintrustLangChainCallbackHandler,
@@ -37144,6 +39395,7 @@ export {
37144
39395
  NOOP_SPAN,
37145
39396
  NOOP_SPAN_PERMALINK,
37146
39397
  NoopSpan,
39398
+ OTELIDGenerator,
37147
39399
  ObjectFetcher,
37148
39400
  Project2 as Project,
37149
39401
  ProjectNameIdMap,
@@ -37155,6 +39407,8 @@ export {
37155
39407
  ScorerBuilder,
37156
39408
  SpanFetcher,
37157
39409
  SpanImpl,
39410
+ TRACEPARENT_HEADER,
39411
+ TRACESTATE_HEADER,
37158
39412
  TestBackgroundLogger,
37159
39413
  ToolBuilder,
37160
39414
  UUIDGenerator,
@@ -37164,6 +39418,7 @@ export {
37164
39418
  isomorph_default as _internalIso,
37165
39419
  _internalSetInitialState,
37166
39420
  addAzureBlobHeaders,
39421
+ agentAssertionScorer,
37167
39422
  braintrustAISDKTelemetry,
37168
39423
  braintrustFlueInstrumentation,
37169
39424
  braintrustFlueObserver,
@@ -37182,6 +39437,7 @@ export {
37182
39437
  devNullWritableStream,
37183
39438
  evaluatorDefinitionSchema,
37184
39439
  evaluatorDefinitionsSchema,
39440
+ extractTraceContextFromHeaders,
37185
39441
  flush,
37186
39442
  getContextManager,
37187
39443
  getIdGenerator,
@@ -37195,6 +39451,7 @@ export {
37195
39451
  initFunction,
37196
39452
  initLogger,
37197
39453
  initNodeTestSuite,
39454
+ injectTraceContext,
37198
39455
  invoke,
37199
39456
  isTemplateFormat,
37200
39457
  loadParameters,
@@ -37233,7 +39490,7 @@ export {
37233
39490
  traced,
37234
39491
  updateSpan,
37235
39492
  uploadLogs3OverflowPayload,
37236
- utf8ByteLength,
39493
+ utf8ByteLength2 as utf8ByteLength,
37237
39494
  withCurrent,
37238
39495
  withDataset,
37239
39496
  withExperiment,