braintrust 3.28.0 → 3.30.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 (54) 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 +2679 -1828
  5. package/dev/dist/index.mjs +1862 -1011
  6. package/dist/apply-auto-instrumentation.js +298 -265
  7. package/dist/apply-auto-instrumentation.mjs +85 -52
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +56 -6
  9. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  10. package/dist/auto-instrumentations/bundler/next.cjs +56 -6
  11. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  12. package/dist/auto-instrumentations/bundler/rollup.cjs +56 -6
  13. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.cjs +56 -6
  15. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  16. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +56 -6
  17. package/dist/auto-instrumentations/bundler/webpack.cjs +56 -6
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  19. package/dist/auto-instrumentations/{chunk-26PKVUKB.mjs → chunk-LW4HDHXT.mjs} +12 -4
  20. package/dist/auto-instrumentations/{chunk-HD35AM3M.mjs → chunk-OXINGIEZ.mjs} +1 -1
  21. package/dist/auto-instrumentations/{chunk-NP7V4XB2.mjs → chunk-U64OYU4Q.mjs} +45 -3
  22. package/dist/auto-instrumentations/hook.mjs +967 -136
  23. package/dist/auto-instrumentations/index.cjs +45 -3
  24. package/dist/auto-instrumentations/index.mjs +1 -1
  25. package/dist/browser.d.mts +893 -24
  26. package/dist/browser.d.ts +893 -24
  27. package/dist/browser.js +2795 -1136
  28. package/dist/browser.mjs +2795 -1136
  29. package/dist/{chunk-BBE7SNRV.js → chunk-2XDW3UCG.js} +155 -23
  30. package/dist/{chunk-UPFNQCGB.mjs → chunk-BU6SM54N.mjs} +1830 -1045
  31. package/dist/{chunk-ZHUHZWFY.mjs → chunk-N3JKQ3D3.mjs} +152 -20
  32. package/dist/{chunk-OBBWQW6K.js → chunk-TWCDSYJN.js} +2890 -2105
  33. package/dist/cli.js +5976 -1348
  34. package/dist/edge-light.d.mts +1 -1
  35. package/dist/edge-light.d.ts +1 -1
  36. package/dist/edge-light.js +2795 -1136
  37. package/dist/edge-light.mjs +2795 -1136
  38. package/dist/index.d.mts +893 -24
  39. package/dist/index.d.ts +893 -24
  40. package/dist/index.js +1448 -699
  41. package/dist/index.mjs +848 -99
  42. package/dist/instrumentation/index.d.mts +563 -9
  43. package/dist/instrumentation/index.d.ts +563 -9
  44. package/dist/instrumentation/index.js +2794 -989
  45. package/dist/instrumentation/index.mjs +2794 -989
  46. package/dist/vitest-evals-reporter.js +16 -16
  47. package/dist/vitest-evals-reporter.mjs +2 -2
  48. package/dist/workerd.d.mts +1 -1
  49. package/dist/workerd.d.ts +1 -1
  50. package/dist/workerd.js +2795 -1136
  51. package/dist/workerd.mjs +2795 -1136
  52. package/package.json +1 -1
  53. package/util/dist/index.d.mts +42 -0
  54. package/util/dist/index.d.ts +42 -0
package/dist/browser.js CHANGED
@@ -104,6 +104,7 @@ __export(browser_exports, {
104
104
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
105
105
  buildLocalSummary: () => buildLocalSummary,
106
106
  collectAnthropicSession: () => collectAnthropicSession,
107
+ completeOpenAIBatchTrace: () => completeOpenAIBatchTrace,
107
108
  configureInstrumentation: () => configureInstrumentation,
108
109
  constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
109
110
  createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
@@ -143,6 +144,8 @@ __export(browser_exports, {
143
144
  loginToState: () => loginToState,
144
145
  logs3OverflowUploadSchema: () => logs3OverflowUploadSchema,
145
146
  newId: () => newId,
147
+ openaiBatchesRetrieveTraced: () => openaiBatchesRetrieveTraced,
148
+ openaiFilesCreateTraced: () => openaiFilesCreateTraced,
146
149
  parseCachedHeader: () => parseCachedHeader,
147
150
  parseTemplateFormat: () => parseTemplateFormat,
148
151
  permalink: () => permalink,
@@ -869,8 +872,6 @@ function newGlobalTracingChannel(nameOrChannels) {
869
872
  var DefaultAsyncLocalStorage = class {
870
873
  constructor() {
871
874
  }
872
- enterWith(_) {
873
- }
874
875
  run(_, callback) {
875
876
  return callback();
876
877
  }
@@ -2687,7 +2688,9 @@ var AclObjectType = import_v36.z.union([
2687
2688
  "project_log",
2688
2689
  "org_project",
2689
2690
  "org_audit_logs",
2690
- "project_group"
2691
+ "project_group",
2692
+ "ai_secret",
2693
+ "org_ai_secret"
2691
2694
  ]),
2692
2695
  import_v36.z.null()
2693
2696
  ]);
@@ -3520,7 +3523,7 @@ var PromptParserNullish = import_v36.z.union([
3520
3523
  }),
3521
3524
  import_v36.z.null()
3522
3525
  ]);
3523
- var PreprocessorSavedFunctionId = import_v36.z.union([
3526
+ var PreprocessorId = import_v36.z.union([
3524
3527
  import_v36.z.object({
3525
3528
  type: import_v36.z.literal("function"),
3526
3529
  id: import_v36.z.string(),
@@ -3531,6 +3534,7 @@ var PreprocessorSavedFunctionId = import_v36.z.union([
3531
3534
  name: import_v36.z.string(),
3532
3535
  function_type: import_v36.z.literal("preprocessor").optional().default("preprocessor")
3533
3536
  }),
3537
+ import_v36.z.object({ type: import_v36.z.literal("inline"), code: import_v36.z.string().min(1) }),
3534
3538
  import_v36.z.null()
3535
3539
  ]);
3536
3540
  var PromptDataNullish = import_v36.z.union([
@@ -3538,7 +3542,7 @@ var PromptDataNullish = import_v36.z.union([
3538
3542
  prompt: PromptBlockDataNullish,
3539
3543
  options: PromptOptionsNullish,
3540
3544
  parser: PromptParserNullish,
3541
- preprocessor: PreprocessorSavedFunctionId,
3545
+ preprocessor: PreprocessorId,
3542
3546
  tool_functions: import_v36.z.union([import_v36.z.array(SavedFunctionId), import_v36.z.null()]),
3543
3547
  template_format: import_v36.z.union([
3544
3548
  import_v36.z.enum(["mustache", "nunjucks", "none"]),
@@ -3740,7 +3744,7 @@ var PromptData = import_v36.z.object({
3740
3744
  prompt: PromptBlockDataNullish,
3741
3745
  options: PromptOptionsNullish,
3742
3746
  parser: PromptParserNullish,
3743
- preprocessor: PreprocessorSavedFunctionId,
3747
+ preprocessor: PreprocessorId,
3744
3748
  tool_functions: import_v36.z.union([import_v36.z.array(SavedFunctionId), import_v36.z.null()]),
3745
3749
  template_format: import_v36.z.union([
3746
3750
  import_v36.z.enum(["mustache", "nunjucks", "none"]),
@@ -4684,6 +4688,7 @@ var View = import_v36.z.object({
4684
4688
  ]),
4685
4689
  name: import_v36.z.string(),
4686
4690
  description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4691
+ starred: import_v36.z.boolean().optional(),
4687
4692
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4688
4693
  updated_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4689
4694
  view_data: ViewData.optional(),
@@ -5385,44 +5390,72 @@ function createCacheLayers({
5385
5390
  }
5386
5391
 
5387
5392
  // src/prompt-cache/prompt-cache.ts
5388
- function createCacheKey(key) {
5393
+ function createCacheKey(key, namespace) {
5394
+ let cacheKey;
5389
5395
  if (key.id) {
5390
- return `id:${key.id}`;
5391
- }
5392
- const prefix = key.projectId ?? key.projectName;
5393
- if (!prefix) {
5394
- throw new Error("Either projectId or projectName must be provided");
5395
- }
5396
- if (!key.slug) {
5397
- throw new Error("Slug must be provided when not using ID");
5396
+ cacheKey = `id:${key.id}`;
5397
+ } else {
5398
+ const prefix = key.projectId ?? key.projectName;
5399
+ if (!prefix) {
5400
+ throw new Error("Either projectId or projectName must be provided");
5401
+ }
5402
+ if (!key.slug) {
5403
+ throw new Error("Slug must be provided when not using ID");
5404
+ }
5405
+ cacheKey = `${prefix}:${key.slug}:${key.version ?? "latest"}`;
5398
5406
  }
5399
- return `${prefix}:${key.slug}:${key.version ?? "latest"}`;
5407
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
5400
5408
  }
5401
- var PromptCache = class {
5409
+ var PromptCache = class _PromptCache {
5402
5410
  memoryCache;
5403
5411
  diskCache;
5412
+ namespace;
5413
+ expectedResolvedOrgIdentity;
5404
5414
  constructor(options) {
5405
5415
  this.memoryCache = options.memoryCache;
5406
5416
  this.diskCache = options.diskCache;
5417
+ this.namespace = options.namespace;
5418
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
5419
+ }
5420
+ /**
5421
+ * Returns a cache view that shares the same storage layers but isolates all
5422
+ * entries under the provided namespace.
5423
+ */
5424
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
5425
+ return new _PromptCache({
5426
+ memoryCache: this.memoryCache,
5427
+ diskCache: this.diskCache,
5428
+ namespace,
5429
+ expectedResolvedOrgIdentity
5430
+ });
5407
5431
  }
5408
5432
  /**
5409
5433
  * Retrieves a prompt from the cache.
5410
5434
  * First checks the in-memory LRU cache, then falls back to checking the disk cache if available.
5411
5435
  */
5412
5436
  async get(key) {
5413
- const cacheKey = createCacheKey(key);
5437
+ const cacheKey = createCacheKey(key, this.namespace);
5414
5438
  if (this.memoryCache) {
5415
- const memoryPrompt = this.memoryCache.get(cacheKey);
5416
- if (memoryPrompt !== void 0) {
5417
- return memoryPrompt;
5439
+ const memoryEntry = this.memoryCache.get(cacheKey);
5440
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
5441
+ return memoryEntry.value;
5418
5442
  }
5419
5443
  }
5420
5444
  if (this.diskCache) {
5421
- const diskPrompt = await this.diskCache.get(cacheKey);
5422
- if (!diskPrompt) {
5445
+ const diskEntry = await this.diskCache.get(cacheKey);
5446
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
5423
5447
  return void 0;
5424
5448
  }
5425
- this.memoryCache?.set(cacheKey, diskPrompt);
5449
+ const serializedPrompt = diskEntry.value;
5450
+ const diskPrompt = new Prompt2(
5451
+ serializedPrompt.metadata,
5452
+ serializedPrompt.defaults,
5453
+ serializedPrompt.noTrace
5454
+ );
5455
+ this.memoryCache?.set(cacheKey, {
5456
+ value: diskPrompt,
5457
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
5458
+ });
5426
5459
  return diskPrompt;
5427
5460
  }
5428
5461
  return void 0;
@@ -5436,58 +5469,91 @@ var PromptCache = class {
5436
5469
  * @throws If there is an error writing to the disk cache.
5437
5470
  */
5438
5471
  async set(key, value) {
5439
- const cacheKey = createCacheKey(key);
5440
- this.memoryCache?.set(cacheKey, value);
5472
+ const cacheKey = createCacheKey(key, this.namespace);
5473
+ const memoryEntry = {
5474
+ value,
5475
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5476
+ };
5477
+ this.memoryCache?.set(cacheKey, memoryEntry);
5441
5478
  if (this.diskCache) {
5442
- await this.diskCache.set(cacheKey, value);
5479
+ await this.diskCache.set(cacheKey, {
5480
+ value: value._internalSerializeForCache(),
5481
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5482
+ });
5443
5483
  }
5444
5484
  }
5445
5485
  };
5446
5486
 
5447
5487
  // src/prompt-cache/parameters-cache.ts
5448
- function createCacheKey2(key) {
5488
+ function createCacheKey2(key, namespace) {
5489
+ let cacheKey;
5449
5490
  if (key.id) {
5450
- return `parameters:id:${key.id}`;
5451
- }
5452
- const prefix = key.projectId ?? key.projectName;
5453
- if (!prefix) {
5454
- throw new Error("Either projectId or projectName must be provided");
5455
- }
5456
- if (!key.slug) {
5457
- throw new Error("Slug must be provided when not using ID");
5491
+ cacheKey = `parameters:id:${key.id}`;
5492
+ } else {
5493
+ const prefix = key.projectId ?? key.projectName;
5494
+ if (!prefix) {
5495
+ throw new Error("Either projectId or projectName must be provided");
5496
+ }
5497
+ if (!key.slug) {
5498
+ throw new Error("Slug must be provided when not using ID");
5499
+ }
5500
+ cacheKey = `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
5458
5501
  }
5459
- return `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
5502
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
5460
5503
  }
5461
- var ParametersCache = class {
5504
+ var ParametersCache = class _ParametersCache {
5462
5505
  memoryCache;
5463
5506
  diskCache;
5507
+ namespace;
5508
+ expectedResolvedOrgIdentity;
5464
5509
  constructor(options) {
5465
5510
  this.memoryCache = options.memoryCache;
5466
5511
  this.diskCache = options.diskCache;
5512
+ this.namespace = options.namespace;
5513
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
5514
+ }
5515
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
5516
+ return new _ParametersCache({
5517
+ memoryCache: this.memoryCache,
5518
+ diskCache: this.diskCache,
5519
+ namespace,
5520
+ expectedResolvedOrgIdentity
5521
+ });
5467
5522
  }
5468
5523
  async get(key) {
5469
- const cacheKey = createCacheKey2(key);
5524
+ const cacheKey = createCacheKey2(key, this.namespace);
5470
5525
  if (this.memoryCache) {
5471
- const memoryParams = this.memoryCache.get(cacheKey);
5472
- if (memoryParams !== void 0) {
5473
- return memoryParams;
5526
+ const memoryEntry = this.memoryCache.get(cacheKey);
5527
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
5528
+ return memoryEntry.value;
5474
5529
  }
5475
5530
  }
5476
5531
  if (this.diskCache) {
5477
- const diskParams = await this.diskCache.get(cacheKey);
5478
- if (!diskParams) {
5532
+ const diskEntry = await this.diskCache.get(cacheKey);
5533
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
5479
5534
  return void 0;
5480
5535
  }
5481
- this.memoryCache?.set(cacheKey, diskParams);
5482
- return diskParams;
5536
+ const diskParameters = new RemoteEvalParameters(diskEntry.value.metadata);
5537
+ this.memoryCache?.set(cacheKey, {
5538
+ value: diskParameters,
5539
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
5540
+ });
5541
+ return diskParameters;
5483
5542
  }
5484
5543
  return void 0;
5485
5544
  }
5486
5545
  async set(key, value) {
5487
- const cacheKey = createCacheKey2(key);
5488
- this.memoryCache?.set(cacheKey, value);
5546
+ const cacheKey = createCacheKey2(key, this.namespace);
5547
+ const memoryEntry = {
5548
+ value,
5549
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5550
+ };
5551
+ this.memoryCache?.set(cacheKey, memoryEntry);
5489
5552
  if (this.diskCache) {
5490
- await this.diskCache.set(cacheKey, value);
5553
+ await this.diskCache.set(cacheKey, {
5554
+ value: value._internalSerializeForCache(),
5555
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5556
+ });
5491
5557
  }
5492
5558
  }
5493
5559
  };
@@ -5791,6 +5857,7 @@ var INSTRUMENTATION_NAMES = {
5791
5857
  CLOUDFLARE_THINK: "cloudflare-think",
5792
5858
  COHERE: "cohere",
5793
5859
  CURSOR_SDK: "cursor-sdk",
5860
+ DEEPSEEK_HARNESS: "deepseek-harness",
5794
5861
  EVE: "eve",
5795
5862
  FLUE: "flue",
5796
5863
  GENKIT: "genkit",
@@ -5816,7 +5883,7 @@ var INSTRUMENTATION_NAMES = {
5816
5883
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5817
5884
  "braintrust.spanInstrumentationName"
5818
5885
  );
5819
- var SDK_VERSION = true ? "3.28.0" : "0.0.0";
5886
+ var SDK_VERSION = true ? "3.30.0" : "0.0.0";
5820
5887
  function withSpanInstrumentationName(args, instrumentationName) {
5821
5888
  return {
5822
5889
  ...args,
@@ -5935,6 +6002,16 @@ var datasetSnapshotRegisterResponseSchema = import_v38.z.object({
5935
6002
  dataset_snapshot: DatasetSnapshot,
5936
6003
  found_existing: import_v38.z.boolean().optional()
5937
6004
  });
6005
+ var datasetObjectInfoSchema = import_v38.z.object({
6006
+ object_id: import_v38.z.string(),
6007
+ object_name: import_v38.z.string(),
6008
+ parent_cols: import_v38.z.object({
6009
+ project: import_v38.z.object({
6010
+ id: import_v38.z.string(),
6011
+ name: import_v38.z.string()
6012
+ })
6013
+ })
6014
+ });
5938
6015
  var datasetRestorePreviewResultSchema = import_v38.z.object({
5939
6016
  rows_to_restore: import_v38.z.number(),
5940
6017
  rows_to_delete: import_v38.z.number()
@@ -6148,12 +6225,53 @@ var loginSchema = import_v38.z.strictObject({
6148
6225
  });
6149
6226
  var stateNonce = 0;
6150
6227
  var V1_PROXY_SUFFIX = "/v1/proxy";
6228
+ var LOADER_LOGIN_CACHE_MAX = 16;
6151
6229
  function normalizeProxyConnUrl(proxyUrl) {
6152
6230
  return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
6153
6231
  }
6154
6232
  var BraintrustState = class _BraintrustState {
6233
+ id;
6234
+ currentExperiment;
6235
+ // Note: the value of IsAsyncFlush doesn't really matter here, since we
6236
+ // (safely) dynamically cast it whenever retrieving the logger.
6237
+ currentLogger;
6238
+ currentParent;
6239
+ currentSpan;
6240
+ // Any time we re-log in, we directly update the apiConn inside the logger.
6241
+ // This is preferable to replacing the whole logger, which would create the
6242
+ // possibility of multiple loggers floating around, which may not log in a
6243
+ // deterministic order.
6244
+ _bgLogger;
6245
+ _overrideBgLogger = null;
6246
+ appUrl = null;
6247
+ appPublicUrl = null;
6248
+ loginToken = null;
6249
+ orgId = null;
6250
+ orgName = null;
6251
+ apiUrl = null;
6252
+ proxyUrl = null;
6253
+ loggedIn = false;
6254
+ gitMetadataSettings;
6255
+ debugLogLevel;
6256
+ debugLogLevelConfigured = false;
6257
+ fetch = globalThis.fetch;
6258
+ _appConn = null;
6259
+ _apiConn = null;
6260
+ _proxyConn = null;
6261
+ promptCache;
6262
+ parametersCache;
6263
+ spanCache;
6264
+ _idGenerator = null;
6265
+ _contextManager = null;
6266
+ _otelFlushCallback = null;
6267
+ spanOriginEnvironment;
6268
+ traceContextSigningSecret;
6269
+ loaderLoginCache = /* @__PURE__ */ new WeakMap();
6270
+ loginParams;
6271
+ activeLoginOrgNameSelector;
6155
6272
  constructor(loginParams) {
6156
- this.loginParams = loginParams;
6273
+ this.loginParams = { ...loginParams };
6274
+ this.activeLoginOrgNameSelector = loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
6157
6275
  this.id = `${(/* @__PURE__ */ new Date()).toLocaleString()}-${stateNonce++}`;
6158
6276
  this.currentExperiment = void 0;
6159
6277
  this.currentLogger = void 0;
@@ -6190,12 +6308,14 @@ var BraintrustState = class _BraintrustState {
6190
6308
  const {
6191
6309
  memoryCache: parametersMemoryCache,
6192
6310
  diskCache: parametersDiskCache
6193
- } = createCacheLayers({
6194
- memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
6195
- diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
6196
- diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
6197
- getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
6198
- });
6311
+ } = createCacheLayers(
6312
+ {
6313
+ memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
6314
+ diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
6315
+ diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
6316
+ getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
6317
+ }
6318
+ );
6199
6319
  this.parametersCache = new ParametersCache({
6200
6320
  memoryCache: parametersMemoryCache,
6201
6321
  diskCache: parametersDiskCache
@@ -6204,43 +6324,6 @@ var BraintrustState = class _BraintrustState {
6204
6324
  this.spanOriginEnvironment = detectSpanOriginEnvironment();
6205
6325
  this._internalSetTraceContextSigningSecret(loginParams.apiKey);
6206
6326
  }
6207
- loginParams;
6208
- id;
6209
- currentExperiment;
6210
- // Note: the value of IsAsyncFlush doesn't really matter here, since we
6211
- // (safely) dynamically cast it whenever retrieving the logger.
6212
- currentLogger;
6213
- currentParent;
6214
- currentSpan;
6215
- // Any time we re-log in, we directly update the apiConn inside the logger.
6216
- // This is preferable to replacing the whole logger, which would create the
6217
- // possibility of multiple loggers floating around, which may not log in a
6218
- // deterministic order.
6219
- _bgLogger;
6220
- _overrideBgLogger = null;
6221
- appUrl = null;
6222
- appPublicUrl = null;
6223
- loginToken = null;
6224
- orgId = null;
6225
- orgName = null;
6226
- apiUrl = null;
6227
- proxyUrl = null;
6228
- loggedIn = false;
6229
- gitMetadataSettings;
6230
- debugLogLevel;
6231
- debugLogLevelConfigured = false;
6232
- fetch = globalThis.fetch;
6233
- _appConn = null;
6234
- _apiConn = null;
6235
- _proxyConn = null;
6236
- promptCache;
6237
- parametersCache;
6238
- spanCache;
6239
- _idGenerator = null;
6240
- _contextManager = null;
6241
- _otelFlushCallback = null;
6242
- spanOriginEnvironment;
6243
- traceContextSigningSecret;
6244
6327
  /** @internal */
6245
6328
  _internalSetTraceContextSigningSecret(secret) {
6246
6329
  const normalizedSecret = secret?.trim();
@@ -6265,6 +6348,101 @@ var BraintrustState = class _BraintrustState {
6265
6348
  this._appConn = null;
6266
6349
  this._apiConn = null;
6267
6350
  this._proxyConn = null;
6351
+ this.loaderLoginCache = /* @__PURE__ */ new WeakMap();
6352
+ }
6353
+ /** @internal */
6354
+ async _internalResolveLoaderLoginOptions({
6355
+ apiKey,
6356
+ appUrl,
6357
+ orgName,
6358
+ fetch: fetch2,
6359
+ forceLogin
6360
+ }) {
6361
+ const resolvedAppUrl = appUrl ?? (this.loggedIn ? this.appUrl ?? void 0 : void 0) ?? this.loginParams.appUrl ?? isomorph_default.getEnv("BRAINTRUST_APP_URL") ?? "https://www.braintrust.dev";
6362
+ const resolvedApiKey = apiKey ?? (this.loggedIn ? this.loginToken ?? void 0 : void 0) ?? this.loginParams.apiKey ?? await isomorph_default.getBraintrustApiKey();
6363
+ if (!resolvedApiKey) {
6364
+ throw new Error(
6365
+ "Please specify an api key (e.g. by setting BRAINTRUST_API_KEY)."
6366
+ );
6367
+ }
6368
+ const normalizedApiKey = HTTPConnection.sanitize_token(resolvedApiKey);
6369
+ const usesActiveCredential = this.loggedIn && normalizedApiKey === this.loginToken;
6370
+ const requestedOrgName = orgName ?? (usesActiveCredential ? this.activeLoginOrgNameSelector : void 0) ?? this.loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
6371
+ const resolvedOrgName = orgName ?? (usesActiveCredential ? this.orgName ?? void 0 : void 0) ?? requestedOrgName;
6372
+ const resolvedFetch = fetch2 ?? (this.loggedIn ? this.fetch : void 0) ?? this.loginParams.fetch ?? globalThis.fetch;
6373
+ const credentialCacheNamespace = JSON.stringify([
6374
+ "loader-credential",
6375
+ resolvedAppUrl,
6376
+ requestedOrgName,
6377
+ normalizedApiKey
6378
+ ]);
6379
+ return {
6380
+ apiKey: normalizedApiKey,
6381
+ appUrl: resolvedAppUrl,
6382
+ orgName: resolvedOrgName,
6383
+ fetch: resolvedFetch,
6384
+ forceLogin,
6385
+ credentialCacheNamespace,
6386
+ existingState: !forceLogin && usesActiveCredential && resolvedAppUrl === this.appUrl && resolvedOrgName === this.orgName && resolvedFetch === this.fetch ? this : void 0
6387
+ };
6388
+ }
6389
+ /** @internal */
6390
+ _internalGetLoaderCacheViews(loginOptions, requestState) {
6391
+ const expectedResolvedOrgIdentity = requestState?.orgId && requestState.appUrl ? JSON.stringify([
6392
+ "loader-org",
6393
+ requestState.appUrl,
6394
+ requestState.orgId
6395
+ ]) : void 0;
6396
+ return {
6397
+ promptCache: this.promptCache.withNamespace(
6398
+ loginOptions.credentialCacheNamespace,
6399
+ expectedResolvedOrgIdentity
6400
+ ),
6401
+ parametersCache: this.parametersCache.withNamespace(
6402
+ loginOptions.credentialCacheNamespace,
6403
+ expectedResolvedOrgIdentity
6404
+ )
6405
+ };
6406
+ }
6407
+ /** @internal */
6408
+ async _internalGetLoaderState({
6409
+ apiKey,
6410
+ appUrl,
6411
+ orgName,
6412
+ fetch: fetch2,
6413
+ forceLogin,
6414
+ existingState
6415
+ }) {
6416
+ if (existingState) {
6417
+ return existingState;
6418
+ }
6419
+ let cache = this.loaderLoginCache.get(fetch2);
6420
+ if (!cache) {
6421
+ cache = new LRUCache({ max: LOADER_LOGIN_CACHE_MAX });
6422
+ this.loaderLoginCache.set(fetch2, cache);
6423
+ }
6424
+ const cacheKey = JSON.stringify([appUrl, orgName, apiKey]);
6425
+ if (!forceLogin) {
6426
+ const cachedState = cache.get(cacheKey);
6427
+ if (cachedState) {
6428
+ return cachedState;
6429
+ }
6430
+ }
6431
+ const statePromise = loginToLoaderRequestState({
6432
+ orgName,
6433
+ apiKey,
6434
+ appUrl,
6435
+ fetch: fetch2
6436
+ });
6437
+ cache.set(cacheKey, statePromise);
6438
+ try {
6439
+ return await statePromise;
6440
+ } catch (error) {
6441
+ if (cache.get(cacheKey) === statePromise) {
6442
+ cache.delete(cacheKey);
6443
+ }
6444
+ throw error;
6445
+ }
6268
6446
  }
6269
6447
  resetIdGenState() {
6270
6448
  this._idGenerator = null;
@@ -6313,6 +6491,8 @@ var BraintrustState = class _BraintrustState {
6313
6491
  this.debugLogLevel = other.debugLogLevel;
6314
6492
  this.debugLogLevelConfigured = other.debugLogLevelConfigured;
6315
6493
  this.traceContextSigningSecret = other.traceContextSigningSecret;
6494
+ this.fetch = other.fetch;
6495
+ this.activeLoginOrgNameSelector = other.activeLoginOrgNameSelector;
6316
6496
  setGlobalDebugLogLevel(
6317
6497
  this.debugLogLevelConfigured ? this.debugLogLevel ?? false : void 0
6318
6498
  );
@@ -6552,36 +6732,85 @@ var FailedHTTPResponse = class extends Error {
6552
6732
  status;
6553
6733
  text;
6554
6734
  data;
6555
- constructor(status, text, data) {
6735
+ cause;
6736
+ constructor(status, text, data, cause) {
6556
6737
  super(`${status}: ${text} (${data})`);
6557
6738
  this.status = status;
6558
6739
  this.text = text;
6559
6740
  this.data = data;
6741
+ this.cause = cause;
6742
+ }
6743
+ };
6744
+ var HTTPTransportError = class extends Error {
6745
+ cause;
6746
+ constructor(cause) {
6747
+ super(cause instanceof Error ? cause.message : String(cause));
6748
+ this.name = "HTTPTransportError";
6749
+ this.cause = cause;
6560
6750
  }
6561
6751
  };
6752
+ var httpTransportErrorCauses = /* @__PURE__ */ new WeakSet();
6753
+ function recordHTTPTransportError(error) {
6754
+ if (typeof error === "object" && error !== null || typeof error === "function") {
6755
+ httpTransportErrorCauses.add(error);
6756
+ }
6757
+ }
6758
+ function rethrowHTTPTransportError(error, classifyTransportErrors) {
6759
+ if (classifyTransportErrors) {
6760
+ throw new HTTPTransportError(error);
6761
+ }
6762
+ recordHTTPTransportError(error);
6763
+ throw error;
6764
+ }
6765
+ function isLoaderCacheFallbackError(error) {
6766
+ if (error instanceof FailedHTTPResponse) {
6767
+ return error.status === 408 || error.status === 429 || error.status >= 500;
6768
+ }
6769
+ if (error instanceof HTTPTransportError) {
6770
+ return true;
6771
+ }
6772
+ return (typeof error === "object" && error !== null || typeof error === "function") && httpTransportErrorCauses.has(error);
6773
+ }
6774
+ async function readJSONResponse(response, classifyTransportErrors = false) {
6775
+ let data;
6776
+ try {
6777
+ data = await response.text();
6778
+ } catch (error) {
6779
+ rethrowHTTPTransportError(error, classifyTransportErrors);
6780
+ }
6781
+ return JSON.parse(data);
6782
+ }
6562
6783
  async function checkResponse(resp) {
6563
6784
  if (resp.ok) {
6564
6785
  return resp;
6565
- } else {
6786
+ }
6787
+ let data;
6788
+ try {
6789
+ data = await resp.text();
6790
+ } catch (error) {
6566
6791
  throw new FailedHTTPResponse(
6567
6792
  resp.status,
6568
6793
  resp.statusText,
6569
- await resp.text()
6794
+ "Unable to read response body",
6795
+ error
6570
6796
  );
6571
6797
  }
6798
+ throw new FailedHTTPResponse(resp.status, resp.statusText, data);
6572
6799
  }
6573
6800
  var HTTPConnection = class _HTTPConnection {
6574
- base_url;
6575
- token;
6576
- headers;
6577
- fetch;
6578
- constructor(base_url, fetch2) {
6801
+ constructor(base_url, fetch2, classifyTransportErrors = false) {
6802
+ this.classifyTransportErrors = classifyTransportErrors;
6579
6803
  this.base_url = base_url;
6580
6804
  this.token = null;
6581
6805
  this.headers = {};
6582
6806
  this._reset();
6583
6807
  this.fetch = fetch2;
6584
6808
  }
6809
+ classifyTransportErrors;
6810
+ base_url;
6811
+ token;
6812
+ headers;
6813
+ fetch;
6585
6814
  setFetch(fetch2) {
6586
6815
  this.fetch = fetch2;
6587
6816
  }
@@ -6621,9 +6850,9 @@ var HTTPConnection = class _HTTPConnection {
6621
6850
  ).toString();
6622
6851
  const this_fetch = this.fetch;
6623
6852
  const this_headers = this.headers;
6624
- return await checkResponse(
6625
- // Using toString() here makes it work with isomorphic fetch
6626
- await this_fetch(url.toString(), {
6853
+ let response;
6854
+ try {
6855
+ response = await this_fetch(url.toString(), {
6627
6856
  headers: {
6628
6857
  Accept: "application/json",
6629
6858
  ...this_headers,
@@ -6631,8 +6860,14 @@ var HTTPConnection = class _HTTPConnection {
6631
6860
  },
6632
6861
  keepalive: true,
6633
6862
  ...rest
6634
- })
6635
- );
6863
+ });
6864
+ } catch (error) {
6865
+ if (config?.signal?.aborted) {
6866
+ throw getAbortReason(config.signal);
6867
+ }
6868
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
6869
+ }
6870
+ return await checkResponse(response);
6636
6871
  }
6637
6872
  async post(path, params, config, retries = 0) {
6638
6873
  const { headers, ...rest } = config || {};
@@ -6642,8 +6877,9 @@ var HTTPConnection = class _HTTPConnection {
6642
6877
  const tries = retries + 1;
6643
6878
  for (let i = 0; i < tries; i++) {
6644
6879
  try {
6645
- return await checkResponse(
6646
- await this_fetch(_urljoin(this_base_url, path), {
6880
+ let response;
6881
+ try {
6882
+ response = await this_fetch(_urljoin(this_base_url, path), {
6647
6883
  method: "POST",
6648
6884
  headers: {
6649
6885
  Accept: "application/json",
@@ -6654,8 +6890,14 @@ var HTTPConnection = class _HTTPConnection {
6654
6890
  body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
6655
6891
  keepalive: true,
6656
6892
  ...rest
6657
- })
6658
- );
6893
+ });
6894
+ } catch (error) {
6895
+ if (config?.signal?.aborted) {
6896
+ throw getAbortReason(config.signal);
6897
+ }
6898
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
6899
+ }
6900
+ return await checkResponse(response);
6659
6901
  } catch (error) {
6660
6902
  if (config?.signal?.aborted) {
6661
6903
  throw getAbortReason(config.signal);
@@ -6680,7 +6922,7 @@ var HTTPConnection = class _HTTPConnection {
6680
6922
  for (let i = 0; i < tries; i++) {
6681
6923
  try {
6682
6924
  const resp = await this.get(`${object_type}`, args);
6683
- return await resp.json();
6925
+ return await readJSONResponse(resp, this.classifyTransportErrors);
6684
6926
  } catch (e) {
6685
6927
  if (i < tries - 1) {
6686
6928
  debugLogger.debug(
@@ -6703,7 +6945,7 @@ var HTTPConnection = class _HTTPConnection {
6703
6945
  const resp = await this.post(`${object_type}`, args, {
6704
6946
  headers: { "Content-Type": "application/json" }
6705
6947
  });
6706
- return await resp.json();
6948
+ return await readJSONResponse(resp, this.classifyTransportErrors);
6707
6949
  }
6708
6950
  // Custom inspect for Node.js console.log
6709
6951
  [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
@@ -8751,6 +8993,7 @@ function initDataset(projectOrOptions, optionalOptions) {
8751
8993
  const {
8752
8994
  project,
8753
8995
  dataset,
8996
+ datasetId,
8754
8997
  description,
8755
8998
  version,
8756
8999
  snapshotName,
@@ -8766,6 +9009,11 @@ function initDataset(projectOrOptions, optionalOptions) {
8766
9009
  state: stateArg,
8767
9010
  _internal_btql
8768
9011
  } = options;
9012
+ if (datasetId !== void 0 && (description !== void 0 || metadata !== void 0)) {
9013
+ throw new Error(
9014
+ "Cannot specify description or metadata when datasetId is provided"
9015
+ );
9016
+ }
8769
9017
  const selection = normalizeDatasetSelection({
8770
9018
  version,
8771
9019
  environment,
@@ -8786,6 +9034,35 @@ function initDataset(projectOrOptions, optionalOptions) {
8786
9034
  fetch: fetch2,
8787
9035
  forceLogin
8788
9036
  });
9037
+ if (datasetId !== void 0) {
9038
+ const objectInfo = datasetObjectInfoSchema.array().parse(
9039
+ await state.appConn().post_json("api/self/get_object_info", {
9040
+ object_type: "dataset",
9041
+ object_ids: [datasetId]
9042
+ })
9043
+ );
9044
+ if (objectInfo.length === 0) {
9045
+ throw new Error(`Dataset with ID ${datasetId} not found`);
9046
+ }
9047
+ if (objectInfo.length !== 1) {
9048
+ throw new Error(
9049
+ `Expected exactly one dataset with ID ${datasetId}, but found ${objectInfo.length}`
9050
+ );
9051
+ }
9052
+ const datasetInfo = objectInfo[0];
9053
+ return {
9054
+ project: {
9055
+ id: datasetInfo.parent_cols.project.id,
9056
+ name: datasetInfo.parent_cols.project.name,
9057
+ fullInfo: datasetInfo.parent_cols.project
9058
+ },
9059
+ dataset: {
9060
+ id: datasetInfo.object_id,
9061
+ name: datasetInfo.object_name,
9062
+ fullInfo: datasetInfo
9063
+ }
9064
+ };
9065
+ }
8789
9066
  const args = {
8790
9067
  org_id: state.orgId,
8791
9068
  project_name: project,
@@ -8939,6 +9216,24 @@ function initLogger(options = {}) {
8939
9216
  }
8940
9217
  return ret;
8941
9218
  }
9219
+ async function runCredentialScopedLoaderRequest(state, loginOptions, request) {
9220
+ const resolvedLoginOptions = await state._internalResolveLoaderLoginOptions(loginOptions);
9221
+ let cacheViews = state._internalGetLoaderCacheViews(resolvedLoginOptions);
9222
+ try {
9223
+ const requestState = await state._internalGetLoaderState(resolvedLoginOptions);
9224
+ cacheViews = state._internalGetLoaderCacheViews(
9225
+ resolvedLoginOptions,
9226
+ requestState
9227
+ );
9228
+ return {
9229
+ ok: true,
9230
+ response: await request(requestState),
9231
+ ...cacheViews
9232
+ };
9233
+ } catch (error) {
9234
+ return { ok: false, error, ...cacheViews };
9235
+ }
9236
+ }
8942
9237
  async function loadPrompt({
8943
9238
  projectName,
8944
9239
  projectId,
@@ -8963,43 +9258,47 @@ async function loadPrompt({
8963
9258
  throw new Error("Must specify slug");
8964
9259
  }
8965
9260
  const state = stateArg ?? _globalState;
8966
- let response;
8967
- try {
8968
- await state.login({
8969
- orgName,
8970
- apiKey,
8971
- appUrl,
8972
- fetch: fetch2,
8973
- forceLogin
8974
- });
8975
- if (id) {
8976
- response = await state.apiConn().get_json(`v1/prompt/${id}`, versionOrEnvironment);
8977
- if (response) {
8978
- response = { objects: [response] };
9261
+ const result = await runCredentialScopedLoaderRequest(
9262
+ state,
9263
+ { orgName, apiKey, appUrl, fetch: fetch2, forceLogin },
9264
+ async (requestState) => {
9265
+ let response2;
9266
+ if (id) {
9267
+ response2 = await requestState.apiConn().get_json(`v1/prompt/${id}`, versionOrEnvironment);
9268
+ if (response2) {
9269
+ response2 = { objects: [response2] };
9270
+ }
9271
+ } else {
9272
+ response2 = await requestState.apiConn().get_json("v1/prompt", {
9273
+ project_name: projectName,
9274
+ project_id: projectId,
9275
+ slug,
9276
+ ...versionOrEnvironment
9277
+ });
8979
9278
  }
8980
- } else {
8981
- response = await state.apiConn().get_json("v1/prompt", {
8982
- project_name: projectName,
8983
- project_id: projectId,
8984
- slug,
8985
- ...versionOrEnvironment
8986
- });
9279
+ return response2;
9280
+ }
9281
+ );
9282
+ const { promptCache } = result;
9283
+ if (!result.ok) {
9284
+ const e = result.error;
9285
+ if (!isLoaderCacheFallbackError(e)) {
9286
+ throw e;
8987
9287
  }
8988
- } catch (e) {
8989
9288
  if (version || environment) {
8990
9289
  throw new Error(`Prompt not found with specified parameters: ${e}`);
8991
9290
  }
8992
9291
  debugLogger.forState(state).warn("Failed to load prompt, attempting to fall back to cache:", e);
8993
9292
  let prompt2;
8994
9293
  if (id) {
8995
- prompt2 = await state.promptCache.get({ id });
9294
+ prompt2 = await promptCache.get({ id });
8996
9295
  if (!prompt2) {
8997
9296
  throw new Error(
8998
9297
  `Prompt with id ${id} not found (not found on server or in local cache): ${e}`
8999
9298
  );
9000
9299
  }
9001
9300
  } else {
9002
- prompt2 = await state.promptCache.get({
9301
+ prompt2 = await promptCache.get({
9003
9302
  slug,
9004
9303
  projectId,
9005
9304
  projectName,
@@ -9015,6 +9314,7 @@ async function loadPrompt({
9015
9314
  }
9016
9315
  return prompt2;
9017
9316
  }
9317
+ const { response } = result;
9018
9318
  if (!("objects" in response) || response.objects.length === 0) {
9019
9319
  if (id) {
9020
9320
  throw new Error(`Prompt with id ${id} not found.`);
@@ -9038,9 +9338,9 @@ async function loadPrompt({
9038
9338
  const prompt = new Prompt2(metadata, defaults || {}, noTrace);
9039
9339
  try {
9040
9340
  if (id) {
9041
- await state.promptCache.set({ id }, prompt);
9341
+ await promptCache.set({ id }, prompt);
9042
9342
  } else if (slug) {
9043
- await state.promptCache.set(
9343
+ await promptCache.set(
9044
9344
  { slug, projectId, projectName, version: version ?? "latest" },
9045
9345
  prompt
9046
9346
  );
@@ -9072,46 +9372,50 @@ async function loadParameters({
9072
9372
  throw new Error("Must specify slug");
9073
9373
  }
9074
9374
  const state = stateArg ?? _globalState;
9075
- let response;
9076
- try {
9077
- await state.login({
9078
- orgName,
9079
- apiKey,
9080
- appUrl,
9081
- fetch: fetch2,
9082
- forceLogin
9083
- });
9084
- if (id) {
9085
- response = await state.apiConn().get_json(`v1/function/${id}`, {
9086
- ...versionOrEnvironment
9087
- });
9088
- if (response) {
9089
- response = { objects: [response] };
9375
+ const result = await runCredentialScopedLoaderRequest(
9376
+ state,
9377
+ { orgName, apiKey, appUrl, fetch: fetch2, forceLogin },
9378
+ async (requestState) => {
9379
+ let response2;
9380
+ if (id) {
9381
+ response2 = await requestState.apiConn().get_json(`v1/function/${id}`, {
9382
+ ...versionOrEnvironment
9383
+ });
9384
+ if (response2) {
9385
+ response2 = { objects: [response2] };
9386
+ }
9387
+ } else {
9388
+ response2 = await requestState.apiConn().get_json("v1/function", {
9389
+ project_name: projectName,
9390
+ project_id: projectId,
9391
+ slug,
9392
+ function_type: "parameters",
9393
+ ...versionOrEnvironment
9394
+ });
9090
9395
  }
9091
- } else {
9092
- response = await state.apiConn().get_json("v1/function", {
9093
- project_name: projectName,
9094
- project_id: projectId,
9095
- slug,
9096
- function_type: "parameters",
9097
- ...versionOrEnvironment
9098
- });
9396
+ return response2;
9397
+ }
9398
+ );
9399
+ const { parametersCache } = result;
9400
+ if (!result.ok) {
9401
+ const e = result.error;
9402
+ if (!isLoaderCacheFallbackError(e)) {
9403
+ throw e;
9099
9404
  }
9100
- } catch (e) {
9101
9405
  if (version || environment) {
9102
9406
  throw new Error(`Parameters not found with specified parameters: ${e}`);
9103
9407
  }
9104
9408
  debugLogger.forState(state).warn("Failed to load parameters, attempting to fall back to cache:", e);
9105
9409
  let parameters2;
9106
9410
  if (id) {
9107
- parameters2 = await state.parametersCache.get({ id });
9411
+ parameters2 = await parametersCache.get({ id });
9108
9412
  if (!parameters2) {
9109
9413
  throw new Error(
9110
9414
  `Parameters with id ${id} not found (not found on server or in local cache): ${e}`
9111
9415
  );
9112
9416
  }
9113
9417
  } else {
9114
- parameters2 = await state.parametersCache.get({
9418
+ parameters2 = await parametersCache.get({
9115
9419
  slug,
9116
9420
  projectId,
9117
9421
  projectName,
@@ -9127,6 +9431,7 @@ async function loadParameters({
9127
9431
  }
9128
9432
  return parameters2;
9129
9433
  }
9434
+ const { response } = result;
9130
9435
  if (!("objects" in response) || response.objects.length === 0) {
9131
9436
  if (id) {
9132
9437
  throw new Error(`Parameters with id ${id} not found.`);
@@ -9150,9 +9455,9 @@ async function loadParameters({
9150
9455
  const parameters = new RemoteEvalParameters(metadata);
9151
9456
  try {
9152
9457
  if (id) {
9153
- await state.parametersCache.set({ id }, parameters);
9458
+ await parametersCache.set({ id }, parameters);
9154
9459
  } else if (slug) {
9155
- await state.parametersCache.set(
9460
+ await parametersCache.set(
9156
9461
  { slug, projectId, projectName, version: version ?? "latest" },
9157
9462
  parameters
9158
9463
  );
@@ -9193,6 +9498,52 @@ async function login(options = {}) {
9193
9498
  await state.login(options);
9194
9499
  return state;
9195
9500
  }
9501
+ async function loginToLoaderRequestState({
9502
+ appUrl,
9503
+ apiKey,
9504
+ orgName,
9505
+ fetch: fetch2
9506
+ }) {
9507
+ let orgId;
9508
+ let apiUrl;
9509
+ if (apiKey === TEST_API_KEY) {
9510
+ orgId = "test-org-id";
9511
+ apiUrl = "https://braintrust.dev/fake-api-url";
9512
+ } else {
9513
+ let loginResponse;
9514
+ try {
9515
+ loginResponse = await fetch2(_urljoin(appUrl, `/api/apikey/login`), {
9516
+ method: "POST",
9517
+ headers: {
9518
+ "Content-Type": "application/json",
9519
+ Authorization: `Bearer ${apiKey}`
9520
+ }
9521
+ });
9522
+ } catch (error) {
9523
+ throw new HTTPTransportError(error);
9524
+ }
9525
+ const info = await readJSONResponse(
9526
+ await checkResponse(loginResponse),
9527
+ true
9528
+ );
9529
+ const org = selectLoginOrg(info.org_info, orgName);
9530
+ orgId = org.id;
9531
+ apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
9532
+ if (!apiUrl) {
9533
+ throw new Error(
9534
+ 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."
9535
+ );
9536
+ }
9537
+ }
9538
+ const apiConnection = new HTTPConnection(apiUrl, fetch2, true);
9539
+ apiConnection.set_token(apiKey);
9540
+ apiConnection.make_long_lived();
9541
+ return {
9542
+ appUrl,
9543
+ orgId,
9544
+ apiConn: () => apiConnection
9545
+ };
9546
+ }
9196
9547
  async function loginToState(options = {}) {
9197
9548
  const {
9198
9549
  appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
@@ -9224,16 +9575,18 @@ async function loginToState(options = {}) {
9224
9575
  _saveOrgInfo(state, testOrgInfo, testOrgInfo[0].name);
9225
9576
  return state;
9226
9577
  } else {
9227
- const resp = await checkResponse(
9228
- await fetch2(_urljoin(state.appUrl, `/api/apikey/login`), {
9578
+ const loginResponse = await fetch2(
9579
+ _urljoin(state.appUrl, `/api/apikey/login`),
9580
+ {
9229
9581
  method: "POST",
9230
9582
  headers: {
9231
9583
  "Content-Type": "application/json",
9232
9584
  Authorization: `Bearer ${apiKey}`
9233
9585
  }
9234
- })
9586
+ }
9235
9587
  );
9236
- const info = await resp.json();
9588
+ const resp = await checkResponse(loginResponse);
9589
+ const info = await readJSONResponse(resp);
9237
9590
  _saveOrgInfo(state, info.org_info, orgName);
9238
9591
  if (!state.apiUrl) {
9239
9592
  if (orgName) {
@@ -9736,11 +10089,11 @@ function wrapTraced(fn, args) {
9736
10089
  }
9737
10090
  if (args?.asyncFlush) {
9738
10091
  return ((...fnArgs) => traced((span) => {
9739
- if (!hasExplicitInput) {
10092
+ if (!args?.noTraceIO && !hasExplicitInput) {
9740
10093
  span.log({ input: fnArgs });
9741
10094
  }
9742
10095
  const output = fn(...fnArgs);
9743
- if (!hasExplicitOutput) {
10096
+ if (!args?.noTraceIO && !hasExplicitOutput) {
9744
10097
  if (output instanceof Promise) {
9745
10098
  return (async () => {
9746
10099
  const result = await output;
@@ -9755,12 +10108,12 @@ function wrapTraced(fn, args) {
9755
10108
  }, spanArgs));
9756
10109
  } else {
9757
10110
  return ((...fnArgs) => traced(async (span) => {
9758
- if (!hasExplicitInput) {
10111
+ if (!args?.noTraceIO && !hasExplicitInput) {
9759
10112
  span.log({ input: fnArgs });
9760
10113
  }
9761
10114
  const outputResult = fn(...fnArgs);
9762
10115
  const output = await outputResult;
9763
- if (!hasExplicitOutput) {
10116
+ if (!args?.noTraceIO && !hasExplicitOutput) {
9764
10117
  span.log({ output });
9765
10118
  }
9766
10119
  return output;
@@ -9777,6 +10130,15 @@ function _internalStartSpanWithInitialMerge(args) {
9777
10130
  [INITIAL_SPAN_WRITE_AS_MERGE]: true
9778
10131
  }).span;
9779
10132
  }
10133
+ function _internalStartSpanWithInitialMergeAndParentSpanIds(args) {
10134
+ return startSpanAndIsLogger(
10135
+ {
10136
+ ...args,
10137
+ [INITIAL_SPAN_WRITE_AS_MERGE]: true
10138
+ },
10139
+ { useParentSpanIdsForObjectParent: true }
10140
+ ).span;
10141
+ }
9780
10142
  function _internalStartSpanWithContext(args, context) {
9781
10143
  return startSpanAndIsLogger({
9782
10144
  ...args,
@@ -9790,7 +10152,7 @@ async function flush(options) {
9790
10152
  function setFetch(fetch2) {
9791
10153
  _internalGetGlobalState().setFetch(fetch2);
9792
10154
  }
9793
- function startSpanAndIsLogger(args) {
10155
+ function startSpanAndIsLogger(args, internalOptions) {
9794
10156
  const state = args?.state ?? _globalState;
9795
10157
  const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
9796
10158
  asyncFlush: args?.asyncFlush,
@@ -9804,7 +10166,7 @@ function startSpanAndIsLogger(args) {
9804
10166
  ) ? {
9805
10167
  spanId: parentObject.data.span_id,
9806
10168
  rootSpanId: parentObject.data.root_span_id
9807
- } : void 0;
10169
+ } : internalOptions?.useParentSpanIdsForObjectParent ? args?.parentSpanIds : void 0;
9808
10170
  const { parent: _ignoredParent, ...spanArgs } = args ?? {};
9809
10171
  const span = new SpanImpl({
9810
10172
  state,
@@ -9886,27 +10248,28 @@ async function* asyncGeneratorWithCurrent(span, gen, state = void 0) {
9886
10248
  function withParent(parent, callback, state = void 0) {
9887
10249
  return (state ?? _globalState).currentParent.run(parent, () => callback());
9888
10250
  }
9889
- function _saveOrgInfo(state, org_info, org_name) {
9890
- if (org_info.length === 0) {
10251
+ function _saveOrgInfo(state, orgInfo, orgName) {
10252
+ const org = selectLoginOrg(orgInfo, orgName);
10253
+ state.orgId = org.id;
10254
+ state.orgName = org.name;
10255
+ state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
10256
+ state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
10257
+ state.gitMetadataSettings = org.git_metadata || void 0;
10258
+ }
10259
+ function selectLoginOrg(orgInfo, orgName) {
10260
+ if (orgInfo.length === 0) {
9891
10261
  throw new LoginInvalidOrgError(
9892
10262
  "This user is not part of any organizations."
9893
10263
  );
9894
10264
  }
9895
- for (const org of org_info) {
9896
- if (org_name === void 0 || org.name === org_name) {
9897
- state.orgId = org.id;
9898
- state.orgName = org.name;
9899
- state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
9900
- state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
9901
- state.gitMetadataSettings = org.git_metadata || void 0;
9902
- break;
10265
+ for (const org of orgInfo) {
10266
+ if (orgName === void 0 || org.name === orgName) {
10267
+ return org;
9903
10268
  }
9904
10269
  }
9905
- if (state.orgId === void 0) {
9906
- throw new LoginInvalidOrgError(
9907
- `Organization ${org_name} not found. Must be one of ${org_info.map((x) => x.name).join(", ")}`
9908
- );
9909
- }
10270
+ throw new LoginInvalidOrgError(
10271
+ `Organization ${orgName} not found. Must be one of ${orgInfo.map((org) => org.name).join(", ")}`
10272
+ );
9910
10273
  }
9911
10274
  function validateTags(tags) {
9912
10275
  const seen = /* @__PURE__ */ new Set();
@@ -11812,6 +12175,14 @@ var Prompt2 = class _Prompt {
11812
12175
  static isPrompt(data) {
11813
12176
  return typeof data === "object" && data !== null && "__braintrust_prompt_marker" in data;
11814
12177
  }
12178
+ /** @internal */
12179
+ _internalSerializeForCache() {
12180
+ return {
12181
+ metadata: this.metadata,
12182
+ defaults: this.defaults,
12183
+ noTrace: this.noTrace
12184
+ };
12185
+ }
11815
12186
  static fromPromptData(name, promptData) {
11816
12187
  return new _Prompt(
11817
12188
  {
@@ -11852,6 +12223,10 @@ var RemoteEvalParameters = class {
11852
12223
  get data() {
11853
12224
  return this.metadata.function_data.data ?? {};
11854
12225
  }
12226
+ /** @internal */
12227
+ _internalSerializeForCache() {
12228
+ return { metadata: this.metadata };
12229
+ }
11855
12230
  validate(data) {
11856
12231
  if (typeof data !== "object" || data === null) {
11857
12232
  return false;
@@ -12638,56 +13013,14 @@ function suppressionStore() {
12638
13013
  autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
12639
13014
  return autoInstrumentationSuppressionStore;
12640
13015
  }
12641
- function currentFrames() {
12642
- return suppressionStore().getStore()?.frames ?? [];
12643
- }
12644
13016
  function isAutoInstrumentationSuppressed() {
12645
- const frames = currentFrames();
12646
- return frames[frames.length - 1]?.mode === "suppress";
13017
+ return suppressionStore().getStore() === true;
12647
13018
  }
12648
13019
  function runWithAutoInstrumentationSuppressed(callback) {
12649
- const frame = {
12650
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
12651
- mode: "suppress"
12652
- };
12653
- return suppressionStore().run(
12654
- { frames: [...currentFrames(), frame] },
12655
- callback
12656
- );
12657
- }
12658
- function bindAutoInstrumentationSuppressionToStart(tracingChannel) {
12659
- const startChannel = tracingChannel.start;
12660
- if (!startChannel) {
12661
- return void 0;
12662
- }
12663
- const store = suppressionStore();
12664
- startChannel.bindStore(store, () => ({
12665
- frames: [
12666
- ...currentFrames(),
12667
- {
12668
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
12669
- mode: "suppress"
12670
- }
12671
- ]
12672
- }));
12673
- return () => {
12674
- startChannel.unbindStore(store);
12675
- };
13020
+ return suppressionStore().run(true, callback);
12676
13021
  }
12677
- function enterAutoInstrumentationAllowed() {
12678
- const frame = {
12679
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
12680
- mode: "allow"
12681
- };
12682
- suppressionStore().enterWith({
12683
- frames: [...currentFrames(), frame]
12684
- });
12685
- return () => {
12686
- const frames = currentFrames().filter(
12687
- (candidate) => candidate.id !== frame.id
12688
- );
12689
- suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
12690
- };
13022
+ function runWithAutoInstrumentationAllowed(callback) {
13023
+ return suppressionStore().run(void 0, callback);
12691
13024
  }
12692
13025
 
12693
13026
  // src/instrumentation/core/channel-tracing.ts
@@ -13277,6 +13610,131 @@ function unsubscribeAll(unsubscribers) {
13277
13610
  return [];
13278
13611
  }
13279
13612
 
13613
+ // src/instrumentation/core/channel-definitions.ts
13614
+ function channel(spec) {
13615
+ return spec;
13616
+ }
13617
+ function defineChannels(pkg, channels, options) {
13618
+ const { instrumentationName } = options;
13619
+ return Object.fromEntries(
13620
+ Object.entries(channels).map(([key, spec]) => {
13621
+ const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
13622
+ if (spec.kind === "async") {
13623
+ const asyncSpec = spec;
13624
+ const tracingChannel2 = () => isomorph_default.newTracingChannel(
13625
+ fullChannelName
13626
+ );
13627
+ const intercept2 = (interceptor) => {
13628
+ const hook = tracingChannel2();
13629
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13630
+ };
13631
+ };
13632
+ return [
13633
+ key,
13634
+ {
13635
+ ...asyncSpec,
13636
+ instrumentationName,
13637
+ intercept: intercept2,
13638
+ invoke: (target, thisArg, args, additional) => {
13639
+ const hook = tracingChannel2();
13640
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13641
+ },
13642
+ tracingChannel: tracingChannel2,
13643
+ tracePromise: (fn, context) => tracingChannel2().tracePromise(
13644
+ fn,
13645
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13646
+ context
13647
+ )
13648
+ }
13649
+ ];
13650
+ }
13651
+ const syncSpec = spec;
13652
+ const tracingChannel = () => isomorph_default.newTracingChannel(
13653
+ fullChannelName
13654
+ );
13655
+ const intercept = (interceptor) => {
13656
+ const hook = tracingChannel();
13657
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13658
+ };
13659
+ };
13660
+ return [
13661
+ key,
13662
+ {
13663
+ ...syncSpec,
13664
+ instrumentationName,
13665
+ intercept,
13666
+ invoke: (target, thisArg, args, additional) => {
13667
+ const hook = tracingChannel();
13668
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13669
+ },
13670
+ tracingChannel,
13671
+ traceSync: (fn, context) => tracingChannel().traceSync(
13672
+ fn,
13673
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13674
+ context
13675
+ )
13676
+ }
13677
+ ];
13678
+ })
13679
+ );
13680
+ }
13681
+
13682
+ // src/instrumentation/plugins/openai-channels.ts
13683
+ var openAIChannels = defineChannels(
13684
+ "openai",
13685
+ {
13686
+ filesCreateTraced: channel({
13687
+ channelName: "files.create-traced",
13688
+ kind: "async"
13689
+ }),
13690
+ batchesRetrieveTraced: channel({
13691
+ channelName: "batches.retrieve-traced",
13692
+ kind: "async"
13693
+ }),
13694
+ batchesCompleteTrace: channel({
13695
+ channelName: "batches.complete-trace",
13696
+ kind: "async"
13697
+ }),
13698
+ chatCompletionsCreate: channel({
13699
+ channelName: "chat.completions.create",
13700
+ kind: "async"
13701
+ }),
13702
+ embeddingsCreate: channel({
13703
+ channelName: "embeddings.create",
13704
+ kind: "async"
13705
+ }),
13706
+ betaChatCompletionsParse: channel({
13707
+ channelName: "beta.chat.completions.parse",
13708
+ kind: "async"
13709
+ }),
13710
+ betaChatCompletionsStream: channel({
13711
+ channelName: "beta.chat.completions.stream",
13712
+ kind: "sync-stream"
13713
+ }),
13714
+ moderationsCreate: channel({
13715
+ channelName: "moderations.create",
13716
+ kind: "async"
13717
+ }),
13718
+ responsesCreate: channel({
13719
+ channelName: "responses.create",
13720
+ kind: "async"
13721
+ }),
13722
+ responsesStream: channel({
13723
+ channelName: "responses.stream",
13724
+ kind: "sync-stream"
13725
+ }),
13726
+ responsesParse: channel({
13727
+ channelName: "responses.parse",
13728
+ kind: "async"
13729
+ }),
13730
+ responsesCompact: channel({
13731
+ channelName: "responses.compact",
13732
+ kind: "async"
13733
+ })
13734
+ },
13735
+ { instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
13736
+ );
13737
+
13280
13738
  // src/wrappers/attachment-utils.ts
13281
13739
  function getExtensionFromMediaType(mediaType) {
13282
13740
  const extensionMap = {
@@ -13452,118 +13910,91 @@ function processInputAttachments(input) {
13452
13910
  return processNode(input);
13453
13911
  }
13454
13912
 
13455
- // src/instrumentation/core/channel-definitions.ts
13456
- function channel(spec) {
13457
- return spec;
13458
- }
13459
- function defineChannels(pkg, channels, options) {
13460
- const { instrumentationName } = options;
13461
- return Object.fromEntries(
13462
- Object.entries(channels).map(([key, spec]) => {
13463
- const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
13464
- if (spec.kind === "async") {
13465
- const asyncSpec = spec;
13466
- const tracingChannel2 = () => isomorph_default.newTracingChannel(
13467
- fullChannelName
13468
- );
13469
- const intercept2 = (interceptor) => {
13470
- const hook = tracingChannel2();
13471
- return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13472
- };
13473
- };
13474
- return [
13475
- key,
13476
- {
13477
- ...asyncSpec,
13478
- instrumentationName,
13479
- intercept: intercept2,
13480
- invoke: (target, thisArg, args, additional) => {
13481
- const hook = tracingChannel2();
13482
- return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13483
- },
13484
- tracingChannel: tracingChannel2,
13485
- tracePromise: (fn, context) => tracingChannel2().tracePromise(
13486
- fn,
13487
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13488
- context
13489
- )
13490
- }
13491
- ];
13913
+ // src/instrumentation/plugins/openai-span-data.ts
13914
+ var OPENAI_METADATA_KEYS = [
13915
+ "model",
13916
+ "temperature",
13917
+ "top_p",
13918
+ "max_tokens",
13919
+ "frequency_penalty",
13920
+ "presence_penalty",
13921
+ "stop",
13922
+ "response_format",
13923
+ "tools",
13924
+ "tool_choice",
13925
+ "parallel_tool_calls",
13926
+ "max_tool_calls"
13927
+ ];
13928
+ function batchMetadata(params) {
13929
+ const metadata = { provider: "openai" };
13930
+ for (const key of OPENAI_METADATA_KEYS) {
13931
+ try {
13932
+ const value = Reflect.get(params, key);
13933
+ if (value !== void 0) {
13934
+ metadata[key] = value;
13492
13935
  }
13493
- const syncSpec = spec;
13494
- const tracingChannel = () => isomorph_default.newTracingChannel(
13495
- fullChannelName
13496
- );
13497
- const intercept = (interceptor) => {
13498
- const hook = tracingChannel();
13499
- return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13500
- };
13501
- };
13502
- return [
13503
- key,
13504
- {
13505
- ...syncSpec,
13506
- instrumentationName,
13507
- intercept,
13508
- invoke: (target, thisArg, args, additional) => {
13509
- const hook = tracingChannel();
13510
- return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13511
- },
13512
- tracingChannel,
13513
- traceSync: (fn, context) => tracingChannel().traceSync(
13514
- fn,
13515
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13516
- context
13517
- )
13518
- }
13519
- ];
13520
- })
13521
- );
13936
+ } catch {
13937
+ }
13938
+ }
13939
+ return metadata;
13940
+ }
13941
+ function extractOpenAIBatchInput(endpoint, params) {
13942
+ const input = endpoint === "/v1/chat/completions" ? params.messages : params.input;
13943
+ return {
13944
+ input: processInputAttachments(input),
13945
+ metadata: batchMetadata(params)
13946
+ };
13947
+ }
13948
+ function extractOpenAIChatInput(params) {
13949
+ const { messages, ...metadata } = params;
13950
+ return {
13951
+ input: processInputAttachments(messages),
13952
+ metadata: { ...metadata, provider: "openai" }
13953
+ };
13954
+ }
13955
+ function extractOpenAIResponsesInput(params) {
13956
+ const { input, ...metadata } = params;
13957
+ return {
13958
+ input: processInputAttachments(input),
13959
+ metadata: { ...metadata, provider: "openai" }
13960
+ };
13961
+ }
13962
+ function extractOpenAIResponsesMetadata(result) {
13963
+ if (!result) {
13964
+ return void 0;
13965
+ }
13966
+ const { output: _output, usage: _usage, ...metadata } = result;
13967
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
13968
+ }
13969
+ function processImagesInOutput(output) {
13970
+ if (Array.isArray(output)) {
13971
+ return output.map(processImagesInOutput);
13972
+ }
13973
+ if (isObject(output) && output.type === "image_generation_call" && typeof output.result === "string" && output.result) {
13974
+ const fileExtension = output.output_format || "png";
13975
+ const contentType = `image/${fileExtension}`;
13976
+ const baseFilename = typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
13977
+ let binaryString;
13978
+ try {
13979
+ binaryString = atob(output.result);
13980
+ } catch {
13981
+ return output;
13982
+ }
13983
+ const bytes = new Uint8Array(binaryString.length);
13984
+ for (let i = 0; i < binaryString.length; i++) {
13985
+ bytes[i] = binaryString.charCodeAt(i);
13986
+ }
13987
+ return {
13988
+ ...output,
13989
+ result: new Attachment({
13990
+ data: new Blob([bytes], { type: contentType }),
13991
+ filename: `${baseFilename}.${fileExtension}`,
13992
+ contentType
13993
+ })
13994
+ };
13995
+ }
13996
+ return output;
13522
13997
  }
13523
-
13524
- // src/instrumentation/plugins/openai-channels.ts
13525
- var openAIChannels = defineChannels(
13526
- "openai",
13527
- {
13528
- chatCompletionsCreate: channel({
13529
- channelName: "chat.completions.create",
13530
- kind: "async"
13531
- }),
13532
- embeddingsCreate: channel({
13533
- channelName: "embeddings.create",
13534
- kind: "async"
13535
- }),
13536
- betaChatCompletionsParse: channel({
13537
- channelName: "beta.chat.completions.parse",
13538
- kind: "async"
13539
- }),
13540
- betaChatCompletionsStream: channel({
13541
- channelName: "beta.chat.completions.stream",
13542
- kind: "sync-stream"
13543
- }),
13544
- moderationsCreate: channel({
13545
- channelName: "moderations.create",
13546
- kind: "async"
13547
- }),
13548
- responsesCreate: channel({
13549
- channelName: "responses.create",
13550
- kind: "async"
13551
- }),
13552
- responsesStream: channel({
13553
- channelName: "responses.stream",
13554
- kind: "sync-stream"
13555
- }),
13556
- responsesParse: channel({
13557
- channelName: "responses.parse",
13558
- kind: "async"
13559
- }),
13560
- responsesCompact: channel({
13561
- channelName: "responses.compact",
13562
- kind: "async"
13563
- })
13564
- },
13565
- { instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
13566
- );
13567
13998
 
13568
13999
  // src/openai-utils.ts
13569
14000
  var BRAINTRUST_CACHED_STREAM_METRIC = "__braintrust_cached_metric";
@@ -13620,23 +14051,573 @@ function getCachedMetricFromHeaders(headers) {
13620
14051
  return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
13621
14052
  }
13622
14053
 
14054
+ // src/instrumentation/plugins/openai-batch-instrumentation.ts
14055
+ var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
14056
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
14057
+ "completed",
14058
+ "failed",
14059
+ "expired",
14060
+ "cancelled"
14061
+ ]);
14062
+ var pendingBatchTraces = /* @__PURE__ */ new Map();
14063
+ function read(value, key) {
14064
+ if (!isObject(value)) {
14065
+ return void 0;
14066
+ }
14067
+ try {
14068
+ return Reflect.get(value, key);
14069
+ } catch {
14070
+ return void 0;
14071
+ }
14072
+ }
14073
+ function isBatchRecordIterable(value) {
14074
+ if (value === null || typeof value !== "object" && typeof value !== "function") {
14075
+ return false;
14076
+ }
14077
+ return typeof read(value, Symbol.iterator) === "function" || typeof read(value, Symbol.asyncIterator) === "function";
14078
+ }
14079
+ function validCustomId(value) {
14080
+ return typeof value === "string" && value.length > 0 && value.length <= 64;
14081
+ }
14082
+ function logBatchInstrumentationError(context, error) {
14083
+ debugLogger.debug(`OpenAI Batch instrumentation ${context}:`, error);
14084
+ }
14085
+ async function exportParent(parent) {
14086
+ if ("toStr" in parent && typeof parent.toStr === "function") {
14087
+ return parent.toStr();
14088
+ }
14089
+ if ("export" in parent && typeof parent.export === "function") {
14090
+ return await parent.export();
14091
+ }
14092
+ return void 0;
14093
+ }
14094
+ async function deterministicDigest(namespace, ...parts) {
14095
+ const encoded = new TextEncoder().encode(
14096
+ [namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
14097
+ );
14098
+ return new Uint8Array(
14099
+ await globalThis.crypto.subtle.digest("SHA-256", encoded)
14100
+ );
14101
+ }
14102
+ function digestHex(bytes, length) {
14103
+ return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
14104
+ }
14105
+ function digestUuid(bytes) {
14106
+ const hex = digestHex(bytes, 16);
14107
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
14108
+ }
14109
+ async function batchSpanIds(inputFileId) {
14110
+ const [row, span, root] = await Promise.all([
14111
+ deterministicDigest("openai:batch:row", inputFileId),
14112
+ deterministicDigest("openai:batch:span", inputFileId),
14113
+ deterministicDigest("openai:batch:root", inputFileId)
14114
+ ]);
14115
+ return {
14116
+ rowId: digestUuid(row),
14117
+ spanId: digestHex(span, 8),
14118
+ rootSpanId: digestHex(root, 16)
14119
+ };
14120
+ }
14121
+ async function childSpanIds(inputFileId, customId) {
14122
+ const [row, span] = await Promise.all([
14123
+ deterministicDigest("openai:batch:child:row", inputFileId, customId),
14124
+ deterministicDigest("openai:batch:child:span", inputFileId, customId)
14125
+ ]);
14126
+ return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
14127
+ }
14128
+ async function startBatchSpan(context) {
14129
+ const ids = await batchSpanIds(context.inputFileId);
14130
+ const parent = SpanComponentsV4.fromStr(context.parent);
14131
+ const hasParentSpan = Boolean(
14132
+ parent.data.row_id && parent.data.span_id && parent.data.root_span_id
14133
+ );
14134
+ return withCurrent(
14135
+ NOOP_SPAN,
14136
+ () => _internalStartSpanWithInitialMergeAndParentSpanIds(
14137
+ withSpanInstrumentationName(
14138
+ {
14139
+ name: "openai.batch",
14140
+ type: "task" /* TASK */,
14141
+ parent: context.parent,
14142
+ ...!hasParentSpan ? {
14143
+ parentSpanIds: {
14144
+ parentSpanIds: [],
14145
+ rootSpanId: ids.rootSpanId
14146
+ }
14147
+ } : {},
14148
+ spanId: ids.spanId,
14149
+ startTime: context.taskStartTime,
14150
+ event: {
14151
+ id: ids.rowId,
14152
+ metadata: {
14153
+ endpoint: context.endpoint,
14154
+ input_file_id: context.inputFileId,
14155
+ provider: "openai"
14156
+ }
14157
+ }
14158
+ },
14159
+ INSTRUMENTATION_NAMES.OPENAI
14160
+ )
14161
+ )
14162
+ );
14163
+ }
14164
+ async function startBatchChild(context, taskParent, input) {
14165
+ const ids = await childSpanIds(context.inputFileId, input.customId);
14166
+ return withCurrent(
14167
+ NOOP_SPAN,
14168
+ () => _internalStartSpanWithInitialMerge(
14169
+ withSpanInstrumentationName(
14170
+ {
14171
+ name: context.endpoint === "/v1/chat/completions" ? "Chat Completion" : "openai.responses.create",
14172
+ type: "llm" /* LLM */,
14173
+ parent: taskParent,
14174
+ spanId: ids.spanId,
14175
+ startTime: context.childStartTime,
14176
+ event: {
14177
+ id: ids.rowId,
14178
+ ...input.spanData?.input !== void 0 ? { input: input.spanData.input } : {},
14179
+ metadata: {
14180
+ ...input.spanData?.metadata,
14181
+ custom_id: input.customId,
14182
+ provider: "openai"
14183
+ }
14184
+ }
14185
+ },
14186
+ INSTRUMENTATION_NAMES.OPENAI
14187
+ )
14188
+ )
14189
+ );
14190
+ }
14191
+ async function* jsonlRecords(file, onIssue = () => {
14192
+ }) {
14193
+ const resolvedFile = await file;
14194
+ if (typeof resolvedFile === "string") {
14195
+ for (const line of resolvedFile.split("\n")) {
14196
+ if (!line.trim()) {
14197
+ continue;
14198
+ }
14199
+ try {
14200
+ yield JSON.parse(line.replace(/\r$/, ""));
14201
+ } catch (error) {
14202
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14203
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14204
+ }
14205
+ }
14206
+ return;
14207
+ }
14208
+ const body = read(resolvedFile, "body");
14209
+ const getReader = read(body, "getReader");
14210
+ if (isObject(body) && typeof getReader === "function") {
14211
+ let reader;
14212
+ try {
14213
+ reader = Reflect.apply(getReader, body, []);
14214
+ const decoder2 = new TextDecoder();
14215
+ let pending = "";
14216
+ while (true) {
14217
+ const readChunk = read(reader, "read");
14218
+ if (typeof readChunk !== "function") {
14219
+ throw new Error("Response body stream has no read method");
14220
+ }
14221
+ const chunk = await Reflect.apply(readChunk, reader, []);
14222
+ if (!isObject(chunk)) {
14223
+ throw new Error("Response body stream returned an invalid chunk");
14224
+ }
14225
+ if (chunk.done === true) {
14226
+ pending += decoder2.decode();
14227
+ break;
14228
+ }
14229
+ if (!(chunk.value instanceof Uint8Array)) {
14230
+ throw new Error("Response body stream returned a non-byte chunk");
14231
+ }
14232
+ pending += decoder2.decode(chunk.value, { stream: true });
14233
+ let newline = pending.indexOf("\n");
14234
+ while (newline !== -1) {
14235
+ const line = pending.slice(0, newline).replace(/\r$/, "");
14236
+ pending = pending.slice(newline + 1);
14237
+ if (line.trim()) {
14238
+ try {
14239
+ yield JSON.parse(line);
14240
+ } catch (error) {
14241
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14242
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14243
+ }
14244
+ }
14245
+ newline = pending.indexOf("\n");
14246
+ }
14247
+ }
14248
+ if (pending.trim()) {
14249
+ try {
14250
+ yield JSON.parse(pending.replace(/\r$/, ""));
14251
+ } catch (error) {
14252
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14253
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14254
+ }
14255
+ }
14256
+ } catch (error) {
14257
+ logBatchInstrumentationError("could not read JSONL response body", error);
14258
+ onIssue(new Error("OpenAI Batch response body could not be read"));
14259
+ } finally {
14260
+ const releaseLock = read(reader, "releaseLock");
14261
+ if (typeof releaseLock === "function") {
14262
+ try {
14263
+ Reflect.apply(releaseLock, reader, []);
14264
+ } catch (error) {
14265
+ logBatchInstrumentationError(
14266
+ "could not release stream reader",
14267
+ error
14268
+ );
14269
+ }
14270
+ }
14271
+ }
14272
+ return;
14273
+ }
14274
+ if (isBatchRecordIterable(resolvedFile)) {
14275
+ for await (const record of resolvedFile) {
14276
+ yield record;
14277
+ }
14278
+ return;
14279
+ }
14280
+ logBatchInstrumentationError("skipped invalid JSONL source", resolvedFile);
14281
+ onIssue(new Error("OpenAI Batch file source is invalid"));
14282
+ }
14283
+ async function readBatchInputs(file) {
14284
+ const inputs = /* @__PURE__ */ new Map();
14285
+ const issues = [];
14286
+ let endpoint;
14287
+ try {
14288
+ for await (const value of jsonlRecords(
14289
+ file,
14290
+ (issue) => issues.push(issue)
14291
+ )) {
14292
+ const customId = read(value, "custom_id");
14293
+ const url = read(value, "url");
14294
+ const body = read(value, "body");
14295
+ if (!validCustomId(customId) || inputs.has(customId) || read(value, "method") !== "POST" || typeof url !== "string" || !SUPPORTED_ENDPOINTS.has(url) || endpoint !== void 0 && endpoint !== url || !isObject(body)) {
14296
+ issues.push(new Error("OpenAI Batch input contains an invalid record"));
14297
+ continue;
14298
+ }
14299
+ endpoint = url;
14300
+ let spanData;
14301
+ try {
14302
+ spanData = extractOpenAIBatchInput(url, body);
14303
+ } catch (error) {
14304
+ logBatchInstrumentationError("could not extract batch input", error);
14305
+ }
14306
+ inputs.set(customId, { customId, spanData });
14307
+ }
14308
+ } catch (error) {
14309
+ logBatchInstrumentationError("could not process input file", error);
14310
+ issues.push(new Error("OpenAI Batch input file could not be processed"));
14311
+ }
14312
+ if (!endpoint || inputs.size === 0) {
14313
+ issues.push(new Error("OpenAI Batch input contains no supported records"));
14314
+ }
14315
+ return { endpoint, inputs, issues };
14316
+ }
14317
+ async function writePendingSpans(trace, endTime) {
14318
+ const task = await startBatchSpan(trace.context);
14319
+ const taskParent = await task.export();
14320
+ for (const input of trace.inputs.values()) {
14321
+ try {
14322
+ const child = await startBatchChild(trace.context, taskParent, input);
14323
+ if (endTime !== void 0) {
14324
+ child.end({ endTime });
14325
+ }
14326
+ } catch (error) {
14327
+ logBatchInstrumentationError("could not write batch request span", error);
14328
+ }
14329
+ }
14330
+ if (endTime !== void 0) {
14331
+ if (trace.status && trace.status !== "completed") {
14332
+ task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14333
+ }
14334
+ task.end({ endTime });
14335
+ }
14336
+ }
14337
+ var interceptOpenAIFilesCreateTraced = async (target, thisArg, args) => {
14338
+ const startTime = getCurrentUnixTimestamp();
14339
+ const inputPromise = readBatchInputs(args[0].inputFileContent);
14340
+ const parentPromise = exportParent(args[0].parent);
14341
+ const file = await Reflect.apply(target, thisArg, args);
14342
+ try {
14343
+ const inputFileId = read(file, "id");
14344
+ const [inputData, exportedParent2] = await Promise.all([
14345
+ inputPromise,
14346
+ parentPromise
14347
+ ]);
14348
+ if (typeof inputFileId !== "string" || !exportedParent2 || !inputData.endpoint || inputData.issues.length > 0) {
14349
+ if (inputData.issues[0]) {
14350
+ logBatchInstrumentationError(
14351
+ "skipped invalid input file",
14352
+ inputData.issues[0]
14353
+ );
14354
+ }
14355
+ return file;
14356
+ }
14357
+ const trace = {
14358
+ context: {
14359
+ inputFileId,
14360
+ endpoint: inputData.endpoint,
14361
+ parent: exportedParent2,
14362
+ taskStartTime: startTime,
14363
+ childStartTime: startTime
14364
+ },
14365
+ inputs: inputData.inputs
14366
+ };
14367
+ pendingBatchTraces.set(inputFileId, trace);
14368
+ await writePendingSpans(trace);
14369
+ } catch (error) {
14370
+ logBatchInstrumentationError("could not start batch spans", error);
14371
+ }
14372
+ return file;
14373
+ };
14374
+ function validTimestamp(value) {
14375
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
14376
+ }
14377
+ function terminalEndTime(batch, startTime) {
14378
+ let timestamp;
14379
+ switch (batch.status) {
14380
+ case "completed":
14381
+ timestamp = batch.completed_at;
14382
+ break;
14383
+ case "failed":
14384
+ timestamp = batch.failed_at;
14385
+ break;
14386
+ case "expired":
14387
+ timestamp = batch.expired_at;
14388
+ break;
14389
+ default:
14390
+ timestamp = batch.cancelled_at;
14391
+ }
14392
+ return validTimestamp(timestamp) ? Math.max(timestamp, startTime) : Math.max(getCurrentUnixTimestamp(), startTime);
14393
+ }
14394
+ async function updateBatchTimestamps(batch) {
14395
+ const trace = pendingBatchTraces.get(batch.input_file_id);
14396
+ if (!trace || trace.context.endpoint !== batch.endpoint) {
14397
+ return;
14398
+ }
14399
+ if (validTimestamp(batch.created_at)) {
14400
+ trace.context.taskStartTime = batch.created_at;
14401
+ }
14402
+ trace.context.childStartTime = validTimestamp(batch.in_progress_at) ? Math.max(batch.in_progress_at, trace.context.taskStartTime) : trace.context.taskStartTime;
14403
+ trace.status = batch.status;
14404
+ if (TERMINAL_STATUSES.has(batch.status)) {
14405
+ trace.endTime = terminalEndTime(batch, trace.context.childStartTime);
14406
+ }
14407
+ await writePendingSpans(trace, trace.endTime);
14408
+ }
14409
+ var interceptOpenAIBatchesRetrieveTraced = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (batch) => {
14410
+ try {
14411
+ await updateBatchTimestamps(batch);
14412
+ } catch (error) {
14413
+ logBatchInstrumentationError("could not update batch timestamps", error);
14414
+ }
14415
+ return batch;
14416
+ });
14417
+ function errorFromResult(result) {
14418
+ const error = read(result.value, "error");
14419
+ if (isObject(error)) {
14420
+ const message = read(error, "message");
14421
+ return new Error(
14422
+ typeof message === "string" ? message : "OpenAI Batch request failed"
14423
+ );
14424
+ }
14425
+ const response = read(result.value, "response");
14426
+ const statusCode = read(response, "status_code");
14427
+ if (result.source === "error" || typeof statusCode === "number" && (statusCode < 200 || statusCode >= 300)) {
14428
+ const message = read(read(read(response, "body"), "error"), "message");
14429
+ return new Error(
14430
+ typeof message === "string" ? message : "OpenAI Batch request failed"
14431
+ );
14432
+ }
14433
+ return void 0;
14434
+ }
14435
+ async function completeBatchResult(context, taskParent, endTime, input, result) {
14436
+ const child = await startBatchChild(context, taskParent, input);
14437
+ try {
14438
+ const resultError = errorFromResult(result);
14439
+ const responseBody = read(read(result.value, "response"), "body");
14440
+ if (resultError) {
14441
+ child.log({ error: resultError });
14442
+ } else if (isObject(responseBody)) {
14443
+ const model = read(responseBody, "model");
14444
+ child.log({
14445
+ output: context.endpoint === "/v1/chat/completions" ? read(responseBody, "choices") : processImagesInOutput(read(responseBody, "output")),
14446
+ ...typeof model === "string" ? { metadata: { model } } : {},
14447
+ metrics: parseMetricsFromUsage(read(responseBody, "usage"))
14448
+ });
14449
+ } else {
14450
+ child.log({ error: new Error("OpenAI Batch response body is missing") });
14451
+ }
14452
+ } catch (error) {
14453
+ child.log({ error });
14454
+ } finally {
14455
+ child.end({ endTime });
14456
+ }
14457
+ }
14458
+ async function completeResultFile({
14459
+ context,
14460
+ endTime,
14461
+ file,
14462
+ inputs,
14463
+ issues,
14464
+ seen,
14465
+ source,
14466
+ taskParent
14467
+ }) {
14468
+ if (file === void 0) {
14469
+ return;
14470
+ }
14471
+ for await (const value of jsonlRecords(file, (issue) => issues.push(issue))) {
14472
+ const customId = read(value, "custom_id");
14473
+ if (!validCustomId(customId) || !isObject(value)) {
14474
+ issues.push(
14475
+ new Error("OpenAI Batch result is missing a valid custom_id")
14476
+ );
14477
+ continue;
14478
+ }
14479
+ if (seen.has(customId)) {
14480
+ issues.push(new Error("OpenAI Batch result contains a duplicate"));
14481
+ continue;
14482
+ }
14483
+ const input = inputs.get(customId);
14484
+ if (!input) {
14485
+ issues.push(
14486
+ new Error("OpenAI Batch result does not match an input record")
14487
+ );
14488
+ continue;
14489
+ }
14490
+ seen.add(customId);
14491
+ await completeBatchResult(context, taskParent, endTime, input, {
14492
+ value,
14493
+ source
14494
+ });
14495
+ }
14496
+ }
14497
+ function sameInputs(first, second) {
14498
+ return first.size === second.size && [...first.keys()].every((customId) => second.has(customId));
14499
+ }
14500
+ async function contextForCompletion(inputFileId, inputData) {
14501
+ if (!inputData.endpoint || inputData.issues.length > 0) {
14502
+ return void 0;
14503
+ }
14504
+ const existing = pendingBatchTraces.get(inputFileId);
14505
+ if (existing) {
14506
+ if (existing.context.endpoint !== inputData.endpoint || !sameInputs(existing.inputs, inputData.inputs)) {
14507
+ return void 0;
14508
+ }
14509
+ return { ...existing, inputs: inputData.inputs };
14510
+ }
14511
+ const parent = await exportParent(getSpanParentObject());
14512
+ if (!parent) {
14513
+ return void 0;
14514
+ }
14515
+ const startTime = getCurrentUnixTimestamp();
14516
+ return {
14517
+ context: {
14518
+ inputFileId,
14519
+ endpoint: inputData.endpoint,
14520
+ parent,
14521
+ taskStartTime: startTime,
14522
+ childStartTime: startTime
14523
+ },
14524
+ inputs: inputData.inputs
14525
+ };
14526
+ }
14527
+ async function completeBatch(args) {
14528
+ const inputData = await readBatchInputs(args.inputFileContent);
14529
+ const trace = await contextForCompletion(args.inputFileId, inputData);
14530
+ if (!trace) {
14531
+ logBatchInstrumentationError(
14532
+ "left batch spans pending",
14533
+ inputData.issues[0] ?? new Error("OpenAI Batch input does not match")
14534
+ );
14535
+ return;
14536
+ }
14537
+ const endTime = trace.endTime ?? getCurrentUnixTimestamp();
14538
+ const task = await startBatchSpan(trace.context);
14539
+ const taskParent = await task.export();
14540
+ const issues = [];
14541
+ const seen = /* @__PURE__ */ new Set();
14542
+ await Promise.all([
14543
+ completeResultFile({
14544
+ context: trace.context,
14545
+ endTime,
14546
+ file: args.outputFileContent,
14547
+ inputs: trace.inputs,
14548
+ issues,
14549
+ seen,
14550
+ source: "output",
14551
+ taskParent
14552
+ }),
14553
+ completeResultFile({
14554
+ context: trace.context,
14555
+ endTime,
14556
+ file: args.errorFileContent,
14557
+ inputs: trace.inputs,
14558
+ issues,
14559
+ seen,
14560
+ source: "error",
14561
+ taskParent
14562
+ })
14563
+ ]);
14564
+ if (issues.length > 0) {
14565
+ logBatchInstrumentationError("left batch spans pending", issues[0]);
14566
+ return;
14567
+ }
14568
+ const missing = [...trace.inputs.values()].filter(
14569
+ ({ customId }) => !seen.has(customId)
14570
+ );
14571
+ if (!trace.status || trace.status === "completed") {
14572
+ if (missing.length > 0) {
14573
+ logBatchInstrumentationError(
14574
+ "left batch spans pending",
14575
+ new Error("OpenAI Batch result files are incomplete")
14576
+ );
14577
+ return;
14578
+ }
14579
+ } else {
14580
+ for (const input of missing) {
14581
+ const child = await startBatchChild(trace.context, taskParent, input);
14582
+ child.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14583
+ child.end({ endTime });
14584
+ }
14585
+ task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14586
+ }
14587
+ task.end({ endTime });
14588
+ pendingBatchTraces.delete(args.inputFileId);
14589
+ }
14590
+ var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (result) => {
14591
+ try {
14592
+ await completeBatch(args[0]);
14593
+ } catch (error) {
14594
+ logBatchInstrumentationError("could not complete batch", error);
14595
+ }
14596
+ return result;
14597
+ });
14598
+
13623
14599
  // src/instrumentation/plugins/openai-plugin.ts
13624
14600
  var OpenAIPlugin = class extends BasePlugin {
13625
14601
  constructor() {
13626
14602
  super();
13627
14603
  }
13628
14604
  onEnable() {
14605
+ this.unsubscribers.push(
14606
+ openAIChannels.filesCreateTraced.intercept(
14607
+ interceptOpenAIFilesCreateTraced
14608
+ ),
14609
+ openAIChannels.batchesRetrieveTraced.intercept(
14610
+ interceptOpenAIBatchesRetrieveTraced
14611
+ ),
14612
+ openAIChannels.batchesCompleteTrace.intercept(
14613
+ interceptOpenAIBatchTraceComplete
14614
+ )
14615
+ );
13629
14616
  this.unsubscribers.push(
13630
14617
  traceStreamingChannel(openAIChannels.chatCompletionsCreate, {
13631
14618
  name: "Chat Completion",
13632
14619
  type: "llm" /* LLM */,
13633
- extractInput: ([params]) => {
13634
- const { messages, ...metadata } = params;
13635
- return {
13636
- input: processInputAttachments(messages),
13637
- metadata: { ...metadata, provider: "openai" }
13638
- };
13639
- },
14620
+ extractInput: ([params]) => extractOpenAIChatInput(params),
13640
14621
  extractOutput: (result) => {
13641
14622
  return result?.choices;
13642
14623
  },
@@ -13682,13 +14663,7 @@ var OpenAIPlugin = class extends BasePlugin {
13682
14663
  traceStreamingChannel(openAIChannels.betaChatCompletionsParse, {
13683
14664
  name: "Chat Completion",
13684
14665
  type: "llm" /* LLM */,
13685
- extractInput: ([params]) => {
13686
- const { messages, ...metadata } = params;
13687
- return {
13688
- input: processInputAttachments(messages),
13689
- metadata: { ...metadata, provider: "openai" }
13690
- };
13691
- },
14666
+ extractInput: ([params]) => extractOpenAIChatInput(params),
13692
14667
  extractOutput: (result) => {
13693
14668
  return result?.choices;
13694
14669
  },
@@ -13710,13 +14685,7 @@ var OpenAIPlugin = class extends BasePlugin {
13710
14685
  traceSyncStreamChannel(openAIChannels.betaChatCompletionsStream, {
13711
14686
  name: "Chat Completion",
13712
14687
  type: "llm" /* LLM */,
13713
- extractInput: ([params]) => {
13714
- const { messages, ...metadata } = params;
13715
- return {
13716
- input: processInputAttachments(messages),
13717
- metadata: { ...metadata, provider: "openai" }
13718
- };
13719
- }
14688
+ extractInput: ([params]) => extractOpenAIChatInput(params)
13720
14689
  })
13721
14690
  );
13722
14691
  this.unsubscribers.push(
@@ -13746,23 +14715,11 @@ var OpenAIPlugin = class extends BasePlugin {
13746
14715
  traceStreamingChannel(openAIChannels.responsesCreate, {
13747
14716
  name: "openai.responses.create",
13748
14717
  type: "llm" /* LLM */,
13749
- extractInput: ([params]) => {
13750
- const { input, ...metadata } = params;
13751
- return {
13752
- input: processInputAttachments(input),
13753
- metadata: { ...metadata, provider: "openai" }
13754
- };
13755
- },
14718
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13756
14719
  extractOutput: (result) => {
13757
14720
  return processImagesInOutput(result?.output);
13758
14721
  },
13759
- extractMetadata: (result) => {
13760
- if (!result) {
13761
- return void 0;
13762
- }
13763
- const { output: _output, usage: _usage, ...metadata } = result;
13764
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13765
- },
14722
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13766
14723
  extractMetrics: (result, startTime, endEvent) => {
13767
14724
  const metrics = withCachedMetric(
13768
14725
  parseMetricsFromUsage(result?.usage),
@@ -13781,13 +14738,7 @@ var OpenAIPlugin = class extends BasePlugin {
13781
14738
  traceSyncStreamChannel(openAIChannels.responsesStream, {
13782
14739
  name: "openai.responses.create",
13783
14740
  type: "llm" /* LLM */,
13784
- extractInput: ([params]) => {
13785
- const { input, ...metadata } = params;
13786
- return {
13787
- input: processInputAttachments(input),
13788
- metadata: { ...metadata, provider: "openai" }
13789
- };
13790
- },
14741
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13791
14742
  extractFromEvent: (event) => {
13792
14743
  if (event.type !== "response.completed" || !event.response) {
13793
14744
  return {};
@@ -13810,23 +14761,11 @@ var OpenAIPlugin = class extends BasePlugin {
13810
14761
  traceStreamingChannel(openAIChannels.responsesParse, {
13811
14762
  name: "openai.responses.parse",
13812
14763
  type: "llm" /* LLM */,
13813
- extractInput: ([params]) => {
13814
- const { input, ...metadata } = params;
13815
- return {
13816
- input: processInputAttachments(input),
13817
- metadata: { ...metadata, provider: "openai" }
13818
- };
13819
- },
14764
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13820
14765
  extractOutput: (result) => {
13821
14766
  return processImagesInOutput(result?.output);
13822
14767
  },
13823
- extractMetadata: (result) => {
13824
- if (!result) {
13825
- return void 0;
13826
- }
13827
- const { output: _output, usage: _usage, ...metadata } = result;
13828
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13829
- },
14768
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13830
14769
  extractMetrics: (result, startTime, endEvent) => {
13831
14770
  const metrics = withCachedMetric(
13832
14771
  parseMetricsFromUsage(result?.usage),
@@ -13845,23 +14784,11 @@ var OpenAIPlugin = class extends BasePlugin {
13845
14784
  traceAsyncChannel(openAIChannels.responsesCompact, {
13846
14785
  name: "openai.responses.compact",
13847
14786
  type: "llm" /* LLM */,
13848
- extractInput: ([params]) => {
13849
- const { input, ...metadata } = params;
13850
- return {
13851
- input: processInputAttachments(input),
13852
- metadata: { ...metadata, provider: "openai" }
13853
- };
13854
- },
14787
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13855
14788
  extractOutput: (result) => {
13856
14789
  return processImagesInOutput(result?.output);
13857
14790
  },
13858
- extractMetadata: (result) => {
13859
- if (!result) {
13860
- return void 0;
13861
- }
13862
- const { output: _output, usage: _usage, ...metadata } = result;
13863
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13864
- },
14791
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13865
14792
  extractMetrics: (result, startTime, endEvent) => {
13866
14793
  const metrics = withCachedMetric(
13867
14794
  parseMetricsFromUsage(result?.usage),
@@ -13917,35 +14844,6 @@ function withCachedMetric(metrics, result, endEvent) {
13917
14844
  cached
13918
14845
  };
13919
14846
  }
13920
- function processImagesInOutput(output) {
13921
- if (Array.isArray(output)) {
13922
- return output.map(processImagesInOutput);
13923
- }
13924
- if (isObject(output)) {
13925
- if (output.type === "image_generation_call" && output.result && typeof output.result === "string") {
13926
- const fileExtension = output.output_format || "png";
13927
- const contentType = `image/${fileExtension}`;
13928
- const baseFilename = output.revised_prompt && typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
13929
- const filename = `${baseFilename}.${fileExtension}`;
13930
- const binaryString = atob(output.result);
13931
- const bytes = new Uint8Array(binaryString.length);
13932
- for (let i = 0; i < binaryString.length; i++) {
13933
- bytes[i] = binaryString.charCodeAt(i);
13934
- }
13935
- const blob = new Blob([bytes], { type: contentType });
13936
- const attachment = new Attachment({
13937
- data: blob,
13938
- filename,
13939
- contentType
13940
- });
13941
- return {
13942
- ...output,
13943
- result: attachment
13944
- };
13945
- }
13946
- }
13947
- return output;
13948
- }
13949
14847
  function mergeLogprobTokens(existing, incoming) {
13950
14848
  if (incoming === void 0) {
13951
14849
  return existing;
@@ -13976,13 +14874,33 @@ function aggregateChatLogprobs(existing, incoming) {
13976
14874
  }
13977
14875
  return aggregated;
13978
14876
  }
14877
+ function createAggregatedChatChoice(index) {
14878
+ return {
14879
+ index,
14880
+ role: void 0,
14881
+ content: void 0,
14882
+ refusal: void 0,
14883
+ toolCallsByIndex: /* @__PURE__ */ new Map(),
14884
+ logprobs: void 0,
14885
+ finish_reason: void 0
14886
+ };
14887
+ }
14888
+ function toChatChoice(choice) {
14889
+ const toolCalls2 = Array.from(choice.toolCallsByIndex.entries()).sort(([left], [right]) => left - right).map(([, toolCall]) => toolCall);
14890
+ return {
14891
+ index: choice.index,
14892
+ message: {
14893
+ role: choice.role,
14894
+ content: choice.content,
14895
+ ...choice.refusal !== void 0 ? { refusal: choice.refusal } : {},
14896
+ tool_calls: toolCalls2.length > 0 ? toolCalls2 : void 0
14897
+ },
14898
+ logprobs: choice.logprobs ?? null,
14899
+ finish_reason: choice.finish_reason
14900
+ };
14901
+ }
13979
14902
  function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
13980
- let role = void 0;
13981
- let content = void 0;
13982
- let refusal = void 0;
13983
- let tool_calls = void 0;
13984
- let logprobs = void 0;
13985
- let finish_reason = void 0;
14903
+ const choicesByIndex = /* @__PURE__ */ new Map();
13986
14904
  let metrics = {};
13987
14905
  for (const chunk of chunks) {
13988
14906
  if (chunk.usage) {
@@ -13991,62 +14909,75 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
13991
14909
  ...parseMetricsFromUsage(chunk.usage)
13992
14910
  };
13993
14911
  }
13994
- const choice = chunk.choices?.[0];
13995
- if (!choice) {
14912
+ const choices = chunk.choices;
14913
+ if (!choices?.length) {
13996
14914
  continue;
13997
14915
  }
13998
- if (choice.finish_reason) {
13999
- finish_reason = choice.finish_reason;
14000
- }
14001
- logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
14002
- const delta = choice.delta;
14003
- if (!delta) {
14004
- continue;
14005
- }
14006
- if (delta.finish_reason) {
14007
- finish_reason = delta.finish_reason;
14008
- }
14009
- if (!role && delta.role) {
14010
- role = delta.role;
14011
- }
14012
- if (delta.content) {
14013
- content = (content || "") + delta.content;
14014
- }
14015
- if (delta.refusal) {
14016
- refusal = (refusal || "") + delta.refusal;
14017
- }
14018
- if (delta.tool_calls) {
14019
- const toolDelta = delta.tool_calls[0];
14020
- if (!tool_calls || toolDelta.id && tool_calls[tool_calls.length - 1].id !== toolDelta.id) {
14021
- tool_calls = [
14022
- ...tool_calls || [],
14023
- {
14024
- id: toolDelta.id,
14025
- type: toolDelta.type,
14026
- function: toolDelta.function
14916
+ for (const choice of choices) {
14917
+ const choiceIndex = choice.index;
14918
+ let aggregatedChoice = choicesByIndex.get(choiceIndex);
14919
+ if (!aggregatedChoice) {
14920
+ aggregatedChoice = createAggregatedChatChoice(choiceIndex);
14921
+ choicesByIndex.set(choiceIndex, aggregatedChoice);
14922
+ }
14923
+ if (choice.finish_reason) {
14924
+ aggregatedChoice.finish_reason = choice.finish_reason;
14925
+ }
14926
+ aggregatedChoice.logprobs = aggregateChatLogprobs(
14927
+ aggregatedChoice.logprobs,
14928
+ choice.logprobs
14929
+ );
14930
+ const delta = choice.delta;
14931
+ if (!delta) {
14932
+ continue;
14933
+ }
14934
+ if (delta.finish_reason) {
14935
+ aggregatedChoice.finish_reason = delta.finish_reason;
14936
+ }
14937
+ if (!aggregatedChoice.role && delta.role) {
14938
+ aggregatedChoice.role = delta.role;
14939
+ }
14940
+ if (delta.content) {
14941
+ aggregatedChoice.content = (aggregatedChoice.content || "") + delta.content;
14942
+ }
14943
+ if (delta.refusal) {
14944
+ aggregatedChoice.refusal = (aggregatedChoice.refusal || "") + delta.refusal;
14945
+ }
14946
+ if (delta.tool_calls) {
14947
+ for (const toolDelta of delta.tool_calls) {
14948
+ let aggregatedToolCall = aggregatedChoice.toolCallsByIndex.get(
14949
+ toolDelta.index
14950
+ );
14951
+ if (!aggregatedToolCall) {
14952
+ aggregatedToolCall = {
14953
+ function: { arguments: "" }
14954
+ };
14955
+ aggregatedChoice.toolCallsByIndex.set(
14956
+ toolDelta.index,
14957
+ aggregatedToolCall
14958
+ );
14027
14959
  }
14028
- ];
14029
- } else {
14030
- tool_calls[tool_calls.length - 1].function.arguments += toolDelta.function.arguments;
14960
+ if (toolDelta.id !== void 0) {
14961
+ aggregatedToolCall.id = toolDelta.id;
14962
+ }
14963
+ if (toolDelta.type !== void 0) {
14964
+ aggregatedToolCall.type = toolDelta.type;
14965
+ }
14966
+ if (toolDelta.function?.name !== void 0) {
14967
+ aggregatedToolCall.function.name = toolDelta.function.name;
14968
+ }
14969
+ if (toolDelta.function?.arguments !== void 0) {
14970
+ aggregatedToolCall.function.arguments += toolDelta.function.arguments;
14971
+ }
14972
+ }
14031
14973
  }
14032
14974
  }
14033
14975
  }
14034
14976
  metrics = withCachedMetric(metrics, streamResult, endEvent);
14977
+ const output = Array.from(choicesByIndex.values()).sort((left, right) => left.index - right.index).map(toChatChoice);
14035
14978
  return {
14036
14979
  metrics,
14037
- output: [
14038
- {
14039
- index: 0,
14040
- message: {
14041
- role,
14042
- content,
14043
- ...refusal !== void 0 ? { refusal } : {},
14044
- tool_calls
14045
- },
14046
- logprobs: logprobs ?? null,
14047
- finish_reason
14048
- }
14049
- ]
14980
+ output: output.length > 0 ? output : [toChatChoice(createAggregatedChatChoice(0))]
14050
14981
  };
14051
14982
  }
14052
14983
  function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
@@ -15382,6 +16313,12 @@ function parseMetricsFromUsage2(usage) {
15382
16313
  }
15383
16314
  }
15384
16315
  }
16316
+ if (isObject(usage.output_tokens_details)) {
16317
+ const thinkingTokens = usage.output_tokens_details.thinking_tokens;
16318
+ if (typeof thinkingTokens === "number") {
16319
+ metrics.completion_reasoning_tokens = thinkingTokens;
16320
+ }
16321
+ }
15385
16322
  if (isObject(usage.server_tool_use)) {
15386
16323
  for (const [name, value] of Object.entries(usage.server_tool_use)) {
15387
16324
  if (typeof value === "number") {
@@ -16338,7 +17275,6 @@ function endHarnessTurn(parent) {
16338
17275
  function braintrustAISDKTelemetry() {
16339
17276
  const operations = /* @__PURE__ */ new Map();
16340
17277
  const operationKeysByCallId = /* @__PURE__ */ new Map();
16341
- const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
16342
17278
  const modelSpans = /* @__PURE__ */ new Map();
16343
17279
  const objectSpans = /* @__PURE__ */ new Map();
16344
17280
  const embedSpans = /* @__PURE__ */ new Map();
@@ -16381,9 +17317,6 @@ function braintrustAISDKTelemetry() {
16381
17317
  return;
16382
17318
  }
16383
17319
  operations.delete(operationKey);
16384
- if (workflowOperationKeyStore.getStore() === operationKey) {
16385
- workflowOperationKeyStore.enterWith(void 0);
16386
- }
16387
17320
  const keys = operationKeysByCallId.get(state.callId);
16388
17321
  if (!keys) {
16389
17322
  return;
@@ -16431,14 +17364,7 @@ function braintrustAISDKTelemetry() {
16431
17364
  return key;
16432
17365
  }
16433
17366
  }
16434
- const workflowOperationKey = workflowOperationKeyStore.getStore();
16435
- if (workflowOperationKey && keys.includes(workflowOperationKey)) {
16436
- return workflowOperationKey;
16437
- }
16438
- if (callId === "workflow-agent") {
16439
- return void 0;
16440
- }
16441
- return mode === "finish" ? keys[0] : keys[keys.length - 1];
17367
+ return callId === "workflow-agent" || mode === "active" ? keys[keys.length - 1] : keys[0];
16442
17368
  };
16443
17369
  const operationKeyFromEvent = (event, mode = "active") => {
16444
17370
  const explicit = explicitOperationKey(event);
@@ -16452,17 +17378,13 @@ function braintrustAISDKTelemetry() {
16452
17378
  if (operationKey) {
16453
17379
  return operationKey;
16454
17380
  }
16455
- const workflowOperationKey2 = workflowOperationKeyStore.getStore();
16456
- if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
16457
- return workflowOperationKey2;
17381
+ const workflowAgentKeys2 = operationKeysByCallId.get("workflow-agent");
17382
+ if (workflowAgentKeys2?.length) {
17383
+ return workflowAgentKeys2[workflowAgentKeys2.length - 1];
16458
17384
  }
16459
17385
  return callId === "workflow-agent" ? void 0 : callId;
16460
17386
  }
16461
17387
  }
16462
- const workflowOperationKey = workflowOperationKeyStore.getStore();
16463
- if (workflowOperationKey && operations.has(workflowOperationKey)) {
16464
- return workflowOperationKey;
16465
- }
16466
17388
  const wrapperSpan = currentWorkflowAgentWrapperSpan();
16467
17389
  if (wrapperSpan?.spanId) {
16468
17390
  for (const [operationKey, state] of operations) {
@@ -16472,8 +17394,8 @@ function braintrustAISDKTelemetry() {
16472
17394
  }
16473
17395
  }
16474
17396
  const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
16475
- if (workflowAgentKeys?.length === 1) {
16476
- return workflowAgentKeys[0];
17397
+ if (workflowAgentKeys?.length) {
17398
+ return workflowAgentKeys[workflowAgentKeys.length - 1];
16477
17399
  }
16478
17400
  if (operations.size === 1) {
16479
17401
  return operations.keys().next().value;
@@ -16676,9 +17598,6 @@ function braintrustAISDKTelemetry() {
16676
17598
  if (!ownsSpan) {
16677
17599
  return;
16678
17600
  }
16679
- if (workflowAgent) {
16680
- workflowOperationKeyStore.enterWith(operationKey);
16681
- }
16682
17601
  let metadata = metadataFromEvent(event);
16683
17602
  const logPayload = { metadata };
16684
17603
  const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
@@ -17150,6 +18069,10 @@ var aiSDKChannels = defineChannels(
17150
18069
  channelName: "generateText",
17151
18070
  kind: "async"
17152
18071
  }),
18072
+ generateImage: channel({
18073
+ channelName: "generateImage",
18074
+ kind: "async"
18075
+ }),
17153
18076
  streamText: channel({
17154
18077
  channelName: "streamText",
17155
18078
  kind: "async"
@@ -17337,7 +18260,7 @@ var AISDKPlugin = class extends BasePlugin {
17337
18260
  }
17338
18261
  subscribeToAISDK() {
17339
18262
  const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
17340
- this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
18263
+ this.unsubscribers.push(interceptAISDKV7TelemetryDispatcher());
17341
18264
  this.unsubscribers.push(subscribeToHarnessAgentCreateSession());
17342
18265
  this.unsubscribers.push(
17343
18266
  subscribeToHarnessContinuation(
@@ -17365,6 +18288,18 @@ var AISDKPlugin = class extends BasePlugin {
17365
18288
  aggregateChunks: aggregateAISDKChunks
17366
18289
  })
17367
18290
  );
18291
+ this.unsubscribers.push(
18292
+ traceAsyncChannel(aiSDKChannels.generateImage, {
18293
+ name: "generateImage",
18294
+ type: "llm" /* LLM */,
18295
+ extractInput: ([params], event) => prepareAISDKGenerateImageInput(params, event.self),
18296
+ extractOutput: (result, endEvent) => processAISDKGenerateImageOutput(
18297
+ result,
18298
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
18299
+ ),
18300
+ extractMetrics: (result) => extractTokenMetrics(result)
18301
+ })
18302
+ );
17368
18303
  this.unsubscribers.push(
17369
18304
  traceStreamingChannel(aiSDKChannels.streamText, {
17370
18305
  name: "streamText",
@@ -17854,26 +18789,29 @@ function subscribeToHarnessContinuation(continuationChannel, defaultDenyOutputPa
17854
18789
  channel2.unsubscribe(handlers);
17855
18790
  };
17856
18791
  }
17857
- function subscribeToAISDKV7TelemetryDispatcher() {
17858
- const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
18792
+ function interceptAISDKV7TelemetryDispatcher() {
17859
18793
  const telemetry = braintrustAISDKTelemetry();
17860
- const handlers = {
17861
- end: (event) => {
17862
- const telemetryOptions = event.arguments?.[0]?.telemetry;
17863
- if (telemetryOptions?.isEnabled === false) {
17864
- return;
18794
+ return aiSDKChannels.v7CreateTelemetryDispatcher.intercept(
18795
+ (target, thisArg, args) => {
18796
+ const dispatcher = Reflect.apply(target, thisArg, args);
18797
+ const telemetryOptions = args[0]?.telemetry;
18798
+ if (telemetryOptions?.isEnabled !== false) {
18799
+ try {
18800
+ patchAISDKV7TelemetryDispatcher(
18801
+ dispatcher,
18802
+ telemetry,
18803
+ telemetryOptions
18804
+ );
18805
+ } catch (error) {
18806
+ debugLogger.error(
18807
+ "Error instrumenting AI SDK v7 telemetry dispatcher:",
18808
+ error
18809
+ );
18810
+ }
17865
18811
  }
17866
- patchAISDKV7TelemetryDispatcher(
17867
- event.result,
17868
- telemetry,
17869
- telemetryOptions
17870
- );
18812
+ return dispatcher;
17871
18813
  }
17872
- };
17873
- channel2.subscribe(handlers);
17874
- return () => {
17875
- channel2.unsubscribe(handlers);
17876
- };
18814
+ );
17877
18815
  }
17878
18816
  function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
17879
18817
  if (!isObject(dispatcher)) {
@@ -18198,16 +19136,10 @@ var convertImageToAttachment = (image, explicitMimeType) => {
18198
19136
  }
18199
19137
  }
18200
19138
  if (explicitMimeType) {
18201
- if (image instanceof Uint8Array) {
18202
- return new Attachment({
18203
- data: new Blob([image], { type: explicitMimeType }),
18204
- filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
18205
- contentType: explicitMimeType
18206
- });
18207
- }
18208
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
19139
+ const blob = convertDataToBlob(image, explicitMimeType);
19140
+ if (blob) {
18209
19141
  return new Attachment({
18210
- data: new Blob([image], { type: explicitMimeType }),
19142
+ data: blob,
18211
19143
  filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
18212
19144
  contentType: explicitMimeType
18213
19145
  });
@@ -18261,6 +19193,25 @@ var convertDataToAttachment = (data, mimeType, filename) => {
18261
19193
  function processAISDKCallInput(params) {
18262
19194
  return processInputAttachmentsSync(params);
18263
19195
  }
19196
+ function processAISDKGenerateImageInput(params) {
19197
+ const prompt = params.prompt;
19198
+ if (!isObject(prompt) || Array.isArray(prompt)) {
19199
+ return processAISDKCallInput(params);
19200
+ }
19201
+ const processedPrompt = { ...prompt };
19202
+ if (Array.isArray(prompt.images)) {
19203
+ processedPrompt.images = prompt.images.map(
19204
+ (image) => convertImageToAttachment(image, "image/png") ?? image
19205
+ );
19206
+ }
19207
+ if (prompt.mask !== void 0) {
19208
+ processedPrompt.mask = convertImageToAttachment(prompt.mask, "image/png") ?? prompt.mask;
19209
+ }
19210
+ return processAISDKCallInput({
19211
+ ...params,
19212
+ prompt: processedPrompt
19213
+ });
19214
+ }
18264
19215
  function processAISDKWorkflowAgentCallInput(params) {
18265
19216
  const processed = processAISDKCallInput(params);
18266
19217
  return {
@@ -18399,6 +19350,12 @@ function prepareAISDKEmbedInput(params, self) {
18399
19350
  metadata: extractMetadataFromEmbedParams(params, self)
18400
19351
  };
18401
19352
  }
19353
+ function prepareAISDKGenerateImageInput(params, self) {
19354
+ return {
19355
+ input: processAISDKGenerateImageInput(params).input,
19356
+ metadata: extractMetadataFromCallParams(params, self)
19357
+ };
19358
+ }
18402
19359
  function prepareAISDKRerankInput(params, self) {
18403
19360
  const { documents, query } = params;
18404
19361
  return {
@@ -19774,6 +20731,57 @@ function processAISDKOutput(output, denyOutputPaths) {
19774
20731
  }
19775
20732
  return normalizeAISDKLoggedOutput(sanitized);
19776
20733
  }
20734
+ function processAISDKGenerateImageOutput(output, denyOutputPaths) {
20735
+ if (!output || typeof output !== "object") {
20736
+ return output;
20737
+ }
20738
+ const summarized = {};
20739
+ for (const field of [
20740
+ "usage",
20741
+ "warnings",
20742
+ "providerMetadata",
20743
+ "experimental_providerMetadata",
20744
+ "responses"
20745
+ ]) {
20746
+ const value = safeSerializableFieldRead(output, field);
20747
+ if (value !== void 0 && isSerializableOutputValue(value)) {
20748
+ summarized[field] = value;
20749
+ }
20750
+ }
20751
+ const images = safeSerializableFieldRead(output, "images");
20752
+ const image = safeSerializableFieldRead(output, "image");
20753
+ const generatedFiles = Array.isArray(images) && images.length > 0 ? images : image !== void 0 ? [image] : [];
20754
+ const loggedOutput = normalizeAISDKLoggedOutput(
20755
+ omit(summarized, denyOutputPaths)
20756
+ );
20757
+ if (generatedFiles.length > 0) {
20758
+ loggedOutput.images = generatedFiles.map(
20759
+ (file, index) => convertAISDKGeneratedFileToAttachment(file, index)
20760
+ );
20761
+ }
20762
+ return loggedOutput;
20763
+ }
20764
+ function convertAISDKGeneratedFileToAttachment(file, index) {
20765
+ if (!file || typeof file !== "object") {
20766
+ return file;
20767
+ }
20768
+ const generatedFile = file;
20769
+ const generatedMediaType = safeSerializableFieldRead(
20770
+ generatedFile,
20771
+ "mediaType"
20772
+ );
20773
+ const mediaType = typeof generatedMediaType === "string" ? generatedMediaType : "application/octet-stream";
20774
+ const data = safeSerializableFieldRead(generatedFile, "base64") ?? safeSerializableFieldRead(generatedFile, "uint8Array");
20775
+ const blob = convertDataToBlob(data, mediaType);
20776
+ if (blob) {
20777
+ return new Attachment({
20778
+ data: blob,
20779
+ filename: `generated_image_${index}.${getExtensionFromMediaType(mediaType)}`,
20780
+ contentType: mediaType
20781
+ });
20782
+ }
20783
+ return file;
20784
+ }
19777
20785
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
19778
20786
  if (!output || typeof output !== "object") {
19779
20787
  return output;
@@ -20274,118 +21282,22 @@ var claudeAgentSDKChannels = defineChannels(
20274
21282
  var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
20275
21283
 
20276
21284
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
20277
- var LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED = /* @__PURE__ */ Symbol.for(
20278
- "braintrust.claude_agent_sdk.local_tool_context_async_iterator_patched"
20279
- );
20280
- function createLocalToolContextStore() {
20281
- const maybeIsoWithAsyncLocalStorage = isomorph_default;
20282
- if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
20283
- return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
20284
- }
20285
- let currentStore;
20286
- return {
20287
- enterWith(store) {
20288
- currentStore = store;
20289
- },
20290
- getStore() {
20291
- return currentStore;
20292
- },
20293
- run(store, callback) {
20294
- const previousStore = currentStore;
20295
- currentStore = store;
20296
- try {
20297
- return callback();
20298
- } finally {
20299
- currentStore = previousStore;
20300
- }
20301
- }
20302
- };
20303
- }
20304
- var localToolContextStore = createLocalToolContextStore();
20305
- var fallbackLocalToolParentResolver;
20306
- function createClaudeLocalToolContext() {
20307
- return {};
20308
- }
20309
- function runWithClaudeLocalToolContext(callback, context) {
20310
- return localToolContextStore.run(
20311
- context ?? createClaudeLocalToolContext(),
20312
- callback
20313
- );
21285
+ var localToolContextStore = isomorph_default.newAsyncLocalStorage();
21286
+ var localToolParentResolversByToolUseId = /* @__PURE__ */ new Map();
21287
+ function runWithClaudeLocalToolContext(callback, resolver) {
21288
+ return localToolContextStore.run(resolver, callback);
20314
21289
  }
20315
- function ensureClaudeLocalToolContext() {
20316
- const existing = localToolContextStore.getStore();
20317
- if (existing) {
20318
- return existing;
20319
- }
20320
- const created = {};
20321
- localToolContextStore.enterWith(created);
20322
- return created;
21290
+ function registerClaudeLocalToolParentResolver(toolUseId, resolver) {
21291
+ localToolParentResolversByToolUseId.set(toolUseId, resolver);
20323
21292
  }
20324
- function setClaudeLocalToolParentResolver(resolver) {
20325
- fallbackLocalToolParentResolver = resolver;
20326
- const context = ensureClaudeLocalToolContext();
20327
- if (!context) {
20328
- return;
21293
+ function getClaudeLocalToolParentResolver(toolUseId) {
21294
+ const currentResolver = localToolContextStore.getStore();
21295
+ if (!toolUseId) {
21296
+ return currentResolver;
20329
21297
  }
20330
- context.resolveLocalToolParent = resolver;
20331
- }
20332
- function getClaudeLocalToolParentResolver() {
20333
- return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
20334
- }
20335
- function isAsyncIterable3(value) {
20336
- return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
20337
- }
20338
- function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
20339
- if (!isAsyncIterable3(result) || Object.isFrozen(result) || Object.isSealed(result)) {
20340
- return result;
20341
- }
20342
- const stream = result;
20343
- const originalAsyncIterator = stream[Symbol.asyncIterator];
20344
- if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
20345
- return result;
20346
- }
20347
- const patchedAsyncIterator = function() {
20348
- return runWithClaudeLocalToolContext(() => {
20349
- const iterator = Reflect.apply(originalAsyncIterator, this, []);
20350
- if (!iterator || typeof iterator !== "object") {
20351
- return iterator;
20352
- }
20353
- const patchMethod = (methodName) => {
20354
- const originalMethod = Reflect.get(iterator, methodName);
20355
- if (typeof originalMethod !== "function") {
20356
- return;
20357
- }
20358
- Reflect.set(
20359
- iterator,
20360
- methodName,
20361
- (...args) => runWithClaudeLocalToolContext(
20362
- () => Reflect.apply(
20363
- originalMethod,
20364
- iterator,
20365
- args
20366
- ),
20367
- localToolContext
20368
- )
20369
- );
20370
- };
20371
- patchMethod("next");
20372
- patchMethod("return");
20373
- patchMethod("throw");
20374
- return iterator;
20375
- }, localToolContext);
20376
- };
20377
- Object.defineProperty(
20378
- patchedAsyncIterator,
20379
- LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
20380
- {
20381
- configurable: false,
20382
- enumerable: false,
20383
- value: true,
20384
- writable: false
20385
- }
20386
- );
20387
- Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
20388
- return result;
21298
+ const registeredResolver = localToolParentResolversByToolUseId.get(toolUseId);
21299
+ localToolParentResolversByToolUseId.delete(toolUseId);
21300
+ return currentResolver ?? registeredResolver;
20389
21301
  }
20390
21302
 
20391
21303
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
@@ -20411,7 +21323,7 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
20411
21323
  const metadata = getMetadata();
20412
21324
  const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
20413
21325
  const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
20414
- const localToolParentResolver = getClaudeLocalToolParentResolver();
21326
+ const localToolParentResolver = getClaudeLocalToolParentResolver(toolUseId);
20415
21327
  const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
20416
21328
  const runWithResolvedParent = async () => {
20417
21329
  const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
@@ -20938,6 +21850,7 @@ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToP
20938
21850
  }
20939
21851
  }
20940
21852
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
21853
+ registerClaudeLocalToolParentResolver(toolUseID, resolveParentSpan);
20941
21854
  return {};
20942
21855
  }
20943
21856
  const parsed = parseToolName(input.tool_name);
@@ -21648,7 +22561,7 @@ async function finalizeQuerySpan(state) {
21648
22561
  }
21649
22562
  var ClaudeAgentSDKPlugin = class extends BasePlugin {
21650
22563
  onEnable() {
21651
- this.subscribeToQuery();
22564
+ this.interceptQuery();
21652
22565
  }
21653
22566
  onDisable() {
21654
22567
  for (const unsubscribe of this.unsubscribers) {
@@ -21656,211 +22569,218 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
21656
22569
  }
21657
22570
  this.unsubscribers = [];
21658
22571
  }
21659
- subscribeToQuery() {
21660
- const channel2 = claudeAgentSDKChannels.query.tracingChannel();
21661
- const spans = /* @__PURE__ */ new WeakMap();
21662
- const handlers = {
21663
- start: (event) => {
21664
- const params = event.arguments[0] ?? {};
21665
- const originalPrompt = params.prompt;
21666
- const options = params.options ?? {};
21667
- const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
21668
- let promptStarted = false;
21669
- let capturedPromptMessages;
21670
- let resolvePromptDone;
21671
- const promptDone = new Promise((resolve) => {
21672
- resolvePromptDone = resolve;
21673
- });
21674
- if (promptIsAsyncIterable) {
21675
- capturedPromptMessages = [];
21676
- const promptStream = originalPrompt;
21677
- params.prompt = (async function* () {
21678
- promptStarted = true;
21679
- try {
21680
- for await (const message of promptStream) {
21681
- capturedPromptMessages.push(message);
21682
- yield message;
21683
- }
21684
- } finally {
21685
- resolvePromptDone?.();
22572
+ interceptQuery() {
22573
+ const startQuery = (params) => {
22574
+ const originalPrompt = params.prompt;
22575
+ const options = params.options ?? {};
22576
+ const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
22577
+ let promptStarted = false;
22578
+ let capturedPromptMessages;
22579
+ let resolvePromptDone;
22580
+ const promptDone = new Promise((resolve) => {
22581
+ resolvePromptDone = resolve;
22582
+ });
22583
+ if (promptIsAsyncIterable) {
22584
+ capturedPromptMessages = [];
22585
+ const promptStream = originalPrompt;
22586
+ params.prompt = (async function* () {
22587
+ promptStarted = true;
22588
+ try {
22589
+ for await (const message of promptStream) {
22590
+ capturedPromptMessages.push(message);
22591
+ yield message;
21686
22592
  }
21687
- })();
21688
- }
21689
- const span = startSpan(
21690
- withSpanInstrumentationName(
21691
- {
21692
- name: "Claude Agent",
21693
- spanAttributes: {
21694
- type: "task" /* TASK */
21695
- }
21696
- },
21697
- INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
21698
- )
21699
- );
21700
- const startTime = getCurrentUnixTimestamp();
21701
- try {
21702
- span.log({
21703
- input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
21704
- metadata: filterSerializableOptions(options)
21705
- });
21706
- } catch (error) {
21707
- console.error("Error extracting input for Claude Agent SDK:", error);
21708
- }
21709
- const activeToolSpans = /* @__PURE__ */ new Map();
21710
- const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
21711
- const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
21712
- const subAgentSpans = /* @__PURE__ */ new Map();
21713
- const endedSubAgentSpans = /* @__PURE__ */ new Set();
21714
- const toolUseToParent = /* @__PURE__ */ new Map();
21715
- const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
21716
- const latestRootLlmParentRef = {
21717
- value: void 0
21718
- };
21719
- const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
21720
- const taskIdToToolUseId = /* @__PURE__ */ new Map();
21721
- const promptMessagesByParentKey = /* @__PURE__ */ new Map();
21722
- const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
21723
- const localToolContext = createClaudeLocalToolContext();
21724
- const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
21725
- const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
21726
- const resolveToolUseParentSpan = async (toolUseID, context) => {
21727
- const trackedParentToolUseId = toolUseToParent.get(toolUseID);
21728
- const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
21729
- const parentKey = llmParentKey(parentToolUseId);
21730
- const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
21731
- const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
21732
- if (!activeLlmSpan && !latestLlmParent) {
21733
- await ensureActiveLlmSpanForParentToolUse(
21734
- span,
21735
- activeLlmSpansByParentToolUse,
21736
- subAgentDetailsByToolUseId,
21737
- activeToolSpans,
21738
- subAgentSpans,
21739
- parentToolUseId,
21740
- getCurrentUnixTimestamp()
21741
- );
21742
- }
21743
- if (parentToolUseId) {
21744
- const subAgentSpan = await ensureSubAgentSpan(
21745
- subAgentDetailsByToolUseId,
21746
- span,
21747
- activeToolSpans,
21748
- subAgentSpans,
21749
- parentToolUseId
21750
- );
21751
- return subAgentSpan.export();
22593
+ } finally {
22594
+ resolvePromptDone?.();
21752
22595
  }
21753
- return span.export();
21754
- };
21755
- localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
21756
- setClaudeLocalToolParentResolver(resolveToolUseParentSpan);
21757
- const optionsWithHooks = injectTracingHooks(
21758
- options,
21759
- resolveToolUseParentSpan,
21760
- taskIdToToolUseId,
21761
- toolUseToParent,
21762
- activeToolSpans,
21763
- localToolHookNames,
21764
- skipLocalToolHooks,
21765
- subAgentDetailsByToolUseId,
21766
- subAgentSpans,
21767
- endedSubAgentSpans
21768
- );
21769
- params.options = optionsWithHooks;
21770
- event.arguments[0] = params;
21771
- spans.set(event, {
21772
- activeLlmSpansByParentToolUse,
21773
- activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
21774
- activeToolSpans,
21775
- conversationHistoryByParentKey,
21776
- capturedPromptMessages,
21777
- currentMessageId: void 0,
21778
- currentMessageStartTime: startTime,
21779
- currentMessages: [],
21780
- endedSubAgentSpans,
21781
- finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
21782
- finalResults: [],
21783
- options: optionsWithHooks,
21784
- originalPrompt,
21785
- processing: Promise.resolve(),
21786
- promptDone,
21787
- promptMessagesByParentKey,
21788
- promptStarted: () => promptStarted,
21789
- promptSourcePriorityByParentKey,
21790
- span,
21791
- subAgentDetailsByToolUseId,
21792
- subAgentSpans,
21793
- taskIdToToolUseId,
21794
- latestLlmParentBySubAgentToolUse,
21795
- latestRootLlmParentRef,
21796
- toolUseToParent,
21797
- usageByMessageId: /* @__PURE__ */ new Map(),
21798
- localToolContext
22596
+ })();
22597
+ }
22598
+ const span = startSpan(
22599
+ withSpanInstrumentationName(
22600
+ {
22601
+ name: "Claude Agent",
22602
+ spanAttributes: {
22603
+ type: "task" /* TASK */
22604
+ }
22605
+ },
22606
+ INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
22607
+ )
22608
+ );
22609
+ const startTime = getCurrentUnixTimestamp();
22610
+ try {
22611
+ span.log({
22612
+ input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
22613
+ metadata: filterSerializableOptions(options)
21799
22614
  });
21800
- },
21801
- end: (event) => {
21802
- const state = spans.get(event);
21803
- if (!state) {
21804
- return;
21805
- }
21806
- const eventResult = bindClaudeLocalToolContextToAsyncIterable(
21807
- event.result,
21808
- state.localToolContext
21809
- );
21810
- if (eventResult === void 0) {
21811
- state.span.end();
21812
- spans.delete(event);
21813
- return;
21814
- }
21815
- if (isAsyncIterable(eventResult)) {
21816
- patchStreamIfNeeded(eventResult, {
21817
- onChunk: (message) => {
21818
- maybeTrackToolUseContext(state, message);
21819
- state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
21820
- console.error(
21821
- "Error processing Claude Agent SDK stream chunk:",
21822
- error
21823
- );
21824
- });
21825
- },
21826
- onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
21827
- spans.delete(event);
21828
- }),
21829
- onError: (error) => state.processing.then(() => {
21830
- state.span.log({
21831
- error: error.message
21832
- });
21833
- }).then(() => finalizeQuerySpan(state)).finally(() => {
21834
- spans.delete(event);
21835
- })
21836
- });
21837
- return;
21838
- }
21839
- try {
21840
- state.span.log({ output: eventResult });
21841
- } catch (error) {
21842
- console.error("Error extracting output for Claude Agent SDK:", error);
21843
- } finally {
21844
- state.span.end();
21845
- spans.delete(event);
22615
+ } catch (error) {
22616
+ console.error("Error extracting input for Claude Agent SDK:", error);
22617
+ }
22618
+ const activeToolSpans = /* @__PURE__ */ new Map();
22619
+ const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
22620
+ const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
22621
+ const subAgentSpans = /* @__PURE__ */ new Map();
22622
+ const endedSubAgentSpans = /* @__PURE__ */ new Set();
22623
+ const toolUseToParent = /* @__PURE__ */ new Map();
22624
+ const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
22625
+ const latestRootLlmParentRef = {
22626
+ value: void 0
22627
+ };
22628
+ const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
22629
+ const taskIdToToolUseId = /* @__PURE__ */ new Map();
22630
+ const promptMessagesByParentKey = /* @__PURE__ */ new Map();
22631
+ const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
22632
+ const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
22633
+ const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
22634
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
22635
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
22636
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
22637
+ const parentKey = llmParentKey(parentToolUseId);
22638
+ const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
22639
+ const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
22640
+ if (!activeLlmSpan && !latestLlmParent) {
22641
+ await ensureActiveLlmSpanForParentToolUse(
22642
+ span,
22643
+ activeLlmSpansByParentToolUse,
22644
+ subAgentDetailsByToolUseId,
22645
+ activeToolSpans,
22646
+ subAgentSpans,
22647
+ parentToolUseId,
22648
+ getCurrentUnixTimestamp()
22649
+ );
21846
22650
  }
21847
- },
21848
- error: (event) => {
21849
- const state = spans.get(event);
21850
- if (!state || !event.error) {
21851
- return;
22651
+ if (parentToolUseId) {
22652
+ const subAgentSpan = await ensureSubAgentSpan(
22653
+ subAgentDetailsByToolUseId,
22654
+ span,
22655
+ activeToolSpans,
22656
+ subAgentSpans,
22657
+ parentToolUseId
22658
+ );
22659
+ return subAgentSpan.export();
21852
22660
  }
21853
- state.span.log({
21854
- error: event.error.message
22661
+ return span.export();
22662
+ };
22663
+ const optionsWithHooks = injectTracingHooks(
22664
+ options,
22665
+ resolveToolUseParentSpan,
22666
+ taskIdToToolUseId,
22667
+ toolUseToParent,
22668
+ activeToolSpans,
22669
+ localToolHookNames,
22670
+ skipLocalToolHooks,
22671
+ subAgentDetailsByToolUseId,
22672
+ subAgentSpans,
22673
+ endedSubAgentSpans
22674
+ );
22675
+ params.options = optionsWithHooks;
22676
+ return {
22677
+ activeLlmSpansByParentToolUse,
22678
+ activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
22679
+ activeToolSpans,
22680
+ conversationHistoryByParentKey,
22681
+ capturedPromptMessages,
22682
+ currentMessageId: void 0,
22683
+ currentMessageStartTime: startTime,
22684
+ currentMessages: [],
22685
+ endedSubAgentSpans,
22686
+ finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
22687
+ finalResults: [],
22688
+ options: optionsWithHooks,
22689
+ originalPrompt,
22690
+ processing: Promise.resolve(),
22691
+ promptDone,
22692
+ promptMessagesByParentKey,
22693
+ promptStarted: () => promptStarted,
22694
+ promptSourcePriorityByParentKey,
22695
+ span,
22696
+ subAgentDetailsByToolUseId,
22697
+ subAgentSpans,
22698
+ taskIdToToolUseId,
22699
+ latestLlmParentBySubAgentToolUse,
22700
+ latestRootLlmParentRef,
22701
+ toolUseToParent,
22702
+ usageByMessageId: /* @__PURE__ */ new Map(),
22703
+ localToolParentResolver: resolveToolUseParentSpan
22704
+ };
22705
+ };
22706
+ const finishQuery = (state, result) => {
22707
+ if (isAsyncIterable(result)) {
22708
+ patchStreamIfNeeded(result, {
22709
+ aroundNext: (callback) => runWithClaudeLocalToolContext(
22710
+ callback,
22711
+ state.localToolParentResolver
22712
+ ),
22713
+ onChunk: (message) => {
22714
+ maybeTrackToolUseContext(state, message);
22715
+ state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
22716
+ console.error(
22717
+ "Error processing Claude Agent SDK stream chunk:",
22718
+ error
22719
+ );
22720
+ });
22721
+ },
22722
+ onComplete: () => state.processing.then(() => finalizeQuerySpan(state)),
22723
+ onError: (error) => state.processing.then(() => {
22724
+ state.span.log({ error: error.message });
22725
+ }).then(() => finalizeQuerySpan(state))
21855
22726
  });
22727
+ return;
22728
+ }
22729
+ try {
22730
+ state.span.log({ output: result });
22731
+ } catch (error) {
22732
+ console.error("Error extracting output for Claude Agent SDK:", error);
22733
+ } finally {
21856
22734
  state.span.end();
21857
- spans.delete(event);
21858
22735
  }
21859
22736
  };
21860
- channel2.subscribe(handlers);
21861
- this.unsubscribers.push(() => {
21862
- channel2.unsubscribe(handlers);
21863
- });
22737
+ this.unsubscribers.push(
22738
+ claudeAgentSDKChannels.query.intercept((target, thisArg, args) => {
22739
+ let state;
22740
+ try {
22741
+ args[0] ??= {};
22742
+ state = startQuery(args[0]);
22743
+ } catch (error) {
22744
+ debugLogger.error(
22745
+ "Error starting Claude Agent SDK instrumentation:",
22746
+ error
22747
+ );
22748
+ }
22749
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
22750
+ try {
22751
+ const result = state ? runWithClaudeLocalToolContext(
22752
+ invokeTarget,
22753
+ state.localToolParentResolver
22754
+ ) : invokeTarget();
22755
+ if (state) {
22756
+ try {
22757
+ finishQuery(state, result);
22758
+ } catch (error) {
22759
+ debugLogger.error(
22760
+ "Error finalizing Claude Agent SDK instrumentation:",
22761
+ error
22762
+ );
22763
+ }
22764
+ }
22765
+ return result;
22766
+ } catch (error) {
22767
+ if (state) {
22768
+ try {
22769
+ state.span.log({
22770
+ error: error instanceof Error ? error.message : String(error)
22771
+ });
22772
+ state.span.end();
22773
+ } catch (instrumentationError) {
22774
+ debugLogger.error(
22775
+ "Error handling Claude Agent SDK instrumentation failure:",
22776
+ instrumentationError
22777
+ );
22778
+ }
22779
+ }
22780
+ throw error;
22781
+ }
22782
+ })
22783
+ );
21864
22784
  }
21865
22785
  };
21866
22786
 
@@ -25974,7 +26894,7 @@ function patchOpenRouterCallModelResult(args) {
25974
26894
  span,
25975
26895
  () => originalMethod.apply(resultLike, args2)
25976
26896
  );
25977
- if (!isAsyncIterable4(stream)) {
26897
+ if (!isAsyncIterable3(stream)) {
25978
26898
  return stream;
25979
26899
  }
25980
26900
  return wrapAsyncIterableWithSpan({
@@ -26169,7 +27089,7 @@ function wrapAsyncIterableWithSpan(args) {
26169
27089
  }
26170
27090
  };
26171
27091
  }
26172
- function isAsyncIterable4(value) {
27092
+ function isAsyncIterable3(value) {
26173
27093
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
26174
27094
  }
26175
27095
  function normalizeError(error) {
@@ -27047,7 +27967,7 @@ function patchOpenRouterCallModelResult2(args) {
27047
27967
  span,
27048
27968
  () => originalMethod.apply(resultLike, args2)
27049
27969
  );
27050
- if (!isAsyncIterable5(stream)) {
27970
+ if (!isAsyncIterable4(stream)) {
27051
27971
  return stream;
27052
27972
  }
27053
27973
  return wrapAsyncIterableWithSpan2({
@@ -27242,7 +28162,7 @@ function wrapAsyncIterableWithSpan2(args) {
27242
28162
  }
27243
28163
  };
27244
28164
  }
27245
- function isAsyncIterable5(value) {
28165
+ function isAsyncIterable4(value) {
27246
28166
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
27247
28167
  }
27248
28168
  function normalizeError2(error) {
@@ -33234,12 +34154,14 @@ function getMetricsFromResponse(response) {
33234
34154
  continue;
33235
34155
  }
33236
34156
  const inputTokenDetails = usageMetadata.input_token_details;
34157
+ const outputTokenDetails = usageMetadata.output_token_details;
33237
34158
  return normalizeTokenMetrics({
33238
34159
  total_tokens: usageMetadata.total_tokens,
33239
34160
  prompt_tokens: usageMetadata.input_tokens,
33240
34161
  completion_tokens: usageMetadata.output_tokens,
33241
34162
  prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
33242
- prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
34163
+ prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
34164
+ completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
33243
34165
  });
33244
34166
  }
33245
34167
  const llmOutput = response.llmOutput || {};
@@ -33826,6 +34748,9 @@ var piCodingAgentChannels = defineChannels(
33826
34748
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
33827
34749
  var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
33828
34750
  var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
34751
+ var PI_TOOL_EXECUTE_WRAPPED = /* @__PURE__ */ Symbol.for(
34752
+ "braintrust.pi_coding_agent.tool_execute_wrapped"
34753
+ );
33829
34754
  var piPromptContextStore;
33830
34755
  var PiCodingAgentPlugin = class extends BasePlugin {
33831
34756
  activePromptStates = /* @__PURE__ */ new Set();
@@ -33906,6 +34831,7 @@ function startPiPromptRun(event, onFinalize) {
33906
34831
  return void 0;
33907
34832
  }
33908
34833
  installPiAgentInstrumentation(agent);
34834
+ wrapPiToolExecutors(agent.state?.tools);
33909
34835
  const metadata = {
33910
34836
  ...extractSessionMetadata(session),
33911
34837
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -33950,7 +34876,7 @@ function extractSession(event) {
33950
34876
  return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
33951
34877
  }
33952
34878
  function isPiAgent(value) {
33953
- return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
34879
+ return isObject(value) && (typeof value.streamFunction === "function" || typeof value.streamFn === "function") && typeof value.subscribe === "function";
33954
34880
  }
33955
34881
  function promptContextStore() {
33956
34882
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
@@ -33960,17 +34886,21 @@ function currentPiPromptState() {
33960
34886
  return promptContextStore().getStore();
33961
34887
  }
33962
34888
  function installPiAgentInstrumentation(agent) {
34889
+ const property = typeof agent.streamFunction === "function" ? "streamFunction" : "streamFn";
34890
+ const streamFunction = agent[property];
33963
34891
  const existing = piAgentPatchStates.get(agent);
33964
- if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
34892
+ if (streamFunction && (!existing || existing.property !== property || streamFunction !== existing.wrappedStreamFunction)) {
33965
34893
  const patchState = {
33966
- originalStreamFn: agent.streamFn,
33967
- wrappedStreamFn: agent.streamFn
34894
+ originalStreamFunction: streamFunction,
34895
+ property,
34896
+ wrappedStreamFunction: streamFunction
33968
34897
  };
33969
- patchState.wrappedStreamFn = makeInstrumentedStreamFn(
34898
+ patchState.wrappedStreamFunction = makeInstrumentedStreamFunction(
33970
34899
  agent,
33971
- patchState.originalStreamFn
34900
+ patchState.originalStreamFunction,
34901
+ property
33972
34902
  );
33973
- agent.streamFn = patchState.wrappedStreamFn;
34903
+ agent[property] = patchState.wrappedStreamFunction;
33974
34904
  piAgentPatchStates.set(agent, patchState);
33975
34905
  }
33976
34906
  if (piAgentEventSubscriptions.has(agent)) {
@@ -33995,14 +34925,21 @@ function installPiAgentInstrumentation(agent) {
33995
34925
  logInstrumentationError4("Pi Coding Agent event subscription", error);
33996
34926
  }
33997
34927
  }
33998
- function makeInstrumentedStreamFn(agent, originalStreamFn) {
33999
- return async function instrumentedPiStreamFn(model, context, options) {
34000
- const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
34928
+ function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
34929
+ return async function instrumentedPiStreamFunction(model, context, options) {
34930
+ const invokeOriginal = () => Reflect.apply(originalStreamFunction, this, [model, context, options]);
34001
34931
  const state = currentPiPromptState();
34002
34932
  if (!state || state.agent !== agent || state.finalized) {
34003
34933
  return invokeOriginal();
34004
34934
  }
34005
- const llmState = await startPiLlmSpan(state, model, context, options);
34935
+ wrapPiToolExecutors(context.tools);
34936
+ const llmState = await startPiLlmSpan(
34937
+ state,
34938
+ model,
34939
+ context,
34940
+ property,
34941
+ options
34942
+ );
34006
34943
  try {
34007
34944
  const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
34008
34945
  return patchAssistantMessageStream(stream, state, llmState);
@@ -34012,12 +34949,39 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
34012
34949
  }
34013
34950
  };
34014
34951
  }
34015
- async function startPiLlmSpan(state, model, context, options) {
34952
+ function wrapPiToolExecutors(tools) {
34953
+ if (!tools) {
34954
+ return;
34955
+ }
34956
+ for (const tool of tools) {
34957
+ try {
34958
+ const execute = tool.execute;
34959
+ if (typeof execute !== "function" || execute[PI_TOOL_EXECUTE_WRAPPED]) {
34960
+ continue;
34961
+ }
34962
+ const wrappedExecute = function(...args) {
34963
+ return runWithAutoInstrumentationAllowed(
34964
+ () => Reflect.apply(execute, this, args)
34965
+ );
34966
+ };
34967
+ Object.defineProperty(wrappedExecute, PI_TOOL_EXECUTE_WRAPPED, {
34968
+ configurable: false,
34969
+ enumerable: false,
34970
+ value: true,
34971
+ writable: false
34972
+ });
34973
+ tool.execute = wrappedExecute;
34974
+ } catch (error) {
34975
+ logInstrumentationError4("Pi Coding Agent tool wrapping", error);
34976
+ }
34977
+ }
34978
+ }
34979
+ async function startPiLlmSpan(state, model, context, property, options) {
34016
34980
  const metadata = {
34017
34981
  ...extractModelMetadata2(model),
34018
34982
  ...extractStreamOptionsMetadata(options),
34019
34983
  ...extractToolMetadata(context.tools),
34020
- "pi_coding_agent.operation": "agent.streamFn"
34984
+ "pi_coding_agent.operation": `agent.${property}`
34021
34985
  };
34022
34986
  const span = startSpan(
34023
34987
  withSpanInstrumentationName(
@@ -34183,35 +35147,26 @@ async function startPiToolSpan(state, event) {
34183
35147
  if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
34184
35148
  return;
34185
35149
  }
34186
- const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
34187
35150
  const metadata = {
34188
35151
  "gen_ai.tool.call.id": event.toolCallId,
34189
35152
  "gen_ai.tool.name": event.toolName,
34190
35153
  "pi_coding_agent.tool.name": event.toolName
34191
35154
  };
34192
- try {
34193
- const span = startSpan(
34194
- withSpanInstrumentationName(
34195
- {
34196
- event: {
34197
- input: event.args,
34198
- metadata
34199
- },
34200
- name: event.toolName || "tool",
34201
- parent: await state.span.export(),
34202
- spanAttributes: { type: "tool" /* TOOL */ }
35155
+ const span = startSpan(
35156
+ withSpanInstrumentationName(
35157
+ {
35158
+ event: {
35159
+ input: event.args,
35160
+ metadata
34203
35161
  },
34204
- INSTRUMENTATION_NAMES.PI_CODING_AGENT
34205
- )
34206
- );
34207
- state.activeToolSpans.set(event.toolCallId, {
34208
- restoreAutoInstrumentation,
34209
- span
34210
- });
34211
- } catch (error) {
34212
- restoreAutoInstrumentation();
34213
- throw error;
34214
- }
35162
+ name: event.toolName || "tool",
35163
+ parent: await state.span.export(),
35164
+ spanAttributes: { type: "tool" /* TOOL */ }
35165
+ },
35166
+ INSTRUMENTATION_NAMES.PI_CODING_AGENT
35167
+ )
35168
+ );
35169
+ state.activeToolSpans.set(event.toolCallId, { span });
34215
35170
  }
34216
35171
  function finishPiToolSpan(state, event) {
34217
35172
  const toolState = state.activeToolSpans.get(event.toolCallId);
@@ -34232,11 +35187,7 @@ function finishPiToolSpan(state, event) {
34232
35187
  output: event.result
34233
35188
  });
34234
35189
  } finally {
34235
- try {
34236
- toolState.span.end();
34237
- } finally {
34238
- toolState.restoreAutoInstrumentation?.();
34239
- }
35190
+ toolState.span.end();
34240
35191
  }
34241
35192
  }
34242
35193
  function finishPiPromptRun(state, error) {
@@ -34286,10 +35237,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
34286
35237
  ...cleanMetrics5(llmState.metrics),
34287
35238
  ...buildDurationMetrics3(llmState.startTime)
34288
35239
  };
34289
- const usageMetrics = extractUsageMetrics2(message?.usage);
34290
- if (Object.keys(usageMetrics).length > 0) {
35240
+ const usageMetrics2 = extractUsageMetrics2(message?.usage);
35241
+ if (Object.keys(usageMetrics2).length > 0) {
34291
35242
  promptState.collectedLlmUsageMetrics = true;
34292
- addMetrics(promptState.metrics, usageMetrics);
35243
+ addMetrics(promptState.metrics, usageMetrics2);
34293
35244
  }
34294
35245
  try {
34295
35246
  safeLog4(llmState.span, {
@@ -34307,14 +35258,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
34307
35258
  }
34308
35259
  function finishOpenToolSpans(state, error) {
34309
35260
  for (const [, toolState] of state.activeToolSpans) {
34310
- try {
34311
- safeLog4(toolState.span, {
34312
- error: error ? toLoggedError(error) : "Pi tool did not complete"
34313
- });
34314
- toolState.span.end();
34315
- } finally {
34316
- toolState.restoreAutoInstrumentation?.();
34317
- }
35261
+ safeLog4(toolState.span, {
35262
+ error: error ? toLoggedError(error) : "Pi tool did not complete"
35263
+ });
35264
+ toolState.span.end();
34318
35265
  }
34319
35266
  state.activeToolSpans.clear();
34320
35267
  }
@@ -34633,12 +35580,12 @@ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
34633
35580
  var StrandsAgentSDKPlugin = class extends BasePlugin {
34634
35581
  activeChildParents = /* @__PURE__ */ new WeakMap();
34635
35582
  onEnable() {
34636
- this.subscribeToAgentStream();
34637
- this.subscribeToMultiAgentStream(
35583
+ this.interceptAgentStream();
35584
+ this.interceptMultiAgentStream(
34638
35585
  strandsAgentSDKChannels.graphStream,
34639
35586
  "Graph.stream"
34640
35587
  );
34641
- this.subscribeToMultiAgentStream(
35588
+ this.interceptMultiAgentStream(
34642
35589
  strandsAgentSDKChannels.swarmStream,
34643
35590
  "Swarm.stream"
34644
35591
  );
@@ -34649,122 +35596,92 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
34649
35596
  }
34650
35597
  this.unsubscribers = [];
34651
35598
  }
34652
- subscribeToAgentStream() {
34653
- const channel2 = strandsAgentSDKChannels.agentStream.tracingChannel();
34654
- const states = /* @__PURE__ */ new WeakMap();
34655
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
34656
- const handlers = {
34657
- start: (event) => {
34658
- const state = startAgentStream(event, this.activeChildParents);
34659
- if (state) {
34660
- states.set(event, state);
34661
- }
34662
- },
34663
- end: (event) => {
34664
- const state = states.get(event);
34665
- if (!state) {
34666
- return;
34667
- }
34668
- const result = event.result;
34669
- if (isAsyncIterable(result)) {
34670
- patchStreamIfNeeded(result, {
34671
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
34672
- onChunk: (chunk) => handleAgentStreamEvent(state, chunk),
34673
- onComplete: () => {
34674
- finalizeAgentStream(state);
34675
- states.delete(event);
34676
- },
34677
- onError: (error) => {
34678
- finalizeAgentStream(state, error);
34679
- states.delete(event);
34680
- }
34681
- });
34682
- return;
34683
- }
34684
- finalizeAgentStream(state, void 0, result);
34685
- states.delete(event);
34686
- },
34687
- error: (event) => {
34688
- const state = states.get(event);
34689
- if (!state || !event.error) {
34690
- return;
34691
- }
34692
- finalizeAgentStream(state, event.error);
34693
- states.delete(event);
34694
- }
34695
- };
34696
- channel2.subscribe(handlers);
34697
- this.unsubscribers.push(() => {
34698
- unbindAutoInstrumentationSuppression?.();
34699
- channel2.unsubscribe(handlers);
34700
- });
35599
+ interceptAgentStream() {
35600
+ this.unsubscribers.push(
35601
+ strandsAgentSDKChannels.agentStream.intercept(
35602
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
35603
+ finalize: finalizeAgentStream,
35604
+ handleChunk: handleAgentStreamEvent,
35605
+ invoke: () => Reflect.apply(target, thisArg, args),
35606
+ name: "Strands Agent SDK",
35607
+ start: () => startAgentStream(
35608
+ args[0],
35609
+ extractAgent(additional.agent, thisArg),
35610
+ this.activeChildParents
35611
+ )
35612
+ })
35613
+ )
35614
+ );
34701
35615
  }
34702
- subscribeToMultiAgentStream(channel2, operation) {
34703
- const tracingChannel = channel2.tracingChannel();
34704
- const states = /* @__PURE__ */ new WeakMap();
34705
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(tracingChannel);
34706
- const handlers = {
34707
- start: (event) => {
34708
- const state = startMultiAgentStream(
34709
- event,
34710
- operation,
34711
- this.activeChildParents
34712
- );
34713
- if (state) {
34714
- states.set(event, state);
34715
- }
34716
- },
34717
- end: (event) => {
34718
- const state = states.get(event);
34719
- if (!state) {
34720
- return;
34721
- }
34722
- const result = event.result;
34723
- if (isAsyncIterable(result)) {
34724
- patchStreamIfNeeded(result, {
34725
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
34726
- onChunk: (chunk) => handleMultiAgentStreamEvent(
34727
- state,
34728
- chunk,
34729
- this.activeChildParents
34730
- ),
34731
- onComplete: () => {
34732
- finalizeMultiAgentStream(state, this.activeChildParents);
34733
- states.delete(event);
34734
- },
34735
- onError: (error) => {
34736
- finalizeMultiAgentStream(state, this.activeChildParents, error);
34737
- states.delete(event);
34738
- }
34739
- });
34740
- return;
34741
- }
34742
- finalizeMultiAgentStream(
34743
- state,
34744
- this.activeChildParents,
34745
- void 0,
34746
- result
35616
+ interceptMultiAgentStream(channel2, operation) {
35617
+ this.unsubscribers.push(
35618
+ channel2.intercept(
35619
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
35620
+ finalize: (state, error, output) => finalizeMultiAgentStream(
35621
+ state,
35622
+ this.activeChildParents,
35623
+ error,
35624
+ output
35625
+ ),
35626
+ handleChunk: (state, chunk) => handleMultiAgentStreamEvent(state, chunk, this.activeChildParents),
35627
+ invoke: () => Reflect.apply(target, thisArg, args),
35628
+ name: "Strands multi-agent",
35629
+ start: () => startMultiAgentStream(
35630
+ args[0],
35631
+ extractOrchestrator(additional.orchestrator, thisArg),
35632
+ operation,
35633
+ this.activeChildParents
35634
+ )
35635
+ })
35636
+ )
35637
+ );
35638
+ }
35639
+ };
35640
+ function instrumentStrandsStreamInvocation(options) {
35641
+ let state;
35642
+ try {
35643
+ state = options.start();
35644
+ } catch (error) {
35645
+ debugLogger.error(`Error starting ${options.name} instrumentation:`, error);
35646
+ }
35647
+ let result;
35648
+ try {
35649
+ result = runWithAutoInstrumentationSuppressed(options.invoke);
35650
+ } catch (error) {
35651
+ if (state) {
35652
+ try {
35653
+ options.finalize(state, error);
35654
+ } catch (instrumentationError) {
35655
+ debugLogger.error(
35656
+ `Error handling ${options.name} instrumentation failure:`,
35657
+ instrumentationError
34747
35658
  );
34748
- states.delete(event);
34749
- },
34750
- error: (event) => {
34751
- const state = states.get(event);
34752
- if (!state || !event.error) {
34753
- return;
34754
- }
34755
- finalizeMultiAgentStream(state, this.activeChildParents, event.error);
34756
- states.delete(event);
34757
35659
  }
34758
- };
34759
- tracingChannel.subscribe(handlers);
34760
- this.unsubscribers.push(() => {
34761
- unbindAutoInstrumentationSuppression?.();
34762
- tracingChannel.unsubscribe(handlers);
34763
- });
35660
+ }
35661
+ throw error;
34764
35662
  }
34765
- };
34766
- function startAgentStream(event, activeChildParents) {
34767
- const agent = extractAgent(event);
35663
+ if (state) {
35664
+ try {
35665
+ if (isAsyncIterable(result)) {
35666
+ patchStreamIfNeeded(result, {
35667
+ aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
35668
+ onChunk: (chunk) => options.handleChunk(state, chunk),
35669
+ onComplete: () => options.finalize(state),
35670
+ onError: (error) => options.finalize(state, error)
35671
+ });
35672
+ } else {
35673
+ options.finalize(state, void 0, result);
35674
+ }
35675
+ } catch (error) {
35676
+ debugLogger.error(
35677
+ `Error finalizing ${options.name} instrumentation:`,
35678
+ error
35679
+ );
35680
+ }
35681
+ }
35682
+ return result;
35683
+ }
35684
+ function startAgentStream(input, agent, activeChildParents) {
34768
35685
  const model = agent?.model;
34769
35686
  const metadata = {
34770
35687
  ...extractAgentMetadata2(agent),
@@ -34774,17 +35691,14 @@ function startAgentStream(event, activeChildParents) {
34774
35691
  };
34775
35692
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
34776
35693
  const attachmentCache = createStrandsAttachmentCache();
34777
- const input = processStrandsInputAttachments(
34778
- event.arguments[0],
34779
- attachmentCache
34780
- );
35694
+ const processedInput = processStrandsInputAttachments(input, attachmentCache);
34781
35695
  const span = parentSpan ? withCurrent(
34782
35696
  parentSpan,
34783
35697
  () => startSpan(
34784
35698
  withSpanInstrumentationName(
34785
35699
  {
34786
35700
  event: {
34787
- input,
35701
+ input: processedInput,
34788
35702
  metadata
34789
35703
  },
34790
35704
  name: formatAgentSpanName(agent),
@@ -34797,7 +35711,7 @@ function startAgentStream(event, activeChildParents) {
34797
35711
  withSpanInstrumentationName(
34798
35712
  {
34799
35713
  event: {
34800
- input,
35714
+ input: processedInput,
34801
35715
  metadata
34802
35716
  },
34803
35717
  name: formatAgentSpanName(agent),
@@ -34815,22 +35729,21 @@ function startAgentStream(event, activeChildParents) {
34815
35729
  startTime: getCurrentUnixTimestamp()
34816
35730
  };
34817
35731
  }
34818
- function startMultiAgentStream(event, operation, activeChildParents) {
34819
- const orchestrator = extractOrchestrator(event);
35732
+ function startMultiAgentStream(input, orchestrator, operation, activeChildParents) {
34820
35733
  const metadata = {
34821
35734
  "strands.operation": operation,
34822
35735
  provider: "strands",
34823
35736
  ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
34824
35737
  };
34825
35738
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
34826
- const input = processStrandsInputAttachments(event.arguments[0]);
35739
+ const processedInput = processStrandsInputAttachments(input);
34827
35740
  const span = parentSpan ? withCurrent(
34828
35741
  parentSpan,
34829
35742
  () => startSpan(
34830
35743
  withSpanInstrumentationName(
34831
35744
  {
34832
35745
  event: {
34833
- input,
35746
+ input: processedInput,
34834
35747
  metadata
34835
35748
  },
34836
35749
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -34843,7 +35756,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
34843
35756
  withSpanInstrumentationName(
34844
35757
  {
34845
35758
  event: {
34846
- input,
35759
+ input: processedInput,
34847
35760
  metadata
34848
35761
  },
34849
35762
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -35214,12 +36127,12 @@ function finalizeMultiAgentStream(state, activeChildParents, error, output) {
35214
36127
  });
35215
36128
  state.span.end();
35216
36129
  }
35217
- function extractAgent(event) {
35218
- const candidate = event.agent ?? event.self;
36130
+ function extractAgent(agent, self) {
36131
+ const candidate = agent ?? self;
35219
36132
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
35220
36133
  }
35221
- function extractOrchestrator(event) {
35222
- const candidate = event.orchestrator ?? event.self;
36134
+ function extractOrchestrator(orchestrator, self) {
36135
+ const candidate = orchestrator ?? self;
35223
36136
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
35224
36137
  }
35225
36138
  function extractAgentMetadata2(agent) {
@@ -37086,6 +37999,7 @@ __export(exports_exports, {
37086
37999
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
37087
38000
  buildLocalSummary: () => buildLocalSummary,
37088
38001
  collectAnthropicSession: () => collectAnthropicSession,
38002
+ completeOpenAIBatchTrace: () => completeOpenAIBatchTrace,
37089
38003
  configureInstrumentation: () => configureInstrumentation,
37090
38004
  constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
37091
38005
  createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
@@ -37124,6 +38038,8 @@ __export(exports_exports, {
37124
38038
  loginToState: () => loginToState,
37125
38039
  logs3OverflowUploadSchema: () => logs3OverflowUploadSchema,
37126
38040
  newId: () => newId,
38041
+ openaiBatchesRetrieveTraced: () => openaiBatchesRetrieveTraced,
38042
+ openaiFilesCreateTraced: () => openaiFilesCreateTraced,
37127
38043
  parseCachedHeader: () => parseCachedHeader,
37128
38044
  parseTemplateFormat: () => parseTemplateFormat,
37129
38045
  permalink: () => permalink,
@@ -37288,6 +38204,260 @@ async function registerSandbox(options) {
37288
38204
  };
37289
38205
  }
37290
38206
 
38207
+ // src/wrappers/openai-promise-utils.ts
38208
+ function splitSpanInfo(allParams) {
38209
+ const { span_info, ...params } = allParams;
38210
+ return {
38211
+ params,
38212
+ span_info
38213
+ };
38214
+ }
38215
+ function createChannelContext(_channel, params, span_info) {
38216
+ return {
38217
+ arguments: (
38218
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38219
+ [params]
38220
+ ),
38221
+ span_info
38222
+ };
38223
+ }
38224
+ async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
38225
+ let enhancedResponse;
38226
+ const tracePromise = (
38227
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38228
+ channel2.tracePromise
38229
+ );
38230
+ const data = await tracePromise(async () => {
38231
+ enhancedResponse = await apiPromise.withResponse();
38232
+ traceContext.response = enhancedResponse.response;
38233
+ return enhancedResponse.data;
38234
+ }, traceContext);
38235
+ if (!enhancedResponse) {
38236
+ throw new Error("Expected withResponse() to provide response");
38237
+ }
38238
+ return {
38239
+ data,
38240
+ response: enhancedResponse.response,
38241
+ request_id: enhancedResponse.request_id
38242
+ };
38243
+ }
38244
+ async function tracePromiseAsResponse(channel2, traceContext, apiPromise) {
38245
+ const tracePromise = (
38246
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38247
+ channel2.tracePromise
38248
+ );
38249
+ let response;
38250
+ await tracePromise(async () => {
38251
+ response = await apiPromise.asResponse();
38252
+ traceContext.response = response;
38253
+ return void 0;
38254
+ }, traceContext);
38255
+ if (!response) {
38256
+ throw new Error("Expected asResponse() to provide response");
38257
+ }
38258
+ return response;
38259
+ }
38260
+ function createLazyAPIPromise(ensureExecuted, ensureResponse, getAPIPromise) {
38261
+ let firstConsumption;
38262
+ let enhancedResponsePromise;
38263
+ let dataPromise;
38264
+ let responsePromise;
38265
+ const withResponse = () => {
38266
+ firstConsumption ??= "data";
38267
+ enhancedResponsePromise ??= firstConsumption === "data" ? ensureExecuted() : getAPIPromise().withResponse();
38268
+ return enhancedResponsePromise;
38269
+ };
38270
+ const asResponse = () => {
38271
+ firstConsumption ??= "response";
38272
+ responsePromise ??= firstConsumption === "response" ? ensureResponse() : getAPIPromise().asResponse();
38273
+ return responsePromise;
38274
+ };
38275
+ return new Proxy({}, {
38276
+ get(target, prop, receiver) {
38277
+ if (prop === "withResponse") {
38278
+ return withResponse;
38279
+ }
38280
+ if (prop === "asResponse") {
38281
+ return asResponse;
38282
+ }
38283
+ if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
38284
+ dataPromise ??= withResponse().then((result) => result.data);
38285
+ const value = Reflect.get(dataPromise, prop, receiver);
38286
+ return typeof value === "function" ? value.bind(dataPromise) : value;
38287
+ }
38288
+ return Reflect.get(target, prop, receiver);
38289
+ }
38290
+ });
38291
+ }
38292
+
38293
+ // src/openai-batch.ts
38294
+ function read2(value, key) {
38295
+ if (value === null || typeof value !== "object" && typeof value !== "function") {
38296
+ return void 0;
38297
+ }
38298
+ try {
38299
+ return Reflect.get(value, key);
38300
+ } catch {
38301
+ return void 0;
38302
+ }
38303
+ }
38304
+ function isAsyncIterable5(value) {
38305
+ return typeof read2(value, Symbol.asyncIterator) === "function";
38306
+ }
38307
+ function teeAsyncIterable(source) {
38308
+ const iterator = source[Symbol.asyncIterator]();
38309
+ const stream = new ReadableStream({
38310
+ async pull(controller) {
38311
+ try {
38312
+ const result = await iterator.next();
38313
+ if (result.done) {
38314
+ controller.close();
38315
+ return;
38316
+ }
38317
+ if (!(result.value instanceof Uint8Array)) {
38318
+ throw new TypeError(
38319
+ "OpenAI upload streams must yield Uint8Array chunks"
38320
+ );
38321
+ }
38322
+ controller.enqueue(result.value);
38323
+ } catch (error) {
38324
+ controller.error(error);
38325
+ }
38326
+ },
38327
+ async cancel(reason) {
38328
+ await iterator.return?.(reason);
38329
+ }
38330
+ });
38331
+ const [uploadStream, trace] = stream.tee();
38332
+ const upload = {
38333
+ async *[Symbol.asyncIterator]() {
38334
+ const reader = uploadStream.getReader();
38335
+ try {
38336
+ while (true) {
38337
+ const result = await reader.read();
38338
+ if (result.done) {
38339
+ return;
38340
+ }
38341
+ yield result.value;
38342
+ }
38343
+ } finally {
38344
+ reader.releaseLock();
38345
+ }
38346
+ }
38347
+ };
38348
+ const path = read2(source, "path");
38349
+ if (typeof path === "string") {
38350
+ Object.defineProperty(upload, "path", { value: path });
38351
+ }
38352
+ return { upload, trace: new Response(trace) };
38353
+ }
38354
+ function teeUpload(upload) {
38355
+ if (upload instanceof Blob) {
38356
+ return { upload, trace: new Response(upload) };
38357
+ }
38358
+ if (upload instanceof Response) {
38359
+ return { upload, trace: upload.clone() };
38360
+ }
38361
+ if (isAsyncIterable5(upload)) {
38362
+ return teeAsyncIterable(upload);
38363
+ }
38364
+ return void 0;
38365
+ }
38366
+ function openaiFilesCreateTraced(files) {
38367
+ return (params, options) => {
38368
+ const parent = getSpanParentObject();
38369
+ const purpose = read2(params, "purpose");
38370
+ const file = read2(params, "file");
38371
+ if (purpose !== "batch") {
38372
+ return files.create(params, options);
38373
+ }
38374
+ let branches;
38375
+ try {
38376
+ branches = teeUpload(file);
38377
+ } catch {
38378
+ return files.create(params, options);
38379
+ }
38380
+ if (!branches) {
38381
+ return files.create(params, options);
38382
+ }
38383
+ const tracedParams = {
38384
+ ...Object(params),
38385
+ file: branches.upload
38386
+ };
38387
+ const apiPromise = files.create(tracedParams, options);
38388
+ let enhancedResponse;
38389
+ const tracedResponse = openAIChannels.filesCreateTraced.invoke(
38390
+ async () => {
38391
+ enhancedResponse = await apiPromise.withResponse();
38392
+ return enhancedResponse.data;
38393
+ },
38394
+ files,
38395
+ [{ params, inputFileContent: branches.trace, parent }],
38396
+ {}
38397
+ ).then((data) => {
38398
+ if (!enhancedResponse) {
38399
+ throw new Error(
38400
+ "Expected OpenAI withResponse() to provide a response"
38401
+ );
38402
+ }
38403
+ return { ...enhancedResponse, data };
38404
+ });
38405
+ return createLazyAPIPromise(
38406
+ () => tracedResponse,
38407
+ () => tracedResponse.then(({ response }) => response),
38408
+ () => apiPromise
38409
+ );
38410
+ };
38411
+ }
38412
+ function openaiBatchesRetrieveTraced(batches) {
38413
+ return (batchId, options) => {
38414
+ const apiPromise = batches.retrieve(batchId, options);
38415
+ let enhancedResponse;
38416
+ const tracedResponse = openAIChannels.batchesRetrieveTraced.invoke(
38417
+ async () => {
38418
+ enhancedResponse = await apiPromise.withResponse();
38419
+ return enhancedResponse.data;
38420
+ },
38421
+ batches,
38422
+ [{ batchId }],
38423
+ {}
38424
+ ).then((data) => {
38425
+ if (!enhancedResponse) {
38426
+ throw new Error(
38427
+ "Expected OpenAI withResponse() to provide a response"
38428
+ );
38429
+ }
38430
+ return { ...enhancedResponse, data };
38431
+ });
38432
+ return createLazyAPIPromise(
38433
+ () => tracedResponse,
38434
+ () => tracedResponse.then(({ response }) => response),
38435
+ () => apiPromise
38436
+ );
38437
+ };
38438
+ }
38439
+ async function completeOpenAIBatchTrace(args) {
38440
+ const inputFileContent = Promise.resolve(args.inputFileContent);
38441
+ const outputFileContent = args.outputFileContent === void 0 ? void 0 : Promise.resolve(args.outputFileContent);
38442
+ const errorFileContent = args.errorFileContent === void 0 ? void 0 : Promise.resolve(args.errorFileContent);
38443
+ void inputFileContent.catch(() => void 0);
38444
+ void outputFileContent?.catch(() => void 0);
38445
+ void errorFileContent?.catch(() => void 0);
38446
+ await openAIChannels.batchesCompleteTrace.invoke(
38447
+ async () => void 0,
38448
+ void 0,
38449
+ [
38450
+ {
38451
+ ...args,
38452
+ inputFileContent,
38453
+ outputFileContent,
38454
+ errorFileContent
38455
+ }
38456
+ ],
38457
+ {}
38458
+ );
38459
+ }
38460
+
37291
38461
  // src/functions/invoke.ts
37292
38462
  async function invoke(args) {
37293
38463
  const {
@@ -37390,58 +38560,6 @@ function initFunction({
37390
38560
  return f;
37391
38561
  }
37392
38562
 
37393
- // src/wrappers/openai-promise-utils.ts
37394
- function splitSpanInfo(allParams) {
37395
- const { span_info, ...params } = allParams;
37396
- return {
37397
- params,
37398
- span_info
37399
- };
37400
- }
37401
- function createChannelContext(_channel, params, span_info) {
37402
- return {
37403
- arguments: (
37404
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37405
- [params]
37406
- ),
37407
- span_info
37408
- };
37409
- }
37410
- async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
37411
- let enhancedResponse;
37412
- const tracePromise = (
37413
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37414
- channel2.tracePromise
37415
- );
37416
- const data = await tracePromise(async () => {
37417
- enhancedResponse = await apiPromise.withResponse();
37418
- traceContext.response = enhancedResponse.response;
37419
- return enhancedResponse.data;
37420
- }, traceContext);
37421
- if (!enhancedResponse) {
37422
- throw new Error("Expected withResponse() to provide response");
37423
- }
37424
- return { data, response: enhancedResponse.response };
37425
- }
37426
- function createLazyAPIPromise(ensureExecuted) {
37427
- let dataPromise = null;
37428
- return new Proxy({}, {
37429
- get(target, prop, receiver) {
37430
- if (prop === "withResponse") {
37431
- return () => ensureExecuted();
37432
- }
37433
- if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
37434
- if (!dataPromise) {
37435
- dataPromise = ensureExecuted().then((result) => result.data);
37436
- }
37437
- const value = Reflect.get(dataPromise, prop, receiver);
37438
- return typeof value === "function" ? value.bind(dataPromise) : value;
37439
- }
37440
- return Reflect.get(target, prop, receiver);
37441
- }
37442
- });
37443
- }
37444
-
37445
38563
  // src/wrappers/oai_responses.ts
37446
38564
  function responsesProxy(openai) {
37447
38565
  if (!openai.responses) {
@@ -37478,17 +38596,33 @@ function wrapResponsesAsync(target, channel2) {
37478
38596
  return (allParams, options) => {
37479
38597
  const { span_info, params } = splitSpanInfo(allParams);
37480
38598
  let executionPromise = null;
38599
+ let apiPromise = null;
38600
+ const getAPIPromise = () => {
38601
+ apiPromise ??= target(params, options);
38602
+ return apiPromise;
38603
+ };
37481
38604
  const ensureExecuted = () => {
37482
38605
  if (!executionPromise) {
37483
38606
  executionPromise = (async () => {
37484
38607
  const traceContext = createChannelContext(channel2, params, span_info);
37485
- const apiPromise = target(params, options);
37486
- return tracePromiseWithResponse(channel2, traceContext, apiPromise);
38608
+ return tracePromiseWithResponse(
38609
+ channel2,
38610
+ traceContext,
38611
+ getAPIPromise()
38612
+ );
37487
38613
  })();
37488
38614
  }
37489
38615
  return executionPromise;
37490
38616
  };
37491
- return createLazyAPIPromise(ensureExecuted);
38617
+ return createLazyAPIPromise(
38618
+ ensureExecuted,
38619
+ () => tracePromiseAsResponse(
38620
+ channel2,
38621
+ createChannelContext(channel2, params, span_info),
38622
+ getAPIPromise()
38623
+ ),
38624
+ getAPIPromise
38625
+ );
37492
38626
  };
37493
38627
  }
37494
38628
  function wrapResponsesSyncStream(target, channel2) {
@@ -37634,6 +38768,11 @@ function wrapChatCompletion(completion) {
37634
38768
  allParams
37635
38769
  );
37636
38770
  let executionPromise = null;
38771
+ let apiPromise = null;
38772
+ const getAPIPromise = () => {
38773
+ apiPromise ??= completion(params, options);
38774
+ return apiPromise;
38775
+ };
37637
38776
  const ensureExecuted = () => {
37638
38777
  if (!executionPromise) {
37639
38778
  executionPromise = (async () => {
@@ -37643,32 +38782,44 @@ function wrapChatCompletion(completion) {
37643
38782
  span_info
37644
38783
  );
37645
38784
  if (params.stream) {
37646
- const completionPromise = completion(
37647
- params,
37648
- options
38785
+ const completionPromise = (
38786
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38787
+ getAPIPromise()
37649
38788
  );
37650
- const { data: data2, response: response2 } = await tracePromiseWithResponse(
38789
+ const { data: data2, response: response2, request_id: request_id2 } = await tracePromiseWithResponse(
37651
38790
  openAIChannels.chatCompletionsCreate,
37652
38791
  traceContext,
37653
38792
  completionPromise
37654
38793
  );
37655
- return { data: data2, response: response2 };
38794
+ return { data: data2, response: response2, request_id: request_id2 };
37656
38795
  }
37657
- const completionResponse = completion(
37658
- params,
37659
- options
38796
+ const completionResponse = (
38797
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38798
+ getAPIPromise()
37660
38799
  );
37661
- const { data, response } = await tracePromiseWithResponse(
38800
+ const { data, response, request_id } = await tracePromiseWithResponse(
37662
38801
  openAIChannels.chatCompletionsCreate,
37663
38802
  traceContext,
37664
38803
  completionResponse
37665
38804
  );
37666
- return { data, response };
38805
+ return { data, response, request_id };
37667
38806
  })();
37668
38807
  }
37669
38808
  return executionPromise;
37670
38809
  };
37671
- return createLazyAPIPromise(ensureExecuted);
38810
+ return createLazyAPIPromise(
38811
+ ensureExecuted,
38812
+ () => tracePromiseAsResponse(
38813
+ openAIChannels.chatCompletionsCreate,
38814
+ createChannelContext(
38815
+ openAIChannels.chatCompletionsCreate,
38816
+ params,
38817
+ span_info
38818
+ ),
38819
+ getAPIPromise()
38820
+ ),
38821
+ getAPIPromise
38822
+ );
37672
38823
  };
37673
38824
  }
37674
38825
  function createEndpointProxy(target, wrapperFn) {
@@ -37686,6 +38837,11 @@ function wrapApiCreateWithChannel(create, channel2) {
37686
38837
  return (allParams, options) => {
37687
38838
  const { span_info, params } = splitSpanInfo(allParams);
37688
38839
  let executionPromise = null;
38840
+ let apiPromise = null;
38841
+ const getAPIPromise = () => {
38842
+ apiPromise ??= create(params, options);
38843
+ return apiPromise;
38844
+ };
37689
38845
  const ensureExecuted = () => {
37690
38846
  if (!executionPromise) {
37691
38847
  executionPromise = (async () => {
@@ -37693,13 +38849,21 @@ function wrapApiCreateWithChannel(create, channel2) {
37693
38849
  return tracePromiseWithResponse(
37694
38850
  channel2,
37695
38851
  traceContext,
37696
- create(params, options)
38852
+ getAPIPromise()
37697
38853
  );
37698
38854
  })();
37699
38855
  }
37700
38856
  return executionPromise;
37701
38857
  };
37702
- return createLazyAPIPromise(ensureExecuted);
38858
+ return createLazyAPIPromise(
38859
+ ensureExecuted,
38860
+ () => tracePromiseAsResponse(
38861
+ channel2,
38862
+ createChannelContext(channel2, params, span_info),
38863
+ getAPIPromise()
38864
+ ),
38865
+ getAPIPromise
38866
+ );
37703
38867
  };
37704
38868
  }
37705
38869
  var wrapEmbeddings = (create) => wrapApiCreateWithChannel(create, openAIChannels.embeddingsCreate);
@@ -37735,6 +38899,13 @@ function wrapAISDK(aiSDK, options = {}) {
37735
38899
  switch (prop) {
37736
38900
  case "generateText":
37737
38901
  return wrapGenerateText(typedAISDK.generateText, options, typedAISDK);
38902
+ case "generateImage":
38903
+ case "experimental_generateImage":
38904
+ return typeof original === "function" ? wrapGenerateImage(
38905
+ original,
38906
+ options,
38907
+ typedAISDK
38908
+ ) : original;
37738
38909
  case "streamText":
37739
38910
  return wrapStreamText(typedAISDK.streamText, options, typedAISDK);
37740
38911
  case "generateObject":
@@ -37971,6 +39142,32 @@ var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
37971
39142
  options
37972
39143
  );
37973
39144
  };
39145
+ var wrapGenerateImage = (generateImage, options = {}, aiSDK) => {
39146
+ return makeGenerateImageWrapper(generateImage, { aiSDK }, options);
39147
+ };
39148
+ var makeGenerateImageWrapper = (generateImage, contextOptions = {}, options = {}) => {
39149
+ const wrapper = async function(allParams) {
39150
+ const { span_info, ...params } = allParams;
39151
+ const tracedParams = { ...params };
39152
+ return aiSDKChannels.generateImage.tracePromise(
39153
+ () => generateImage(tracedParams),
39154
+ createAISDKChannelContext(tracedParams, {
39155
+ aiSDK: contextOptions.aiSDK,
39156
+ denyOutputPaths: options.denyOutputPaths,
39157
+ self: contextOptions.self,
39158
+ span_info: mergeSpanInfo(span_info, {
39159
+ name: "generateImage",
39160
+ spanType: contextOptions.spanType
39161
+ })
39162
+ })
39163
+ );
39164
+ };
39165
+ Object.defineProperty(wrapper, "name", {
39166
+ value: "generateImage",
39167
+ writable: false
39168
+ });
39169
+ return wrapper;
39170
+ };
37974
39171
  var makeEmbedWrapper = (channel2, name, embed, contextOptions = {}, options = {}) => {
37975
39172
  const wrapper = async function(allParams) {
37976
39173
  const { span_info, ...params } = allParams;
@@ -38721,7 +39918,7 @@ function braintrustEveHook(options) {
38721
39918
  }
38722
39919
  };
38723
39920
  }
38724
- function braintrustEveInstrumentation(options) {
39921
+ function createLegacyEveInstrumentation(options) {
38725
39922
  const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
38726
39923
  return {
38727
39924
  events: {
@@ -40109,8 +41306,10 @@ function capturedModelInput(modelInput) {
40109
41306
  const value = [];
40110
41307
  if (typeof instructions === "string") {
40111
41308
  value.push({ content: instructions, role: "system" });
40112
- } else if (instructions) {
41309
+ } else if (Array.isArray(instructions)) {
40113
41310
  value.push(...instructions.map(capturedEveModelMessage));
41311
+ } else if (instructions) {
41312
+ value.push(capturedEveModelMessage(instructions));
40114
41313
  }
40115
41314
  value.push(...messages.map(capturedEveModelMessage));
40116
41315
  try {
@@ -40354,6 +41553,472 @@ async function deterministicEveId(...parts) {
40354
41553
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
40355
41554
  }
40356
41555
 
41556
+ // src/instrumentation/plugins/eve-provider.ts
41557
+ var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
41558
+ function createEveInstrumentationProvider(options = {}) {
41559
+ const bridge = new EveProviderBridge(options.metadata);
41560
+ return {
41561
+ // Eve versions before tracePolicy use capture to decide whether provider
41562
+ // events include content. Newer versions prefer tracePolicy when both are
41563
+ // present, so keep the deprecated field for backwards compatibility.
41564
+ capture: "content",
41565
+ tracePolicy: () => ({
41566
+ emit: true,
41567
+ recordInputs: true,
41568
+ recordOutputs: true
41569
+ }),
41570
+ events: {
41571
+ "action.completed": (event, context) => bridge.handleActionTerminal(event, context),
41572
+ "action.failed": (event, context) => bridge.handleActionTerminal(event, context),
41573
+ "action.started": (event, context) => bridge.handleActionStarted(event, context),
41574
+ "model.call.completed": (event, context) => bridge.handleModelTerminal(event, context),
41575
+ "model.call.failed": (event, context) => bridge.handleModelTerminal(event, context),
41576
+ "model.call.started": (event, context) => bridge.handleModelStarted(event, context),
41577
+ "step.attempt.completed": (event) => bridge.handleStepAttemptTerminal(event),
41578
+ "step.attempt.failed": (event) => bridge.handleStepAttemptTerminal(event),
41579
+ "turn.cancelled": (event, context) => bridge.handleTurnTerminal(event, context),
41580
+ "turn.completed": (event, context) => bridge.handleTurnTerminal(event, context),
41581
+ "turn.failed": (event, context) => bridge.handleTurnTerminal(event, context),
41582
+ "turn.started": (event, context) => bridge.handleTurnStarted(event, context)
41583
+ },
41584
+ flush,
41585
+ setup: options.setup
41586
+ };
41587
+ }
41588
+ var EveProviderBridge = class {
41589
+ constructor(metadata) {
41590
+ this.metadata = metadata;
41591
+ }
41592
+ metadata;
41593
+ activeActions = /* @__PURE__ */ new Map();
41594
+ activeModels = /* @__PURE__ */ new Map();
41595
+ modelsByAttempt = /* @__PURE__ */ new Map();
41596
+ settledOperations = new LRUCache({
41597
+ max: MAX_EVE_PROVIDER_CACHE_ENTRIES
41598
+ });
41599
+ turns = new LRUCache({
41600
+ max: MAX_EVE_PROVIDER_CACHE_ENTRIES
41601
+ });
41602
+ async handleTurnStarted(event, context) {
41603
+ await this.contain("turn start", async () => {
41604
+ if (this.settledOperations.has(event.idempotencyKey)) {
41605
+ context.state.set({ skip: true });
41606
+ return;
41607
+ }
41608
+ const { rowId, spanId } = await generateEveIds(
41609
+ "turn",
41610
+ event.idempotencyKey
41611
+ );
41612
+ const key = turnKey3(event.sessionId, event.turnId);
41613
+ const stored = storedSpan(context);
41614
+ if (stored && "exported" in stored && stored.rootSpanId) {
41615
+ this.turns.set(key, { rootSpanId: stored.rootSpanId, spanId });
41616
+ return;
41617
+ }
41618
+ let rootSpanId = spanId;
41619
+ let parentSpanId;
41620
+ if (event.parentLineage) {
41621
+ const parentTurnKey = turnKey3(
41622
+ event.parentLineage.sessionId,
41623
+ event.parentLineage.turnId
41624
+ );
41625
+ const parentTurn = this.turns.get(parentTurnKey);
41626
+ rootSpanId = parentTurn?.rootSpanId ?? // Eve propagates the root session through every nested subagent. Use
41627
+ // it instead of the immediate parent session when no ancestor ran
41628
+ // in-process.
41629
+ (await generateEveIds(
41630
+ "turn",
41631
+ turnIdempotencyKey(
41632
+ event.rootSessionId,
41633
+ event.parentLineage.turnId
41634
+ )
41635
+ )).spanId;
41636
+ parentSpanId = (await generateEveIds(
41637
+ "subagent",
41638
+ actionIdempotencyKey(
41639
+ event.parentLineage.sessionId,
41640
+ event.parentLineage.turnId,
41641
+ event.parentLineage.callId
41642
+ )
41643
+ )).spanId;
41644
+ }
41645
+ const metadata = this.spanMetadata(event.sessionId);
41646
+ const span = await this.startSpan(
41647
+ context,
41648
+ {
41649
+ event: { id: rowId, metadata },
41650
+ name: "eve.turn",
41651
+ parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
41652
+ spanAttributes: { type: "task" /* TASK */ },
41653
+ spanId
41654
+ },
41655
+ rootSpanId
41656
+ );
41657
+ span?.log({ metadata });
41658
+ this.turns.set(key, {
41659
+ rootSpanId,
41660
+ spanId
41661
+ });
41662
+ });
41663
+ }
41664
+ async handleTurnTerminal(event, context) {
41665
+ await this.contain("turn terminal", async () => {
41666
+ if (this.settledOperations.has(event.idempotencyKey)) {
41667
+ context.state.set(void 0);
41668
+ return;
41669
+ }
41670
+ const error = event.type === "turn.failed" ? event.error : void 0;
41671
+ this.drainActionsForTurn(event.sessionId, event.turnId, error);
41672
+ const stored = storedSpan(context);
41673
+ if (stored && "exported" in stored) {
41674
+ updateSpan({
41675
+ exported: stored.exported,
41676
+ ...error !== void 0 ? { error } : {},
41677
+ metrics: { end: Date.now() / 1e3 }
41678
+ });
41679
+ }
41680
+ this.settledOperations.set(event.idempotencyKey, true);
41681
+ context.state.set(void 0);
41682
+ this.turns.delete(turnKey3(event.sessionId, event.turnId));
41683
+ });
41684
+ }
41685
+ async handleModelStarted(event, context) {
41686
+ await this.contain("model start", async () => {
41687
+ if (this.settledOperations.has(event.idempotencyKey)) {
41688
+ context.state.set({ skip: true });
41689
+ return;
41690
+ }
41691
+ const parent = await this.parentForScope(event.scope);
41692
+ const { rowId, spanId } = await generateEveIds(
41693
+ "step",
41694
+ event.idempotencyKey
41695
+ );
41696
+ const input = event.input ? capturedModelInput(event.input) : void 0;
41697
+ const metadata = {
41698
+ ...this.spanMetadata(event.scope.sessionId),
41699
+ model: event.model.modelId,
41700
+ provider: event.model.provider
41701
+ };
41702
+ const span = await this.startSpan(context, {
41703
+ event: {
41704
+ id: rowId,
41705
+ ...input !== void 0 ? { input } : {},
41706
+ metadata
41707
+ },
41708
+ name: "eve.step",
41709
+ parentSpanIds: parent,
41710
+ spanAttributes: { type: "llm" /* LLM */ },
41711
+ spanId
41712
+ });
41713
+ if (!span) return;
41714
+ span.log({ ...input !== void 0 ? { input } : {}, metadata });
41715
+ this.activeModels.set(event.idempotencyKey, {
41716
+ span,
41717
+ turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
41718
+ });
41719
+ const keys = this.modelsByAttempt.get(event.scope.attemptId) ?? /* @__PURE__ */ new Set();
41720
+ keys.add(event.idempotencyKey);
41721
+ this.modelsByAttempt.set(event.scope.attemptId, keys);
41722
+ });
41723
+ }
41724
+ async handleModelTerminal(event, context) {
41725
+ await this.contain("model terminal", async () => {
41726
+ if (this.settledOperations.has(event.idempotencyKey)) {
41727
+ context.state.set(void 0);
41728
+ return;
41729
+ }
41730
+ const active = this.activeModels.get(event.idempotencyKey);
41731
+ if (active) {
41732
+ const span = active.span;
41733
+ if (event.type === "model.call.failed") {
41734
+ if (event.error !== void 0) span.log({ error: event.error });
41735
+ } else {
41736
+ span.log({
41737
+ metrics: usageMetrics(event.usage),
41738
+ output: modelOutput(event)
41739
+ });
41740
+ }
41741
+ span.end();
41742
+ } else {
41743
+ const stored = storedSpan(context);
41744
+ if (stored && "exported" in stored) {
41745
+ updateSpan({
41746
+ exported: stored.exported,
41747
+ ...event.type === "model.call.failed" ? event.error !== void 0 ? { error: event.error } : {} : { output: modelOutput(event) },
41748
+ metrics: {
41749
+ ...event.type === "model.call.completed" ? usageMetrics(event.usage) : {},
41750
+ end: Date.now() / 1e3
41751
+ }
41752
+ });
41753
+ }
41754
+ }
41755
+ this.settledOperations.set(event.idempotencyKey, true);
41756
+ this.forgetModel(event.scope.attemptId, event.idempotencyKey);
41757
+ context.state.set(void 0);
41758
+ });
41759
+ }
41760
+ async handleActionStarted(event, context) {
41761
+ await this.contain("action start", async () => {
41762
+ if (event.kind === "load-skill" || this.settledOperations.has(event.idempotencyKey)) {
41763
+ context.state.set({ skip: true });
41764
+ return;
41765
+ }
41766
+ const parent = await this.parentForScope(event.scope);
41767
+ const { rowId, spanId } = await generateEveIds(
41768
+ event.kind === "subagent-call" ? "subagent" : "tool",
41769
+ event.idempotencyKey
41770
+ );
41771
+ const metadata = {
41772
+ ...this.spanMetadata(event.scope.sessionId),
41773
+ "eve.action_kind": event.kind
41774
+ };
41775
+ const span = await this.startSpan(context, {
41776
+ event: {
41777
+ id: rowId,
41778
+ ...event.input !== void 0 ? { input: event.input } : {},
41779
+ metadata
41780
+ },
41781
+ name: event.name,
41782
+ parentSpanIds: parent,
41783
+ spanAttributes: { type: "tool" /* TOOL */ },
41784
+ spanId
41785
+ });
41786
+ if (!span) return;
41787
+ span.log({
41788
+ ...event.input !== void 0 ? { input: event.input } : {},
41789
+ metadata
41790
+ });
41791
+ this.activeActions.set(event.idempotencyKey, {
41792
+ span,
41793
+ turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
41794
+ });
41795
+ });
41796
+ }
41797
+ async handleActionTerminal(event, context) {
41798
+ await this.contain("action terminal", async () => {
41799
+ if (this.settledOperations.has(event.idempotencyKey)) {
41800
+ context.state.set(void 0);
41801
+ return;
41802
+ }
41803
+ const stored = storedSpan(context);
41804
+ if (stored?.skip) {
41805
+ context.state.set(void 0);
41806
+ return;
41807
+ }
41808
+ const active = this.activeActions.get(event.idempotencyKey);
41809
+ const end = finiteTimestamp(event.acceptedAtMs) ?? Date.now();
41810
+ if (active) {
41811
+ const span = active.span;
41812
+ if (event.type === "action.failed") {
41813
+ span.log({
41814
+ error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
41815
+ });
41816
+ } else if (event.output.type === "error") {
41817
+ span.log({
41818
+ error: event.output.error ?? new Error("Eve action returned an error")
41819
+ });
41820
+ } else {
41821
+ span.log({ output: event.output.output });
41822
+ }
41823
+ span.end({ endTime: end / 1e3 });
41824
+ } else {
41825
+ const stored2 = storedSpan(context);
41826
+ if (stored2 && "exported" in stored2) {
41827
+ updateSpan({
41828
+ exported: stored2.exported,
41829
+ ...event.type === "action.failed" ? {
41830
+ error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
41831
+ } : event.output.type === "error" ? {
41832
+ error: event.output.error ?? new Error("Eve action returned an error")
41833
+ } : { output: event.output.output },
41834
+ metrics: { end: end / 1e3 }
41835
+ });
41836
+ }
41837
+ }
41838
+ this.settledOperations.set(event.idempotencyKey, true);
41839
+ this.activeActions.delete(event.idempotencyKey);
41840
+ context.state.set(void 0);
41841
+ });
41842
+ }
41843
+ handleStepAttemptTerminal(event) {
41844
+ void this.contain("step attempt terminal", () => {
41845
+ const keys = this.modelsByAttempt.get(event.scope.attemptId);
41846
+ if (!keys) return;
41847
+ for (const key of keys) {
41848
+ const active = this.activeModels.get(key);
41849
+ if (!active) continue;
41850
+ if (event.type === "step.attempt.failed" && event.error !== void 0) {
41851
+ active.span.log({ error: event.error });
41852
+ }
41853
+ active.span.end();
41854
+ this.activeModels.delete(key);
41855
+ }
41856
+ this.modelsByAttempt.delete(event.scope.attemptId);
41857
+ });
41858
+ }
41859
+ async parentForScope(scope) {
41860
+ const key = turnKey3(scope.sessionId, scope.turnId);
41861
+ const known = this.turns.get(key);
41862
+ if (known) {
41863
+ return { rootSpanId: known.rootSpanId, spanId: known.spanId };
41864
+ }
41865
+ const [{ spanId }, { spanId: rootSpanId }] = await Promise.all([
41866
+ generateEveIds("turn", turnIdempotencyKey(scope.sessionId, scope.turnId)),
41867
+ generateEveIds(
41868
+ "turn",
41869
+ turnIdempotencyKey(
41870
+ scope.rootSessionId ?? scope.sessionId,
41871
+ scope.turnId
41872
+ )
41873
+ )
41874
+ ]);
41875
+ return { rootSpanId, spanId };
41876
+ }
41877
+ async startSpan(context, args, rootSpanId) {
41878
+ const span = withCurrent(
41879
+ NOOP_SPAN,
41880
+ () => _internalStartSpanWithInitialMerge(
41881
+ withSpanInstrumentationName(args ?? {}, INSTRUMENTATION_NAMES.EVE)
41882
+ )
41883
+ );
41884
+ try {
41885
+ context.state.set({
41886
+ exported: await span.export(),
41887
+ ...rootSpanId ? { rootSpanId } : {}
41888
+ });
41889
+ } catch (error) {
41890
+ debugLogger.warn("Error exporting Eve provider span:", error);
41891
+ }
41892
+ return span;
41893
+ }
41894
+ drainActionsForTurn(sessionId, turnId, error) {
41895
+ const key = turnKey3(sessionId, turnId);
41896
+ for (const [idempotencyKey, active] of this.activeActions) {
41897
+ if (active.turnKey !== key) continue;
41898
+ if (error !== void 0) active.span.log({ error });
41899
+ active.span.end();
41900
+ this.activeActions.delete(idempotencyKey);
41901
+ }
41902
+ }
41903
+ forgetModel(attemptId, idempotencyKey) {
41904
+ this.activeModels.delete(idempotencyKey);
41905
+ const keys = this.modelsByAttempt.get(attemptId);
41906
+ keys?.delete(idempotencyKey);
41907
+ if (keys?.size === 0) this.modelsByAttempt.delete(attemptId);
41908
+ }
41909
+ spanMetadata(sessionId) {
41910
+ return {
41911
+ ...this.metadata ?? {},
41912
+ "eve.session_id": sessionId
41913
+ };
41914
+ }
41915
+ async contain(operation, fn) {
41916
+ try {
41917
+ await fn();
41918
+ } catch (error) {
41919
+ debugLogger.warn(`Error in Eve provider ${operation}:`, error);
41920
+ }
41921
+ }
41922
+ };
41923
+ function storedSpan(context) {
41924
+ const value = context.state.get();
41925
+ if (!isObject(value)) return void 0;
41926
+ if (value["skip"] === true) return { skip: true };
41927
+ return typeof value["exported"] === "string" ? {
41928
+ exported: value["exported"],
41929
+ ...typeof value["rootSpanId"] === "string" && value["rootSpanId"].length > 0 ? { rootSpanId: value["rootSpanId"] } : {}
41930
+ } : void 0;
41931
+ }
41932
+ function modelOutput(event) {
41933
+ const content = event.content ?? [];
41934
+ let text = "";
41935
+ const reasoning = [];
41936
+ const toolCalls2 = [];
41937
+ for (const part of content) {
41938
+ if (part.type === "text") {
41939
+ text += part.text;
41940
+ } else if (part.type === "reasoning" && part.text.trim().length > 0) {
41941
+ reasoning.push({ content: part.text });
41942
+ } else if (part.type === "tool-call") {
41943
+ toolCalls2.push({
41944
+ function: {
41945
+ arguments: safeJsonStringify(part.input),
41946
+ name: part.toolName
41947
+ },
41948
+ id: part.callId,
41949
+ type: "function"
41950
+ });
41951
+ }
41952
+ }
41953
+ return [
41954
+ {
41955
+ finish_reason: normalizeFinishReason3(event.finishReason),
41956
+ index: 0,
41957
+ message: {
41958
+ content: text || null,
41959
+ ...reasoning.length > 0 ? { reasoning } : {},
41960
+ role: "assistant",
41961
+ ...toolCalls2.length > 0 ? { tool_calls: toolCalls2 } : {}
41962
+ }
41963
+ }
41964
+ ];
41965
+ }
41966
+ function usageMetrics(usage) {
41967
+ const promptTokens = nonNegativeNumber(usage.inputTokens);
41968
+ const completionTokens = nonNegativeNumber(usage.outputTokens);
41969
+ const cachedTokens = nonNegativeNumber(
41970
+ usage.inputTokenDetails?.cacheReadTokens
41971
+ );
41972
+ const cacheCreationTokens = nonNegativeNumber(
41973
+ usage.inputTokenDetails?.cacheWriteTokens
41974
+ );
41975
+ return {
41976
+ ...promptTokens !== void 0 ? { prompt_tokens: promptTokens } : {},
41977
+ ...completionTokens !== void 0 ? { completion_tokens: completionTokens } : {},
41978
+ ...promptTokens !== void 0 && completionTokens !== void 0 ? { tokens: promptTokens + completionTokens } : {},
41979
+ ...cachedTokens !== void 0 ? { prompt_cached_tokens: cachedTokens } : {},
41980
+ ...cacheCreationTokens !== void 0 ? { prompt_cache_creation_tokens: cacheCreationTokens } : {}
41981
+ };
41982
+ }
41983
+ function nonNegativeNumber(value) {
41984
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
41985
+ }
41986
+ function finiteTimestamp(value) {
41987
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
41988
+ }
41989
+ function normalizeFinishReason3(value) {
41990
+ if (value === "content-filter") return "content_filter";
41991
+ if (value === "tool-calls") return "tool_calls";
41992
+ return value;
41993
+ }
41994
+ function safeJsonStringify(value) {
41995
+ try {
41996
+ return JSON.stringify(value) ?? "null";
41997
+ } catch {
41998
+ return "null";
41999
+ }
42000
+ }
42001
+ function turnKey3(sessionId, turnId) {
42002
+ return `${sessionId}:${turnId}`;
42003
+ }
42004
+ function turnIdempotencyKey(sessionId, turnId) {
42005
+ return `turn:${sessionId}:${turnId}`;
42006
+ }
42007
+ function actionIdempotencyKey(sessionId, turnId, callId) {
42008
+ return `action:${sessionId}:${turnId}:${callId}`;
42009
+ }
42010
+
42011
+ // src/instrumentation/plugins/eve-instrumentation.ts
42012
+ var EVE_INSTRUMENTATION_PROVIDER = /* @__PURE__ */ Symbol.for("eve.instrumentation.provider");
42013
+ function braintrustEveInstrumentation(options) {
42014
+ const definition = "defineState" in options ? createLegacyEveInstrumentation(options) : createEveInstrumentationProvider(options);
42015
+ const declaration = {
42016
+ ...definition,
42017
+ [EVE_INSTRUMENTATION_PROVIDER]: true
42018
+ };
42019
+ return declaration;
42020
+ }
42021
+
40357
42022
  // src/typed-instrumentation-helpers.ts
40358
42023
  var TypedApplyProxy = Proxy;
40359
42024
 
@@ -40755,11 +42420,11 @@ function wrapClaudeAgentQuery(queryFn, defaultThis) {
40755
42420
  }
40756
42421
  };
40757
42422
  const invocationTarget = thisArg === proxy || thisArg === void 0 ? defaultThis ?? thisArg : thisArg;
40758
- return claudeAgentSDKChannels.query.traceSync(
40759
- () => Reflect.apply(target, invocationTarget, [wrappedParams]),
40760
- // The channel carries no extra context fields, but the generated
40761
- // StartOf<> type for Record<string, never> is overly strict here.
40762
- { arguments: [wrappedParams] }
42423
+ return claudeAgentSDKChannels.query.invoke(
42424
+ target,
42425
+ invocationTarget,
42426
+ [wrappedParams],
42427
+ {}
40763
42428
  );
40764
42429
  }
40765
42430
  });
@@ -41374,13 +43039,11 @@ function wrapAgentInstance(agent) {
41374
43039
  if (prop === "stream" && typeof value === "function") {
41375
43040
  return function(args, options) {
41376
43041
  const callArgs = [args, options];
41377
- return strandsAgentSDKChannels.agentStream.traceSync(
41378
- () => Reflect.apply(value, target, callArgs),
41379
- {
41380
- agent: proxy,
41381
- arguments: callArgs,
41382
- self: proxy
41383
- }
43042
+ return strandsAgentSDKChannels.agentStream.invoke(
43043
+ value,
43044
+ target,
43045
+ callArgs,
43046
+ { agent: proxy }
41384
43047
  );
41385
43048
  };
41386
43049
  }
@@ -41411,12 +43074,12 @@ function wrapMultiAgentInstance(orchestrator, kind) {
41411
43074
  return function(input, options) {
41412
43075
  const callArgs = [input, options];
41413
43076
  const channel2 = kind === "graph" ? strandsAgentSDKChannels.graphStream : strandsAgentSDKChannels.swarmStream;
41414
- return channel2.traceSync(
41415
- () => Reflect.apply(value, target, callArgs),
43077
+ return channel2.invoke(
43078
+ value,
43079
+ target,
43080
+ callArgs,
41416
43081
  {
41417
- arguments: callArgs,
41418
- orchestrator: proxy,
41419
- self: proxy
43082
+ orchestrator: proxy
41420
43083
  }
41421
43084
  );
41422
43085
  };
@@ -43368,9 +45031,6 @@ var VitestContextManager = class {
43368
45031
  getCurrentContext() {
43369
45032
  return this.contextStorage.getStore();
43370
45033
  }
43371
- setContext(context) {
43372
- this.contextStorage.enterWith(context);
43373
- }
43374
45034
  runInContext(context, callback) {
43375
45035
  return this.contextStorage.run(context, callback);
43376
45036
  }
@@ -43756,8 +45416,7 @@ function wrapDescribe(originalDescribe, config, afterAll) {
43756
45416
  if (config.onProgress) {
43757
45417
  config.onProgress({ type: "suite_start", suiteName });
43758
45418
  }
43759
- contextManager.setContext(lazyContext);
43760
- factory();
45419
+ contextManager.runInContext(lazyContext, factory);
43761
45420
  if (afterAll) {
43762
45421
  afterAll(async () => {
43763
45422
  await flushExperimentWithSync(context, config);