braintrust 3.28.0 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +1 -1
  2. package/dev/dist/index.d.mts +356 -7
  3. package/dev/dist/index.d.ts +356 -7
  4. package/dev/dist/index.js +1815 -1548
  5. package/dev/dist/index.mjs +1054 -787
  6. package/dist/apply-auto-instrumentation.js +297 -264
  7. package/dist/apply-auto-instrumentation.mjs +84 -51
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +43 -5
  9. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  10. package/dist/auto-instrumentations/bundler/next.cjs +43 -5
  11. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  12. package/dist/auto-instrumentations/bundler/rollup.cjs +43 -5
  13. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.cjs +43 -5
  15. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  16. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +43 -5
  17. package/dist/auto-instrumentations/bundler/webpack.cjs +43 -5
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  19. package/dist/auto-instrumentations/{chunk-NP7V4XB2.mjs → chunk-AOIYCVEL.mjs} +32 -2
  20. package/dist/auto-instrumentations/{chunk-26PKVUKB.mjs → chunk-DKTGDNA7.mjs} +12 -4
  21. package/dist/auto-instrumentations/{chunk-HD35AM3M.mjs → chunk-OMCZ3MV2.mjs} +1 -1
  22. package/dist/auto-instrumentations/hook.mjs +952 -133
  23. package/dist/auto-instrumentations/index.cjs +32 -2
  24. package/dist/auto-instrumentations/index.mjs +1 -1
  25. package/dist/browser.d.mts +760 -22
  26. package/dist/browser.d.ts +760 -22
  27. package/dist/browser.js +1661 -848
  28. package/dist/browser.mjs +1661 -848
  29. package/dist/{chunk-BBE7SNRV.js → chunk-6Z5S7VOU.js} +143 -23
  30. package/dist/{chunk-ZHUHZWFY.mjs → chunk-7FA6VP2S.mjs} +140 -20
  31. package/dist/{chunk-UPFNQCGB.mjs → chunk-M6XPNJC4.mjs} +1144 -931
  32. package/dist/{chunk-OBBWQW6K.js → chunk-XLLGRXGR.js} +2335 -2122
  33. package/dist/cli.js +5134 -1090
  34. package/dist/edge-light.js +1661 -848
  35. package/dist/edge-light.mjs +1661 -848
  36. package/dist/index.d.mts +760 -22
  37. package/dist/index.d.ts +760 -22
  38. package/dist/index.js +1054 -567
  39. package/dist/index.mjs +514 -27
  40. package/dist/instrumentation/index.d.mts +548 -9
  41. package/dist/instrumentation/index.d.ts +548 -9
  42. package/dist/instrumentation/index.js +1975 -765
  43. package/dist/instrumentation/index.mjs +1975 -765
  44. package/dist/vitest-evals-reporter.js +16 -16
  45. package/dist/vitest-evals-reporter.mjs +2 -2
  46. package/dist/workerd.js +1661 -848
  47. package/dist/workerd.mjs +1661 -848
  48. package/package.json +1 -1
  49. package/util/dist/index.d.mts +42 -0
  50. package/util/dist/index.d.ts +42 -0
package/dist/browser.js CHANGED
@@ -869,8 +869,6 @@ function newGlobalTracingChannel(nameOrChannels) {
869
869
  var DefaultAsyncLocalStorage = class {
870
870
  constructor() {
871
871
  }
872
- enterWith(_) {
873
- }
874
872
  run(_, callback) {
875
873
  return callback();
876
874
  }
@@ -2687,7 +2685,9 @@ var AclObjectType = import_v36.z.union([
2687
2685
  "project_log",
2688
2686
  "org_project",
2689
2687
  "org_audit_logs",
2690
- "project_group"
2688
+ "project_group",
2689
+ "ai_secret",
2690
+ "org_ai_secret"
2691
2691
  ]),
2692
2692
  import_v36.z.null()
2693
2693
  ]);
@@ -3520,7 +3520,7 @@ var PromptParserNullish = import_v36.z.union([
3520
3520
  }),
3521
3521
  import_v36.z.null()
3522
3522
  ]);
3523
- var PreprocessorSavedFunctionId = import_v36.z.union([
3523
+ var PreprocessorId = import_v36.z.union([
3524
3524
  import_v36.z.object({
3525
3525
  type: import_v36.z.literal("function"),
3526
3526
  id: import_v36.z.string(),
@@ -3531,6 +3531,7 @@ var PreprocessorSavedFunctionId = import_v36.z.union([
3531
3531
  name: import_v36.z.string(),
3532
3532
  function_type: import_v36.z.literal("preprocessor").optional().default("preprocessor")
3533
3533
  }),
3534
+ import_v36.z.object({ type: import_v36.z.literal("inline"), code: import_v36.z.string().min(1) }),
3534
3535
  import_v36.z.null()
3535
3536
  ]);
3536
3537
  var PromptDataNullish = import_v36.z.union([
@@ -3538,7 +3539,7 @@ var PromptDataNullish = import_v36.z.union([
3538
3539
  prompt: PromptBlockDataNullish,
3539
3540
  options: PromptOptionsNullish,
3540
3541
  parser: PromptParserNullish,
3541
- preprocessor: PreprocessorSavedFunctionId,
3542
+ preprocessor: PreprocessorId,
3542
3543
  tool_functions: import_v36.z.union([import_v36.z.array(SavedFunctionId), import_v36.z.null()]),
3543
3544
  template_format: import_v36.z.union([
3544
3545
  import_v36.z.enum(["mustache", "nunjucks", "none"]),
@@ -3740,7 +3741,7 @@ var PromptData = import_v36.z.object({
3740
3741
  prompt: PromptBlockDataNullish,
3741
3742
  options: PromptOptionsNullish,
3742
3743
  parser: PromptParserNullish,
3743
- preprocessor: PreprocessorSavedFunctionId,
3744
+ preprocessor: PreprocessorId,
3744
3745
  tool_functions: import_v36.z.union([import_v36.z.array(SavedFunctionId), import_v36.z.null()]),
3745
3746
  template_format: import_v36.z.union([
3746
3747
  import_v36.z.enum(["mustache", "nunjucks", "none"]),
@@ -4684,6 +4685,7 @@ var View = import_v36.z.object({
4684
4685
  ]),
4685
4686
  name: import_v36.z.string(),
4686
4687
  description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4688
+ starred: import_v36.z.boolean().optional(),
4687
4689
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4688
4690
  updated_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4689
4691
  view_data: ViewData.optional(),
@@ -5385,44 +5387,72 @@ function createCacheLayers({
5385
5387
  }
5386
5388
 
5387
5389
  // src/prompt-cache/prompt-cache.ts
5388
- function createCacheKey(key) {
5390
+ function createCacheKey(key, namespace) {
5391
+ let cacheKey;
5389
5392
  if (key.id) {
5390
- return `id:${key.id}`;
5391
- }
5392
- const prefix = key.projectId ?? key.projectName;
5393
- if (!prefix) {
5394
- throw new Error("Either projectId or projectName must be provided");
5395
- }
5396
- if (!key.slug) {
5397
- throw new Error("Slug must be provided when not using ID");
5393
+ cacheKey = `id:${key.id}`;
5394
+ } else {
5395
+ const prefix = key.projectId ?? key.projectName;
5396
+ if (!prefix) {
5397
+ throw new Error("Either projectId or projectName must be provided");
5398
+ }
5399
+ if (!key.slug) {
5400
+ throw new Error("Slug must be provided when not using ID");
5401
+ }
5402
+ cacheKey = `${prefix}:${key.slug}:${key.version ?? "latest"}`;
5398
5403
  }
5399
- return `${prefix}:${key.slug}:${key.version ?? "latest"}`;
5404
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
5400
5405
  }
5401
- var PromptCache = class {
5406
+ var PromptCache = class _PromptCache {
5402
5407
  memoryCache;
5403
5408
  diskCache;
5409
+ namespace;
5410
+ expectedResolvedOrgIdentity;
5404
5411
  constructor(options) {
5405
5412
  this.memoryCache = options.memoryCache;
5406
5413
  this.diskCache = options.diskCache;
5414
+ this.namespace = options.namespace;
5415
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
5416
+ }
5417
+ /**
5418
+ * Returns a cache view that shares the same storage layers but isolates all
5419
+ * entries under the provided namespace.
5420
+ */
5421
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
5422
+ return new _PromptCache({
5423
+ memoryCache: this.memoryCache,
5424
+ diskCache: this.diskCache,
5425
+ namespace,
5426
+ expectedResolvedOrgIdentity
5427
+ });
5407
5428
  }
5408
5429
  /**
5409
5430
  * Retrieves a prompt from the cache.
5410
5431
  * First checks the in-memory LRU cache, then falls back to checking the disk cache if available.
5411
5432
  */
5412
5433
  async get(key) {
5413
- const cacheKey = createCacheKey(key);
5434
+ const cacheKey = createCacheKey(key, this.namespace);
5414
5435
  if (this.memoryCache) {
5415
- const memoryPrompt = this.memoryCache.get(cacheKey);
5416
- if (memoryPrompt !== void 0) {
5417
- return memoryPrompt;
5436
+ const memoryEntry = this.memoryCache.get(cacheKey);
5437
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
5438
+ return memoryEntry.value;
5418
5439
  }
5419
5440
  }
5420
5441
  if (this.diskCache) {
5421
- const diskPrompt = await this.diskCache.get(cacheKey);
5422
- if (!diskPrompt) {
5442
+ const diskEntry = await this.diskCache.get(cacheKey);
5443
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
5423
5444
  return void 0;
5424
5445
  }
5425
- this.memoryCache?.set(cacheKey, diskPrompt);
5446
+ const serializedPrompt = diskEntry.value;
5447
+ const diskPrompt = new Prompt2(
5448
+ serializedPrompt.metadata,
5449
+ serializedPrompt.defaults,
5450
+ serializedPrompt.noTrace
5451
+ );
5452
+ this.memoryCache?.set(cacheKey, {
5453
+ value: diskPrompt,
5454
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
5455
+ });
5426
5456
  return diskPrompt;
5427
5457
  }
5428
5458
  return void 0;
@@ -5436,58 +5466,91 @@ var PromptCache = class {
5436
5466
  * @throws If there is an error writing to the disk cache.
5437
5467
  */
5438
5468
  async set(key, value) {
5439
- const cacheKey = createCacheKey(key);
5440
- this.memoryCache?.set(cacheKey, value);
5469
+ const cacheKey = createCacheKey(key, this.namespace);
5470
+ const memoryEntry = {
5471
+ value,
5472
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5473
+ };
5474
+ this.memoryCache?.set(cacheKey, memoryEntry);
5441
5475
  if (this.diskCache) {
5442
- await this.diskCache.set(cacheKey, value);
5476
+ await this.diskCache.set(cacheKey, {
5477
+ value: value._internalSerializeForCache(),
5478
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5479
+ });
5443
5480
  }
5444
5481
  }
5445
5482
  };
5446
5483
 
5447
5484
  // src/prompt-cache/parameters-cache.ts
5448
- function createCacheKey2(key) {
5485
+ function createCacheKey2(key, namespace) {
5486
+ let cacheKey;
5449
5487
  if (key.id) {
5450
- return `parameters:id:${key.id}`;
5451
- }
5452
- const prefix = key.projectId ?? key.projectName;
5453
- if (!prefix) {
5454
- throw new Error("Either projectId or projectName must be provided");
5455
- }
5456
- if (!key.slug) {
5457
- throw new Error("Slug must be provided when not using ID");
5488
+ cacheKey = `parameters:id:${key.id}`;
5489
+ } else {
5490
+ const prefix = key.projectId ?? key.projectName;
5491
+ if (!prefix) {
5492
+ throw new Error("Either projectId or projectName must be provided");
5493
+ }
5494
+ if (!key.slug) {
5495
+ throw new Error("Slug must be provided when not using ID");
5496
+ }
5497
+ cacheKey = `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
5458
5498
  }
5459
- return `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
5499
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
5460
5500
  }
5461
- var ParametersCache = class {
5501
+ var ParametersCache = class _ParametersCache {
5462
5502
  memoryCache;
5463
5503
  diskCache;
5504
+ namespace;
5505
+ expectedResolvedOrgIdentity;
5464
5506
  constructor(options) {
5465
5507
  this.memoryCache = options.memoryCache;
5466
5508
  this.diskCache = options.diskCache;
5509
+ this.namespace = options.namespace;
5510
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
5511
+ }
5512
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
5513
+ return new _ParametersCache({
5514
+ memoryCache: this.memoryCache,
5515
+ diskCache: this.diskCache,
5516
+ namespace,
5517
+ expectedResolvedOrgIdentity
5518
+ });
5467
5519
  }
5468
5520
  async get(key) {
5469
- const cacheKey = createCacheKey2(key);
5521
+ const cacheKey = createCacheKey2(key, this.namespace);
5470
5522
  if (this.memoryCache) {
5471
- const memoryParams = this.memoryCache.get(cacheKey);
5472
- if (memoryParams !== void 0) {
5473
- return memoryParams;
5523
+ const memoryEntry = this.memoryCache.get(cacheKey);
5524
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
5525
+ return memoryEntry.value;
5474
5526
  }
5475
5527
  }
5476
5528
  if (this.diskCache) {
5477
- const diskParams = await this.diskCache.get(cacheKey);
5478
- if (!diskParams) {
5529
+ const diskEntry = await this.diskCache.get(cacheKey);
5530
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
5479
5531
  return void 0;
5480
5532
  }
5481
- this.memoryCache?.set(cacheKey, diskParams);
5482
- return diskParams;
5533
+ const diskParameters = new RemoteEvalParameters(diskEntry.value.metadata);
5534
+ this.memoryCache?.set(cacheKey, {
5535
+ value: diskParameters,
5536
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
5537
+ });
5538
+ return diskParameters;
5483
5539
  }
5484
5540
  return void 0;
5485
5541
  }
5486
5542
  async set(key, value) {
5487
- const cacheKey = createCacheKey2(key);
5488
- this.memoryCache?.set(cacheKey, value);
5543
+ const cacheKey = createCacheKey2(key, this.namespace);
5544
+ const memoryEntry = {
5545
+ value,
5546
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5547
+ };
5548
+ this.memoryCache?.set(cacheKey, memoryEntry);
5489
5549
  if (this.diskCache) {
5490
- await this.diskCache.set(cacheKey, value);
5550
+ await this.diskCache.set(cacheKey, {
5551
+ value: value._internalSerializeForCache(),
5552
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5553
+ });
5491
5554
  }
5492
5555
  }
5493
5556
  };
@@ -5791,6 +5854,7 @@ var INSTRUMENTATION_NAMES = {
5791
5854
  CLOUDFLARE_THINK: "cloudflare-think",
5792
5855
  COHERE: "cohere",
5793
5856
  CURSOR_SDK: "cursor-sdk",
5857
+ DEEPSEEK_HARNESS: "deepseek-harness",
5794
5858
  EVE: "eve",
5795
5859
  FLUE: "flue",
5796
5860
  GENKIT: "genkit",
@@ -5816,7 +5880,7 @@ var INSTRUMENTATION_NAMES = {
5816
5880
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5817
5881
  "braintrust.spanInstrumentationName"
5818
5882
  );
5819
- var SDK_VERSION = true ? "3.28.0" : "0.0.0";
5883
+ var SDK_VERSION = true ? "3.29.0" : "0.0.0";
5820
5884
  function withSpanInstrumentationName(args, instrumentationName) {
5821
5885
  return {
5822
5886
  ...args,
@@ -5935,6 +5999,16 @@ var datasetSnapshotRegisterResponseSchema = import_v38.z.object({
5935
5999
  dataset_snapshot: DatasetSnapshot,
5936
6000
  found_existing: import_v38.z.boolean().optional()
5937
6001
  });
6002
+ var datasetObjectInfoSchema = import_v38.z.object({
6003
+ object_id: import_v38.z.string(),
6004
+ object_name: import_v38.z.string(),
6005
+ parent_cols: import_v38.z.object({
6006
+ project: import_v38.z.object({
6007
+ id: import_v38.z.string(),
6008
+ name: import_v38.z.string()
6009
+ })
6010
+ })
6011
+ });
5938
6012
  var datasetRestorePreviewResultSchema = import_v38.z.object({
5939
6013
  rows_to_restore: import_v38.z.number(),
5940
6014
  rows_to_delete: import_v38.z.number()
@@ -6148,12 +6222,53 @@ var loginSchema = import_v38.z.strictObject({
6148
6222
  });
6149
6223
  var stateNonce = 0;
6150
6224
  var V1_PROXY_SUFFIX = "/v1/proxy";
6225
+ var LOADER_LOGIN_CACHE_MAX = 16;
6151
6226
  function normalizeProxyConnUrl(proxyUrl) {
6152
6227
  return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
6153
6228
  }
6154
6229
  var BraintrustState = class _BraintrustState {
6230
+ id;
6231
+ currentExperiment;
6232
+ // Note: the value of IsAsyncFlush doesn't really matter here, since we
6233
+ // (safely) dynamically cast it whenever retrieving the logger.
6234
+ currentLogger;
6235
+ currentParent;
6236
+ currentSpan;
6237
+ // Any time we re-log in, we directly update the apiConn inside the logger.
6238
+ // This is preferable to replacing the whole logger, which would create the
6239
+ // possibility of multiple loggers floating around, which may not log in a
6240
+ // deterministic order.
6241
+ _bgLogger;
6242
+ _overrideBgLogger = null;
6243
+ appUrl = null;
6244
+ appPublicUrl = null;
6245
+ loginToken = null;
6246
+ orgId = null;
6247
+ orgName = null;
6248
+ apiUrl = null;
6249
+ proxyUrl = null;
6250
+ loggedIn = false;
6251
+ gitMetadataSettings;
6252
+ debugLogLevel;
6253
+ debugLogLevelConfigured = false;
6254
+ fetch = globalThis.fetch;
6255
+ _appConn = null;
6256
+ _apiConn = null;
6257
+ _proxyConn = null;
6258
+ promptCache;
6259
+ parametersCache;
6260
+ spanCache;
6261
+ _idGenerator = null;
6262
+ _contextManager = null;
6263
+ _otelFlushCallback = null;
6264
+ spanOriginEnvironment;
6265
+ traceContextSigningSecret;
6266
+ loaderLoginCache = /* @__PURE__ */ new WeakMap();
6267
+ loginParams;
6268
+ activeLoginOrgNameSelector;
6155
6269
  constructor(loginParams) {
6156
- this.loginParams = loginParams;
6270
+ this.loginParams = { ...loginParams };
6271
+ this.activeLoginOrgNameSelector = loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
6157
6272
  this.id = `${(/* @__PURE__ */ new Date()).toLocaleString()}-${stateNonce++}`;
6158
6273
  this.currentExperiment = void 0;
6159
6274
  this.currentLogger = void 0;
@@ -6190,12 +6305,14 @@ var BraintrustState = class _BraintrustState {
6190
6305
  const {
6191
6306
  memoryCache: parametersMemoryCache,
6192
6307
  diskCache: parametersDiskCache
6193
- } = createCacheLayers({
6194
- memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
6195
- diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
6196
- diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
6197
- getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
6198
- });
6308
+ } = createCacheLayers(
6309
+ {
6310
+ memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
6311
+ diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
6312
+ diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
6313
+ getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
6314
+ }
6315
+ );
6199
6316
  this.parametersCache = new ParametersCache({
6200
6317
  memoryCache: parametersMemoryCache,
6201
6318
  diskCache: parametersDiskCache
@@ -6204,43 +6321,6 @@ var BraintrustState = class _BraintrustState {
6204
6321
  this.spanOriginEnvironment = detectSpanOriginEnvironment();
6205
6322
  this._internalSetTraceContextSigningSecret(loginParams.apiKey);
6206
6323
  }
6207
- loginParams;
6208
- id;
6209
- currentExperiment;
6210
- // Note: the value of IsAsyncFlush doesn't really matter here, since we
6211
- // (safely) dynamically cast it whenever retrieving the logger.
6212
- currentLogger;
6213
- currentParent;
6214
- currentSpan;
6215
- // Any time we re-log in, we directly update the apiConn inside the logger.
6216
- // This is preferable to replacing the whole logger, which would create the
6217
- // possibility of multiple loggers floating around, which may not log in a
6218
- // deterministic order.
6219
- _bgLogger;
6220
- _overrideBgLogger = null;
6221
- appUrl = null;
6222
- appPublicUrl = null;
6223
- loginToken = null;
6224
- orgId = null;
6225
- orgName = null;
6226
- apiUrl = null;
6227
- proxyUrl = null;
6228
- loggedIn = false;
6229
- gitMetadataSettings;
6230
- debugLogLevel;
6231
- debugLogLevelConfigured = false;
6232
- fetch = globalThis.fetch;
6233
- _appConn = null;
6234
- _apiConn = null;
6235
- _proxyConn = null;
6236
- promptCache;
6237
- parametersCache;
6238
- spanCache;
6239
- _idGenerator = null;
6240
- _contextManager = null;
6241
- _otelFlushCallback = null;
6242
- spanOriginEnvironment;
6243
- traceContextSigningSecret;
6244
6324
  /** @internal */
6245
6325
  _internalSetTraceContextSigningSecret(secret) {
6246
6326
  const normalizedSecret = secret?.trim();
@@ -6265,6 +6345,101 @@ var BraintrustState = class _BraintrustState {
6265
6345
  this._appConn = null;
6266
6346
  this._apiConn = null;
6267
6347
  this._proxyConn = null;
6348
+ this.loaderLoginCache = /* @__PURE__ */ new WeakMap();
6349
+ }
6350
+ /** @internal */
6351
+ async _internalResolveLoaderLoginOptions({
6352
+ apiKey,
6353
+ appUrl,
6354
+ orgName,
6355
+ fetch: fetch2,
6356
+ forceLogin
6357
+ }) {
6358
+ const resolvedAppUrl = appUrl ?? (this.loggedIn ? this.appUrl ?? void 0 : void 0) ?? this.loginParams.appUrl ?? isomorph_default.getEnv("BRAINTRUST_APP_URL") ?? "https://www.braintrust.dev";
6359
+ const resolvedApiKey = apiKey ?? (this.loggedIn ? this.loginToken ?? void 0 : void 0) ?? this.loginParams.apiKey ?? await isomorph_default.getBraintrustApiKey();
6360
+ if (!resolvedApiKey) {
6361
+ throw new Error(
6362
+ "Please specify an api key (e.g. by setting BRAINTRUST_API_KEY)."
6363
+ );
6364
+ }
6365
+ const normalizedApiKey = HTTPConnection.sanitize_token(resolvedApiKey);
6366
+ const usesActiveCredential = this.loggedIn && normalizedApiKey === this.loginToken;
6367
+ const requestedOrgName = orgName ?? (usesActiveCredential ? this.activeLoginOrgNameSelector : void 0) ?? this.loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
6368
+ const resolvedOrgName = orgName ?? (usesActiveCredential ? this.orgName ?? void 0 : void 0) ?? requestedOrgName;
6369
+ const resolvedFetch = fetch2 ?? (this.loggedIn ? this.fetch : void 0) ?? this.loginParams.fetch ?? globalThis.fetch;
6370
+ const credentialCacheNamespace = JSON.stringify([
6371
+ "loader-credential",
6372
+ resolvedAppUrl,
6373
+ requestedOrgName,
6374
+ normalizedApiKey
6375
+ ]);
6376
+ return {
6377
+ apiKey: normalizedApiKey,
6378
+ appUrl: resolvedAppUrl,
6379
+ orgName: resolvedOrgName,
6380
+ fetch: resolvedFetch,
6381
+ forceLogin,
6382
+ credentialCacheNamespace,
6383
+ existingState: !forceLogin && usesActiveCredential && resolvedAppUrl === this.appUrl && resolvedOrgName === this.orgName && resolvedFetch === this.fetch ? this : void 0
6384
+ };
6385
+ }
6386
+ /** @internal */
6387
+ _internalGetLoaderCacheViews(loginOptions, requestState) {
6388
+ const expectedResolvedOrgIdentity = requestState?.orgId && requestState.appUrl ? JSON.stringify([
6389
+ "loader-org",
6390
+ requestState.appUrl,
6391
+ requestState.orgId
6392
+ ]) : void 0;
6393
+ return {
6394
+ promptCache: this.promptCache.withNamespace(
6395
+ loginOptions.credentialCacheNamespace,
6396
+ expectedResolvedOrgIdentity
6397
+ ),
6398
+ parametersCache: this.parametersCache.withNamespace(
6399
+ loginOptions.credentialCacheNamespace,
6400
+ expectedResolvedOrgIdentity
6401
+ )
6402
+ };
6403
+ }
6404
+ /** @internal */
6405
+ async _internalGetLoaderState({
6406
+ apiKey,
6407
+ appUrl,
6408
+ orgName,
6409
+ fetch: fetch2,
6410
+ forceLogin,
6411
+ existingState
6412
+ }) {
6413
+ if (existingState) {
6414
+ return existingState;
6415
+ }
6416
+ let cache = this.loaderLoginCache.get(fetch2);
6417
+ if (!cache) {
6418
+ cache = new LRUCache({ max: LOADER_LOGIN_CACHE_MAX });
6419
+ this.loaderLoginCache.set(fetch2, cache);
6420
+ }
6421
+ const cacheKey = JSON.stringify([appUrl, orgName, apiKey]);
6422
+ if (!forceLogin) {
6423
+ const cachedState = cache.get(cacheKey);
6424
+ if (cachedState) {
6425
+ return cachedState;
6426
+ }
6427
+ }
6428
+ const statePromise = loginToLoaderRequestState({
6429
+ orgName,
6430
+ apiKey,
6431
+ appUrl,
6432
+ fetch: fetch2
6433
+ });
6434
+ cache.set(cacheKey, statePromise);
6435
+ try {
6436
+ return await statePromise;
6437
+ } catch (error) {
6438
+ if (cache.get(cacheKey) === statePromise) {
6439
+ cache.delete(cacheKey);
6440
+ }
6441
+ throw error;
6442
+ }
6268
6443
  }
6269
6444
  resetIdGenState() {
6270
6445
  this._idGenerator = null;
@@ -6313,6 +6488,8 @@ var BraintrustState = class _BraintrustState {
6313
6488
  this.debugLogLevel = other.debugLogLevel;
6314
6489
  this.debugLogLevelConfigured = other.debugLogLevelConfigured;
6315
6490
  this.traceContextSigningSecret = other.traceContextSigningSecret;
6491
+ this.fetch = other.fetch;
6492
+ this.activeLoginOrgNameSelector = other.activeLoginOrgNameSelector;
6316
6493
  setGlobalDebugLogLevel(
6317
6494
  this.debugLogLevelConfigured ? this.debugLogLevel ?? false : void 0
6318
6495
  );
@@ -6552,36 +6729,85 @@ var FailedHTTPResponse = class extends Error {
6552
6729
  status;
6553
6730
  text;
6554
6731
  data;
6555
- constructor(status, text, data) {
6732
+ cause;
6733
+ constructor(status, text, data, cause) {
6556
6734
  super(`${status}: ${text} (${data})`);
6557
6735
  this.status = status;
6558
6736
  this.text = text;
6559
6737
  this.data = data;
6738
+ this.cause = cause;
6739
+ }
6740
+ };
6741
+ var HTTPTransportError = class extends Error {
6742
+ cause;
6743
+ constructor(cause) {
6744
+ super(cause instanceof Error ? cause.message : String(cause));
6745
+ this.name = "HTTPTransportError";
6746
+ this.cause = cause;
6560
6747
  }
6561
6748
  };
6749
+ var httpTransportErrorCauses = /* @__PURE__ */ new WeakSet();
6750
+ function recordHTTPTransportError(error) {
6751
+ if (typeof error === "object" && error !== null || typeof error === "function") {
6752
+ httpTransportErrorCauses.add(error);
6753
+ }
6754
+ }
6755
+ function rethrowHTTPTransportError(error, classifyTransportErrors) {
6756
+ if (classifyTransportErrors) {
6757
+ throw new HTTPTransportError(error);
6758
+ }
6759
+ recordHTTPTransportError(error);
6760
+ throw error;
6761
+ }
6762
+ function isLoaderCacheFallbackError(error) {
6763
+ if (error instanceof FailedHTTPResponse) {
6764
+ return error.status === 408 || error.status === 429 || error.status >= 500;
6765
+ }
6766
+ if (error instanceof HTTPTransportError) {
6767
+ return true;
6768
+ }
6769
+ return (typeof error === "object" && error !== null || typeof error === "function") && httpTransportErrorCauses.has(error);
6770
+ }
6771
+ async function readJSONResponse(response, classifyTransportErrors = false) {
6772
+ let data;
6773
+ try {
6774
+ data = await response.text();
6775
+ } catch (error) {
6776
+ rethrowHTTPTransportError(error, classifyTransportErrors);
6777
+ }
6778
+ return JSON.parse(data);
6779
+ }
6562
6780
  async function checkResponse(resp) {
6563
6781
  if (resp.ok) {
6564
6782
  return resp;
6565
- } else {
6783
+ }
6784
+ let data;
6785
+ try {
6786
+ data = await resp.text();
6787
+ } catch (error) {
6566
6788
  throw new FailedHTTPResponse(
6567
6789
  resp.status,
6568
6790
  resp.statusText,
6569
- await resp.text()
6791
+ "Unable to read response body",
6792
+ error
6570
6793
  );
6571
6794
  }
6795
+ throw new FailedHTTPResponse(resp.status, resp.statusText, data);
6572
6796
  }
6573
6797
  var HTTPConnection = class _HTTPConnection {
6574
- base_url;
6575
- token;
6576
- headers;
6577
- fetch;
6578
- constructor(base_url, fetch2) {
6798
+ constructor(base_url, fetch2, classifyTransportErrors = false) {
6799
+ this.classifyTransportErrors = classifyTransportErrors;
6579
6800
  this.base_url = base_url;
6580
6801
  this.token = null;
6581
6802
  this.headers = {};
6582
6803
  this._reset();
6583
6804
  this.fetch = fetch2;
6584
6805
  }
6806
+ classifyTransportErrors;
6807
+ base_url;
6808
+ token;
6809
+ headers;
6810
+ fetch;
6585
6811
  setFetch(fetch2) {
6586
6812
  this.fetch = fetch2;
6587
6813
  }
@@ -6621,9 +6847,9 @@ var HTTPConnection = class _HTTPConnection {
6621
6847
  ).toString();
6622
6848
  const this_fetch = this.fetch;
6623
6849
  const this_headers = this.headers;
6624
- return await checkResponse(
6625
- // Using toString() here makes it work with isomorphic fetch
6626
- await this_fetch(url.toString(), {
6850
+ let response;
6851
+ try {
6852
+ response = await this_fetch(url.toString(), {
6627
6853
  headers: {
6628
6854
  Accept: "application/json",
6629
6855
  ...this_headers,
@@ -6631,8 +6857,14 @@ var HTTPConnection = class _HTTPConnection {
6631
6857
  },
6632
6858
  keepalive: true,
6633
6859
  ...rest
6634
- })
6635
- );
6860
+ });
6861
+ } catch (error) {
6862
+ if (config?.signal?.aborted) {
6863
+ throw getAbortReason(config.signal);
6864
+ }
6865
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
6866
+ }
6867
+ return await checkResponse(response);
6636
6868
  }
6637
6869
  async post(path, params, config, retries = 0) {
6638
6870
  const { headers, ...rest } = config || {};
@@ -6642,8 +6874,9 @@ var HTTPConnection = class _HTTPConnection {
6642
6874
  const tries = retries + 1;
6643
6875
  for (let i = 0; i < tries; i++) {
6644
6876
  try {
6645
- return await checkResponse(
6646
- await this_fetch(_urljoin(this_base_url, path), {
6877
+ let response;
6878
+ try {
6879
+ response = await this_fetch(_urljoin(this_base_url, path), {
6647
6880
  method: "POST",
6648
6881
  headers: {
6649
6882
  Accept: "application/json",
@@ -6654,8 +6887,14 @@ var HTTPConnection = class _HTTPConnection {
6654
6887
  body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
6655
6888
  keepalive: true,
6656
6889
  ...rest
6657
- })
6658
- );
6890
+ });
6891
+ } catch (error) {
6892
+ if (config?.signal?.aborted) {
6893
+ throw getAbortReason(config.signal);
6894
+ }
6895
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
6896
+ }
6897
+ return await checkResponse(response);
6659
6898
  } catch (error) {
6660
6899
  if (config?.signal?.aborted) {
6661
6900
  throw getAbortReason(config.signal);
@@ -6680,7 +6919,7 @@ var HTTPConnection = class _HTTPConnection {
6680
6919
  for (let i = 0; i < tries; i++) {
6681
6920
  try {
6682
6921
  const resp = await this.get(`${object_type}`, args);
6683
- return await resp.json();
6922
+ return await readJSONResponse(resp, this.classifyTransportErrors);
6684
6923
  } catch (e) {
6685
6924
  if (i < tries - 1) {
6686
6925
  debugLogger.debug(
@@ -6703,7 +6942,7 @@ var HTTPConnection = class _HTTPConnection {
6703
6942
  const resp = await this.post(`${object_type}`, args, {
6704
6943
  headers: { "Content-Type": "application/json" }
6705
6944
  });
6706
- return await resp.json();
6945
+ return await readJSONResponse(resp, this.classifyTransportErrors);
6707
6946
  }
6708
6947
  // Custom inspect for Node.js console.log
6709
6948
  [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
@@ -8751,6 +8990,7 @@ function initDataset(projectOrOptions, optionalOptions) {
8751
8990
  const {
8752
8991
  project,
8753
8992
  dataset,
8993
+ datasetId,
8754
8994
  description,
8755
8995
  version,
8756
8996
  snapshotName,
@@ -8766,6 +9006,11 @@ function initDataset(projectOrOptions, optionalOptions) {
8766
9006
  state: stateArg,
8767
9007
  _internal_btql
8768
9008
  } = options;
9009
+ if (datasetId !== void 0 && (description !== void 0 || metadata !== void 0)) {
9010
+ throw new Error(
9011
+ "Cannot specify description or metadata when datasetId is provided"
9012
+ );
9013
+ }
8769
9014
  const selection = normalizeDatasetSelection({
8770
9015
  version,
8771
9016
  environment,
@@ -8786,6 +9031,35 @@ function initDataset(projectOrOptions, optionalOptions) {
8786
9031
  fetch: fetch2,
8787
9032
  forceLogin
8788
9033
  });
9034
+ if (datasetId !== void 0) {
9035
+ const objectInfo = datasetObjectInfoSchema.array().parse(
9036
+ await state.appConn().post_json("api/self/get_object_info", {
9037
+ object_type: "dataset",
9038
+ object_ids: [datasetId]
9039
+ })
9040
+ );
9041
+ if (objectInfo.length === 0) {
9042
+ throw new Error(`Dataset with ID ${datasetId} not found`);
9043
+ }
9044
+ if (objectInfo.length !== 1) {
9045
+ throw new Error(
9046
+ `Expected exactly one dataset with ID ${datasetId}, but found ${objectInfo.length}`
9047
+ );
9048
+ }
9049
+ const datasetInfo = objectInfo[0];
9050
+ return {
9051
+ project: {
9052
+ id: datasetInfo.parent_cols.project.id,
9053
+ name: datasetInfo.parent_cols.project.name,
9054
+ fullInfo: datasetInfo.parent_cols.project
9055
+ },
9056
+ dataset: {
9057
+ id: datasetInfo.object_id,
9058
+ name: datasetInfo.object_name,
9059
+ fullInfo: datasetInfo
9060
+ }
9061
+ };
9062
+ }
8789
9063
  const args = {
8790
9064
  org_id: state.orgId,
8791
9065
  project_name: project,
@@ -8939,6 +9213,24 @@ function initLogger(options = {}) {
8939
9213
  }
8940
9214
  return ret;
8941
9215
  }
9216
+ async function runCredentialScopedLoaderRequest(state, loginOptions, request) {
9217
+ const resolvedLoginOptions = await state._internalResolveLoaderLoginOptions(loginOptions);
9218
+ let cacheViews = state._internalGetLoaderCacheViews(resolvedLoginOptions);
9219
+ try {
9220
+ const requestState = await state._internalGetLoaderState(resolvedLoginOptions);
9221
+ cacheViews = state._internalGetLoaderCacheViews(
9222
+ resolvedLoginOptions,
9223
+ requestState
9224
+ );
9225
+ return {
9226
+ ok: true,
9227
+ response: await request(requestState),
9228
+ ...cacheViews
9229
+ };
9230
+ } catch (error) {
9231
+ return { ok: false, error, ...cacheViews };
9232
+ }
9233
+ }
8942
9234
  async function loadPrompt({
8943
9235
  projectName,
8944
9236
  projectId,
@@ -8963,43 +9255,47 @@ async function loadPrompt({
8963
9255
  throw new Error("Must specify slug");
8964
9256
  }
8965
9257
  const state = stateArg ?? _globalState;
8966
- let response;
8967
- try {
8968
- await state.login({
8969
- orgName,
8970
- apiKey,
8971
- appUrl,
8972
- fetch: fetch2,
8973
- forceLogin
8974
- });
8975
- if (id) {
8976
- response = await state.apiConn().get_json(`v1/prompt/${id}`, versionOrEnvironment);
8977
- if (response) {
8978
- response = { objects: [response] };
9258
+ const result = await runCredentialScopedLoaderRequest(
9259
+ state,
9260
+ { orgName, apiKey, appUrl, fetch: fetch2, forceLogin },
9261
+ async (requestState) => {
9262
+ let response2;
9263
+ if (id) {
9264
+ response2 = await requestState.apiConn().get_json(`v1/prompt/${id}`, versionOrEnvironment);
9265
+ if (response2) {
9266
+ response2 = { objects: [response2] };
9267
+ }
9268
+ } else {
9269
+ response2 = await requestState.apiConn().get_json("v1/prompt", {
9270
+ project_name: projectName,
9271
+ project_id: projectId,
9272
+ slug,
9273
+ ...versionOrEnvironment
9274
+ });
8979
9275
  }
8980
- } else {
8981
- response = await state.apiConn().get_json("v1/prompt", {
8982
- project_name: projectName,
8983
- project_id: projectId,
8984
- slug,
8985
- ...versionOrEnvironment
8986
- });
9276
+ return response2;
9277
+ }
9278
+ );
9279
+ const { promptCache } = result;
9280
+ if (!result.ok) {
9281
+ const e = result.error;
9282
+ if (!isLoaderCacheFallbackError(e)) {
9283
+ throw e;
8987
9284
  }
8988
- } catch (e) {
8989
9285
  if (version || environment) {
8990
9286
  throw new Error(`Prompt not found with specified parameters: ${e}`);
8991
9287
  }
8992
9288
  debugLogger.forState(state).warn("Failed to load prompt, attempting to fall back to cache:", e);
8993
9289
  let prompt2;
8994
9290
  if (id) {
8995
- prompt2 = await state.promptCache.get({ id });
9291
+ prompt2 = await promptCache.get({ id });
8996
9292
  if (!prompt2) {
8997
9293
  throw new Error(
8998
9294
  `Prompt with id ${id} not found (not found on server or in local cache): ${e}`
8999
9295
  );
9000
9296
  }
9001
9297
  } else {
9002
- prompt2 = await state.promptCache.get({
9298
+ prompt2 = await promptCache.get({
9003
9299
  slug,
9004
9300
  projectId,
9005
9301
  projectName,
@@ -9015,6 +9311,7 @@ async function loadPrompt({
9015
9311
  }
9016
9312
  return prompt2;
9017
9313
  }
9314
+ const { response } = result;
9018
9315
  if (!("objects" in response) || response.objects.length === 0) {
9019
9316
  if (id) {
9020
9317
  throw new Error(`Prompt with id ${id} not found.`);
@@ -9038,9 +9335,9 @@ async function loadPrompt({
9038
9335
  const prompt = new Prompt2(metadata, defaults || {}, noTrace);
9039
9336
  try {
9040
9337
  if (id) {
9041
- await state.promptCache.set({ id }, prompt);
9338
+ await promptCache.set({ id }, prompt);
9042
9339
  } else if (slug) {
9043
- await state.promptCache.set(
9340
+ await promptCache.set(
9044
9341
  { slug, projectId, projectName, version: version ?? "latest" },
9045
9342
  prompt
9046
9343
  );
@@ -9072,46 +9369,50 @@ async function loadParameters({
9072
9369
  throw new Error("Must specify slug");
9073
9370
  }
9074
9371
  const state = stateArg ?? _globalState;
9075
- let response;
9076
- try {
9077
- await state.login({
9078
- orgName,
9079
- apiKey,
9080
- appUrl,
9081
- fetch: fetch2,
9082
- forceLogin
9083
- });
9084
- if (id) {
9085
- response = await state.apiConn().get_json(`v1/function/${id}`, {
9086
- ...versionOrEnvironment
9087
- });
9088
- if (response) {
9089
- response = { objects: [response] };
9372
+ const result = await runCredentialScopedLoaderRequest(
9373
+ state,
9374
+ { orgName, apiKey, appUrl, fetch: fetch2, forceLogin },
9375
+ async (requestState) => {
9376
+ let response2;
9377
+ if (id) {
9378
+ response2 = await requestState.apiConn().get_json(`v1/function/${id}`, {
9379
+ ...versionOrEnvironment
9380
+ });
9381
+ if (response2) {
9382
+ response2 = { objects: [response2] };
9383
+ }
9384
+ } else {
9385
+ response2 = await requestState.apiConn().get_json("v1/function", {
9386
+ project_name: projectName,
9387
+ project_id: projectId,
9388
+ slug,
9389
+ function_type: "parameters",
9390
+ ...versionOrEnvironment
9391
+ });
9090
9392
  }
9091
- } else {
9092
- response = await state.apiConn().get_json("v1/function", {
9093
- project_name: projectName,
9094
- project_id: projectId,
9095
- slug,
9096
- function_type: "parameters",
9097
- ...versionOrEnvironment
9098
- });
9393
+ return response2;
9394
+ }
9395
+ );
9396
+ const { parametersCache } = result;
9397
+ if (!result.ok) {
9398
+ const e = result.error;
9399
+ if (!isLoaderCacheFallbackError(e)) {
9400
+ throw e;
9099
9401
  }
9100
- } catch (e) {
9101
9402
  if (version || environment) {
9102
9403
  throw new Error(`Parameters not found with specified parameters: ${e}`);
9103
9404
  }
9104
9405
  debugLogger.forState(state).warn("Failed to load parameters, attempting to fall back to cache:", e);
9105
9406
  let parameters2;
9106
9407
  if (id) {
9107
- parameters2 = await state.parametersCache.get({ id });
9408
+ parameters2 = await parametersCache.get({ id });
9108
9409
  if (!parameters2) {
9109
9410
  throw new Error(
9110
9411
  `Parameters with id ${id} not found (not found on server or in local cache): ${e}`
9111
9412
  );
9112
9413
  }
9113
9414
  } else {
9114
- parameters2 = await state.parametersCache.get({
9415
+ parameters2 = await parametersCache.get({
9115
9416
  slug,
9116
9417
  projectId,
9117
9418
  projectName,
@@ -9127,6 +9428,7 @@ async function loadParameters({
9127
9428
  }
9128
9429
  return parameters2;
9129
9430
  }
9431
+ const { response } = result;
9130
9432
  if (!("objects" in response) || response.objects.length === 0) {
9131
9433
  if (id) {
9132
9434
  throw new Error(`Parameters with id ${id} not found.`);
@@ -9150,9 +9452,9 @@ async function loadParameters({
9150
9452
  const parameters = new RemoteEvalParameters(metadata);
9151
9453
  try {
9152
9454
  if (id) {
9153
- await state.parametersCache.set({ id }, parameters);
9455
+ await parametersCache.set({ id }, parameters);
9154
9456
  } else if (slug) {
9155
- await state.parametersCache.set(
9457
+ await parametersCache.set(
9156
9458
  { slug, projectId, projectName, version: version ?? "latest" },
9157
9459
  parameters
9158
9460
  );
@@ -9193,6 +9495,52 @@ async function login(options = {}) {
9193
9495
  await state.login(options);
9194
9496
  return state;
9195
9497
  }
9498
+ async function loginToLoaderRequestState({
9499
+ appUrl,
9500
+ apiKey,
9501
+ orgName,
9502
+ fetch: fetch2
9503
+ }) {
9504
+ let orgId;
9505
+ let apiUrl;
9506
+ if (apiKey === TEST_API_KEY) {
9507
+ orgId = "test-org-id";
9508
+ apiUrl = "https://braintrust.dev/fake-api-url";
9509
+ } else {
9510
+ let loginResponse;
9511
+ try {
9512
+ loginResponse = await fetch2(_urljoin(appUrl, `/api/apikey/login`), {
9513
+ method: "POST",
9514
+ headers: {
9515
+ "Content-Type": "application/json",
9516
+ Authorization: `Bearer ${apiKey}`
9517
+ }
9518
+ });
9519
+ } catch (error) {
9520
+ throw new HTTPTransportError(error);
9521
+ }
9522
+ const info = await readJSONResponse(
9523
+ await checkResponse(loginResponse),
9524
+ true
9525
+ );
9526
+ const org = selectLoginOrg(info.org_info, orgName);
9527
+ orgId = org.id;
9528
+ apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
9529
+ if (!apiUrl) {
9530
+ throw new Error(
9531
+ orgName ? `Unable to log into organization '${orgName}'. Are you sure this credential is scoped to the organization?` : "Unable to log into any organization with the provided credential."
9532
+ );
9533
+ }
9534
+ }
9535
+ const apiConnection = new HTTPConnection(apiUrl, fetch2, true);
9536
+ apiConnection.set_token(apiKey);
9537
+ apiConnection.make_long_lived();
9538
+ return {
9539
+ appUrl,
9540
+ orgId,
9541
+ apiConn: () => apiConnection
9542
+ };
9543
+ }
9196
9544
  async function loginToState(options = {}) {
9197
9545
  const {
9198
9546
  appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
@@ -9224,16 +9572,18 @@ async function loginToState(options = {}) {
9224
9572
  _saveOrgInfo(state, testOrgInfo, testOrgInfo[0].name);
9225
9573
  return state;
9226
9574
  } else {
9227
- const resp = await checkResponse(
9228
- await fetch2(_urljoin(state.appUrl, `/api/apikey/login`), {
9575
+ const loginResponse = await fetch2(
9576
+ _urljoin(state.appUrl, `/api/apikey/login`),
9577
+ {
9229
9578
  method: "POST",
9230
9579
  headers: {
9231
9580
  "Content-Type": "application/json",
9232
9581
  Authorization: `Bearer ${apiKey}`
9233
9582
  }
9234
- })
9583
+ }
9235
9584
  );
9236
- const info = await resp.json();
9585
+ const resp = await checkResponse(loginResponse);
9586
+ const info = await readJSONResponse(resp);
9237
9587
  _saveOrgInfo(state, info.org_info, orgName);
9238
9588
  if (!state.apiUrl) {
9239
9589
  if (orgName) {
@@ -9736,11 +10086,11 @@ function wrapTraced(fn, args) {
9736
10086
  }
9737
10087
  if (args?.asyncFlush) {
9738
10088
  return ((...fnArgs) => traced((span) => {
9739
- if (!hasExplicitInput) {
10089
+ if (!args?.noTraceIO && !hasExplicitInput) {
9740
10090
  span.log({ input: fnArgs });
9741
10091
  }
9742
10092
  const output = fn(...fnArgs);
9743
- if (!hasExplicitOutput) {
10093
+ if (!args?.noTraceIO && !hasExplicitOutput) {
9744
10094
  if (output instanceof Promise) {
9745
10095
  return (async () => {
9746
10096
  const result = await output;
@@ -9755,12 +10105,12 @@ function wrapTraced(fn, args) {
9755
10105
  }, spanArgs));
9756
10106
  } else {
9757
10107
  return ((...fnArgs) => traced(async (span) => {
9758
- if (!hasExplicitInput) {
10108
+ if (!args?.noTraceIO && !hasExplicitInput) {
9759
10109
  span.log({ input: fnArgs });
9760
10110
  }
9761
10111
  const outputResult = fn(...fnArgs);
9762
10112
  const output = await outputResult;
9763
- if (!hasExplicitOutput) {
10113
+ if (!args?.noTraceIO && !hasExplicitOutput) {
9764
10114
  span.log({ output });
9765
10115
  }
9766
10116
  return output;
@@ -9886,27 +10236,28 @@ async function* asyncGeneratorWithCurrent(span, gen, state = void 0) {
9886
10236
  function withParent(parent, callback, state = void 0) {
9887
10237
  return (state ?? _globalState).currentParent.run(parent, () => callback());
9888
10238
  }
9889
- function _saveOrgInfo(state, org_info, org_name) {
9890
- if (org_info.length === 0) {
10239
+ function _saveOrgInfo(state, orgInfo, orgName) {
10240
+ const org = selectLoginOrg(orgInfo, orgName);
10241
+ state.orgId = org.id;
10242
+ state.orgName = org.name;
10243
+ state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
10244
+ state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
10245
+ state.gitMetadataSettings = org.git_metadata || void 0;
10246
+ }
10247
+ function selectLoginOrg(orgInfo, orgName) {
10248
+ if (orgInfo.length === 0) {
9891
10249
  throw new LoginInvalidOrgError(
9892
10250
  "This user is not part of any organizations."
9893
10251
  );
9894
10252
  }
9895
- for (const org of org_info) {
9896
- if (org_name === void 0 || org.name === org_name) {
9897
- state.orgId = org.id;
9898
- state.orgName = org.name;
9899
- state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
9900
- state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
9901
- state.gitMetadataSettings = org.git_metadata || void 0;
9902
- break;
10253
+ for (const org of orgInfo) {
10254
+ if (orgName === void 0 || org.name === orgName) {
10255
+ return org;
9903
10256
  }
9904
10257
  }
9905
- if (state.orgId === void 0) {
9906
- throw new LoginInvalidOrgError(
9907
- `Organization ${org_name} not found. Must be one of ${org_info.map((x) => x.name).join(", ")}`
9908
- );
9909
- }
10258
+ throw new LoginInvalidOrgError(
10259
+ `Organization ${orgName} not found. Must be one of ${orgInfo.map((org) => org.name).join(", ")}`
10260
+ );
9910
10261
  }
9911
10262
  function validateTags(tags) {
9912
10263
  const seen = /* @__PURE__ */ new Set();
@@ -11812,6 +12163,14 @@ var Prompt2 = class _Prompt {
11812
12163
  static isPrompt(data) {
11813
12164
  return typeof data === "object" && data !== null && "__braintrust_prompt_marker" in data;
11814
12165
  }
12166
+ /** @internal */
12167
+ _internalSerializeForCache() {
12168
+ return {
12169
+ metadata: this.metadata,
12170
+ defaults: this.defaults,
12171
+ noTrace: this.noTrace
12172
+ };
12173
+ }
11815
12174
  static fromPromptData(name, promptData) {
11816
12175
  return new _Prompt(
11817
12176
  {
@@ -11852,6 +12211,10 @@ var RemoteEvalParameters = class {
11852
12211
  get data() {
11853
12212
  return this.metadata.function_data.data ?? {};
11854
12213
  }
12214
+ /** @internal */
12215
+ _internalSerializeForCache() {
12216
+ return { metadata: this.metadata };
12217
+ }
11855
12218
  validate(data) {
11856
12219
  if (typeof data !== "object" || data === null) {
11857
12220
  return false;
@@ -12638,56 +13001,14 @@ function suppressionStore() {
12638
13001
  autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
12639
13002
  return autoInstrumentationSuppressionStore;
12640
13003
  }
12641
- function currentFrames() {
12642
- return suppressionStore().getStore()?.frames ?? [];
12643
- }
12644
13004
  function isAutoInstrumentationSuppressed() {
12645
- const frames = currentFrames();
12646
- return frames[frames.length - 1]?.mode === "suppress";
13005
+ return suppressionStore().getStore() === true;
12647
13006
  }
12648
13007
  function runWithAutoInstrumentationSuppressed(callback) {
12649
- const frame = {
12650
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
12651
- mode: "suppress"
12652
- };
12653
- return suppressionStore().run(
12654
- { frames: [...currentFrames(), frame] },
12655
- callback
12656
- );
13008
+ return suppressionStore().run(true, callback);
12657
13009
  }
12658
- function bindAutoInstrumentationSuppressionToStart(tracingChannel) {
12659
- const startChannel = tracingChannel.start;
12660
- if (!startChannel) {
12661
- return void 0;
12662
- }
12663
- const store = suppressionStore();
12664
- startChannel.bindStore(store, () => ({
12665
- frames: [
12666
- ...currentFrames(),
12667
- {
12668
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
12669
- mode: "suppress"
12670
- }
12671
- ]
12672
- }));
12673
- return () => {
12674
- startChannel.unbindStore(store);
12675
- };
12676
- }
12677
- function enterAutoInstrumentationAllowed() {
12678
- const frame = {
12679
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
12680
- mode: "allow"
12681
- };
12682
- suppressionStore().enterWith({
12683
- frames: [...currentFrames(), frame]
12684
- });
12685
- return () => {
12686
- const frames = currentFrames().filter(
12687
- (candidate) => candidate.id !== frame.id
12688
- );
12689
- suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
12690
- };
13010
+ function runWithAutoInstrumentationAllowed(callback) {
13011
+ return suppressionStore().run(void 0, callback);
12691
13012
  }
12692
13013
 
12693
13014
  // src/instrumentation/core/channel-tracing.ts
@@ -13976,13 +14297,33 @@ function aggregateChatLogprobs(existing, incoming) {
13976
14297
  }
13977
14298
  return aggregated;
13978
14299
  }
14300
+ function createAggregatedChatChoice(index) {
14301
+ return {
14302
+ index,
14303
+ role: void 0,
14304
+ content: void 0,
14305
+ refusal: void 0,
14306
+ toolCallsByIndex: /* @__PURE__ */ new Map(),
14307
+ logprobs: void 0,
14308
+ finish_reason: void 0
14309
+ };
14310
+ }
14311
+ function toChatChoice(choice) {
14312
+ const toolCalls2 = Array.from(choice.toolCallsByIndex.entries()).sort(([left], [right]) => left - right).map(([, toolCall]) => toolCall);
14313
+ return {
14314
+ index: choice.index,
14315
+ message: {
14316
+ role: choice.role,
14317
+ content: choice.content,
14318
+ ...choice.refusal !== void 0 ? { refusal: choice.refusal } : {},
14319
+ tool_calls: toolCalls2.length > 0 ? toolCalls2 : void 0
14320
+ },
14321
+ logprobs: choice.logprobs ?? null,
14322
+ finish_reason: choice.finish_reason
14323
+ };
14324
+ }
13979
14325
  function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
13980
- let role = void 0;
13981
- let content = void 0;
13982
- let refusal = void 0;
13983
- let tool_calls = void 0;
13984
- let logprobs = void 0;
13985
- let finish_reason = void 0;
14326
+ const choicesByIndex = /* @__PURE__ */ new Map();
13986
14327
  let metrics = {};
13987
14328
  for (const chunk of chunks) {
13988
14329
  if (chunk.usage) {
@@ -13991,62 +14332,75 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
13991
14332
  ...parseMetricsFromUsage(chunk.usage)
13992
14333
  };
13993
14334
  }
13994
- const choice = chunk.choices?.[0];
13995
- if (!choice) {
13996
- continue;
13997
- }
13998
- if (choice.finish_reason) {
13999
- finish_reason = choice.finish_reason;
14000
- }
14001
- logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
14002
- const delta = choice.delta;
14003
- if (!delta) {
14335
+ const choices = chunk.choices;
14336
+ if (!choices?.length) {
14004
14337
  continue;
14005
14338
  }
14006
- if (delta.finish_reason) {
14007
- finish_reason = delta.finish_reason;
14008
- }
14009
- if (!role && delta.role) {
14010
- role = delta.role;
14011
- }
14012
- if (delta.content) {
14013
- content = (content || "") + delta.content;
14014
- }
14015
- if (delta.refusal) {
14016
- refusal = (refusal || "") + delta.refusal;
14017
- }
14018
- if (delta.tool_calls) {
14019
- const toolDelta = delta.tool_calls[0];
14020
- if (!tool_calls || toolDelta.id && tool_calls[tool_calls.length - 1].id !== toolDelta.id) {
14021
- tool_calls = [
14022
- ...tool_calls || [],
14023
- {
14024
- id: toolDelta.id,
14025
- type: toolDelta.type,
14026
- function: toolDelta.function
14339
+ for (const choice of choices) {
14340
+ const choiceIndex = choice.index;
14341
+ let aggregatedChoice = choicesByIndex.get(choiceIndex);
14342
+ if (!aggregatedChoice) {
14343
+ aggregatedChoice = createAggregatedChatChoice(choiceIndex);
14344
+ choicesByIndex.set(choiceIndex, aggregatedChoice);
14345
+ }
14346
+ if (choice.finish_reason) {
14347
+ aggregatedChoice.finish_reason = choice.finish_reason;
14348
+ }
14349
+ aggregatedChoice.logprobs = aggregateChatLogprobs(
14350
+ aggregatedChoice.logprobs,
14351
+ choice.logprobs
14352
+ );
14353
+ const delta = choice.delta;
14354
+ if (!delta) {
14355
+ continue;
14356
+ }
14357
+ if (delta.finish_reason) {
14358
+ aggregatedChoice.finish_reason = delta.finish_reason;
14359
+ }
14360
+ if (!aggregatedChoice.role && delta.role) {
14361
+ aggregatedChoice.role = delta.role;
14362
+ }
14363
+ if (delta.content) {
14364
+ aggregatedChoice.content = (aggregatedChoice.content || "") + delta.content;
14365
+ }
14366
+ if (delta.refusal) {
14367
+ aggregatedChoice.refusal = (aggregatedChoice.refusal || "") + delta.refusal;
14368
+ }
14369
+ if (delta.tool_calls) {
14370
+ for (const toolDelta of delta.tool_calls) {
14371
+ let aggregatedToolCall = aggregatedChoice.toolCallsByIndex.get(
14372
+ toolDelta.index
14373
+ );
14374
+ if (!aggregatedToolCall) {
14375
+ aggregatedToolCall = {
14376
+ function: { arguments: "" }
14377
+ };
14378
+ aggregatedChoice.toolCallsByIndex.set(
14379
+ toolDelta.index,
14380
+ aggregatedToolCall
14381
+ );
14027
14382
  }
14028
- ];
14029
- } else {
14030
- tool_calls[tool_calls.length - 1].function.arguments += toolDelta.function.arguments;
14383
+ if (toolDelta.id !== void 0) {
14384
+ aggregatedToolCall.id = toolDelta.id;
14385
+ }
14386
+ if (toolDelta.type !== void 0) {
14387
+ aggregatedToolCall.type = toolDelta.type;
14388
+ }
14389
+ if (toolDelta.function?.name !== void 0) {
14390
+ aggregatedToolCall.function.name = toolDelta.function.name;
14391
+ }
14392
+ if (toolDelta.function?.arguments !== void 0) {
14393
+ aggregatedToolCall.function.arguments += toolDelta.function.arguments;
14394
+ }
14395
+ }
14031
14396
  }
14032
14397
  }
14033
14398
  }
14034
14399
  metrics = withCachedMetric(metrics, streamResult, endEvent);
14400
+ const output = Array.from(choicesByIndex.values()).sort((left, right) => left.index - right.index).map(toChatChoice);
14035
14401
  return {
14036
14402
  metrics,
14037
- output: [
14038
- {
14039
- index: 0,
14040
- message: {
14041
- role,
14042
- content,
14043
- ...refusal !== void 0 ? { refusal } : {},
14044
- tool_calls
14045
- },
14046
- logprobs: logprobs ?? null,
14047
- finish_reason
14048
- }
14049
- ]
14403
+ output: output.length > 0 ? output : [toChatChoice(createAggregatedChatChoice(0))]
14050
14404
  };
14051
14405
  }
14052
14406
  function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
@@ -15382,6 +15736,12 @@ function parseMetricsFromUsage2(usage) {
15382
15736
  }
15383
15737
  }
15384
15738
  }
15739
+ if (isObject(usage.output_tokens_details)) {
15740
+ const thinkingTokens = usage.output_tokens_details.thinking_tokens;
15741
+ if (typeof thinkingTokens === "number") {
15742
+ metrics.completion_reasoning_tokens = thinkingTokens;
15743
+ }
15744
+ }
15385
15745
  if (isObject(usage.server_tool_use)) {
15386
15746
  for (const [name, value] of Object.entries(usage.server_tool_use)) {
15387
15747
  if (typeof value === "number") {
@@ -16338,7 +16698,6 @@ function endHarnessTurn(parent) {
16338
16698
  function braintrustAISDKTelemetry() {
16339
16699
  const operations = /* @__PURE__ */ new Map();
16340
16700
  const operationKeysByCallId = /* @__PURE__ */ new Map();
16341
- const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
16342
16701
  const modelSpans = /* @__PURE__ */ new Map();
16343
16702
  const objectSpans = /* @__PURE__ */ new Map();
16344
16703
  const embedSpans = /* @__PURE__ */ new Map();
@@ -16381,9 +16740,6 @@ function braintrustAISDKTelemetry() {
16381
16740
  return;
16382
16741
  }
16383
16742
  operations.delete(operationKey);
16384
- if (workflowOperationKeyStore.getStore() === operationKey) {
16385
- workflowOperationKeyStore.enterWith(void 0);
16386
- }
16387
16743
  const keys = operationKeysByCallId.get(state.callId);
16388
16744
  if (!keys) {
16389
16745
  return;
@@ -16431,14 +16787,7 @@ function braintrustAISDKTelemetry() {
16431
16787
  return key;
16432
16788
  }
16433
16789
  }
16434
- const workflowOperationKey = workflowOperationKeyStore.getStore();
16435
- if (workflowOperationKey && keys.includes(workflowOperationKey)) {
16436
- return workflowOperationKey;
16437
- }
16438
- if (callId === "workflow-agent") {
16439
- return void 0;
16440
- }
16441
- return mode === "finish" ? keys[0] : keys[keys.length - 1];
16790
+ return callId === "workflow-agent" || mode === "active" ? keys[keys.length - 1] : keys[0];
16442
16791
  };
16443
16792
  const operationKeyFromEvent = (event, mode = "active") => {
16444
16793
  const explicit = explicitOperationKey(event);
@@ -16452,17 +16801,13 @@ function braintrustAISDKTelemetry() {
16452
16801
  if (operationKey) {
16453
16802
  return operationKey;
16454
16803
  }
16455
- const workflowOperationKey2 = workflowOperationKeyStore.getStore();
16456
- if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
16457
- return workflowOperationKey2;
16804
+ const workflowAgentKeys2 = operationKeysByCallId.get("workflow-agent");
16805
+ if (workflowAgentKeys2?.length) {
16806
+ return workflowAgentKeys2[workflowAgentKeys2.length - 1];
16458
16807
  }
16459
16808
  return callId === "workflow-agent" ? void 0 : callId;
16460
16809
  }
16461
16810
  }
16462
- const workflowOperationKey = workflowOperationKeyStore.getStore();
16463
- if (workflowOperationKey && operations.has(workflowOperationKey)) {
16464
- return workflowOperationKey;
16465
- }
16466
16811
  const wrapperSpan = currentWorkflowAgentWrapperSpan();
16467
16812
  if (wrapperSpan?.spanId) {
16468
16813
  for (const [operationKey, state] of operations) {
@@ -16472,8 +16817,8 @@ function braintrustAISDKTelemetry() {
16472
16817
  }
16473
16818
  }
16474
16819
  const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
16475
- if (workflowAgentKeys?.length === 1) {
16476
- return workflowAgentKeys[0];
16820
+ if (workflowAgentKeys?.length) {
16821
+ return workflowAgentKeys[workflowAgentKeys.length - 1];
16477
16822
  }
16478
16823
  if (operations.size === 1) {
16479
16824
  return operations.keys().next().value;
@@ -16676,9 +17021,6 @@ function braintrustAISDKTelemetry() {
16676
17021
  if (!ownsSpan) {
16677
17022
  return;
16678
17023
  }
16679
- if (workflowAgent) {
16680
- workflowOperationKeyStore.enterWith(operationKey);
16681
- }
16682
17024
  let metadata = metadataFromEvent(event);
16683
17025
  const logPayload = { metadata };
16684
17026
  const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
@@ -17150,6 +17492,10 @@ var aiSDKChannels = defineChannels(
17150
17492
  channelName: "generateText",
17151
17493
  kind: "async"
17152
17494
  }),
17495
+ generateImage: channel({
17496
+ channelName: "generateImage",
17497
+ kind: "async"
17498
+ }),
17153
17499
  streamText: channel({
17154
17500
  channelName: "streamText",
17155
17501
  kind: "async"
@@ -17337,7 +17683,7 @@ var AISDKPlugin = class extends BasePlugin {
17337
17683
  }
17338
17684
  subscribeToAISDK() {
17339
17685
  const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
17340
- this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
17686
+ this.unsubscribers.push(interceptAISDKV7TelemetryDispatcher());
17341
17687
  this.unsubscribers.push(subscribeToHarnessAgentCreateSession());
17342
17688
  this.unsubscribers.push(
17343
17689
  subscribeToHarnessContinuation(
@@ -17365,6 +17711,18 @@ var AISDKPlugin = class extends BasePlugin {
17365
17711
  aggregateChunks: aggregateAISDKChunks
17366
17712
  })
17367
17713
  );
17714
+ this.unsubscribers.push(
17715
+ traceAsyncChannel(aiSDKChannels.generateImage, {
17716
+ name: "generateImage",
17717
+ type: "llm" /* LLM */,
17718
+ extractInput: ([params], event) => prepareAISDKGenerateImageInput(params, event.self),
17719
+ extractOutput: (result, endEvent) => processAISDKGenerateImageOutput(
17720
+ result,
17721
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
17722
+ ),
17723
+ extractMetrics: (result) => extractTokenMetrics(result)
17724
+ })
17725
+ );
17368
17726
  this.unsubscribers.push(
17369
17727
  traceStreamingChannel(aiSDKChannels.streamText, {
17370
17728
  name: "streamText",
@@ -17854,26 +18212,29 @@ function subscribeToHarnessContinuation(continuationChannel, defaultDenyOutputPa
17854
18212
  channel2.unsubscribe(handlers);
17855
18213
  };
17856
18214
  }
17857
- function subscribeToAISDKV7TelemetryDispatcher() {
17858
- const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
18215
+ function interceptAISDKV7TelemetryDispatcher() {
17859
18216
  const telemetry = braintrustAISDKTelemetry();
17860
- const handlers = {
17861
- end: (event) => {
17862
- const telemetryOptions = event.arguments?.[0]?.telemetry;
17863
- if (telemetryOptions?.isEnabled === false) {
17864
- return;
18217
+ return aiSDKChannels.v7CreateTelemetryDispatcher.intercept(
18218
+ (target, thisArg, args) => {
18219
+ const dispatcher = Reflect.apply(target, thisArg, args);
18220
+ const telemetryOptions = args[0]?.telemetry;
18221
+ if (telemetryOptions?.isEnabled !== false) {
18222
+ try {
18223
+ patchAISDKV7TelemetryDispatcher(
18224
+ dispatcher,
18225
+ telemetry,
18226
+ telemetryOptions
18227
+ );
18228
+ } catch (error) {
18229
+ debugLogger.error(
18230
+ "Error instrumenting AI SDK v7 telemetry dispatcher:",
18231
+ error
18232
+ );
18233
+ }
17865
18234
  }
17866
- patchAISDKV7TelemetryDispatcher(
17867
- event.result,
17868
- telemetry,
17869
- telemetryOptions
17870
- );
18235
+ return dispatcher;
17871
18236
  }
17872
- };
17873
- channel2.subscribe(handlers);
17874
- return () => {
17875
- channel2.unsubscribe(handlers);
17876
- };
18237
+ );
17877
18238
  }
17878
18239
  function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
17879
18240
  if (!isObject(dispatcher)) {
@@ -18198,16 +18559,10 @@ var convertImageToAttachment = (image, explicitMimeType) => {
18198
18559
  }
18199
18560
  }
18200
18561
  if (explicitMimeType) {
18201
- if (image instanceof Uint8Array) {
18202
- return new Attachment({
18203
- data: new Blob([image], { type: explicitMimeType }),
18204
- filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
18205
- contentType: explicitMimeType
18206
- });
18207
- }
18208
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
18562
+ const blob = convertDataToBlob(image, explicitMimeType);
18563
+ if (blob) {
18209
18564
  return new Attachment({
18210
- data: new Blob([image], { type: explicitMimeType }),
18565
+ data: blob,
18211
18566
  filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
18212
18567
  contentType: explicitMimeType
18213
18568
  });
@@ -18261,6 +18616,25 @@ var convertDataToAttachment = (data, mimeType, filename) => {
18261
18616
  function processAISDKCallInput(params) {
18262
18617
  return processInputAttachmentsSync(params);
18263
18618
  }
18619
+ function processAISDKGenerateImageInput(params) {
18620
+ const prompt = params.prompt;
18621
+ if (!isObject(prompt) || Array.isArray(prompt)) {
18622
+ return processAISDKCallInput(params);
18623
+ }
18624
+ const processedPrompt = { ...prompt };
18625
+ if (Array.isArray(prompt.images)) {
18626
+ processedPrompt.images = prompt.images.map(
18627
+ (image) => convertImageToAttachment(image, "image/png") ?? image
18628
+ );
18629
+ }
18630
+ if (prompt.mask !== void 0) {
18631
+ processedPrompt.mask = convertImageToAttachment(prompt.mask, "image/png") ?? prompt.mask;
18632
+ }
18633
+ return processAISDKCallInput({
18634
+ ...params,
18635
+ prompt: processedPrompt
18636
+ });
18637
+ }
18264
18638
  function processAISDKWorkflowAgentCallInput(params) {
18265
18639
  const processed = processAISDKCallInput(params);
18266
18640
  return {
@@ -18399,6 +18773,12 @@ function prepareAISDKEmbedInput(params, self) {
18399
18773
  metadata: extractMetadataFromEmbedParams(params, self)
18400
18774
  };
18401
18775
  }
18776
+ function prepareAISDKGenerateImageInput(params, self) {
18777
+ return {
18778
+ input: processAISDKGenerateImageInput(params).input,
18779
+ metadata: extractMetadataFromCallParams(params, self)
18780
+ };
18781
+ }
18402
18782
  function prepareAISDKRerankInput(params, self) {
18403
18783
  const { documents, query } = params;
18404
18784
  return {
@@ -19774,6 +20154,57 @@ function processAISDKOutput(output, denyOutputPaths) {
19774
20154
  }
19775
20155
  return normalizeAISDKLoggedOutput(sanitized);
19776
20156
  }
20157
+ function processAISDKGenerateImageOutput(output, denyOutputPaths) {
20158
+ if (!output || typeof output !== "object") {
20159
+ return output;
20160
+ }
20161
+ const summarized = {};
20162
+ for (const field of [
20163
+ "usage",
20164
+ "warnings",
20165
+ "providerMetadata",
20166
+ "experimental_providerMetadata",
20167
+ "responses"
20168
+ ]) {
20169
+ const value = safeSerializableFieldRead(output, field);
20170
+ if (value !== void 0 && isSerializableOutputValue(value)) {
20171
+ summarized[field] = value;
20172
+ }
20173
+ }
20174
+ const images = safeSerializableFieldRead(output, "images");
20175
+ const image = safeSerializableFieldRead(output, "image");
20176
+ const generatedFiles = Array.isArray(images) && images.length > 0 ? images : image !== void 0 ? [image] : [];
20177
+ const loggedOutput = normalizeAISDKLoggedOutput(
20178
+ omit(summarized, denyOutputPaths)
20179
+ );
20180
+ if (generatedFiles.length > 0) {
20181
+ loggedOutput.images = generatedFiles.map(
20182
+ (file, index) => convertAISDKGeneratedFileToAttachment(file, index)
20183
+ );
20184
+ }
20185
+ return loggedOutput;
20186
+ }
20187
+ function convertAISDKGeneratedFileToAttachment(file, index) {
20188
+ if (!file || typeof file !== "object") {
20189
+ return file;
20190
+ }
20191
+ const generatedFile = file;
20192
+ const generatedMediaType = safeSerializableFieldRead(
20193
+ generatedFile,
20194
+ "mediaType"
20195
+ );
20196
+ const mediaType = typeof generatedMediaType === "string" ? generatedMediaType : "application/octet-stream";
20197
+ const data = safeSerializableFieldRead(generatedFile, "base64") ?? safeSerializableFieldRead(generatedFile, "uint8Array");
20198
+ const blob = convertDataToBlob(data, mediaType);
20199
+ if (blob) {
20200
+ return new Attachment({
20201
+ data: blob,
20202
+ filename: `generated_image_${index}.${getExtensionFromMediaType(mediaType)}`,
20203
+ contentType: mediaType
20204
+ });
20205
+ }
20206
+ return file;
20207
+ }
19777
20208
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
19778
20209
  if (!output || typeof output !== "object") {
19779
20210
  return output;
@@ -20274,118 +20705,22 @@ var claudeAgentSDKChannels = defineChannels(
20274
20705
  var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
20275
20706
 
20276
20707
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
20277
- var LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED = /* @__PURE__ */ Symbol.for(
20278
- "braintrust.claude_agent_sdk.local_tool_context_async_iterator_patched"
20279
- );
20280
- function createLocalToolContextStore() {
20281
- const maybeIsoWithAsyncLocalStorage = isomorph_default;
20282
- if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
20283
- return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
20284
- }
20285
- let currentStore;
20286
- return {
20287
- enterWith(store) {
20288
- currentStore = store;
20289
- },
20290
- getStore() {
20291
- return currentStore;
20292
- },
20293
- run(store, callback) {
20294
- const previousStore = currentStore;
20295
- currentStore = store;
20296
- try {
20297
- return callback();
20298
- } finally {
20299
- currentStore = previousStore;
20300
- }
20301
- }
20302
- };
20303
- }
20304
- var localToolContextStore = createLocalToolContextStore();
20305
- var fallbackLocalToolParentResolver;
20306
- function createClaudeLocalToolContext() {
20307
- return {};
20308
- }
20309
- function runWithClaudeLocalToolContext(callback, context) {
20310
- return localToolContextStore.run(
20311
- context ?? createClaudeLocalToolContext(),
20312
- callback
20313
- );
20314
- }
20315
- function ensureClaudeLocalToolContext() {
20316
- const existing = localToolContextStore.getStore();
20317
- if (existing) {
20318
- return existing;
20319
- }
20320
- const created = {};
20321
- localToolContextStore.enterWith(created);
20322
- return created;
20323
- }
20324
- function setClaudeLocalToolParentResolver(resolver) {
20325
- fallbackLocalToolParentResolver = resolver;
20326
- const context = ensureClaudeLocalToolContext();
20327
- if (!context) {
20328
- return;
20329
- }
20330
- context.resolveLocalToolParent = resolver;
20331
- }
20332
- function getClaudeLocalToolParentResolver() {
20333
- return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
20708
+ var localToolContextStore = isomorph_default.newAsyncLocalStorage();
20709
+ var localToolParentResolversByToolUseId = /* @__PURE__ */ new Map();
20710
+ function runWithClaudeLocalToolContext(callback, resolver) {
20711
+ return localToolContextStore.run(resolver, callback);
20334
20712
  }
20335
- function isAsyncIterable3(value) {
20336
- return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
20713
+ function registerClaudeLocalToolParentResolver(toolUseId, resolver) {
20714
+ localToolParentResolversByToolUseId.set(toolUseId, resolver);
20337
20715
  }
20338
- function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
20339
- if (!isAsyncIterable3(result) || Object.isFrozen(result) || Object.isSealed(result)) {
20340
- return result;
20341
- }
20342
- const stream = result;
20343
- const originalAsyncIterator = stream[Symbol.asyncIterator];
20344
- if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
20345
- return result;
20716
+ function getClaudeLocalToolParentResolver(toolUseId) {
20717
+ const currentResolver = localToolContextStore.getStore();
20718
+ if (!toolUseId) {
20719
+ return currentResolver;
20346
20720
  }
20347
- const patchedAsyncIterator = function() {
20348
- return runWithClaudeLocalToolContext(() => {
20349
- const iterator = Reflect.apply(originalAsyncIterator, this, []);
20350
- if (!iterator || typeof iterator !== "object") {
20351
- return iterator;
20352
- }
20353
- const patchMethod = (methodName) => {
20354
- const originalMethod = Reflect.get(iterator, methodName);
20355
- if (typeof originalMethod !== "function") {
20356
- return;
20357
- }
20358
- Reflect.set(
20359
- iterator,
20360
- methodName,
20361
- (...args) => runWithClaudeLocalToolContext(
20362
- () => Reflect.apply(
20363
- originalMethod,
20364
- iterator,
20365
- args
20366
- ),
20367
- localToolContext
20368
- )
20369
- );
20370
- };
20371
- patchMethod("next");
20372
- patchMethod("return");
20373
- patchMethod("throw");
20374
- return iterator;
20375
- }, localToolContext);
20376
- };
20377
- Object.defineProperty(
20378
- patchedAsyncIterator,
20379
- LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
20380
- {
20381
- configurable: false,
20382
- enumerable: false,
20383
- value: true,
20384
- writable: false
20385
- }
20386
- );
20387
- Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
20388
- return result;
20721
+ const registeredResolver = localToolParentResolversByToolUseId.get(toolUseId);
20722
+ localToolParentResolversByToolUseId.delete(toolUseId);
20723
+ return currentResolver ?? registeredResolver;
20389
20724
  }
20390
20725
 
20391
20726
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
@@ -20411,7 +20746,7 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
20411
20746
  const metadata = getMetadata();
20412
20747
  const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
20413
20748
  const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
20414
- const localToolParentResolver = getClaudeLocalToolParentResolver();
20749
+ const localToolParentResolver = getClaudeLocalToolParentResolver(toolUseId);
20415
20750
  const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
20416
20751
  const runWithResolvedParent = async () => {
20417
20752
  const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
@@ -20938,6 +21273,7 @@ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToP
20938
21273
  }
20939
21274
  }
20940
21275
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
21276
+ registerClaudeLocalToolParentResolver(toolUseID, resolveParentSpan);
20941
21277
  return {};
20942
21278
  }
20943
21279
  const parsed = parseToolName(input.tool_name);
@@ -21648,7 +21984,7 @@ async function finalizeQuerySpan(state) {
21648
21984
  }
21649
21985
  var ClaudeAgentSDKPlugin = class extends BasePlugin {
21650
21986
  onEnable() {
21651
- this.subscribeToQuery();
21987
+ this.interceptQuery();
21652
21988
  }
21653
21989
  onDisable() {
21654
21990
  for (const unsubscribe of this.unsubscribers) {
@@ -21656,211 +21992,218 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
21656
21992
  }
21657
21993
  this.unsubscribers = [];
21658
21994
  }
21659
- subscribeToQuery() {
21660
- const channel2 = claudeAgentSDKChannels.query.tracingChannel();
21661
- const spans = /* @__PURE__ */ new WeakMap();
21662
- const handlers = {
21663
- start: (event) => {
21664
- const params = event.arguments[0] ?? {};
21665
- const originalPrompt = params.prompt;
21666
- const options = params.options ?? {};
21667
- const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
21668
- let promptStarted = false;
21669
- let capturedPromptMessages;
21670
- let resolvePromptDone;
21671
- const promptDone = new Promise((resolve) => {
21672
- resolvePromptDone = resolve;
21673
- });
21674
- if (promptIsAsyncIterable) {
21675
- capturedPromptMessages = [];
21676
- const promptStream = originalPrompt;
21677
- params.prompt = (async function* () {
21678
- promptStarted = true;
21679
- try {
21680
- for await (const message of promptStream) {
21681
- capturedPromptMessages.push(message);
21682
- yield message;
21683
- }
21684
- } finally {
21685
- resolvePromptDone?.();
21995
+ interceptQuery() {
21996
+ const startQuery = (params) => {
21997
+ const originalPrompt = params.prompt;
21998
+ const options = params.options ?? {};
21999
+ const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
22000
+ let promptStarted = false;
22001
+ let capturedPromptMessages;
22002
+ let resolvePromptDone;
22003
+ const promptDone = new Promise((resolve) => {
22004
+ resolvePromptDone = resolve;
22005
+ });
22006
+ if (promptIsAsyncIterable) {
22007
+ capturedPromptMessages = [];
22008
+ const promptStream = originalPrompt;
22009
+ params.prompt = (async function* () {
22010
+ promptStarted = true;
22011
+ try {
22012
+ for await (const message of promptStream) {
22013
+ capturedPromptMessages.push(message);
22014
+ yield message;
21686
22015
  }
21687
- })();
21688
- }
21689
- const span = startSpan(
21690
- withSpanInstrumentationName(
21691
- {
21692
- name: "Claude Agent",
21693
- spanAttributes: {
21694
- type: "task" /* TASK */
21695
- }
21696
- },
21697
- INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
21698
- )
21699
- );
21700
- const startTime = getCurrentUnixTimestamp();
21701
- try {
21702
- span.log({
21703
- input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
21704
- metadata: filterSerializableOptions(options)
21705
- });
21706
- } catch (error) {
21707
- console.error("Error extracting input for Claude Agent SDK:", error);
21708
- }
21709
- const activeToolSpans = /* @__PURE__ */ new Map();
21710
- const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
21711
- const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
21712
- const subAgentSpans = /* @__PURE__ */ new Map();
21713
- const endedSubAgentSpans = /* @__PURE__ */ new Set();
21714
- const toolUseToParent = /* @__PURE__ */ new Map();
21715
- const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
21716
- const latestRootLlmParentRef = {
21717
- value: void 0
21718
- };
21719
- const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
21720
- const taskIdToToolUseId = /* @__PURE__ */ new Map();
21721
- const promptMessagesByParentKey = /* @__PURE__ */ new Map();
21722
- const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
21723
- const localToolContext = createClaudeLocalToolContext();
21724
- const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
21725
- const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
21726
- const resolveToolUseParentSpan = async (toolUseID, context) => {
21727
- const trackedParentToolUseId = toolUseToParent.get(toolUseID);
21728
- const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
21729
- const parentKey = llmParentKey(parentToolUseId);
21730
- const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
21731
- const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
21732
- if (!activeLlmSpan && !latestLlmParent) {
21733
- await ensureActiveLlmSpanForParentToolUse(
21734
- span,
21735
- activeLlmSpansByParentToolUse,
21736
- subAgentDetailsByToolUseId,
21737
- activeToolSpans,
21738
- subAgentSpans,
21739
- parentToolUseId,
21740
- getCurrentUnixTimestamp()
21741
- );
21742
- }
21743
- if (parentToolUseId) {
21744
- const subAgentSpan = await ensureSubAgentSpan(
21745
- subAgentDetailsByToolUseId,
21746
- span,
21747
- activeToolSpans,
21748
- subAgentSpans,
21749
- parentToolUseId
21750
- );
21751
- return subAgentSpan.export();
22016
+ } finally {
22017
+ resolvePromptDone?.();
21752
22018
  }
21753
- return span.export();
21754
- };
21755
- localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
21756
- setClaudeLocalToolParentResolver(resolveToolUseParentSpan);
21757
- const optionsWithHooks = injectTracingHooks(
21758
- options,
21759
- resolveToolUseParentSpan,
21760
- taskIdToToolUseId,
21761
- toolUseToParent,
21762
- activeToolSpans,
21763
- localToolHookNames,
21764
- skipLocalToolHooks,
21765
- subAgentDetailsByToolUseId,
21766
- subAgentSpans,
21767
- endedSubAgentSpans
21768
- );
21769
- params.options = optionsWithHooks;
21770
- event.arguments[0] = params;
21771
- spans.set(event, {
21772
- activeLlmSpansByParentToolUse,
21773
- activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
21774
- activeToolSpans,
21775
- conversationHistoryByParentKey,
21776
- capturedPromptMessages,
21777
- currentMessageId: void 0,
21778
- currentMessageStartTime: startTime,
21779
- currentMessages: [],
21780
- endedSubAgentSpans,
21781
- finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
21782
- finalResults: [],
21783
- options: optionsWithHooks,
21784
- originalPrompt,
21785
- processing: Promise.resolve(),
21786
- promptDone,
21787
- promptMessagesByParentKey,
21788
- promptStarted: () => promptStarted,
21789
- promptSourcePriorityByParentKey,
21790
- span,
21791
- subAgentDetailsByToolUseId,
21792
- subAgentSpans,
21793
- taskIdToToolUseId,
21794
- latestLlmParentBySubAgentToolUse,
21795
- latestRootLlmParentRef,
21796
- toolUseToParent,
21797
- usageByMessageId: /* @__PURE__ */ new Map(),
21798
- localToolContext
22019
+ })();
22020
+ }
22021
+ const span = startSpan(
22022
+ withSpanInstrumentationName(
22023
+ {
22024
+ name: "Claude Agent",
22025
+ spanAttributes: {
22026
+ type: "task" /* TASK */
22027
+ }
22028
+ },
22029
+ INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
22030
+ )
22031
+ );
22032
+ const startTime = getCurrentUnixTimestamp();
22033
+ try {
22034
+ span.log({
22035
+ input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
22036
+ metadata: filterSerializableOptions(options)
21799
22037
  });
21800
- },
21801
- end: (event) => {
21802
- const state = spans.get(event);
21803
- if (!state) {
21804
- return;
21805
- }
21806
- const eventResult = bindClaudeLocalToolContextToAsyncIterable(
21807
- event.result,
21808
- state.localToolContext
21809
- );
21810
- if (eventResult === void 0) {
21811
- state.span.end();
21812
- spans.delete(event);
21813
- return;
21814
- }
21815
- if (isAsyncIterable(eventResult)) {
21816
- patchStreamIfNeeded(eventResult, {
21817
- onChunk: (message) => {
21818
- maybeTrackToolUseContext(state, message);
21819
- state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
21820
- console.error(
21821
- "Error processing Claude Agent SDK stream chunk:",
21822
- error
21823
- );
21824
- });
21825
- },
21826
- onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
21827
- spans.delete(event);
21828
- }),
21829
- onError: (error) => state.processing.then(() => {
21830
- state.span.log({
21831
- error: error.message
21832
- });
21833
- }).then(() => finalizeQuerySpan(state)).finally(() => {
21834
- spans.delete(event);
21835
- })
21836
- });
21837
- return;
21838
- }
21839
- try {
21840
- state.span.log({ output: eventResult });
21841
- } catch (error) {
21842
- console.error("Error extracting output for Claude Agent SDK:", error);
21843
- } finally {
21844
- state.span.end();
21845
- spans.delete(event);
22038
+ } catch (error) {
22039
+ console.error("Error extracting input for Claude Agent SDK:", error);
22040
+ }
22041
+ const activeToolSpans = /* @__PURE__ */ new Map();
22042
+ const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
22043
+ const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
22044
+ const subAgentSpans = /* @__PURE__ */ new Map();
22045
+ const endedSubAgentSpans = /* @__PURE__ */ new Set();
22046
+ const toolUseToParent = /* @__PURE__ */ new Map();
22047
+ const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
22048
+ const latestRootLlmParentRef = {
22049
+ value: void 0
22050
+ };
22051
+ const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
22052
+ const taskIdToToolUseId = /* @__PURE__ */ new Map();
22053
+ const promptMessagesByParentKey = /* @__PURE__ */ new Map();
22054
+ const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
22055
+ const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
22056
+ const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
22057
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
22058
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
22059
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
22060
+ const parentKey = llmParentKey(parentToolUseId);
22061
+ const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
22062
+ const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
22063
+ if (!activeLlmSpan && !latestLlmParent) {
22064
+ await ensureActiveLlmSpanForParentToolUse(
22065
+ span,
22066
+ activeLlmSpansByParentToolUse,
22067
+ subAgentDetailsByToolUseId,
22068
+ activeToolSpans,
22069
+ subAgentSpans,
22070
+ parentToolUseId,
22071
+ getCurrentUnixTimestamp()
22072
+ );
21846
22073
  }
21847
- },
21848
- error: (event) => {
21849
- const state = spans.get(event);
21850
- if (!state || !event.error) {
21851
- return;
22074
+ if (parentToolUseId) {
22075
+ const subAgentSpan = await ensureSubAgentSpan(
22076
+ subAgentDetailsByToolUseId,
22077
+ span,
22078
+ activeToolSpans,
22079
+ subAgentSpans,
22080
+ parentToolUseId
22081
+ );
22082
+ return subAgentSpan.export();
21852
22083
  }
21853
- state.span.log({
21854
- error: event.error.message
22084
+ return span.export();
22085
+ };
22086
+ const optionsWithHooks = injectTracingHooks(
22087
+ options,
22088
+ resolveToolUseParentSpan,
22089
+ taskIdToToolUseId,
22090
+ toolUseToParent,
22091
+ activeToolSpans,
22092
+ localToolHookNames,
22093
+ skipLocalToolHooks,
22094
+ subAgentDetailsByToolUseId,
22095
+ subAgentSpans,
22096
+ endedSubAgentSpans
22097
+ );
22098
+ params.options = optionsWithHooks;
22099
+ return {
22100
+ activeLlmSpansByParentToolUse,
22101
+ activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
22102
+ activeToolSpans,
22103
+ conversationHistoryByParentKey,
22104
+ capturedPromptMessages,
22105
+ currentMessageId: void 0,
22106
+ currentMessageStartTime: startTime,
22107
+ currentMessages: [],
22108
+ endedSubAgentSpans,
22109
+ finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
22110
+ finalResults: [],
22111
+ options: optionsWithHooks,
22112
+ originalPrompt,
22113
+ processing: Promise.resolve(),
22114
+ promptDone,
22115
+ promptMessagesByParentKey,
22116
+ promptStarted: () => promptStarted,
22117
+ promptSourcePriorityByParentKey,
22118
+ span,
22119
+ subAgentDetailsByToolUseId,
22120
+ subAgentSpans,
22121
+ taskIdToToolUseId,
22122
+ latestLlmParentBySubAgentToolUse,
22123
+ latestRootLlmParentRef,
22124
+ toolUseToParent,
22125
+ usageByMessageId: /* @__PURE__ */ new Map(),
22126
+ localToolParentResolver: resolveToolUseParentSpan
22127
+ };
22128
+ };
22129
+ const finishQuery = (state, result) => {
22130
+ if (isAsyncIterable(result)) {
22131
+ patchStreamIfNeeded(result, {
22132
+ aroundNext: (callback) => runWithClaudeLocalToolContext(
22133
+ callback,
22134
+ state.localToolParentResolver
22135
+ ),
22136
+ onChunk: (message) => {
22137
+ maybeTrackToolUseContext(state, message);
22138
+ state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
22139
+ console.error(
22140
+ "Error processing Claude Agent SDK stream chunk:",
22141
+ error
22142
+ );
22143
+ });
22144
+ },
22145
+ onComplete: () => state.processing.then(() => finalizeQuerySpan(state)),
22146
+ onError: (error) => state.processing.then(() => {
22147
+ state.span.log({ error: error.message });
22148
+ }).then(() => finalizeQuerySpan(state))
21855
22149
  });
22150
+ return;
22151
+ }
22152
+ try {
22153
+ state.span.log({ output: result });
22154
+ } catch (error) {
22155
+ console.error("Error extracting output for Claude Agent SDK:", error);
22156
+ } finally {
21856
22157
  state.span.end();
21857
- spans.delete(event);
21858
22158
  }
21859
22159
  };
21860
- channel2.subscribe(handlers);
21861
- this.unsubscribers.push(() => {
21862
- channel2.unsubscribe(handlers);
21863
- });
22160
+ this.unsubscribers.push(
22161
+ claudeAgentSDKChannels.query.intercept((target, thisArg, args) => {
22162
+ let state;
22163
+ try {
22164
+ args[0] ??= {};
22165
+ state = startQuery(args[0]);
22166
+ } catch (error) {
22167
+ debugLogger.error(
22168
+ "Error starting Claude Agent SDK instrumentation:",
22169
+ error
22170
+ );
22171
+ }
22172
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
22173
+ try {
22174
+ const result = state ? runWithClaudeLocalToolContext(
22175
+ invokeTarget,
22176
+ state.localToolParentResolver
22177
+ ) : invokeTarget();
22178
+ if (state) {
22179
+ try {
22180
+ finishQuery(state, result);
22181
+ } catch (error) {
22182
+ debugLogger.error(
22183
+ "Error finalizing Claude Agent SDK instrumentation:",
22184
+ error
22185
+ );
22186
+ }
22187
+ }
22188
+ return result;
22189
+ } catch (error) {
22190
+ if (state) {
22191
+ try {
22192
+ state.span.log({
22193
+ error: error instanceof Error ? error.message : String(error)
22194
+ });
22195
+ state.span.end();
22196
+ } catch (instrumentationError) {
22197
+ debugLogger.error(
22198
+ "Error handling Claude Agent SDK instrumentation failure:",
22199
+ instrumentationError
22200
+ );
22201
+ }
22202
+ }
22203
+ throw error;
22204
+ }
22205
+ })
22206
+ );
21864
22207
  }
21865
22208
  };
21866
22209
 
@@ -25974,7 +26317,7 @@ function patchOpenRouterCallModelResult(args) {
25974
26317
  span,
25975
26318
  () => originalMethod.apply(resultLike, args2)
25976
26319
  );
25977
- if (!isAsyncIterable4(stream)) {
26320
+ if (!isAsyncIterable3(stream)) {
25978
26321
  return stream;
25979
26322
  }
25980
26323
  return wrapAsyncIterableWithSpan({
@@ -26169,7 +26512,7 @@ function wrapAsyncIterableWithSpan(args) {
26169
26512
  }
26170
26513
  };
26171
26514
  }
26172
- function isAsyncIterable4(value) {
26515
+ function isAsyncIterable3(value) {
26173
26516
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
26174
26517
  }
26175
26518
  function normalizeError(error) {
@@ -27047,7 +27390,7 @@ function patchOpenRouterCallModelResult2(args) {
27047
27390
  span,
27048
27391
  () => originalMethod.apply(resultLike, args2)
27049
27392
  );
27050
- if (!isAsyncIterable5(stream)) {
27393
+ if (!isAsyncIterable4(stream)) {
27051
27394
  return stream;
27052
27395
  }
27053
27396
  return wrapAsyncIterableWithSpan2({
@@ -27242,7 +27585,7 @@ function wrapAsyncIterableWithSpan2(args) {
27242
27585
  }
27243
27586
  };
27244
27587
  }
27245
- function isAsyncIterable5(value) {
27588
+ function isAsyncIterable4(value) {
27246
27589
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
27247
27590
  }
27248
27591
  function normalizeError2(error) {
@@ -33234,12 +33577,14 @@ function getMetricsFromResponse(response) {
33234
33577
  continue;
33235
33578
  }
33236
33579
  const inputTokenDetails = usageMetadata.input_token_details;
33580
+ const outputTokenDetails = usageMetadata.output_token_details;
33237
33581
  return normalizeTokenMetrics({
33238
33582
  total_tokens: usageMetadata.total_tokens,
33239
33583
  prompt_tokens: usageMetadata.input_tokens,
33240
33584
  completion_tokens: usageMetadata.output_tokens,
33241
33585
  prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
33242
- prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
33586
+ prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
33587
+ completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
33243
33588
  });
33244
33589
  }
33245
33590
  const llmOutput = response.llmOutput || {};
@@ -33826,6 +34171,9 @@ var piCodingAgentChannels = defineChannels(
33826
34171
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
33827
34172
  var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
33828
34173
  var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
34174
+ var PI_TOOL_EXECUTE_WRAPPED = /* @__PURE__ */ Symbol.for(
34175
+ "braintrust.pi_coding_agent.tool_execute_wrapped"
34176
+ );
33829
34177
  var piPromptContextStore;
33830
34178
  var PiCodingAgentPlugin = class extends BasePlugin {
33831
34179
  activePromptStates = /* @__PURE__ */ new Set();
@@ -33906,6 +34254,7 @@ function startPiPromptRun(event, onFinalize) {
33906
34254
  return void 0;
33907
34255
  }
33908
34256
  installPiAgentInstrumentation(agent);
34257
+ wrapPiToolExecutors(agent.state?.tools);
33909
34258
  const metadata = {
33910
34259
  ...extractSessionMetadata(session),
33911
34260
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -34002,6 +34351,7 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
34002
34351
  if (!state || state.agent !== agent || state.finalized) {
34003
34352
  return invokeOriginal();
34004
34353
  }
34354
+ wrapPiToolExecutors(context.tools);
34005
34355
  const llmState = await startPiLlmSpan(state, model, context, options);
34006
34356
  try {
34007
34357
  const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
@@ -34012,6 +34362,33 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
34012
34362
  }
34013
34363
  };
34014
34364
  }
34365
+ function wrapPiToolExecutors(tools) {
34366
+ if (!tools) {
34367
+ return;
34368
+ }
34369
+ for (const tool of tools) {
34370
+ try {
34371
+ const execute = tool.execute;
34372
+ if (typeof execute !== "function" || execute[PI_TOOL_EXECUTE_WRAPPED]) {
34373
+ continue;
34374
+ }
34375
+ const wrappedExecute = function(...args) {
34376
+ return runWithAutoInstrumentationAllowed(
34377
+ () => Reflect.apply(execute, this, args)
34378
+ );
34379
+ };
34380
+ Object.defineProperty(wrappedExecute, PI_TOOL_EXECUTE_WRAPPED, {
34381
+ configurable: false,
34382
+ enumerable: false,
34383
+ value: true,
34384
+ writable: false
34385
+ });
34386
+ tool.execute = wrappedExecute;
34387
+ } catch (error) {
34388
+ logInstrumentationError4("Pi Coding Agent tool wrapping", error);
34389
+ }
34390
+ }
34391
+ }
34015
34392
  async function startPiLlmSpan(state, model, context, options) {
34016
34393
  const metadata = {
34017
34394
  ...extractModelMetadata2(model),
@@ -34183,35 +34560,26 @@ async function startPiToolSpan(state, event) {
34183
34560
  if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
34184
34561
  return;
34185
34562
  }
34186
- const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
34187
34563
  const metadata = {
34188
34564
  "gen_ai.tool.call.id": event.toolCallId,
34189
34565
  "gen_ai.tool.name": event.toolName,
34190
34566
  "pi_coding_agent.tool.name": event.toolName
34191
34567
  };
34192
- try {
34193
- const span = startSpan(
34194
- withSpanInstrumentationName(
34195
- {
34196
- event: {
34197
- input: event.args,
34198
- metadata
34199
- },
34200
- name: event.toolName || "tool",
34201
- parent: await state.span.export(),
34202
- spanAttributes: { type: "tool" /* TOOL */ }
34568
+ const span = startSpan(
34569
+ withSpanInstrumentationName(
34570
+ {
34571
+ event: {
34572
+ input: event.args,
34573
+ metadata
34203
34574
  },
34204
- INSTRUMENTATION_NAMES.PI_CODING_AGENT
34205
- )
34206
- );
34207
- state.activeToolSpans.set(event.toolCallId, {
34208
- restoreAutoInstrumentation,
34209
- span
34210
- });
34211
- } catch (error) {
34212
- restoreAutoInstrumentation();
34213
- throw error;
34214
- }
34575
+ name: event.toolName || "tool",
34576
+ parent: await state.span.export(),
34577
+ spanAttributes: { type: "tool" /* TOOL */ }
34578
+ },
34579
+ INSTRUMENTATION_NAMES.PI_CODING_AGENT
34580
+ )
34581
+ );
34582
+ state.activeToolSpans.set(event.toolCallId, { span });
34215
34583
  }
34216
34584
  function finishPiToolSpan(state, event) {
34217
34585
  const toolState = state.activeToolSpans.get(event.toolCallId);
@@ -34232,11 +34600,7 @@ function finishPiToolSpan(state, event) {
34232
34600
  output: event.result
34233
34601
  });
34234
34602
  } finally {
34235
- try {
34236
- toolState.span.end();
34237
- } finally {
34238
- toolState.restoreAutoInstrumentation?.();
34239
- }
34603
+ toolState.span.end();
34240
34604
  }
34241
34605
  }
34242
34606
  function finishPiPromptRun(state, error) {
@@ -34286,10 +34650,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
34286
34650
  ...cleanMetrics5(llmState.metrics),
34287
34651
  ...buildDurationMetrics3(llmState.startTime)
34288
34652
  };
34289
- const usageMetrics = extractUsageMetrics2(message?.usage);
34290
- if (Object.keys(usageMetrics).length > 0) {
34653
+ const usageMetrics2 = extractUsageMetrics2(message?.usage);
34654
+ if (Object.keys(usageMetrics2).length > 0) {
34291
34655
  promptState.collectedLlmUsageMetrics = true;
34292
- addMetrics(promptState.metrics, usageMetrics);
34656
+ addMetrics(promptState.metrics, usageMetrics2);
34293
34657
  }
34294
34658
  try {
34295
34659
  safeLog4(llmState.span, {
@@ -34307,14 +34671,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
34307
34671
  }
34308
34672
  function finishOpenToolSpans(state, error) {
34309
34673
  for (const [, toolState] of state.activeToolSpans) {
34310
- try {
34311
- safeLog4(toolState.span, {
34312
- error: error ? toLoggedError(error) : "Pi tool did not complete"
34313
- });
34314
- toolState.span.end();
34315
- } finally {
34316
- toolState.restoreAutoInstrumentation?.();
34317
- }
34674
+ safeLog4(toolState.span, {
34675
+ error: error ? toLoggedError(error) : "Pi tool did not complete"
34676
+ });
34677
+ toolState.span.end();
34318
34678
  }
34319
34679
  state.activeToolSpans.clear();
34320
34680
  }
@@ -34633,12 +34993,12 @@ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
34633
34993
  var StrandsAgentSDKPlugin = class extends BasePlugin {
34634
34994
  activeChildParents = /* @__PURE__ */ new WeakMap();
34635
34995
  onEnable() {
34636
- this.subscribeToAgentStream();
34637
- this.subscribeToMultiAgentStream(
34996
+ this.interceptAgentStream();
34997
+ this.interceptMultiAgentStream(
34638
34998
  strandsAgentSDKChannels.graphStream,
34639
34999
  "Graph.stream"
34640
35000
  );
34641
- this.subscribeToMultiAgentStream(
35001
+ this.interceptMultiAgentStream(
34642
35002
  strandsAgentSDKChannels.swarmStream,
34643
35003
  "Swarm.stream"
34644
35004
  );
@@ -34649,122 +35009,92 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
34649
35009
  }
34650
35010
  this.unsubscribers = [];
34651
35011
  }
34652
- subscribeToAgentStream() {
34653
- const channel2 = strandsAgentSDKChannels.agentStream.tracingChannel();
34654
- const states = /* @__PURE__ */ new WeakMap();
34655
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
34656
- const handlers = {
34657
- start: (event) => {
34658
- const state = startAgentStream(event, this.activeChildParents);
34659
- if (state) {
34660
- states.set(event, state);
34661
- }
34662
- },
34663
- end: (event) => {
34664
- const state = states.get(event);
34665
- if (!state) {
34666
- return;
34667
- }
34668
- const result = event.result;
34669
- if (isAsyncIterable(result)) {
34670
- patchStreamIfNeeded(result, {
34671
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
34672
- onChunk: (chunk) => handleAgentStreamEvent(state, chunk),
34673
- onComplete: () => {
34674
- finalizeAgentStream(state);
34675
- states.delete(event);
34676
- },
34677
- onError: (error) => {
34678
- finalizeAgentStream(state, error);
34679
- states.delete(event);
34680
- }
34681
- });
34682
- return;
34683
- }
34684
- finalizeAgentStream(state, void 0, result);
34685
- states.delete(event);
34686
- },
34687
- error: (event) => {
34688
- const state = states.get(event);
34689
- if (!state || !event.error) {
34690
- return;
34691
- }
34692
- finalizeAgentStream(state, event.error);
34693
- states.delete(event);
34694
- }
34695
- };
34696
- channel2.subscribe(handlers);
34697
- this.unsubscribers.push(() => {
34698
- unbindAutoInstrumentationSuppression?.();
34699
- channel2.unsubscribe(handlers);
34700
- });
35012
+ interceptAgentStream() {
35013
+ this.unsubscribers.push(
35014
+ strandsAgentSDKChannels.agentStream.intercept(
35015
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
35016
+ finalize: finalizeAgentStream,
35017
+ handleChunk: handleAgentStreamEvent,
35018
+ invoke: () => Reflect.apply(target, thisArg, args),
35019
+ name: "Strands Agent SDK",
35020
+ start: () => startAgentStream(
35021
+ args[0],
35022
+ extractAgent(additional.agent, thisArg),
35023
+ this.activeChildParents
35024
+ )
35025
+ })
35026
+ )
35027
+ );
34701
35028
  }
34702
- subscribeToMultiAgentStream(channel2, operation) {
34703
- const tracingChannel = channel2.tracingChannel();
34704
- const states = /* @__PURE__ */ new WeakMap();
34705
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(tracingChannel);
34706
- const handlers = {
34707
- start: (event) => {
34708
- const state = startMultiAgentStream(
34709
- event,
34710
- operation,
34711
- this.activeChildParents
34712
- );
34713
- if (state) {
34714
- states.set(event, state);
34715
- }
34716
- },
34717
- end: (event) => {
34718
- const state = states.get(event);
34719
- if (!state) {
34720
- return;
34721
- }
34722
- const result = event.result;
34723
- if (isAsyncIterable(result)) {
34724
- patchStreamIfNeeded(result, {
34725
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
34726
- onChunk: (chunk) => handleMultiAgentStreamEvent(
34727
- state,
34728
- chunk,
34729
- this.activeChildParents
34730
- ),
34731
- onComplete: () => {
34732
- finalizeMultiAgentStream(state, this.activeChildParents);
34733
- states.delete(event);
34734
- },
34735
- onError: (error) => {
34736
- finalizeMultiAgentStream(state, this.activeChildParents, error);
34737
- states.delete(event);
34738
- }
34739
- });
34740
- return;
34741
- }
34742
- finalizeMultiAgentStream(
34743
- state,
34744
- this.activeChildParents,
34745
- void 0,
34746
- result
35029
+ interceptMultiAgentStream(channel2, operation) {
35030
+ this.unsubscribers.push(
35031
+ channel2.intercept(
35032
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
35033
+ finalize: (state, error, output) => finalizeMultiAgentStream(
35034
+ state,
35035
+ this.activeChildParents,
35036
+ error,
35037
+ output
35038
+ ),
35039
+ handleChunk: (state, chunk) => handleMultiAgentStreamEvent(state, chunk, this.activeChildParents),
35040
+ invoke: () => Reflect.apply(target, thisArg, args),
35041
+ name: "Strands multi-agent",
35042
+ start: () => startMultiAgentStream(
35043
+ args[0],
35044
+ extractOrchestrator(additional.orchestrator, thisArg),
35045
+ operation,
35046
+ this.activeChildParents
35047
+ )
35048
+ })
35049
+ )
35050
+ );
35051
+ }
35052
+ };
35053
+ function instrumentStrandsStreamInvocation(options) {
35054
+ let state;
35055
+ try {
35056
+ state = options.start();
35057
+ } catch (error) {
35058
+ debugLogger.error(`Error starting ${options.name} instrumentation:`, error);
35059
+ }
35060
+ let result;
35061
+ try {
35062
+ result = runWithAutoInstrumentationSuppressed(options.invoke);
35063
+ } catch (error) {
35064
+ if (state) {
35065
+ try {
35066
+ options.finalize(state, error);
35067
+ } catch (instrumentationError) {
35068
+ debugLogger.error(
35069
+ `Error handling ${options.name} instrumentation failure:`,
35070
+ instrumentationError
34747
35071
  );
34748
- states.delete(event);
34749
- },
34750
- error: (event) => {
34751
- const state = states.get(event);
34752
- if (!state || !event.error) {
34753
- return;
34754
- }
34755
- finalizeMultiAgentStream(state, this.activeChildParents, event.error);
34756
- states.delete(event);
34757
35072
  }
34758
- };
34759
- tracingChannel.subscribe(handlers);
34760
- this.unsubscribers.push(() => {
34761
- unbindAutoInstrumentationSuppression?.();
34762
- tracingChannel.unsubscribe(handlers);
34763
- });
35073
+ }
35074
+ throw error;
34764
35075
  }
34765
- };
34766
- function startAgentStream(event, activeChildParents) {
34767
- const agent = extractAgent(event);
35076
+ if (state) {
35077
+ try {
35078
+ if (isAsyncIterable(result)) {
35079
+ patchStreamIfNeeded(result, {
35080
+ aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
35081
+ onChunk: (chunk) => options.handleChunk(state, chunk),
35082
+ onComplete: () => options.finalize(state),
35083
+ onError: (error) => options.finalize(state, error)
35084
+ });
35085
+ } else {
35086
+ options.finalize(state, void 0, result);
35087
+ }
35088
+ } catch (error) {
35089
+ debugLogger.error(
35090
+ `Error finalizing ${options.name} instrumentation:`,
35091
+ error
35092
+ );
35093
+ }
35094
+ }
35095
+ return result;
35096
+ }
35097
+ function startAgentStream(input, agent, activeChildParents) {
34768
35098
  const model = agent?.model;
34769
35099
  const metadata = {
34770
35100
  ...extractAgentMetadata2(agent),
@@ -34774,17 +35104,14 @@ function startAgentStream(event, activeChildParents) {
34774
35104
  };
34775
35105
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
34776
35106
  const attachmentCache = createStrandsAttachmentCache();
34777
- const input = processStrandsInputAttachments(
34778
- event.arguments[0],
34779
- attachmentCache
34780
- );
35107
+ const processedInput = processStrandsInputAttachments(input, attachmentCache);
34781
35108
  const span = parentSpan ? withCurrent(
34782
35109
  parentSpan,
34783
35110
  () => startSpan(
34784
35111
  withSpanInstrumentationName(
34785
35112
  {
34786
35113
  event: {
34787
- input,
35114
+ input: processedInput,
34788
35115
  metadata
34789
35116
  },
34790
35117
  name: formatAgentSpanName(agent),
@@ -34797,7 +35124,7 @@ function startAgentStream(event, activeChildParents) {
34797
35124
  withSpanInstrumentationName(
34798
35125
  {
34799
35126
  event: {
34800
- input,
35127
+ input: processedInput,
34801
35128
  metadata
34802
35129
  },
34803
35130
  name: formatAgentSpanName(agent),
@@ -34815,22 +35142,21 @@ function startAgentStream(event, activeChildParents) {
34815
35142
  startTime: getCurrentUnixTimestamp()
34816
35143
  };
34817
35144
  }
34818
- function startMultiAgentStream(event, operation, activeChildParents) {
34819
- const orchestrator = extractOrchestrator(event);
35145
+ function startMultiAgentStream(input, orchestrator, operation, activeChildParents) {
34820
35146
  const metadata = {
34821
35147
  "strands.operation": operation,
34822
35148
  provider: "strands",
34823
35149
  ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
34824
35150
  };
34825
35151
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
34826
- const input = processStrandsInputAttachments(event.arguments[0]);
35152
+ const processedInput = processStrandsInputAttachments(input);
34827
35153
  const span = parentSpan ? withCurrent(
34828
35154
  parentSpan,
34829
35155
  () => startSpan(
34830
35156
  withSpanInstrumentationName(
34831
35157
  {
34832
35158
  event: {
34833
- input,
35159
+ input: processedInput,
34834
35160
  metadata
34835
35161
  },
34836
35162
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -34843,7 +35169,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
34843
35169
  withSpanInstrumentationName(
34844
35170
  {
34845
35171
  event: {
34846
- input,
35172
+ input: processedInput,
34847
35173
  metadata
34848
35174
  },
34849
35175
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -35214,12 +35540,12 @@ function finalizeMultiAgentStream(state, activeChildParents, error, output) {
35214
35540
  });
35215
35541
  state.span.end();
35216
35542
  }
35217
- function extractAgent(event) {
35218
- const candidate = event.agent ?? event.self;
35543
+ function extractAgent(agent, self) {
35544
+ const candidate = agent ?? self;
35219
35545
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
35220
35546
  }
35221
- function extractOrchestrator(event) {
35222
- const candidate = event.orchestrator ?? event.self;
35547
+ function extractOrchestrator(orchestrator, self) {
35548
+ const candidate = orchestrator ?? self;
35223
35549
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
35224
35550
  }
35225
35551
  function extractAgentMetadata2(agent) {
@@ -37735,6 +38061,13 @@ function wrapAISDK(aiSDK, options = {}) {
37735
38061
  switch (prop) {
37736
38062
  case "generateText":
37737
38063
  return wrapGenerateText(typedAISDK.generateText, options, typedAISDK);
38064
+ case "generateImage":
38065
+ case "experimental_generateImage":
38066
+ return typeof original === "function" ? wrapGenerateImage(
38067
+ original,
38068
+ options,
38069
+ typedAISDK
38070
+ ) : original;
37738
38071
  case "streamText":
37739
38072
  return wrapStreamText(typedAISDK.streamText, options, typedAISDK);
37740
38073
  case "generateObject":
@@ -37971,6 +38304,32 @@ var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
37971
38304
  options
37972
38305
  );
37973
38306
  };
38307
+ var wrapGenerateImage = (generateImage, options = {}, aiSDK) => {
38308
+ return makeGenerateImageWrapper(generateImage, { aiSDK }, options);
38309
+ };
38310
+ var makeGenerateImageWrapper = (generateImage, contextOptions = {}, options = {}) => {
38311
+ const wrapper = async function(allParams) {
38312
+ const { span_info, ...params } = allParams;
38313
+ const tracedParams = { ...params };
38314
+ return aiSDKChannels.generateImage.tracePromise(
38315
+ () => generateImage(tracedParams),
38316
+ createAISDKChannelContext(tracedParams, {
38317
+ aiSDK: contextOptions.aiSDK,
38318
+ denyOutputPaths: options.denyOutputPaths,
38319
+ self: contextOptions.self,
38320
+ span_info: mergeSpanInfo(span_info, {
38321
+ name: "generateImage",
38322
+ spanType: contextOptions.spanType
38323
+ })
38324
+ })
38325
+ );
38326
+ };
38327
+ Object.defineProperty(wrapper, "name", {
38328
+ value: "generateImage",
38329
+ writable: false
38330
+ });
38331
+ return wrapper;
38332
+ };
37974
38333
  var makeEmbedWrapper = (channel2, name, embed, contextOptions = {}, options = {}) => {
37975
38334
  const wrapper = async function(allParams) {
37976
38335
  const { span_info, ...params } = allParams;
@@ -38721,7 +39080,7 @@ function braintrustEveHook(options) {
38721
39080
  }
38722
39081
  };
38723
39082
  }
38724
- function braintrustEveInstrumentation(options) {
39083
+ function createLegacyEveInstrumentation(options) {
38725
39084
  const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
38726
39085
  return {
38727
39086
  events: {
@@ -40109,8 +40468,10 @@ function capturedModelInput(modelInput) {
40109
40468
  const value = [];
40110
40469
  if (typeof instructions === "string") {
40111
40470
  value.push({ content: instructions, role: "system" });
40112
- } else if (instructions) {
40471
+ } else if (Array.isArray(instructions)) {
40113
40472
  value.push(...instructions.map(capturedEveModelMessage));
40473
+ } else if (instructions) {
40474
+ value.push(capturedEveModelMessage(instructions));
40114
40475
  }
40115
40476
  value.push(...messages.map(capturedEveModelMessage));
40116
40477
  try {
@@ -40354,6 +40715,464 @@ async function deterministicEveId(...parts) {
40354
40715
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
40355
40716
  }
40356
40717
 
40718
+ // src/instrumentation/plugins/eve-provider.ts
40719
+ var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
40720
+ function createEveInstrumentationProvider(options = {}) {
40721
+ const bridge = new EveProviderBridge(options.metadata);
40722
+ return {
40723
+ capture: "content",
40724
+ events: {
40725
+ "action.completed": (event, context) => bridge.handleActionTerminal(event, context),
40726
+ "action.failed": (event, context) => bridge.handleActionTerminal(event, context),
40727
+ "action.started": (event, context) => bridge.handleActionStarted(event, context),
40728
+ "model.call.completed": (event, context) => bridge.handleModelTerminal(event, context),
40729
+ "model.call.failed": (event, context) => bridge.handleModelTerminal(event, context),
40730
+ "model.call.started": (event, context) => bridge.handleModelStarted(event, context),
40731
+ "step.attempt.completed": (event) => bridge.handleStepAttemptTerminal(event),
40732
+ "step.attempt.failed": (event) => bridge.handleStepAttemptTerminal(event),
40733
+ "turn.cancelled": (event, context) => bridge.handleTurnTerminal(event, context),
40734
+ "turn.completed": (event, context) => bridge.handleTurnTerminal(event, context),
40735
+ "turn.failed": (event, context) => bridge.handleTurnTerminal(event, context),
40736
+ "turn.started": (event, context) => bridge.handleTurnStarted(event, context)
40737
+ },
40738
+ flush,
40739
+ setup: options.setup
40740
+ };
40741
+ }
40742
+ var EveProviderBridge = class {
40743
+ constructor(metadata) {
40744
+ this.metadata = metadata;
40745
+ }
40746
+ metadata;
40747
+ activeActions = /* @__PURE__ */ new Map();
40748
+ activeModels = /* @__PURE__ */ new Map();
40749
+ modelsByAttempt = /* @__PURE__ */ new Map();
40750
+ settledOperations = new LRUCache({
40751
+ max: MAX_EVE_PROVIDER_CACHE_ENTRIES
40752
+ });
40753
+ turns = new LRUCache({
40754
+ max: MAX_EVE_PROVIDER_CACHE_ENTRIES
40755
+ });
40756
+ async handleTurnStarted(event, context) {
40757
+ await this.contain("turn start", async () => {
40758
+ if (this.settledOperations.has(event.idempotencyKey)) {
40759
+ context.state.set({ skip: true });
40760
+ return;
40761
+ }
40762
+ const { rowId, spanId } = await generateEveIds(
40763
+ "turn",
40764
+ event.idempotencyKey
40765
+ );
40766
+ const key = turnKey3(event.sessionId, event.turnId);
40767
+ const stored = storedSpan(context);
40768
+ if (stored && "exported" in stored && stored.rootSpanId) {
40769
+ this.turns.set(key, { rootSpanId: stored.rootSpanId, spanId });
40770
+ return;
40771
+ }
40772
+ let rootSpanId = spanId;
40773
+ let parentSpanId;
40774
+ if (event.parentLineage) {
40775
+ const parentTurnKey = turnKey3(
40776
+ event.parentLineage.sessionId,
40777
+ event.parentLineage.turnId
40778
+ );
40779
+ const parentTurn = this.turns.get(parentTurnKey);
40780
+ rootSpanId = parentTurn?.rootSpanId ?? // Eve propagates the root session through every nested subagent. Use
40781
+ // it instead of the immediate parent session when no ancestor ran
40782
+ // in-process.
40783
+ (await generateEveIds(
40784
+ "turn",
40785
+ turnIdempotencyKey(
40786
+ event.rootSessionId,
40787
+ event.parentLineage.turnId
40788
+ )
40789
+ )).spanId;
40790
+ parentSpanId = (await generateEveIds(
40791
+ "subagent",
40792
+ actionIdempotencyKey(
40793
+ event.parentLineage.sessionId,
40794
+ event.parentLineage.turnId,
40795
+ event.parentLineage.callId
40796
+ )
40797
+ )).spanId;
40798
+ }
40799
+ const metadata = this.spanMetadata(event.sessionId);
40800
+ const span = await this.startSpan(
40801
+ context,
40802
+ {
40803
+ event: { id: rowId, metadata },
40804
+ name: "eve.turn",
40805
+ parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
40806
+ spanAttributes: { type: "task" /* TASK */ },
40807
+ spanId
40808
+ },
40809
+ rootSpanId
40810
+ );
40811
+ span?.log({ metadata });
40812
+ this.turns.set(key, {
40813
+ rootSpanId,
40814
+ spanId
40815
+ });
40816
+ });
40817
+ }
40818
+ async handleTurnTerminal(event, context) {
40819
+ await this.contain("turn terminal", async () => {
40820
+ if (this.settledOperations.has(event.idempotencyKey)) {
40821
+ context.state.set(void 0);
40822
+ return;
40823
+ }
40824
+ const error = event.type === "turn.failed" ? event.error : void 0;
40825
+ this.drainActionsForTurn(event.sessionId, event.turnId, error);
40826
+ const stored = storedSpan(context);
40827
+ if (stored && "exported" in stored) {
40828
+ updateSpan({
40829
+ exported: stored.exported,
40830
+ ...error !== void 0 ? { error } : {},
40831
+ metrics: { end: Date.now() / 1e3 }
40832
+ });
40833
+ }
40834
+ this.settledOperations.set(event.idempotencyKey, true);
40835
+ context.state.set(void 0);
40836
+ this.turns.delete(turnKey3(event.sessionId, event.turnId));
40837
+ });
40838
+ }
40839
+ async handleModelStarted(event, context) {
40840
+ await this.contain("model start", async () => {
40841
+ if (this.settledOperations.has(event.idempotencyKey)) {
40842
+ context.state.set({ skip: true });
40843
+ return;
40844
+ }
40845
+ const parent = await this.parentForScope(event.scope);
40846
+ const { rowId, spanId } = await generateEveIds(
40847
+ "step",
40848
+ event.idempotencyKey
40849
+ );
40850
+ const input = event.input ? capturedModelInput(event.input) : void 0;
40851
+ const metadata = {
40852
+ ...this.spanMetadata(event.scope.sessionId),
40853
+ model: event.model.modelId,
40854
+ provider: event.model.provider
40855
+ };
40856
+ const span = await this.startSpan(context, {
40857
+ event: {
40858
+ id: rowId,
40859
+ ...input !== void 0 ? { input } : {},
40860
+ metadata
40861
+ },
40862
+ name: "eve.step",
40863
+ parentSpanIds: parent,
40864
+ spanAttributes: { type: "llm" /* LLM */ },
40865
+ spanId
40866
+ });
40867
+ if (!span) return;
40868
+ span.log({ ...input !== void 0 ? { input } : {}, metadata });
40869
+ this.activeModels.set(event.idempotencyKey, {
40870
+ span,
40871
+ turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
40872
+ });
40873
+ const keys = this.modelsByAttempt.get(event.scope.attemptId) ?? /* @__PURE__ */ new Set();
40874
+ keys.add(event.idempotencyKey);
40875
+ this.modelsByAttempt.set(event.scope.attemptId, keys);
40876
+ });
40877
+ }
40878
+ async handleModelTerminal(event, context) {
40879
+ await this.contain("model terminal", async () => {
40880
+ if (this.settledOperations.has(event.idempotencyKey)) {
40881
+ context.state.set(void 0);
40882
+ return;
40883
+ }
40884
+ const active = this.activeModels.get(event.idempotencyKey);
40885
+ if (active) {
40886
+ const span = active.span;
40887
+ if (event.type === "model.call.failed") {
40888
+ if (event.error !== void 0) span.log({ error: event.error });
40889
+ } else {
40890
+ span.log({
40891
+ metrics: usageMetrics(event.usage),
40892
+ output: modelOutput(event)
40893
+ });
40894
+ }
40895
+ span.end();
40896
+ } else {
40897
+ const stored = storedSpan(context);
40898
+ if (stored && "exported" in stored) {
40899
+ updateSpan({
40900
+ exported: stored.exported,
40901
+ ...event.type === "model.call.failed" ? event.error !== void 0 ? { error: event.error } : {} : { output: modelOutput(event) },
40902
+ metrics: {
40903
+ ...event.type === "model.call.completed" ? usageMetrics(event.usage) : {},
40904
+ end: Date.now() / 1e3
40905
+ }
40906
+ });
40907
+ }
40908
+ }
40909
+ this.settledOperations.set(event.idempotencyKey, true);
40910
+ this.forgetModel(event.scope.attemptId, event.idempotencyKey);
40911
+ context.state.set(void 0);
40912
+ });
40913
+ }
40914
+ async handleActionStarted(event, context) {
40915
+ await this.contain("action start", async () => {
40916
+ if (event.kind === "load-skill" || this.settledOperations.has(event.idempotencyKey)) {
40917
+ context.state.set({ skip: true });
40918
+ return;
40919
+ }
40920
+ const parent = await this.parentForScope(event.scope);
40921
+ const { rowId, spanId } = await generateEveIds(
40922
+ event.kind === "subagent-call" ? "subagent" : "tool",
40923
+ event.idempotencyKey
40924
+ );
40925
+ const metadata = {
40926
+ ...this.spanMetadata(event.scope.sessionId),
40927
+ "eve.action_kind": event.kind
40928
+ };
40929
+ const span = await this.startSpan(context, {
40930
+ event: {
40931
+ id: rowId,
40932
+ ...event.input !== void 0 ? { input: event.input } : {},
40933
+ metadata
40934
+ },
40935
+ name: event.name,
40936
+ parentSpanIds: parent,
40937
+ spanAttributes: { type: "tool" /* TOOL */ },
40938
+ spanId
40939
+ });
40940
+ if (!span) return;
40941
+ span.log({
40942
+ ...event.input !== void 0 ? { input: event.input } : {},
40943
+ metadata
40944
+ });
40945
+ this.activeActions.set(event.idempotencyKey, {
40946
+ span,
40947
+ turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
40948
+ });
40949
+ });
40950
+ }
40951
+ async handleActionTerminal(event, context) {
40952
+ await this.contain("action terminal", async () => {
40953
+ if (this.settledOperations.has(event.idempotencyKey)) {
40954
+ context.state.set(void 0);
40955
+ return;
40956
+ }
40957
+ const stored = storedSpan(context);
40958
+ if (stored?.skip) {
40959
+ context.state.set(void 0);
40960
+ return;
40961
+ }
40962
+ const active = this.activeActions.get(event.idempotencyKey);
40963
+ const end = finiteTimestamp(event.acceptedAtMs) ?? Date.now();
40964
+ if (active) {
40965
+ const span = active.span;
40966
+ if (event.type === "action.failed") {
40967
+ span.log({
40968
+ error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
40969
+ });
40970
+ } else if (event.output.type === "error") {
40971
+ span.log({
40972
+ error: event.output.error ?? new Error("Eve action returned an error")
40973
+ });
40974
+ } else {
40975
+ span.log({ output: event.output.output });
40976
+ }
40977
+ span.end({ endTime: end / 1e3 });
40978
+ } else {
40979
+ const stored2 = storedSpan(context);
40980
+ if (stored2 && "exported" in stored2) {
40981
+ updateSpan({
40982
+ exported: stored2.exported,
40983
+ ...event.type === "action.failed" ? {
40984
+ error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
40985
+ } : event.output.type === "error" ? {
40986
+ error: event.output.error ?? new Error("Eve action returned an error")
40987
+ } : { output: event.output.output },
40988
+ metrics: { end: end / 1e3 }
40989
+ });
40990
+ }
40991
+ }
40992
+ this.settledOperations.set(event.idempotencyKey, true);
40993
+ this.activeActions.delete(event.idempotencyKey);
40994
+ context.state.set(void 0);
40995
+ });
40996
+ }
40997
+ handleStepAttemptTerminal(event) {
40998
+ void this.contain("step attempt terminal", () => {
40999
+ const keys = this.modelsByAttempt.get(event.scope.attemptId);
41000
+ if (!keys) return;
41001
+ for (const key of keys) {
41002
+ const active = this.activeModels.get(key);
41003
+ if (!active) continue;
41004
+ if (event.type === "step.attempt.failed" && event.error !== void 0) {
41005
+ active.span.log({ error: event.error });
41006
+ }
41007
+ active.span.end();
41008
+ this.activeModels.delete(key);
41009
+ }
41010
+ this.modelsByAttempt.delete(event.scope.attemptId);
41011
+ });
41012
+ }
41013
+ async parentForScope(scope) {
41014
+ const key = turnKey3(scope.sessionId, scope.turnId);
41015
+ const known = this.turns.get(key);
41016
+ if (known) {
41017
+ return { rootSpanId: known.rootSpanId, spanId: known.spanId };
41018
+ }
41019
+ const [{ spanId }, { spanId: rootSpanId }] = await Promise.all([
41020
+ generateEveIds("turn", turnIdempotencyKey(scope.sessionId, scope.turnId)),
41021
+ generateEveIds(
41022
+ "turn",
41023
+ turnIdempotencyKey(
41024
+ scope.rootSessionId ?? scope.sessionId,
41025
+ scope.turnId
41026
+ )
41027
+ )
41028
+ ]);
41029
+ return { rootSpanId, spanId };
41030
+ }
41031
+ async startSpan(context, args, rootSpanId) {
41032
+ const span = withCurrent(
41033
+ NOOP_SPAN,
41034
+ () => _internalStartSpanWithInitialMerge(
41035
+ withSpanInstrumentationName(args ?? {}, INSTRUMENTATION_NAMES.EVE)
41036
+ )
41037
+ );
41038
+ try {
41039
+ context.state.set({
41040
+ exported: await span.export(),
41041
+ ...rootSpanId ? { rootSpanId } : {}
41042
+ });
41043
+ } catch (error) {
41044
+ debugLogger.warn("Error exporting Eve provider span:", error);
41045
+ }
41046
+ return span;
41047
+ }
41048
+ drainActionsForTurn(sessionId, turnId, error) {
41049
+ const key = turnKey3(sessionId, turnId);
41050
+ for (const [idempotencyKey, active] of this.activeActions) {
41051
+ if (active.turnKey !== key) continue;
41052
+ if (error !== void 0) active.span.log({ error });
41053
+ active.span.end();
41054
+ this.activeActions.delete(idempotencyKey);
41055
+ }
41056
+ }
41057
+ forgetModel(attemptId, idempotencyKey) {
41058
+ this.activeModels.delete(idempotencyKey);
41059
+ const keys = this.modelsByAttempt.get(attemptId);
41060
+ keys?.delete(idempotencyKey);
41061
+ if (keys?.size === 0) this.modelsByAttempt.delete(attemptId);
41062
+ }
41063
+ spanMetadata(sessionId) {
41064
+ return {
41065
+ ...this.metadata ?? {},
41066
+ "eve.session_id": sessionId
41067
+ };
41068
+ }
41069
+ async contain(operation, fn) {
41070
+ try {
41071
+ await fn();
41072
+ } catch (error) {
41073
+ debugLogger.warn(`Error in Eve provider ${operation}:`, error);
41074
+ }
41075
+ }
41076
+ };
41077
+ function storedSpan(context) {
41078
+ const value = context.state.get();
41079
+ if (!isObject(value)) return void 0;
41080
+ if (value["skip"] === true) return { skip: true };
41081
+ return typeof value["exported"] === "string" ? {
41082
+ exported: value["exported"],
41083
+ ...typeof value["rootSpanId"] === "string" && value["rootSpanId"].length > 0 ? { rootSpanId: value["rootSpanId"] } : {}
41084
+ } : void 0;
41085
+ }
41086
+ function modelOutput(event) {
41087
+ const content = event.content ?? [];
41088
+ let text = "";
41089
+ const reasoning = [];
41090
+ const toolCalls2 = [];
41091
+ for (const part of content) {
41092
+ if (part.type === "text") {
41093
+ text += part.text;
41094
+ } else if (part.type === "reasoning" && part.text.trim().length > 0) {
41095
+ reasoning.push({ content: part.text });
41096
+ } else if (part.type === "tool-call") {
41097
+ toolCalls2.push({
41098
+ function: {
41099
+ arguments: safeJsonStringify(part.input),
41100
+ name: part.toolName
41101
+ },
41102
+ id: part.callId,
41103
+ type: "function"
41104
+ });
41105
+ }
41106
+ }
41107
+ return [
41108
+ {
41109
+ finish_reason: normalizeFinishReason3(event.finishReason),
41110
+ index: 0,
41111
+ message: {
41112
+ content: text || null,
41113
+ ...reasoning.length > 0 ? { reasoning } : {},
41114
+ role: "assistant",
41115
+ ...toolCalls2.length > 0 ? { tool_calls: toolCalls2 } : {}
41116
+ }
41117
+ }
41118
+ ];
41119
+ }
41120
+ function usageMetrics(usage) {
41121
+ const promptTokens = nonNegativeNumber(usage.inputTokens);
41122
+ const completionTokens = nonNegativeNumber(usage.outputTokens);
41123
+ const cachedTokens = nonNegativeNumber(
41124
+ usage.inputTokenDetails?.cacheReadTokens
41125
+ );
41126
+ const cacheCreationTokens = nonNegativeNumber(
41127
+ usage.inputTokenDetails?.cacheWriteTokens
41128
+ );
41129
+ return {
41130
+ ...promptTokens !== void 0 ? { prompt_tokens: promptTokens } : {},
41131
+ ...completionTokens !== void 0 ? { completion_tokens: completionTokens } : {},
41132
+ ...promptTokens !== void 0 && completionTokens !== void 0 ? { tokens: promptTokens + completionTokens } : {},
41133
+ ...cachedTokens !== void 0 ? { prompt_cached_tokens: cachedTokens } : {},
41134
+ ...cacheCreationTokens !== void 0 ? { prompt_cache_creation_tokens: cacheCreationTokens } : {}
41135
+ };
41136
+ }
41137
+ function nonNegativeNumber(value) {
41138
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
41139
+ }
41140
+ function finiteTimestamp(value) {
41141
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
41142
+ }
41143
+ function normalizeFinishReason3(value) {
41144
+ if (value === "content-filter") return "content_filter";
41145
+ if (value === "tool-calls") return "tool_calls";
41146
+ return value;
41147
+ }
41148
+ function safeJsonStringify(value) {
41149
+ try {
41150
+ return JSON.stringify(value) ?? "null";
41151
+ } catch {
41152
+ return "null";
41153
+ }
41154
+ }
41155
+ function turnKey3(sessionId, turnId) {
41156
+ return `${sessionId}:${turnId}`;
41157
+ }
41158
+ function turnIdempotencyKey(sessionId, turnId) {
41159
+ return `turn:${sessionId}:${turnId}`;
41160
+ }
41161
+ function actionIdempotencyKey(sessionId, turnId, callId) {
41162
+ return `action:${sessionId}:${turnId}:${callId}`;
41163
+ }
41164
+
41165
+ // src/instrumentation/plugins/eve-instrumentation.ts
41166
+ var EVE_INSTRUMENTATION_PROVIDER = /* @__PURE__ */ Symbol.for("eve.instrumentation.provider");
41167
+ function braintrustEveInstrumentation(options) {
41168
+ const definition = "defineState" in options ? createLegacyEveInstrumentation(options) : createEveInstrumentationProvider(options);
41169
+ const declaration = {
41170
+ ...definition,
41171
+ [EVE_INSTRUMENTATION_PROVIDER]: true
41172
+ };
41173
+ return declaration;
41174
+ }
41175
+
40357
41176
  // src/typed-instrumentation-helpers.ts
40358
41177
  var TypedApplyProxy = Proxy;
40359
41178
 
@@ -40755,11 +41574,11 @@ function wrapClaudeAgentQuery(queryFn, defaultThis) {
40755
41574
  }
40756
41575
  };
40757
41576
  const invocationTarget = thisArg === proxy || thisArg === void 0 ? defaultThis ?? thisArg : thisArg;
40758
- return claudeAgentSDKChannels.query.traceSync(
40759
- () => Reflect.apply(target, invocationTarget, [wrappedParams]),
40760
- // The channel carries no extra context fields, but the generated
40761
- // StartOf<> type for Record<string, never> is overly strict here.
40762
- { arguments: [wrappedParams] }
41577
+ return claudeAgentSDKChannels.query.invoke(
41578
+ target,
41579
+ invocationTarget,
41580
+ [wrappedParams],
41581
+ {}
40763
41582
  );
40764
41583
  }
40765
41584
  });
@@ -41374,13 +42193,11 @@ function wrapAgentInstance(agent) {
41374
42193
  if (prop === "stream" && typeof value === "function") {
41375
42194
  return function(args, options) {
41376
42195
  const callArgs = [args, options];
41377
- return strandsAgentSDKChannels.agentStream.traceSync(
41378
- () => Reflect.apply(value, target, callArgs),
41379
- {
41380
- agent: proxy,
41381
- arguments: callArgs,
41382
- self: proxy
41383
- }
42196
+ return strandsAgentSDKChannels.agentStream.invoke(
42197
+ value,
42198
+ target,
42199
+ callArgs,
42200
+ { agent: proxy }
41384
42201
  );
41385
42202
  };
41386
42203
  }
@@ -41411,12 +42228,12 @@ function wrapMultiAgentInstance(orchestrator, kind) {
41411
42228
  return function(input, options) {
41412
42229
  const callArgs = [input, options];
41413
42230
  const channel2 = kind === "graph" ? strandsAgentSDKChannels.graphStream : strandsAgentSDKChannels.swarmStream;
41414
- return channel2.traceSync(
41415
- () => Reflect.apply(value, target, callArgs),
42231
+ return channel2.invoke(
42232
+ value,
42233
+ target,
42234
+ callArgs,
41416
42235
  {
41417
- arguments: callArgs,
41418
- orchestrator: proxy,
41419
- self: proxy
42236
+ orchestrator: proxy
41420
42237
  }
41421
42238
  );
41422
42239
  };
@@ -43368,9 +44185,6 @@ var VitestContextManager = class {
43368
44185
  getCurrentContext() {
43369
44186
  return this.contextStorage.getStore();
43370
44187
  }
43371
- setContext(context) {
43372
- this.contextStorage.enterWith(context);
43373
- }
43374
44188
  runInContext(context, callback) {
43375
44189
  return this.contextStorage.run(context, callback);
43376
44190
  }
@@ -43756,8 +44570,7 @@ function wrapDescribe(originalDescribe, config, afterAll) {
43756
44570
  if (config.onProgress) {
43757
44571
  config.onProgress({ type: "suite_start", suiteName });
43758
44572
  }
43759
- contextManager.setContext(lazyContext);
43760
- factory();
44573
+ contextManager.runInContext(lazyContext, factory);
43761
44574
  if (afterAll) {
43762
44575
  afterAll(async () => {
43763
44576
  await flushExperimentWithSync(context, config);
@@ -44336,7 +45149,7 @@ function isAsync(fn) {
44336
45149
  function isAsyncGenerator2(fn) {
44337
45150
  return fn[Symbol.toStringTag] === "AsyncGenerator";
44338
45151
  }
44339
- function isAsyncIterable6(obj) {
45152
+ function isAsyncIterable5(obj) {
44340
45153
  return typeof obj[Symbol.asyncIterator] === "function";
44341
45154
  }
44342
45155
  function wrapAsync(asyncFn) {
@@ -44508,7 +45321,7 @@ var eachOfLimit$2 = (limit) => {
44508
45321
  if (isAsyncGenerator2(obj)) {
44509
45322
  return asyncEachOfLimit(obj, limit, iteratee, callback);
44510
45323
  }
44511
- if (isAsyncIterable6(obj)) {
45324
+ if (isAsyncIterable5(obj)) {
44512
45325
  return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback);
44513
45326
  }
44514
45327
  var nextElem = createIterator(obj);
@@ -45863,7 +46676,7 @@ function callEvaluatorData(data) {
45863
46676
  baseExperiment
45864
46677
  };
45865
46678
  }
45866
- function isAsyncIterable7(value) {
46679
+ function isAsyncIterable6(value) {
45867
46680
  return typeof value === "object" && value !== null && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
45868
46681
  }
45869
46682
  function isIterable(value) {
@@ -45898,7 +46711,7 @@ async function _internalResolveEvaluatorData(evaluator, experiment) {
45898
46711
  }).asDataset();
45899
46712
  }
45900
46713
  const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
45901
- if (isAsyncIterable7(resolvedDataResult)) {
46714
+ if (isAsyncIterable6(resolvedDataResult)) {
45902
46715
  return resolvedDataResult;
45903
46716
  }
45904
46717
  if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {