braintrust 3.20.0 → 3.22.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 +6 -0
  3. package/dev/dist/index.d.mts +1338 -199
  4. package/dev/dist/index.d.ts +1338 -199
  5. package/dev/dist/index.js +2904 -997
  6. package/dev/dist/index.mjs +2418 -511
  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 +824 -56
  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 +4411 -719
  49. package/dist/browser.d.ts +4411 -719
  50. package/dist/browser.js +4274 -480
  51. package/dist/browser.mjs +4274 -480
  52. package/dist/{chunk-LPC4W2WX.js → chunk-BFGIH2ZJ.js} +4 -0
  53. package/dist/{chunk-Y7W7WP6H.mjs → chunk-KMGUTPB7.mjs} +4 -0
  54. package/dist/{chunk-POCCIJAL.js → chunk-MWVVR5LR.js} +3278 -1334
  55. package/dist/{chunk-F73OMF66.mjs → chunk-ZG2O3XVF.mjs} +2542 -598
  56. package/dist/cli.js +2338 -419
  57. package/dist/edge-light.d.mts +1 -1
  58. package/dist/edge-light.d.ts +1 -1
  59. package/dist/edge-light.js +4274 -480
  60. package/dist/edge-light.mjs +4274 -480
  61. package/dist/index.d.mts +4926 -1234
  62. package/dist/index.d.ts +4926 -1234
  63. package/dist/index.js +2303 -435
  64. package/dist/index.mjs +1914 -46
  65. package/dist/instrumentation/index.d.mts +1026 -20
  66. package/dist/instrumentation/index.d.ts +1026 -20
  67. package/dist/instrumentation/index.js +3864 -483
  68. package/dist/instrumentation/index.mjs +3862 -483
  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 +4274 -480
  74. package/dist/workerd.mjs +4274 -480
  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 +16 -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
@@ -30,10 +30,121 @@ import {
30
30
  smithyClientChannels,
31
31
  smithyCoreChannels,
32
32
  strandsAgentSDKChannels
33
- } from "./chunk-Y7W7WP6H.mjs";
33
+ } from "./chunk-KMGUTPB7.mjs";
34
34
 
35
35
  // src/id-gen.ts
36
36
  import { v4 as uuidv4 } from "uuid";
37
+
38
+ // src/debug-logger.ts
39
+ var PREFIX = "[braintrust]";
40
+ var DEBUG_LOG_LEVEL_SYMBOL = /* @__PURE__ */ Symbol.for("braintrust-debug-log-level");
41
+ var LOG_LEVEL_PRIORITY = {
42
+ error: 0,
43
+ warn: 1,
44
+ info: 2,
45
+ debug: 3
46
+ };
47
+ var hasWarnedAboutInvalidEnvValue = false;
48
+ var debugLogStateResolver = void 0;
49
+ function warnInvalidEnvValue(value) {
50
+ if (hasWarnedAboutInvalidEnvValue) {
51
+ return;
52
+ }
53
+ hasWarnedAboutInvalidEnvValue = true;
54
+ console.warn(
55
+ PREFIX,
56
+ `Invalid BRAINTRUST_DEBUG_LOG_LEVEL value "${value}". Expected "error", "warn", "info", or "debug".`
57
+ );
58
+ }
59
+ function normalizeDebugLogLevelOption(option) {
60
+ if (option === false) {
61
+ return void 0;
62
+ }
63
+ if (option === "error" || option === "warn" || option === "info" || option === "debug") {
64
+ return option;
65
+ }
66
+ throw new Error(
67
+ `Invalid debugLogLevel value "${option}". Expected false, "error", "warn", "info", or "debug".`
68
+ );
69
+ }
70
+ function parseDebugLogLevelEnv(value) {
71
+ if (!value) {
72
+ return void 0;
73
+ }
74
+ if (value === "error" || value === "warn" || value === "info" || value === "debug") {
75
+ return value;
76
+ }
77
+ warnInvalidEnvValue(value);
78
+ return void 0;
79
+ }
80
+ function getEnvDebugLogLevel() {
81
+ return parseDebugLogLevelEnv(isomorph_default.getEnv("BRAINTRUST_DEBUG_LOG_LEVEL"));
82
+ }
83
+ function setGlobalDebugLogLevel(level) {
84
+ globalThis[DEBUG_LOG_LEVEL_SYMBOL] = level;
85
+ }
86
+ function resetDebugLoggerForTests() {
87
+ hasWarnedAboutInvalidEnvValue = false;
88
+ setGlobalDebugLogLevel(void 0);
89
+ }
90
+ function setDebugLogStateResolver(resolver) {
91
+ debugLogStateResolver = resolver;
92
+ }
93
+ function resolveDebugLogLevel(state) {
94
+ const stateLevel = state?.getDebugLogLevel?.();
95
+ const hasStateOverride = state?.hasDebugLogLevelOverride?.() ?? false;
96
+ if (hasStateOverride) {
97
+ return stateLevel;
98
+ }
99
+ const globalLevel = (
100
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
101
+ globalThis[DEBUG_LOG_LEVEL_SYMBOL]
102
+ );
103
+ if (globalLevel !== void 0) {
104
+ return globalLevel === false ? void 0 : globalLevel;
105
+ }
106
+ return getEnvDebugLogLevel();
107
+ }
108
+ function emit(method, state, args) {
109
+ const level = resolveDebugLogLevel(state);
110
+ if (!level || LOG_LEVEL_PRIORITY[method] > LOG_LEVEL_PRIORITY[level]) {
111
+ return;
112
+ }
113
+ if (method === "info") {
114
+ console.log(PREFIX, ...args);
115
+ } else if (method === "debug") {
116
+ console.debug(PREFIX, ...args);
117
+ } else if (method === "warn") {
118
+ console.warn(PREFIX, ...args);
119
+ } else {
120
+ console.error(PREFIX, ...args);
121
+ }
122
+ }
123
+ function createDebugLogger(state) {
124
+ const resolveState = () => state ?? debugLogStateResolver?.();
125
+ return {
126
+ info(...args) {
127
+ emit("info", resolveState(), args);
128
+ },
129
+ debug(...args) {
130
+ emit("debug", resolveState(), args);
131
+ },
132
+ warn(...args) {
133
+ emit("warn", resolveState(), args);
134
+ },
135
+ error(...args) {
136
+ emit("error", resolveState(), args);
137
+ }
138
+ };
139
+ }
140
+ var debugLogger = {
141
+ ...createDebugLogger(),
142
+ forState(state) {
143
+ return createDebugLogger(state);
144
+ }
145
+ };
146
+
147
+ // src/id-gen.ts
37
148
  var IDGenerator = class {
38
149
  };
39
150
  var UUIDGenerator = class extends IDGenerator {
@@ -47,8 +158,291 @@ var UUIDGenerator = class extends IDGenerator {
47
158
  return true;
48
159
  }
49
160
  };
161
+ function generateHexId(bytes) {
162
+ let result = "";
163
+ for (let i = 0; i < bytes; i++) {
164
+ result += Math.floor(Math.random() * 256).toString(16).padStart(2, "0");
165
+ }
166
+ return result;
167
+ }
168
+ var OTELIDGenerator = class extends IDGenerator {
169
+ getSpanId() {
170
+ return generateHexId(8);
171
+ }
172
+ getTraceId() {
173
+ return generateHexId(16);
174
+ }
175
+ shareRootSpanId() {
176
+ return false;
177
+ }
178
+ };
179
+ function parseEnvBool(name) {
180
+ const raw = isomorph_default.getEnv(name);
181
+ if (raw === void 0 || raw === null) {
182
+ return false;
183
+ }
184
+ const normalized = raw.trim().toLowerCase();
185
+ return normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "y" || normalized === "on";
186
+ }
187
+ var _warnedLegacyUuidConflict = false;
188
+ function resolveUseLegacyUuidIds() {
189
+ const legacy = parseEnvBool("BRAINTRUST_LEGACY_IDS");
190
+ if (parseEnvBool("BRAINTRUST_OTEL_COMPAT")) {
191
+ if (legacy && !_warnedLegacyUuidConflict) {
192
+ _warnedLegacyUuidConflict = true;
193
+ debugLogger.warn(
194
+ "BRAINTRUST_LEGACY_IDS is ignored because BRAINTRUST_OTEL_COMPAT requires OpenTelemetry-compatible hex span IDs. Using hex IDs."
195
+ );
196
+ }
197
+ return false;
198
+ }
199
+ return legacy;
200
+ }
50
201
  function getIdGenerator() {
51
- return globalThis.BRAINTRUST_ID_GENERATOR !== void 0 ? new globalThis.BRAINTRUST_ID_GENERATOR() : new UUIDGenerator();
202
+ if (globalThis.BRAINTRUST_ID_GENERATOR !== void 0) {
203
+ return new globalThis.BRAINTRUST_ID_GENERATOR();
204
+ }
205
+ return resolveUseLegacyUuidIds() ? new UUIDGenerator() : new OTELIDGenerator();
206
+ }
207
+
208
+ // src/propagation.ts
209
+ var TRACEPARENT_HEADER = "traceparent";
210
+ var TRACESTATE_HEADER = "tracestate";
211
+ var BAGGAGE_HEADER = "baggage";
212
+ var BRAINTRUST_PARENT_KEY = "braintrust.parent";
213
+ var DEFAULT_TRACE_FLAGS = "01";
214
+ var TRACEPARENT_RE = /^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/;
215
+ var ZERO_TRACE_ID = "0".repeat(32);
216
+ var ZERO_SPAN_ID = "0".repeat(16);
217
+ var MAX_BAGGAGE_LENGTH = 8192;
218
+ var MAX_BAGGAGE_MEMBERS = 64;
219
+ var _utf8Encoder = new TextEncoder();
220
+ function utf8ByteLength(value) {
221
+ return _utf8Encoder.encode(value).length;
222
+ }
223
+ function capBaggageToMemberBoundary(value) {
224
+ const totalBytes = utf8ByteLength(value);
225
+ const withinBytes = totalBytes <= MAX_BAGGAGE_LENGTH;
226
+ let commaCount = 0;
227
+ for (let i = 0; i < value.length; i++) {
228
+ if (value.charCodeAt(i) === 44) {
229
+ commaCount++;
230
+ }
231
+ }
232
+ const withinMembers = commaCount < MAX_BAGGAGE_MEMBERS;
233
+ if (withinBytes && withinMembers) {
234
+ return value;
235
+ }
236
+ const kept = [];
237
+ let length = 0;
238
+ for (const rawMember of value.split(",")) {
239
+ if (kept.length >= MAX_BAGGAGE_MEMBERS) {
240
+ break;
241
+ }
242
+ const cost = utf8ByteLength(rawMember) + (kept.length ? 1 : 0);
243
+ if (length + cost > MAX_BAGGAGE_LENGTH) {
244
+ break;
245
+ }
246
+ kept.push(rawMember);
247
+ length += cost;
248
+ }
249
+ if (!kept.length) {
250
+ return "";
251
+ }
252
+ return kept.join(",");
253
+ }
254
+ function isTraceContextHeaderTupleArray(value) {
255
+ return Array.isArray(value) && value.every(
256
+ (item) => Array.isArray(item) && typeof item[0] === "string" && typeof item[1] === "string"
257
+ );
258
+ }
259
+ function isListHeader(name) {
260
+ const lowered = name.toLowerCase();
261
+ return lowered === BAGGAGE_HEADER || lowered === TRACESTATE_HEADER;
262
+ }
263
+ function headerValueToString(value, name) {
264
+ if (value === void 0 || value === null) {
265
+ return void 0;
266
+ }
267
+ if (Array.isArray(value)) {
268
+ const stringValues = value.filter((item) => {
269
+ return typeof item === "string";
270
+ });
271
+ if (!stringValues.length) {
272
+ return void 0;
273
+ }
274
+ return isListHeader(name) ? stringValues.join(",") : stringValues[0];
275
+ }
276
+ return typeof value === "string" ? value : String(value);
277
+ }
278
+ function getHeader(headers, name) {
279
+ if (!headers) {
280
+ return void 0;
281
+ }
282
+ if (isTraceContextHeaderTupleArray(headers)) {
283
+ const lowered2 = name.toLowerCase();
284
+ const matches = headers.filter(([key]) => key.toLowerCase() === lowered2).map(([, value]) => value);
285
+ if (!matches.length) {
286
+ return void 0;
287
+ }
288
+ return headerValueToString(matches, name);
289
+ }
290
+ const getter = headers.get;
291
+ if (typeof getter === "function") {
292
+ try {
293
+ const value = headerValueToString(getter.call(headers, name), name);
294
+ if (value !== void 0) {
295
+ return value;
296
+ }
297
+ } catch {
298
+ }
299
+ }
300
+ const nodeGetter = headers.getHeader;
301
+ if (typeof nodeGetter === "function") {
302
+ try {
303
+ const value = headerValueToString(nodeGetter.call(headers, name), name);
304
+ if (value !== void 0) {
305
+ return value;
306
+ }
307
+ } catch {
308
+ }
309
+ }
310
+ const headerBag = headers;
311
+ const exact = headerValueToString(headerBag[name], name);
312
+ if (exact !== void 0) {
313
+ return exact;
314
+ }
315
+ const lowered = name.toLowerCase();
316
+ for (const key of Object.keys(headers)) {
317
+ if (key !== name && key.toLowerCase() === lowered) {
318
+ const value = headerValueToString(headerBag[key], name);
319
+ if (value !== void 0) {
320
+ return value;
321
+ }
322
+ }
323
+ }
324
+ return void 0;
325
+ }
326
+ function isHex(value, length) {
327
+ if (typeof value !== "string" || value.length !== length) {
328
+ return false;
329
+ }
330
+ for (let i = 0; i < value.length; i++) {
331
+ const c = value[i];
332
+ const isDigit = c >= "0" && c <= "9";
333
+ const isLowerHex = c >= "a" && c <= "f";
334
+ if (!isDigit && !isLowerHex) {
335
+ return false;
336
+ }
337
+ }
338
+ return true;
339
+ }
340
+ function parseTraceparent(value) {
341
+ if (!value || typeof value !== "string") {
342
+ return void 0;
343
+ }
344
+ const match = TRACEPARENT_RE.exec(value.trim());
345
+ if (!match) {
346
+ return void 0;
347
+ }
348
+ const traceId = match[1];
349
+ const spanId = match[2];
350
+ const traceFlags = match[3];
351
+ if (traceId === ZERO_TRACE_ID || spanId === ZERO_SPAN_ID) {
352
+ return void 0;
353
+ }
354
+ return { traceId, spanId, traceFlags };
355
+ }
356
+ function formatTraceparent(traceId, spanId, traceFlags = DEFAULT_TRACE_FLAGS) {
357
+ if (!isHex(traceId, 32) || traceId === ZERO_TRACE_ID) {
358
+ return void 0;
359
+ }
360
+ if (!isHex(spanId, 16) || spanId === ZERO_SPAN_ID) {
361
+ return void 0;
362
+ }
363
+ const flags = isHex(traceFlags, 2) ? traceFlags : DEFAULT_TRACE_FLAGS;
364
+ return `00-${traceId}-${spanId}-${flags}`;
365
+ }
366
+ function percentEncode(value) {
367
+ return encodeURIComponent(value);
368
+ }
369
+ function percentDecode(value) {
370
+ if (!value.includes("%")) {
371
+ return value;
372
+ }
373
+ try {
374
+ return decodeURIComponent(value);
375
+ } catch {
376
+ return value;
377
+ }
378
+ }
379
+ function parseBaggage(value) {
380
+ const result = {};
381
+ if (!value || typeof value !== "string") {
382
+ return result;
383
+ }
384
+ const bounded = capBaggageToMemberBoundary(value);
385
+ for (let member of bounded.split(",")) {
386
+ member = member.trim();
387
+ if (!member || !member.includes("=")) {
388
+ continue;
389
+ }
390
+ member = member.split(";", 1)[0];
391
+ const eq = member.indexOf("=");
392
+ const key = percentDecode(member.slice(0, eq).trim());
393
+ const val = member.slice(eq + 1).trim();
394
+ if (!key) {
395
+ continue;
396
+ }
397
+ result[key] = percentDecode(val);
398
+ }
399
+ return result;
400
+ }
401
+ function mergeBaggage(existing, braintrustParent) {
402
+ let btMember = void 0;
403
+ if (braintrustParent) {
404
+ const encodedKey = percentEncode(BRAINTRUST_PARENT_KEY);
405
+ const encodedVal = percentEncode(String(braintrustParent));
406
+ btMember = `${encodedKey}=${encodedVal}`;
407
+ if (utf8ByteLength(btMember) > MAX_BAGGAGE_LENGTH) {
408
+ btMember = void 0;
409
+ }
410
+ }
411
+ let byteBudget = MAX_BAGGAGE_LENGTH;
412
+ let memberBudget = MAX_BAGGAGE_MEMBERS;
413
+ if (btMember !== void 0) {
414
+ byteBudget -= utf8ByteLength(btMember) + 1;
415
+ memberBudget -= 1;
416
+ }
417
+ const relayed = [];
418
+ let length = 0;
419
+ if (existing && typeof existing === "string") {
420
+ for (const rawMember of existing.split(",")) {
421
+ const member = rawMember.trim();
422
+ if (!member || !member.includes("=")) {
423
+ continue;
424
+ }
425
+ const keyPart = member.split(";", 1)[0].split("=", 1)[0];
426
+ const key = percentDecode(keyPart.trim());
427
+ if (key === BRAINTRUST_PARENT_KEY) {
428
+ continue;
429
+ }
430
+ if (relayed.length >= memberBudget) {
431
+ break;
432
+ }
433
+ const cost = utf8ByteLength(member) + (relayed.length ? 1 : 0);
434
+ if (length + cost > byteBudget) {
435
+ break;
436
+ }
437
+ relayed.push(member);
438
+ length += cost;
439
+ }
440
+ }
441
+ const members = btMember !== void 0 ? [...relayed, btMember] : relayed;
442
+ if (!members.length) {
443
+ return void 0;
444
+ }
445
+ return members.join(",");
52
446
  }
53
447
 
54
448
  // util/type_util.ts
@@ -670,7 +1064,7 @@ var SpanComponentsV3 = class _SpanComponentsV3 {
670
1064
  case 3 /* PLAYGROUND_LOGS */:
671
1065
  return { prompt_session_id: this.data.object_id, log_id: "x" };
672
1066
  default:
673
- const _ = this.data.object_type;
1067
+ this.data.object_type;
674
1068
  throw new Error("Impossible");
675
1069
  }
676
1070
  }
@@ -1185,7 +1579,7 @@ var SpanComponentsV4 = class _SpanComponentsV4 {
1185
1579
  case 3 /* PLAYGROUND_LOGS */:
1186
1580
  return { prompt_session_id: this.data.object_id, log_id: "x" };
1187
1581
  default:
1188
- const _ = this.data.object_type;
1582
+ this.data.object_type;
1189
1583
  throw new Error(`Invalid object_type ${this.data.object_type}`);
1190
1584
  }
1191
1585
  }
@@ -1364,7 +1758,8 @@ var AclObjectType = z6.union([
1364
1758
  "role",
1365
1759
  "org_member",
1366
1760
  "project_log",
1367
- "org_project"
1761
+ "org_project",
1762
+ "org_audit_logs"
1368
1763
  ]),
1369
1764
  z6.null()
1370
1765
  ]);
@@ -1390,6 +1785,17 @@ var Acl = z6.object({
1390
1785
  _object_org_id: z6.string().uuid(),
1391
1786
  created: z6.union([z6.string(), z6.null()]).optional()
1392
1787
  });
1788
+ var Agent = z6.object({
1789
+ id: z6.string().uuid(),
1790
+ project_id: z6.string().uuid(),
1791
+ user_id: z6.string().uuid(),
1792
+ created: z6.union([z6.string(), z6.null()]).optional(),
1793
+ name: z6.string(),
1794
+ slug: z6.string(),
1795
+ kind: z6.string(),
1796
+ description: z6.union([z6.string(), z6.null()]).optional(),
1797
+ metadata: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional()
1798
+ });
1393
1799
  var AISecret = z6.object({
1394
1800
  id: z6.string().uuid(),
1395
1801
  created: z6.union([z6.string(), z6.null()]).optional(),
@@ -1536,6 +1942,7 @@ var AttachmentStatus = z6.object({
1536
1942
  upload_status: UploadStatus,
1537
1943
  error_message: z6.string().optional()
1538
1944
  });
1945
+ var AutomationStatus = z6.enum(["active", "paused"]);
1539
1946
  var FunctionTypeEnum = z6.enum([
1540
1947
  "llm",
1541
1948
  "scorer",
@@ -1581,7 +1988,9 @@ var TopicMapData = z6.object({
1581
1988
  topic_names: z6.record(z6.string()).optional(),
1582
1989
  generation_settings: TopicMapGenerationSettings.optional(),
1583
1990
  disable_reconciliation: z6.boolean().optional(),
1584
- distance_threshold: z6.number().optional()
1991
+ distance_threshold: z6.number().optional(),
1992
+ btql_filter: z6.string().optional(),
1993
+ automation_btql_filter: z6.string().optional()
1585
1994
  });
1586
1995
  var BatchedFacetData = z6.object({
1587
1996
  type: z6.literal("batched_facet"),
@@ -1655,19 +2064,30 @@ var CallEvent = z6.union([
1655
2064
  var ChatCompletionContentPartTextWithTitle = z6.object({
1656
2065
  text: z6.string().default(""),
1657
2066
  type: z6.literal("text"),
1658
- cache_control: z6.object({ type: z6.literal("ephemeral") }).optional()
2067
+ cache_control: z6.object({
2068
+ type: z6.literal("ephemeral"),
2069
+ ttl: z6.enum(["5m", "1h"]).optional()
2070
+ }).optional()
1659
2071
  });
1660
2072
  var ChatCompletionContentPartImageWithTitle = z6.object({
1661
2073
  image_url: z6.object({
1662
2074
  url: z6.string(),
1663
2075
  detail: z6.union([z6.literal("auto"), z6.literal("low"), z6.literal("high")]).optional()
1664
2076
  }),
1665
- type: z6.literal("image_url")
2077
+ type: z6.literal("image_url"),
2078
+ cache_control: z6.object({
2079
+ type: z6.literal("ephemeral"),
2080
+ ttl: z6.enum(["5m", "1h"]).optional()
2081
+ }).optional()
1666
2082
  });
1667
2083
  var ChatCompletionContentPartFileFile = z6.object({ file_data: z6.string(), filename: z6.string(), file_id: z6.string() }).partial();
1668
2084
  var ChatCompletionContentPartFileWithTitle = z6.object({
1669
2085
  file: ChatCompletionContentPartFileFile,
1670
- type: z6.literal("file")
2086
+ type: z6.literal("file"),
2087
+ cache_control: z6.object({
2088
+ type: z6.literal("ephemeral"),
2089
+ ttl: z6.enum(["5m", "1h"]).optional()
2090
+ }).optional()
1671
2091
  });
1672
2092
  var ChatCompletionContentPart = z6.union([
1673
2093
  ChatCompletionContentPartTextWithTitle,
@@ -1677,7 +2097,10 @@ var ChatCompletionContentPart = z6.union([
1677
2097
  var ChatCompletionContentPartText = z6.object({
1678
2098
  text: z6.string().default(""),
1679
2099
  type: z6.literal("text"),
1680
- cache_control: z6.object({ type: z6.literal("ephemeral") }).optional()
2100
+ cache_control: z6.object({
2101
+ type: z6.literal("ephemeral"),
2102
+ ttl: z6.enum(["5m", "1h"]).optional()
2103
+ }).optional()
1681
2104
  });
1682
2105
  var ChatCompletionMessageToolCall = z6.object({
1683
2106
  id: z6.string(),
@@ -1864,7 +2287,7 @@ var DatasetEvent = z6.object({
1864
2287
  origin: ObjectReferenceNullish.optional(),
1865
2288
  comments: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
1866
2289
  audit_data: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
1867
- facets: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
2290
+ facets: z6.union([z6.record(z6.union([z6.string(), z6.null()])), z6.null()]).optional(),
1868
2291
  classifications: z6.union([
1869
2292
  z6.record(
1870
2293
  z6.array(
@@ -2016,7 +2439,7 @@ var ExperimentEvent = z6.object({
2016
2439
  origin: ObjectReferenceNullish.optional(),
2017
2440
  comments: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
2018
2441
  audit_data: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
2019
- facets: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
2442
+ facets: z6.union([z6.record(z6.union([z6.string(), z6.null()])), z6.null()]).optional(),
2020
2443
  classifications: z6.union([
2021
2444
  z6.record(
2022
2445
  z6.array(
@@ -2154,7 +2577,8 @@ var PromptParserNullish = z6.union([
2154
2577
  use_cot: z6.boolean(),
2155
2578
  choice_scores: z6.record(z6.number().gte(0).lte(1)).optional(),
2156
2579
  choice: z6.array(z6.string()).optional(),
2157
- allow_no_match: z6.boolean().optional()
2580
+ allow_no_match: z6.boolean().optional(),
2581
+ allow_skip: z6.boolean().optional()
2158
2582
  }),
2159
2583
  z6.null()
2160
2584
  ]);
@@ -2484,6 +2908,9 @@ var Group = z6.object({
2484
2908
  var GroupScope = z6.object({
2485
2909
  type: z6.literal("group"),
2486
2910
  group_by: z6.string(),
2911
+ interval_seconds: z6.number().gte(1).optional(),
2912
+ max_traces: z6.number().int().gte(1).lte(64).optional(),
2913
+ placement: z6.enum(["first", "each"]),
2487
2914
  idle_seconds: z6.number().optional()
2488
2915
  });
2489
2916
  var IfExists = z6.enum(["error", "ignore", "replace"]);
@@ -2632,6 +3059,10 @@ var RetentionObjectType = z6.enum([
2632
3059
  "experiment",
2633
3060
  "dataset"
2634
3061
  ]);
3062
+ var TopicAutomationFacetModel = z6.union([
3063
+ z6.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3064
+ z6.null()
3065
+ ]);
2635
3066
  var TopicMapFunctionAutomation = z6.object({
2636
3067
  function: SavedFunctionId.and(z6.unknown()),
2637
3068
  btql_filter: z6.union([z6.string(), z6.null()]).optional()
@@ -2644,7 +3075,9 @@ var TopicAutomationDataScope = z6.union([
2644
3075
  ]);
2645
3076
  var TopicAutomationConfig = z6.object({
2646
3077
  event_type: z6.literal("topic"),
3078
+ status: AutomationStatus.optional(),
2647
3079
  sampling_rate: z6.number().gte(0).lte(1),
3080
+ facet_model: TopicAutomationFacetModel.optional(),
2648
3081
  facet_functions: z6.array(SavedFunctionId),
2649
3082
  topic_map_functions: z6.array(TopicMapFunctionAutomation),
2650
3083
  scope: z6.union([SpanScope, TraceScope, GroupScope, z6.null()]).optional(),
@@ -2658,6 +3091,19 @@ var TopicAutomationConfig = z6.object({
2658
3091
  z6.null()
2659
3092
  ]).optional()
2660
3093
  });
3094
+ var TopicDigestAutomationConfig = z6.object({
3095
+ event_type: z6.literal("topic_digest"),
3096
+ status: AutomationStatus.optional(),
3097
+ window_seconds: z6.number().int().gte(3600).lte(2592e3).optional().default(86400),
3098
+ scheduled_time_minutes_utc: z6.number().int().gte(0).lte(1439),
3099
+ action: z6.object({
3100
+ type: z6.literal("slack"),
3101
+ workspace_id: z6.string(),
3102
+ channel: z6.string(),
3103
+ message_template: z6.string().optional()
3104
+ }),
3105
+ topic_map_function_ids: z6.array(z6.string()).max(10).optional()
3106
+ });
2661
3107
  var ProjectAutomation = z6.object({
2662
3108
  id: z6.string().uuid(),
2663
3109
  project_id: z6.string().uuid(),
@@ -2682,6 +3128,7 @@ var ProjectAutomation = z6.object({
2682
3128
  }),
2683
3129
  z6.object({
2684
3130
  event_type: z6.literal("btql_export"),
3131
+ status: AutomationStatus.optional(),
2685
3132
  export_definition: z6.union([
2686
3133
  z6.object({ type: z6.literal("log_traces") }),
2687
3134
  z6.object({ type: z6.literal("log_spans") }),
@@ -2704,6 +3151,21 @@ var ProjectAutomation = z6.object({
2704
3151
  ]),
2705
3152
  batch_size: z6.union([z6.number(), z6.null()]).optional()
2706
3153
  }),
3154
+ z6.object({
3155
+ event_type: z6.literal("async_query"),
3156
+ status: AutomationStatus.optional(),
3157
+ created_by_user_id: z6.string().uuid(),
3158
+ object_type: z6.enum([
3159
+ "project_logs",
3160
+ "experiment",
3161
+ "dataset",
3162
+ "playground_logs"
3163
+ ]),
3164
+ object_id: z6.string(),
3165
+ query: z6.string(),
3166
+ format: z6.literal("jsonl"),
3167
+ batch_size: z6.union([z6.number(), z6.null()]).optional()
3168
+ }),
2707
3169
  z6.object({
2708
3170
  event_type: z6.literal("retention"),
2709
3171
  object_type: RetentionObjectType,
@@ -2722,7 +3184,8 @@ var ProjectAutomation = z6.object({
2722
3184
  })
2723
3185
  ])
2724
3186
  }),
2725
- TopicAutomationConfig
3187
+ TopicAutomationConfig,
3188
+ TopicDigestAutomationConfig
2726
3189
  ])
2727
3190
  });
2728
3191
  var ProjectLogsEvent = z6.object({
@@ -2761,7 +3224,7 @@ var ProjectLogsEvent = z6.object({
2761
3224
  comments: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
2762
3225
  audit_data: z6.union([z6.array(z6.unknown()), z6.null()]).optional(),
2763
3226
  _async_scoring_state: z6.unknown().optional(),
2764
- facets: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
3227
+ facets: z6.union([z6.record(z6.union([z6.string(), z6.null()])), z6.null()]).optional(),
2765
3228
  classifications: z6.union([
2766
3229
  z6.record(
2767
3230
  z6.array(
@@ -2810,16 +3273,39 @@ var ProjectScoreCategories = z6.union([
2810
3273
  z6.array(z6.string()),
2811
3274
  z6.null()
2812
3275
  ]);
3276
+ var ProjectScoreCondition = z6.union([
3277
+ z6.object({
3278
+ when: z6.object({
3279
+ clauses: z6.union([z6.array(z6.string()), z6.null()]),
3280
+ subspan_clauses: z6.union([z6.array(z6.string()), z6.null()]),
3281
+ trace_clauses: z6.union([z6.array(z6.string()), z6.null()])
3282
+ }).partial(),
3283
+ behavior: z6.literal("hidden").optional().default("hidden")
3284
+ }),
3285
+ z6.null()
3286
+ ]);
2813
3287
  var ProjectScoreConfig = z6.union([
2814
3288
  z6.object({
2815
3289
  multi_select: z6.union([z6.boolean(), z6.null()]),
2816
3290
  destination: z6.union([z6.string(), z6.null()]),
2817
- online: OnlineScoreConfig
2818
- }).partial(),
2819
- z6.null()
2820
- ]);
2821
- var ProjectScore = z6.object({
2822
- id: z6.string().uuid(),
3291
+ visibility: z6.union([
3292
+ z6.object({
3293
+ users: z6.union([z6.array(z6.string()), z6.null()]),
3294
+ groups: z6.union([z6.array(z6.string()), z6.null()])
3295
+ }).partial(),
3296
+ z6.null()
3297
+ ]),
3298
+ online: OnlineScoreConfig,
3299
+ condition: ProjectScoreCondition,
3300
+ object_types: z6.union([
3301
+ z6.array(z6.enum(["project_logs", "dataset", "experiment"])),
3302
+ z6.null()
3303
+ ])
3304
+ }).partial(),
3305
+ z6.null()
3306
+ ]);
3307
+ var ProjectScore = z6.object({
3308
+ id: z6.string().uuid(),
2823
3309
  project_id: z6.string().uuid(),
2824
3310
  user_id: z6.string().uuid(),
2825
3311
  created: z6.union([z6.string(), z6.null()]).optional(),
@@ -2999,8 +3485,7 @@ var User = z6.object({
2999
3485
  family_name: z6.union([z6.string(), z6.null()]).optional(),
3000
3486
  email: z6.union([z6.string(), z6.null()]).optional(),
3001
3487
  avatar_url: z6.union([z6.string(), z6.null()]).optional(),
3002
- created: z6.union([z6.string(), z6.null()]).optional(),
3003
- last_active_at: z6.union([z6.number(), z6.null()]).optional()
3488
+ created: z6.union([z6.string(), z6.null()]).optional()
3004
3489
  });
3005
3490
  var ViewDataSearch = z6.union([
3006
3491
  z6.object({
@@ -3553,115 +4038,6 @@ function devNullWritableStream() {
3553
4038
  // src/logger.ts
3554
4039
  import { v4 as uuidv42 } from "uuid";
3555
4040
 
3556
- // src/debug-logger.ts
3557
- var PREFIX = "[braintrust]";
3558
- var DEBUG_LOG_LEVEL_SYMBOL = /* @__PURE__ */ Symbol.for("braintrust-debug-log-level");
3559
- var LOG_LEVEL_PRIORITY = {
3560
- error: 0,
3561
- warn: 1,
3562
- info: 2,
3563
- debug: 3
3564
- };
3565
- var hasWarnedAboutInvalidEnvValue = false;
3566
- var debugLogStateResolver = void 0;
3567
- function warnInvalidEnvValue(value) {
3568
- if (hasWarnedAboutInvalidEnvValue) {
3569
- return;
3570
- }
3571
- hasWarnedAboutInvalidEnvValue = true;
3572
- console.warn(
3573
- PREFIX,
3574
- `Invalid BRAINTRUST_DEBUG_LOG_LEVEL value "${value}". Expected "error", "warn", "info", or "debug".`
3575
- );
3576
- }
3577
- function normalizeDebugLogLevelOption(option) {
3578
- if (option === false) {
3579
- return void 0;
3580
- }
3581
- if (option === "error" || option === "warn" || option === "info" || option === "debug") {
3582
- return option;
3583
- }
3584
- throw new Error(
3585
- `Invalid debugLogLevel value "${option}". Expected false, "error", "warn", "info", or "debug".`
3586
- );
3587
- }
3588
- function parseDebugLogLevelEnv(value) {
3589
- if (!value) {
3590
- return void 0;
3591
- }
3592
- if (value === "error" || value === "warn" || value === "info" || value === "debug") {
3593
- return value;
3594
- }
3595
- warnInvalidEnvValue(value);
3596
- return void 0;
3597
- }
3598
- function getEnvDebugLogLevel() {
3599
- return parseDebugLogLevelEnv(isomorph_default.getEnv("BRAINTRUST_DEBUG_LOG_LEVEL"));
3600
- }
3601
- function setGlobalDebugLogLevel(level) {
3602
- globalThis[DEBUG_LOG_LEVEL_SYMBOL] = level;
3603
- }
3604
- function resetDebugLoggerForTests() {
3605
- hasWarnedAboutInvalidEnvValue = false;
3606
- setGlobalDebugLogLevel(void 0);
3607
- }
3608
- function setDebugLogStateResolver(resolver) {
3609
- debugLogStateResolver = resolver;
3610
- }
3611
- function resolveDebugLogLevel(state) {
3612
- const stateLevel = state?.getDebugLogLevel?.();
3613
- const hasStateOverride = state?.hasDebugLogLevelOverride?.() ?? false;
3614
- if (hasStateOverride) {
3615
- return stateLevel;
3616
- }
3617
- const globalLevel = (
3618
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
3619
- globalThis[DEBUG_LOG_LEVEL_SYMBOL]
3620
- );
3621
- if (globalLevel !== void 0) {
3622
- return globalLevel === false ? void 0 : globalLevel;
3623
- }
3624
- return getEnvDebugLogLevel();
3625
- }
3626
- function emit(method, state, args) {
3627
- const level = resolveDebugLogLevel(state);
3628
- if (!level || LOG_LEVEL_PRIORITY[method] > LOG_LEVEL_PRIORITY[level]) {
3629
- return;
3630
- }
3631
- if (method === "info") {
3632
- console.log(PREFIX, ...args);
3633
- } else if (method === "debug") {
3634
- console.debug(PREFIX, ...args);
3635
- } else if (method === "warn") {
3636
- console.warn(PREFIX, ...args);
3637
- } else {
3638
- console.error(PREFIX, ...args);
3639
- }
3640
- }
3641
- function createDebugLogger(state) {
3642
- const resolveState = () => state ?? debugLogStateResolver?.();
3643
- return {
3644
- info(...args) {
3645
- emit("info", resolveState(), args);
3646
- },
3647
- debug(...args) {
3648
- emit("debug", resolveState(), args);
3649
- },
3650
- warn(...args) {
3651
- emit("warn", resolveState(), args);
3652
- },
3653
- error(...args) {
3654
- emit("error", resolveState(), args);
3655
- }
3656
- };
3657
- }
3658
- var debugLogger = {
3659
- ...createDebugLogger(),
3660
- forState(state) {
3661
- return createDebugLogger(state);
3662
- }
3663
- };
3664
-
3665
4041
  // src/queue.ts
3666
4042
  var DEFAULT_QUEUE_SIZE = 15e3;
3667
4043
  var Queue = class {
@@ -3834,13 +4210,23 @@ var LRUCache = class {
3834
4210
  * @returns The cached value if found, undefined otherwise.
3835
4211
  */
3836
4212
  get(key) {
3837
- const value = this.cache.get(key);
3838
- if (value === void 0) {
4213
+ const entry = this.cache.get(key);
4214
+ if (entry === void 0) {
3839
4215
  return void 0;
3840
4216
  }
3841
4217
  this.cache.delete(key);
3842
- this.cache.set(key, value);
3843
- return value;
4218
+ this.cache.set(key, entry);
4219
+ return entry.value;
4220
+ }
4221
+ /**
4222
+ * Checks whether a key exists and marks it as most recently used.
4223
+ */
4224
+ has(key) {
4225
+ if (!this.cache.has(key)) {
4226
+ return false;
4227
+ }
4228
+ this.get(key);
4229
+ return true;
3844
4230
  }
3845
4231
  /**
3846
4232
  * Stores a value in the cache.
@@ -3857,7 +4243,38 @@ var LRUCache = class {
3857
4243
  const first = this.cache.keys().next().value;
3858
4244
  this.cache.delete(first);
3859
4245
  }
3860
- this.cache.set(key, value);
4246
+ this.cache.set(key, { value });
4247
+ }
4248
+ /**
4249
+ * Removes an item from the cache.
4250
+ */
4251
+ delete(key) {
4252
+ return this.cache.delete(key);
4253
+ }
4254
+ /**
4255
+ * Iterates over cache entries from least to most recently used.
4256
+ */
4257
+ *entries() {
4258
+ for (const [key, entry] of this.cache) {
4259
+ yield [key, entry.value];
4260
+ }
4261
+ }
4262
+ /**
4263
+ * Iterates over cache keys from least to most recently used.
4264
+ */
4265
+ keys() {
4266
+ return this.cache.keys();
4267
+ }
4268
+ /**
4269
+ * Iterates over cache values from least to most recently used.
4270
+ */
4271
+ *values() {
4272
+ for (const entry of this.cache.values()) {
4273
+ yield entry.value;
4274
+ }
4275
+ }
4276
+ [Symbol.iterator]() {
4277
+ return this.entries();
3861
4278
  }
3862
4279
  /**
3863
4280
  * Removes all items from the cache.
@@ -4415,6 +4832,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
4415
4832
  return `ERROR: Failed to mask field '${fieldName}' - ${errorType}`;
4416
4833
  }
4417
4834
  }
4835
+ var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
4836
+ "braintrust.initial-span-write-as-merge"
4837
+ );
4418
4838
  var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
4419
4839
  "braintrust.currentSpanStore"
4420
4840
  );
@@ -4455,7 +4875,10 @@ var BraintrustContextManager = class extends ContextManager {
4455
4875
  }
4456
4876
  };
4457
4877
  function getSpanComponentsClass() {
4458
- return globalThis.BRAINTRUST_SPAN_COMPONENT ? globalThis.BRAINTRUST_SPAN_COMPONENT : SpanComponentsV3;
4878
+ if (globalThis.BRAINTRUST_SPAN_COMPONENT) {
4879
+ return globalThis.BRAINTRUST_SPAN_COMPONENT;
4880
+ }
4881
+ return resolveUseLegacyUuidIds() ? SpanComponentsV3 : SpanComponentsV4;
4459
4882
  }
4460
4883
  function getContextManager() {
4461
4884
  return globalThis.BRAINTRUST_CONTEXT_MANAGER ? new globalThis.BRAINTRUST_CONTEXT_MANAGER() : new BraintrustContextManager();
@@ -4491,6 +4914,9 @@ var NoopSpan = class {
4491
4914
  async export() {
4492
4915
  return "";
4493
4916
  }
4917
+ inject(carrier) {
4918
+ return carrier ?? {};
4919
+ }
4494
4920
  async permalink() {
4495
4921
  return NOOP_SPAN_PERMALINK;
4496
4922
  }
@@ -4541,6 +4967,10 @@ var loginSchema = z8.strictObject({
4541
4967
  debugLogLevelDisabled: z8.boolean().optional()
4542
4968
  });
4543
4969
  var stateNonce = 0;
4970
+ var V1_PROXY_SUFFIX = "/v1/proxy";
4971
+ function normalizeProxyConnUrl(proxyUrl) {
4972
+ return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
4973
+ }
4544
4974
  var BraintrustState = class _BraintrustState {
4545
4975
  constructor(loginParams) {
4546
4976
  this.loginParams = loginParams;
@@ -4811,7 +5241,10 @@ var BraintrustState = class _BraintrustState {
4811
5241
  if (!this.proxyUrl) {
4812
5242
  throw new Error("Must initialize proxyUrl before requesting proxyConn");
4813
5243
  }
4814
- this._proxyConn = new HTTPConnection(this.proxyUrl, this.fetch);
5244
+ this._proxyConn = new HTTPConnection(
5245
+ normalizeProxyConnUrl(this.proxyUrl),
5246
+ this.fetch
5247
+ );
4815
5248
  }
4816
5249
  return this._proxyConn;
4817
5250
  }
@@ -5569,7 +6002,7 @@ function updateSpan({
5569
6002
  ...event
5570
6003
  }) {
5571
6004
  const resolvedState = state ?? _globalState;
5572
- const components = getSpanComponentsClass().fromStr(exported);
6005
+ const components = SpanComponentsV4.fromStr(exported);
5573
6006
  if (!components.data.row_id) {
5574
6007
  throw new Error("Exported span must have a row id");
5575
6008
  }
@@ -5669,7 +6102,7 @@ async function permalink(slug, opts) {
5669
6102
  return state.appUrl;
5670
6103
  };
5671
6104
  try {
5672
- const components = getSpanComponentsClass().fromStr(slug);
6105
+ const components = SpanComponentsV4.fromStr(slug);
5673
6106
  const object_type = spanObjectTypeV3ToString(components.data.object_type);
5674
6107
  const [orgName, appUrl, object_id] = await Promise.all([
5675
6108
  getOrgName(),
@@ -5693,35 +6126,47 @@ function startSpanParentArgs(args) {
5693
6126
  let argParentObjectId = void 0;
5694
6127
  let argParentSpanIds = void 0;
5695
6128
  let argPropagatedEvent = void 0;
5696
- if (args.parent) {
6129
+ let argPropagatedState = void 0;
6130
+ const { parentSlug, propagatedState: parentPropagatedState } = normalizeParent(args.parent, args.state);
6131
+ if (parentSlug) {
5697
6132
  if (args.parentSpanIds) {
5698
6133
  throw new Error("Cannot specify both parent and parentSpanIds");
5699
6134
  }
5700
- const parentComponents = getSpanComponentsClass().fromStr(args.parent);
6135
+ const parentComponents = SpanComponentsV4.fromStr(parentSlug);
5701
6136
  if (args.parentObjectType !== parentComponents.data.object_type) {
5702
6137
  throw new Error(
5703
6138
  `Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
5704
6139
  );
5705
6140
  }
5706
6141
  argParentObjectId = args.parentObjectId;
5707
- if (parentComponents.data.row_id) {
6142
+ if (parentComponents.data.row_id && parentSpanIdsUsable(
6143
+ parentComponents.data.span_id,
6144
+ parentComponents.data.root_span_id
6145
+ )) {
5708
6146
  argParentSpanIds = {
5709
6147
  spanId: parentComponents.data.span_id,
5710
6148
  rootSpanId: parentComponents.data.root_span_id
5711
6149
  };
5712
6150
  }
5713
6151
  argPropagatedEvent = args.propagatedEvent ?? (parentComponents.data.propagated_event ?? void 0);
6152
+ const propagatedState = args.propagatedState ?? parentPropagatedState;
6153
+ if (propagatedState) {
6154
+ const { braintrustParent: _ignoredBraintrustParent, ...w3cState } = propagatedState;
6155
+ argPropagatedState = w3cState;
6156
+ }
5714
6157
  } else {
5715
6158
  argParentObjectId = args.parentObjectId;
5716
6159
  argParentSpanIds = args.parentSpanIds;
5717
6160
  argPropagatedEvent = args.propagatedEvent;
6161
+ argPropagatedState = args.propagatedState;
5718
6162
  }
5719
6163
  return {
5720
6164
  parentObjectType: args.parentObjectType,
5721
6165
  parentObjectId: argParentObjectId,
5722
6166
  parentComputeObjectMetadataArgs: args.parentComputeObjectMetadataArgs,
5723
6167
  parentSpanIds: argParentSpanIds,
5724
- propagatedEvent: argPropagatedEvent
6168
+ propagatedEvent: argPropagatedEvent,
6169
+ propagatedState: argPropagatedState
5725
6170
  };
5726
6171
  }
5727
6172
  var Logger = class {
@@ -5922,6 +6367,22 @@ var Logger = class {
5922
6367
  _getLinkBaseUrl() {
5923
6368
  return _getLinkBaseUrl(this.state, this._linkArgs);
5924
6369
  }
6370
+ /**
6371
+ * Return this logger's Braintrust parent string (`project_id:<id>` or
6372
+ * `project_name:<name>`) for the `braintrust.parent` baggage entry, or
6373
+ * undefined when it cannot be determined synchronously.
6374
+ */
6375
+ _getOtelParent() {
6376
+ const id = this.computeMetadataArgs?.project_id || this.lazyId.getSync().value;
6377
+ if (id) {
6378
+ return `project_id:${id}`;
6379
+ }
6380
+ const name = this.computeMetadataArgs?.project_name;
6381
+ if (name) {
6382
+ return `project_name:${name}`;
6383
+ }
6384
+ return void 0;
6385
+ }
5925
6386
  };
5926
6387
  function castLogger(logger, asyncFlush) {
5927
6388
  if (logger === void 0) return void 0;
@@ -6016,12 +6477,12 @@ function stringifyWithOverflowMeta(item) {
6016
6477
  object_ids: pickLogs3OverflowObjectIds(record),
6017
6478
  is_delete: record[OBJECT_DELETE_FIELD] === true,
6018
6479
  input_row: {
6019
- byte_size: utf8ByteLength(str)
6480
+ byte_size: utf8ByteLength2(str)
6020
6481
  }
6021
6482
  }
6022
6483
  };
6023
6484
  }
6024
- function utf8ByteLength(value) {
6485
+ function utf8ByteLength2(value) {
6025
6486
  if (typeof TextEncoder !== "undefined") {
6026
6487
  return new TextEncoder().encode(value).length;
6027
6488
  }
@@ -6409,7 +6870,7 @@ var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
6409
6870
  }) {
6410
6871
  const conn = await this.apiConn.get();
6411
6872
  const dataStr = constructLogs3Data(items);
6412
- const payloadBytes = utf8ByteLength(dataStr);
6873
+ const payloadBytes = utf8ByteLength2(dataStr);
6413
6874
  const useOverflow = canUseOverflow && payloadBytes > maxRequestSize;
6414
6875
  if (this.allPublishPayloadsDir) {
6415
6876
  await _HTTPBackgroundLogger.writePayloadToDir({
@@ -7030,6 +7491,8 @@ function initDataset(projectOrOptions, optionalOptions) {
7030
7491
  const normalizedVersion = selection.version;
7031
7492
  const normalizedEnvironment = selection.environment;
7032
7493
  const normalizedSnapshotName = selection.snapshotName;
7494
+ const cliInternalBtql = globalThis.__bt_eval_internal_btql;
7495
+ const internalBtql = cliInternalBtql === void 0 ? _internal_btql : _internal_btql === void 0 ? cliInternalBtql : isObject(_internal_btql) ? { ...cliInternalBtql, ..._internal_btql } : _internal_btql;
7033
7496
  const state = stateArg ?? _globalState;
7034
7497
  const lazyMetadata = new LazyValue(
7035
7498
  async () => {
@@ -7081,7 +7544,7 @@ function initDataset(projectOrOptions, optionalOptions) {
7081
7544
  lazyMetadata,
7082
7545
  typeof resolvedVersion === "string" ? resolvedVersion : void 0,
7083
7546
  legacy,
7084
- _internal_btql,
7547
+ internalBtql,
7085
7548
  resolvedVersion instanceof LazyValue || normalizedEnvironment !== void 0 || normalizedSnapshotName !== void 0 ? {
7086
7549
  ...resolvedVersion instanceof LazyValue ? {
7087
7550
  lazyPinnedVersion: resolvedVersion
@@ -7545,100 +8008,362 @@ function currentSpan(options) {
7545
8008
  const state = options?.state ?? _globalState;
7546
8009
  return state.contextManager.getCurrentSpan() ?? NOOP_SPAN;
7547
8010
  }
7548
- function getSpanParentObject(options) {
8011
+ function getSpanParentObjectAndPropagatedState(options) {
7549
8012
  const state = options?.state ?? _globalState;
7550
8013
  const parentSpan = currentSpan({ state });
7551
8014
  if (!Object.is(parentSpan, NOOP_SPAN)) {
7552
- return parentSpan;
8015
+ return { parentObject: parentSpan, propagatedState: void 0 };
8016
+ }
8017
+ const parent = options?.parent ?? state.currentParent.getStore();
8018
+ const { parentSlug, propagatedState } = normalizeParent(parent, state);
8019
+ if (parentSlug) {
8020
+ return {
8021
+ parentObject: SpanComponentsV4.fromStr(parentSlug),
8022
+ propagatedState
8023
+ };
7553
8024
  }
7554
- const parentStr = options?.parent ?? state.currentParent.getStore();
7555
- if (parentStr) return getSpanComponentsClass().fromStr(parentStr);
7556
8025
  const experiment = currentExperiment();
7557
8026
  if (experiment) {
7558
- return experiment;
8027
+ return { parentObject: experiment, propagatedState: void 0 };
7559
8028
  }
7560
8029
  const logger = currentLogger(options);
7561
8030
  if (logger) {
7562
- return logger;
8031
+ return { parentObject: logger, propagatedState: void 0 };
7563
8032
  }
7564
- return NOOP_SPAN;
8033
+ return { parentObject: NOOP_SPAN, propagatedState: void 0 };
7565
8034
  }
7566
- function logError(span, error) {
7567
- let errorMessage = "<error>";
7568
- let stackTrace = "";
7569
- if (error instanceof Error) {
7570
- errorMessage = error.message;
7571
- stackTrace = error.stack || "";
7572
- } else {
7573
- errorMessage = String(error);
7574
- }
7575
- span.log({ error: `${errorMessage}
7576
-
7577
- ${stackTrace}` });
8035
+ function getSpanParentObject(options) {
8036
+ return getSpanParentObjectAndPropagatedState(options).parentObject;
7578
8037
  }
7579
- function traced(callback, args) {
7580
- const { span, isSyncFlushLogger } = startSpanAndIsLogger(args);
7581
- const ret = runCatchFinally(
7582
- () => {
7583
- if (args?.setCurrent ?? true) {
7584
- return withCurrent(span, callback);
7585
- } else {
7586
- return callback(span);
7587
- }
7588
- },
7589
- (e) => {
7590
- logError(span, e);
7591
- throw e;
7592
- },
7593
- () => span.end()
7594
- );
7595
- if (args?.asyncFlush === void 0 || args?.asyncFlush) {
7596
- return ret;
7597
- } else {
7598
- return (async () => {
7599
- const awaitedRet = await ret;
7600
- if (isSyncFlushLogger) {
7601
- await span.flush();
7602
- }
7603
- return awaitedRet;
7604
- })();
8038
+ function currentBraintrustParent(state) {
8039
+ const resolvedState = state ?? _globalState;
8040
+ const experiment = currentExperiment({ state: resolvedState });
8041
+ if (experiment) {
8042
+ try {
8043
+ return experiment._getOtelParent() ?? void 0;
8044
+ } catch {
8045
+ return void 0;
8046
+ }
7605
8047
  }
8048
+ const logger = currentLogger({ state: resolvedState });
8049
+ if (logger) {
8050
+ try {
8051
+ return logger._getOtelParent() ?? void 0;
8052
+ } catch {
8053
+ return void 0;
8054
+ }
8055
+ }
8056
+ return void 0;
7606
8057
  }
7607
- function isGeneratorFunction(fn) {
7608
- return Object.prototype.toString.call(fn) === "[object GeneratorFunction]";
8058
+ function braintrustParentToComponents(braintrustParent) {
8059
+ if (!braintrustParent) {
8060
+ return void 0;
8061
+ }
8062
+ if (braintrustParent.startsWith("project_id:")) {
8063
+ const objectId = braintrustParent.slice("project_id:".length);
8064
+ return objectId ? {
8065
+ objectType: 2 /* PROJECT_LOGS */,
8066
+ objectId,
8067
+ computeArgs: void 0
8068
+ } : void 0;
8069
+ }
8070
+ if (braintrustParent.startsWith("project_name:")) {
8071
+ const name = braintrustParent.slice("project_name:".length);
8072
+ return name ? {
8073
+ objectType: 2 /* PROJECT_LOGS */,
8074
+ objectId: void 0,
8075
+ computeArgs: { project_name: name }
8076
+ } : void 0;
8077
+ }
8078
+ if (braintrustParent.startsWith("experiment_id:")) {
8079
+ const objectId = braintrustParent.slice("experiment_id:".length);
8080
+ return objectId ? {
8081
+ objectType: 1 /* EXPERIMENT */,
8082
+ objectId,
8083
+ computeArgs: void 0
8084
+ } : void 0;
8085
+ }
8086
+ return void 0;
7609
8087
  }
7610
- function isAsyncGeneratorFunction(fn) {
7611
- return Object.prototype.toString.call(fn) === "[object AsyncGeneratorFunction]";
8088
+ function isMutableHeaderTupleArray(carrier) {
8089
+ return Array.isArray(carrier) && carrier.every((item) => Array.isArray(item) && typeof item[0] === "string");
7612
8090
  }
7613
- function wrapTracedSyncGenerator(fn, spanArgs, noTraceIO) {
7614
- const wrapper = function* (...fnArgs) {
7615
- const span = startSpan(spanArgs);
7616
- try {
7617
- if (!noTraceIO) {
7618
- span.log({ input: fnArgs });
8091
+ function setHeader(carrier, name, value) {
8092
+ if (isMutableHeaderTupleArray(carrier)) {
8093
+ const lowered2 = name.toLowerCase();
8094
+ for (let i = carrier.length - 1; i >= 0; i--) {
8095
+ if (carrier[i][0].toLowerCase() === lowered2) {
8096
+ carrier.splice(i, 1);
7619
8097
  }
7620
- const envValue = isomorph_default.getEnv("BRAINTRUST_MAX_GENERATOR_ITEMS");
7621
- const maxItems = envValue !== void 0 ? Number(envValue) : 1e3;
7622
- if (!noTraceIO && maxItems !== 0) {
7623
- let collected = [];
7624
- let truncated = false;
7625
- const gen = generatorWithCurrent(span, fn.apply(this, fnArgs));
7626
- try {
7627
- for (const value of gen) {
7628
- if (maxItems === -1 || !truncated && collected.length < maxItems) {
7629
- collected.push(value);
7630
- } else {
7631
- truncated = true;
7632
- collected = [];
7633
- debugLogger.warn(
7634
- `Generator output exceeded limit of ${maxItems} items, output not logged. Increase BRAINTRUST_MAX_GENERATOR_ITEMS or set to -1 to disable limit.`
7635
- );
7636
- }
7637
- yield value;
7638
- }
7639
- if (!truncated) {
7640
- span.log({ output: collected });
7641
- }
8098
+ }
8099
+ carrier.push([name, value]);
8100
+ return;
8101
+ }
8102
+ const setter = carrier.set;
8103
+ if (typeof setter === "function") {
8104
+ const deleter = carrier.delete;
8105
+ if (typeof deleter === "function") {
8106
+ try {
8107
+ deleter.call(carrier, name);
8108
+ } catch {
8109
+ }
8110
+ }
8111
+ setter.call(carrier, name, value);
8112
+ return;
8113
+ }
8114
+ const nodeSetter = carrier.setHeader;
8115
+ if (typeof nodeSetter === "function") {
8116
+ const remover = carrier.removeHeader;
8117
+ if (typeof remover === "function") {
8118
+ try {
8119
+ remover.call(carrier, name);
8120
+ } catch {
8121
+ }
8122
+ }
8123
+ nodeSetter.call(carrier, name, value);
8124
+ return;
8125
+ }
8126
+ const headerSetter = carrier.header;
8127
+ if (typeof headerSetter === "function") {
8128
+ const deleter = carrier.delete;
8129
+ if (typeof deleter === "function") {
8130
+ try {
8131
+ deleter.call(carrier, name);
8132
+ } catch {
8133
+ }
8134
+ }
8135
+ const remover = carrier.removeHeader;
8136
+ if (typeof remover === "function") {
8137
+ try {
8138
+ remover.call(carrier, name);
8139
+ } catch {
8140
+ }
8141
+ }
8142
+ headerSetter.call(carrier, name, value);
8143
+ return;
8144
+ }
8145
+ const headerBag = carrier;
8146
+ const lowered = name.toLowerCase();
8147
+ for (const key of Object.keys(headerBag)) {
8148
+ if (key !== name && key.toLowerCase() === lowered) {
8149
+ delete headerBag[key];
8150
+ }
8151
+ }
8152
+ headerBag[name] = value;
8153
+ }
8154
+ function deleteHeader(carrier, name) {
8155
+ const lowered = name.toLowerCase();
8156
+ if (isMutableHeaderTupleArray(carrier)) {
8157
+ for (let i = carrier.length - 1; i >= 0; i--) {
8158
+ if (carrier[i][0].toLowerCase() === lowered) {
8159
+ carrier.splice(i, 1);
8160
+ }
8161
+ }
8162
+ return;
8163
+ }
8164
+ const deleter = carrier.delete;
8165
+ if (typeof deleter === "function") {
8166
+ try {
8167
+ deleter.call(carrier, name);
8168
+ return;
8169
+ } catch {
8170
+ }
8171
+ }
8172
+ const remover = carrier.removeHeader;
8173
+ if (typeof remover === "function") {
8174
+ try {
8175
+ remover.call(carrier, name);
8176
+ return;
8177
+ } catch {
8178
+ }
8179
+ }
8180
+ const headerBag = carrier;
8181
+ for (const key of Object.keys(headerBag)) {
8182
+ if (key.toLowerCase() === lowered) {
8183
+ delete headerBag[key];
8184
+ }
8185
+ }
8186
+ }
8187
+ function _injectIntoCarrier(carrier, args) {
8188
+ const traceFlags = args.propagatedState?.traceFlags;
8189
+ const traceparent = traceFlags ? formatTraceparent(args.traceId, args.spanId, traceFlags) : formatTraceparent(args.traceId, args.spanId);
8190
+ if (traceparent === void 0) {
8191
+ return;
8192
+ }
8193
+ setHeader(carrier, TRACEPARENT_HEADER, traceparent);
8194
+ const tracestate = args.propagatedState?.tracestate;
8195
+ if (tracestate) {
8196
+ setHeader(carrier, TRACESTATE_HEADER, tracestate);
8197
+ }
8198
+ const existing = getHeader(carrier, BAGGAGE_HEADER);
8199
+ const baggageValue = mergeBaggage(existing, args.braintrustParent);
8200
+ if (baggageValue !== void 0) {
8201
+ setHeader(carrier, BAGGAGE_HEADER, baggageValue);
8202
+ } else if (existing !== void 0) {
8203
+ deleteHeader(carrier, BAGGAGE_HEADER);
8204
+ }
8205
+ }
8206
+ function injectTraceContext(carrier, options) {
8207
+ const resolvedCarrier = carrier ?? {};
8208
+ const span = options?.span ?? currentSpan({ state: options?.state });
8209
+ try {
8210
+ return span.inject(resolvedCarrier);
8211
+ } catch (e) {
8212
+ debugLogger.warn(`Error injecting trace context: ${e}`);
8213
+ return resolvedCarrier;
8214
+ }
8215
+ }
8216
+ function extractTraceContextFromHeaders(headers) {
8217
+ if (!headers) {
8218
+ return void 0;
8219
+ }
8220
+ const traceparent = getHeader(headers, TRACEPARENT_HEADER);
8221
+ if (!traceparent || parseTraceparent(traceparent) === void 0) {
8222
+ return void 0;
8223
+ }
8224
+ const context = { [TRACEPARENT_HEADER]: traceparent };
8225
+ const baggageValue = getHeader(headers, BAGGAGE_HEADER);
8226
+ if (baggageValue) {
8227
+ context[BAGGAGE_HEADER] = baggageValue;
8228
+ }
8229
+ const tracestate = getHeader(headers, TRACESTATE_HEADER);
8230
+ if (tracestate) {
8231
+ context[TRACESTATE_HEADER] = tracestate;
8232
+ }
8233
+ return context;
8234
+ }
8235
+ function resolveW3cParent(context, state) {
8236
+ const traceparent = getHeader(context, TRACEPARENT_HEADER);
8237
+ const parsed = traceparent ? parseTraceparent(traceparent) : void 0;
8238
+ if (parsed === void 0) {
8239
+ return { parentSlug: void 0, propagatedState: void 0 };
8240
+ }
8241
+ const { traceId, spanId, traceFlags } = parsed;
8242
+ let braintrustParent = void 0;
8243
+ const baggageValue = getHeader(context, BAGGAGE_HEADER);
8244
+ if (baggageValue) {
8245
+ braintrustParent = parseBaggage(baggageValue)[BRAINTRUST_PARENT_KEY];
8246
+ }
8247
+ if (!braintrustParent) {
8248
+ braintrustParent = currentBraintrustParent(state);
8249
+ }
8250
+ if (!braintrustParent) {
8251
+ debugLogger.warn(
8252
+ "Received traceparent without a braintrust.parent and no active logger/experiment; cannot route the trace. Starting a fresh local span instead."
8253
+ );
8254
+ return { parentSlug: void 0, propagatedState: void 0 };
8255
+ }
8256
+ const parsedParent = braintrustParentToComponents(braintrustParent);
8257
+ if (parsedParent === void 0) {
8258
+ debugLogger.warn(
8259
+ `Invalid braintrust.parent: ${JSON.stringify(braintrustParent)}`
8260
+ );
8261
+ return { parentSlug: void 0, propagatedState: void 0 };
8262
+ }
8263
+ const { objectType, objectId, computeArgs } = parsedParent;
8264
+ const tracestate = getHeader(context, TRACESTATE_HEADER);
8265
+ const slug = new SpanComponentsV4({
8266
+ object_type: objectType,
8267
+ ...computeArgs ? { compute_object_metadata_args: computeArgs } : { object_id: objectId },
8268
+ row_id: "bt-propagation",
8269
+ // non-empty to enable span_id/root_span_id
8270
+ span_id: spanId,
8271
+ root_span_id: traceId
8272
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
8273
+ }).toStr();
8274
+ return {
8275
+ parentSlug: slug,
8276
+ propagatedState: { tracestate, traceFlags, braintrustParent }
8277
+ };
8278
+ }
8279
+ function normalizeParent(parent, state) {
8280
+ if (parent && typeof parent === "object") {
8281
+ return resolveW3cParent(parent, state);
8282
+ }
8283
+ return {
8284
+ parentSlug: parent ?? void 0,
8285
+ propagatedState: void 0
8286
+ };
8287
+ }
8288
+ function parentSpanIdsUsable(spanId, rootSpanId) {
8289
+ return Boolean(spanId) && Boolean(rootSpanId);
8290
+ }
8291
+ function logError(span, error) {
8292
+ let errorMessage = "<error>";
8293
+ let stackTrace = "";
8294
+ if (error instanceof Error) {
8295
+ errorMessage = error.message;
8296
+ stackTrace = error.stack || "";
8297
+ } else {
8298
+ errorMessage = String(error);
8299
+ }
8300
+ span.log({ error: `${errorMessage}
8301
+
8302
+ ${stackTrace}` });
8303
+ }
8304
+ function traced(callback, args) {
8305
+ const { span, isSyncFlushLogger } = startSpanAndIsLogger(args);
8306
+ const ret = runCatchFinally(
8307
+ () => {
8308
+ if (args?.setCurrent ?? true) {
8309
+ return withCurrent(span, callback);
8310
+ } else {
8311
+ return callback(span);
8312
+ }
8313
+ },
8314
+ (e) => {
8315
+ logError(span, e);
8316
+ throw e;
8317
+ },
8318
+ () => span.end()
8319
+ );
8320
+ if (args?.asyncFlush === void 0 || args?.asyncFlush) {
8321
+ return ret;
8322
+ } else {
8323
+ return (async () => {
8324
+ const awaitedRet = await ret;
8325
+ if (isSyncFlushLogger) {
8326
+ await span.flush();
8327
+ }
8328
+ return awaitedRet;
8329
+ })();
8330
+ }
8331
+ }
8332
+ function isGeneratorFunction(fn) {
8333
+ return Object.prototype.toString.call(fn) === "[object GeneratorFunction]";
8334
+ }
8335
+ function isAsyncGeneratorFunction(fn) {
8336
+ return Object.prototype.toString.call(fn) === "[object AsyncGeneratorFunction]";
8337
+ }
8338
+ function wrapTracedSyncGenerator(fn, spanArgs, noTraceIO) {
8339
+ const wrapper = function* (...fnArgs) {
8340
+ const span = startSpan(spanArgs);
8341
+ try {
8342
+ if (!noTraceIO) {
8343
+ span.log({ input: fnArgs });
8344
+ }
8345
+ const envValue = isomorph_default.getEnv("BRAINTRUST_MAX_GENERATOR_ITEMS");
8346
+ const maxItems = envValue !== void 0 ? Number(envValue) : 1e3;
8347
+ if (!noTraceIO && maxItems !== 0) {
8348
+ let collected = [];
8349
+ let truncated = false;
8350
+ const gen = generatorWithCurrent(span, fn.apply(this, fnArgs));
8351
+ try {
8352
+ for (const value of gen) {
8353
+ if (maxItems === -1 || !truncated && collected.length < maxItems) {
8354
+ collected.push(value);
8355
+ } else {
8356
+ truncated = true;
8357
+ collected = [];
8358
+ debugLogger.warn(
8359
+ `Generator output exceeded limit of ${maxItems} items, output not logged. Increase BRAINTRUST_MAX_GENERATOR_ITEMS or set to -1 to disable limit.`
8360
+ );
8361
+ }
8362
+ yield value;
8363
+ }
8364
+ if (!truncated) {
8365
+ span.log({ output: collected });
8366
+ }
7642
8367
  } catch (error) {
7643
8368
  logError(span, error);
7644
8369
  if (!truncated && collected.length > 0) {
@@ -7760,6 +8485,12 @@ var traceable = wrapTraced;
7760
8485
  function startSpan(args) {
7761
8486
  return startSpanAndIsLogger(args).span;
7762
8487
  }
8488
+ function _internalStartSpanWithInitialMerge(args) {
8489
+ return startSpanAndIsLogger({
8490
+ ...args,
8491
+ [INITIAL_SPAN_WRITE_AS_MERGE]: true
8492
+ }).span;
8493
+ }
7763
8494
  async function flush(options) {
7764
8495
  const state = options?.state ?? _globalState;
7765
8496
  return await state.bgLogger().flush();
@@ -7769,19 +8500,23 @@ function setFetch(fetch2) {
7769
8500
  }
7770
8501
  function startSpanAndIsLogger(args) {
7771
8502
  const state = args?.state ?? _globalState;
7772
- const parentObject = getSpanParentObject({
8503
+ const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
7773
8504
  asyncFlush: args?.asyncFlush,
7774
8505
  parent: args?.parent,
7775
8506
  state
7776
8507
  });
7777
8508
  if (parentObject instanceof SpanComponentsV3 || parentObject instanceof SpanComponentsV4) {
7778
- const parentSpanIds = parentObject.data.row_id ? {
8509
+ const parentSpanIds = parentObject.data.row_id && parentSpanIdsUsable(
8510
+ parentObject.data.span_id,
8511
+ parentObject.data.root_span_id
8512
+ ) ? {
7779
8513
  spanId: parentObject.data.span_id,
7780
8514
  rootSpanId: parentObject.data.root_span_id
7781
8515
  } : void 0;
8516
+ const { parent: _ignoredParent, ...spanArgs } = args ?? {};
7782
8517
  const span = new SpanImpl({
7783
8518
  state,
7784
- ...args,
8519
+ ...spanArgs,
7785
8520
  parentObjectType: parentObject.data.object_type,
7786
8521
  parentObjectId: new LazyValue(
7787
8522
  spanComponentsToObjectIdLambda(state, parentObject)
@@ -7789,7 +8524,8 @@ function startSpanAndIsLogger(args) {
7789
8524
  parentComputeObjectMetadataArgs: parentObject.data.compute_object_metadata_args ?? void 0,
7790
8525
  parentSpanIds,
7791
8526
  propagatedEvent: args?.propagatedEvent ?? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
7792
- (parentObject.data.propagated_event ?? void 0)
8527
+ (parentObject.data.propagated_event ?? void 0),
8528
+ propagatedState
7793
8529
  });
7794
8530
  return {
7795
8531
  span,
@@ -8078,11 +8814,12 @@ function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
8078
8814
  var DEFAULT_FETCH_BATCH_SIZE = 1e3;
8079
8815
  var MAX_BTQL_ITERATIONS = 1e4;
8080
8816
  var ObjectFetcher = class {
8081
- constructor(objectType, pinnedVersion, mutateRecord, _internal_btql) {
8817
+ constructor(objectType, pinnedVersion, mutateRecord, _internal_btql, _internalBrainstoreRealtime = true) {
8082
8818
  this.objectType = objectType;
8083
8819
  this.pinnedVersion = pinnedVersion;
8084
8820
  this.mutateRecord = mutateRecord;
8085
8821
  this._internal_btql = _internal_btql;
8822
+ this._internalBrainstoreRealtime = _internalBrainstoreRealtime;
8086
8823
  }
8087
8824
  _fetchedData = void 0;
8088
8825
  get id() {
@@ -8141,7 +8878,7 @@ var ObjectFetcher = class {
8141
8878
  ...internalBtqlWithoutReservedQueryKeys
8142
8879
  },
8143
8880
  use_columnstore: false,
8144
- brainstore_realtime: true,
8881
+ brainstore_realtime: this._internalBrainstoreRealtime,
8145
8882
  query_source: `js_sdk_object_fetcher_${this.objectType}`,
8146
8883
  ...this.pinnedVersion !== void 0 ? {
8147
8884
  version: this.pinnedVersion
@@ -8490,6 +9227,15 @@ View complete results in Braintrust or run experiment.summarize() again.`
8490
9227
  object_id: await this.id
8491
9228
  }).toStr();
8492
9229
  }
9230
+ /**
9231
+ * Return this experiment's Braintrust parent string (`experiment_id:<id>`) for
9232
+ * the `braintrust.parent` baggage entry, or undefined when it cannot be
9233
+ * determined synchronously.
9234
+ */
9235
+ _getOtelParent() {
9236
+ const id = this.lazyId.getSync().value;
9237
+ return id ? `experiment_id:${id}` : void 0;
9238
+ }
8493
9239
  /**
8494
9240
  * Flush any pending rows to the server.
8495
9241
  */
@@ -8532,7 +9278,8 @@ var ReadonlyExperiment = class extends ObjectFetcher {
8532
9278
  async *asDataset(options) {
8533
9279
  const records = this.fetch(options);
8534
9280
  for await (const record of records) {
8535
- if (record.root_span_id !== record.span_id) {
9281
+ const isRoot = record.is_root ?? record.root_span_id === record.span_id;
9282
+ if (!isRoot) {
8536
9283
  continue;
8537
9284
  }
8538
9285
  const { output, expected: expectedRecord, metadata } = record;
@@ -8594,9 +9341,16 @@ var SpanImpl = class _SpanImpl {
8594
9341
  _spanId;
8595
9342
  _rootSpanId;
8596
9343
  _spanParents;
9344
+ // Inbound W3C trace-context state (tracestate + raw traceparent flags) to
9345
+ // forward on outbound propagation. Captured at the span that received it (via
9346
+ // extractTraceContextFromHeaders) and inherited by all subspans, so that any
9347
+ // inject() within the trace re-emits the upstream state unchanged, per the W3C
9348
+ // Trace Context spec. Not interpreted.
9349
+ _propagatedState;
8597
9350
  kind = "span";
8598
9351
  constructor(args) {
8599
9352
  this._state = args.state;
9353
+ this._propagatedState = args.propagatedState;
8600
9354
  const spanAttributes = args.spanAttributes ?? {};
8601
9355
  const rawEvent = args.event ?? {};
8602
9356
  const type = args.type ?? (args.parentSpanIds ? void 0 : args.defaultRootType);
@@ -8647,7 +9401,7 @@ var SpanImpl = class _SpanImpl {
8647
9401
  this._spanId = resolvedIds.spanId;
8648
9402
  this._rootSpanId = resolvedIds.rootSpanId;
8649
9403
  this._spanParents = resolvedIds.spanParents;
8650
- this.isMerge = false;
9404
+ this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
8651
9405
  this.logInternal({ event, internalData });
8652
9406
  this.isMerge = true;
8653
9407
  }
@@ -8712,7 +9466,7 @@ var SpanImpl = class _SpanImpl {
8712
9466
  tags: partialRecord.tags,
8713
9467
  span_id: this._spanId,
8714
9468
  span_parents: this._spanParents,
8715
- is_root: this._spanId === this._rootSpanId,
9469
+ is_root: !this._spanParents || this._spanParents.length === 0,
8716
9470
  span_attributes: partialRecord.span_attributes
8717
9471
  };
8718
9472
  this._state.spanCache.queueWrite(
@@ -8774,7 +9528,8 @@ var SpanImpl = class _SpanImpl {
8774
9528
  parentObjectId: this.parentObjectId,
8775
9529
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
8776
9530
  parentSpanIds,
8777
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
9531
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
9532
+ propagatedState: this._propagatedState
8778
9533
  })
8779
9534
  });
8780
9535
  }
@@ -8793,7 +9548,8 @@ var SpanImpl = class _SpanImpl {
8793
9548
  parentObjectId: this.parentObjectId,
8794
9549
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
8795
9550
  parentSpanIds,
8796
- propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent
9551
+ propagatedEvent: args?.propagatedEvent ?? this.propagatedEvent,
9552
+ propagatedState: this._propagatedState
8797
9553
  }),
8798
9554
  spanId
8799
9555
  });
@@ -8821,6 +9577,42 @@ var SpanImpl = class _SpanImpl {
8821
9577
  propagated_event: this.propagatedEvent
8822
9578
  }).toStr();
8823
9579
  }
9580
+ /**
9581
+ * Return this span's Braintrust parent string (`project_id:<id>`,
9582
+ * `project_name:<name>`, or `experiment_id:<id>`) for the `braintrust.parent`
9583
+ * baggage entry, or undefined when it cannot be determined synchronously.
9584
+ */
9585
+ _getOtelParent() {
9586
+ if (this.parentObjectType === 2 /* PROJECT_LOGS */) {
9587
+ const id = this.parentComputeObjectMetadataArgs?.project_id || this.parentObjectId.getSync().value;
9588
+ const name = this.parentComputeObjectMetadataArgs?.project_name;
9589
+ if (id) {
9590
+ return `project_id:${id}`;
9591
+ } else if (name) {
9592
+ return `project_name:${name}`;
9593
+ }
9594
+ } else if (this.parentObjectType === 1 /* EXPERIMENT */) {
9595
+ const id = this.parentComputeObjectMetadataArgs?.experiment_id || this.parentObjectId.getSync().value;
9596
+ if (id) {
9597
+ return `experiment_id:${id}`;
9598
+ }
9599
+ }
9600
+ return void 0;
9601
+ }
9602
+ inject(carrier) {
9603
+ const resolvedCarrier = carrier ?? {};
9604
+ try {
9605
+ _injectIntoCarrier(resolvedCarrier, {
9606
+ traceId: this._rootSpanId,
9607
+ spanId: this._spanId,
9608
+ braintrustParent: this._getOtelParent() ?? this._propagatedState?.braintrustParent,
9609
+ propagatedState: this._propagatedState
9610
+ });
9611
+ } catch (e) {
9612
+ debugLogger.warn(`Error injecting trace context: ${e}`);
9613
+ }
9614
+ return resolvedCarrier;
9615
+ }
8824
9616
  async permalink() {
8825
9617
  return await permalink(await this.export(), {
8826
9618
  state: this._state
@@ -8956,6 +9748,7 @@ var Dataset2 = class extends ObjectFetcher {
8956
9748
  _internal_btql
8957
9749
  );
8958
9750
  this.state = state;
9751
+ void this.__braintrust_dataset_marker;
8959
9752
  this.lazyMetadata = lazyMetadata;
8960
9753
  this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
8961
9754
  this.pinnedEnvironment = pinState?.pinnedEnvironment;
@@ -9473,6 +10266,7 @@ var Prompt2 = class _Prompt {
9473
10266
  this.metadata = metadata;
9474
10267
  this.defaults = defaults;
9475
10268
  this.noTrace = noTrace;
10269
+ void this.__braintrust_prompt_marker;
9476
10270
  }
9477
10271
  parsedPromptData;
9478
10272
  hasParsedPromptData = false;
@@ -9709,6 +10503,7 @@ var Prompt2 = class _Prompt {
9709
10503
  var RemoteEvalParameters = class {
9710
10504
  constructor(metadata) {
9711
10505
  this.metadata = metadata;
10506
+ void this.__braintrust_parameters_marker;
9712
10507
  }
9713
10508
  __braintrust_parameters_marker = true;
9714
10509
  get id() {
@@ -9845,6 +10640,7 @@ var _exportsForTestingOnly = {
9845
10640
  isAsyncGeneratorFunction,
9846
10641
  resetIdGenStateForTests,
9847
10642
  validateTags,
10643
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9848
10644
  isomorph: isomorph_default
9849
10645
  // Expose isomorph for build type detection
9850
10646
  };
@@ -10728,6 +11524,22 @@ function runStreamingCompletionHook(args) {
10728
11524
  );
10729
11525
  }
10730
11526
  }
11527
+ function runStreamingErrorHook(args) {
11528
+ if (!args.config.onError) {
11529
+ return;
11530
+ }
11531
+ try {
11532
+ args.config.onError({
11533
+ channelName: args.channelName,
11534
+ error: args.error,
11535
+ event: args.event,
11536
+ span: args.span,
11537
+ startTime: args.startTime
11538
+ });
11539
+ } catch (error) {
11540
+ debugLogger.error(`Error in onError hook for ${args.channelName}:`, error);
11541
+ }
11542
+ }
10731
11543
  function traceAsyncChannel(channel, config) {
10732
11544
  const tracingChannel2 = channel.tracingChannel();
10733
11545
  const states = /* @__PURE__ */ new WeakMap();
@@ -10889,6 +11701,14 @@ function traceStreamingChannel(channel, config) {
10889
11701
  }
10890
11702
  },
10891
11703
  onError: (error) => {
11704
+ runStreamingErrorHook({
11705
+ channelName,
11706
+ config,
11707
+ error,
11708
+ event: asyncEndEvent,
11709
+ span,
11710
+ startTime
11711
+ });
10892
11712
  span.log({
10893
11713
  error: error.message
10894
11714
  });
@@ -10946,6 +11766,17 @@ function traceStreamingChannel(channel, config) {
10946
11766
  }
10947
11767
  },
10948
11768
  error: (event) => {
11769
+ const spanData = states.get(event);
11770
+ if (spanData) {
11771
+ runStreamingErrorHook({
11772
+ channelName,
11773
+ config,
11774
+ error: event.error,
11775
+ event,
11776
+ span: spanData.span,
11777
+ startTime: spanData.startTime
11778
+ });
11779
+ }
10949
11780
  logErrorAndEnd(states, event);
10950
11781
  }
10951
11782
  };
@@ -11345,18 +12176,51 @@ function serializeAISDKToolsForLogging(tools) {
11345
12176
  return serialized;
11346
12177
  }
11347
12178
 
12179
+ // src/wrappers/ai-sdk/workflow-agent-context.ts
12180
+ var workflowAgentWrapperSpans = /* @__PURE__ */ new Map();
12181
+ function registerWorkflowAgentWrapperSpan(span) {
12182
+ if (span.spanId) {
12183
+ workflowAgentWrapperSpans.set(span.spanId, span);
12184
+ }
12185
+ }
12186
+ function unregisterWorkflowAgentWrapperSpan(span) {
12187
+ if (span.spanId) {
12188
+ workflowAgentWrapperSpans.delete(span.spanId);
12189
+ }
12190
+ }
12191
+ function currentWorkflowAgentWrapperSpan() {
12192
+ const parentSpanIds = _internalGetGlobalState().contextManager.getParentSpanIds()?.spanParents ?? [];
12193
+ for (const parentSpanId of parentSpanIds) {
12194
+ const span = workflowAgentWrapperSpans.get(parentSpanId);
12195
+ if (span) {
12196
+ return span;
12197
+ }
12198
+ }
12199
+ return void 0;
12200
+ }
12201
+
12202
+ // src/vendor-sdk-types/ai-sdk-v7-telemetry.ts
12203
+ var BRAINTRUST_AI_SDK_V7_OPERATION_KEY = /* @__PURE__ */ Symbol.for(
12204
+ "braintrust.ai-sdk.v7.telemetry-operation-key"
12205
+ );
12206
+
11348
12207
  // src/instrumentation/plugins/ai-sdk-plugin.ts
11349
12208
  var DEFAULT_DENY_OUTPUT_PATHS = [
11350
12209
  // v3
11351
12210
  "roundtrips[].request.body",
12211
+ "roundtrips[].request.headers",
11352
12212
  "roundtrips[].response.headers",
11353
12213
  "rawResponse.headers",
11354
12214
  "responseMessages",
11355
12215
  // v5
11356
12216
  "request.body",
12217
+ "request.headers",
12218
+ "responses[].headers",
11357
12219
  "response.body",
11358
12220
  "response.headers",
11359
12221
  "steps[].request.body",
12222
+ "steps[].request.headers",
12223
+ "steps[].responses[].headers",
11360
12224
  "steps[].response.body",
11361
12225
  "steps[].response.headers"
11362
12226
  ];
@@ -11368,6 +12232,18 @@ var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
11368
12232
  var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
11369
12233
  "braintrust.ai-sdk.deny-output-paths"
11370
12234
  );
12235
+ var aiSDKV7TelemetryOperationCounter = 0;
12236
+ var TRANSPORT_PAYLOAD_ROOT_PATHS = [
12237
+ "rawResponse",
12238
+ "request",
12239
+ "response",
12240
+ "responses[]",
12241
+ "roundtrips[].request",
12242
+ "roundtrips[].response",
12243
+ "steps[].request",
12244
+ "steps[].response",
12245
+ "steps[].responses[]"
12246
+ ];
11371
12247
  var AI_SDK_V7_TELEMETRY_CALLBACKS = [
11372
12248
  "onStart",
11373
12249
  "onStepStart",
@@ -11376,14 +12252,16 @@ var AI_SDK_V7_TELEMETRY_CALLBACKS = [
11376
12252
  "onToolExecutionStart",
11377
12253
  "onToolExecutionEnd",
11378
12254
  "onChunk",
12255
+ "onStepEnd",
11379
12256
  "onStepFinish",
11380
12257
  "onObjectStepStart",
11381
- "onObjectStepFinish",
12258
+ "onObjectStepEnd",
11382
12259
  "onEmbedStart",
11383
- "onEmbedFinish",
12260
+ "onEmbedEnd",
11384
12261
  "onRerankStart",
11385
- "onRerankFinish",
11386
- "onFinish",
12262
+ "onRerankEnd",
12263
+ "onEnd",
12264
+ "onAbort",
11387
12265
  "onError"
11388
12266
  ];
11389
12267
  var AISDKPlugin = class extends BasePlugin {
@@ -11541,7 +12419,9 @@ var AISDKPlugin = class extends BasePlugin {
11541
12419
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
11542
12420
  name: "Agent.generate",
11543
12421
  type: "function" /* FUNCTION */,
11544
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
12422
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
12423
+ agentOwner: true
12424
+ }),
11545
12425
  extractOutput: (result, endEvent) => {
11546
12426
  finalizeAISDKChildTracing(endEvent);
11547
12427
  return processAISDKOutput(
@@ -11557,7 +12437,9 @@ var AISDKPlugin = class extends BasePlugin {
11557
12437
  traceStreamingChannel(aiSDKChannels.agentStream, {
11558
12438
  name: "Agent.stream",
11559
12439
  type: "function" /* FUNCTION */,
11560
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
12440
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
12441
+ agentOwner: true
12442
+ }),
11561
12443
  extractOutput: (result, endEvent) => processAISDKOutput(
11562
12444
  result,
11563
12445
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -11577,7 +12459,9 @@ var AISDKPlugin = class extends BasePlugin {
11577
12459
  traceSyncStreamChannel(aiSDKChannels.agentStreamSync, {
11578
12460
  name: "Agent.stream",
11579
12461
  type: "function" /* FUNCTION */,
11580
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
12462
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
12463
+ agentOwner: true
12464
+ }),
11581
12465
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
11582
12466
  defaultDenyOutputPaths: denyOutputPaths,
11583
12467
  endEvent,
@@ -11591,7 +12475,9 @@ var AISDKPlugin = class extends BasePlugin {
11591
12475
  traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
11592
12476
  name: "ToolLoopAgent.generate",
11593
12477
  type: "function" /* FUNCTION */,
11594
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
12478
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
12479
+ agentOwner: true
12480
+ }),
11595
12481
  extractOutput: (result, endEvent) => {
11596
12482
  finalizeAISDKChildTracing(endEvent);
11597
12483
  return processAISDKOutput(
@@ -11607,7 +12493,9 @@ var AISDKPlugin = class extends BasePlugin {
11607
12493
  traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
11608
12494
  name: "ToolLoopAgent.stream",
11609
12495
  type: "function" /* FUNCTION */,
11610
- extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
12496
+ extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths, {
12497
+ agentOwner: true
12498
+ }),
11611
12499
  extractOutput: (result, endEvent) => processAISDKOutput(
11612
12500
  result,
11613
12501
  resolveDenyOutputPaths(endEvent, denyOutputPaths)
@@ -11623,6 +12511,42 @@ var AISDKPlugin = class extends BasePlugin {
11623
12511
  })
11624
12512
  })
11625
12513
  );
12514
+ this.unsubscribers.push(
12515
+ traceStreamingChannel(aiSDKChannels.workflowAgentStream, {
12516
+ name: "WorkflowAgent.stream",
12517
+ type: "function" /* FUNCTION */,
12518
+ extractInput: ([params], event, span) => prepareAISDKWorkflowAgentStreamInput(
12519
+ params,
12520
+ event,
12521
+ span,
12522
+ denyOutputPaths
12523
+ ),
12524
+ extractOutput: (result, endEvent) => {
12525
+ finalizeAISDKChildTracing(endEvent);
12526
+ return processAISDKOutput(
12527
+ result,
12528
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
12529
+ );
12530
+ },
12531
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
12532
+ aggregateChunks: aggregateAISDKChunks,
12533
+ onComplete: ({ span }) => {
12534
+ unregisterWorkflowAgentWrapperSpan(span);
12535
+ },
12536
+ onError: ({ event, span }) => {
12537
+ finalizeAISDKChildTracing(event);
12538
+ unregisterWorkflowAgentWrapperSpan(span);
12539
+ },
12540
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
12541
+ defaultDenyOutputPaths: denyOutputPaths,
12542
+ endEvent,
12543
+ onComplete: () => unregisterWorkflowAgentWrapperSpan(span),
12544
+ result,
12545
+ span,
12546
+ startTime
12547
+ })
12548
+ })
12549
+ );
11626
12550
  }
11627
12551
  };
11628
12552
  function subscribeToAISDKV7TelemetryDispatcher() {
@@ -11634,7 +12558,11 @@ function subscribeToAISDKV7TelemetryDispatcher() {
11634
12558
  if (telemetryOptions?.isEnabled === false) {
11635
12559
  return;
11636
12560
  }
11637
- patchAISDKV7TelemetryDispatcher(event.result, telemetry);
12561
+ patchAISDKV7TelemetryDispatcher(
12562
+ event.result,
12563
+ telemetry,
12564
+ telemetryOptions
12565
+ );
11638
12566
  }
11639
12567
  };
11640
12568
  channel.subscribe(handlers);
@@ -11642,7 +12570,7 @@ function subscribeToAISDKV7TelemetryDispatcher() {
11642
12570
  channel.unsubscribe(handlers);
11643
12571
  };
11644
12572
  }
11645
- function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
12573
+ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
11646
12574
  if (!isObject(dispatcher)) {
11647
12575
  return;
11648
12576
  }
@@ -11651,6 +12579,54 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
11651
12579
  return;
11652
12580
  }
11653
12581
  dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true;
12582
+ let operationKey;
12583
+ const telemetryEventFields = {};
12584
+ if (typeof telemetryOptions?.recordInputs === "boolean") {
12585
+ telemetryEventFields.recordInputs = telemetryOptions.recordInputs;
12586
+ }
12587
+ if (typeof telemetryOptions?.recordOutputs === "boolean") {
12588
+ telemetryEventFields.recordOutputs = telemetryOptions.recordOutputs;
12589
+ }
12590
+ if (typeof telemetryOptions?.functionId === "string") {
12591
+ telemetryEventFields.functionId = telemetryOptions.functionId;
12592
+ }
12593
+ const eventWithOperationKey = (event) => {
12594
+ if (!isObject(event)) {
12595
+ return event;
12596
+ }
12597
+ const eventRecord = event;
12598
+ const callId = typeof eventRecord.callId === "string" ? eventRecord.callId : "unknown";
12599
+ operationKey ??= `${callId}:${++aiSDKV7TelemetryOperationCounter}`;
12600
+ if (Object.keys(telemetryEventFields).length > 0) {
12601
+ const augmentedEvent = {
12602
+ ...telemetryEventFields,
12603
+ ...event
12604
+ };
12605
+ try {
12606
+ Object.defineProperty(augmentedEvent, BRAINTRUST_AI_SDK_V7_OPERATION_KEY, {
12607
+ configurable: true,
12608
+ enumerable: false,
12609
+ value: operationKey
12610
+ });
12611
+ } catch {
12612
+ augmentedEvent[BRAINTRUST_AI_SDK_V7_OPERATION_KEY] = operationKey;
12613
+ }
12614
+ return augmentedEvent;
12615
+ }
12616
+ try {
12617
+ Object.defineProperty(eventRecord, BRAINTRUST_AI_SDK_V7_OPERATION_KEY, {
12618
+ configurable: true,
12619
+ enumerable: false,
12620
+ value: operationKey
12621
+ });
12622
+ return event;
12623
+ } catch {
12624
+ return {
12625
+ ...event,
12626
+ [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey
12627
+ };
12628
+ }
12629
+ };
11654
12630
  for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
11655
12631
  const braintrustCallback = telemetry[key];
11656
12632
  if (typeof braintrustCallback !== "function") {
@@ -11659,13 +12635,19 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
11659
12635
  const existingCallback = dispatcherRecord[key];
11660
12636
  dispatcherRecord[key] = (event) => {
11661
12637
  const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
11662
- const braintrustResult = braintrustCallback.call(telemetry, event);
11663
- const pending = [existingResult, braintrustResult].filter(isPromiseLike);
11664
- if (pending.length > 0) {
11665
- return Promise.allSettled(pending).then(() => void 0);
11666
- }
11667
- };
11668
- }
12638
+ try {
12639
+ const braintrustResult = braintrustCallback.call(
12640
+ telemetry,
12641
+ eventWithOperationKey(event)
12642
+ );
12643
+ if (isPromiseLike(braintrustResult)) {
12644
+ void Promise.resolve(braintrustResult).catch(() => void 0);
12645
+ }
12646
+ } catch {
12647
+ }
12648
+ return existingResult;
12649
+ };
12650
+ }
11669
12651
  const braintrustExecuteTool = telemetry.executeTool;
11670
12652
  if (typeof braintrustExecuteTool !== "function") {
11671
12653
  return;
@@ -11673,6 +12655,7 @@ function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
11673
12655
  const existingExecuteTool = dispatcherRecord.executeTool;
11674
12656
  dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
11675
12657
  ...args,
12658
+ ...operationKey ? { [BRAINTRUST_AI_SDK_V7_OPERATION_KEY]: operationKey } : {},
11676
12659
  execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
11677
12660
  });
11678
12661
  }
@@ -11771,6 +12754,8 @@ var serializeOutputObject = (output, model) => {
11771
12754
  var processInputAttachmentsSync = (input) => {
11772
12755
  if (!input) return { input };
11773
12756
  const processed = { ...input };
12757
+ delete processed.headers;
12758
+ delete processed.experimental_output;
11774
12759
  if (input.messages && Array.isArray(input.messages)) {
11775
12760
  processed.messages = input.messages.map(processMessage);
11776
12761
  }
@@ -11804,10 +12789,10 @@ var processInputAttachmentsSync = (input) => {
11804
12789
  processed.output = serialized;
11805
12790
  }
11806
12791
  }
11807
- if ("prepareCall" in processed && typeof processed.prepareCall === "function") {
11808
- processed.prepareCall = "[Function]";
11809
- }
11810
- return { input: processed, outputPromise };
12792
+ return {
12793
+ input: sanitizeAISDKCallInputValue(processed),
12794
+ outputPromise
12795
+ };
11811
12796
  };
11812
12797
  var processMessage = (message) => {
11813
12798
  if (!message || typeof message !== "object") return message;
@@ -11971,7 +12956,21 @@ var convertDataToAttachment = (data, mimeType, filename) => {
11971
12956
  function processAISDKCallInput(params) {
11972
12957
  return processInputAttachmentsSync(params);
11973
12958
  }
11974
- function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
12959
+ function processAISDKWorkflowAgentCallInput(params) {
12960
+ const processed = processAISDKCallInput(params);
12961
+ return {
12962
+ ...processed,
12963
+ input: extractWorkflowAgentInput(processed.input)
12964
+ };
12965
+ }
12966
+ function processAISDKWorkflowAgentModelCallInput(params) {
12967
+ const processed = processAISDKCallInput(params);
12968
+ return {
12969
+ ...processed,
12970
+ input: extractWorkflowAgentModelInput(processed.input)
12971
+ };
12972
+ }
12973
+ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths, childTracingOptions = {}) {
11975
12974
  const { input, outputPromise } = processAISDKCallInput(params);
11976
12975
  if (outputPromise && input && typeof input === "object") {
11977
12976
  outputPromise.then((resolvedData) => {
@@ -11990,7 +12989,29 @@ function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
11990
12989
  event.self,
11991
12990
  span,
11992
12991
  defaultDenyOutputPaths,
11993
- event.aiSDK
12992
+ event.aiSDK,
12993
+ childTracingOptions
12994
+ );
12995
+ event.modelWrapped = childTracing.modelWrapped;
12996
+ if (childTracing.cleanup) {
12997
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
12998
+ }
12999
+ return {
13000
+ input,
13001
+ metadata
13002
+ };
13003
+ }
13004
+ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOutputPaths) {
13005
+ registerWorkflowAgentWrapperSpan(span);
13006
+ const { input } = processAISDKWorkflowAgentCallInput(params);
13007
+ const metadata = extractWorkflowMetadataFromCallParams(params, event.self);
13008
+ const childTracing = prepareAISDKChildTracing(
13009
+ params,
13010
+ event.self,
13011
+ span,
13012
+ defaultDenyOutputPaths,
13013
+ event.aiSDK,
13014
+ { agentOwner: true, workflowAgent: true }
11994
13015
  );
11995
13016
  event.modelWrapped = childTracing.modelWrapped;
11996
13017
  if (childTracing.cleanup) {
@@ -12027,6 +13048,9 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
12027
13048
  function hasModelChildTracing(event) {
12028
13049
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
12029
13050
  }
13051
+ function serializeToolExecutionInput(args) {
13052
+ return args.length > 0 ? args[0] : args;
13053
+ }
12030
13054
  function createAISDKIntegrationMetadata() {
12031
13055
  return {
12032
13056
  braintrust: {
@@ -12038,6 +13062,13 @@ function createAISDKIntegrationMetadata() {
12038
13062
  function resolveModelFromSelf(self) {
12039
13063
  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;
12040
13064
  }
13065
+ function resolveToolsFromSelf(self) {
13066
+ if (!self || typeof self !== "object") {
13067
+ return void 0;
13068
+ }
13069
+ const selfRecord = self;
13070
+ return selfRecord.tools ?? selfRecord.settings?.tools;
13071
+ }
12041
13072
  function extractBaseMetadata(model, self) {
12042
13073
  const metadata = createAISDKIntegrationMetadata();
12043
13074
  const { model: modelId, provider } = serializeModelWithProvider(
@@ -12053,12 +13084,175 @@ function extractBaseMetadata(model, self) {
12053
13084
  }
12054
13085
  function extractMetadataFromCallParams(params, self) {
12055
13086
  const metadata = extractBaseMetadata(params.model, self);
12056
- const tools = serializeAISDKToolsForLogging(params.tools);
13087
+ const tools = serializeAISDKToolsForLogging(
13088
+ params.tools ?? resolveToolsFromSelf(self)
13089
+ );
12057
13090
  if (tools) {
12058
13091
  metadata.tools = tools;
12059
13092
  }
12060
13093
  return metadata;
12061
13094
  }
13095
+ function extractWorkflowMetadataFromCallParams(params, self) {
13096
+ const metadata = extractMetadataFromCallParams(params, self);
13097
+ const options = extractAISDKCallOptionsForMetadata(params);
13098
+ if (Object.keys(options).length > 0) {
13099
+ metadata.options = options;
13100
+ }
13101
+ return metadata;
13102
+ }
13103
+ function extractWorkflowAgentInput(params) {
13104
+ const input = {};
13105
+ if (params.instructions !== void 0) {
13106
+ input.instructions = params.instructions;
13107
+ }
13108
+ if (params.system !== void 0) {
13109
+ input.system = params.system;
13110
+ }
13111
+ if (Array.isArray(params.messages)) {
13112
+ return { ...input, messages: params.messages };
13113
+ }
13114
+ if (typeof params.prompt === "string") {
13115
+ return { ...input, prompt: params.prompt };
13116
+ }
13117
+ if (Array.isArray(params.prompt)) {
13118
+ return { ...input, prompt: params.prompt };
13119
+ }
13120
+ return input;
13121
+ }
13122
+ function extractWorkflowAgentModelInput(params) {
13123
+ const input = {};
13124
+ if (params.instructions !== void 0) {
13125
+ input.instructions = params.instructions;
13126
+ }
13127
+ if (params.system !== void 0) {
13128
+ input.system = params.system;
13129
+ }
13130
+ if (Array.isArray(params.messages)) {
13131
+ return { ...input, messages: params.messages };
13132
+ }
13133
+ if (typeof params.prompt === "string") {
13134
+ return { ...input, prompt: params.prompt };
13135
+ }
13136
+ if (Array.isArray(params.prompt)) {
13137
+ return { ...input, messages: params.prompt };
13138
+ }
13139
+ return input;
13140
+ }
13141
+ function sanitizeAISDKCallInputValue(value, depth = 0) {
13142
+ if (value === void 0 || typeof value === "function") {
13143
+ return void 0;
13144
+ }
13145
+ if (value === null || typeof value !== "object") {
13146
+ return value;
13147
+ }
13148
+ if (isPromiseLike(value)) {
13149
+ return "[Promise]";
13150
+ }
13151
+ if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) {
13152
+ return "[AbortSignal]";
13153
+ }
13154
+ if (depth >= 8) {
13155
+ return "[Object]";
13156
+ }
13157
+ if (Array.isArray(value)) {
13158
+ return value.map((item) => sanitizeAISDKCallInputValue(item, depth + 1)).filter((item) => item !== void 0);
13159
+ }
13160
+ if (!isObject(value)) {
13161
+ return value;
13162
+ }
13163
+ const prototype = Object.getPrototypeOf(value);
13164
+ if (prototype !== Object.prototype && prototype !== null) {
13165
+ return value;
13166
+ }
13167
+ const sanitized = {};
13168
+ for (const [key, nested] of Object.entries(value)) {
13169
+ if (key === "__proto__" || key === "constructor" || key === "prototype" || key.toLowerCase() === "headers") {
13170
+ continue;
13171
+ }
13172
+ const sanitizedNested = sanitizeAISDKCallInputValue(nested, depth + 1);
13173
+ if (sanitizedNested !== void 0) {
13174
+ sanitized[key] = sanitizedNested;
13175
+ }
13176
+ }
13177
+ return sanitized;
13178
+ }
13179
+ function extractAISDKCallOptionsForMetadata(params) {
13180
+ const options = {};
13181
+ const inputOrTopLevelKeys = /* @__PURE__ */ new Set([
13182
+ "model",
13183
+ "instructions",
13184
+ "messages",
13185
+ "prompt",
13186
+ "system",
13187
+ "tools",
13188
+ "headers",
13189
+ "abortSignal",
13190
+ "signal",
13191
+ "experimental_output"
13192
+ ]);
13193
+ for (const [key, value] of Object.entries(params)) {
13194
+ if (inputOrTopLevelKeys.has(key) || key === "__proto__" || key === "constructor" || key === "prototype" || /^on[A-Z]/.test(key) && typeof value === "function") {
13195
+ continue;
13196
+ }
13197
+ const sanitized = sanitizeAISDKMetadataValue(value);
13198
+ if (sanitized !== void 0) {
13199
+ options[key] = sanitized;
13200
+ }
13201
+ }
13202
+ return options;
13203
+ }
13204
+ function sanitizeAISDKMetadataValue(value, depth = 0) {
13205
+ if (value === void 0) {
13206
+ return void 0;
13207
+ }
13208
+ if (typeof value === "function") {
13209
+ return "[Function]";
13210
+ }
13211
+ if (value === null || typeof value !== "object") {
13212
+ return value;
13213
+ }
13214
+ if (isPromiseLike(value)) {
13215
+ return "[Promise]";
13216
+ }
13217
+ if (typeof AbortSignal !== "undefined" && value instanceof AbortSignal) {
13218
+ return "[AbortSignal]";
13219
+ }
13220
+ if (depth >= 8) {
13221
+ return "[Object]";
13222
+ }
13223
+ if (Array.isArray(value)) {
13224
+ return value.map((item) => sanitizeAISDKMetadataValue(item, depth + 1)).filter((item) => item !== void 0);
13225
+ }
13226
+ if (!isObject(value)) {
13227
+ return value;
13228
+ }
13229
+ const sanitized = {};
13230
+ for (const [key, nested] of Object.entries(value)) {
13231
+ if (key === "__proto__" || key === "constructor" || key === "prototype" || key.toLowerCase() === "headers") {
13232
+ continue;
13233
+ }
13234
+ const sanitizedNested = sanitizeAISDKMetadataValue(nested, depth + 1);
13235
+ if (sanitizedNested !== void 0) {
13236
+ sanitized[key] = sanitizedNested;
13237
+ }
13238
+ }
13239
+ return sanitized;
13240
+ }
13241
+ function buildAISDKModelStartEvent(callOptions, baseMetadata, options) {
13242
+ if (!options.workflowAgent) {
13243
+ return {
13244
+ input: processAISDKCallInput(callOptions).input,
13245
+ metadata: baseMetadata
13246
+ };
13247
+ }
13248
+ return {
13249
+ input: processAISDKWorkflowAgentModelCallInput(callOptions).input,
13250
+ metadata: {
13251
+ ...baseMetadata,
13252
+ ...extractWorkflowMetadataFromCallParams(callOptions)
13253
+ }
13254
+ };
13255
+ }
12062
13256
  function extractMetadataFromEmbedParams(params, self) {
12063
13257
  return extractBaseMetadata(params.model, self);
12064
13258
  }
@@ -12072,65 +13266,228 @@ function extractMetadataFromRerankParams(params, self) {
12072
13266
  }
12073
13267
  return metadata;
12074
13268
  }
12075
- function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
13269
+ function activeAISDKChildPatchEntry(entries) {
13270
+ const activeSpan = currentSpan();
13271
+ const activeSpanId = activeSpan.spanId;
13272
+ if (activeSpanId) {
13273
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
13274
+ const entry = entries[index];
13275
+ if (entry?.activeSpanIds.has(activeSpanId)) {
13276
+ return entry;
13277
+ }
13278
+ }
13279
+ }
13280
+ const activeParentSpanIds = activeSpan.spanParents ?? [];
13281
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
13282
+ const entry = entries[index];
13283
+ if (entry?.parentSpan.spanId && activeParentSpanIds.includes(entry.parentSpan.spanId)) {
13284
+ return entry;
13285
+ }
13286
+ }
13287
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
13288
+ const entry = entries[index];
13289
+ if (entry?.parentSpan.spanId === activeSpanId) {
13290
+ return entry;
13291
+ }
13292
+ }
13293
+ return entries[entries.length - 1];
13294
+ }
13295
+ function attachNestedAISDKChildPatchEntry(entries, nestedSpan, cleanup) {
13296
+ const activeSpanId = currentSpan().spanId;
13297
+ if (!activeSpanId || activeSpanId === nestedSpan.spanId) {
13298
+ return false;
13299
+ }
13300
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
13301
+ const entry = entries[index];
13302
+ if (entry?.parentSpan.spanId === activeSpanId || entry?.activeSpanIds.has(activeSpanId)) {
13303
+ entry.activeSpanIds.add(nestedSpan.spanId);
13304
+ cleanup.push(() => {
13305
+ entry.activeSpanIds.delete(nestedSpan.spanId);
13306
+ });
13307
+ return true;
13308
+ }
13309
+ }
13310
+ return false;
13311
+ }
13312
+ function shadowActiveAISDKChildPatchEntry(entries, entry, nestedSpan, cleanup) {
13313
+ const activeSpanId = currentSpan().spanId;
13314
+ if (!activeSpanId || activeSpanId === nestedSpan.spanId) {
13315
+ return;
13316
+ }
13317
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
13318
+ const existingEntry = entries[index];
13319
+ if (existingEntry?.parentSpan.spanId === activeSpanId || existingEntry?.activeSpanIds.has(activeSpanId)) {
13320
+ entry.activeSpanIds.add(activeSpanId);
13321
+ cleanup.push(() => {
13322
+ entry.activeSpanIds.delete(activeSpanId);
13323
+ });
13324
+ return;
13325
+ }
13326
+ }
13327
+ }
13328
+ function closeOpenAISDKModelPatchSpans(entry) {
13329
+ for (const span of entry.openSpans) {
13330
+ span.end();
13331
+ }
13332
+ entry.openSpans.clear();
13333
+ }
13334
+ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK, childTracingOptions = {}) {
12076
13335
  const cleanup = [];
12077
- const patchedModels = /* @__PURE__ */ new WeakSet();
13336
+ const patchedModels = /* @__PURE__ */ new WeakMap();
12078
13337
  const patchedTools = /* @__PURE__ */ new WeakSet();
12079
13338
  let modelWrapped = false;
12080
13339
  const patchModel = (model) => {
12081
13340
  const resolvedModel = resolveAISDKModel(model, aiSDK);
12082
- if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
13341
+ if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function") {
12083
13342
  return resolvedModel;
12084
13343
  }
12085
- patchedModels.add(resolvedModel);
12086
- resolvedModel[AUTO_PATCHED_MODEL] = true;
13344
+ const existingWrappedModel = patchedModels.get(resolvedModel);
13345
+ if (existingWrappedModel) {
13346
+ modelWrapped = true;
13347
+ return existingWrappedModel;
13348
+ }
12087
13349
  modelWrapped = true;
13350
+ const modelRecord = resolvedModel;
13351
+ const entry = {
13352
+ activeSpanIds: /* @__PURE__ */ new Set([parentSpan.spanId]),
13353
+ baseMetadata: buildAISDKChildMetadata(resolvedModel),
13354
+ childTracingOptions,
13355
+ denyOutputPaths,
13356
+ openSpans: /* @__PURE__ */ new Set(),
13357
+ parentSpan
13358
+ };
13359
+ const cleanupModelEntry = (state2, patchedModel) => {
13360
+ closeOpenAISDKModelPatchSpans(entry);
13361
+ const index = state2.entries.indexOf(entry);
13362
+ if (index >= 0) {
13363
+ state2.entries.splice(index, 1);
13364
+ }
13365
+ if (state2.entries.length > 0) {
13366
+ return;
13367
+ }
13368
+ patchedModel.doGenerate = state2.originalDoGenerate;
13369
+ patchedModel.doStream = state2.originalDoStream;
13370
+ delete patchedModel[AUTO_PATCHED_MODEL];
13371
+ };
13372
+ const existingState = modelRecord[AUTO_PATCHED_MODEL];
13373
+ if (existingState) {
13374
+ patchedModels.set(resolvedModel, resolvedModel);
13375
+ if (childTracingOptions.agentOwner && attachNestedAISDKChildPatchEntry(
13376
+ existingState.entries,
13377
+ parentSpan,
13378
+ cleanup
13379
+ )) {
13380
+ return resolvedModel;
13381
+ }
13382
+ if (!childTracingOptions.agentOwner) {
13383
+ shadowActiveAISDKChildPatchEntry(
13384
+ existingState.entries,
13385
+ entry,
13386
+ parentSpan,
13387
+ cleanup
13388
+ );
13389
+ }
13390
+ existingState.entries.push(entry);
13391
+ cleanup.push(() => {
13392
+ cleanupModelEntry(existingState, modelRecord);
13393
+ });
13394
+ return resolvedModel;
13395
+ }
12088
13396
  const originalDoGenerate = resolvedModel.doGenerate;
12089
13397
  const originalDoStream = resolvedModel.doStream;
12090
- const baseMetadata = buildAISDKChildMetadata(resolvedModel);
12091
- resolvedModel.doGenerate = async function doGeneratePatched(options) {
12092
- return parentSpan.traced(
13398
+ const wrappedModel = Object.create(
13399
+ Object.getPrototypeOf(resolvedModel)
13400
+ );
13401
+ Object.defineProperties(
13402
+ wrappedModel,
13403
+ Object.getOwnPropertyDescriptors(resolvedModel)
13404
+ );
13405
+ const wrappedModelRecord = wrappedModel;
13406
+ const state = {
13407
+ entries: [entry],
13408
+ originalDoGenerate,
13409
+ originalDoStream
13410
+ };
13411
+ Object.defineProperty(wrappedModel, AUTO_PATCHED_MODEL, {
13412
+ configurable: true,
13413
+ value: state
13414
+ });
13415
+ wrappedModel.doGenerate = async function doGeneratePatched(callOptions) {
13416
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
13417
+ if (!activeEntry) {
13418
+ return Reflect.apply(originalDoGenerate, resolvedModel, [callOptions]);
13419
+ }
13420
+ closeOpenAISDKModelPatchSpans(activeEntry);
13421
+ return activeEntry.parentSpan.traced(
12093
13422
  async (span) => {
12094
- const result = await Reflect.apply(
12095
- originalDoGenerate,
12096
- resolvedModel,
12097
- [options]
12098
- );
12099
- span.log({
12100
- output: processAISDKOutput(result, denyOutputPaths),
12101
- metrics: extractTokenMetrics(result),
12102
- ...buildResolvedMetadataPayload(result)
12103
- });
12104
- return result;
13423
+ activeEntry.openSpans.add(span);
13424
+ try {
13425
+ const result = await Reflect.apply(
13426
+ originalDoGenerate,
13427
+ resolvedModel,
13428
+ [callOptions]
13429
+ );
13430
+ const output = processAISDKOutput(
13431
+ result,
13432
+ activeEntry.denyOutputPaths
13433
+ );
13434
+ const metrics = extractTokenMetrics(result);
13435
+ const metadataPayload = buildResolvedMetadataPayload(result);
13436
+ const missingUsageMetadata = buildMissingUsageMetadata(
13437
+ output,
13438
+ metrics,
13439
+ "ai_sdk_result_missing_usage"
13440
+ );
13441
+ span.log({
13442
+ output,
13443
+ metrics,
13444
+ ...mergeMetadataPayload(metadataPayload, missingUsageMetadata)
13445
+ });
13446
+ return result;
13447
+ } finally {
13448
+ activeEntry.openSpans.delete(span);
13449
+ }
12105
13450
  },
12106
13451
  {
12107
13452
  name: "doGenerate",
12108
13453
  spanAttributes: {
12109
13454
  type: "llm" /* LLM */
12110
13455
  },
12111
- event: {
12112
- input: processAISDKCallInput(options).input,
12113
- metadata: baseMetadata
12114
- }
13456
+ event: buildAISDKModelStartEvent(
13457
+ callOptions,
13458
+ activeEntry.baseMetadata,
13459
+ {
13460
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
13461
+ }
13462
+ )
12115
13463
  }
12116
13464
  );
12117
13465
  };
12118
13466
  if (originalDoStream) {
12119
- resolvedModel.doStream = async function doStreamPatched(options) {
12120
- const span = parentSpan.startSpan({
13467
+ wrappedModel.doStream = async function doStreamPatched(callOptions) {
13468
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
13469
+ if (!activeEntry) {
13470
+ return Reflect.apply(originalDoStream, resolvedModel, [callOptions]);
13471
+ }
13472
+ closeOpenAISDKModelPatchSpans(activeEntry);
13473
+ const span = activeEntry.parentSpan.startSpan({
12121
13474
  name: "doStream",
12122
13475
  spanAttributes: {
12123
13476
  type: "llm" /* LLM */
12124
13477
  },
12125
- event: {
12126
- input: processAISDKCallInput(options).input,
12127
- metadata: baseMetadata
12128
- }
13478
+ event: buildAISDKModelStartEvent(
13479
+ callOptions,
13480
+ activeEntry.baseMetadata,
13481
+ {
13482
+ workflowAgent: activeEntry.childTracingOptions.workflowAgent
13483
+ }
13484
+ )
12129
13485
  });
13486
+ activeEntry.openSpans.add(span);
12130
13487
  const streamStartTime = getCurrentUnixTimestamp();
12131
13488
  const result = await withCurrent(
12132
13489
  span,
12133
- () => Reflect.apply(originalDoStream, resolvedModel, [options])
13490
+ () => Reflect.apply(originalDoStream, resolvedModel, [callOptions])
12134
13491
  );
12135
13492
  let firstChunkTime;
12136
13493
  const output = {};
@@ -12138,6 +13495,44 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
12138
13495
  let reasoning = "";
12139
13496
  const toolCalls = [];
12140
13497
  let object = void 0;
13498
+ let streamSpanEnded = false;
13499
+ const logAndEndStreamSpan = (usageUnavailableReason) => {
13500
+ if (streamSpanEnded) {
13501
+ return;
13502
+ }
13503
+ output.text = text;
13504
+ output.reasoning = reasoning;
13505
+ output.toolCalls = toolCalls;
13506
+ if (object !== void 0) {
13507
+ output.object = object;
13508
+ }
13509
+ const metrics = extractTokenMetrics(output);
13510
+ if (firstChunkTime !== void 0 && !activeEntry.childTracingOptions.workflowAgent) {
13511
+ metrics.time_to_first_token = Math.max(
13512
+ firstChunkTime - streamStartTime,
13513
+ 1e-6
13514
+ );
13515
+ }
13516
+ const metadataPayload = buildResolvedMetadataPayload(
13517
+ output
13518
+ );
13519
+ const missingUsageMetadata = usageUnavailableReason ? { usage_unavailable_reason: usageUnavailableReason } : buildMissingUsageMetadata(
13520
+ output,
13521
+ metrics,
13522
+ "ai_sdk_result_missing_usage"
13523
+ );
13524
+ span.log({
13525
+ output: processAISDKOutput(
13526
+ output,
13527
+ activeEntry.denyOutputPaths
13528
+ ),
13529
+ metrics,
13530
+ ...mergeMetadataPayload(metadataPayload, missingUsageMetadata)
13531
+ });
13532
+ activeEntry.openSpans.delete(span);
13533
+ span.end();
13534
+ streamSpanEnded = true;
13535
+ };
12141
13536
  const transformStream = new TransformStream({
12142
13537
  transform(chunk, controller) {
12143
13538
  if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
@@ -12175,33 +13570,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
12175
13570
  }
12176
13571
  break;
12177
13572
  case "finish":
12178
- output.text = text;
12179
- output.reasoning = reasoning;
12180
- output.toolCalls = toolCalls;
12181
13573
  output.finishReason = chunk.finishReason;
12182
13574
  output.usage = chunk.usage;
12183
- if (object !== void 0) {
12184
- output.object = object;
12185
- }
12186
- const metrics = extractTokenMetrics(output);
12187
- if (firstChunkTime !== void 0) {
12188
- metrics.time_to_first_token = Math.max(
12189
- firstChunkTime - streamStartTime,
12190
- 1e-6
12191
- );
12192
- }
12193
- span.log({
12194
- output: processAISDKOutput(
12195
- output,
12196
- denyOutputPaths
12197
- ),
12198
- metrics,
12199
- ...buildResolvedMetadataPayload(output)
12200
- });
12201
- span.end();
13575
+ logAndEndStreamSpan();
12202
13576
  break;
12203
13577
  }
12204
13578
  controller.enqueue(chunk);
13579
+ },
13580
+ flush() {
13581
+ logAndEndStreamSpan("ai_sdk_stream_finished_without_usage");
12205
13582
  }
12206
13583
  });
12207
13584
  return {
@@ -12211,32 +13588,79 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
12211
13588
  };
12212
13589
  }
12213
13590
  cleanup.push(() => {
12214
- resolvedModel.doGenerate = originalDoGenerate;
12215
- if (originalDoStream) {
12216
- resolvedModel.doStream = originalDoStream;
12217
- }
12218
- delete resolvedModel[AUTO_PATCHED_MODEL];
13591
+ cleanupModelEntry(state, wrappedModelRecord);
12219
13592
  });
12220
- return resolvedModel;
13593
+ patchedModels.set(resolvedModel, wrappedModel);
13594
+ patchedModels.set(wrappedModel, wrappedModel);
13595
+ return wrappedModel;
12221
13596
  };
12222
13597
  const patchTool = (tool, name) => {
12223
- if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
13598
+ if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool)) {
12224
13599
  return;
12225
13600
  }
12226
13601
  patchedTools.add(tool);
12227
- tool[AUTO_PATCHED_TOOL] = true;
12228
- const originalExecute = tool.execute;
13602
+ const toolRecord = tool;
13603
+ const entry = {
13604
+ activeSpanIds: /* @__PURE__ */ new Set([parentSpan.spanId]),
13605
+ childTracingOptions,
13606
+ name,
13607
+ parentSpan
13608
+ };
13609
+ const cleanupToolEntry = (state2) => {
13610
+ const index = state2.entries.indexOf(entry);
13611
+ if (index >= 0) {
13612
+ state2.entries.splice(index, 1);
13613
+ }
13614
+ if (state2.entries.length > 0) {
13615
+ return;
13616
+ }
13617
+ tool.execute = state2.originalExecute;
13618
+ delete toolRecord[AUTO_PATCHED_TOOL];
13619
+ };
13620
+ const existingState = toolRecord[AUTO_PATCHED_TOOL];
13621
+ if (existingState) {
13622
+ if (childTracingOptions.agentOwner && attachNestedAISDKChildPatchEntry(
13623
+ existingState.entries,
13624
+ parentSpan,
13625
+ cleanup
13626
+ )) {
13627
+ return;
13628
+ }
13629
+ if (!childTracingOptions.agentOwner) {
13630
+ shadowActiveAISDKChildPatchEntry(
13631
+ existingState.entries,
13632
+ entry,
13633
+ parentSpan,
13634
+ cleanup
13635
+ );
13636
+ }
13637
+ existingState.entries.push(entry);
13638
+ cleanup.push(() => {
13639
+ cleanupToolEntry(existingState);
13640
+ });
13641
+ return;
13642
+ }
13643
+ const originalExecute = toolRecord.execute;
13644
+ const state = {
13645
+ entries: [entry],
13646
+ originalExecute
13647
+ };
13648
+ toolRecord[AUTO_PATCHED_TOOL] = state;
12229
13649
  tool.execute = function executePatched(...args) {
13650
+ const activeEntry = activeAISDKChildPatchEntry(state.entries);
12230
13651
  const result = Reflect.apply(originalExecute, this, args);
13652
+ if (!activeEntry) {
13653
+ return result;
13654
+ }
12231
13655
  if (isAsyncGenerator(result)) {
12232
13656
  return (async function* () {
12233
- const span = parentSpan.startSpan({
12234
- name,
13657
+ const span = activeEntry.parentSpan.startSpan({
13658
+ name: activeEntry.name,
12235
13659
  spanAttributes: {
12236
13660
  type: "tool" /* TOOL */
12237
13661
  }
12238
13662
  });
12239
- span.log({ input: args.length === 1 ? args[0] : args });
13663
+ span.log({ input: serializeToolExecutionInput(args) });
12240
13664
  try {
12241
13665
  let lastValue;
12242
13666
  for await (const value of result) {
@@ -12252,15 +13676,15 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
12252
13676
  }
12253
13677
  })();
12254
13678
  }
12255
- return parentSpan.traced(
13679
+ return activeEntry.parentSpan.traced(
12256
13680
  async (span) => {
12257
- span.log({ input: args.length === 1 ? args[0] : args });
13681
+ span.log({ input: serializeToolExecutionInput(args) });
12258
13682
  const awaitedResult = await result;
12259
13683
  span.log({ output: awaitedResult });
12260
13684
  return awaitedResult;
12261
13685
  },
12262
13686
  {
12263
- name,
13687
+ name: activeEntry.name,
12264
13688
  spanAttributes: {
12265
13689
  type: "tool" /* TOOL */
12266
13690
  }
@@ -12268,8 +13692,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
12268
13692
  );
12269
13693
  };
12270
13694
  cleanup.push(() => {
12271
- tool.execute = originalExecute;
12272
- delete tool[AUTO_PATCHED_TOOL];
13695
+ cleanupToolEntry(state);
12273
13696
  });
12274
13697
  };
12275
13698
  const patchTools = (tools) => {
@@ -12288,25 +13711,42 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
12288
13711
  }
12289
13712
  };
12290
13713
  if (params && typeof params === "object") {
12291
- const patchedParamModel = patchModel(params.model);
12292
- if (typeof params.model === "string" && patchedParamModel && typeof patchedParamModel === "object") {
13714
+ const originalParamModel = params.model;
13715
+ const patchedParamModel = patchModel(originalParamModel);
13716
+ if (patchedParamModel && patchedParamModel !== originalParamModel) {
12293
13717
  params.model = patchedParamModel;
13718
+ cleanup.push(() => {
13719
+ params.model = originalParamModel;
13720
+ });
12294
13721
  }
12295
13722
  patchTools(params.tools);
12296
13723
  }
12297
13724
  if (self && typeof self === "object") {
12298
13725
  const selfRecord = self;
12299
13726
  if (selfRecord.model !== void 0) {
12300
- const patchedSelfModel = patchModel(selfRecord.model);
12301
- if (typeof selfRecord.model === "string" && patchedSelfModel && typeof patchedSelfModel === "object") {
13727
+ const originalSelfModel = selfRecord.model;
13728
+ const patchedSelfModel = patchModel(originalSelfModel);
13729
+ if (patchedSelfModel && patchedSelfModel !== originalSelfModel) {
12302
13730
  selfRecord.model = patchedSelfModel;
13731
+ cleanup.push(() => {
13732
+ selfRecord.model = originalSelfModel;
13733
+ });
12303
13734
  }
12304
13735
  }
13736
+ if (selfRecord.tools !== void 0) {
13737
+ patchTools(selfRecord.tools);
13738
+ }
12305
13739
  if (selfRecord.settings && typeof selfRecord.settings === "object") {
12306
13740
  if (selfRecord.settings.model !== void 0) {
12307
- const patchedSettingsModel = patchModel(selfRecord.settings.model);
12308
- if (typeof selfRecord.settings.model === "string" && patchedSettingsModel && typeof patchedSettingsModel === "object") {
13741
+ const originalSettingsModel = selfRecord.settings.model;
13742
+ const patchedSettingsModel = patchModel(originalSettingsModel);
13743
+ if (patchedSettingsModel && patchedSettingsModel !== originalSettingsModel) {
12309
13744
  selfRecord.settings.model = patchedSettingsModel;
13745
+ cleanup.push(() => {
13746
+ if (selfRecord.settings) {
13747
+ selfRecord.settings.model = originalSettingsModel;
13748
+ }
13749
+ });
12310
13750
  }
12311
13751
  }
12312
13752
  if (selfRecord.settings.tools !== void 0) {
@@ -12403,99 +13843,190 @@ function isAISDKContentAsyncIterableChunk(chunk) {
12403
13843
  return isObject(part) && typeof part.type !== "string";
12404
13844
  }
12405
13845
  function patchAISDKStreamingResult(args) {
12406
- const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
13846
+ const {
13847
+ defaultDenyOutputPaths,
13848
+ endEvent,
13849
+ onComplete,
13850
+ result,
13851
+ span,
13852
+ startTime
13853
+ } = args;
12407
13854
  if (!result || typeof result !== "object") {
12408
13855
  return false;
12409
13856
  }
12410
13857
  const resultRecord = result;
12411
13858
  attachKnownResultPromiseHandlers(resultRecord);
13859
+ let finalized = false;
13860
+ const finalize = () => {
13861
+ if (finalized) {
13862
+ return;
13863
+ }
13864
+ finalized = true;
13865
+ finalizeAISDKChildTracing(endEvent);
13866
+ span.end();
13867
+ onComplete?.();
13868
+ };
13869
+ let outputLogged = false;
13870
+ const logStreamingOutput = async (firstChunkTime) => {
13871
+ if (outputLogged) {
13872
+ return;
13873
+ }
13874
+ outputLogged = true;
13875
+ try {
13876
+ const metrics = extractTopLevelAISDKMetrics(result, endEvent);
13877
+ if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
13878
+ metrics.time_to_first_token = firstChunkTime - startTime;
13879
+ }
13880
+ const output = await processAISDKStreamingOutput(
13881
+ result,
13882
+ resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
13883
+ );
13884
+ const metadata = buildResolvedMetadataPayload(result).metadata;
13885
+ span.log({
13886
+ output,
13887
+ ...metadata ? { metadata } : {},
13888
+ metrics
13889
+ });
13890
+ } catch (error) {
13891
+ span.log({ error: toLoggedError(error) });
13892
+ } finally {
13893
+ finalize();
13894
+ }
13895
+ };
13896
+ const createAsyncIterableHooks = () => {
13897
+ let firstChunkTime;
13898
+ return {
13899
+ onChunk: (chunk) => {
13900
+ if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
13901
+ firstChunkTime = getCurrentUnixTimestamp();
13902
+ }
13903
+ },
13904
+ onComplete: async () => {
13905
+ await logStreamingOutput(firstChunkTime);
13906
+ },
13907
+ onError: (error) => {
13908
+ if (!outputLogged) {
13909
+ outputLogged = true;
13910
+ span.log({
13911
+ error: error.message
13912
+ });
13913
+ }
13914
+ finalize();
13915
+ },
13916
+ onCancel: finalize
13917
+ };
13918
+ };
13919
+ const patchAsyncIterable = (stream) => isReadableStreamLike(stream) ? createPatchedReadableStream(stream, createAsyncIterableHooks()) : createPatchedAsyncIterable(stream, createAsyncIterableHooks());
13920
+ const patchAsyncIterableField = (field) => {
13921
+ let descriptorOwner = resultRecord;
13922
+ let descriptor;
13923
+ while (descriptorOwner) {
13924
+ descriptor = Object.getOwnPropertyDescriptor(descriptorOwner, field);
13925
+ if (descriptor) {
13926
+ break;
13927
+ }
13928
+ descriptorOwner = Object.getPrototypeOf(descriptorOwner);
13929
+ }
13930
+ if (!descriptor || descriptorOwner === resultRecord && !descriptor.configurable) {
13931
+ return false;
13932
+ }
13933
+ if ("value" in descriptor) {
13934
+ if (!isAsyncIterable(descriptor.value)) {
13935
+ return false;
13936
+ }
13937
+ try {
13938
+ Object.defineProperty(resultRecord, field, {
13939
+ configurable: descriptorOwner === resultRecord ? descriptor.configurable : true,
13940
+ enumerable: descriptor.enumerable,
13941
+ value: patchAsyncIterable(descriptor.value),
13942
+ writable: descriptor.writable
13943
+ });
13944
+ return true;
13945
+ } catch {
13946
+ return false;
13947
+ }
13948
+ }
13949
+ if (typeof descriptor.get !== "function") {
13950
+ return false;
13951
+ }
13952
+ const originalGet = descriptor.get;
13953
+ const originalSet = descriptor.set;
13954
+ try {
13955
+ Object.defineProperty(resultRecord, field, {
13956
+ configurable: descriptorOwner === resultRecord ? descriptor.configurable : true,
13957
+ enumerable: descriptor.enumerable,
13958
+ get() {
13959
+ const stream = originalGet.call(this);
13960
+ return isAsyncIterable(stream) ? patchAsyncIterable(stream) : stream;
13961
+ },
13962
+ ...originalSet ? {
13963
+ set(value) {
13964
+ originalSet.call(this, value);
13965
+ }
13966
+ } : {}
13967
+ });
13968
+ return true;
13969
+ } catch {
13970
+ return false;
13971
+ }
13972
+ };
13973
+ let patched = false;
12412
13974
  if (isReadableStreamLike(resultRecord.baseStream)) {
12413
- let firstChunkTime2;
12414
- const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
13975
+ let firstChunkTime;
13976
+ const transformedBaseStream = resultRecord.baseStream.pipeThrough(
12415
13977
  new TransformStream({
12416
13978
  transform(chunk, controller) {
12417
- if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
12418
- firstChunkTime2 = getCurrentUnixTimestamp();
13979
+ if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
13980
+ firstChunkTime = getCurrentUnixTimestamp();
12419
13981
  }
12420
13982
  controller.enqueue(chunk);
12421
13983
  },
12422
13984
  async flush() {
12423
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
12424
- if (metrics.time_to_first_token === void 0 && firstChunkTime2 !== void 0) {
12425
- metrics.time_to_first_token = firstChunkTime2 - startTime;
12426
- }
12427
- const output = await processAISDKStreamingOutput(
12428
- result,
12429
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
12430
- );
12431
- const metadata = buildResolvedMetadataPayload(result).metadata;
12432
- span.log({
12433
- output,
12434
- ...metadata ? { metadata } : {},
12435
- metrics
12436
- });
12437
- finalizeAISDKChildTracing(endEvent);
12438
- span.end();
13985
+ await logStreamingOutput(firstChunkTime);
12439
13986
  }
12440
13987
  })
12441
13988
  );
13989
+ const reader = transformedBaseStream.getReader();
13990
+ const wrappedBaseStream = new ReadableStream({
13991
+ async pull(controller) {
13992
+ try {
13993
+ const { done, value } = await reader.read();
13994
+ if (done) {
13995
+ controller.close();
13996
+ return;
13997
+ }
13998
+ controller.enqueue(value);
13999
+ } catch (error) {
14000
+ span.log({ error: toLoggedError(error) });
14001
+ finalize();
14002
+ controller.error(error);
14003
+ }
14004
+ },
14005
+ async cancel(reason) {
14006
+ try {
14007
+ finalize();
14008
+ } finally {
14009
+ await reader.cancel(reason);
14010
+ }
14011
+ }
14012
+ });
12442
14013
  Object.defineProperty(resultRecord, "baseStream", {
12443
14014
  configurable: true,
12444
14015
  enumerable: true,
12445
14016
  value: wrappedBaseStream,
12446
14017
  writable: true
12447
14018
  });
12448
- return true;
14019
+ patched = true;
12449
14020
  }
12450
- const streamField = findAsyncIterableField(resultRecord, [
14021
+ for (const field of [
12451
14022
  "partialObjectStream",
12452
14023
  "textStream",
12453
14024
  "fullStream",
12454
14025
  "stream"
12455
- ]);
12456
- if (!streamField) {
12457
- return false;
14026
+ ]) {
14027
+ patched = patchAsyncIterableField(field) || patched;
12458
14028
  }
12459
- let firstChunkTime;
12460
- const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
12461
- onChunk: (chunk) => {
12462
- if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
12463
- firstChunkTime = getCurrentUnixTimestamp();
12464
- }
12465
- },
12466
- onComplete: async () => {
12467
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
12468
- if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
12469
- metrics.time_to_first_token = firstChunkTime - startTime;
12470
- }
12471
- const output = await processAISDKStreamingOutput(
12472
- result,
12473
- resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
12474
- );
12475
- const metadata = buildResolvedMetadataPayload(result).metadata;
12476
- span.log({
12477
- output,
12478
- ...metadata ? { metadata } : {},
12479
- metrics
12480
- });
12481
- finalizeAISDKChildTracing(endEvent);
12482
- span.end();
12483
- },
12484
- onError: (error) => {
12485
- span.log({
12486
- error: error.message
12487
- });
12488
- finalizeAISDKChildTracing(endEvent);
12489
- span.end();
12490
- }
12491
- });
12492
- Object.defineProperty(resultRecord, streamField.field, {
12493
- configurable: true,
12494
- enumerable: true,
12495
- value: wrappedStream,
12496
- writable: true
12497
- });
12498
- return true;
14029
+ return patched;
12499
14030
  }
12500
14031
  function attachKnownResultPromiseHandlers(result) {
12501
14032
  const promiseLikeFields = [
@@ -12527,34 +14058,72 @@ function attachKnownResultPromiseHandlers(result) {
12527
14058
  }
12528
14059
  }
12529
14060
  function isReadableStreamLike(value) {
12530
- return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
12531
- }
12532
- function findAsyncIterableField(result, candidateFields) {
12533
- for (const field of candidateFields) {
12534
- try {
12535
- const stream = result[field];
12536
- if (isAsyncIterable(stream)) {
12537
- return { field, stream };
14061
+ return value != null && typeof value === "object" && typeof value.getReader === "function" && typeof value.pipeThrough === "function";
14062
+ }
14063
+ function createPatchedReadableStream(stream, hooks) {
14064
+ let reader;
14065
+ let completed = false;
14066
+ return new ReadableStream({
14067
+ async pull(controller) {
14068
+ reader ??= stream.getReader();
14069
+ try {
14070
+ const { done, value } = await reader.read();
14071
+ if (done) {
14072
+ completed = true;
14073
+ await hooks.onComplete();
14074
+ controller.close();
14075
+ return;
14076
+ }
14077
+ hooks.onChunk(value);
14078
+ controller.enqueue(value);
14079
+ } catch (error) {
14080
+ completed = true;
14081
+ hooks.onError(
14082
+ error instanceof Error ? error : new Error(String(error))
14083
+ );
14084
+ controller.error(error);
14085
+ }
14086
+ },
14087
+ async cancel(reason) {
14088
+ if (!completed) {
14089
+ completed = true;
14090
+ try {
14091
+ await hooks.onCancel?.();
14092
+ } catch {
14093
+ }
14094
+ }
14095
+ if (reader) {
14096
+ await reader.cancel(reason);
14097
+ } else if (stream.cancel) {
14098
+ await stream.cancel(reason);
12538
14099
  }
12539
- } catch {
12540
14100
  }
12541
- }
12542
- return null;
14101
+ });
12543
14102
  }
12544
14103
  function createPatchedAsyncIterable(stream, hooks) {
12545
14104
  return {
12546
14105
  async *[Symbol.asyncIterator]() {
14106
+ let completed = false;
12547
14107
  try {
12548
14108
  for await (const chunk of stream) {
12549
14109
  hooks.onChunk(chunk);
12550
14110
  yield chunk;
12551
14111
  }
14112
+ completed = true;
12552
14113
  await hooks.onComplete();
12553
14114
  } catch (error) {
14115
+ completed = true;
12554
14116
  hooks.onError(
12555
14117
  error instanceof Error ? error : new Error(String(error))
12556
14118
  );
12557
14119
  throw error;
14120
+ } finally {
14121
+ if (!completed) {
14122
+ try {
14123
+ await hooks.onCancel?.();
14124
+ } catch {
14125
+ }
14126
+ }
12558
14127
  }
12559
14128
  }
12560
14129
  };
@@ -12629,6 +14198,40 @@ function buildResolvedMetadataPayload(result) {
12629
14198
  }
12630
14199
  return Object.keys(metadata).length > 0 ? { metadata } : {};
12631
14200
  }
14201
+ function mergeMetadataPayload(metadataPayload, extraMetadata) {
14202
+ if (!extraMetadata || Object.keys(extraMetadata).length === 0) {
14203
+ return metadataPayload;
14204
+ }
14205
+ return {
14206
+ metadata: {
14207
+ ...metadataPayload.metadata ?? {},
14208
+ ...extraMetadata
14209
+ }
14210
+ };
14211
+ }
14212
+ function buildMissingUsageMetadata(output, metrics, reason) {
14213
+ if (!hasLoggedOutput(output) || hasTokenUsageMetrics(metrics)) {
14214
+ return void 0;
14215
+ }
14216
+ return { usage_unavailable_reason: reason };
14217
+ }
14218
+ function hasLoggedOutput(output) {
14219
+ if (output === null || output === void 0) {
14220
+ return false;
14221
+ }
14222
+ if (Array.isArray(output)) {
14223
+ return output.length > 0;
14224
+ }
14225
+ if (typeof output === "object") {
14226
+ return Object.keys(output).length > 0;
14227
+ }
14228
+ return true;
14229
+ }
14230
+ function hasTokenUsageMetrics(metrics) {
14231
+ return Object.keys(metrics).some(
14232
+ (key) => key !== "estimated_cost" && key !== "time_to_first_token"
14233
+ );
14234
+ }
12632
14235
  function resolveAISDKModel(model, aiSDK) {
12633
14236
  if (typeof model !== "string") {
12634
14237
  return model;
@@ -12652,7 +14255,45 @@ function isAsyncGenerator(value) {
12652
14255
  function processAISDKOutput(output, denyOutputPaths) {
12653
14256
  if (!output) return output;
12654
14257
  const merged = extractSerializableOutputFields(output);
12655
- return normalizeAISDKLoggedOutput(omit(merged, denyOutputPaths));
14258
+ const deleteOutputPaths = denyOutputPaths.filter(
14259
+ (path2) => path2.toLowerCase().endsWith("headers")
14260
+ );
14261
+ const sanitized = omit(merged, denyOutputPaths, deleteOutputPaths);
14262
+ for (const path2 of TRANSPORT_PAYLOAD_ROOT_PATHS) {
14263
+ const stack = [{ obj: sanitized, keys: parsePath(path2) }];
14264
+ while (stack.length > 0) {
14265
+ const entry = stack.pop();
14266
+ if (!entry || entry.keys.length === 0) {
14267
+ continue;
14268
+ }
14269
+ const firstKey = entry.keys[0];
14270
+ const remainingKeys = entry.keys.slice(1);
14271
+ if (firstKey === "[]") {
14272
+ if (Array.isArray(entry.obj)) {
14273
+ for (const item of entry.obj) {
14274
+ stack.push({
14275
+ obj: item,
14276
+ keys: remainingKeys
14277
+ });
14278
+ }
14279
+ }
14280
+ continue;
14281
+ }
14282
+ if (!entry.obj || typeof entry.obj !== "object" || !(firstKey in entry.obj)) {
14283
+ continue;
14284
+ }
14285
+ const record = entry.obj;
14286
+ if (remainingKeys.length === 0) {
14287
+ record[firstKey] = sanitizeAISDKMetadataValue(record[firstKey]);
14288
+ continue;
14289
+ }
14290
+ stack.push({
14291
+ obj: record[firstKey],
14292
+ keys: remainingKeys
14293
+ });
14294
+ }
14295
+ }
14296
+ return normalizeAISDKLoggedOutput(sanitized);
12656
14297
  }
12657
14298
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
12658
14299
  if (!output || typeof output !== "object") {
@@ -12743,6 +14384,8 @@ function extractTokenMetrics(result) {
12743
14384
  );
12744
14385
  if (totalTokens !== void 0) {
12745
14386
  metrics.tokens = totalTokens;
14387
+ } else if (promptTokens !== void 0 && completionTokens !== void 0) {
14388
+ metrics.tokens = promptTokens + completionTokens;
12746
14389
  }
12747
14390
  const promptCachedTokens = firstNumber(
12748
14391
  usage.inputTokens?.cacheRead,
@@ -12866,7 +14509,9 @@ function extractGetterValues(obj) {
12866
14509
  const getterValues = {};
12867
14510
  const getterNames = [
12868
14511
  "content",
14512
+ "messages",
12869
14513
  "text",
14514
+ "output",
12870
14515
  "object",
12871
14516
  "value",
12872
14517
  "values",
@@ -12906,7 +14551,9 @@ function extractGetterValues(obj) {
12906
14551
  function extractSerializableOutputFields(output) {
12907
14552
  const serialized = {};
12908
14553
  const directFieldNames = [
14554
+ "messages",
12909
14555
  "steps",
14556
+ "output",
12910
14557
  "request",
12911
14558
  "responseMessages",
12912
14559
  "warnings",
@@ -13088,7 +14735,7 @@ function parsePath(path2) {
13088
14735
  }
13089
14736
  return keys;
13090
14737
  }
13091
- function omitAtPath(obj, keys) {
14738
+ function omitAtPath(obj, keys, deleteLeaf = false) {
13092
14739
  if (keys.length === 0) return;
13093
14740
  const firstKey = keys[0];
13094
14741
  const remainingKeys = keys.slice(1);
@@ -13098,29 +14745,36 @@ function omitAtPath(obj, keys) {
13098
14745
  if (remainingKeys.length > 0) {
13099
14746
  omitAtPath(
13100
14747
  item,
13101
- remainingKeys
14748
+ remainingKeys,
14749
+ deleteLeaf
13102
14750
  );
13103
14751
  }
13104
14752
  });
13105
14753
  }
13106
14754
  } else if (remainingKeys.length === 0) {
13107
14755
  if (obj && typeof obj === "object" && firstKey in obj) {
13108
- obj[firstKey] = "<omitted>";
14756
+ if (deleteLeaf) {
14757
+ delete obj[firstKey];
14758
+ } else {
14759
+ obj[firstKey] = "<omitted>";
14760
+ }
13109
14761
  }
13110
14762
  } else {
13111
14763
  if (obj && typeof obj === "object" && firstKey in obj) {
13112
14764
  omitAtPath(
13113
14765
  obj[firstKey],
13114
- remainingKeys
14766
+ remainingKeys,
14767
+ deleteLeaf
13115
14768
  );
13116
14769
  }
13117
14770
  }
13118
14771
  }
13119
- function omit(obj, paths) {
14772
+ function omit(obj, paths, deletePaths = []) {
13120
14773
  const result = deepCopy(obj);
14774
+ const deletePathSet = new Set(deletePaths);
13121
14775
  for (const path2 of paths) {
13122
14776
  const keys = parsePath(path2);
13123
- omitAtPath(result, keys);
14777
+ omitAtPath(result, keys, deletePathSet.has(path2));
13124
14778
  }
13125
14779
  return result;
13126
14780
  }
@@ -13128,11 +14782,14 @@ function omit(obj, paths) {
13128
14782
  // src/wrappers/ai-sdk/telemetry.ts
13129
14783
  function braintrustAISDKTelemetry() {
13130
14784
  const operations = /* @__PURE__ */ new Map();
14785
+ const operationKeysByCallId = /* @__PURE__ */ new Map();
14786
+ const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
13131
14787
  const modelSpans = /* @__PURE__ */ new Map();
13132
14788
  const objectSpans = /* @__PURE__ */ new Map();
13133
14789
  const embedSpans = /* @__PURE__ */ new Map();
13134
14790
  const rerankSpans = /* @__PURE__ */ new Map();
13135
14791
  const toolSpans = /* @__PURE__ */ new Map();
14792
+ let workflowAgentOperationCounter = 0;
13136
14793
  const runSafely = (name, callback) => {
13137
14794
  try {
13138
14795
  callback();
@@ -13140,42 +14797,333 @@ function braintrustAISDKTelemetry() {
13140
14797
  console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error);
13141
14798
  }
13142
14799
  };
13143
- const startChildSpan = (callId, name, type, event) => {
13144
- const parent = operations.get(callId)?.span;
14800
+ const startChildSpan = (operationKey, name, type, event) => {
14801
+ const parent = operations.get(operationKey)?.span;
13145
14802
  const spanArgs = {
13146
14803
  name,
13147
14804
  spanAttributes: { type },
13148
14805
  ...event ? { event } : {}
13149
14806
  };
13150
14807
  const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
13151
- const state = operations.get(callId);
14808
+ const state = operations.get(operationKey);
13152
14809
  if (state && type === "llm" /* LLM */) {
13153
14810
  state.hadModelChild = true;
13154
14811
  }
13155
14812
  return span;
13156
14813
  };
14814
+ const registerOperation = (state) => {
14815
+ operations.set(state.operationKey, state);
14816
+ const keys = operationKeysByCallId.get(state.callId) ?? [];
14817
+ keys.push(state.operationKey);
14818
+ operationKeysByCallId.set(state.callId, keys);
14819
+ };
14820
+ const deleteOperation = (operationKey) => {
14821
+ const state = operations.get(operationKey);
14822
+ if (!state) {
14823
+ return;
14824
+ }
14825
+ operations.delete(operationKey);
14826
+ if (workflowOperationKeyStore.getStore() === operationKey) {
14827
+ workflowOperationKeyStore.enterWith(void 0);
14828
+ }
14829
+ const keys = operationKeysByCallId.get(state.callId);
14830
+ if (!keys) {
14831
+ return;
14832
+ }
14833
+ const index = keys.indexOf(operationKey);
14834
+ if (index >= 0) {
14835
+ keys.splice(index, 1);
14836
+ }
14837
+ if (keys.length === 0) {
14838
+ operationKeysByCallId.delete(state.callId);
14839
+ }
14840
+ };
14841
+ const explicitOperationKey = (event) => {
14842
+ if (!isObject(event)) {
14843
+ return void 0;
14844
+ }
14845
+ const key = event[BRAINTRUST_AI_SDK_V7_OPERATION_KEY];
14846
+ return typeof key === "string" ? key : void 0;
14847
+ };
14848
+ const createOperationKey = (event, operationName) => {
14849
+ const explicit = explicitOperationKey(event);
14850
+ if (explicit) {
14851
+ return explicit;
14852
+ }
14853
+ if (operationName === "WorkflowAgent.stream") {
14854
+ workflowAgentOperationCounter += 1;
14855
+ return `${event.callId}:${workflowAgentOperationCounter}`;
14856
+ }
14857
+ return event.callId;
14858
+ };
14859
+ const operationKeyForCallId = (callId, mode = "active") => {
14860
+ const keys = operationKeysByCallId.get(callId);
14861
+ if (!keys || keys.length === 0) {
14862
+ return operations.has(callId) ? callId : void 0;
14863
+ }
14864
+ if (keys.length === 1) {
14865
+ return keys[0];
14866
+ }
14867
+ const wrapperSpan = currentWorkflowAgentWrapperSpan();
14868
+ if (wrapperSpan?.spanId) {
14869
+ const key = keys.find(
14870
+ (candidate) => operations.get(candidate)?.span.spanId === wrapperSpan.spanId
14871
+ );
14872
+ if (key) {
14873
+ return key;
14874
+ }
14875
+ }
14876
+ const workflowOperationKey = workflowOperationKeyStore.getStore();
14877
+ if (workflowOperationKey && keys.includes(workflowOperationKey)) {
14878
+ return workflowOperationKey;
14879
+ }
14880
+ if (callId === "workflow-agent") {
14881
+ return void 0;
14882
+ }
14883
+ return mode === "finish" ? keys[0] : keys[keys.length - 1];
14884
+ };
14885
+ const operationKeyFromEvent = (event, mode = "active") => {
14886
+ const explicit = explicitOperationKey(event);
14887
+ if (explicit && operations.has(explicit)) {
14888
+ return explicit;
14889
+ }
14890
+ if (isObject(event)) {
14891
+ const callId = event.callId;
14892
+ if (typeof callId === "string") {
14893
+ const operationKey = operationKeyForCallId(callId, mode);
14894
+ if (operationKey) {
14895
+ return operationKey;
14896
+ }
14897
+ const workflowOperationKey2 = workflowOperationKeyStore.getStore();
14898
+ if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
14899
+ return workflowOperationKey2;
14900
+ }
14901
+ return callId === "workflow-agent" ? void 0 : callId;
14902
+ }
14903
+ }
14904
+ const workflowOperationKey = workflowOperationKeyStore.getStore();
14905
+ if (workflowOperationKey && operations.has(workflowOperationKey)) {
14906
+ return workflowOperationKey;
14907
+ }
14908
+ const wrapperSpan = currentWorkflowAgentWrapperSpan();
14909
+ if (wrapperSpan?.spanId) {
14910
+ for (const [operationKey, state] of operations) {
14911
+ if (state.operationName === "WorkflowAgent.stream" && state.span.spanId === wrapperSpan.spanId) {
14912
+ return operationKey;
14913
+ }
14914
+ }
14915
+ }
14916
+ const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
14917
+ if (workflowAgentKeys?.length === 1) {
14918
+ return workflowAgentKeys[0];
14919
+ }
14920
+ if (operations.size === 1) {
14921
+ return operations.keys().next().value;
14922
+ }
14923
+ return void 0;
14924
+ };
14925
+ const closeOpenChildSpans = (operationKey, error) => {
14926
+ const openModelSpans = modelSpans.get(operationKey);
14927
+ if (openModelSpans) {
14928
+ for (const span of openModelSpans) {
14929
+ if (error !== void 0) {
14930
+ logError(span, error);
14931
+ }
14932
+ span.end();
14933
+ }
14934
+ modelSpans.delete(operationKey);
14935
+ }
14936
+ const openObjectSpan = objectSpans.get(operationKey);
14937
+ if (openObjectSpan) {
14938
+ if (error !== void 0) {
14939
+ logError(openObjectSpan, error);
14940
+ }
14941
+ openObjectSpan.end();
14942
+ objectSpans.delete(operationKey);
14943
+ }
14944
+ for (const [embedCallId, embedState] of embedSpans) {
14945
+ if (embedState.operationKey === operationKey) {
14946
+ if (error !== void 0) {
14947
+ logError(embedState.span, error);
14948
+ }
14949
+ embedState.span.end();
14950
+ embedSpans.delete(embedCallId);
14951
+ }
14952
+ }
14953
+ const openRerankSpan = rerankSpans.get(operationKey);
14954
+ if (openRerankSpan) {
14955
+ if (error !== void 0) {
14956
+ logError(openRerankSpan, error);
14957
+ }
14958
+ openRerankSpan.end();
14959
+ rerankSpans.delete(operationKey);
14960
+ }
14961
+ for (const [toolCallId, toolState] of toolSpans) {
14962
+ if (toolState.operationKey === operationKey) {
14963
+ if (error !== void 0) {
14964
+ logError(toolState.span, error);
14965
+ }
14966
+ toolState.span.end();
14967
+ toolSpans.delete(toolCallId);
14968
+ }
14969
+ }
14970
+ };
14971
+ const abortReasonFromEvent = (event) => {
14972
+ if (isObject(event)) {
14973
+ const abortEvent = event;
14974
+ if (abortEvent.error !== void 0) {
14975
+ return abortEvent.error;
14976
+ }
14977
+ if (abortEvent.reason !== void 0) {
14978
+ return abortEvent.reason;
14979
+ }
14980
+ }
14981
+ return new Error("AI SDK operation aborted");
14982
+ };
14983
+ const shouldSkipTelemetryChildren = (state) => state?.operationName === "WorkflowAgent.stream" && !state.ownsSpan;
14984
+ const onObjectStepEnd = (event) => {
14985
+ runSafely("onObjectStepEnd", () => {
14986
+ const operationKey = operationKeyFromEvent(event);
14987
+ const span = operationKey ? objectSpans.get(operationKey) : void 0;
14988
+ if (!operationKey || !span) {
14989
+ return;
14990
+ }
14991
+ const result = {
14992
+ ...event,
14993
+ text: event.objectText
14994
+ };
14995
+ span.log({
14996
+ ...shouldRecordOutputs(event) ? {
14997
+ output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
14998
+ } : {},
14999
+ metrics: extractTokenMetrics(result)
15000
+ });
15001
+ span.end();
15002
+ objectSpans.delete(operationKey);
15003
+ });
15004
+ };
15005
+ const onEmbedEnd = (event) => {
15006
+ runSafely("onEmbedEnd", () => {
15007
+ const state = embedSpans.get(event.embedCallId);
15008
+ if (!state) {
15009
+ return;
15010
+ }
15011
+ const result = {
15012
+ ...event,
15013
+ embeddings: event.embeddings
15014
+ };
15015
+ state.span.log({
15016
+ ...shouldRecordOutputs(event) ? {
15017
+ output: processAISDKEmbeddingOutput(
15018
+ result,
15019
+ DEFAULT_DENY_OUTPUT_PATHS
15020
+ )
15021
+ } : {},
15022
+ metrics: extractTokenMetrics(result)
15023
+ });
15024
+ state.span.end();
15025
+ embedSpans.delete(event.embedCallId);
15026
+ });
15027
+ };
15028
+ const onRerankEnd = (event) => {
15029
+ runSafely("onRerankEnd", () => {
15030
+ const operationKey = operationKeyFromEvent(event);
15031
+ const span = operationKey ? rerankSpans.get(operationKey) : void 0;
15032
+ if (!operationKey || !span) {
15033
+ return;
15034
+ }
15035
+ const result = {
15036
+ ranking: event.ranking?.map((entry) => ({
15037
+ originalIndex: entry.index,
15038
+ score: entry.relevanceScore
15039
+ }))
15040
+ };
15041
+ span.log({
15042
+ ...shouldRecordOutputs(event) ? {
15043
+ output: processAISDKRerankOutput(
15044
+ result,
15045
+ DEFAULT_DENY_OUTPUT_PATHS
15046
+ )
15047
+ } : {}
15048
+ });
15049
+ span.end();
15050
+ rerankSpans.delete(operationKey);
15051
+ });
15052
+ };
15053
+ const onEnd = (event) => {
15054
+ runSafely("onEnd", () => {
15055
+ const operationKey = operationKeyFromEvent(event, "finish");
15056
+ const state = operationKey ? operations.get(operationKey) : void 0;
15057
+ if (!state) {
15058
+ return;
15059
+ }
15060
+ if (!state.ownsSpan) {
15061
+ deleteOperation(state.operationKey);
15062
+ return;
15063
+ }
15064
+ const result = finishResult(event, state.operationName);
15065
+ const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
15066
+ const timeToFirstToken = state.operationName === "WorkflowAgent.stream" ? void 0 : extractTimeToFirstToken(result, state);
15067
+ if (timeToFirstToken !== void 0) {
15068
+ metrics.time_to_first_token = timeToFirstToken;
15069
+ }
15070
+ state.span.log({
15071
+ ...shouldRecordOutputs(event) ? {
15072
+ output: finishOutput(result, state.operationName)
15073
+ } : {},
15074
+ metrics
15075
+ });
15076
+ state.span.end();
15077
+ deleteOperation(state.operationKey);
15078
+ });
15079
+ };
13157
15080
  return {
13158
15081
  onStart(event) {
13159
15082
  runSafely("onStart", () => {
13160
15083
  const operationName = operationNameFromId(event.operationId);
13161
- const span = startSpan({
15084
+ const workflowAgent = operationName === "WorkflowAgent.stream";
15085
+ const wrapperSpan = workflowAgent ? currentWorkflowAgentWrapperSpan() : void 0;
15086
+ const ownsSpan = !wrapperSpan;
15087
+ const span = ownsSpan ? startSpan({
13162
15088
  name: operationName,
13163
15089
  spanAttributes: { type: "function" /* FUNCTION */ }
13164
- });
13165
- operations.set(event.callId, {
15090
+ }) : wrapperSpan;
15091
+ const operationKey = createOperationKey(event, operationName);
15092
+ registerOperation({
15093
+ callId: event.callId,
13166
15094
  hadModelChild: false,
15095
+ loggedInput: false,
13167
15096
  operationName,
15097
+ operationKey,
15098
+ ownsSpan,
13168
15099
  span,
13169
15100
  startTime: getCurrentUnixTimestamp()
13170
15101
  });
13171
- const metadata = metadataFromEvent(event);
15102
+ if (!ownsSpan) {
15103
+ return;
15104
+ }
15105
+ if (workflowAgent) {
15106
+ workflowOperationKeyStore.enterWith(operationKey);
15107
+ }
15108
+ let metadata = metadataFromEvent(event);
13172
15109
  const logPayload = { metadata };
15110
+ const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
15111
+ if (workflowAgentCallInput) {
15112
+ metadata = {
15113
+ ...metadata,
15114
+ ...extractWorkflowMetadataFromCallParams(workflowAgentCallInput)
15115
+ };
15116
+ logPayload.metadata = metadata;
15117
+ }
13173
15118
  if (shouldRecordInputs(event)) {
13174
- const { input, outputPromise } = processAISDKCallInput(
13175
- operationInput(event, operationName)
13176
- );
15119
+ const callInput = workflowAgentCallInput ?? operationInput(event, operationName);
15120
+ const { input, outputPromise } = workflowAgent ? processAISDKWorkflowAgentCallInput(callInput) : processAISDKCallInput(callInput);
13177
15121
  logPayload.input = input;
13178
- if (outputPromise && input && typeof input === "object") {
15122
+ const state = operations.get(operationKey);
15123
+ if (state) {
15124
+ state.loggedInput = hasPromptLikeInput(input);
15125
+ }
15126
+ if (outputPromise && !workflowAgent && input && typeof input === "object") {
13179
15127
  outputPromise.then((resolvedData) => {
13180
15128
  span.log({
13181
15129
  input: {
@@ -13192,41 +15140,67 @@ function braintrustAISDKTelemetry() {
13192
15140
  },
13193
15141
  onLanguageModelCallStart(event) {
13194
15142
  runSafely("onLanguageModelCallStart", () => {
13195
- const state = operations.get(event.callId);
13196
- const openSpans = modelSpans.get(event.callId);
13197
- if (openSpans) {
15143
+ const operationKey = operationKeyFromEvent(event);
15144
+ const state = operationKey ? operations.get(operationKey) : void 0;
15145
+ if (shouldSkipTelemetryChildren(state)) {
15146
+ return;
15147
+ }
15148
+ const operationName = state?.operationName ?? "generateText";
15149
+ const callInput = operationInput(event, operationName);
15150
+ const workflowAgent = operationName === "WorkflowAgent.stream";
15151
+ const processedInput = shouldRecordInputs(event) && workflowAgent ? processAISDKWorkflowAgentModelCallInput(callInput).input : shouldRecordInputs(event) ? processAISDKCallInput(callInput).input : void 0;
15152
+ if (workflowAgent && state?.ownsSpan && !state.loggedInput && hasPromptLikeInput(processedInput)) {
15153
+ state.span.log({
15154
+ input: processedInput,
15155
+ metadata: {
15156
+ ...metadataFromEvent(event),
15157
+ ...extractWorkflowMetadataFromCallParams(callInput)
15158
+ }
15159
+ });
15160
+ state.loggedInput = true;
15161
+ }
15162
+ const openSpans = operationKey ? modelSpans.get(operationKey) : void 0;
15163
+ if (operationKey && openSpans) {
13198
15164
  for (const span2 of openSpans) {
13199
15165
  span2.end();
13200
15166
  }
13201
- modelSpans.delete(event.callId);
15167
+ modelSpans.delete(operationKey);
13202
15168
  }
13203
15169
  const span = startChildSpan(
13204
- event.callId,
13205
- state?.operationName === "streamText" ? "doStream" : "doGenerate",
15170
+ operationKey ?? event.callId,
15171
+ operationName === "streamText" ? "doStream" : "doGenerate",
13206
15172
  "llm" /* LLM */,
13207
15173
  {
13208
15174
  ...shouldRecordInputs(event) ? {
13209
- input: processAISDKCallInput(
13210
- operationInput(
13211
- event,
13212
- state?.operationName ?? "generateText"
13213
- )
13214
- ).input
15175
+ input: processedInput
13215
15176
  } : {},
13216
- metadata: metadataFromEvent(event)
15177
+ metadata: workflowAgent ? {
15178
+ ...metadataFromEvent(event),
15179
+ ...extractWorkflowMetadataFromCallParams(callInput)
15180
+ } : metadataFromEvent(event)
13217
15181
  }
13218
15182
  );
13219
- const spans = modelSpans.get(event.callId) ?? [];
15183
+ const spanKey = operationKey ?? event.callId;
15184
+ const spans = modelSpans.get(spanKey) ?? [];
13220
15185
  spans.push(span);
13221
- modelSpans.set(event.callId, spans);
15186
+ modelSpans.set(spanKey, spans);
13222
15187
  });
13223
15188
  },
13224
15189
  onLanguageModelCallEnd(event) {
13225
15190
  runSafely("onLanguageModelCallEnd", () => {
13226
- const span = shiftModelSpan(modelSpans, event.callId);
15191
+ const operationKey = operationKeyFromEvent(event);
15192
+ const state = operationKey ? operations.get(operationKey) : void 0;
15193
+ if (shouldSkipTelemetryChildren(state)) {
15194
+ return;
15195
+ }
15196
+ const span = operationKey ? shiftModelSpan(modelSpans, operationKey) : void 0;
13227
15197
  if (!span) {
13228
15198
  return;
13229
15199
  }
15200
+ const timeToFirstOutputMs = safePerformance(event)?.timeToFirstOutputMs;
15201
+ if (state?.operationName === "streamText" && state.firstChunkTime === void 0 && typeof timeToFirstOutputMs === "number") {
15202
+ state.firstChunkTime = state.startTime + timeToFirstOutputMs / 1e3;
15203
+ }
13230
15204
  const result = {
13231
15205
  ...event,
13232
15206
  response: event.responseId ? { id: event.responseId } : void 0
@@ -13242,14 +15216,18 @@ function braintrustAISDKTelemetry() {
13242
15216
  },
13243
15217
  onObjectStepStart(event) {
13244
15218
  runSafely("onObjectStepStart", () => {
13245
- const state = operations.get(event.callId);
13246
- const openSpan = objectSpans.get(event.callId);
13247
- if (openSpan) {
15219
+ const operationKey = operationKeyFromEvent(event);
15220
+ const state = operationKey ? operations.get(operationKey) : void 0;
15221
+ if (shouldSkipTelemetryChildren(state)) {
15222
+ return;
15223
+ }
15224
+ const openSpan = operationKey ? objectSpans.get(operationKey) : void 0;
15225
+ if (operationKey && openSpan) {
13248
15226
  openSpan.end();
13249
- objectSpans.delete(event.callId);
15227
+ objectSpans.delete(operationKey);
13250
15228
  }
13251
15229
  const span = startChildSpan(
13252
- event.callId,
15230
+ operationKey ?? event.callId,
13253
15231
  state?.operationName === "streamObject" ? "doStream" : "doGenerate",
13254
15232
  "llm" /* LLM */,
13255
15233
  {
@@ -13261,40 +15239,25 @@ function braintrustAISDKTelemetry() {
13261
15239
  metadata: metadataFromEvent(event)
13262
15240
  }
13263
15241
  );
13264
- objectSpans.set(event.callId, span);
13265
- });
13266
- },
13267
- onObjectStepFinish(event) {
13268
- runSafely("onObjectStepFinish", () => {
13269
- const span = objectSpans.get(event.callId);
13270
- if (!span) {
13271
- return;
13272
- }
13273
- const result = {
13274
- ...event,
13275
- text: event.objectText
13276
- };
13277
- span.log({
13278
- ...shouldRecordOutputs(event) ? {
13279
- output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
13280
- } : {},
13281
- metrics: extractTokenMetrics(result)
13282
- });
13283
- span.end();
13284
- objectSpans.delete(event.callId);
15242
+ objectSpans.set(operationKey ?? event.callId, span);
13285
15243
  });
13286
15244
  },
15245
+ onObjectStepEnd,
13287
15246
  onEmbedStart(event) {
13288
15247
  runSafely("onEmbedStart", () => {
13289
- const state = operations.get(event.callId);
15248
+ const operationKey = operationKeyFromEvent(event);
15249
+ const state = operationKey ? operations.get(operationKey) : void 0;
15250
+ if (shouldSkipTelemetryChildren(state)) {
15251
+ return;
15252
+ }
13290
15253
  for (const [embedCallId, embedState] of embedSpans) {
13291
- if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
15254
+ if (embedState.operationKey === operationKey && (state?.operationName === "embed" || embedState.values === event.values)) {
13292
15255
  embedState.span.end();
13293
15256
  embedSpans.delete(embedCallId);
13294
15257
  }
13295
15258
  }
13296
15259
  const span = startChildSpan(
13297
- event.callId,
15260
+ operationKey ?? event.callId,
13298
15261
  "doEmbed",
13299
15262
  "llm" /* LLM */,
13300
15263
  {
@@ -13307,44 +15270,27 @@ function braintrustAISDKTelemetry() {
13307
15270
  }
13308
15271
  );
13309
15272
  embedSpans.set(event.embedCallId, {
13310
- callId: event.callId,
15273
+ operationKey: operationKey ?? event.callId,
13311
15274
  span,
13312
15275
  values: event.values
13313
15276
  });
13314
15277
  });
13315
15278
  },
13316
- onEmbedFinish(event) {
13317
- runSafely("onEmbedFinish", () => {
13318
- const state = embedSpans.get(event.embedCallId);
13319
- if (!state) {
13320
- return;
13321
- }
13322
- const result = {
13323
- ...event,
13324
- embeddings: event.embeddings
13325
- };
13326
- state.span.log({
13327
- ...shouldRecordOutputs(event) ? {
13328
- output: processAISDKEmbeddingOutput(
13329
- result,
13330
- DEFAULT_DENY_OUTPUT_PATHS
13331
- )
13332
- } : {},
13333
- metrics: extractTokenMetrics(result)
13334
- });
13335
- state.span.end();
13336
- embedSpans.delete(event.embedCallId);
13337
- });
13338
- },
15279
+ onEmbedEnd,
13339
15280
  onRerankStart(event) {
13340
15281
  runSafely("onRerankStart", () => {
13341
- const openSpan = rerankSpans.get(event.callId);
13342
- if (openSpan) {
15282
+ const operationKey = operationKeyFromEvent(event);
15283
+ const state = operationKey ? operations.get(operationKey) : void 0;
15284
+ if (shouldSkipTelemetryChildren(state)) {
15285
+ return;
15286
+ }
15287
+ const openSpan = operationKey ? rerankSpans.get(operationKey) : void 0;
15288
+ if (operationKey && openSpan) {
13343
15289
  openSpan.end();
13344
- rerankSpans.delete(event.callId);
15290
+ rerankSpans.delete(operationKey);
13345
15291
  }
13346
15292
  const span = startChildSpan(
13347
- event.callId,
15293
+ operationKey ?? event.callId,
13348
15294
  "doRerank",
13349
15295
  "llm" /* LLM */,
13350
15296
  {
@@ -13358,41 +15304,23 @@ function braintrustAISDKTelemetry() {
13358
15304
  metadata: metadataFromEvent(event)
13359
15305
  }
13360
15306
  );
13361
- rerankSpans.set(event.callId, span);
13362
- });
13363
- },
13364
- onRerankFinish(event) {
13365
- runSafely("onRerankFinish", () => {
13366
- const span = rerankSpans.get(event.callId);
13367
- if (!span) {
13368
- return;
13369
- }
13370
- const result = {
13371
- ranking: event.ranking?.map((entry) => ({
13372
- originalIndex: entry.index,
13373
- score: entry.relevanceScore
13374
- }))
13375
- };
13376
- span.log({
13377
- ...shouldRecordOutputs(event) ? {
13378
- output: processAISDKRerankOutput(
13379
- result,
13380
- DEFAULT_DENY_OUTPUT_PATHS
13381
- )
13382
- } : {}
13383
- });
13384
- span.end();
13385
- rerankSpans.delete(event.callId);
15307
+ rerankSpans.set(operationKey ?? event.callId, span);
13386
15308
  });
13387
15309
  },
15310
+ onRerankEnd,
13388
15311
  onToolExecutionStart(event) {
13389
15312
  runSafely("onToolExecutionStart", () => {
15313
+ const operationKey = operationKeyFromEvent(event);
15314
+ const state = operationKey ? operations.get(operationKey) : void 0;
15315
+ if (shouldSkipTelemetryChildren(state)) {
15316
+ return;
15317
+ }
13390
15318
  const toolCallId = event.toolCall.toolCallId;
13391
- if (!toolCallId) {
15319
+ if (!operationKey || !toolCallId) {
13392
15320
  return;
13393
15321
  }
13394
15322
  const span = startChildSpan(
13395
- event.callId,
15323
+ operationKey,
13396
15324
  event.toolCall.toolName || "tool",
13397
15325
  "tool" /* TOOL */,
13398
15326
  {
@@ -13406,7 +15334,7 @@ function braintrustAISDKTelemetry() {
13406
15334
  }
13407
15335
  }
13408
15336
  );
13409
- toolSpans.set(toolCallId, { callId: event.callId, span });
15337
+ toolSpans.set(toolCallId, { operationKey, span });
13410
15338
  });
13411
15339
  },
13412
15340
  onToolExecutionEnd(event) {
@@ -13417,14 +15345,17 @@ function braintrustAISDKTelemetry() {
13417
15345
  return;
13418
15346
  }
13419
15347
  const toolOutput = event.toolOutput;
13420
- if (toolOutput?.type === "tool-error") {
15348
+ const workflowToolError = event.success === false && "error" in event ? event.error : void 0;
15349
+ if (toolOutput?.type === "tool-error" || workflowToolError !== void 0) {
15350
+ const error = toolOutput?.error ?? workflowToolError;
13421
15351
  state.span.log({
13422
- error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
15352
+ error: error instanceof Error ? error.message : String(error),
13423
15353
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
13424
15354
  });
13425
15355
  } else {
15356
+ const output = toolOutput && "output" in toolOutput ? toolOutput.output : event.output;
13426
15357
  state.span.log({
13427
- ...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
15358
+ ...shouldRecordOutputs(event) ? { output } : {},
13428
15359
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
13429
15360
  });
13430
15361
  }
@@ -13438,83 +15369,46 @@ function braintrustAISDKTelemetry() {
13438
15369
  if (!callId) {
13439
15370
  return;
13440
15371
  }
13441
- const state = operations.get(callId);
15372
+ const operationKey = operationKeyForCallId(callId);
15373
+ const state = operationKey ? operations.get(operationKey) : void 0;
13442
15374
  if (!state || state.firstChunkTime !== void 0) {
13443
15375
  return;
13444
15376
  }
13445
15377
  state.firstChunkTime = getCurrentUnixTimestamp();
13446
15378
  });
13447
15379
  },
13448
- onFinish(event) {
13449
- runSafely("onFinish", () => {
13450
- const state = operations.get(event.callId);
13451
- if (!state) {
15380
+ onEnd,
15381
+ onAbort(event) {
15382
+ runSafely("onAbort", () => {
15383
+ const operationKey = operationKeyFromEvent(event, "finish");
15384
+ const state = operationKey ? operations.get(operationKey) : void 0;
15385
+ if (!operationKey || !state) {
13452
15386
  return;
13453
15387
  }
13454
- const result = finishResult(event, state.operationName);
13455
- const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
13456
- if (state.firstChunkTime !== void 0) {
13457
- metrics.time_to_first_token = state.firstChunkTime - state.startTime;
15388
+ const error = abortReasonFromEvent(event);
15389
+ closeOpenChildSpans(operationKey, error);
15390
+ if (state.ownsSpan) {
15391
+ logError(state.span, error);
15392
+ state.span.end();
13458
15393
  }
13459
- state.span.log({
13460
- ...shouldRecordOutputs(event) ? {
13461
- output: finishOutput(result, state.operationName)
13462
- } : {},
13463
- metrics
13464
- });
13465
- state.span.end();
13466
- operations.delete(event.callId);
15394
+ deleteOperation(operationKey);
13467
15395
  });
13468
15396
  },
13469
15397
  onError(event) {
13470
15398
  runSafely("onError", () => {
13471
15399
  const errorEvent = isObject(event) ? event : {};
13472
- const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
13473
- if (!callId) {
13474
- return;
13475
- }
13476
- const state = operations.get(callId);
13477
- if (!state) {
15400
+ const operationKey = operationKeyFromEvent(errorEvent, "finish");
15401
+ const state = operationKey ? operations.get(operationKey) : void 0;
15402
+ if (!operationKey || !state) {
13478
15403
  return;
13479
15404
  }
13480
15405
  const error = errorEvent.error ?? event;
13481
- const openModelSpans = modelSpans.get(callId);
13482
- if (openModelSpans) {
13483
- for (const span of openModelSpans) {
13484
- logError(span, error);
13485
- span.end();
13486
- }
13487
- modelSpans.delete(callId);
13488
- }
13489
- const openObjectSpan = objectSpans.get(callId);
13490
- if (openObjectSpan) {
13491
- logError(openObjectSpan, error);
13492
- openObjectSpan.end();
13493
- objectSpans.delete(callId);
13494
- }
13495
- for (const [embedCallId, embedState] of embedSpans) {
13496
- if (embedState.callId === callId) {
13497
- logError(embedState.span, error);
13498
- embedState.span.end();
13499
- embedSpans.delete(embedCallId);
13500
- }
13501
- }
13502
- const openRerankSpan = rerankSpans.get(callId);
13503
- if (openRerankSpan) {
13504
- logError(openRerankSpan, error);
13505
- openRerankSpan.end();
13506
- rerankSpans.delete(callId);
13507
- }
13508
- for (const [toolCallId, toolState] of toolSpans) {
13509
- if (toolState.callId === callId) {
13510
- logError(toolState.span, error);
13511
- toolState.span.end();
13512
- toolSpans.delete(toolCallId);
13513
- }
15406
+ closeOpenChildSpans(operationKey, error);
15407
+ if (state.ownsSpan) {
15408
+ logError(state.span, error);
15409
+ state.span.end();
13514
15410
  }
13515
- logError(state.span, error);
13516
- state.span.end();
13517
- operations.delete(callId);
15411
+ deleteOperation(operationKey);
13518
15412
  });
13519
15413
  },
13520
15414
  executeTool({ toolCallId, execute }) {
@@ -13529,7 +15423,16 @@ function shouldRecordInputs(event) {
13529
15423
  function shouldRecordOutputs(event) {
13530
15424
  return event.recordOutputs !== false;
13531
15425
  }
15426
+ function hasPromptLikeInput(input) {
15427
+ if (!isObject(input)) {
15428
+ return false;
15429
+ }
15430
+ return input.prompt !== void 0 || input.messages !== void 0;
15431
+ }
13532
15432
  function operationNameFromId(operationId) {
15433
+ if (operationId === "ai.workflowAgent.stream") {
15434
+ return "WorkflowAgent.stream";
15435
+ }
13533
15436
  return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
13534
15437
  }
13535
15438
  function modelFromEvent(event) {
@@ -13575,6 +15478,7 @@ function operationInput(event, operationName) {
13575
15478
  }
13576
15479
  return {
13577
15480
  model: modelFromEvent(event),
15481
+ instructions: event.instructions,
13578
15482
  system: event.system,
13579
15483
  prompt: event.prompt,
13580
15484
  messages: event.messages,
@@ -13623,6 +15527,30 @@ function finishResult(event, operationName) {
13623
15527
  }
13624
15528
  return event;
13625
15529
  }
15530
+ function extractTimeToFirstToken(result, state) {
15531
+ if (state.firstChunkTime !== void 0) {
15532
+ return state.firstChunkTime - state.startTime;
15533
+ }
15534
+ const performanceCandidates = [
15535
+ safePerformance(result),
15536
+ safePerformance(result.finalStep),
15537
+ ...Array.isArray(result.steps) ? (result.steps ?? []).map(safePerformance) : []
15538
+ ];
15539
+ for (const performance of performanceCandidates) {
15540
+ const timeToFirstOutputMs = performance?.timeToFirstOutputMs;
15541
+ if (typeof timeToFirstOutputMs === "number") {
15542
+ return timeToFirstOutputMs / 1e3;
15543
+ }
15544
+ }
15545
+ return void 0;
15546
+ }
15547
+ function safePerformance(value) {
15548
+ if (!isObject(value)) {
15549
+ return void 0;
15550
+ }
15551
+ const performance = value.performance;
15552
+ return isObject(performance) ? performance : void 0;
15553
+ }
13626
15554
  function finishOutput(result, operationName) {
13627
15555
  if (operationName === "embed" || operationName === "embedMany") {
13628
15556
  return processAISDKEmbeddingOutput(
@@ -28707,7 +30635,13 @@ var BraintrustObservabilityExporter = class {
28707
30635
  const args = {
28708
30636
  name: exported.name,
28709
30637
  spanAttributes: { type: spanTypeFor(exported.type) },
28710
- startTime: epochSeconds(exported.startTime)
30638
+ startTime: epochSeconds(exported.startTime),
30639
+ // Use the Mastra span id as the Braintrust row id so that
30640
+ // `logFeedback({ id: <mastra span id> })` (and Mastra's score events)
30641
+ // attach to the right row. Without this, `SpanImpl` auto-generates a
30642
+ // row id (`this._id = eventId ?? idGenerator.getSpanId()`) that no
30643
+ // external caller could know.
30644
+ event: { id: exported.id }
28711
30645
  };
28712
30646
  const parentRecord = exported.parentSpanId ? this.spans.get(exported.parentSpanId) : void 0;
28713
30647
  if (!this.capturedParent) {
@@ -29136,12 +31070,17 @@ export {
29136
31070
  debugLogger,
29137
31071
  IDGenerator,
29138
31072
  UUIDGenerator,
31073
+ OTELIDGenerator,
29139
31074
  getIdGenerator,
31075
+ TRACEPARENT_HEADER,
31076
+ TRACESTATE_HEADER,
31077
+ BAGGAGE_HEADER,
31078
+ BRAINTRUST_PARENT_KEY,
29140
31079
  spanObjectTypeV3ToTypedString,
29141
- SpanComponentsV3,
29142
31080
  isObject,
29143
31081
  mergeDicts,
29144
31082
  slugify,
31083
+ SpanComponentsV4,
29145
31084
  makeScorerPropagatedEvent,
29146
31085
  loadPrettyXact,
29147
31086
  getCurrentUnixTimestamp,
@@ -29169,6 +31108,7 @@ export {
29169
31108
  BraintrustStream,
29170
31109
  createFinalValuePassThroughStream,
29171
31110
  devNullWritableStream,
31111
+ LRUCache,
29172
31112
  LOGS3_OVERFLOW_REFERENCE_TYPE,
29173
31113
  DEFAULT_MAX_REQUEST_SIZE,
29174
31114
  LoginInvalidOrgError,
@@ -29197,7 +31137,7 @@ export {
29197
31137
  constructLogs3OverflowRequest,
29198
31138
  pickLogs3OverflowObjectIds,
29199
31139
  uploadLogs3OverflowPayload,
29200
- utf8ByteLength,
31140
+ utf8ByteLength2 as utf8ByteLength,
29201
31141
  TestBackgroundLogger,
29202
31142
  init,
29203
31143
  initExperiment,
@@ -29217,11 +31157,14 @@ export {
29217
31157
  currentLogger,
29218
31158
  currentSpan,
29219
31159
  getSpanParentObject,
31160
+ injectTraceContext,
31161
+ extractTraceContextFromHeaders,
29220
31162
  logError,
29221
31163
  traced,
29222
31164
  wrapTraced,
29223
31165
  traceable,
29224
31166
  startSpan,
31167
+ _internalStartSpanWithInitialMerge,
29225
31168
  flush,
29226
31169
  setFetch,
29227
31170
  withCurrent,
@@ -29249,6 +31192,7 @@ export {
29249
31192
  finalizeAnthropicTokens,
29250
31193
  extractAnthropicCacheTokens,
29251
31194
  zodToJsonSchema,
31195
+ currentWorkflowAgentWrapperSpan,
29252
31196
  braintrustAISDKTelemetry,
29253
31197
  CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION,
29254
31198
  wrapLocalClaudeToolHandler,