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
@@ -664,8 +664,6 @@ function newGlobalTracingChannel(nameOrChannels) {
664
664
  var DefaultAsyncLocalStorage = class {
665
665
  constructor() {
666
666
  }
667
- enterWith(_) {
668
- }
669
667
  run(_, callback) {
670
668
  return callback();
671
669
  }
@@ -2777,7 +2775,9 @@ var AclObjectType = z6.union([
2777
2775
  "project_log",
2778
2776
  "org_project",
2779
2777
  "org_audit_logs",
2780
- "project_group"
2778
+ "project_group",
2779
+ "ai_secret",
2780
+ "org_ai_secret"
2781
2781
  ]),
2782
2782
  z6.null()
2783
2783
  ]);
@@ -3610,7 +3610,7 @@ var PromptParserNullish = z6.union([
3610
3610
  }),
3611
3611
  z6.null()
3612
3612
  ]);
3613
- var PreprocessorSavedFunctionId = z6.union([
3613
+ var PreprocessorId = z6.union([
3614
3614
  z6.object({
3615
3615
  type: z6.literal("function"),
3616
3616
  id: z6.string(),
@@ -3621,6 +3621,7 @@ var PreprocessorSavedFunctionId = z6.union([
3621
3621
  name: z6.string(),
3622
3622
  function_type: z6.literal("preprocessor").optional().default("preprocessor")
3623
3623
  }),
3624
+ z6.object({ type: z6.literal("inline"), code: z6.string().min(1) }),
3624
3625
  z6.null()
3625
3626
  ]);
3626
3627
  var PromptDataNullish = z6.union([
@@ -3628,7 +3629,7 @@ var PromptDataNullish = z6.union([
3628
3629
  prompt: PromptBlockDataNullish,
3629
3630
  options: PromptOptionsNullish,
3630
3631
  parser: PromptParserNullish,
3631
- preprocessor: PreprocessorSavedFunctionId,
3632
+ preprocessor: PreprocessorId,
3632
3633
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
3633
3634
  template_format: z6.union([
3634
3635
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -3830,7 +3831,7 @@ var PromptData = z6.object({
3830
3831
  prompt: PromptBlockDataNullish,
3831
3832
  options: PromptOptionsNullish,
3832
3833
  parser: PromptParserNullish,
3833
- preprocessor: PreprocessorSavedFunctionId,
3834
+ preprocessor: PreprocessorId,
3834
3835
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
3835
3836
  template_format: z6.union([
3836
3837
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -4774,6 +4775,7 @@ var View = z6.object({
4774
4775
  ]),
4775
4776
  name: z6.string(),
4776
4777
  description: z6.union([z6.string(), z6.null()]).optional(),
4778
+ starred: z6.boolean().optional(),
4777
4779
  created: z6.union([z6.string(), z6.null()]).optional(),
4778
4780
  updated_at: z6.union([z6.string(), z6.null()]).optional(),
4779
4781
  view_data: ViewData.optional(),
@@ -5477,44 +5479,72 @@ function createCacheLayers({
5477
5479
  }
5478
5480
 
5479
5481
  // src/prompt-cache/prompt-cache.ts
5480
- function createCacheKey(key) {
5482
+ function createCacheKey(key, namespace) {
5483
+ let cacheKey;
5481
5484
  if (key.id) {
5482
- return `id:${key.id}`;
5483
- }
5484
- const prefix = key.projectId ?? key.projectName;
5485
- if (!prefix) {
5486
- throw new Error("Either projectId or projectName must be provided");
5487
- }
5488
- if (!key.slug) {
5489
- throw new Error("Slug must be provided when not using ID");
5485
+ cacheKey = `id:${key.id}`;
5486
+ } else {
5487
+ const prefix = key.projectId ?? key.projectName;
5488
+ if (!prefix) {
5489
+ throw new Error("Either projectId or projectName must be provided");
5490
+ }
5491
+ if (!key.slug) {
5492
+ throw new Error("Slug must be provided when not using ID");
5493
+ }
5494
+ cacheKey = `${prefix}:${key.slug}:${key.version ?? "latest"}`;
5490
5495
  }
5491
- return `${prefix}:${key.slug}:${key.version ?? "latest"}`;
5496
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
5492
5497
  }
5493
- var PromptCache = class {
5498
+ var PromptCache = class _PromptCache {
5494
5499
  memoryCache;
5495
5500
  diskCache;
5501
+ namespace;
5502
+ expectedResolvedOrgIdentity;
5496
5503
  constructor(options) {
5497
5504
  this.memoryCache = options.memoryCache;
5498
5505
  this.diskCache = options.diskCache;
5506
+ this.namespace = options.namespace;
5507
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
5508
+ }
5509
+ /**
5510
+ * Returns a cache view that shares the same storage layers but isolates all
5511
+ * entries under the provided namespace.
5512
+ */
5513
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
5514
+ return new _PromptCache({
5515
+ memoryCache: this.memoryCache,
5516
+ diskCache: this.diskCache,
5517
+ namespace,
5518
+ expectedResolvedOrgIdentity
5519
+ });
5499
5520
  }
5500
5521
  /**
5501
5522
  * Retrieves a prompt from the cache.
5502
5523
  * First checks the in-memory LRU cache, then falls back to checking the disk cache if available.
5503
5524
  */
5504
5525
  async get(key) {
5505
- const cacheKey = createCacheKey(key);
5526
+ const cacheKey = createCacheKey(key, this.namespace);
5506
5527
  if (this.memoryCache) {
5507
- const memoryPrompt = this.memoryCache.get(cacheKey);
5508
- if (memoryPrompt !== void 0) {
5509
- return memoryPrompt;
5528
+ const memoryEntry = this.memoryCache.get(cacheKey);
5529
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
5530
+ return memoryEntry.value;
5510
5531
  }
5511
5532
  }
5512
5533
  if (this.diskCache) {
5513
- const diskPrompt = await this.diskCache.get(cacheKey);
5514
- if (!diskPrompt) {
5534
+ const diskEntry = await this.diskCache.get(cacheKey);
5535
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
5515
5536
  return void 0;
5516
5537
  }
5517
- this.memoryCache?.set(cacheKey, diskPrompt);
5538
+ const serializedPrompt = diskEntry.value;
5539
+ const diskPrompt = new Prompt2(
5540
+ serializedPrompt.metadata,
5541
+ serializedPrompt.defaults,
5542
+ serializedPrompt.noTrace
5543
+ );
5544
+ this.memoryCache?.set(cacheKey, {
5545
+ value: diskPrompt,
5546
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
5547
+ });
5518
5548
  return diskPrompt;
5519
5549
  }
5520
5550
  return void 0;
@@ -5528,58 +5558,91 @@ var PromptCache = class {
5528
5558
  * @throws If there is an error writing to the disk cache.
5529
5559
  */
5530
5560
  async set(key, value) {
5531
- const cacheKey = createCacheKey(key);
5532
- this.memoryCache?.set(cacheKey, value);
5561
+ const cacheKey = createCacheKey(key, this.namespace);
5562
+ const memoryEntry = {
5563
+ value,
5564
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5565
+ };
5566
+ this.memoryCache?.set(cacheKey, memoryEntry);
5533
5567
  if (this.diskCache) {
5534
- await this.diskCache.set(cacheKey, value);
5568
+ await this.diskCache.set(cacheKey, {
5569
+ value: value._internalSerializeForCache(),
5570
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5571
+ });
5535
5572
  }
5536
5573
  }
5537
5574
  };
5538
5575
 
5539
5576
  // src/prompt-cache/parameters-cache.ts
5540
- function createCacheKey2(key) {
5577
+ function createCacheKey2(key, namespace) {
5578
+ let cacheKey;
5541
5579
  if (key.id) {
5542
- return `parameters:id:${key.id}`;
5543
- }
5544
- const prefix = key.projectId ?? key.projectName;
5545
- if (!prefix) {
5546
- throw new Error("Either projectId or projectName must be provided");
5547
- }
5548
- if (!key.slug) {
5549
- throw new Error("Slug must be provided when not using ID");
5580
+ cacheKey = `parameters:id:${key.id}`;
5581
+ } else {
5582
+ const prefix = key.projectId ?? key.projectName;
5583
+ if (!prefix) {
5584
+ throw new Error("Either projectId or projectName must be provided");
5585
+ }
5586
+ if (!key.slug) {
5587
+ throw new Error("Slug must be provided when not using ID");
5588
+ }
5589
+ cacheKey = `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
5550
5590
  }
5551
- return `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
5591
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
5552
5592
  }
5553
- var ParametersCache = class {
5593
+ var ParametersCache = class _ParametersCache {
5554
5594
  memoryCache;
5555
5595
  diskCache;
5596
+ namespace;
5597
+ expectedResolvedOrgIdentity;
5556
5598
  constructor(options) {
5557
5599
  this.memoryCache = options.memoryCache;
5558
5600
  this.diskCache = options.diskCache;
5601
+ this.namespace = options.namespace;
5602
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
5603
+ }
5604
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
5605
+ return new _ParametersCache({
5606
+ memoryCache: this.memoryCache,
5607
+ diskCache: this.diskCache,
5608
+ namespace,
5609
+ expectedResolvedOrgIdentity
5610
+ });
5559
5611
  }
5560
5612
  async get(key) {
5561
- const cacheKey = createCacheKey2(key);
5613
+ const cacheKey = createCacheKey2(key, this.namespace);
5562
5614
  if (this.memoryCache) {
5563
- const memoryParams = this.memoryCache.get(cacheKey);
5564
- if (memoryParams !== void 0) {
5565
- return memoryParams;
5615
+ const memoryEntry = this.memoryCache.get(cacheKey);
5616
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
5617
+ return memoryEntry.value;
5566
5618
  }
5567
5619
  }
5568
5620
  if (this.diskCache) {
5569
- const diskParams = await this.diskCache.get(cacheKey);
5570
- if (!diskParams) {
5621
+ const diskEntry = await this.diskCache.get(cacheKey);
5622
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
5571
5623
  return void 0;
5572
5624
  }
5573
- this.memoryCache?.set(cacheKey, diskParams);
5574
- return diskParams;
5625
+ const diskParameters = new RemoteEvalParameters(diskEntry.value.metadata);
5626
+ this.memoryCache?.set(cacheKey, {
5627
+ value: diskParameters,
5628
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
5629
+ });
5630
+ return diskParameters;
5575
5631
  }
5576
5632
  return void 0;
5577
5633
  }
5578
5634
  async set(key, value) {
5579
- const cacheKey = createCacheKey2(key);
5580
- this.memoryCache?.set(cacheKey, value);
5635
+ const cacheKey = createCacheKey2(key, this.namespace);
5636
+ const memoryEntry = {
5637
+ value,
5638
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5639
+ };
5640
+ this.memoryCache?.set(cacheKey, memoryEntry);
5581
5641
  if (this.diskCache) {
5582
- await this.diskCache.set(cacheKey, value);
5642
+ await this.diskCache.set(cacheKey, {
5643
+ value: value._internalSerializeForCache(),
5644
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5645
+ });
5583
5646
  }
5584
5647
  }
5585
5648
  };
@@ -5883,6 +5946,7 @@ var INSTRUMENTATION_NAMES = {
5883
5946
  CLOUDFLARE_THINK: "cloudflare-think",
5884
5947
  COHERE: "cohere",
5885
5948
  CURSOR_SDK: "cursor-sdk",
5949
+ DEEPSEEK_HARNESS: "deepseek-harness",
5886
5950
  EVE: "eve",
5887
5951
  FLUE: "flue",
5888
5952
  GENKIT: "genkit",
@@ -5908,7 +5972,7 @@ var INSTRUMENTATION_NAMES = {
5908
5972
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5909
5973
  "braintrust.spanInstrumentationName"
5910
5974
  );
5911
- var SDK_VERSION = true ? "3.28.0" : "0.0.0";
5975
+ var SDK_VERSION = true ? "3.29.0" : "0.0.0";
5912
5976
  function withSpanInstrumentationName(args, instrumentationName) {
5913
5977
  return {
5914
5978
  ...args,
@@ -6027,6 +6091,16 @@ var datasetSnapshotRegisterResponseSchema = z8.object({
6027
6091
  dataset_snapshot: DatasetSnapshot,
6028
6092
  found_existing: z8.boolean().optional()
6029
6093
  });
6094
+ var datasetObjectInfoSchema = z8.object({
6095
+ object_id: z8.string(),
6096
+ object_name: z8.string(),
6097
+ parent_cols: z8.object({
6098
+ project: z8.object({
6099
+ id: z8.string(),
6100
+ name: z8.string()
6101
+ })
6102
+ })
6103
+ });
6030
6104
  var datasetRestorePreviewResultSchema = z8.object({
6031
6105
  rows_to_restore: z8.number(),
6032
6106
  rows_to_delete: z8.number()
@@ -6240,12 +6314,53 @@ var loginSchema = z8.strictObject({
6240
6314
  });
6241
6315
  var stateNonce = 0;
6242
6316
  var V1_PROXY_SUFFIX = "/v1/proxy";
6317
+ var LOADER_LOGIN_CACHE_MAX = 16;
6243
6318
  function normalizeProxyConnUrl(proxyUrl) {
6244
6319
  return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
6245
6320
  }
6246
6321
  var BraintrustState = class _BraintrustState {
6322
+ id;
6323
+ currentExperiment;
6324
+ // Note: the value of IsAsyncFlush doesn't really matter here, since we
6325
+ // (safely) dynamically cast it whenever retrieving the logger.
6326
+ currentLogger;
6327
+ currentParent;
6328
+ currentSpan;
6329
+ // Any time we re-log in, we directly update the apiConn inside the logger.
6330
+ // This is preferable to replacing the whole logger, which would create the
6331
+ // possibility of multiple loggers floating around, which may not log in a
6332
+ // deterministic order.
6333
+ _bgLogger;
6334
+ _overrideBgLogger = null;
6335
+ appUrl = null;
6336
+ appPublicUrl = null;
6337
+ loginToken = null;
6338
+ orgId = null;
6339
+ orgName = null;
6340
+ apiUrl = null;
6341
+ proxyUrl = null;
6342
+ loggedIn = false;
6343
+ gitMetadataSettings;
6344
+ debugLogLevel;
6345
+ debugLogLevelConfigured = false;
6346
+ fetch = globalThis.fetch;
6347
+ _appConn = null;
6348
+ _apiConn = null;
6349
+ _proxyConn = null;
6350
+ promptCache;
6351
+ parametersCache;
6352
+ spanCache;
6353
+ _idGenerator = null;
6354
+ _contextManager = null;
6355
+ _otelFlushCallback = null;
6356
+ spanOriginEnvironment;
6357
+ traceContextSigningSecret;
6358
+ loaderLoginCache = /* @__PURE__ */ new WeakMap();
6359
+ loginParams;
6360
+ activeLoginOrgNameSelector;
6247
6361
  constructor(loginParams) {
6248
- this.loginParams = loginParams;
6362
+ this.loginParams = { ...loginParams };
6363
+ this.activeLoginOrgNameSelector = loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
6249
6364
  this.id = `${(/* @__PURE__ */ new Date()).toLocaleString()}-${stateNonce++}`;
6250
6365
  this.currentExperiment = void 0;
6251
6366
  this.currentLogger = void 0;
@@ -6282,12 +6397,14 @@ var BraintrustState = class _BraintrustState {
6282
6397
  const {
6283
6398
  memoryCache: parametersMemoryCache,
6284
6399
  diskCache: parametersDiskCache
6285
- } = createCacheLayers({
6286
- memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
6287
- diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
6288
- diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
6289
- getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
6290
- });
6400
+ } = createCacheLayers(
6401
+ {
6402
+ memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
6403
+ diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
6404
+ diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
6405
+ getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
6406
+ }
6407
+ );
6291
6408
  this.parametersCache = new ParametersCache({
6292
6409
  memoryCache: parametersMemoryCache,
6293
6410
  diskCache: parametersDiskCache
@@ -6296,43 +6413,6 @@ var BraintrustState = class _BraintrustState {
6296
6413
  this.spanOriginEnvironment = detectSpanOriginEnvironment();
6297
6414
  this._internalSetTraceContextSigningSecret(loginParams.apiKey);
6298
6415
  }
6299
- loginParams;
6300
- id;
6301
- currentExperiment;
6302
- // Note: the value of IsAsyncFlush doesn't really matter here, since we
6303
- // (safely) dynamically cast it whenever retrieving the logger.
6304
- currentLogger;
6305
- currentParent;
6306
- currentSpan;
6307
- // Any time we re-log in, we directly update the apiConn inside the logger.
6308
- // This is preferable to replacing the whole logger, which would create the
6309
- // possibility of multiple loggers floating around, which may not log in a
6310
- // deterministic order.
6311
- _bgLogger;
6312
- _overrideBgLogger = null;
6313
- appUrl = null;
6314
- appPublicUrl = null;
6315
- loginToken = null;
6316
- orgId = null;
6317
- orgName = null;
6318
- apiUrl = null;
6319
- proxyUrl = null;
6320
- loggedIn = false;
6321
- gitMetadataSettings;
6322
- debugLogLevel;
6323
- debugLogLevelConfigured = false;
6324
- fetch = globalThis.fetch;
6325
- _appConn = null;
6326
- _apiConn = null;
6327
- _proxyConn = null;
6328
- promptCache;
6329
- parametersCache;
6330
- spanCache;
6331
- _idGenerator = null;
6332
- _contextManager = null;
6333
- _otelFlushCallback = null;
6334
- spanOriginEnvironment;
6335
- traceContextSigningSecret;
6336
6416
  /** @internal */
6337
6417
  _internalSetTraceContextSigningSecret(secret) {
6338
6418
  const normalizedSecret = secret?.trim();
@@ -6357,6 +6437,101 @@ var BraintrustState = class _BraintrustState {
6357
6437
  this._appConn = null;
6358
6438
  this._apiConn = null;
6359
6439
  this._proxyConn = null;
6440
+ this.loaderLoginCache = /* @__PURE__ */ new WeakMap();
6441
+ }
6442
+ /** @internal */
6443
+ async _internalResolveLoaderLoginOptions({
6444
+ apiKey,
6445
+ appUrl,
6446
+ orgName,
6447
+ fetch: fetch2,
6448
+ forceLogin
6449
+ }) {
6450
+ const resolvedAppUrl = appUrl ?? (this.loggedIn ? this.appUrl ?? void 0 : void 0) ?? this.loginParams.appUrl ?? isomorph_default.getEnv("BRAINTRUST_APP_URL") ?? "https://www.braintrust.dev";
6451
+ const resolvedApiKey = apiKey ?? (this.loggedIn ? this.loginToken ?? void 0 : void 0) ?? this.loginParams.apiKey ?? await isomorph_default.getBraintrustApiKey();
6452
+ if (!resolvedApiKey) {
6453
+ throw new Error(
6454
+ "Please specify an api key (e.g. by setting BRAINTRUST_API_KEY)."
6455
+ );
6456
+ }
6457
+ const normalizedApiKey = HTTPConnection.sanitize_token(resolvedApiKey);
6458
+ const usesActiveCredential = this.loggedIn && normalizedApiKey === this.loginToken;
6459
+ const requestedOrgName = orgName ?? (usesActiveCredential ? this.activeLoginOrgNameSelector : void 0) ?? this.loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
6460
+ const resolvedOrgName = orgName ?? (usesActiveCredential ? this.orgName ?? void 0 : void 0) ?? requestedOrgName;
6461
+ const resolvedFetch = fetch2 ?? (this.loggedIn ? this.fetch : void 0) ?? this.loginParams.fetch ?? globalThis.fetch;
6462
+ const credentialCacheNamespace = JSON.stringify([
6463
+ "loader-credential",
6464
+ resolvedAppUrl,
6465
+ requestedOrgName,
6466
+ normalizedApiKey
6467
+ ]);
6468
+ return {
6469
+ apiKey: normalizedApiKey,
6470
+ appUrl: resolvedAppUrl,
6471
+ orgName: resolvedOrgName,
6472
+ fetch: resolvedFetch,
6473
+ forceLogin,
6474
+ credentialCacheNamespace,
6475
+ existingState: !forceLogin && usesActiveCredential && resolvedAppUrl === this.appUrl && resolvedOrgName === this.orgName && resolvedFetch === this.fetch ? this : void 0
6476
+ };
6477
+ }
6478
+ /** @internal */
6479
+ _internalGetLoaderCacheViews(loginOptions, requestState) {
6480
+ const expectedResolvedOrgIdentity = requestState?.orgId && requestState.appUrl ? JSON.stringify([
6481
+ "loader-org",
6482
+ requestState.appUrl,
6483
+ requestState.orgId
6484
+ ]) : void 0;
6485
+ return {
6486
+ promptCache: this.promptCache.withNamespace(
6487
+ loginOptions.credentialCacheNamespace,
6488
+ expectedResolvedOrgIdentity
6489
+ ),
6490
+ parametersCache: this.parametersCache.withNamespace(
6491
+ loginOptions.credentialCacheNamespace,
6492
+ expectedResolvedOrgIdentity
6493
+ )
6494
+ };
6495
+ }
6496
+ /** @internal */
6497
+ async _internalGetLoaderState({
6498
+ apiKey,
6499
+ appUrl,
6500
+ orgName,
6501
+ fetch: fetch2,
6502
+ forceLogin,
6503
+ existingState
6504
+ }) {
6505
+ if (existingState) {
6506
+ return existingState;
6507
+ }
6508
+ let cache = this.loaderLoginCache.get(fetch2);
6509
+ if (!cache) {
6510
+ cache = new LRUCache({ max: LOADER_LOGIN_CACHE_MAX });
6511
+ this.loaderLoginCache.set(fetch2, cache);
6512
+ }
6513
+ const cacheKey = JSON.stringify([appUrl, orgName, apiKey]);
6514
+ if (!forceLogin) {
6515
+ const cachedState = cache.get(cacheKey);
6516
+ if (cachedState) {
6517
+ return cachedState;
6518
+ }
6519
+ }
6520
+ const statePromise = loginToLoaderRequestState({
6521
+ orgName,
6522
+ apiKey,
6523
+ appUrl,
6524
+ fetch: fetch2
6525
+ });
6526
+ cache.set(cacheKey, statePromise);
6527
+ try {
6528
+ return await statePromise;
6529
+ } catch (error) {
6530
+ if (cache.get(cacheKey) === statePromise) {
6531
+ cache.delete(cacheKey);
6532
+ }
6533
+ throw error;
6534
+ }
6360
6535
  }
6361
6536
  resetIdGenState() {
6362
6537
  this._idGenerator = null;
@@ -6405,6 +6580,8 @@ var BraintrustState = class _BraintrustState {
6405
6580
  this.debugLogLevel = other.debugLogLevel;
6406
6581
  this.debugLogLevelConfigured = other.debugLogLevelConfigured;
6407
6582
  this.traceContextSigningSecret = other.traceContextSigningSecret;
6583
+ this.fetch = other.fetch;
6584
+ this.activeLoginOrgNameSelector = other.activeLoginOrgNameSelector;
6408
6585
  setGlobalDebugLogLevel(
6409
6586
  this.debugLogLevelConfigured ? this.debugLogLevel ?? false : void 0
6410
6587
  );
@@ -6612,36 +6789,76 @@ var FailedHTTPResponse = class extends Error {
6612
6789
  status;
6613
6790
  text;
6614
6791
  data;
6615
- constructor(status, text, data) {
6792
+ cause;
6793
+ constructor(status, text, data, cause) {
6616
6794
  super(`${status}: ${text} (${data})`);
6617
6795
  this.status = status;
6618
6796
  this.text = text;
6619
6797
  this.data = data;
6798
+ this.cause = cause;
6799
+ }
6800
+ };
6801
+ var HTTPTransportError = class extends Error {
6802
+ cause;
6803
+ constructor(cause) {
6804
+ super(cause instanceof Error ? cause.message : String(cause));
6805
+ this.name = "HTTPTransportError";
6806
+ this.cause = cause;
6620
6807
  }
6621
6808
  };
6809
+ var httpTransportErrorCauses = /* @__PURE__ */ new WeakSet();
6810
+ function recordHTTPTransportError(error) {
6811
+ if (typeof error === "object" && error !== null || typeof error === "function") {
6812
+ httpTransportErrorCauses.add(error);
6813
+ }
6814
+ }
6815
+ function rethrowHTTPTransportError(error, classifyTransportErrors) {
6816
+ if (classifyTransportErrors) {
6817
+ throw new HTTPTransportError(error);
6818
+ }
6819
+ recordHTTPTransportError(error);
6820
+ throw error;
6821
+ }
6822
+ async function readJSONResponse(response, classifyTransportErrors = false) {
6823
+ let data;
6824
+ try {
6825
+ data = await response.text();
6826
+ } catch (error) {
6827
+ rethrowHTTPTransportError(error, classifyTransportErrors);
6828
+ }
6829
+ return JSON.parse(data);
6830
+ }
6622
6831
  async function checkResponse(resp) {
6623
6832
  if (resp.ok) {
6624
6833
  return resp;
6625
- } else {
6834
+ }
6835
+ let data;
6836
+ try {
6837
+ data = await resp.text();
6838
+ } catch (error) {
6626
6839
  throw new FailedHTTPResponse(
6627
6840
  resp.status,
6628
6841
  resp.statusText,
6629
- await resp.text()
6842
+ "Unable to read response body",
6843
+ error
6630
6844
  );
6631
6845
  }
6846
+ throw new FailedHTTPResponse(resp.status, resp.statusText, data);
6632
6847
  }
6633
6848
  var HTTPConnection = class _HTTPConnection {
6634
- base_url;
6635
- token;
6636
- headers;
6637
- fetch;
6638
- constructor(base_url, fetch2) {
6849
+ constructor(base_url, fetch2, classifyTransportErrors = false) {
6850
+ this.classifyTransportErrors = classifyTransportErrors;
6639
6851
  this.base_url = base_url;
6640
6852
  this.token = null;
6641
6853
  this.headers = {};
6642
6854
  this._reset();
6643
6855
  this.fetch = fetch2;
6644
6856
  }
6857
+ classifyTransportErrors;
6858
+ base_url;
6859
+ token;
6860
+ headers;
6861
+ fetch;
6645
6862
  setFetch(fetch2) {
6646
6863
  this.fetch = fetch2;
6647
6864
  }
@@ -6681,9 +6898,9 @@ var HTTPConnection = class _HTTPConnection {
6681
6898
  ).toString();
6682
6899
  const this_fetch = this.fetch;
6683
6900
  const this_headers = this.headers;
6684
- return await checkResponse(
6685
- // Using toString() here makes it work with isomorphic fetch
6686
- await this_fetch(url.toString(), {
6901
+ let response;
6902
+ try {
6903
+ response = await this_fetch(url.toString(), {
6687
6904
  headers: {
6688
6905
  Accept: "application/json",
6689
6906
  ...this_headers,
@@ -6691,8 +6908,14 @@ var HTTPConnection = class _HTTPConnection {
6691
6908
  },
6692
6909
  keepalive: true,
6693
6910
  ...rest
6694
- })
6695
- );
6911
+ });
6912
+ } catch (error) {
6913
+ if (config?.signal?.aborted) {
6914
+ throw getAbortReason(config.signal);
6915
+ }
6916
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
6917
+ }
6918
+ return await checkResponse(response);
6696
6919
  }
6697
6920
  async post(path3, params, config, retries = 0) {
6698
6921
  const { headers, ...rest } = config || {};
@@ -6702,8 +6925,9 @@ var HTTPConnection = class _HTTPConnection {
6702
6925
  const tries = retries + 1;
6703
6926
  for (let i = 0; i < tries; i++) {
6704
6927
  try {
6705
- return await checkResponse(
6706
- await this_fetch(_urljoin(this_base_url, path3), {
6928
+ let response;
6929
+ try {
6930
+ response = await this_fetch(_urljoin(this_base_url, path3), {
6707
6931
  method: "POST",
6708
6932
  headers: {
6709
6933
  Accept: "application/json",
@@ -6714,8 +6938,14 @@ var HTTPConnection = class _HTTPConnection {
6714
6938
  body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
6715
6939
  keepalive: true,
6716
6940
  ...rest
6717
- })
6718
- );
6941
+ });
6942
+ } catch (error) {
6943
+ if (config?.signal?.aborted) {
6944
+ throw getAbortReason(config.signal);
6945
+ }
6946
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
6947
+ }
6948
+ return await checkResponse(response);
6719
6949
  } catch (error) {
6720
6950
  if (config?.signal?.aborted) {
6721
6951
  throw getAbortReason(config.signal);
@@ -6740,7 +6970,7 @@ var HTTPConnection = class _HTTPConnection {
6740
6970
  for (let i = 0; i < tries; i++) {
6741
6971
  try {
6742
6972
  const resp = await this.get(`${object_type}`, args);
6743
- return await resp.json();
6973
+ return await readJSONResponse(resp, this.classifyTransportErrors);
6744
6974
  } catch (e) {
6745
6975
  if (i < tries - 1) {
6746
6976
  debugLogger.debug(
@@ -6763,7 +6993,7 @@ var HTTPConnection = class _HTTPConnection {
6763
6993
  const resp = await this.post(`${object_type}`, args, {
6764
6994
  headers: { "Content-Type": "application/json" }
6765
6995
  });
6766
- return await resp.json();
6996
+ return await readJSONResponse(resp, this.classifyTransportErrors);
6767
6997
  }
6768
6998
  // Custom inspect for Node.js console.log
6769
6999
  [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
@@ -8583,6 +8813,7 @@ function initDataset(projectOrOptions, optionalOptions) {
8583
8813
  const {
8584
8814
  project,
8585
8815
  dataset,
8816
+ datasetId,
8586
8817
  description,
8587
8818
  version,
8588
8819
  snapshotName,
@@ -8598,6 +8829,11 @@ function initDataset(projectOrOptions, optionalOptions) {
8598
8829
  state: stateArg,
8599
8830
  _internal_btql
8600
8831
  } = options;
8832
+ if (datasetId !== void 0 && (description !== void 0 || metadata !== void 0)) {
8833
+ throw new Error(
8834
+ "Cannot specify description or metadata when datasetId is provided"
8835
+ );
8836
+ }
8601
8837
  const selection = normalizeDatasetSelection({
8602
8838
  version,
8603
8839
  environment,
@@ -8618,6 +8854,35 @@ function initDataset(projectOrOptions, optionalOptions) {
8618
8854
  fetch: fetch2,
8619
8855
  forceLogin
8620
8856
  });
8857
+ if (datasetId !== void 0) {
8858
+ const objectInfo = datasetObjectInfoSchema.array().parse(
8859
+ await state.appConn().post_json("api/self/get_object_info", {
8860
+ object_type: "dataset",
8861
+ object_ids: [datasetId]
8862
+ })
8863
+ );
8864
+ if (objectInfo.length === 0) {
8865
+ throw new Error(`Dataset with ID ${datasetId} not found`);
8866
+ }
8867
+ if (objectInfo.length !== 1) {
8868
+ throw new Error(
8869
+ `Expected exactly one dataset with ID ${datasetId}, but found ${objectInfo.length}`
8870
+ );
8871
+ }
8872
+ const datasetInfo = objectInfo[0];
8873
+ return {
8874
+ project: {
8875
+ id: datasetInfo.parent_cols.project.id,
8876
+ name: datasetInfo.parent_cols.project.name,
8877
+ fullInfo: datasetInfo.parent_cols.project
8878
+ },
8879
+ dataset: {
8880
+ id: datasetInfo.object_id,
8881
+ name: datasetInfo.object_name,
8882
+ fullInfo: datasetInfo
8883
+ }
8884
+ };
8885
+ }
8621
8886
  const args = {
8622
8887
  org_id: state.orgId,
8623
8888
  project_name: project,
@@ -8792,6 +9057,52 @@ async function login(options = {}) {
8792
9057
  await state.login(options);
8793
9058
  return state;
8794
9059
  }
9060
+ async function loginToLoaderRequestState({
9061
+ appUrl,
9062
+ apiKey,
9063
+ orgName,
9064
+ fetch: fetch2
9065
+ }) {
9066
+ let orgId;
9067
+ let apiUrl;
9068
+ if (apiKey === TEST_API_KEY) {
9069
+ orgId = "test-org-id";
9070
+ apiUrl = "https://braintrust.dev/fake-api-url";
9071
+ } else {
9072
+ let loginResponse;
9073
+ try {
9074
+ loginResponse = await fetch2(_urljoin(appUrl, `/api/apikey/login`), {
9075
+ method: "POST",
9076
+ headers: {
9077
+ "Content-Type": "application/json",
9078
+ Authorization: `Bearer ${apiKey}`
9079
+ }
9080
+ });
9081
+ } catch (error) {
9082
+ throw new HTTPTransportError(error);
9083
+ }
9084
+ const info = await readJSONResponse(
9085
+ await checkResponse(loginResponse),
9086
+ true
9087
+ );
9088
+ const org = selectLoginOrg(info.org_info, orgName);
9089
+ orgId = org.id;
9090
+ apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
9091
+ if (!apiUrl) {
9092
+ throw new Error(
9093
+ 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."
9094
+ );
9095
+ }
9096
+ }
9097
+ const apiConnection = new HTTPConnection(apiUrl, fetch2, true);
9098
+ apiConnection.set_token(apiKey);
9099
+ apiConnection.make_long_lived();
9100
+ return {
9101
+ appUrl,
9102
+ orgId,
9103
+ apiConn: () => apiConnection
9104
+ };
9105
+ }
8795
9106
  async function loginToState(options = {}) {
8796
9107
  const {
8797
9108
  appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
@@ -8823,16 +9134,18 @@ async function loginToState(options = {}) {
8823
9134
  _saveOrgInfo(state, testOrgInfo, testOrgInfo[0].name);
8824
9135
  return state;
8825
9136
  } else {
8826
- const resp = await checkResponse(
8827
- await fetch2(_urljoin(state.appUrl, `/api/apikey/login`), {
9137
+ const loginResponse = await fetch2(
9138
+ _urljoin(state.appUrl, `/api/apikey/login`),
9139
+ {
8828
9140
  method: "POST",
8829
9141
  headers: {
8830
9142
  "Content-Type": "application/json",
8831
9143
  Authorization: `Bearer ${apiKey}`
8832
9144
  }
8833
- })
9145
+ }
8834
9146
  );
8835
- const info = await resp.json();
9147
+ const resp = await checkResponse(loginResponse);
9148
+ const info = await readJSONResponse(resp);
8836
9149
  _saveOrgInfo(state, info.org_info, orgName);
8837
9150
  if (!state.apiUrl) {
8838
9151
  if (orgName) {
@@ -9234,27 +9547,28 @@ function withCurrent(span, callback, state = void 0) {
9234
9547
  function withParent(parent, callback, state = void 0) {
9235
9548
  return (state ?? _globalState).currentParent.run(parent, () => callback());
9236
9549
  }
9237
- function _saveOrgInfo(state, org_info, org_name) {
9238
- if (org_info.length === 0) {
9550
+ function _saveOrgInfo(state, orgInfo, orgName) {
9551
+ const org = selectLoginOrg(orgInfo, orgName);
9552
+ state.orgId = org.id;
9553
+ state.orgName = org.name;
9554
+ state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
9555
+ state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
9556
+ state.gitMetadataSettings = org.git_metadata || void 0;
9557
+ }
9558
+ function selectLoginOrg(orgInfo, orgName) {
9559
+ if (orgInfo.length === 0) {
9239
9560
  throw new LoginInvalidOrgError(
9240
9561
  "This user is not part of any organizations."
9241
9562
  );
9242
9563
  }
9243
- for (const org of org_info) {
9244
- if (org_name === void 0 || org.name === org_name) {
9245
- state.orgId = org.id;
9246
- state.orgName = org.name;
9247
- state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
9248
- state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
9249
- state.gitMetadataSettings = org.git_metadata || void 0;
9250
- break;
9564
+ for (const org of orgInfo) {
9565
+ if (orgName === void 0 || org.name === orgName) {
9566
+ return org;
9251
9567
  }
9252
9568
  }
9253
- if (state.orgId === void 0) {
9254
- throw new LoginInvalidOrgError(
9255
- `Organization ${org_name} not found. Must be one of ${org_info.map((x) => x.name).join(", ")}`
9256
- );
9257
- }
9569
+ throw new LoginInvalidOrgError(
9570
+ `Organization ${orgName} not found. Must be one of ${orgInfo.map((org) => org.name).join(", ")}`
9571
+ );
9258
9572
  }
9259
9573
  function validateTags(tags) {
9260
9574
  const seen = /* @__PURE__ */ new Set();
@@ -11157,6 +11471,14 @@ var Prompt2 = class _Prompt {
11157
11471
  static isPrompt(data) {
11158
11472
  return typeof data === "object" && data !== null && "__braintrust_prompt_marker" in data;
11159
11473
  }
11474
+ /** @internal */
11475
+ _internalSerializeForCache() {
11476
+ return {
11477
+ metadata: this.metadata,
11478
+ defaults: this.defaults,
11479
+ noTrace: this.noTrace
11480
+ };
11481
+ }
11160
11482
  static fromPromptData(name, promptData) {
11161
11483
  return new _Prompt(
11162
11484
  {
@@ -11197,6 +11519,10 @@ var RemoteEvalParameters = class {
11197
11519
  get data() {
11198
11520
  return this.metadata.function_data.data ?? {};
11199
11521
  }
11522
+ /** @internal */
11523
+ _internalSerializeForCache() {
11524
+ return { metadata: this.metadata };
11525
+ }
11200
11526
  validate(data) {
11201
11527
  if (typeof data !== "object" || data === null) {
11202
11528
  return false;
@@ -11888,56 +12214,14 @@ function suppressionStore() {
11888
12214
  autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
11889
12215
  return autoInstrumentationSuppressionStore;
11890
12216
  }
11891
- function currentFrames() {
11892
- return suppressionStore().getStore()?.frames ?? [];
11893
- }
11894
12217
  function isAutoInstrumentationSuppressed() {
11895
- const frames = currentFrames();
11896
- return frames[frames.length - 1]?.mode === "suppress";
12218
+ return suppressionStore().getStore() === true;
11897
12219
  }
11898
12220
  function runWithAutoInstrumentationSuppressed(callback) {
11899
- const frame = {
11900
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
11901
- mode: "suppress"
11902
- };
11903
- return suppressionStore().run(
11904
- { frames: [...currentFrames(), frame] },
11905
- callback
11906
- );
11907
- }
11908
- function bindAutoInstrumentationSuppressionToStart(tracingChannel) {
11909
- const startChannel = tracingChannel.start;
11910
- if (!startChannel) {
11911
- return void 0;
11912
- }
11913
- const store = suppressionStore();
11914
- startChannel.bindStore(store, () => ({
11915
- frames: [
11916
- ...currentFrames(),
11917
- {
11918
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
11919
- mode: "suppress"
11920
- }
11921
- ]
11922
- }));
11923
- return () => {
11924
- startChannel.unbindStore(store);
11925
- };
12221
+ return suppressionStore().run(true, callback);
11926
12222
  }
11927
- function enterAutoInstrumentationAllowed() {
11928
- const frame = {
11929
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
11930
- mode: "allow"
11931
- };
11932
- suppressionStore().enterWith({
11933
- frames: [...currentFrames(), frame]
11934
- });
11935
- return () => {
11936
- const frames = currentFrames().filter(
11937
- (candidate) => candidate.id !== frame.id
11938
- );
11939
- suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
11940
- };
12223
+ function runWithAutoInstrumentationAllowed(callback) {
12224
+ return suppressionStore().run(void 0, callback);
11941
12225
  }
11942
12226
 
11943
12227
  // src/instrumentation/core/channel-tracing.ts
@@ -13226,13 +13510,33 @@ function aggregateChatLogprobs(existing, incoming) {
13226
13510
  }
13227
13511
  return aggregated;
13228
13512
  }
13513
+ function createAggregatedChatChoice(index) {
13514
+ return {
13515
+ index,
13516
+ role: void 0,
13517
+ content: void 0,
13518
+ refusal: void 0,
13519
+ toolCallsByIndex: /* @__PURE__ */ new Map(),
13520
+ logprobs: void 0,
13521
+ finish_reason: void 0
13522
+ };
13523
+ }
13524
+ function toChatChoice(choice) {
13525
+ const toolCalls = Array.from(choice.toolCallsByIndex.entries()).sort(([left], [right]) => left - right).map(([, toolCall]) => toolCall);
13526
+ return {
13527
+ index: choice.index,
13528
+ message: {
13529
+ role: choice.role,
13530
+ content: choice.content,
13531
+ ...choice.refusal !== void 0 ? { refusal: choice.refusal } : {},
13532
+ tool_calls: toolCalls.length > 0 ? toolCalls : void 0
13533
+ },
13534
+ logprobs: choice.logprobs ?? null,
13535
+ finish_reason: choice.finish_reason
13536
+ };
13537
+ }
13229
13538
  function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
13230
- let role = void 0;
13231
- let content = void 0;
13232
- let refusal = void 0;
13233
- let tool_calls = void 0;
13234
- let logprobs = void 0;
13235
- let finish_reason = void 0;
13539
+ const choicesByIndex = /* @__PURE__ */ new Map();
13236
13540
  let metrics = {};
13237
13541
  for (const chunk of chunks) {
13238
13542
  if (chunk.usage) {
@@ -13241,62 +13545,75 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
13241
13545
  ...parseMetricsFromUsage(chunk.usage)
13242
13546
  };
13243
13547
  }
13244
- const choice = chunk.choices?.[0];
13245
- if (!choice) {
13548
+ const choices = chunk.choices;
13549
+ if (!choices?.length) {
13246
13550
  continue;
13247
13551
  }
13248
- if (choice.finish_reason) {
13249
- finish_reason = choice.finish_reason;
13250
- }
13251
- logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
13252
- const delta = choice.delta;
13253
- if (!delta) {
13254
- continue;
13255
- }
13256
- if (delta.finish_reason) {
13257
- finish_reason = delta.finish_reason;
13258
- }
13259
- if (!role && delta.role) {
13260
- role = delta.role;
13261
- }
13262
- if (delta.content) {
13263
- content = (content || "") + delta.content;
13264
- }
13265
- if (delta.refusal) {
13266
- refusal = (refusal || "") + delta.refusal;
13267
- }
13268
- if (delta.tool_calls) {
13269
- const toolDelta = delta.tool_calls[0];
13270
- if (!tool_calls || toolDelta.id && tool_calls[tool_calls.length - 1].id !== toolDelta.id) {
13271
- tool_calls = [
13272
- ...tool_calls || [],
13273
- {
13274
- id: toolDelta.id,
13275
- type: toolDelta.type,
13276
- function: toolDelta.function
13552
+ for (const choice of choices) {
13553
+ const choiceIndex = choice.index;
13554
+ let aggregatedChoice = choicesByIndex.get(choiceIndex);
13555
+ if (!aggregatedChoice) {
13556
+ aggregatedChoice = createAggregatedChatChoice(choiceIndex);
13557
+ choicesByIndex.set(choiceIndex, aggregatedChoice);
13558
+ }
13559
+ if (choice.finish_reason) {
13560
+ aggregatedChoice.finish_reason = choice.finish_reason;
13561
+ }
13562
+ aggregatedChoice.logprobs = aggregateChatLogprobs(
13563
+ aggregatedChoice.logprobs,
13564
+ choice.logprobs
13565
+ );
13566
+ const delta = choice.delta;
13567
+ if (!delta) {
13568
+ continue;
13569
+ }
13570
+ if (delta.finish_reason) {
13571
+ aggregatedChoice.finish_reason = delta.finish_reason;
13572
+ }
13573
+ if (!aggregatedChoice.role && delta.role) {
13574
+ aggregatedChoice.role = delta.role;
13575
+ }
13576
+ if (delta.content) {
13577
+ aggregatedChoice.content = (aggregatedChoice.content || "") + delta.content;
13578
+ }
13579
+ if (delta.refusal) {
13580
+ aggregatedChoice.refusal = (aggregatedChoice.refusal || "") + delta.refusal;
13581
+ }
13582
+ if (delta.tool_calls) {
13583
+ for (const toolDelta of delta.tool_calls) {
13584
+ let aggregatedToolCall = aggregatedChoice.toolCallsByIndex.get(
13585
+ toolDelta.index
13586
+ );
13587
+ if (!aggregatedToolCall) {
13588
+ aggregatedToolCall = {
13589
+ function: { arguments: "" }
13590
+ };
13591
+ aggregatedChoice.toolCallsByIndex.set(
13592
+ toolDelta.index,
13593
+ aggregatedToolCall
13594
+ );
13277
13595
  }
13278
- ];
13279
- } else {
13280
- tool_calls[tool_calls.length - 1].function.arguments += toolDelta.function.arguments;
13596
+ if (toolDelta.id !== void 0) {
13597
+ aggregatedToolCall.id = toolDelta.id;
13598
+ }
13599
+ if (toolDelta.type !== void 0) {
13600
+ aggregatedToolCall.type = toolDelta.type;
13601
+ }
13602
+ if (toolDelta.function?.name !== void 0) {
13603
+ aggregatedToolCall.function.name = toolDelta.function.name;
13604
+ }
13605
+ if (toolDelta.function?.arguments !== void 0) {
13606
+ aggregatedToolCall.function.arguments += toolDelta.function.arguments;
13607
+ }
13608
+ }
13281
13609
  }
13282
13610
  }
13283
13611
  }
13284
13612
  metrics = withCachedMetric(metrics, streamResult, endEvent);
13613
+ const output = Array.from(choicesByIndex.values()).sort((left, right) => left.index - right.index).map(toChatChoice);
13285
13614
  return {
13286
13615
  metrics,
13287
- output: [
13288
- {
13289
- index: 0,
13290
- message: {
13291
- role,
13292
- content,
13293
- ...refusal !== void 0 ? { refusal } : {},
13294
- tool_calls
13295
- },
13296
- logprobs: logprobs ?? null,
13297
- finish_reason
13298
- }
13299
- ]
13616
+ output: output.length > 0 ? output : [toChatChoice(createAggregatedChatChoice(0))]
13300
13617
  };
13301
13618
  }
13302
13619
  function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
@@ -14619,6 +14936,12 @@ function parseMetricsFromUsage2(usage) {
14619
14936
  }
14620
14937
  }
14621
14938
  }
14939
+ if (isObject(usage.output_tokens_details)) {
14940
+ const thinkingTokens = usage.output_tokens_details.thinking_tokens;
14941
+ if (typeof thinkingTokens === "number") {
14942
+ metrics.completion_reasoning_tokens = thinkingTokens;
14943
+ }
14944
+ }
14622
14945
  if (isObject(usage.server_tool_use)) {
14623
14946
  for (const [name, value] of Object.entries(usage.server_tool_use)) {
14624
14947
  if (typeof value === "number") {
@@ -15575,7 +15898,6 @@ function endHarnessTurn(parent) {
15575
15898
  function braintrustAISDKTelemetry() {
15576
15899
  const operations = /* @__PURE__ */ new Map();
15577
15900
  const operationKeysByCallId = /* @__PURE__ */ new Map();
15578
- const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
15579
15901
  const modelSpans = /* @__PURE__ */ new Map();
15580
15902
  const objectSpans = /* @__PURE__ */ new Map();
15581
15903
  const embedSpans = /* @__PURE__ */ new Map();
@@ -15618,9 +15940,6 @@ function braintrustAISDKTelemetry() {
15618
15940
  return;
15619
15941
  }
15620
15942
  operations.delete(operationKey);
15621
- if (workflowOperationKeyStore.getStore() === operationKey) {
15622
- workflowOperationKeyStore.enterWith(void 0);
15623
- }
15624
15943
  const keys = operationKeysByCallId.get(state.callId);
15625
15944
  if (!keys) {
15626
15945
  return;
@@ -15668,14 +15987,7 @@ function braintrustAISDKTelemetry() {
15668
15987
  return key;
15669
15988
  }
15670
15989
  }
15671
- const workflowOperationKey = workflowOperationKeyStore.getStore();
15672
- if (workflowOperationKey && keys.includes(workflowOperationKey)) {
15673
- return workflowOperationKey;
15674
- }
15675
- if (callId === "workflow-agent") {
15676
- return void 0;
15677
- }
15678
- return mode === "finish" ? keys[0] : keys[keys.length - 1];
15990
+ return callId === "workflow-agent" || mode === "active" ? keys[keys.length - 1] : keys[0];
15679
15991
  };
15680
15992
  const operationKeyFromEvent = (event, mode = "active") => {
15681
15993
  const explicit = explicitOperationKey(event);
@@ -15689,17 +16001,13 @@ function braintrustAISDKTelemetry() {
15689
16001
  if (operationKey) {
15690
16002
  return operationKey;
15691
16003
  }
15692
- const workflowOperationKey2 = workflowOperationKeyStore.getStore();
15693
- if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
15694
- return workflowOperationKey2;
16004
+ const workflowAgentKeys2 = operationKeysByCallId.get("workflow-agent");
16005
+ if (workflowAgentKeys2?.length) {
16006
+ return workflowAgentKeys2[workflowAgentKeys2.length - 1];
15695
16007
  }
15696
16008
  return callId === "workflow-agent" ? void 0 : callId;
15697
16009
  }
15698
16010
  }
15699
- const workflowOperationKey = workflowOperationKeyStore.getStore();
15700
- if (workflowOperationKey && operations.has(workflowOperationKey)) {
15701
- return workflowOperationKey;
15702
- }
15703
16011
  const wrapperSpan = currentWorkflowAgentWrapperSpan();
15704
16012
  if (wrapperSpan?.spanId) {
15705
16013
  for (const [operationKey, state] of operations) {
@@ -15709,8 +16017,8 @@ function braintrustAISDKTelemetry() {
15709
16017
  }
15710
16018
  }
15711
16019
  const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
15712
- if (workflowAgentKeys?.length === 1) {
15713
- return workflowAgentKeys[0];
16020
+ if (workflowAgentKeys?.length) {
16021
+ return workflowAgentKeys[workflowAgentKeys.length - 1];
15714
16022
  }
15715
16023
  if (operations.size === 1) {
15716
16024
  return operations.keys().next().value;
@@ -15913,9 +16221,6 @@ function braintrustAISDKTelemetry() {
15913
16221
  if (!ownsSpan) {
15914
16222
  return;
15915
16223
  }
15916
- if (workflowAgent) {
15917
- workflowOperationKeyStore.enterWith(operationKey);
15918
- }
15919
16224
  let metadata = metadataFromEvent(event);
15920
16225
  const logPayload = { metadata };
15921
16226
  const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
@@ -16387,6 +16692,10 @@ var aiSDKChannels = defineChannels(
16387
16692
  channelName: "generateText",
16388
16693
  kind: "async"
16389
16694
  }),
16695
+ generateImage: channel({
16696
+ channelName: "generateImage",
16697
+ kind: "async"
16698
+ }),
16390
16699
  streamText: channel({
16391
16700
  channelName: "streamText",
16392
16701
  kind: "async"
@@ -16574,7 +16883,7 @@ var AISDKPlugin = class extends BasePlugin {
16574
16883
  }
16575
16884
  subscribeToAISDK() {
16576
16885
  const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
16577
- this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
16886
+ this.unsubscribers.push(interceptAISDKV7TelemetryDispatcher());
16578
16887
  this.unsubscribers.push(subscribeToHarnessAgentCreateSession());
16579
16888
  this.unsubscribers.push(
16580
16889
  subscribeToHarnessContinuation(
@@ -16602,6 +16911,18 @@ var AISDKPlugin = class extends BasePlugin {
16602
16911
  aggregateChunks: aggregateAISDKChunks
16603
16912
  })
16604
16913
  );
16914
+ this.unsubscribers.push(
16915
+ traceAsyncChannel(aiSDKChannels.generateImage, {
16916
+ name: "generateImage",
16917
+ type: "llm" /* LLM */,
16918
+ extractInput: ([params], event) => prepareAISDKGenerateImageInput(params, event.self),
16919
+ extractOutput: (result, endEvent) => processAISDKGenerateImageOutput(
16920
+ result,
16921
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
16922
+ ),
16923
+ extractMetrics: (result) => extractTokenMetrics(result)
16924
+ })
16925
+ );
16605
16926
  this.unsubscribers.push(
16606
16927
  traceStreamingChannel(aiSDKChannels.streamText, {
16607
16928
  name: "streamText",
@@ -17091,26 +17412,29 @@ function subscribeToHarnessContinuation(continuationChannel, defaultDenyOutputPa
17091
17412
  channel2.unsubscribe(handlers);
17092
17413
  };
17093
17414
  }
17094
- function subscribeToAISDKV7TelemetryDispatcher() {
17095
- const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
17415
+ function interceptAISDKV7TelemetryDispatcher() {
17096
17416
  const telemetry = braintrustAISDKTelemetry();
17097
- const handlers = {
17098
- end: (event) => {
17099
- const telemetryOptions = event.arguments?.[0]?.telemetry;
17100
- if (telemetryOptions?.isEnabled === false) {
17101
- return;
17417
+ return aiSDKChannels.v7CreateTelemetryDispatcher.intercept(
17418
+ (target, thisArg, args) => {
17419
+ const dispatcher = Reflect.apply(target, thisArg, args);
17420
+ const telemetryOptions = args[0]?.telemetry;
17421
+ if (telemetryOptions?.isEnabled !== false) {
17422
+ try {
17423
+ patchAISDKV7TelemetryDispatcher(
17424
+ dispatcher,
17425
+ telemetry,
17426
+ telemetryOptions
17427
+ );
17428
+ } catch (error) {
17429
+ debugLogger.error(
17430
+ "Error instrumenting AI SDK v7 telemetry dispatcher:",
17431
+ error
17432
+ );
17433
+ }
17102
17434
  }
17103
- patchAISDKV7TelemetryDispatcher(
17104
- event.result,
17105
- telemetry,
17106
- telemetryOptions
17107
- );
17435
+ return dispatcher;
17108
17436
  }
17109
- };
17110
- channel2.subscribe(handlers);
17111
- return () => {
17112
- channel2.unsubscribe(handlers);
17113
- };
17437
+ );
17114
17438
  }
17115
17439
  function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
17116
17440
  if (!isObject(dispatcher)) {
@@ -17435,16 +17759,10 @@ var convertImageToAttachment = (image, explicitMimeType) => {
17435
17759
  }
17436
17760
  }
17437
17761
  if (explicitMimeType) {
17438
- if (image instanceof Uint8Array) {
17439
- return new Attachment({
17440
- data: new Blob([image], { type: explicitMimeType }),
17441
- filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
17442
- contentType: explicitMimeType
17443
- });
17444
- }
17445
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
17762
+ const blob = convertDataToBlob(image, explicitMimeType);
17763
+ if (blob) {
17446
17764
  return new Attachment({
17447
- data: new Blob([image], { type: explicitMimeType }),
17765
+ data: blob,
17448
17766
  filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
17449
17767
  contentType: explicitMimeType
17450
17768
  });
@@ -17498,6 +17816,25 @@ var convertDataToAttachment = (data, mimeType, filename) => {
17498
17816
  function processAISDKCallInput(params) {
17499
17817
  return processInputAttachmentsSync(params);
17500
17818
  }
17819
+ function processAISDKGenerateImageInput(params) {
17820
+ const prompt = params.prompt;
17821
+ if (!isObject(prompt) || Array.isArray(prompt)) {
17822
+ return processAISDKCallInput(params);
17823
+ }
17824
+ const processedPrompt = { ...prompt };
17825
+ if (Array.isArray(prompt.images)) {
17826
+ processedPrompt.images = prompt.images.map(
17827
+ (image) => convertImageToAttachment(image, "image/png") ?? image
17828
+ );
17829
+ }
17830
+ if (prompt.mask !== void 0) {
17831
+ processedPrompt.mask = convertImageToAttachment(prompt.mask, "image/png") ?? prompt.mask;
17832
+ }
17833
+ return processAISDKCallInput({
17834
+ ...params,
17835
+ prompt: processedPrompt
17836
+ });
17837
+ }
17501
17838
  function processAISDKWorkflowAgentCallInput(params) {
17502
17839
  const processed = processAISDKCallInput(params);
17503
17840
  return {
@@ -17636,6 +17973,12 @@ function prepareAISDKEmbedInput(params, self) {
17636
17973
  metadata: extractMetadataFromEmbedParams(params, self)
17637
17974
  };
17638
17975
  }
17976
+ function prepareAISDKGenerateImageInput(params, self) {
17977
+ return {
17978
+ input: processAISDKGenerateImageInput(params).input,
17979
+ metadata: extractMetadataFromCallParams(params, self)
17980
+ };
17981
+ }
17639
17982
  function prepareAISDKRerankInput(params, self) {
17640
17983
  const { documents, query } = params;
17641
17984
  return {
@@ -19011,6 +19354,57 @@ function processAISDKOutput(output, denyOutputPaths) {
19011
19354
  }
19012
19355
  return normalizeAISDKLoggedOutput(sanitized);
19013
19356
  }
19357
+ function processAISDKGenerateImageOutput(output, denyOutputPaths) {
19358
+ if (!output || typeof output !== "object") {
19359
+ return output;
19360
+ }
19361
+ const summarized = {};
19362
+ for (const field of [
19363
+ "usage",
19364
+ "warnings",
19365
+ "providerMetadata",
19366
+ "experimental_providerMetadata",
19367
+ "responses"
19368
+ ]) {
19369
+ const value = safeSerializableFieldRead(output, field);
19370
+ if (value !== void 0 && isSerializableOutputValue(value)) {
19371
+ summarized[field] = value;
19372
+ }
19373
+ }
19374
+ const images = safeSerializableFieldRead(output, "images");
19375
+ const image = safeSerializableFieldRead(output, "image");
19376
+ const generatedFiles = Array.isArray(images) && images.length > 0 ? images : image !== void 0 ? [image] : [];
19377
+ const loggedOutput = normalizeAISDKLoggedOutput(
19378
+ omit(summarized, denyOutputPaths)
19379
+ );
19380
+ if (generatedFiles.length > 0) {
19381
+ loggedOutput.images = generatedFiles.map(
19382
+ (file, index) => convertAISDKGeneratedFileToAttachment(file, index)
19383
+ );
19384
+ }
19385
+ return loggedOutput;
19386
+ }
19387
+ function convertAISDKGeneratedFileToAttachment(file, index) {
19388
+ if (!file || typeof file !== "object") {
19389
+ return file;
19390
+ }
19391
+ const generatedFile = file;
19392
+ const generatedMediaType = safeSerializableFieldRead(
19393
+ generatedFile,
19394
+ "mediaType"
19395
+ );
19396
+ const mediaType = typeof generatedMediaType === "string" ? generatedMediaType : "application/octet-stream";
19397
+ const data = safeSerializableFieldRead(generatedFile, "base64") ?? safeSerializableFieldRead(generatedFile, "uint8Array");
19398
+ const blob = convertDataToBlob(data, mediaType);
19399
+ if (blob) {
19400
+ return new Attachment({
19401
+ data: blob,
19402
+ filename: `generated_image_${index}.${getExtensionFromMediaType(mediaType)}`,
19403
+ contentType: mediaType
19404
+ });
19405
+ }
19406
+ return file;
19407
+ }
19014
19408
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
19015
19409
  if (!output || typeof output !== "object") {
19016
19410
  return output;
@@ -19511,118 +19905,22 @@ var claudeAgentSDKChannels = defineChannels(
19511
19905
  var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
19512
19906
 
19513
19907
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
19514
- var LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED = /* @__PURE__ */ Symbol.for(
19515
- "braintrust.claude_agent_sdk.local_tool_context_async_iterator_patched"
19516
- );
19517
- function createLocalToolContextStore() {
19518
- const maybeIsoWithAsyncLocalStorage = isomorph_default;
19519
- if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
19520
- return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
19521
- }
19522
- let currentStore;
19523
- return {
19524
- enterWith(store) {
19525
- currentStore = store;
19526
- },
19527
- getStore() {
19528
- return currentStore;
19529
- },
19530
- run(store, callback) {
19531
- const previousStore = currentStore;
19532
- currentStore = store;
19533
- try {
19534
- return callback();
19535
- } finally {
19536
- currentStore = previousStore;
19537
- }
19538
- }
19539
- };
19908
+ var localToolContextStore = isomorph_default.newAsyncLocalStorage();
19909
+ var localToolParentResolversByToolUseId = /* @__PURE__ */ new Map();
19910
+ function runWithClaudeLocalToolContext(callback, resolver) {
19911
+ return localToolContextStore.run(resolver, callback);
19540
19912
  }
19541
- var localToolContextStore = createLocalToolContextStore();
19542
- var fallbackLocalToolParentResolver;
19543
- function createClaudeLocalToolContext() {
19544
- return {};
19913
+ function registerClaudeLocalToolParentResolver(toolUseId, resolver) {
19914
+ localToolParentResolversByToolUseId.set(toolUseId, resolver);
19545
19915
  }
19546
- function runWithClaudeLocalToolContext(callback, context) {
19547
- return localToolContextStore.run(
19548
- context ?? createClaudeLocalToolContext(),
19549
- callback
19550
- );
19551
- }
19552
- function ensureClaudeLocalToolContext() {
19553
- const existing = localToolContextStore.getStore();
19554
- if (existing) {
19555
- return existing;
19556
- }
19557
- const created = {};
19558
- localToolContextStore.enterWith(created);
19559
- return created;
19560
- }
19561
- function setClaudeLocalToolParentResolver(resolver) {
19562
- fallbackLocalToolParentResolver = resolver;
19563
- const context = ensureClaudeLocalToolContext();
19564
- if (!context) {
19565
- return;
19916
+ function getClaudeLocalToolParentResolver(toolUseId) {
19917
+ const currentResolver = localToolContextStore.getStore();
19918
+ if (!toolUseId) {
19919
+ return currentResolver;
19566
19920
  }
19567
- context.resolveLocalToolParent = resolver;
19568
- }
19569
- function getClaudeLocalToolParentResolver() {
19570
- return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
19571
- }
19572
- function isAsyncIterable3(value) {
19573
- return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
19574
- }
19575
- function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
19576
- if (!isAsyncIterable3(result) || Object.isFrozen(result) || Object.isSealed(result)) {
19577
- return result;
19578
- }
19579
- const stream = result;
19580
- const originalAsyncIterator = stream[Symbol.asyncIterator];
19581
- if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
19582
- return result;
19583
- }
19584
- const patchedAsyncIterator = function() {
19585
- return runWithClaudeLocalToolContext(() => {
19586
- const iterator = Reflect.apply(originalAsyncIterator, this, []);
19587
- if (!iterator || typeof iterator !== "object") {
19588
- return iterator;
19589
- }
19590
- const patchMethod = (methodName) => {
19591
- const originalMethod = Reflect.get(iterator, methodName);
19592
- if (typeof originalMethod !== "function") {
19593
- return;
19594
- }
19595
- Reflect.set(
19596
- iterator,
19597
- methodName,
19598
- (...args) => runWithClaudeLocalToolContext(
19599
- () => Reflect.apply(
19600
- originalMethod,
19601
- iterator,
19602
- args
19603
- ),
19604
- localToolContext
19605
- )
19606
- );
19607
- };
19608
- patchMethod("next");
19609
- patchMethod("return");
19610
- patchMethod("throw");
19611
- return iterator;
19612
- }, localToolContext);
19613
- };
19614
- Object.defineProperty(
19615
- patchedAsyncIterator,
19616
- LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
19617
- {
19618
- configurable: false,
19619
- enumerable: false,
19620
- value: true,
19621
- writable: false
19622
- }
19623
- );
19624
- Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
19625
- return result;
19921
+ const registeredResolver = localToolParentResolversByToolUseId.get(toolUseId);
19922
+ localToolParentResolversByToolUseId.delete(toolUseId);
19923
+ return currentResolver ?? registeredResolver;
19626
19924
  }
19627
19925
 
19628
19926
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
@@ -19648,7 +19946,7 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
19648
19946
  const metadata = getMetadata();
19649
19947
  const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
19650
19948
  const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
19651
- const localToolParentResolver = getClaudeLocalToolParentResolver();
19949
+ const localToolParentResolver = getClaudeLocalToolParentResolver(toolUseId);
19652
19950
  const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
19653
19951
  const runWithResolvedParent = async () => {
19654
19952
  const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
@@ -20175,6 +20473,7 @@ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToP
20175
20473
  }
20176
20474
  }
20177
20475
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
20476
+ registerClaudeLocalToolParentResolver(toolUseID, resolveParentSpan);
20178
20477
  return {};
20179
20478
  }
20180
20479
  const parsed = parseToolName(input.tool_name);
@@ -20885,7 +21184,7 @@ async function finalizeQuerySpan(state) {
20885
21184
  }
20886
21185
  var ClaudeAgentSDKPlugin = class extends BasePlugin {
20887
21186
  onEnable() {
20888
- this.subscribeToQuery();
21187
+ this.interceptQuery();
20889
21188
  }
20890
21189
  onDisable() {
20891
21190
  for (const unsubscribe of this.unsubscribers) {
@@ -20893,211 +21192,218 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
20893
21192
  }
20894
21193
  this.unsubscribers = [];
20895
21194
  }
20896
- subscribeToQuery() {
20897
- const channel2 = claudeAgentSDKChannels.query.tracingChannel();
20898
- const spans = /* @__PURE__ */ new WeakMap();
20899
- const handlers = {
20900
- start: (event) => {
20901
- const params = event.arguments[0] ?? {};
20902
- const originalPrompt = params.prompt;
20903
- const options = params.options ?? {};
20904
- const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
20905
- let promptStarted = false;
20906
- let capturedPromptMessages;
20907
- let resolvePromptDone;
20908
- const promptDone = new Promise((resolve) => {
20909
- resolvePromptDone = resolve;
20910
- });
20911
- if (promptIsAsyncIterable) {
20912
- capturedPromptMessages = [];
20913
- const promptStream = originalPrompt;
20914
- params.prompt = (async function* () {
20915
- promptStarted = true;
20916
- try {
20917
- for await (const message of promptStream) {
20918
- capturedPromptMessages.push(message);
20919
- yield message;
20920
- }
20921
- } finally {
20922
- resolvePromptDone?.();
21195
+ interceptQuery() {
21196
+ const startQuery = (params) => {
21197
+ const originalPrompt = params.prompt;
21198
+ const options = params.options ?? {};
21199
+ const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
21200
+ let promptStarted = false;
21201
+ let capturedPromptMessages;
21202
+ let resolvePromptDone;
21203
+ const promptDone = new Promise((resolve) => {
21204
+ resolvePromptDone = resolve;
21205
+ });
21206
+ if (promptIsAsyncIterable) {
21207
+ capturedPromptMessages = [];
21208
+ const promptStream = originalPrompt;
21209
+ params.prompt = (async function* () {
21210
+ promptStarted = true;
21211
+ try {
21212
+ for await (const message of promptStream) {
21213
+ capturedPromptMessages.push(message);
21214
+ yield message;
20923
21215
  }
20924
- })();
20925
- }
20926
- const span = startSpan(
20927
- withSpanInstrumentationName(
20928
- {
20929
- name: "Claude Agent",
20930
- spanAttributes: {
20931
- type: "task" /* TASK */
20932
- }
20933
- },
20934
- INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
20935
- )
20936
- );
20937
- const startTime = getCurrentUnixTimestamp();
20938
- try {
20939
- span.log({
20940
- input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
20941
- metadata: filterSerializableOptions(options)
20942
- });
20943
- } catch (error) {
20944
- console.error("Error extracting input for Claude Agent SDK:", error);
20945
- }
20946
- const activeToolSpans = /* @__PURE__ */ new Map();
20947
- const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
20948
- const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
20949
- const subAgentSpans = /* @__PURE__ */ new Map();
20950
- const endedSubAgentSpans = /* @__PURE__ */ new Set();
20951
- const toolUseToParent = /* @__PURE__ */ new Map();
20952
- const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
20953
- const latestRootLlmParentRef = {
20954
- value: void 0
20955
- };
20956
- const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
20957
- const taskIdToToolUseId = /* @__PURE__ */ new Map();
20958
- const promptMessagesByParentKey = /* @__PURE__ */ new Map();
20959
- const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
20960
- const localToolContext = createClaudeLocalToolContext();
20961
- const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
20962
- const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
20963
- const resolveToolUseParentSpan = async (toolUseID, context) => {
20964
- const trackedParentToolUseId = toolUseToParent.get(toolUseID);
20965
- const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
20966
- const parentKey = llmParentKey(parentToolUseId);
20967
- const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
20968
- const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
20969
- if (!activeLlmSpan && !latestLlmParent) {
20970
- await ensureActiveLlmSpanForParentToolUse(
20971
- span,
20972
- activeLlmSpansByParentToolUse,
20973
- subAgentDetailsByToolUseId,
20974
- activeToolSpans,
20975
- subAgentSpans,
20976
- parentToolUseId,
20977
- getCurrentUnixTimestamp()
20978
- );
20979
- }
20980
- if (parentToolUseId) {
20981
- const subAgentSpan = await ensureSubAgentSpan(
20982
- subAgentDetailsByToolUseId,
20983
- span,
20984
- activeToolSpans,
20985
- subAgentSpans,
20986
- parentToolUseId
20987
- );
20988
- return subAgentSpan.export();
21216
+ } finally {
21217
+ resolvePromptDone?.();
20989
21218
  }
20990
- return span.export();
20991
- };
20992
- localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
20993
- setClaudeLocalToolParentResolver(resolveToolUseParentSpan);
20994
- const optionsWithHooks = injectTracingHooks(
20995
- options,
20996
- resolveToolUseParentSpan,
20997
- taskIdToToolUseId,
20998
- toolUseToParent,
20999
- activeToolSpans,
21000
- localToolHookNames,
21001
- skipLocalToolHooks,
21002
- subAgentDetailsByToolUseId,
21003
- subAgentSpans,
21004
- endedSubAgentSpans
21005
- );
21006
- params.options = optionsWithHooks;
21007
- event.arguments[0] = params;
21008
- spans.set(event, {
21009
- activeLlmSpansByParentToolUse,
21010
- activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
21011
- activeToolSpans,
21012
- conversationHistoryByParentKey,
21013
- capturedPromptMessages,
21014
- currentMessageId: void 0,
21015
- currentMessageStartTime: startTime,
21016
- currentMessages: [],
21017
- endedSubAgentSpans,
21018
- finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
21019
- finalResults: [],
21020
- options: optionsWithHooks,
21021
- originalPrompt,
21022
- processing: Promise.resolve(),
21023
- promptDone,
21024
- promptMessagesByParentKey,
21025
- promptStarted: () => promptStarted,
21026
- promptSourcePriorityByParentKey,
21027
- span,
21028
- subAgentDetailsByToolUseId,
21029
- subAgentSpans,
21030
- taskIdToToolUseId,
21031
- latestLlmParentBySubAgentToolUse,
21032
- latestRootLlmParentRef,
21033
- toolUseToParent,
21034
- usageByMessageId: /* @__PURE__ */ new Map(),
21035
- localToolContext
21219
+ })();
21220
+ }
21221
+ const span = startSpan(
21222
+ withSpanInstrumentationName(
21223
+ {
21224
+ name: "Claude Agent",
21225
+ spanAttributes: {
21226
+ type: "task" /* TASK */
21227
+ }
21228
+ },
21229
+ INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
21230
+ )
21231
+ );
21232
+ const startTime = getCurrentUnixTimestamp();
21233
+ try {
21234
+ span.log({
21235
+ input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
21236
+ metadata: filterSerializableOptions(options)
21036
21237
  });
21037
- },
21038
- end: (event) => {
21039
- const state = spans.get(event);
21040
- if (!state) {
21041
- return;
21042
- }
21043
- const eventResult = bindClaudeLocalToolContextToAsyncIterable(
21044
- event.result,
21045
- state.localToolContext
21046
- );
21047
- if (eventResult === void 0) {
21048
- state.span.end();
21049
- spans.delete(event);
21050
- return;
21051
- }
21052
- if (isAsyncIterable(eventResult)) {
21053
- patchStreamIfNeeded(eventResult, {
21054
- onChunk: (message) => {
21055
- maybeTrackToolUseContext(state, message);
21056
- state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
21057
- console.error(
21058
- "Error processing Claude Agent SDK stream chunk:",
21059
- error
21060
- );
21061
- });
21062
- },
21063
- onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
21064
- spans.delete(event);
21065
- }),
21066
- onError: (error) => state.processing.then(() => {
21067
- state.span.log({
21068
- error: error.message
21069
- });
21070
- }).then(() => finalizeQuerySpan(state)).finally(() => {
21071
- spans.delete(event);
21072
- })
21073
- });
21074
- return;
21075
- }
21076
- try {
21077
- state.span.log({ output: eventResult });
21078
- } catch (error) {
21079
- console.error("Error extracting output for Claude Agent SDK:", error);
21080
- } finally {
21081
- state.span.end();
21082
- spans.delete(event);
21238
+ } catch (error) {
21239
+ console.error("Error extracting input for Claude Agent SDK:", error);
21240
+ }
21241
+ const activeToolSpans = /* @__PURE__ */ new Map();
21242
+ const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
21243
+ const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
21244
+ const subAgentSpans = /* @__PURE__ */ new Map();
21245
+ const endedSubAgentSpans = /* @__PURE__ */ new Set();
21246
+ const toolUseToParent = /* @__PURE__ */ new Map();
21247
+ const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
21248
+ const latestRootLlmParentRef = {
21249
+ value: void 0
21250
+ };
21251
+ const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
21252
+ const taskIdToToolUseId = /* @__PURE__ */ new Map();
21253
+ const promptMessagesByParentKey = /* @__PURE__ */ new Map();
21254
+ const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
21255
+ const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
21256
+ const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
21257
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
21258
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
21259
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
21260
+ const parentKey = llmParentKey(parentToolUseId);
21261
+ const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
21262
+ const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
21263
+ if (!activeLlmSpan && !latestLlmParent) {
21264
+ await ensureActiveLlmSpanForParentToolUse(
21265
+ span,
21266
+ activeLlmSpansByParentToolUse,
21267
+ subAgentDetailsByToolUseId,
21268
+ activeToolSpans,
21269
+ subAgentSpans,
21270
+ parentToolUseId,
21271
+ getCurrentUnixTimestamp()
21272
+ );
21083
21273
  }
21084
- },
21085
- error: (event) => {
21086
- const state = spans.get(event);
21087
- if (!state || !event.error) {
21088
- return;
21274
+ if (parentToolUseId) {
21275
+ const subAgentSpan = await ensureSubAgentSpan(
21276
+ subAgentDetailsByToolUseId,
21277
+ span,
21278
+ activeToolSpans,
21279
+ subAgentSpans,
21280
+ parentToolUseId
21281
+ );
21282
+ return subAgentSpan.export();
21089
21283
  }
21090
- state.span.log({
21091
- error: event.error.message
21284
+ return span.export();
21285
+ };
21286
+ const optionsWithHooks = injectTracingHooks(
21287
+ options,
21288
+ resolveToolUseParentSpan,
21289
+ taskIdToToolUseId,
21290
+ toolUseToParent,
21291
+ activeToolSpans,
21292
+ localToolHookNames,
21293
+ skipLocalToolHooks,
21294
+ subAgentDetailsByToolUseId,
21295
+ subAgentSpans,
21296
+ endedSubAgentSpans
21297
+ );
21298
+ params.options = optionsWithHooks;
21299
+ return {
21300
+ activeLlmSpansByParentToolUse,
21301
+ activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
21302
+ activeToolSpans,
21303
+ conversationHistoryByParentKey,
21304
+ capturedPromptMessages,
21305
+ currentMessageId: void 0,
21306
+ currentMessageStartTime: startTime,
21307
+ currentMessages: [],
21308
+ endedSubAgentSpans,
21309
+ finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
21310
+ finalResults: [],
21311
+ options: optionsWithHooks,
21312
+ originalPrompt,
21313
+ processing: Promise.resolve(),
21314
+ promptDone,
21315
+ promptMessagesByParentKey,
21316
+ promptStarted: () => promptStarted,
21317
+ promptSourcePriorityByParentKey,
21318
+ span,
21319
+ subAgentDetailsByToolUseId,
21320
+ subAgentSpans,
21321
+ taskIdToToolUseId,
21322
+ latestLlmParentBySubAgentToolUse,
21323
+ latestRootLlmParentRef,
21324
+ toolUseToParent,
21325
+ usageByMessageId: /* @__PURE__ */ new Map(),
21326
+ localToolParentResolver: resolveToolUseParentSpan
21327
+ };
21328
+ };
21329
+ const finishQuery = (state, result) => {
21330
+ if (isAsyncIterable(result)) {
21331
+ patchStreamIfNeeded(result, {
21332
+ aroundNext: (callback) => runWithClaudeLocalToolContext(
21333
+ callback,
21334
+ state.localToolParentResolver
21335
+ ),
21336
+ onChunk: (message) => {
21337
+ maybeTrackToolUseContext(state, message);
21338
+ state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
21339
+ console.error(
21340
+ "Error processing Claude Agent SDK stream chunk:",
21341
+ error
21342
+ );
21343
+ });
21344
+ },
21345
+ onComplete: () => state.processing.then(() => finalizeQuerySpan(state)),
21346
+ onError: (error) => state.processing.then(() => {
21347
+ state.span.log({ error: error.message });
21348
+ }).then(() => finalizeQuerySpan(state))
21092
21349
  });
21350
+ return;
21351
+ }
21352
+ try {
21353
+ state.span.log({ output: result });
21354
+ } catch (error) {
21355
+ console.error("Error extracting output for Claude Agent SDK:", error);
21356
+ } finally {
21093
21357
  state.span.end();
21094
- spans.delete(event);
21095
21358
  }
21096
21359
  };
21097
- channel2.subscribe(handlers);
21098
- this.unsubscribers.push(() => {
21099
- channel2.unsubscribe(handlers);
21100
- });
21360
+ this.unsubscribers.push(
21361
+ claudeAgentSDKChannels.query.intercept((target, thisArg, args) => {
21362
+ let state;
21363
+ try {
21364
+ args[0] ??= {};
21365
+ state = startQuery(args[0]);
21366
+ } catch (error) {
21367
+ debugLogger.error(
21368
+ "Error starting Claude Agent SDK instrumentation:",
21369
+ error
21370
+ );
21371
+ }
21372
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
21373
+ try {
21374
+ const result = state ? runWithClaudeLocalToolContext(
21375
+ invokeTarget,
21376
+ state.localToolParentResolver
21377
+ ) : invokeTarget();
21378
+ if (state) {
21379
+ try {
21380
+ finishQuery(state, result);
21381
+ } catch (error) {
21382
+ debugLogger.error(
21383
+ "Error finalizing Claude Agent SDK instrumentation:",
21384
+ error
21385
+ );
21386
+ }
21387
+ }
21388
+ return result;
21389
+ } catch (error) {
21390
+ if (state) {
21391
+ try {
21392
+ state.span.log({
21393
+ error: error instanceof Error ? error.message : String(error)
21394
+ });
21395
+ state.span.end();
21396
+ } catch (instrumentationError) {
21397
+ debugLogger.error(
21398
+ "Error handling Claude Agent SDK instrumentation failure:",
21399
+ instrumentationError
21400
+ );
21401
+ }
21402
+ }
21403
+ throw error;
21404
+ }
21405
+ })
21406
+ );
21101
21407
  }
21102
21408
  };
21103
21409
 
@@ -25211,7 +25517,7 @@ function patchOpenRouterCallModelResult(args) {
25211
25517
  span,
25212
25518
  () => originalMethod.apply(resultLike, args2)
25213
25519
  );
25214
- if (!isAsyncIterable4(stream)) {
25520
+ if (!isAsyncIterable3(stream)) {
25215
25521
  return stream;
25216
25522
  }
25217
25523
  return wrapAsyncIterableWithSpan({
@@ -25406,7 +25712,7 @@ function wrapAsyncIterableWithSpan(args) {
25406
25712
  }
25407
25713
  };
25408
25714
  }
25409
- function isAsyncIterable4(value) {
25715
+ function isAsyncIterable3(value) {
25410
25716
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
25411
25717
  }
25412
25718
  function normalizeError(error) {
@@ -26284,7 +26590,7 @@ function patchOpenRouterCallModelResult2(args) {
26284
26590
  span,
26285
26591
  () => originalMethod.apply(resultLike, args2)
26286
26592
  );
26287
- if (!isAsyncIterable5(stream)) {
26593
+ if (!isAsyncIterable4(stream)) {
26288
26594
  return stream;
26289
26595
  }
26290
26596
  return wrapAsyncIterableWithSpan2({
@@ -26479,7 +26785,7 @@ function wrapAsyncIterableWithSpan2(args) {
26479
26785
  }
26480
26786
  };
26481
26787
  }
26482
- function isAsyncIterable5(value) {
26788
+ function isAsyncIterable4(value) {
26483
26789
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
26484
26790
  }
26485
26791
  function normalizeError2(error) {
@@ -32471,12 +32777,14 @@ function getMetricsFromResponse(response) {
32471
32777
  continue;
32472
32778
  }
32473
32779
  const inputTokenDetails = usageMetadata.input_token_details;
32780
+ const outputTokenDetails = usageMetadata.output_token_details;
32474
32781
  return normalizeTokenMetrics({
32475
32782
  total_tokens: usageMetadata.total_tokens,
32476
32783
  prompt_tokens: usageMetadata.input_tokens,
32477
32784
  completion_tokens: usageMetadata.output_tokens,
32478
32785
  prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
32479
- prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
32786
+ prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
32787
+ completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
32480
32788
  });
32481
32789
  }
32482
32790
  const llmOutput = response.llmOutput || {};
@@ -33063,6 +33371,9 @@ var piCodingAgentChannels = defineChannels(
33063
33371
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
33064
33372
  var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
33065
33373
  var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
33374
+ var PI_TOOL_EXECUTE_WRAPPED = /* @__PURE__ */ Symbol.for(
33375
+ "braintrust.pi_coding_agent.tool_execute_wrapped"
33376
+ );
33066
33377
  var piPromptContextStore;
33067
33378
  var PiCodingAgentPlugin = class extends BasePlugin {
33068
33379
  activePromptStates = /* @__PURE__ */ new Set();
@@ -33143,6 +33454,7 @@ function startPiPromptRun(event, onFinalize) {
33143
33454
  return void 0;
33144
33455
  }
33145
33456
  installPiAgentInstrumentation(agent);
33457
+ wrapPiToolExecutors(agent.state?.tools);
33146
33458
  const metadata = {
33147
33459
  ...extractSessionMetadata(session),
33148
33460
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -33239,6 +33551,7 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
33239
33551
  if (!state || state.agent !== agent || state.finalized) {
33240
33552
  return invokeOriginal();
33241
33553
  }
33554
+ wrapPiToolExecutors(context.tools);
33242
33555
  const llmState = await startPiLlmSpan(state, model, context, options);
33243
33556
  try {
33244
33557
  const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
@@ -33249,6 +33562,33 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
33249
33562
  }
33250
33563
  };
33251
33564
  }
33565
+ function wrapPiToolExecutors(tools) {
33566
+ if (!tools) {
33567
+ return;
33568
+ }
33569
+ for (const tool of tools) {
33570
+ try {
33571
+ const execute = tool.execute;
33572
+ if (typeof execute !== "function" || execute[PI_TOOL_EXECUTE_WRAPPED]) {
33573
+ continue;
33574
+ }
33575
+ const wrappedExecute = function(...args) {
33576
+ return runWithAutoInstrumentationAllowed(
33577
+ () => Reflect.apply(execute, this, args)
33578
+ );
33579
+ };
33580
+ Object.defineProperty(wrappedExecute, PI_TOOL_EXECUTE_WRAPPED, {
33581
+ configurable: false,
33582
+ enumerable: false,
33583
+ value: true,
33584
+ writable: false
33585
+ });
33586
+ tool.execute = wrappedExecute;
33587
+ } catch (error) {
33588
+ logInstrumentationError4("Pi Coding Agent tool wrapping", error);
33589
+ }
33590
+ }
33591
+ }
33252
33592
  async function startPiLlmSpan(state, model, context, options) {
33253
33593
  const metadata = {
33254
33594
  ...extractModelMetadata2(model),
@@ -33420,35 +33760,26 @@ async function startPiToolSpan(state, event) {
33420
33760
  if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
33421
33761
  return;
33422
33762
  }
33423
- const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
33424
33763
  const metadata = {
33425
33764
  "gen_ai.tool.call.id": event.toolCallId,
33426
33765
  "gen_ai.tool.name": event.toolName,
33427
33766
  "pi_coding_agent.tool.name": event.toolName
33428
33767
  };
33429
- try {
33430
- const span = startSpan(
33431
- withSpanInstrumentationName(
33432
- {
33433
- event: {
33434
- input: event.args,
33435
- metadata
33436
- },
33437
- name: event.toolName || "tool",
33438
- parent: await state.span.export(),
33439
- spanAttributes: { type: "tool" /* TOOL */ }
33768
+ const span = startSpan(
33769
+ withSpanInstrumentationName(
33770
+ {
33771
+ event: {
33772
+ input: event.args,
33773
+ metadata
33440
33774
  },
33441
- INSTRUMENTATION_NAMES.PI_CODING_AGENT
33442
- )
33443
- );
33444
- state.activeToolSpans.set(event.toolCallId, {
33445
- restoreAutoInstrumentation,
33446
- span
33447
- });
33448
- } catch (error) {
33449
- restoreAutoInstrumentation();
33450
- throw error;
33451
- }
33775
+ name: event.toolName || "tool",
33776
+ parent: await state.span.export(),
33777
+ spanAttributes: { type: "tool" /* TOOL */ }
33778
+ },
33779
+ INSTRUMENTATION_NAMES.PI_CODING_AGENT
33780
+ )
33781
+ );
33782
+ state.activeToolSpans.set(event.toolCallId, { span });
33452
33783
  }
33453
33784
  function finishPiToolSpan(state, event) {
33454
33785
  const toolState = state.activeToolSpans.get(event.toolCallId);
@@ -33469,11 +33800,7 @@ function finishPiToolSpan(state, event) {
33469
33800
  output: event.result
33470
33801
  });
33471
33802
  } finally {
33472
- try {
33473
- toolState.span.end();
33474
- } finally {
33475
- toolState.restoreAutoInstrumentation?.();
33476
- }
33803
+ toolState.span.end();
33477
33804
  }
33478
33805
  }
33479
33806
  function finishPiPromptRun(state, error) {
@@ -33544,14 +33871,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
33544
33871
  }
33545
33872
  function finishOpenToolSpans(state, error) {
33546
33873
  for (const [, toolState] of state.activeToolSpans) {
33547
- try {
33548
- safeLog4(toolState.span, {
33549
- error: error ? toLoggedError(error) : "Pi tool did not complete"
33550
- });
33551
- toolState.span.end();
33552
- } finally {
33553
- toolState.restoreAutoInstrumentation?.();
33554
- }
33874
+ safeLog4(toolState.span, {
33875
+ error: error ? toLoggedError(error) : "Pi tool did not complete"
33876
+ });
33877
+ toolState.span.end();
33555
33878
  }
33556
33879
  state.activeToolSpans.clear();
33557
33880
  }
@@ -33870,12 +34193,12 @@ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
33870
34193
  var StrandsAgentSDKPlugin = class extends BasePlugin {
33871
34194
  activeChildParents = /* @__PURE__ */ new WeakMap();
33872
34195
  onEnable() {
33873
- this.subscribeToAgentStream();
33874
- this.subscribeToMultiAgentStream(
34196
+ this.interceptAgentStream();
34197
+ this.interceptMultiAgentStream(
33875
34198
  strandsAgentSDKChannels.graphStream,
33876
34199
  "Graph.stream"
33877
34200
  );
33878
- this.subscribeToMultiAgentStream(
34201
+ this.interceptMultiAgentStream(
33879
34202
  strandsAgentSDKChannels.swarmStream,
33880
34203
  "Swarm.stream"
33881
34204
  );
@@ -33886,122 +34209,92 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
33886
34209
  }
33887
34210
  this.unsubscribers = [];
33888
34211
  }
33889
- subscribeToAgentStream() {
33890
- const channel2 = strandsAgentSDKChannels.agentStream.tracingChannel();
33891
- const states = /* @__PURE__ */ new WeakMap();
33892
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
33893
- const handlers = {
33894
- start: (event) => {
33895
- const state = startAgentStream(event, this.activeChildParents);
33896
- if (state) {
33897
- states.set(event, state);
33898
- }
33899
- },
33900
- end: (event) => {
33901
- const state = states.get(event);
33902
- if (!state) {
33903
- return;
33904
- }
33905
- const result = event.result;
33906
- if (isAsyncIterable(result)) {
33907
- patchStreamIfNeeded(result, {
33908
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
33909
- onChunk: (chunk) => handleAgentStreamEvent(state, chunk),
33910
- onComplete: () => {
33911
- finalizeAgentStream(state);
33912
- states.delete(event);
33913
- },
33914
- onError: (error) => {
33915
- finalizeAgentStream(state, error);
33916
- states.delete(event);
33917
- }
33918
- });
33919
- return;
33920
- }
33921
- finalizeAgentStream(state, void 0, result);
33922
- states.delete(event);
33923
- },
33924
- error: (event) => {
33925
- const state = states.get(event);
33926
- if (!state || !event.error) {
33927
- return;
33928
- }
33929
- finalizeAgentStream(state, event.error);
33930
- states.delete(event);
33931
- }
33932
- };
33933
- channel2.subscribe(handlers);
33934
- this.unsubscribers.push(() => {
33935
- unbindAutoInstrumentationSuppression?.();
33936
- channel2.unsubscribe(handlers);
33937
- });
34212
+ interceptAgentStream() {
34213
+ this.unsubscribers.push(
34214
+ strandsAgentSDKChannels.agentStream.intercept(
34215
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
34216
+ finalize: finalizeAgentStream,
34217
+ handleChunk: handleAgentStreamEvent,
34218
+ invoke: () => Reflect.apply(target, thisArg, args),
34219
+ name: "Strands Agent SDK",
34220
+ start: () => startAgentStream(
34221
+ args[0],
34222
+ extractAgent(additional.agent, thisArg),
34223
+ this.activeChildParents
34224
+ )
34225
+ })
34226
+ )
34227
+ );
33938
34228
  }
33939
- subscribeToMultiAgentStream(channel2, operation) {
33940
- const tracingChannel = channel2.tracingChannel();
33941
- const states = /* @__PURE__ */ new WeakMap();
33942
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(tracingChannel);
33943
- const handlers = {
33944
- start: (event) => {
33945
- const state = startMultiAgentStream(
33946
- event,
33947
- operation,
33948
- this.activeChildParents
33949
- );
33950
- if (state) {
33951
- states.set(event, state);
33952
- }
33953
- },
33954
- end: (event) => {
33955
- const state = states.get(event);
33956
- if (!state) {
33957
- return;
33958
- }
33959
- const result = event.result;
33960
- if (isAsyncIterable(result)) {
33961
- patchStreamIfNeeded(result, {
33962
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
33963
- onChunk: (chunk) => handleMultiAgentStreamEvent(
33964
- state,
33965
- chunk,
33966
- this.activeChildParents
33967
- ),
33968
- onComplete: () => {
33969
- finalizeMultiAgentStream(state, this.activeChildParents);
33970
- states.delete(event);
33971
- },
33972
- onError: (error) => {
33973
- finalizeMultiAgentStream(state, this.activeChildParents, error);
33974
- states.delete(event);
33975
- }
33976
- });
33977
- return;
33978
- }
33979
- finalizeMultiAgentStream(
33980
- state,
33981
- this.activeChildParents,
33982
- void 0,
33983
- result
34229
+ interceptMultiAgentStream(channel2, operation) {
34230
+ this.unsubscribers.push(
34231
+ channel2.intercept(
34232
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
34233
+ finalize: (state, error, output) => finalizeMultiAgentStream(
34234
+ state,
34235
+ this.activeChildParents,
34236
+ error,
34237
+ output
34238
+ ),
34239
+ handleChunk: (state, chunk) => handleMultiAgentStreamEvent(state, chunk, this.activeChildParents),
34240
+ invoke: () => Reflect.apply(target, thisArg, args),
34241
+ name: "Strands multi-agent",
34242
+ start: () => startMultiAgentStream(
34243
+ args[0],
34244
+ extractOrchestrator(additional.orchestrator, thisArg),
34245
+ operation,
34246
+ this.activeChildParents
34247
+ )
34248
+ })
34249
+ )
34250
+ );
34251
+ }
34252
+ };
34253
+ function instrumentStrandsStreamInvocation(options) {
34254
+ let state;
34255
+ try {
34256
+ state = options.start();
34257
+ } catch (error) {
34258
+ debugLogger.error(`Error starting ${options.name} instrumentation:`, error);
34259
+ }
34260
+ let result;
34261
+ try {
34262
+ result = runWithAutoInstrumentationSuppressed(options.invoke);
34263
+ } catch (error) {
34264
+ if (state) {
34265
+ try {
34266
+ options.finalize(state, error);
34267
+ } catch (instrumentationError) {
34268
+ debugLogger.error(
34269
+ `Error handling ${options.name} instrumentation failure:`,
34270
+ instrumentationError
33984
34271
  );
33985
- states.delete(event);
33986
- },
33987
- error: (event) => {
33988
- const state = states.get(event);
33989
- if (!state || !event.error) {
33990
- return;
33991
- }
33992
- finalizeMultiAgentStream(state, this.activeChildParents, event.error);
33993
- states.delete(event);
33994
34272
  }
33995
- };
33996
- tracingChannel.subscribe(handlers);
33997
- this.unsubscribers.push(() => {
33998
- unbindAutoInstrumentationSuppression?.();
33999
- tracingChannel.unsubscribe(handlers);
34000
- });
34273
+ }
34274
+ throw error;
34001
34275
  }
34002
- };
34003
- function startAgentStream(event, activeChildParents) {
34004
- const agent = extractAgent(event);
34276
+ if (state) {
34277
+ try {
34278
+ if (isAsyncIterable(result)) {
34279
+ patchStreamIfNeeded(result, {
34280
+ aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
34281
+ onChunk: (chunk) => options.handleChunk(state, chunk),
34282
+ onComplete: () => options.finalize(state),
34283
+ onError: (error) => options.finalize(state, error)
34284
+ });
34285
+ } else {
34286
+ options.finalize(state, void 0, result);
34287
+ }
34288
+ } catch (error) {
34289
+ debugLogger.error(
34290
+ `Error finalizing ${options.name} instrumentation:`,
34291
+ error
34292
+ );
34293
+ }
34294
+ }
34295
+ return result;
34296
+ }
34297
+ function startAgentStream(input, agent, activeChildParents) {
34005
34298
  const model = agent?.model;
34006
34299
  const metadata = {
34007
34300
  ...extractAgentMetadata2(agent),
@@ -34011,17 +34304,14 @@ function startAgentStream(event, activeChildParents) {
34011
34304
  };
34012
34305
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
34013
34306
  const attachmentCache = createStrandsAttachmentCache();
34014
- const input = processStrandsInputAttachments(
34015
- event.arguments[0],
34016
- attachmentCache
34017
- );
34307
+ const processedInput = processStrandsInputAttachments(input, attachmentCache);
34018
34308
  const span = parentSpan ? withCurrent(
34019
34309
  parentSpan,
34020
34310
  () => startSpan(
34021
34311
  withSpanInstrumentationName(
34022
34312
  {
34023
34313
  event: {
34024
- input,
34314
+ input: processedInput,
34025
34315
  metadata
34026
34316
  },
34027
34317
  name: formatAgentSpanName(agent),
@@ -34034,7 +34324,7 @@ function startAgentStream(event, activeChildParents) {
34034
34324
  withSpanInstrumentationName(
34035
34325
  {
34036
34326
  event: {
34037
- input,
34327
+ input: processedInput,
34038
34328
  metadata
34039
34329
  },
34040
34330
  name: formatAgentSpanName(agent),
@@ -34052,22 +34342,21 @@ function startAgentStream(event, activeChildParents) {
34052
34342
  startTime: getCurrentUnixTimestamp()
34053
34343
  };
34054
34344
  }
34055
- function startMultiAgentStream(event, operation, activeChildParents) {
34056
- const orchestrator = extractOrchestrator(event);
34345
+ function startMultiAgentStream(input, orchestrator, operation, activeChildParents) {
34057
34346
  const metadata = {
34058
34347
  "strands.operation": operation,
34059
34348
  provider: "strands",
34060
34349
  ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
34061
34350
  };
34062
34351
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
34063
- const input = processStrandsInputAttachments(event.arguments[0]);
34352
+ const processedInput = processStrandsInputAttachments(input);
34064
34353
  const span = parentSpan ? withCurrent(
34065
34354
  parentSpan,
34066
34355
  () => startSpan(
34067
34356
  withSpanInstrumentationName(
34068
34357
  {
34069
34358
  event: {
34070
- input,
34359
+ input: processedInput,
34071
34360
  metadata
34072
34361
  },
34073
34362
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -34080,7 +34369,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
34080
34369
  withSpanInstrumentationName(
34081
34370
  {
34082
34371
  event: {
34083
- input,
34372
+ input: processedInput,
34084
34373
  metadata
34085
34374
  },
34086
34375
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -34451,12 +34740,12 @@ function finalizeMultiAgentStream(state, activeChildParents, error, output) {
34451
34740
  });
34452
34741
  state.span.end();
34453
34742
  }
34454
- function extractAgent(event) {
34455
- const candidate = event.agent ?? event.self;
34743
+ function extractAgent(agent, self) {
34744
+ const candidate = agent ?? self;
34456
34745
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
34457
34746
  }
34458
- function extractOrchestrator(event) {
34459
- const candidate = event.orchestrator ?? event.self;
34747
+ function extractOrchestrator(orchestrator, self) {
34748
+ const candidate = orchestrator ?? self;
34460
34749
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
34461
34750
  }
34462
34751
  function extractAgentMetadata2(agent) {
@@ -36664,7 +36953,7 @@ function isAsync(fn) {
36664
36953
  function isAsyncGenerator2(fn) {
36665
36954
  return fn[Symbol.toStringTag] === "AsyncGenerator";
36666
36955
  }
36667
- function isAsyncIterable6(obj) {
36956
+ function isAsyncIterable5(obj) {
36668
36957
  return typeof obj[Symbol.asyncIterator] === "function";
36669
36958
  }
36670
36959
  function wrapAsync(asyncFn) {
@@ -36836,7 +37125,7 @@ var eachOfLimit$2 = (limit) => {
36836
37125
  if (isAsyncGenerator2(obj)) {
36837
37126
  return asyncEachOfLimit(obj, limit, iteratee, callback);
36838
37127
  }
36839
- if (isAsyncIterable6(obj)) {
37128
+ if (isAsyncIterable5(obj)) {
36840
37129
  return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback);
36841
37130
  }
36842
37131
  var nextElem = createIterator(obj);
@@ -38272,7 +38561,7 @@ function callEvaluatorData(data) {
38272
38561
  baseExperiment
38273
38562
  };
38274
38563
  }
38275
- function isAsyncIterable7(value) {
38564
+ function isAsyncIterable6(value) {
38276
38565
  return typeof value === "object" && value !== null && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
38277
38566
  }
38278
38567
  function isIterable(value) {
@@ -38307,7 +38596,7 @@ async function _internalResolveEvaluatorData(evaluator, experiment) {
38307
38596
  }).asDataset();
38308
38597
  }
38309
38598
  const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
38310
- if (isAsyncIterable7(resolvedDataResult)) {
38599
+ if (isAsyncIterable6(resolvedDataResult)) {
38311
38600
  return resolvedDataResult;
38312
38601
  }
38313
38602
  if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
@@ -40207,14 +40496,9 @@ async function getDataset(state, data) {
40207
40496
  _internal_btql: data._internal_btql ?? void 0
40208
40497
  });
40209
40498
  } else if ("dataset_id" in data) {
40210
- const datasetInfo = await getDatasetById({
40211
- state,
40212
- datasetId: data.dataset_id
40213
- });
40214
40499
  return initDataset({
40215
40500
  state,
40216
- projectId: datasetInfo.projectId,
40217
- dataset: datasetInfo.dataset,
40501
+ datasetId: data.dataset_id,
40218
40502
  version: data.dataset_version ?? void 0,
40219
40503
  environment: data.dataset_environment ?? void 0,
40220
40504
  _internal_btql: data._internal_btql ?? void 0
@@ -40225,23 +40509,6 @@ async function getDataset(state, data) {
40225
40509
  return data.data;
40226
40510
  }
40227
40511
  }
40228
- var datasetFetchSchema = z14.object({
40229
- project_id: z14.string(),
40230
- name: z14.string()
40231
- });
40232
- async function getDatasetById({
40233
- state,
40234
- datasetId
40235
- }) {
40236
- const dataset = await state.appConn().post_json("api/dataset/get", {
40237
- id: datasetId
40238
- });
40239
- const parsed = z14.array(datasetFetchSchema).parse(dataset);
40240
- if (parsed.length === 0) {
40241
- throw new Error(`Dataset '${datasetId}' not found`);
40242
- }
40243
- return { projectId: parsed[0].project_id, dataset: parsed[0].name };
40244
- }
40245
40512
  function makeScorer(state, name, score, projectId) {
40246
40513
  const ret = async (input) => {
40247
40514
  const request = {