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
@@ -104,6 +104,7 @@ __export(edge_light_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(edge_light_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;
@@ -12672,56 +13047,14 @@ function suppressionStore() {
12672
13047
  autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
12673
13048
  return autoInstrumentationSuppressionStore;
12674
13049
  }
12675
- function currentFrames() {
12676
- return suppressionStore().getStore()?.frames ?? [];
12677
- }
12678
13050
  function isAutoInstrumentationSuppressed() {
12679
- const frames = currentFrames();
12680
- return frames[frames.length - 1]?.mode === "suppress";
13051
+ return suppressionStore().getStore() === true;
12681
13052
  }
12682
13053
  function runWithAutoInstrumentationSuppressed(callback) {
12683
- const frame = {
12684
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
12685
- mode: "suppress"
12686
- };
12687
- return suppressionStore().run(
12688
- { frames: [...currentFrames(), frame] },
12689
- callback
12690
- );
12691
- }
12692
- function bindAutoInstrumentationSuppressionToStart(tracingChannel) {
12693
- const startChannel = tracingChannel.start;
12694
- if (!startChannel) {
12695
- return void 0;
12696
- }
12697
- const store = suppressionStore();
12698
- startChannel.bindStore(store, () => ({
12699
- frames: [
12700
- ...currentFrames(),
12701
- {
12702
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
12703
- mode: "suppress"
12704
- }
12705
- ]
12706
- }));
12707
- return () => {
12708
- startChannel.unbindStore(store);
12709
- };
13054
+ return suppressionStore().run(true, callback);
12710
13055
  }
12711
- function enterAutoInstrumentationAllowed() {
12712
- const frame = {
12713
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
12714
- mode: "allow"
12715
- };
12716
- suppressionStore().enterWith({
12717
- frames: [...currentFrames(), frame]
12718
- });
12719
- return () => {
12720
- const frames = currentFrames().filter(
12721
- (candidate) => candidate.id !== frame.id
12722
- );
12723
- suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
12724
- };
13056
+ function runWithAutoInstrumentationAllowed(callback) {
13057
+ return suppressionStore().run(void 0, callback);
12725
13058
  }
12726
13059
 
12727
13060
  // src/instrumentation/core/channel-tracing.ts
@@ -13311,6 +13644,131 @@ function unsubscribeAll(unsubscribers) {
13311
13644
  return [];
13312
13645
  }
13313
13646
 
13647
+ // src/instrumentation/core/channel-definitions.ts
13648
+ function channel(spec) {
13649
+ return spec;
13650
+ }
13651
+ function defineChannels(pkg, channels, options) {
13652
+ const { instrumentationName } = options;
13653
+ return Object.fromEntries(
13654
+ Object.entries(channels).map(([key, spec]) => {
13655
+ const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
13656
+ if (spec.kind === "async") {
13657
+ const asyncSpec = spec;
13658
+ const tracingChannel2 = () => isomorph_default.newTracingChannel(
13659
+ fullChannelName
13660
+ );
13661
+ const intercept2 = (interceptor) => {
13662
+ const hook = tracingChannel2();
13663
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13664
+ };
13665
+ };
13666
+ return [
13667
+ key,
13668
+ {
13669
+ ...asyncSpec,
13670
+ instrumentationName,
13671
+ intercept: intercept2,
13672
+ invoke: (target, thisArg, args, additional) => {
13673
+ const hook = tracingChannel2();
13674
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13675
+ },
13676
+ tracingChannel: tracingChannel2,
13677
+ tracePromise: (fn, context) => tracingChannel2().tracePromise(
13678
+ fn,
13679
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13680
+ context
13681
+ )
13682
+ }
13683
+ ];
13684
+ }
13685
+ const syncSpec = spec;
13686
+ const tracingChannel = () => isomorph_default.newTracingChannel(
13687
+ fullChannelName
13688
+ );
13689
+ const intercept = (interceptor) => {
13690
+ const hook = tracingChannel();
13691
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13692
+ };
13693
+ };
13694
+ return [
13695
+ key,
13696
+ {
13697
+ ...syncSpec,
13698
+ instrumentationName,
13699
+ intercept,
13700
+ invoke: (target, thisArg, args, additional) => {
13701
+ const hook = tracingChannel();
13702
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13703
+ },
13704
+ tracingChannel,
13705
+ traceSync: (fn, context) => tracingChannel().traceSync(
13706
+ fn,
13707
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13708
+ context
13709
+ )
13710
+ }
13711
+ ];
13712
+ })
13713
+ );
13714
+ }
13715
+
13716
+ // src/instrumentation/plugins/openai-channels.ts
13717
+ var openAIChannels = defineChannels(
13718
+ "openai",
13719
+ {
13720
+ filesCreateTraced: channel({
13721
+ channelName: "files.create-traced",
13722
+ kind: "async"
13723
+ }),
13724
+ batchesRetrieveTraced: channel({
13725
+ channelName: "batches.retrieve-traced",
13726
+ kind: "async"
13727
+ }),
13728
+ batchesCompleteTrace: channel({
13729
+ channelName: "batches.complete-trace",
13730
+ kind: "async"
13731
+ }),
13732
+ chatCompletionsCreate: channel({
13733
+ channelName: "chat.completions.create",
13734
+ kind: "async"
13735
+ }),
13736
+ embeddingsCreate: channel({
13737
+ channelName: "embeddings.create",
13738
+ kind: "async"
13739
+ }),
13740
+ betaChatCompletionsParse: channel({
13741
+ channelName: "beta.chat.completions.parse",
13742
+ kind: "async"
13743
+ }),
13744
+ betaChatCompletionsStream: channel({
13745
+ channelName: "beta.chat.completions.stream",
13746
+ kind: "sync-stream"
13747
+ }),
13748
+ moderationsCreate: channel({
13749
+ channelName: "moderations.create",
13750
+ kind: "async"
13751
+ }),
13752
+ responsesCreate: channel({
13753
+ channelName: "responses.create",
13754
+ kind: "async"
13755
+ }),
13756
+ responsesStream: channel({
13757
+ channelName: "responses.stream",
13758
+ kind: "sync-stream"
13759
+ }),
13760
+ responsesParse: channel({
13761
+ channelName: "responses.parse",
13762
+ kind: "async"
13763
+ }),
13764
+ responsesCompact: channel({
13765
+ channelName: "responses.compact",
13766
+ kind: "async"
13767
+ })
13768
+ },
13769
+ { instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
13770
+ );
13771
+
13314
13772
  // src/wrappers/attachment-utils.ts
13315
13773
  function getExtensionFromMediaType(mediaType) {
13316
13774
  const extensionMap = {
@@ -13486,118 +13944,91 @@ function processInputAttachments(input) {
13486
13944
  return processNode(input);
13487
13945
  }
13488
13946
 
13489
- // src/instrumentation/core/channel-definitions.ts
13490
- function channel(spec) {
13491
- return spec;
13492
- }
13493
- function defineChannels(pkg, channels, options) {
13494
- const { instrumentationName } = options;
13495
- return Object.fromEntries(
13496
- Object.entries(channels).map(([key, spec]) => {
13497
- const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
13498
- if (spec.kind === "async") {
13499
- const asyncSpec = spec;
13500
- const tracingChannel2 = () => isomorph_default.newTracingChannel(
13501
- fullChannelName
13502
- );
13503
- const intercept2 = (interceptor) => {
13504
- const hook = tracingChannel2();
13505
- return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13506
- };
13507
- };
13508
- return [
13509
- key,
13510
- {
13511
- ...asyncSpec,
13512
- instrumentationName,
13513
- intercept: intercept2,
13514
- invoke: (target, thisArg, args, additional) => {
13515
- const hook = tracingChannel2();
13516
- return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13517
- },
13518
- tracingChannel: tracingChannel2,
13519
- tracePromise: (fn, context) => tracingChannel2().tracePromise(
13520
- fn,
13521
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13522
- context
13523
- )
13524
- }
13525
- ];
13947
+ // src/instrumentation/plugins/openai-span-data.ts
13948
+ var OPENAI_METADATA_KEYS = [
13949
+ "model",
13950
+ "temperature",
13951
+ "top_p",
13952
+ "max_tokens",
13953
+ "frequency_penalty",
13954
+ "presence_penalty",
13955
+ "stop",
13956
+ "response_format",
13957
+ "tools",
13958
+ "tool_choice",
13959
+ "parallel_tool_calls",
13960
+ "max_tool_calls"
13961
+ ];
13962
+ function batchMetadata(params) {
13963
+ const metadata = { provider: "openai" };
13964
+ for (const key of OPENAI_METADATA_KEYS) {
13965
+ try {
13966
+ const value = Reflect.get(params, key);
13967
+ if (value !== void 0) {
13968
+ metadata[key] = value;
13526
13969
  }
13527
- const syncSpec = spec;
13528
- const tracingChannel = () => isomorph_default.newTracingChannel(
13529
- fullChannelName
13530
- );
13531
- const intercept = (interceptor) => {
13532
- const hook = tracingChannel();
13533
- return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13534
- };
13535
- };
13536
- return [
13537
- key,
13538
- {
13539
- ...syncSpec,
13540
- instrumentationName,
13541
- intercept,
13542
- invoke: (target, thisArg, args, additional) => {
13543
- const hook = tracingChannel();
13544
- return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13545
- },
13546
- tracingChannel,
13547
- traceSync: (fn, context) => tracingChannel().traceSync(
13548
- fn,
13549
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13550
- context
13551
- )
13552
- }
13553
- ];
13554
- })
13555
- );
13970
+ } catch {
13971
+ }
13972
+ }
13973
+ return metadata;
13974
+ }
13975
+ function extractOpenAIBatchInput(endpoint, params) {
13976
+ const input = endpoint === "/v1/chat/completions" ? params.messages : params.input;
13977
+ return {
13978
+ input: processInputAttachments(input),
13979
+ metadata: batchMetadata(params)
13980
+ };
13981
+ }
13982
+ function extractOpenAIChatInput(params) {
13983
+ const { messages, ...metadata } = params;
13984
+ return {
13985
+ input: processInputAttachments(messages),
13986
+ metadata: { ...metadata, provider: "openai" }
13987
+ };
13988
+ }
13989
+ function extractOpenAIResponsesInput(params) {
13990
+ const { input, ...metadata } = params;
13991
+ return {
13992
+ input: processInputAttachments(input),
13993
+ metadata: { ...metadata, provider: "openai" }
13994
+ };
13995
+ }
13996
+ function extractOpenAIResponsesMetadata(result) {
13997
+ if (!result) {
13998
+ return void 0;
13999
+ }
14000
+ const { output: _output, usage: _usage, ...metadata } = result;
14001
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
14002
+ }
14003
+ function processImagesInOutput(output) {
14004
+ if (Array.isArray(output)) {
14005
+ return output.map(processImagesInOutput);
14006
+ }
14007
+ if (isObject(output) && output.type === "image_generation_call" && typeof output.result === "string" && output.result) {
14008
+ const fileExtension = output.output_format || "png";
14009
+ const contentType = `image/${fileExtension}`;
14010
+ const baseFilename = typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
14011
+ let binaryString;
14012
+ try {
14013
+ binaryString = atob(output.result);
14014
+ } catch {
14015
+ return output;
14016
+ }
14017
+ const bytes = new Uint8Array(binaryString.length);
14018
+ for (let i = 0; i < binaryString.length; i++) {
14019
+ bytes[i] = binaryString.charCodeAt(i);
14020
+ }
14021
+ return {
14022
+ ...output,
14023
+ result: new Attachment({
14024
+ data: new Blob([bytes], { type: contentType }),
14025
+ filename: `${baseFilename}.${fileExtension}`,
14026
+ contentType
14027
+ })
14028
+ };
14029
+ }
14030
+ return output;
13556
14031
  }
13557
-
13558
- // src/instrumentation/plugins/openai-channels.ts
13559
- var openAIChannels = defineChannels(
13560
- "openai",
13561
- {
13562
- chatCompletionsCreate: channel({
13563
- channelName: "chat.completions.create",
13564
- kind: "async"
13565
- }),
13566
- embeddingsCreate: channel({
13567
- channelName: "embeddings.create",
13568
- kind: "async"
13569
- }),
13570
- betaChatCompletionsParse: channel({
13571
- channelName: "beta.chat.completions.parse",
13572
- kind: "async"
13573
- }),
13574
- betaChatCompletionsStream: channel({
13575
- channelName: "beta.chat.completions.stream",
13576
- kind: "sync-stream"
13577
- }),
13578
- moderationsCreate: channel({
13579
- channelName: "moderations.create",
13580
- kind: "async"
13581
- }),
13582
- responsesCreate: channel({
13583
- channelName: "responses.create",
13584
- kind: "async"
13585
- }),
13586
- responsesStream: channel({
13587
- channelName: "responses.stream",
13588
- kind: "sync-stream"
13589
- }),
13590
- responsesParse: channel({
13591
- channelName: "responses.parse",
13592
- kind: "async"
13593
- }),
13594
- responsesCompact: channel({
13595
- channelName: "responses.compact",
13596
- kind: "async"
13597
- })
13598
- },
13599
- { instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
13600
- );
13601
14032
 
13602
14033
  // src/openai-utils.ts
13603
14034
  var BRAINTRUST_CACHED_STREAM_METRIC = "__braintrust_cached_metric";
@@ -13654,23 +14085,573 @@ function getCachedMetricFromHeaders(headers) {
13654
14085
  return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
13655
14086
  }
13656
14087
 
14088
+ // src/instrumentation/plugins/openai-batch-instrumentation.ts
14089
+ var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
14090
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
14091
+ "completed",
14092
+ "failed",
14093
+ "expired",
14094
+ "cancelled"
14095
+ ]);
14096
+ var pendingBatchTraces = /* @__PURE__ */ new Map();
14097
+ function read(value, key) {
14098
+ if (!isObject(value)) {
14099
+ return void 0;
14100
+ }
14101
+ try {
14102
+ return Reflect.get(value, key);
14103
+ } catch {
14104
+ return void 0;
14105
+ }
14106
+ }
14107
+ function isBatchRecordIterable(value) {
14108
+ if (value === null || typeof value !== "object" && typeof value !== "function") {
14109
+ return false;
14110
+ }
14111
+ return typeof read(value, Symbol.iterator) === "function" || typeof read(value, Symbol.asyncIterator) === "function";
14112
+ }
14113
+ function validCustomId(value) {
14114
+ return typeof value === "string" && value.length > 0 && value.length <= 64;
14115
+ }
14116
+ function logBatchInstrumentationError(context, error) {
14117
+ debugLogger.debug(`OpenAI Batch instrumentation ${context}:`, error);
14118
+ }
14119
+ async function exportParent(parent) {
14120
+ if ("toStr" in parent && typeof parent.toStr === "function") {
14121
+ return parent.toStr();
14122
+ }
14123
+ if ("export" in parent && typeof parent.export === "function") {
14124
+ return await parent.export();
14125
+ }
14126
+ return void 0;
14127
+ }
14128
+ async function deterministicDigest(namespace, ...parts) {
14129
+ const encoded = new TextEncoder().encode(
14130
+ [namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
14131
+ );
14132
+ return new Uint8Array(
14133
+ await globalThis.crypto.subtle.digest("SHA-256", encoded)
14134
+ );
14135
+ }
14136
+ function digestHex(bytes, length) {
14137
+ return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
14138
+ }
14139
+ function digestUuid(bytes) {
14140
+ const hex = digestHex(bytes, 16);
14141
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
14142
+ }
14143
+ async function batchSpanIds(inputFileId) {
14144
+ const [row, span, root] = await Promise.all([
14145
+ deterministicDigest("openai:batch:row", inputFileId),
14146
+ deterministicDigest("openai:batch:span", inputFileId),
14147
+ deterministicDigest("openai:batch:root", inputFileId)
14148
+ ]);
14149
+ return {
14150
+ rowId: digestUuid(row),
14151
+ spanId: digestHex(span, 8),
14152
+ rootSpanId: digestHex(root, 16)
14153
+ };
14154
+ }
14155
+ async function childSpanIds(inputFileId, customId) {
14156
+ const [row, span] = await Promise.all([
14157
+ deterministicDigest("openai:batch:child:row", inputFileId, customId),
14158
+ deterministicDigest("openai:batch:child:span", inputFileId, customId)
14159
+ ]);
14160
+ return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
14161
+ }
14162
+ async function startBatchSpan(context) {
14163
+ const ids = await batchSpanIds(context.inputFileId);
14164
+ const parent = SpanComponentsV4.fromStr(context.parent);
14165
+ const hasParentSpan = Boolean(
14166
+ parent.data.row_id && parent.data.span_id && parent.data.root_span_id
14167
+ );
14168
+ return withCurrent(
14169
+ NOOP_SPAN,
14170
+ () => _internalStartSpanWithInitialMergeAndParentSpanIds(
14171
+ withSpanInstrumentationName(
14172
+ {
14173
+ name: "openai.batch",
14174
+ type: "task" /* TASK */,
14175
+ parent: context.parent,
14176
+ ...!hasParentSpan ? {
14177
+ parentSpanIds: {
14178
+ parentSpanIds: [],
14179
+ rootSpanId: ids.rootSpanId
14180
+ }
14181
+ } : {},
14182
+ spanId: ids.spanId,
14183
+ startTime: context.taskStartTime,
14184
+ event: {
14185
+ id: ids.rowId,
14186
+ metadata: {
14187
+ endpoint: context.endpoint,
14188
+ input_file_id: context.inputFileId,
14189
+ provider: "openai"
14190
+ }
14191
+ }
14192
+ },
14193
+ INSTRUMENTATION_NAMES.OPENAI
14194
+ )
14195
+ )
14196
+ );
14197
+ }
14198
+ async function startBatchChild(context, taskParent, input) {
14199
+ const ids = await childSpanIds(context.inputFileId, input.customId);
14200
+ return withCurrent(
14201
+ NOOP_SPAN,
14202
+ () => _internalStartSpanWithInitialMerge(
14203
+ withSpanInstrumentationName(
14204
+ {
14205
+ name: context.endpoint === "/v1/chat/completions" ? "Chat Completion" : "openai.responses.create",
14206
+ type: "llm" /* LLM */,
14207
+ parent: taskParent,
14208
+ spanId: ids.spanId,
14209
+ startTime: context.childStartTime,
14210
+ event: {
14211
+ id: ids.rowId,
14212
+ ...input.spanData?.input !== void 0 ? { input: input.spanData.input } : {},
14213
+ metadata: {
14214
+ ...input.spanData?.metadata,
14215
+ custom_id: input.customId,
14216
+ provider: "openai"
14217
+ }
14218
+ }
14219
+ },
14220
+ INSTRUMENTATION_NAMES.OPENAI
14221
+ )
14222
+ )
14223
+ );
14224
+ }
14225
+ async function* jsonlRecords(file, onIssue = () => {
14226
+ }) {
14227
+ const resolvedFile = await file;
14228
+ if (typeof resolvedFile === "string") {
14229
+ for (const line of resolvedFile.split("\n")) {
14230
+ if (!line.trim()) {
14231
+ continue;
14232
+ }
14233
+ try {
14234
+ yield JSON.parse(line.replace(/\r$/, ""));
14235
+ } catch (error) {
14236
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14237
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14238
+ }
14239
+ }
14240
+ return;
14241
+ }
14242
+ const body = read(resolvedFile, "body");
14243
+ const getReader = read(body, "getReader");
14244
+ if (isObject(body) && typeof getReader === "function") {
14245
+ let reader;
14246
+ try {
14247
+ reader = Reflect.apply(getReader, body, []);
14248
+ const decoder2 = new TextDecoder();
14249
+ let pending = "";
14250
+ while (true) {
14251
+ const readChunk = read(reader, "read");
14252
+ if (typeof readChunk !== "function") {
14253
+ throw new Error("Response body stream has no read method");
14254
+ }
14255
+ const chunk = await Reflect.apply(readChunk, reader, []);
14256
+ if (!isObject(chunk)) {
14257
+ throw new Error("Response body stream returned an invalid chunk");
14258
+ }
14259
+ if (chunk.done === true) {
14260
+ pending += decoder2.decode();
14261
+ break;
14262
+ }
14263
+ if (!(chunk.value instanceof Uint8Array)) {
14264
+ throw new Error("Response body stream returned a non-byte chunk");
14265
+ }
14266
+ pending += decoder2.decode(chunk.value, { stream: true });
14267
+ let newline = pending.indexOf("\n");
14268
+ while (newline !== -1) {
14269
+ const line = pending.slice(0, newline).replace(/\r$/, "");
14270
+ pending = pending.slice(newline + 1);
14271
+ if (line.trim()) {
14272
+ try {
14273
+ yield JSON.parse(line);
14274
+ } catch (error) {
14275
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14276
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14277
+ }
14278
+ }
14279
+ newline = pending.indexOf("\n");
14280
+ }
14281
+ }
14282
+ if (pending.trim()) {
14283
+ try {
14284
+ yield JSON.parse(pending.replace(/\r$/, ""));
14285
+ } catch (error) {
14286
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14287
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14288
+ }
14289
+ }
14290
+ } catch (error) {
14291
+ logBatchInstrumentationError("could not read JSONL response body", error);
14292
+ onIssue(new Error("OpenAI Batch response body could not be read"));
14293
+ } finally {
14294
+ const releaseLock = read(reader, "releaseLock");
14295
+ if (typeof releaseLock === "function") {
14296
+ try {
14297
+ Reflect.apply(releaseLock, reader, []);
14298
+ } catch (error) {
14299
+ logBatchInstrumentationError(
14300
+ "could not release stream reader",
14301
+ error
14302
+ );
14303
+ }
14304
+ }
14305
+ }
14306
+ return;
14307
+ }
14308
+ if (isBatchRecordIterable(resolvedFile)) {
14309
+ for await (const record of resolvedFile) {
14310
+ yield record;
14311
+ }
14312
+ return;
14313
+ }
14314
+ logBatchInstrumentationError("skipped invalid JSONL source", resolvedFile);
14315
+ onIssue(new Error("OpenAI Batch file source is invalid"));
14316
+ }
14317
+ async function readBatchInputs(file) {
14318
+ const inputs = /* @__PURE__ */ new Map();
14319
+ const issues = [];
14320
+ let endpoint;
14321
+ try {
14322
+ for await (const value of jsonlRecords(
14323
+ file,
14324
+ (issue) => issues.push(issue)
14325
+ )) {
14326
+ const customId = read(value, "custom_id");
14327
+ const url = read(value, "url");
14328
+ const body = read(value, "body");
14329
+ if (!validCustomId(customId) || inputs.has(customId) || read(value, "method") !== "POST" || typeof url !== "string" || !SUPPORTED_ENDPOINTS.has(url) || endpoint !== void 0 && endpoint !== url || !isObject(body)) {
14330
+ issues.push(new Error("OpenAI Batch input contains an invalid record"));
14331
+ continue;
14332
+ }
14333
+ endpoint = url;
14334
+ let spanData;
14335
+ try {
14336
+ spanData = extractOpenAIBatchInput(url, body);
14337
+ } catch (error) {
14338
+ logBatchInstrumentationError("could not extract batch input", error);
14339
+ }
14340
+ inputs.set(customId, { customId, spanData });
14341
+ }
14342
+ } catch (error) {
14343
+ logBatchInstrumentationError("could not process input file", error);
14344
+ issues.push(new Error("OpenAI Batch input file could not be processed"));
14345
+ }
14346
+ if (!endpoint || inputs.size === 0) {
14347
+ issues.push(new Error("OpenAI Batch input contains no supported records"));
14348
+ }
14349
+ return { endpoint, inputs, issues };
14350
+ }
14351
+ async function writePendingSpans(trace, endTime) {
14352
+ const task = await startBatchSpan(trace.context);
14353
+ const taskParent = await task.export();
14354
+ for (const input of trace.inputs.values()) {
14355
+ try {
14356
+ const child = await startBatchChild(trace.context, taskParent, input);
14357
+ if (endTime !== void 0) {
14358
+ child.end({ endTime });
14359
+ }
14360
+ } catch (error) {
14361
+ logBatchInstrumentationError("could not write batch request span", error);
14362
+ }
14363
+ }
14364
+ if (endTime !== void 0) {
14365
+ if (trace.status && trace.status !== "completed") {
14366
+ task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14367
+ }
14368
+ task.end({ endTime });
14369
+ }
14370
+ }
14371
+ var interceptOpenAIFilesCreateTraced = async (target, thisArg, args) => {
14372
+ const startTime = getCurrentUnixTimestamp();
14373
+ const inputPromise = readBatchInputs(args[0].inputFileContent);
14374
+ const parentPromise = exportParent(args[0].parent);
14375
+ const file = await Reflect.apply(target, thisArg, args);
14376
+ try {
14377
+ const inputFileId = read(file, "id");
14378
+ const [inputData, exportedParent2] = await Promise.all([
14379
+ inputPromise,
14380
+ parentPromise
14381
+ ]);
14382
+ if (typeof inputFileId !== "string" || !exportedParent2 || !inputData.endpoint || inputData.issues.length > 0) {
14383
+ if (inputData.issues[0]) {
14384
+ logBatchInstrumentationError(
14385
+ "skipped invalid input file",
14386
+ inputData.issues[0]
14387
+ );
14388
+ }
14389
+ return file;
14390
+ }
14391
+ const trace = {
14392
+ context: {
14393
+ inputFileId,
14394
+ endpoint: inputData.endpoint,
14395
+ parent: exportedParent2,
14396
+ taskStartTime: startTime,
14397
+ childStartTime: startTime
14398
+ },
14399
+ inputs: inputData.inputs
14400
+ };
14401
+ pendingBatchTraces.set(inputFileId, trace);
14402
+ await writePendingSpans(trace);
14403
+ } catch (error) {
14404
+ logBatchInstrumentationError("could not start batch spans", error);
14405
+ }
14406
+ return file;
14407
+ };
14408
+ function validTimestamp(value) {
14409
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
14410
+ }
14411
+ function terminalEndTime(batch, startTime) {
14412
+ let timestamp;
14413
+ switch (batch.status) {
14414
+ case "completed":
14415
+ timestamp = batch.completed_at;
14416
+ break;
14417
+ case "failed":
14418
+ timestamp = batch.failed_at;
14419
+ break;
14420
+ case "expired":
14421
+ timestamp = batch.expired_at;
14422
+ break;
14423
+ default:
14424
+ timestamp = batch.cancelled_at;
14425
+ }
14426
+ return validTimestamp(timestamp) ? Math.max(timestamp, startTime) : Math.max(getCurrentUnixTimestamp(), startTime);
14427
+ }
14428
+ async function updateBatchTimestamps(batch) {
14429
+ const trace = pendingBatchTraces.get(batch.input_file_id);
14430
+ if (!trace || trace.context.endpoint !== batch.endpoint) {
14431
+ return;
14432
+ }
14433
+ if (validTimestamp(batch.created_at)) {
14434
+ trace.context.taskStartTime = batch.created_at;
14435
+ }
14436
+ trace.context.childStartTime = validTimestamp(batch.in_progress_at) ? Math.max(batch.in_progress_at, trace.context.taskStartTime) : trace.context.taskStartTime;
14437
+ trace.status = batch.status;
14438
+ if (TERMINAL_STATUSES.has(batch.status)) {
14439
+ trace.endTime = terminalEndTime(batch, trace.context.childStartTime);
14440
+ }
14441
+ await writePendingSpans(trace, trace.endTime);
14442
+ }
14443
+ var interceptOpenAIBatchesRetrieveTraced = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (batch) => {
14444
+ try {
14445
+ await updateBatchTimestamps(batch);
14446
+ } catch (error) {
14447
+ logBatchInstrumentationError("could not update batch timestamps", error);
14448
+ }
14449
+ return batch;
14450
+ });
14451
+ function errorFromResult(result) {
14452
+ const error = read(result.value, "error");
14453
+ if (isObject(error)) {
14454
+ const message = read(error, "message");
14455
+ return new Error(
14456
+ typeof message === "string" ? message : "OpenAI Batch request failed"
14457
+ );
14458
+ }
14459
+ const response = read(result.value, "response");
14460
+ const statusCode = read(response, "status_code");
14461
+ if (result.source === "error" || typeof statusCode === "number" && (statusCode < 200 || statusCode >= 300)) {
14462
+ const message = read(read(read(response, "body"), "error"), "message");
14463
+ return new Error(
14464
+ typeof message === "string" ? message : "OpenAI Batch request failed"
14465
+ );
14466
+ }
14467
+ return void 0;
14468
+ }
14469
+ async function completeBatchResult(context, taskParent, endTime, input, result) {
14470
+ const child = await startBatchChild(context, taskParent, input);
14471
+ try {
14472
+ const resultError = errorFromResult(result);
14473
+ const responseBody = read(read(result.value, "response"), "body");
14474
+ if (resultError) {
14475
+ child.log({ error: resultError });
14476
+ } else if (isObject(responseBody)) {
14477
+ const model = read(responseBody, "model");
14478
+ child.log({
14479
+ output: context.endpoint === "/v1/chat/completions" ? read(responseBody, "choices") : processImagesInOutput(read(responseBody, "output")),
14480
+ ...typeof model === "string" ? { metadata: { model } } : {},
14481
+ metrics: parseMetricsFromUsage(read(responseBody, "usage"))
14482
+ });
14483
+ } else {
14484
+ child.log({ error: new Error("OpenAI Batch response body is missing") });
14485
+ }
14486
+ } catch (error) {
14487
+ child.log({ error });
14488
+ } finally {
14489
+ child.end({ endTime });
14490
+ }
14491
+ }
14492
+ async function completeResultFile({
14493
+ context,
14494
+ endTime,
14495
+ file,
14496
+ inputs,
14497
+ issues,
14498
+ seen,
14499
+ source,
14500
+ taskParent
14501
+ }) {
14502
+ if (file === void 0) {
14503
+ return;
14504
+ }
14505
+ for await (const value of jsonlRecords(file, (issue) => issues.push(issue))) {
14506
+ const customId = read(value, "custom_id");
14507
+ if (!validCustomId(customId) || !isObject(value)) {
14508
+ issues.push(
14509
+ new Error("OpenAI Batch result is missing a valid custom_id")
14510
+ );
14511
+ continue;
14512
+ }
14513
+ if (seen.has(customId)) {
14514
+ issues.push(new Error("OpenAI Batch result contains a duplicate"));
14515
+ continue;
14516
+ }
14517
+ const input = inputs.get(customId);
14518
+ if (!input) {
14519
+ issues.push(
14520
+ new Error("OpenAI Batch result does not match an input record")
14521
+ );
14522
+ continue;
14523
+ }
14524
+ seen.add(customId);
14525
+ await completeBatchResult(context, taskParent, endTime, input, {
14526
+ value,
14527
+ source
14528
+ });
14529
+ }
14530
+ }
14531
+ function sameInputs(first, second) {
14532
+ return first.size === second.size && [...first.keys()].every((customId) => second.has(customId));
14533
+ }
14534
+ async function contextForCompletion(inputFileId, inputData) {
14535
+ if (!inputData.endpoint || inputData.issues.length > 0) {
14536
+ return void 0;
14537
+ }
14538
+ const existing = pendingBatchTraces.get(inputFileId);
14539
+ if (existing) {
14540
+ if (existing.context.endpoint !== inputData.endpoint || !sameInputs(existing.inputs, inputData.inputs)) {
14541
+ return void 0;
14542
+ }
14543
+ return { ...existing, inputs: inputData.inputs };
14544
+ }
14545
+ const parent = await exportParent(getSpanParentObject());
14546
+ if (!parent) {
14547
+ return void 0;
14548
+ }
14549
+ const startTime = getCurrentUnixTimestamp();
14550
+ return {
14551
+ context: {
14552
+ inputFileId,
14553
+ endpoint: inputData.endpoint,
14554
+ parent,
14555
+ taskStartTime: startTime,
14556
+ childStartTime: startTime
14557
+ },
14558
+ inputs: inputData.inputs
14559
+ };
14560
+ }
14561
+ async function completeBatch(args) {
14562
+ const inputData = await readBatchInputs(args.inputFileContent);
14563
+ const trace = await contextForCompletion(args.inputFileId, inputData);
14564
+ if (!trace) {
14565
+ logBatchInstrumentationError(
14566
+ "left batch spans pending",
14567
+ inputData.issues[0] ?? new Error("OpenAI Batch input does not match")
14568
+ );
14569
+ return;
14570
+ }
14571
+ const endTime = trace.endTime ?? getCurrentUnixTimestamp();
14572
+ const task = await startBatchSpan(trace.context);
14573
+ const taskParent = await task.export();
14574
+ const issues = [];
14575
+ const seen = /* @__PURE__ */ new Set();
14576
+ await Promise.all([
14577
+ completeResultFile({
14578
+ context: trace.context,
14579
+ endTime,
14580
+ file: args.outputFileContent,
14581
+ inputs: trace.inputs,
14582
+ issues,
14583
+ seen,
14584
+ source: "output",
14585
+ taskParent
14586
+ }),
14587
+ completeResultFile({
14588
+ context: trace.context,
14589
+ endTime,
14590
+ file: args.errorFileContent,
14591
+ inputs: trace.inputs,
14592
+ issues,
14593
+ seen,
14594
+ source: "error",
14595
+ taskParent
14596
+ })
14597
+ ]);
14598
+ if (issues.length > 0) {
14599
+ logBatchInstrumentationError("left batch spans pending", issues[0]);
14600
+ return;
14601
+ }
14602
+ const missing = [...trace.inputs.values()].filter(
14603
+ ({ customId }) => !seen.has(customId)
14604
+ );
14605
+ if (!trace.status || trace.status === "completed") {
14606
+ if (missing.length > 0) {
14607
+ logBatchInstrumentationError(
14608
+ "left batch spans pending",
14609
+ new Error("OpenAI Batch result files are incomplete")
14610
+ );
14611
+ return;
14612
+ }
14613
+ } else {
14614
+ for (const input of missing) {
14615
+ const child = await startBatchChild(trace.context, taskParent, input);
14616
+ child.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14617
+ child.end({ endTime });
14618
+ }
14619
+ task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14620
+ }
14621
+ task.end({ endTime });
14622
+ pendingBatchTraces.delete(args.inputFileId);
14623
+ }
14624
+ var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (result) => {
14625
+ try {
14626
+ await completeBatch(args[0]);
14627
+ } catch (error) {
14628
+ logBatchInstrumentationError("could not complete batch", error);
14629
+ }
14630
+ return result;
14631
+ });
14632
+
13657
14633
  // src/instrumentation/plugins/openai-plugin.ts
13658
14634
  var OpenAIPlugin = class extends BasePlugin {
13659
14635
  constructor() {
13660
14636
  super();
13661
14637
  }
13662
14638
  onEnable() {
14639
+ this.unsubscribers.push(
14640
+ openAIChannels.filesCreateTraced.intercept(
14641
+ interceptOpenAIFilesCreateTraced
14642
+ ),
14643
+ openAIChannels.batchesRetrieveTraced.intercept(
14644
+ interceptOpenAIBatchesRetrieveTraced
14645
+ ),
14646
+ openAIChannels.batchesCompleteTrace.intercept(
14647
+ interceptOpenAIBatchTraceComplete
14648
+ )
14649
+ );
13663
14650
  this.unsubscribers.push(
13664
14651
  traceStreamingChannel(openAIChannels.chatCompletionsCreate, {
13665
14652
  name: "Chat Completion",
13666
14653
  type: "llm" /* LLM */,
13667
- extractInput: ([params]) => {
13668
- const { messages, ...metadata } = params;
13669
- return {
13670
- input: processInputAttachments(messages),
13671
- metadata: { ...metadata, provider: "openai" }
13672
- };
13673
- },
14654
+ extractInput: ([params]) => extractOpenAIChatInput(params),
13674
14655
  extractOutput: (result) => {
13675
14656
  return result?.choices;
13676
14657
  },
@@ -13716,13 +14697,7 @@ var OpenAIPlugin = class extends BasePlugin {
13716
14697
  traceStreamingChannel(openAIChannels.betaChatCompletionsParse, {
13717
14698
  name: "Chat Completion",
13718
14699
  type: "llm" /* LLM */,
13719
- extractInput: ([params]) => {
13720
- const { messages, ...metadata } = params;
13721
- return {
13722
- input: processInputAttachments(messages),
13723
- metadata: { ...metadata, provider: "openai" }
13724
- };
13725
- },
14700
+ extractInput: ([params]) => extractOpenAIChatInput(params),
13726
14701
  extractOutput: (result) => {
13727
14702
  return result?.choices;
13728
14703
  },
@@ -13744,13 +14719,7 @@ var OpenAIPlugin = class extends BasePlugin {
13744
14719
  traceSyncStreamChannel(openAIChannels.betaChatCompletionsStream, {
13745
14720
  name: "Chat Completion",
13746
14721
  type: "llm" /* LLM */,
13747
- extractInput: ([params]) => {
13748
- const { messages, ...metadata } = params;
13749
- return {
13750
- input: processInputAttachments(messages),
13751
- metadata: { ...metadata, provider: "openai" }
13752
- };
13753
- }
14722
+ extractInput: ([params]) => extractOpenAIChatInput(params)
13754
14723
  })
13755
14724
  );
13756
14725
  this.unsubscribers.push(
@@ -13780,23 +14749,11 @@ var OpenAIPlugin = class extends BasePlugin {
13780
14749
  traceStreamingChannel(openAIChannels.responsesCreate, {
13781
14750
  name: "openai.responses.create",
13782
14751
  type: "llm" /* LLM */,
13783
- extractInput: ([params]) => {
13784
- const { input, ...metadata } = params;
13785
- return {
13786
- input: processInputAttachments(input),
13787
- metadata: { ...metadata, provider: "openai" }
13788
- };
13789
- },
14752
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13790
14753
  extractOutput: (result) => {
13791
14754
  return processImagesInOutput(result?.output);
13792
14755
  },
13793
- extractMetadata: (result) => {
13794
- if (!result) {
13795
- return void 0;
13796
- }
13797
- const { output: _output, usage: _usage, ...metadata } = result;
13798
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13799
- },
14756
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13800
14757
  extractMetrics: (result, startTime, endEvent) => {
13801
14758
  const metrics = withCachedMetric(
13802
14759
  parseMetricsFromUsage(result?.usage),
@@ -13815,13 +14772,7 @@ var OpenAIPlugin = class extends BasePlugin {
13815
14772
  traceSyncStreamChannel(openAIChannels.responsesStream, {
13816
14773
  name: "openai.responses.create",
13817
14774
  type: "llm" /* LLM */,
13818
- extractInput: ([params]) => {
13819
- const { input, ...metadata } = params;
13820
- return {
13821
- input: processInputAttachments(input),
13822
- metadata: { ...metadata, provider: "openai" }
13823
- };
13824
- },
14775
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13825
14776
  extractFromEvent: (event) => {
13826
14777
  if (event.type !== "response.completed" || !event.response) {
13827
14778
  return {};
@@ -13844,23 +14795,11 @@ var OpenAIPlugin = class extends BasePlugin {
13844
14795
  traceStreamingChannel(openAIChannels.responsesParse, {
13845
14796
  name: "openai.responses.parse",
13846
14797
  type: "llm" /* LLM */,
13847
- extractInput: ([params]) => {
13848
- const { input, ...metadata } = params;
13849
- return {
13850
- input: processInputAttachments(input),
13851
- metadata: { ...metadata, provider: "openai" }
13852
- };
13853
- },
14798
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13854
14799
  extractOutput: (result) => {
13855
14800
  return processImagesInOutput(result?.output);
13856
14801
  },
13857
- extractMetadata: (result) => {
13858
- if (!result) {
13859
- return void 0;
13860
- }
13861
- const { output: _output, usage: _usage, ...metadata } = result;
13862
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13863
- },
14802
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13864
14803
  extractMetrics: (result, startTime, endEvent) => {
13865
14804
  const metrics = withCachedMetric(
13866
14805
  parseMetricsFromUsage(result?.usage),
@@ -13879,23 +14818,11 @@ var OpenAIPlugin = class extends BasePlugin {
13879
14818
  traceAsyncChannel(openAIChannels.responsesCompact, {
13880
14819
  name: "openai.responses.compact",
13881
14820
  type: "llm" /* LLM */,
13882
- extractInput: ([params]) => {
13883
- const { input, ...metadata } = params;
13884
- return {
13885
- input: processInputAttachments(input),
13886
- metadata: { ...metadata, provider: "openai" }
13887
- };
13888
- },
14821
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13889
14822
  extractOutput: (result) => {
13890
14823
  return processImagesInOutput(result?.output);
13891
14824
  },
13892
- extractMetadata: (result) => {
13893
- if (!result) {
13894
- return void 0;
13895
- }
13896
- const { output: _output, usage: _usage, ...metadata } = result;
13897
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13898
- },
14825
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13899
14826
  extractMetrics: (result, startTime, endEvent) => {
13900
14827
  const metrics = withCachedMetric(
13901
14828
  parseMetricsFromUsage(result?.usage),
@@ -13951,35 +14878,6 @@ function withCachedMetric(metrics, result, endEvent) {
13951
14878
  cached
13952
14879
  };
13953
14880
  }
13954
- function processImagesInOutput(output) {
13955
- if (Array.isArray(output)) {
13956
- return output.map(processImagesInOutput);
13957
- }
13958
- if (isObject(output)) {
13959
- if (output.type === "image_generation_call" && output.result && typeof output.result === "string") {
13960
- const fileExtension = output.output_format || "png";
13961
- const contentType = `image/${fileExtension}`;
13962
- const baseFilename = output.revised_prompt && typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
13963
- const filename = `${baseFilename}.${fileExtension}`;
13964
- const binaryString = atob(output.result);
13965
- const bytes = new Uint8Array(binaryString.length);
13966
- for (let i = 0; i < binaryString.length; i++) {
13967
- bytes[i] = binaryString.charCodeAt(i);
13968
- }
13969
- const blob = new Blob([bytes], { type: contentType });
13970
- const attachment = new Attachment({
13971
- data: blob,
13972
- filename,
13973
- contentType
13974
- });
13975
- return {
13976
- ...output,
13977
- result: attachment
13978
- };
13979
- }
13980
- }
13981
- return output;
13982
- }
13983
14881
  function mergeLogprobTokens(existing, incoming) {
13984
14882
  if (incoming === void 0) {
13985
14883
  return existing;
@@ -14010,13 +14908,33 @@ function aggregateChatLogprobs(existing, incoming) {
14010
14908
  }
14011
14909
  return aggregated;
14012
14910
  }
14911
+ function createAggregatedChatChoice(index) {
14912
+ return {
14913
+ index,
14914
+ role: void 0,
14915
+ content: void 0,
14916
+ refusal: void 0,
14917
+ toolCallsByIndex: /* @__PURE__ */ new Map(),
14918
+ logprobs: void 0,
14919
+ finish_reason: void 0
14920
+ };
14921
+ }
14922
+ function toChatChoice(choice) {
14923
+ const toolCalls2 = Array.from(choice.toolCallsByIndex.entries()).sort(([left], [right]) => left - right).map(([, toolCall]) => toolCall);
14924
+ return {
14925
+ index: choice.index,
14926
+ message: {
14927
+ role: choice.role,
14928
+ content: choice.content,
14929
+ ...choice.refusal !== void 0 ? { refusal: choice.refusal } : {},
14930
+ tool_calls: toolCalls2.length > 0 ? toolCalls2 : void 0
14931
+ },
14932
+ logprobs: choice.logprobs ?? null,
14933
+ finish_reason: choice.finish_reason
14934
+ };
14935
+ }
14013
14936
  function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
14014
- let role = void 0;
14015
- let content = void 0;
14016
- let refusal = void 0;
14017
- let tool_calls = void 0;
14018
- let logprobs = void 0;
14019
- let finish_reason = void 0;
14937
+ const choicesByIndex = /* @__PURE__ */ new Map();
14020
14938
  let metrics = {};
14021
14939
  for (const chunk of chunks) {
14022
14940
  if (chunk.usage) {
@@ -14025,62 +14943,75 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
14025
14943
  ...parseMetricsFromUsage(chunk.usage)
14026
14944
  };
14027
14945
  }
14028
- const choice = chunk.choices?.[0];
14029
- if (!choice) {
14946
+ const choices = chunk.choices;
14947
+ if (!choices?.length) {
14030
14948
  continue;
14031
14949
  }
14032
- if (choice.finish_reason) {
14033
- finish_reason = choice.finish_reason;
14034
- }
14035
- logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
14036
- const delta = choice.delta;
14037
- if (!delta) {
14038
- continue;
14039
- }
14040
- if (delta.finish_reason) {
14041
- finish_reason = delta.finish_reason;
14042
- }
14043
- if (!role && delta.role) {
14044
- role = delta.role;
14045
- }
14046
- if (delta.content) {
14047
- content = (content || "") + delta.content;
14048
- }
14049
- if (delta.refusal) {
14050
- refusal = (refusal || "") + delta.refusal;
14051
- }
14052
- if (delta.tool_calls) {
14053
- const toolDelta = delta.tool_calls[0];
14054
- if (!tool_calls || toolDelta.id && tool_calls[tool_calls.length - 1].id !== toolDelta.id) {
14055
- tool_calls = [
14056
- ...tool_calls || [],
14057
- {
14058
- id: toolDelta.id,
14059
- type: toolDelta.type,
14060
- function: toolDelta.function
14950
+ for (const choice of choices) {
14951
+ const choiceIndex = choice.index;
14952
+ let aggregatedChoice = choicesByIndex.get(choiceIndex);
14953
+ if (!aggregatedChoice) {
14954
+ aggregatedChoice = createAggregatedChatChoice(choiceIndex);
14955
+ choicesByIndex.set(choiceIndex, aggregatedChoice);
14956
+ }
14957
+ if (choice.finish_reason) {
14958
+ aggregatedChoice.finish_reason = choice.finish_reason;
14959
+ }
14960
+ aggregatedChoice.logprobs = aggregateChatLogprobs(
14961
+ aggregatedChoice.logprobs,
14962
+ choice.logprobs
14963
+ );
14964
+ const delta = choice.delta;
14965
+ if (!delta) {
14966
+ continue;
14967
+ }
14968
+ if (delta.finish_reason) {
14969
+ aggregatedChoice.finish_reason = delta.finish_reason;
14970
+ }
14971
+ if (!aggregatedChoice.role && delta.role) {
14972
+ aggregatedChoice.role = delta.role;
14973
+ }
14974
+ if (delta.content) {
14975
+ aggregatedChoice.content = (aggregatedChoice.content || "") + delta.content;
14976
+ }
14977
+ if (delta.refusal) {
14978
+ aggregatedChoice.refusal = (aggregatedChoice.refusal || "") + delta.refusal;
14979
+ }
14980
+ if (delta.tool_calls) {
14981
+ for (const toolDelta of delta.tool_calls) {
14982
+ let aggregatedToolCall = aggregatedChoice.toolCallsByIndex.get(
14983
+ toolDelta.index
14984
+ );
14985
+ if (!aggregatedToolCall) {
14986
+ aggregatedToolCall = {
14987
+ function: { arguments: "" }
14988
+ };
14989
+ aggregatedChoice.toolCallsByIndex.set(
14990
+ toolDelta.index,
14991
+ aggregatedToolCall
14992
+ );
14061
14993
  }
14062
- ];
14063
- } else {
14064
- tool_calls[tool_calls.length - 1].function.arguments += toolDelta.function.arguments;
14994
+ if (toolDelta.id !== void 0) {
14995
+ aggregatedToolCall.id = toolDelta.id;
14996
+ }
14997
+ if (toolDelta.type !== void 0) {
14998
+ aggregatedToolCall.type = toolDelta.type;
14999
+ }
15000
+ if (toolDelta.function?.name !== void 0) {
15001
+ aggregatedToolCall.function.name = toolDelta.function.name;
15002
+ }
15003
+ if (toolDelta.function?.arguments !== void 0) {
15004
+ aggregatedToolCall.function.arguments += toolDelta.function.arguments;
15005
+ }
15006
+ }
14065
15007
  }
14066
15008
  }
14067
15009
  }
14068
15010
  metrics = withCachedMetric(metrics, streamResult, endEvent);
15011
+ const output = Array.from(choicesByIndex.values()).sort((left, right) => left.index - right.index).map(toChatChoice);
14069
15012
  return {
14070
15013
  metrics,
14071
- output: [
14072
- {
14073
- index: 0,
14074
- message: {
14075
- role,
14076
- content,
14077
- ...refusal !== void 0 ? { refusal } : {},
14078
- tool_calls
14079
- },
14080
- logprobs: logprobs ?? null,
14081
- finish_reason
14082
- }
14083
- ]
15014
+ output: output.length > 0 ? output : [toChatChoice(createAggregatedChatChoice(0))]
14084
15015
  };
14085
15016
  }
14086
15017
  function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
@@ -15416,6 +16347,12 @@ function parseMetricsFromUsage2(usage) {
15416
16347
  }
15417
16348
  }
15418
16349
  }
16350
+ if (isObject(usage.output_tokens_details)) {
16351
+ const thinkingTokens = usage.output_tokens_details.thinking_tokens;
16352
+ if (typeof thinkingTokens === "number") {
16353
+ metrics.completion_reasoning_tokens = thinkingTokens;
16354
+ }
16355
+ }
15419
16356
  if (isObject(usage.server_tool_use)) {
15420
16357
  for (const [name, value] of Object.entries(usage.server_tool_use)) {
15421
16358
  if (typeof value === "number") {
@@ -16372,7 +17309,6 @@ function endHarnessTurn(parent) {
16372
17309
  function braintrustAISDKTelemetry() {
16373
17310
  const operations = /* @__PURE__ */ new Map();
16374
17311
  const operationKeysByCallId = /* @__PURE__ */ new Map();
16375
- const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
16376
17312
  const modelSpans = /* @__PURE__ */ new Map();
16377
17313
  const objectSpans = /* @__PURE__ */ new Map();
16378
17314
  const embedSpans = /* @__PURE__ */ new Map();
@@ -16415,9 +17351,6 @@ function braintrustAISDKTelemetry() {
16415
17351
  return;
16416
17352
  }
16417
17353
  operations.delete(operationKey);
16418
- if (workflowOperationKeyStore.getStore() === operationKey) {
16419
- workflowOperationKeyStore.enterWith(void 0);
16420
- }
16421
17354
  const keys = operationKeysByCallId.get(state.callId);
16422
17355
  if (!keys) {
16423
17356
  return;
@@ -16465,14 +17398,7 @@ function braintrustAISDKTelemetry() {
16465
17398
  return key;
16466
17399
  }
16467
17400
  }
16468
- const workflowOperationKey = workflowOperationKeyStore.getStore();
16469
- if (workflowOperationKey && keys.includes(workflowOperationKey)) {
16470
- return workflowOperationKey;
16471
- }
16472
- if (callId === "workflow-agent") {
16473
- return void 0;
16474
- }
16475
- return mode === "finish" ? keys[0] : keys[keys.length - 1];
17401
+ return callId === "workflow-agent" || mode === "active" ? keys[keys.length - 1] : keys[0];
16476
17402
  };
16477
17403
  const operationKeyFromEvent = (event, mode = "active") => {
16478
17404
  const explicit = explicitOperationKey(event);
@@ -16486,17 +17412,13 @@ function braintrustAISDKTelemetry() {
16486
17412
  if (operationKey) {
16487
17413
  return operationKey;
16488
17414
  }
16489
- const workflowOperationKey2 = workflowOperationKeyStore.getStore();
16490
- if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
16491
- return workflowOperationKey2;
17415
+ const workflowAgentKeys2 = operationKeysByCallId.get("workflow-agent");
17416
+ if (workflowAgentKeys2?.length) {
17417
+ return workflowAgentKeys2[workflowAgentKeys2.length - 1];
16492
17418
  }
16493
17419
  return callId === "workflow-agent" ? void 0 : callId;
16494
17420
  }
16495
17421
  }
16496
- const workflowOperationKey = workflowOperationKeyStore.getStore();
16497
- if (workflowOperationKey && operations.has(workflowOperationKey)) {
16498
- return workflowOperationKey;
16499
- }
16500
17422
  const wrapperSpan = currentWorkflowAgentWrapperSpan();
16501
17423
  if (wrapperSpan?.spanId) {
16502
17424
  for (const [operationKey, state] of operations) {
@@ -16506,8 +17428,8 @@ function braintrustAISDKTelemetry() {
16506
17428
  }
16507
17429
  }
16508
17430
  const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
16509
- if (workflowAgentKeys?.length === 1) {
16510
- return workflowAgentKeys[0];
17431
+ if (workflowAgentKeys?.length) {
17432
+ return workflowAgentKeys[workflowAgentKeys.length - 1];
16511
17433
  }
16512
17434
  if (operations.size === 1) {
16513
17435
  return operations.keys().next().value;
@@ -16710,9 +17632,6 @@ function braintrustAISDKTelemetry() {
16710
17632
  if (!ownsSpan) {
16711
17633
  return;
16712
17634
  }
16713
- if (workflowAgent) {
16714
- workflowOperationKeyStore.enterWith(operationKey);
16715
- }
16716
17635
  let metadata = metadataFromEvent(event);
16717
17636
  const logPayload = { metadata };
16718
17637
  const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
@@ -17184,6 +18103,10 @@ var aiSDKChannels = defineChannels(
17184
18103
  channelName: "generateText",
17185
18104
  kind: "async"
17186
18105
  }),
18106
+ generateImage: channel({
18107
+ channelName: "generateImage",
18108
+ kind: "async"
18109
+ }),
17187
18110
  streamText: channel({
17188
18111
  channelName: "streamText",
17189
18112
  kind: "async"
@@ -17371,7 +18294,7 @@ var AISDKPlugin = class extends BasePlugin {
17371
18294
  }
17372
18295
  subscribeToAISDK() {
17373
18296
  const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
17374
- this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
18297
+ this.unsubscribers.push(interceptAISDKV7TelemetryDispatcher());
17375
18298
  this.unsubscribers.push(subscribeToHarnessAgentCreateSession());
17376
18299
  this.unsubscribers.push(
17377
18300
  subscribeToHarnessContinuation(
@@ -17399,6 +18322,18 @@ var AISDKPlugin = class extends BasePlugin {
17399
18322
  aggregateChunks: aggregateAISDKChunks
17400
18323
  })
17401
18324
  );
18325
+ this.unsubscribers.push(
18326
+ traceAsyncChannel(aiSDKChannels.generateImage, {
18327
+ name: "generateImage",
18328
+ type: "llm" /* LLM */,
18329
+ extractInput: ([params], event) => prepareAISDKGenerateImageInput(params, event.self),
18330
+ extractOutput: (result, endEvent) => processAISDKGenerateImageOutput(
18331
+ result,
18332
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
18333
+ ),
18334
+ extractMetrics: (result) => extractTokenMetrics(result)
18335
+ })
18336
+ );
17402
18337
  this.unsubscribers.push(
17403
18338
  traceStreamingChannel(aiSDKChannels.streamText, {
17404
18339
  name: "streamText",
@@ -17888,26 +18823,29 @@ function subscribeToHarnessContinuation(continuationChannel, defaultDenyOutputPa
17888
18823
  channel2.unsubscribe(handlers);
17889
18824
  };
17890
18825
  }
17891
- function subscribeToAISDKV7TelemetryDispatcher() {
17892
- const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
18826
+ function interceptAISDKV7TelemetryDispatcher() {
17893
18827
  const telemetry = braintrustAISDKTelemetry();
17894
- const handlers = {
17895
- end: (event) => {
17896
- const telemetryOptions = event.arguments?.[0]?.telemetry;
17897
- if (telemetryOptions?.isEnabled === false) {
17898
- return;
18828
+ return aiSDKChannels.v7CreateTelemetryDispatcher.intercept(
18829
+ (target, thisArg, args) => {
18830
+ const dispatcher = Reflect.apply(target, thisArg, args);
18831
+ const telemetryOptions = args[0]?.telemetry;
18832
+ if (telemetryOptions?.isEnabled !== false) {
18833
+ try {
18834
+ patchAISDKV7TelemetryDispatcher(
18835
+ dispatcher,
18836
+ telemetry,
18837
+ telemetryOptions
18838
+ );
18839
+ } catch (error) {
18840
+ debugLogger.error(
18841
+ "Error instrumenting AI SDK v7 telemetry dispatcher:",
18842
+ error
18843
+ );
18844
+ }
17899
18845
  }
17900
- patchAISDKV7TelemetryDispatcher(
17901
- event.result,
17902
- telemetry,
17903
- telemetryOptions
17904
- );
18846
+ return dispatcher;
17905
18847
  }
17906
- };
17907
- channel2.subscribe(handlers);
17908
- return () => {
17909
- channel2.unsubscribe(handlers);
17910
- };
18848
+ );
17911
18849
  }
17912
18850
  function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
17913
18851
  if (!isObject(dispatcher)) {
@@ -18232,16 +19170,10 @@ var convertImageToAttachment = (image, explicitMimeType) => {
18232
19170
  }
18233
19171
  }
18234
19172
  if (explicitMimeType) {
18235
- if (image instanceof Uint8Array) {
18236
- return new Attachment({
18237
- data: new Blob([image], { type: explicitMimeType }),
18238
- filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
18239
- contentType: explicitMimeType
18240
- });
18241
- }
18242
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
19173
+ const blob = convertDataToBlob(image, explicitMimeType);
19174
+ if (blob) {
18243
19175
  return new Attachment({
18244
- data: new Blob([image], { type: explicitMimeType }),
19176
+ data: blob,
18245
19177
  filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
18246
19178
  contentType: explicitMimeType
18247
19179
  });
@@ -18295,6 +19227,25 @@ var convertDataToAttachment = (data, mimeType, filename) => {
18295
19227
  function processAISDKCallInput(params) {
18296
19228
  return processInputAttachmentsSync(params);
18297
19229
  }
19230
+ function processAISDKGenerateImageInput(params) {
19231
+ const prompt = params.prompt;
19232
+ if (!isObject(prompt) || Array.isArray(prompt)) {
19233
+ return processAISDKCallInput(params);
19234
+ }
19235
+ const processedPrompt = { ...prompt };
19236
+ if (Array.isArray(prompt.images)) {
19237
+ processedPrompt.images = prompt.images.map(
19238
+ (image) => convertImageToAttachment(image, "image/png") ?? image
19239
+ );
19240
+ }
19241
+ if (prompt.mask !== void 0) {
19242
+ processedPrompt.mask = convertImageToAttachment(prompt.mask, "image/png") ?? prompt.mask;
19243
+ }
19244
+ return processAISDKCallInput({
19245
+ ...params,
19246
+ prompt: processedPrompt
19247
+ });
19248
+ }
18298
19249
  function processAISDKWorkflowAgentCallInput(params) {
18299
19250
  const processed = processAISDKCallInput(params);
18300
19251
  return {
@@ -18433,6 +19384,12 @@ function prepareAISDKEmbedInput(params, self) {
18433
19384
  metadata: extractMetadataFromEmbedParams(params, self)
18434
19385
  };
18435
19386
  }
19387
+ function prepareAISDKGenerateImageInput(params, self) {
19388
+ return {
19389
+ input: processAISDKGenerateImageInput(params).input,
19390
+ metadata: extractMetadataFromCallParams(params, self)
19391
+ };
19392
+ }
18436
19393
  function prepareAISDKRerankInput(params, self) {
18437
19394
  const { documents, query } = params;
18438
19395
  return {
@@ -19808,6 +20765,57 @@ function processAISDKOutput(output, denyOutputPaths) {
19808
20765
  }
19809
20766
  return normalizeAISDKLoggedOutput(sanitized);
19810
20767
  }
20768
+ function processAISDKGenerateImageOutput(output, denyOutputPaths) {
20769
+ if (!output || typeof output !== "object") {
20770
+ return output;
20771
+ }
20772
+ const summarized = {};
20773
+ for (const field of [
20774
+ "usage",
20775
+ "warnings",
20776
+ "providerMetadata",
20777
+ "experimental_providerMetadata",
20778
+ "responses"
20779
+ ]) {
20780
+ const value = safeSerializableFieldRead(output, field);
20781
+ if (value !== void 0 && isSerializableOutputValue(value)) {
20782
+ summarized[field] = value;
20783
+ }
20784
+ }
20785
+ const images = safeSerializableFieldRead(output, "images");
20786
+ const image = safeSerializableFieldRead(output, "image");
20787
+ const generatedFiles = Array.isArray(images) && images.length > 0 ? images : image !== void 0 ? [image] : [];
20788
+ const loggedOutput = normalizeAISDKLoggedOutput(
20789
+ omit(summarized, denyOutputPaths)
20790
+ );
20791
+ if (generatedFiles.length > 0) {
20792
+ loggedOutput.images = generatedFiles.map(
20793
+ (file, index) => convertAISDKGeneratedFileToAttachment(file, index)
20794
+ );
20795
+ }
20796
+ return loggedOutput;
20797
+ }
20798
+ function convertAISDKGeneratedFileToAttachment(file, index) {
20799
+ if (!file || typeof file !== "object") {
20800
+ return file;
20801
+ }
20802
+ const generatedFile = file;
20803
+ const generatedMediaType = safeSerializableFieldRead(
20804
+ generatedFile,
20805
+ "mediaType"
20806
+ );
20807
+ const mediaType = typeof generatedMediaType === "string" ? generatedMediaType : "application/octet-stream";
20808
+ const data = safeSerializableFieldRead(generatedFile, "base64") ?? safeSerializableFieldRead(generatedFile, "uint8Array");
20809
+ const blob = convertDataToBlob(data, mediaType);
20810
+ if (blob) {
20811
+ return new Attachment({
20812
+ data: blob,
20813
+ filename: `generated_image_${index}.${getExtensionFromMediaType(mediaType)}`,
20814
+ contentType: mediaType
20815
+ });
20816
+ }
20817
+ return file;
20818
+ }
19811
20819
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
19812
20820
  if (!output || typeof output !== "object") {
19813
20821
  return output;
@@ -20308,118 +21316,22 @@ var claudeAgentSDKChannels = defineChannels(
20308
21316
  var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
20309
21317
 
20310
21318
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
20311
- var LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED = /* @__PURE__ */ Symbol.for(
20312
- "braintrust.claude_agent_sdk.local_tool_context_async_iterator_patched"
20313
- );
20314
- function createLocalToolContextStore() {
20315
- const maybeIsoWithAsyncLocalStorage = isomorph_default;
20316
- if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
20317
- return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
20318
- }
20319
- let currentStore;
20320
- return {
20321
- enterWith(store) {
20322
- currentStore = store;
20323
- },
20324
- getStore() {
20325
- return currentStore;
20326
- },
20327
- run(store, callback) {
20328
- const previousStore = currentStore;
20329
- currentStore = store;
20330
- try {
20331
- return callback();
20332
- } finally {
20333
- currentStore = previousStore;
20334
- }
20335
- }
20336
- };
20337
- }
20338
- var localToolContextStore = createLocalToolContextStore();
20339
- var fallbackLocalToolParentResolver;
20340
- function createClaudeLocalToolContext() {
20341
- return {};
20342
- }
20343
- function runWithClaudeLocalToolContext(callback, context) {
20344
- return localToolContextStore.run(
20345
- context ?? createClaudeLocalToolContext(),
20346
- callback
20347
- );
21319
+ var localToolContextStore = isomorph_default.newAsyncLocalStorage();
21320
+ var localToolParentResolversByToolUseId = /* @__PURE__ */ new Map();
21321
+ function runWithClaudeLocalToolContext(callback, resolver) {
21322
+ return localToolContextStore.run(resolver, callback);
20348
21323
  }
20349
- function ensureClaudeLocalToolContext() {
20350
- const existing = localToolContextStore.getStore();
20351
- if (existing) {
20352
- return existing;
20353
- }
20354
- const created = {};
20355
- localToolContextStore.enterWith(created);
20356
- return created;
21324
+ function registerClaudeLocalToolParentResolver(toolUseId, resolver) {
21325
+ localToolParentResolversByToolUseId.set(toolUseId, resolver);
20357
21326
  }
20358
- function setClaudeLocalToolParentResolver(resolver) {
20359
- fallbackLocalToolParentResolver = resolver;
20360
- const context = ensureClaudeLocalToolContext();
20361
- if (!context) {
20362
- return;
21327
+ function getClaudeLocalToolParentResolver(toolUseId) {
21328
+ const currentResolver = localToolContextStore.getStore();
21329
+ if (!toolUseId) {
21330
+ return currentResolver;
20363
21331
  }
20364
- context.resolveLocalToolParent = resolver;
20365
- }
20366
- function getClaudeLocalToolParentResolver() {
20367
- return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
20368
- }
20369
- function isAsyncIterable3(value) {
20370
- return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
20371
- }
20372
- function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
20373
- if (!isAsyncIterable3(result) || Object.isFrozen(result) || Object.isSealed(result)) {
20374
- return result;
20375
- }
20376
- const stream = result;
20377
- const originalAsyncIterator = stream[Symbol.asyncIterator];
20378
- if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
20379
- return result;
20380
- }
20381
- const patchedAsyncIterator = function() {
20382
- return runWithClaudeLocalToolContext(() => {
20383
- const iterator = Reflect.apply(originalAsyncIterator, this, []);
20384
- if (!iterator || typeof iterator !== "object") {
20385
- return iterator;
20386
- }
20387
- const patchMethod = (methodName) => {
20388
- const originalMethod = Reflect.get(iterator, methodName);
20389
- if (typeof originalMethod !== "function") {
20390
- return;
20391
- }
20392
- Reflect.set(
20393
- iterator,
20394
- methodName,
20395
- (...args) => runWithClaudeLocalToolContext(
20396
- () => Reflect.apply(
20397
- originalMethod,
20398
- iterator,
20399
- args
20400
- ),
20401
- localToolContext
20402
- )
20403
- );
20404
- };
20405
- patchMethod("next");
20406
- patchMethod("return");
20407
- patchMethod("throw");
20408
- return iterator;
20409
- }, localToolContext);
20410
- };
20411
- Object.defineProperty(
20412
- patchedAsyncIterator,
20413
- LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
20414
- {
20415
- configurable: false,
20416
- enumerable: false,
20417
- value: true,
20418
- writable: false
20419
- }
20420
- );
20421
- Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
20422
- return result;
21332
+ const registeredResolver = localToolParentResolversByToolUseId.get(toolUseId);
21333
+ localToolParentResolversByToolUseId.delete(toolUseId);
21334
+ return currentResolver ?? registeredResolver;
20423
21335
  }
20424
21336
 
20425
21337
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
@@ -20445,7 +21357,7 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
20445
21357
  const metadata = getMetadata();
20446
21358
  const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
20447
21359
  const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
20448
- const localToolParentResolver = getClaudeLocalToolParentResolver();
21360
+ const localToolParentResolver = getClaudeLocalToolParentResolver(toolUseId);
20449
21361
  const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
20450
21362
  const runWithResolvedParent = async () => {
20451
21363
  const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
@@ -20972,6 +21884,7 @@ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToP
20972
21884
  }
20973
21885
  }
20974
21886
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
21887
+ registerClaudeLocalToolParentResolver(toolUseID, resolveParentSpan);
20975
21888
  return {};
20976
21889
  }
20977
21890
  const parsed = parseToolName(input.tool_name);
@@ -21682,7 +22595,7 @@ async function finalizeQuerySpan(state) {
21682
22595
  }
21683
22596
  var ClaudeAgentSDKPlugin = class extends BasePlugin {
21684
22597
  onEnable() {
21685
- this.subscribeToQuery();
22598
+ this.interceptQuery();
21686
22599
  }
21687
22600
  onDisable() {
21688
22601
  for (const unsubscribe of this.unsubscribers) {
@@ -21690,211 +22603,218 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
21690
22603
  }
21691
22604
  this.unsubscribers = [];
21692
22605
  }
21693
- subscribeToQuery() {
21694
- const channel2 = claudeAgentSDKChannels.query.tracingChannel();
21695
- const spans = /* @__PURE__ */ new WeakMap();
21696
- const handlers = {
21697
- start: (event) => {
21698
- const params = event.arguments[0] ?? {};
21699
- const originalPrompt = params.prompt;
21700
- const options = params.options ?? {};
21701
- const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
21702
- let promptStarted = false;
21703
- let capturedPromptMessages;
21704
- let resolvePromptDone;
21705
- const promptDone = new Promise((resolve) => {
21706
- resolvePromptDone = resolve;
21707
- });
21708
- if (promptIsAsyncIterable) {
21709
- capturedPromptMessages = [];
21710
- const promptStream = originalPrompt;
21711
- params.prompt = (async function* () {
21712
- promptStarted = true;
21713
- try {
21714
- for await (const message of promptStream) {
21715
- capturedPromptMessages.push(message);
21716
- yield message;
21717
- }
21718
- } finally {
21719
- resolvePromptDone?.();
22606
+ interceptQuery() {
22607
+ const startQuery = (params) => {
22608
+ const originalPrompt = params.prompt;
22609
+ const options = params.options ?? {};
22610
+ const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
22611
+ let promptStarted = false;
22612
+ let capturedPromptMessages;
22613
+ let resolvePromptDone;
22614
+ const promptDone = new Promise((resolve) => {
22615
+ resolvePromptDone = resolve;
22616
+ });
22617
+ if (promptIsAsyncIterable) {
22618
+ capturedPromptMessages = [];
22619
+ const promptStream = originalPrompt;
22620
+ params.prompt = (async function* () {
22621
+ promptStarted = true;
22622
+ try {
22623
+ for await (const message of promptStream) {
22624
+ capturedPromptMessages.push(message);
22625
+ yield message;
21720
22626
  }
21721
- })();
21722
- }
21723
- const span = startSpan(
21724
- withSpanInstrumentationName(
21725
- {
21726
- name: "Claude Agent",
21727
- spanAttributes: {
21728
- type: "task" /* TASK */
21729
- }
21730
- },
21731
- INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
21732
- )
21733
- );
21734
- const startTime = getCurrentUnixTimestamp();
21735
- try {
21736
- span.log({
21737
- input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
21738
- metadata: filterSerializableOptions(options)
21739
- });
21740
- } catch (error) {
21741
- console.error("Error extracting input for Claude Agent SDK:", error);
21742
- }
21743
- const activeToolSpans = /* @__PURE__ */ new Map();
21744
- const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
21745
- const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
21746
- const subAgentSpans = /* @__PURE__ */ new Map();
21747
- const endedSubAgentSpans = /* @__PURE__ */ new Set();
21748
- const toolUseToParent = /* @__PURE__ */ new Map();
21749
- const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
21750
- const latestRootLlmParentRef = {
21751
- value: void 0
21752
- };
21753
- const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
21754
- const taskIdToToolUseId = /* @__PURE__ */ new Map();
21755
- const promptMessagesByParentKey = /* @__PURE__ */ new Map();
21756
- const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
21757
- const localToolContext = createClaudeLocalToolContext();
21758
- const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
21759
- const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
21760
- const resolveToolUseParentSpan = async (toolUseID, context) => {
21761
- const trackedParentToolUseId = toolUseToParent.get(toolUseID);
21762
- const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
21763
- const parentKey = llmParentKey(parentToolUseId);
21764
- const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
21765
- const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
21766
- if (!activeLlmSpan && !latestLlmParent) {
21767
- await ensureActiveLlmSpanForParentToolUse(
21768
- span,
21769
- activeLlmSpansByParentToolUse,
21770
- subAgentDetailsByToolUseId,
21771
- activeToolSpans,
21772
- subAgentSpans,
21773
- parentToolUseId,
21774
- getCurrentUnixTimestamp()
21775
- );
21776
- }
21777
- if (parentToolUseId) {
21778
- const subAgentSpan = await ensureSubAgentSpan(
21779
- subAgentDetailsByToolUseId,
21780
- span,
21781
- activeToolSpans,
21782
- subAgentSpans,
21783
- parentToolUseId
21784
- );
21785
- return subAgentSpan.export();
22627
+ } finally {
22628
+ resolvePromptDone?.();
21786
22629
  }
21787
- return span.export();
21788
- };
21789
- localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
21790
- setClaudeLocalToolParentResolver(resolveToolUseParentSpan);
21791
- const optionsWithHooks = injectTracingHooks(
21792
- options,
21793
- resolveToolUseParentSpan,
21794
- taskIdToToolUseId,
21795
- toolUseToParent,
21796
- activeToolSpans,
21797
- localToolHookNames,
21798
- skipLocalToolHooks,
21799
- subAgentDetailsByToolUseId,
21800
- subAgentSpans,
21801
- endedSubAgentSpans
21802
- );
21803
- params.options = optionsWithHooks;
21804
- event.arguments[0] = params;
21805
- spans.set(event, {
21806
- activeLlmSpansByParentToolUse,
21807
- activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
21808
- activeToolSpans,
21809
- conversationHistoryByParentKey,
21810
- capturedPromptMessages,
21811
- currentMessageId: void 0,
21812
- currentMessageStartTime: startTime,
21813
- currentMessages: [],
21814
- endedSubAgentSpans,
21815
- finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
21816
- finalResults: [],
21817
- options: optionsWithHooks,
21818
- originalPrompt,
21819
- processing: Promise.resolve(),
21820
- promptDone,
21821
- promptMessagesByParentKey,
21822
- promptStarted: () => promptStarted,
21823
- promptSourcePriorityByParentKey,
21824
- span,
21825
- subAgentDetailsByToolUseId,
21826
- subAgentSpans,
21827
- taskIdToToolUseId,
21828
- latestLlmParentBySubAgentToolUse,
21829
- latestRootLlmParentRef,
21830
- toolUseToParent,
21831
- usageByMessageId: /* @__PURE__ */ new Map(),
21832
- localToolContext
22630
+ })();
22631
+ }
22632
+ const span = startSpan(
22633
+ withSpanInstrumentationName(
22634
+ {
22635
+ name: "Claude Agent",
22636
+ spanAttributes: {
22637
+ type: "task" /* TASK */
22638
+ }
22639
+ },
22640
+ INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
22641
+ )
22642
+ );
22643
+ const startTime = getCurrentUnixTimestamp();
22644
+ try {
22645
+ span.log({
22646
+ input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
22647
+ metadata: filterSerializableOptions(options)
21833
22648
  });
21834
- },
21835
- end: (event) => {
21836
- const state = spans.get(event);
21837
- if (!state) {
21838
- return;
21839
- }
21840
- const eventResult = bindClaudeLocalToolContextToAsyncIterable(
21841
- event.result,
21842
- state.localToolContext
21843
- );
21844
- if (eventResult === void 0) {
21845
- state.span.end();
21846
- spans.delete(event);
21847
- return;
21848
- }
21849
- if (isAsyncIterable(eventResult)) {
21850
- patchStreamIfNeeded(eventResult, {
21851
- onChunk: (message) => {
21852
- maybeTrackToolUseContext(state, message);
21853
- state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
21854
- console.error(
21855
- "Error processing Claude Agent SDK stream chunk:",
21856
- error
21857
- );
21858
- });
21859
- },
21860
- onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
21861
- spans.delete(event);
21862
- }),
21863
- onError: (error) => state.processing.then(() => {
21864
- state.span.log({
21865
- error: error.message
21866
- });
21867
- }).then(() => finalizeQuerySpan(state)).finally(() => {
21868
- spans.delete(event);
21869
- })
21870
- });
21871
- return;
21872
- }
21873
- try {
21874
- state.span.log({ output: eventResult });
21875
- } catch (error) {
21876
- console.error("Error extracting output for Claude Agent SDK:", error);
21877
- } finally {
21878
- state.span.end();
21879
- spans.delete(event);
22649
+ } catch (error) {
22650
+ console.error("Error extracting input for Claude Agent SDK:", error);
22651
+ }
22652
+ const activeToolSpans = /* @__PURE__ */ new Map();
22653
+ const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
22654
+ const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
22655
+ const subAgentSpans = /* @__PURE__ */ new Map();
22656
+ const endedSubAgentSpans = /* @__PURE__ */ new Set();
22657
+ const toolUseToParent = /* @__PURE__ */ new Map();
22658
+ const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
22659
+ const latestRootLlmParentRef = {
22660
+ value: void 0
22661
+ };
22662
+ const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
22663
+ const taskIdToToolUseId = /* @__PURE__ */ new Map();
22664
+ const promptMessagesByParentKey = /* @__PURE__ */ new Map();
22665
+ const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
22666
+ const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
22667
+ const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
22668
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
22669
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
22670
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
22671
+ const parentKey = llmParentKey(parentToolUseId);
22672
+ const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
22673
+ const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
22674
+ if (!activeLlmSpan && !latestLlmParent) {
22675
+ await ensureActiveLlmSpanForParentToolUse(
22676
+ span,
22677
+ activeLlmSpansByParentToolUse,
22678
+ subAgentDetailsByToolUseId,
22679
+ activeToolSpans,
22680
+ subAgentSpans,
22681
+ parentToolUseId,
22682
+ getCurrentUnixTimestamp()
22683
+ );
21880
22684
  }
21881
- },
21882
- error: (event) => {
21883
- const state = spans.get(event);
21884
- if (!state || !event.error) {
21885
- return;
22685
+ if (parentToolUseId) {
22686
+ const subAgentSpan = await ensureSubAgentSpan(
22687
+ subAgentDetailsByToolUseId,
22688
+ span,
22689
+ activeToolSpans,
22690
+ subAgentSpans,
22691
+ parentToolUseId
22692
+ );
22693
+ return subAgentSpan.export();
21886
22694
  }
21887
- state.span.log({
21888
- error: event.error.message
22695
+ return span.export();
22696
+ };
22697
+ const optionsWithHooks = injectTracingHooks(
22698
+ options,
22699
+ resolveToolUseParentSpan,
22700
+ taskIdToToolUseId,
22701
+ toolUseToParent,
22702
+ activeToolSpans,
22703
+ localToolHookNames,
22704
+ skipLocalToolHooks,
22705
+ subAgentDetailsByToolUseId,
22706
+ subAgentSpans,
22707
+ endedSubAgentSpans
22708
+ );
22709
+ params.options = optionsWithHooks;
22710
+ return {
22711
+ activeLlmSpansByParentToolUse,
22712
+ activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
22713
+ activeToolSpans,
22714
+ conversationHistoryByParentKey,
22715
+ capturedPromptMessages,
22716
+ currentMessageId: void 0,
22717
+ currentMessageStartTime: startTime,
22718
+ currentMessages: [],
22719
+ endedSubAgentSpans,
22720
+ finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
22721
+ finalResults: [],
22722
+ options: optionsWithHooks,
22723
+ originalPrompt,
22724
+ processing: Promise.resolve(),
22725
+ promptDone,
22726
+ promptMessagesByParentKey,
22727
+ promptStarted: () => promptStarted,
22728
+ promptSourcePriorityByParentKey,
22729
+ span,
22730
+ subAgentDetailsByToolUseId,
22731
+ subAgentSpans,
22732
+ taskIdToToolUseId,
22733
+ latestLlmParentBySubAgentToolUse,
22734
+ latestRootLlmParentRef,
22735
+ toolUseToParent,
22736
+ usageByMessageId: /* @__PURE__ */ new Map(),
22737
+ localToolParentResolver: resolveToolUseParentSpan
22738
+ };
22739
+ };
22740
+ const finishQuery = (state, result) => {
22741
+ if (isAsyncIterable(result)) {
22742
+ patchStreamIfNeeded(result, {
22743
+ aroundNext: (callback) => runWithClaudeLocalToolContext(
22744
+ callback,
22745
+ state.localToolParentResolver
22746
+ ),
22747
+ onChunk: (message) => {
22748
+ maybeTrackToolUseContext(state, message);
22749
+ state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
22750
+ console.error(
22751
+ "Error processing Claude Agent SDK stream chunk:",
22752
+ error
22753
+ );
22754
+ });
22755
+ },
22756
+ onComplete: () => state.processing.then(() => finalizeQuerySpan(state)),
22757
+ onError: (error) => state.processing.then(() => {
22758
+ state.span.log({ error: error.message });
22759
+ }).then(() => finalizeQuerySpan(state))
21889
22760
  });
22761
+ return;
22762
+ }
22763
+ try {
22764
+ state.span.log({ output: result });
22765
+ } catch (error) {
22766
+ console.error("Error extracting output for Claude Agent SDK:", error);
22767
+ } finally {
21890
22768
  state.span.end();
21891
- spans.delete(event);
21892
22769
  }
21893
22770
  };
21894
- channel2.subscribe(handlers);
21895
- this.unsubscribers.push(() => {
21896
- channel2.unsubscribe(handlers);
21897
- });
22771
+ this.unsubscribers.push(
22772
+ claudeAgentSDKChannels.query.intercept((target, thisArg, args) => {
22773
+ let state;
22774
+ try {
22775
+ args[0] ??= {};
22776
+ state = startQuery(args[0]);
22777
+ } catch (error) {
22778
+ debugLogger.error(
22779
+ "Error starting Claude Agent SDK instrumentation:",
22780
+ error
22781
+ );
22782
+ }
22783
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
22784
+ try {
22785
+ const result = state ? runWithClaudeLocalToolContext(
22786
+ invokeTarget,
22787
+ state.localToolParentResolver
22788
+ ) : invokeTarget();
22789
+ if (state) {
22790
+ try {
22791
+ finishQuery(state, result);
22792
+ } catch (error) {
22793
+ debugLogger.error(
22794
+ "Error finalizing Claude Agent SDK instrumentation:",
22795
+ error
22796
+ );
22797
+ }
22798
+ }
22799
+ return result;
22800
+ } catch (error) {
22801
+ if (state) {
22802
+ try {
22803
+ state.span.log({
22804
+ error: error instanceof Error ? error.message : String(error)
22805
+ });
22806
+ state.span.end();
22807
+ } catch (instrumentationError) {
22808
+ debugLogger.error(
22809
+ "Error handling Claude Agent SDK instrumentation failure:",
22810
+ instrumentationError
22811
+ );
22812
+ }
22813
+ }
22814
+ throw error;
22815
+ }
22816
+ })
22817
+ );
21898
22818
  }
21899
22819
  };
21900
22820
 
@@ -26008,7 +26928,7 @@ function patchOpenRouterCallModelResult(args) {
26008
26928
  span,
26009
26929
  () => originalMethod.apply(resultLike, args2)
26010
26930
  );
26011
- if (!isAsyncIterable4(stream)) {
26931
+ if (!isAsyncIterable3(stream)) {
26012
26932
  return stream;
26013
26933
  }
26014
26934
  return wrapAsyncIterableWithSpan({
@@ -26203,7 +27123,7 @@ function wrapAsyncIterableWithSpan(args) {
26203
27123
  }
26204
27124
  };
26205
27125
  }
26206
- function isAsyncIterable4(value) {
27126
+ function isAsyncIterable3(value) {
26207
27127
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
26208
27128
  }
26209
27129
  function normalizeError(error) {
@@ -27081,7 +28001,7 @@ function patchOpenRouterCallModelResult2(args) {
27081
28001
  span,
27082
28002
  () => originalMethod.apply(resultLike, args2)
27083
28003
  );
27084
- if (!isAsyncIterable5(stream)) {
28004
+ if (!isAsyncIterable4(stream)) {
27085
28005
  return stream;
27086
28006
  }
27087
28007
  return wrapAsyncIterableWithSpan2({
@@ -27276,7 +28196,7 @@ function wrapAsyncIterableWithSpan2(args) {
27276
28196
  }
27277
28197
  };
27278
28198
  }
27279
- function isAsyncIterable5(value) {
28199
+ function isAsyncIterable4(value) {
27280
28200
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
27281
28201
  }
27282
28202
  function normalizeError2(error) {
@@ -33268,12 +34188,14 @@ function getMetricsFromResponse(response) {
33268
34188
  continue;
33269
34189
  }
33270
34190
  const inputTokenDetails = usageMetadata.input_token_details;
34191
+ const outputTokenDetails = usageMetadata.output_token_details;
33271
34192
  return normalizeTokenMetrics({
33272
34193
  total_tokens: usageMetadata.total_tokens,
33273
34194
  prompt_tokens: usageMetadata.input_tokens,
33274
34195
  completion_tokens: usageMetadata.output_tokens,
33275
34196
  prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
33276
- prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
34197
+ prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
34198
+ completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
33277
34199
  });
33278
34200
  }
33279
34201
  const llmOutput = response.llmOutput || {};
@@ -33860,6 +34782,9 @@ var piCodingAgentChannels = defineChannels(
33860
34782
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
33861
34783
  var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
33862
34784
  var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
34785
+ var PI_TOOL_EXECUTE_WRAPPED = /* @__PURE__ */ Symbol.for(
34786
+ "braintrust.pi_coding_agent.tool_execute_wrapped"
34787
+ );
33863
34788
  var piPromptContextStore;
33864
34789
  var PiCodingAgentPlugin = class extends BasePlugin {
33865
34790
  activePromptStates = /* @__PURE__ */ new Set();
@@ -33940,6 +34865,7 @@ function startPiPromptRun(event, onFinalize) {
33940
34865
  return void 0;
33941
34866
  }
33942
34867
  installPiAgentInstrumentation(agent);
34868
+ wrapPiToolExecutors(agent.state?.tools);
33943
34869
  const metadata = {
33944
34870
  ...extractSessionMetadata(session),
33945
34871
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -33984,7 +34910,7 @@ function extractSession(event) {
33984
34910
  return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
33985
34911
  }
33986
34912
  function isPiAgent(value) {
33987
- return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
34913
+ return isObject(value) && (typeof value.streamFunction === "function" || typeof value.streamFn === "function") && typeof value.subscribe === "function";
33988
34914
  }
33989
34915
  function promptContextStore() {
33990
34916
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
@@ -33994,17 +34920,21 @@ function currentPiPromptState() {
33994
34920
  return promptContextStore().getStore();
33995
34921
  }
33996
34922
  function installPiAgentInstrumentation(agent) {
34923
+ const property = typeof agent.streamFunction === "function" ? "streamFunction" : "streamFn";
34924
+ const streamFunction = agent[property];
33997
34925
  const existing = piAgentPatchStates.get(agent);
33998
- if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
34926
+ if (streamFunction && (!existing || existing.property !== property || streamFunction !== existing.wrappedStreamFunction)) {
33999
34927
  const patchState = {
34000
- originalStreamFn: agent.streamFn,
34001
- wrappedStreamFn: agent.streamFn
34928
+ originalStreamFunction: streamFunction,
34929
+ property,
34930
+ wrappedStreamFunction: streamFunction
34002
34931
  };
34003
- patchState.wrappedStreamFn = makeInstrumentedStreamFn(
34932
+ patchState.wrappedStreamFunction = makeInstrumentedStreamFunction(
34004
34933
  agent,
34005
- patchState.originalStreamFn
34934
+ patchState.originalStreamFunction,
34935
+ property
34006
34936
  );
34007
- agent.streamFn = patchState.wrappedStreamFn;
34937
+ agent[property] = patchState.wrappedStreamFunction;
34008
34938
  piAgentPatchStates.set(agent, patchState);
34009
34939
  }
34010
34940
  if (piAgentEventSubscriptions.has(agent)) {
@@ -34029,14 +34959,21 @@ function installPiAgentInstrumentation(agent) {
34029
34959
  logInstrumentationError4("Pi Coding Agent event subscription", error);
34030
34960
  }
34031
34961
  }
34032
- function makeInstrumentedStreamFn(agent, originalStreamFn) {
34033
- return async function instrumentedPiStreamFn(model, context, options) {
34034
- const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
34962
+ function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
34963
+ return async function instrumentedPiStreamFunction(model, context, options) {
34964
+ const invokeOriginal = () => Reflect.apply(originalStreamFunction, this, [model, context, options]);
34035
34965
  const state = currentPiPromptState();
34036
34966
  if (!state || state.agent !== agent || state.finalized) {
34037
34967
  return invokeOriginal();
34038
34968
  }
34039
- const llmState = await startPiLlmSpan(state, model, context, options);
34969
+ wrapPiToolExecutors(context.tools);
34970
+ const llmState = await startPiLlmSpan(
34971
+ state,
34972
+ model,
34973
+ context,
34974
+ property,
34975
+ options
34976
+ );
34040
34977
  try {
34041
34978
  const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
34042
34979
  return patchAssistantMessageStream(stream, state, llmState);
@@ -34046,12 +34983,39 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
34046
34983
  }
34047
34984
  };
34048
34985
  }
34049
- async function startPiLlmSpan(state, model, context, options) {
34986
+ function wrapPiToolExecutors(tools) {
34987
+ if (!tools) {
34988
+ return;
34989
+ }
34990
+ for (const tool of tools) {
34991
+ try {
34992
+ const execute = tool.execute;
34993
+ if (typeof execute !== "function" || execute[PI_TOOL_EXECUTE_WRAPPED]) {
34994
+ continue;
34995
+ }
34996
+ const wrappedExecute = function(...args) {
34997
+ return runWithAutoInstrumentationAllowed(
34998
+ () => Reflect.apply(execute, this, args)
34999
+ );
35000
+ };
35001
+ Object.defineProperty(wrappedExecute, PI_TOOL_EXECUTE_WRAPPED, {
35002
+ configurable: false,
35003
+ enumerable: false,
35004
+ value: true,
35005
+ writable: false
35006
+ });
35007
+ tool.execute = wrappedExecute;
35008
+ } catch (error) {
35009
+ logInstrumentationError4("Pi Coding Agent tool wrapping", error);
35010
+ }
35011
+ }
35012
+ }
35013
+ async function startPiLlmSpan(state, model, context, property, options) {
34050
35014
  const metadata = {
34051
35015
  ...extractModelMetadata2(model),
34052
35016
  ...extractStreamOptionsMetadata(options),
34053
35017
  ...extractToolMetadata(context.tools),
34054
- "pi_coding_agent.operation": "agent.streamFn"
35018
+ "pi_coding_agent.operation": `agent.${property}`
34055
35019
  };
34056
35020
  const span = startSpan(
34057
35021
  withSpanInstrumentationName(
@@ -34217,35 +35181,26 @@ async function startPiToolSpan(state, event) {
34217
35181
  if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
34218
35182
  return;
34219
35183
  }
34220
- const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
34221
35184
  const metadata = {
34222
35185
  "gen_ai.tool.call.id": event.toolCallId,
34223
35186
  "gen_ai.tool.name": event.toolName,
34224
35187
  "pi_coding_agent.tool.name": event.toolName
34225
35188
  };
34226
- try {
34227
- const span = startSpan(
34228
- withSpanInstrumentationName(
34229
- {
34230
- event: {
34231
- input: event.args,
34232
- metadata
34233
- },
34234
- name: event.toolName || "tool",
34235
- parent: await state.span.export(),
34236
- spanAttributes: { type: "tool" /* TOOL */ }
35189
+ const span = startSpan(
35190
+ withSpanInstrumentationName(
35191
+ {
35192
+ event: {
35193
+ input: event.args,
35194
+ metadata
34237
35195
  },
34238
- INSTRUMENTATION_NAMES.PI_CODING_AGENT
34239
- )
34240
- );
34241
- state.activeToolSpans.set(event.toolCallId, {
34242
- restoreAutoInstrumentation,
34243
- span
34244
- });
34245
- } catch (error) {
34246
- restoreAutoInstrumentation();
34247
- throw error;
34248
- }
35196
+ name: event.toolName || "tool",
35197
+ parent: await state.span.export(),
35198
+ spanAttributes: { type: "tool" /* TOOL */ }
35199
+ },
35200
+ INSTRUMENTATION_NAMES.PI_CODING_AGENT
35201
+ )
35202
+ );
35203
+ state.activeToolSpans.set(event.toolCallId, { span });
34249
35204
  }
34250
35205
  function finishPiToolSpan(state, event) {
34251
35206
  const toolState = state.activeToolSpans.get(event.toolCallId);
@@ -34266,11 +35221,7 @@ function finishPiToolSpan(state, event) {
34266
35221
  output: event.result
34267
35222
  });
34268
35223
  } finally {
34269
- try {
34270
- toolState.span.end();
34271
- } finally {
34272
- toolState.restoreAutoInstrumentation?.();
34273
- }
35224
+ toolState.span.end();
34274
35225
  }
34275
35226
  }
34276
35227
  function finishPiPromptRun(state, error) {
@@ -34320,10 +35271,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
34320
35271
  ...cleanMetrics5(llmState.metrics),
34321
35272
  ...buildDurationMetrics3(llmState.startTime)
34322
35273
  };
34323
- const usageMetrics = extractUsageMetrics2(message?.usage);
34324
- if (Object.keys(usageMetrics).length > 0) {
35274
+ const usageMetrics2 = extractUsageMetrics2(message?.usage);
35275
+ if (Object.keys(usageMetrics2).length > 0) {
34325
35276
  promptState.collectedLlmUsageMetrics = true;
34326
- addMetrics(promptState.metrics, usageMetrics);
35277
+ addMetrics(promptState.metrics, usageMetrics2);
34327
35278
  }
34328
35279
  try {
34329
35280
  safeLog4(llmState.span, {
@@ -34341,14 +35292,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
34341
35292
  }
34342
35293
  function finishOpenToolSpans(state, error) {
34343
35294
  for (const [, toolState] of state.activeToolSpans) {
34344
- try {
34345
- safeLog4(toolState.span, {
34346
- error: error ? toLoggedError(error) : "Pi tool did not complete"
34347
- });
34348
- toolState.span.end();
34349
- } finally {
34350
- toolState.restoreAutoInstrumentation?.();
34351
- }
35295
+ safeLog4(toolState.span, {
35296
+ error: error ? toLoggedError(error) : "Pi tool did not complete"
35297
+ });
35298
+ toolState.span.end();
34352
35299
  }
34353
35300
  state.activeToolSpans.clear();
34354
35301
  }
@@ -34667,12 +35614,12 @@ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
34667
35614
  var StrandsAgentSDKPlugin = class extends BasePlugin {
34668
35615
  activeChildParents = /* @__PURE__ */ new WeakMap();
34669
35616
  onEnable() {
34670
- this.subscribeToAgentStream();
34671
- this.subscribeToMultiAgentStream(
35617
+ this.interceptAgentStream();
35618
+ this.interceptMultiAgentStream(
34672
35619
  strandsAgentSDKChannels.graphStream,
34673
35620
  "Graph.stream"
34674
35621
  );
34675
- this.subscribeToMultiAgentStream(
35622
+ this.interceptMultiAgentStream(
34676
35623
  strandsAgentSDKChannels.swarmStream,
34677
35624
  "Swarm.stream"
34678
35625
  );
@@ -34683,122 +35630,92 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
34683
35630
  }
34684
35631
  this.unsubscribers = [];
34685
35632
  }
34686
- subscribeToAgentStream() {
34687
- const channel2 = strandsAgentSDKChannels.agentStream.tracingChannel();
34688
- const states = /* @__PURE__ */ new WeakMap();
34689
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
34690
- const handlers = {
34691
- start: (event) => {
34692
- const state = startAgentStream(event, this.activeChildParents);
34693
- if (state) {
34694
- states.set(event, state);
34695
- }
34696
- },
34697
- end: (event) => {
34698
- const state = states.get(event);
34699
- if (!state) {
34700
- return;
34701
- }
34702
- const result = event.result;
34703
- if (isAsyncIterable(result)) {
34704
- patchStreamIfNeeded(result, {
34705
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
34706
- onChunk: (chunk) => handleAgentStreamEvent(state, chunk),
34707
- onComplete: () => {
34708
- finalizeAgentStream(state);
34709
- states.delete(event);
34710
- },
34711
- onError: (error) => {
34712
- finalizeAgentStream(state, error);
34713
- states.delete(event);
34714
- }
34715
- });
34716
- return;
34717
- }
34718
- finalizeAgentStream(state, void 0, result);
34719
- states.delete(event);
34720
- },
34721
- error: (event) => {
34722
- const state = states.get(event);
34723
- if (!state || !event.error) {
34724
- return;
34725
- }
34726
- finalizeAgentStream(state, event.error);
34727
- states.delete(event);
34728
- }
34729
- };
34730
- channel2.subscribe(handlers);
34731
- this.unsubscribers.push(() => {
34732
- unbindAutoInstrumentationSuppression?.();
34733
- channel2.unsubscribe(handlers);
34734
- });
35633
+ interceptAgentStream() {
35634
+ this.unsubscribers.push(
35635
+ strandsAgentSDKChannels.agentStream.intercept(
35636
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
35637
+ finalize: finalizeAgentStream,
35638
+ handleChunk: handleAgentStreamEvent,
35639
+ invoke: () => Reflect.apply(target, thisArg, args),
35640
+ name: "Strands Agent SDK",
35641
+ start: () => startAgentStream(
35642
+ args[0],
35643
+ extractAgent(additional.agent, thisArg),
35644
+ this.activeChildParents
35645
+ )
35646
+ })
35647
+ )
35648
+ );
34735
35649
  }
34736
- subscribeToMultiAgentStream(channel2, operation) {
34737
- const tracingChannel = channel2.tracingChannel();
34738
- const states = /* @__PURE__ */ new WeakMap();
34739
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(tracingChannel);
34740
- const handlers = {
34741
- start: (event) => {
34742
- const state = startMultiAgentStream(
34743
- event,
34744
- operation,
34745
- this.activeChildParents
34746
- );
34747
- if (state) {
34748
- states.set(event, state);
34749
- }
34750
- },
34751
- end: (event) => {
34752
- const state = states.get(event);
34753
- if (!state) {
34754
- return;
34755
- }
34756
- const result = event.result;
34757
- if (isAsyncIterable(result)) {
34758
- patchStreamIfNeeded(result, {
34759
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
34760
- onChunk: (chunk) => handleMultiAgentStreamEvent(
34761
- state,
34762
- chunk,
34763
- this.activeChildParents
34764
- ),
34765
- onComplete: () => {
34766
- finalizeMultiAgentStream(state, this.activeChildParents);
34767
- states.delete(event);
34768
- },
34769
- onError: (error) => {
34770
- finalizeMultiAgentStream(state, this.activeChildParents, error);
34771
- states.delete(event);
34772
- }
34773
- });
34774
- return;
34775
- }
34776
- finalizeMultiAgentStream(
34777
- state,
34778
- this.activeChildParents,
34779
- void 0,
34780
- result
35650
+ interceptMultiAgentStream(channel2, operation) {
35651
+ this.unsubscribers.push(
35652
+ channel2.intercept(
35653
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
35654
+ finalize: (state, error, output) => finalizeMultiAgentStream(
35655
+ state,
35656
+ this.activeChildParents,
35657
+ error,
35658
+ output
35659
+ ),
35660
+ handleChunk: (state, chunk) => handleMultiAgentStreamEvent(state, chunk, this.activeChildParents),
35661
+ invoke: () => Reflect.apply(target, thisArg, args),
35662
+ name: "Strands multi-agent",
35663
+ start: () => startMultiAgentStream(
35664
+ args[0],
35665
+ extractOrchestrator(additional.orchestrator, thisArg),
35666
+ operation,
35667
+ this.activeChildParents
35668
+ )
35669
+ })
35670
+ )
35671
+ );
35672
+ }
35673
+ };
35674
+ function instrumentStrandsStreamInvocation(options) {
35675
+ let state;
35676
+ try {
35677
+ state = options.start();
35678
+ } catch (error) {
35679
+ debugLogger.error(`Error starting ${options.name} instrumentation:`, error);
35680
+ }
35681
+ let result;
35682
+ try {
35683
+ result = runWithAutoInstrumentationSuppressed(options.invoke);
35684
+ } catch (error) {
35685
+ if (state) {
35686
+ try {
35687
+ options.finalize(state, error);
35688
+ } catch (instrumentationError) {
35689
+ debugLogger.error(
35690
+ `Error handling ${options.name} instrumentation failure:`,
35691
+ instrumentationError
34781
35692
  );
34782
- states.delete(event);
34783
- },
34784
- error: (event) => {
34785
- const state = states.get(event);
34786
- if (!state || !event.error) {
34787
- return;
34788
- }
34789
- finalizeMultiAgentStream(state, this.activeChildParents, event.error);
34790
- states.delete(event);
34791
35693
  }
34792
- };
34793
- tracingChannel.subscribe(handlers);
34794
- this.unsubscribers.push(() => {
34795
- unbindAutoInstrumentationSuppression?.();
34796
- tracingChannel.unsubscribe(handlers);
34797
- });
35694
+ }
35695
+ throw error;
34798
35696
  }
34799
- };
34800
- function startAgentStream(event, activeChildParents) {
34801
- const agent = extractAgent(event);
35697
+ if (state) {
35698
+ try {
35699
+ if (isAsyncIterable(result)) {
35700
+ patchStreamIfNeeded(result, {
35701
+ aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
35702
+ onChunk: (chunk) => options.handleChunk(state, chunk),
35703
+ onComplete: () => options.finalize(state),
35704
+ onError: (error) => options.finalize(state, error)
35705
+ });
35706
+ } else {
35707
+ options.finalize(state, void 0, result);
35708
+ }
35709
+ } catch (error) {
35710
+ debugLogger.error(
35711
+ `Error finalizing ${options.name} instrumentation:`,
35712
+ error
35713
+ );
35714
+ }
35715
+ }
35716
+ return result;
35717
+ }
35718
+ function startAgentStream(input, agent, activeChildParents) {
34802
35719
  const model = agent?.model;
34803
35720
  const metadata = {
34804
35721
  ...extractAgentMetadata2(agent),
@@ -34808,17 +35725,14 @@ function startAgentStream(event, activeChildParents) {
34808
35725
  };
34809
35726
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
34810
35727
  const attachmentCache = createStrandsAttachmentCache();
34811
- const input = processStrandsInputAttachments(
34812
- event.arguments[0],
34813
- attachmentCache
34814
- );
35728
+ const processedInput = processStrandsInputAttachments(input, attachmentCache);
34815
35729
  const span = parentSpan ? withCurrent(
34816
35730
  parentSpan,
34817
35731
  () => startSpan(
34818
35732
  withSpanInstrumentationName(
34819
35733
  {
34820
35734
  event: {
34821
- input,
35735
+ input: processedInput,
34822
35736
  metadata
34823
35737
  },
34824
35738
  name: formatAgentSpanName(agent),
@@ -34831,7 +35745,7 @@ function startAgentStream(event, activeChildParents) {
34831
35745
  withSpanInstrumentationName(
34832
35746
  {
34833
35747
  event: {
34834
- input,
35748
+ input: processedInput,
34835
35749
  metadata
34836
35750
  },
34837
35751
  name: formatAgentSpanName(agent),
@@ -34849,22 +35763,21 @@ function startAgentStream(event, activeChildParents) {
34849
35763
  startTime: getCurrentUnixTimestamp()
34850
35764
  };
34851
35765
  }
34852
- function startMultiAgentStream(event, operation, activeChildParents) {
34853
- const orchestrator = extractOrchestrator(event);
35766
+ function startMultiAgentStream(input, orchestrator, operation, activeChildParents) {
34854
35767
  const metadata = {
34855
35768
  "strands.operation": operation,
34856
35769
  provider: "strands",
34857
35770
  ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
34858
35771
  };
34859
35772
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
34860
- const input = processStrandsInputAttachments(event.arguments[0]);
35773
+ const processedInput = processStrandsInputAttachments(input);
34861
35774
  const span = parentSpan ? withCurrent(
34862
35775
  parentSpan,
34863
35776
  () => startSpan(
34864
35777
  withSpanInstrumentationName(
34865
35778
  {
34866
35779
  event: {
34867
- input,
35780
+ input: processedInput,
34868
35781
  metadata
34869
35782
  },
34870
35783
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -34877,7 +35790,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
34877
35790
  withSpanInstrumentationName(
34878
35791
  {
34879
35792
  event: {
34880
- input,
35793
+ input: processedInput,
34881
35794
  metadata
34882
35795
  },
34883
35796
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -35248,12 +36161,12 @@ function finalizeMultiAgentStream(state, activeChildParents, error, output) {
35248
36161
  });
35249
36162
  state.span.end();
35250
36163
  }
35251
- function extractAgent(event) {
35252
- const candidate = event.agent ?? event.self;
36164
+ function extractAgent(agent, self) {
36165
+ const candidate = agent ?? self;
35253
36166
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
35254
36167
  }
35255
- function extractOrchestrator(event) {
35256
- const candidate = event.orchestrator ?? event.self;
36168
+ function extractOrchestrator(orchestrator, self) {
36169
+ const candidate = orchestrator ?? self;
35257
36170
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
35258
36171
  }
35259
36172
  function extractAgentMetadata2(agent) {
@@ -37118,6 +38031,7 @@ __export(exports_exports, {
37118
38031
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
37119
38032
  buildLocalSummary: () => buildLocalSummary,
37120
38033
  collectAnthropicSession: () => collectAnthropicSession,
38034
+ completeOpenAIBatchTrace: () => completeOpenAIBatchTrace,
37121
38035
  configureInstrumentation: () => configureInstrumentation,
37122
38036
  constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
37123
38037
  createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
@@ -37156,6 +38070,8 @@ __export(exports_exports, {
37156
38070
  loginToState: () => loginToState,
37157
38071
  logs3OverflowUploadSchema: () => logs3OverflowUploadSchema,
37158
38072
  newId: () => newId,
38073
+ openaiBatchesRetrieveTraced: () => openaiBatchesRetrieveTraced,
38074
+ openaiFilesCreateTraced: () => openaiFilesCreateTraced,
37159
38075
  parseCachedHeader: () => parseCachedHeader,
37160
38076
  parseTemplateFormat: () => parseTemplateFormat,
37161
38077
  permalink: () => permalink,
@@ -37320,6 +38236,260 @@ async function registerSandbox(options) {
37320
38236
  };
37321
38237
  }
37322
38238
 
38239
+ // src/wrappers/openai-promise-utils.ts
38240
+ function splitSpanInfo(allParams) {
38241
+ const { span_info, ...params } = allParams;
38242
+ return {
38243
+ params,
38244
+ span_info
38245
+ };
38246
+ }
38247
+ function createChannelContext(_channel, params, span_info) {
38248
+ return {
38249
+ arguments: (
38250
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38251
+ [params]
38252
+ ),
38253
+ span_info
38254
+ };
38255
+ }
38256
+ async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
38257
+ let enhancedResponse;
38258
+ const tracePromise = (
38259
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38260
+ channel2.tracePromise
38261
+ );
38262
+ const data = await tracePromise(async () => {
38263
+ enhancedResponse = await apiPromise.withResponse();
38264
+ traceContext.response = enhancedResponse.response;
38265
+ return enhancedResponse.data;
38266
+ }, traceContext);
38267
+ if (!enhancedResponse) {
38268
+ throw new Error("Expected withResponse() to provide response");
38269
+ }
38270
+ return {
38271
+ data,
38272
+ response: enhancedResponse.response,
38273
+ request_id: enhancedResponse.request_id
38274
+ };
38275
+ }
38276
+ async function tracePromiseAsResponse(channel2, traceContext, apiPromise) {
38277
+ const tracePromise = (
38278
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38279
+ channel2.tracePromise
38280
+ );
38281
+ let response;
38282
+ await tracePromise(async () => {
38283
+ response = await apiPromise.asResponse();
38284
+ traceContext.response = response;
38285
+ return void 0;
38286
+ }, traceContext);
38287
+ if (!response) {
38288
+ throw new Error("Expected asResponse() to provide response");
38289
+ }
38290
+ return response;
38291
+ }
38292
+ function createLazyAPIPromise(ensureExecuted, ensureResponse, getAPIPromise) {
38293
+ let firstConsumption;
38294
+ let enhancedResponsePromise;
38295
+ let dataPromise;
38296
+ let responsePromise;
38297
+ const withResponse = () => {
38298
+ firstConsumption ??= "data";
38299
+ enhancedResponsePromise ??= firstConsumption === "data" ? ensureExecuted() : getAPIPromise().withResponse();
38300
+ return enhancedResponsePromise;
38301
+ };
38302
+ const asResponse = () => {
38303
+ firstConsumption ??= "response";
38304
+ responsePromise ??= firstConsumption === "response" ? ensureResponse() : getAPIPromise().asResponse();
38305
+ return responsePromise;
38306
+ };
38307
+ return new Proxy({}, {
38308
+ get(target, prop, receiver) {
38309
+ if (prop === "withResponse") {
38310
+ return withResponse;
38311
+ }
38312
+ if (prop === "asResponse") {
38313
+ return asResponse;
38314
+ }
38315
+ if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
38316
+ dataPromise ??= withResponse().then((result) => result.data);
38317
+ const value = Reflect.get(dataPromise, prop, receiver);
38318
+ return typeof value === "function" ? value.bind(dataPromise) : value;
38319
+ }
38320
+ return Reflect.get(target, prop, receiver);
38321
+ }
38322
+ });
38323
+ }
38324
+
38325
+ // src/openai-batch.ts
38326
+ function read2(value, key) {
38327
+ if (value === null || typeof value !== "object" && typeof value !== "function") {
38328
+ return void 0;
38329
+ }
38330
+ try {
38331
+ return Reflect.get(value, key);
38332
+ } catch {
38333
+ return void 0;
38334
+ }
38335
+ }
38336
+ function isAsyncIterable5(value) {
38337
+ return typeof read2(value, Symbol.asyncIterator) === "function";
38338
+ }
38339
+ function teeAsyncIterable(source) {
38340
+ const iterator = source[Symbol.asyncIterator]();
38341
+ const stream = new ReadableStream({
38342
+ async pull(controller) {
38343
+ try {
38344
+ const result = await iterator.next();
38345
+ if (result.done) {
38346
+ controller.close();
38347
+ return;
38348
+ }
38349
+ if (!(result.value instanceof Uint8Array)) {
38350
+ throw new TypeError(
38351
+ "OpenAI upload streams must yield Uint8Array chunks"
38352
+ );
38353
+ }
38354
+ controller.enqueue(result.value);
38355
+ } catch (error) {
38356
+ controller.error(error);
38357
+ }
38358
+ },
38359
+ async cancel(reason) {
38360
+ await iterator.return?.(reason);
38361
+ }
38362
+ });
38363
+ const [uploadStream, trace] = stream.tee();
38364
+ const upload = {
38365
+ async *[Symbol.asyncIterator]() {
38366
+ const reader = uploadStream.getReader();
38367
+ try {
38368
+ while (true) {
38369
+ const result = await reader.read();
38370
+ if (result.done) {
38371
+ return;
38372
+ }
38373
+ yield result.value;
38374
+ }
38375
+ } finally {
38376
+ reader.releaseLock();
38377
+ }
38378
+ }
38379
+ };
38380
+ const path = read2(source, "path");
38381
+ if (typeof path === "string") {
38382
+ Object.defineProperty(upload, "path", { value: path });
38383
+ }
38384
+ return { upload, trace: new Response(trace) };
38385
+ }
38386
+ function teeUpload(upload) {
38387
+ if (upload instanceof Blob) {
38388
+ return { upload, trace: new Response(upload) };
38389
+ }
38390
+ if (upload instanceof Response) {
38391
+ return { upload, trace: upload.clone() };
38392
+ }
38393
+ if (isAsyncIterable5(upload)) {
38394
+ return teeAsyncIterable(upload);
38395
+ }
38396
+ return void 0;
38397
+ }
38398
+ function openaiFilesCreateTraced(files) {
38399
+ return (params, options) => {
38400
+ const parent = getSpanParentObject();
38401
+ const purpose = read2(params, "purpose");
38402
+ const file = read2(params, "file");
38403
+ if (purpose !== "batch") {
38404
+ return files.create(params, options);
38405
+ }
38406
+ let branches;
38407
+ try {
38408
+ branches = teeUpload(file);
38409
+ } catch {
38410
+ return files.create(params, options);
38411
+ }
38412
+ if (!branches) {
38413
+ return files.create(params, options);
38414
+ }
38415
+ const tracedParams = {
38416
+ ...Object(params),
38417
+ file: branches.upload
38418
+ };
38419
+ const apiPromise = files.create(tracedParams, options);
38420
+ let enhancedResponse;
38421
+ const tracedResponse = openAIChannels.filesCreateTraced.invoke(
38422
+ async () => {
38423
+ enhancedResponse = await apiPromise.withResponse();
38424
+ return enhancedResponse.data;
38425
+ },
38426
+ files,
38427
+ [{ params, inputFileContent: branches.trace, parent }],
38428
+ {}
38429
+ ).then((data) => {
38430
+ if (!enhancedResponse) {
38431
+ throw new Error(
38432
+ "Expected OpenAI withResponse() to provide a response"
38433
+ );
38434
+ }
38435
+ return { ...enhancedResponse, data };
38436
+ });
38437
+ return createLazyAPIPromise(
38438
+ () => tracedResponse,
38439
+ () => tracedResponse.then(({ response }) => response),
38440
+ () => apiPromise
38441
+ );
38442
+ };
38443
+ }
38444
+ function openaiBatchesRetrieveTraced(batches) {
38445
+ return (batchId, options) => {
38446
+ const apiPromise = batches.retrieve(batchId, options);
38447
+ let enhancedResponse;
38448
+ const tracedResponse = openAIChannels.batchesRetrieveTraced.invoke(
38449
+ async () => {
38450
+ enhancedResponse = await apiPromise.withResponse();
38451
+ return enhancedResponse.data;
38452
+ },
38453
+ batches,
38454
+ [{ batchId }],
38455
+ {}
38456
+ ).then((data) => {
38457
+ if (!enhancedResponse) {
38458
+ throw new Error(
38459
+ "Expected OpenAI withResponse() to provide a response"
38460
+ );
38461
+ }
38462
+ return { ...enhancedResponse, data };
38463
+ });
38464
+ return createLazyAPIPromise(
38465
+ () => tracedResponse,
38466
+ () => tracedResponse.then(({ response }) => response),
38467
+ () => apiPromise
38468
+ );
38469
+ };
38470
+ }
38471
+ async function completeOpenAIBatchTrace(args) {
38472
+ const inputFileContent = Promise.resolve(args.inputFileContent);
38473
+ const outputFileContent = args.outputFileContent === void 0 ? void 0 : Promise.resolve(args.outputFileContent);
38474
+ const errorFileContent = args.errorFileContent === void 0 ? void 0 : Promise.resolve(args.errorFileContent);
38475
+ void inputFileContent.catch(() => void 0);
38476
+ void outputFileContent?.catch(() => void 0);
38477
+ void errorFileContent?.catch(() => void 0);
38478
+ await openAIChannels.batchesCompleteTrace.invoke(
38479
+ async () => void 0,
38480
+ void 0,
38481
+ [
38482
+ {
38483
+ ...args,
38484
+ inputFileContent,
38485
+ outputFileContent,
38486
+ errorFileContent
38487
+ }
38488
+ ],
38489
+ {}
38490
+ );
38491
+ }
38492
+
37323
38493
  // src/functions/invoke.ts
37324
38494
  async function invoke(args) {
37325
38495
  const {
@@ -37422,58 +38592,6 @@ function initFunction({
37422
38592
  return f;
37423
38593
  }
37424
38594
 
37425
- // src/wrappers/openai-promise-utils.ts
37426
- function splitSpanInfo(allParams) {
37427
- const { span_info, ...params } = allParams;
37428
- return {
37429
- params,
37430
- span_info
37431
- };
37432
- }
37433
- function createChannelContext(_channel, params, span_info) {
37434
- return {
37435
- arguments: (
37436
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37437
- [params]
37438
- ),
37439
- span_info
37440
- };
37441
- }
37442
- async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
37443
- let enhancedResponse;
37444
- const tracePromise = (
37445
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37446
- channel2.tracePromise
37447
- );
37448
- const data = await tracePromise(async () => {
37449
- enhancedResponse = await apiPromise.withResponse();
37450
- traceContext.response = enhancedResponse.response;
37451
- return enhancedResponse.data;
37452
- }, traceContext);
37453
- if (!enhancedResponse) {
37454
- throw new Error("Expected withResponse() to provide response");
37455
- }
37456
- return { data, response: enhancedResponse.response };
37457
- }
37458
- function createLazyAPIPromise(ensureExecuted) {
37459
- let dataPromise = null;
37460
- return new Proxy({}, {
37461
- get(target, prop, receiver) {
37462
- if (prop === "withResponse") {
37463
- return () => ensureExecuted();
37464
- }
37465
- if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
37466
- if (!dataPromise) {
37467
- dataPromise = ensureExecuted().then((result) => result.data);
37468
- }
37469
- const value = Reflect.get(dataPromise, prop, receiver);
37470
- return typeof value === "function" ? value.bind(dataPromise) : value;
37471
- }
37472
- return Reflect.get(target, prop, receiver);
37473
- }
37474
- });
37475
- }
37476
-
37477
38595
  // src/wrappers/oai_responses.ts
37478
38596
  function responsesProxy(openai) {
37479
38597
  if (!openai.responses) {
@@ -37510,17 +38628,33 @@ function wrapResponsesAsync(target, channel2) {
37510
38628
  return (allParams, options) => {
37511
38629
  const { span_info, params } = splitSpanInfo(allParams);
37512
38630
  let executionPromise = null;
38631
+ let apiPromise = null;
38632
+ const getAPIPromise = () => {
38633
+ apiPromise ??= target(params, options);
38634
+ return apiPromise;
38635
+ };
37513
38636
  const ensureExecuted = () => {
37514
38637
  if (!executionPromise) {
37515
38638
  executionPromise = (async () => {
37516
38639
  const traceContext = createChannelContext(channel2, params, span_info);
37517
- const apiPromise = target(params, options);
37518
- return tracePromiseWithResponse(channel2, traceContext, apiPromise);
38640
+ return tracePromiseWithResponse(
38641
+ channel2,
38642
+ traceContext,
38643
+ getAPIPromise()
38644
+ );
37519
38645
  })();
37520
38646
  }
37521
38647
  return executionPromise;
37522
38648
  };
37523
- return createLazyAPIPromise(ensureExecuted);
38649
+ return createLazyAPIPromise(
38650
+ ensureExecuted,
38651
+ () => tracePromiseAsResponse(
38652
+ channel2,
38653
+ createChannelContext(channel2, params, span_info),
38654
+ getAPIPromise()
38655
+ ),
38656
+ getAPIPromise
38657
+ );
37524
38658
  };
37525
38659
  }
37526
38660
  function wrapResponsesSyncStream(target, channel2) {
@@ -37666,6 +38800,11 @@ function wrapChatCompletion(completion) {
37666
38800
  allParams
37667
38801
  );
37668
38802
  let executionPromise = null;
38803
+ let apiPromise = null;
38804
+ const getAPIPromise = () => {
38805
+ apiPromise ??= completion(params, options);
38806
+ return apiPromise;
38807
+ };
37669
38808
  const ensureExecuted = () => {
37670
38809
  if (!executionPromise) {
37671
38810
  executionPromise = (async () => {
@@ -37675,32 +38814,44 @@ function wrapChatCompletion(completion) {
37675
38814
  span_info
37676
38815
  );
37677
38816
  if (params.stream) {
37678
- const completionPromise = completion(
37679
- params,
37680
- options
38817
+ const completionPromise = (
38818
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38819
+ getAPIPromise()
37681
38820
  );
37682
- const { data: data2, response: response2 } = await tracePromiseWithResponse(
38821
+ const { data: data2, response: response2, request_id: request_id2 } = await tracePromiseWithResponse(
37683
38822
  openAIChannels.chatCompletionsCreate,
37684
38823
  traceContext,
37685
38824
  completionPromise
37686
38825
  );
37687
- return { data: data2, response: response2 };
38826
+ return { data: data2, response: response2, request_id: request_id2 };
37688
38827
  }
37689
- const completionResponse = completion(
37690
- params,
37691
- options
38828
+ const completionResponse = (
38829
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38830
+ getAPIPromise()
37692
38831
  );
37693
- const { data, response } = await tracePromiseWithResponse(
38832
+ const { data, response, request_id } = await tracePromiseWithResponse(
37694
38833
  openAIChannels.chatCompletionsCreate,
37695
38834
  traceContext,
37696
38835
  completionResponse
37697
38836
  );
37698
- return { data, response };
38837
+ return { data, response, request_id };
37699
38838
  })();
37700
38839
  }
37701
38840
  return executionPromise;
37702
38841
  };
37703
- return createLazyAPIPromise(ensureExecuted);
38842
+ return createLazyAPIPromise(
38843
+ ensureExecuted,
38844
+ () => tracePromiseAsResponse(
38845
+ openAIChannels.chatCompletionsCreate,
38846
+ createChannelContext(
38847
+ openAIChannels.chatCompletionsCreate,
38848
+ params,
38849
+ span_info
38850
+ ),
38851
+ getAPIPromise()
38852
+ ),
38853
+ getAPIPromise
38854
+ );
37704
38855
  };
37705
38856
  }
37706
38857
  function createEndpointProxy(target, wrapperFn) {
@@ -37718,6 +38869,11 @@ function wrapApiCreateWithChannel(create, channel2) {
37718
38869
  return (allParams, options) => {
37719
38870
  const { span_info, params } = splitSpanInfo(allParams);
37720
38871
  let executionPromise = null;
38872
+ let apiPromise = null;
38873
+ const getAPIPromise = () => {
38874
+ apiPromise ??= create(params, options);
38875
+ return apiPromise;
38876
+ };
37721
38877
  const ensureExecuted = () => {
37722
38878
  if (!executionPromise) {
37723
38879
  executionPromise = (async () => {
@@ -37725,13 +38881,21 @@ function wrapApiCreateWithChannel(create, channel2) {
37725
38881
  return tracePromiseWithResponse(
37726
38882
  channel2,
37727
38883
  traceContext,
37728
- create(params, options)
38884
+ getAPIPromise()
37729
38885
  );
37730
38886
  })();
37731
38887
  }
37732
38888
  return executionPromise;
37733
38889
  };
37734
- return createLazyAPIPromise(ensureExecuted);
38890
+ return createLazyAPIPromise(
38891
+ ensureExecuted,
38892
+ () => tracePromiseAsResponse(
38893
+ channel2,
38894
+ createChannelContext(channel2, params, span_info),
38895
+ getAPIPromise()
38896
+ ),
38897
+ getAPIPromise
38898
+ );
37735
38899
  };
37736
38900
  }
37737
38901
  var wrapEmbeddings = (create) => wrapApiCreateWithChannel(create, openAIChannels.embeddingsCreate);
@@ -37767,6 +38931,13 @@ function wrapAISDK(aiSDK, options = {}) {
37767
38931
  switch (prop) {
37768
38932
  case "generateText":
37769
38933
  return wrapGenerateText(typedAISDK.generateText, options, typedAISDK);
38934
+ case "generateImage":
38935
+ case "experimental_generateImage":
38936
+ return typeof original === "function" ? wrapGenerateImage(
38937
+ original,
38938
+ options,
38939
+ typedAISDK
38940
+ ) : original;
37770
38941
  case "streamText":
37771
38942
  return wrapStreamText(typedAISDK.streamText, options, typedAISDK);
37772
38943
  case "generateObject":
@@ -38003,6 +39174,32 @@ var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
38003
39174
  options
38004
39175
  );
38005
39176
  };
39177
+ var wrapGenerateImage = (generateImage, options = {}, aiSDK) => {
39178
+ return makeGenerateImageWrapper(generateImage, { aiSDK }, options);
39179
+ };
39180
+ var makeGenerateImageWrapper = (generateImage, contextOptions = {}, options = {}) => {
39181
+ const wrapper = async function(allParams) {
39182
+ const { span_info, ...params } = allParams;
39183
+ const tracedParams = { ...params };
39184
+ return aiSDKChannels.generateImage.tracePromise(
39185
+ () => generateImage(tracedParams),
39186
+ createAISDKChannelContext(tracedParams, {
39187
+ aiSDK: contextOptions.aiSDK,
39188
+ denyOutputPaths: options.denyOutputPaths,
39189
+ self: contextOptions.self,
39190
+ span_info: mergeSpanInfo(span_info, {
39191
+ name: "generateImage",
39192
+ spanType: contextOptions.spanType
39193
+ })
39194
+ })
39195
+ );
39196
+ };
39197
+ Object.defineProperty(wrapper, "name", {
39198
+ value: "generateImage",
39199
+ writable: false
39200
+ });
39201
+ return wrapper;
39202
+ };
38006
39203
  var makeEmbedWrapper = (channel2, name, embed, contextOptions = {}, options = {}) => {
38007
39204
  const wrapper = async function(allParams) {
38008
39205
  const { span_info, ...params } = allParams;
@@ -38753,7 +39950,7 @@ function braintrustEveHook(options) {
38753
39950
  }
38754
39951
  };
38755
39952
  }
38756
- function braintrustEveInstrumentation(options) {
39953
+ function createLegacyEveInstrumentation(options) {
38757
39954
  const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
38758
39955
  return {
38759
39956
  events: {
@@ -40141,8 +41338,10 @@ function capturedModelInput(modelInput) {
40141
41338
  const value = [];
40142
41339
  if (typeof instructions === "string") {
40143
41340
  value.push({ content: instructions, role: "system" });
40144
- } else if (instructions) {
41341
+ } else if (Array.isArray(instructions)) {
40145
41342
  value.push(...instructions.map(capturedEveModelMessage));
41343
+ } else if (instructions) {
41344
+ value.push(capturedEveModelMessage(instructions));
40146
41345
  }
40147
41346
  value.push(...messages.map(capturedEveModelMessage));
40148
41347
  try {
@@ -40386,6 +41585,472 @@ async function deterministicEveId(...parts) {
40386
41585
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
40387
41586
  }
40388
41587
 
41588
+ // src/instrumentation/plugins/eve-provider.ts
41589
+ var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
41590
+ function createEveInstrumentationProvider(options = {}) {
41591
+ const bridge = new EveProviderBridge(options.metadata);
41592
+ return {
41593
+ // Eve versions before tracePolicy use capture to decide whether provider
41594
+ // events include content. Newer versions prefer tracePolicy when both are
41595
+ // present, so keep the deprecated field for backwards compatibility.
41596
+ capture: "content",
41597
+ tracePolicy: () => ({
41598
+ emit: true,
41599
+ recordInputs: true,
41600
+ recordOutputs: true
41601
+ }),
41602
+ events: {
41603
+ "action.completed": (event, context) => bridge.handleActionTerminal(event, context),
41604
+ "action.failed": (event, context) => bridge.handleActionTerminal(event, context),
41605
+ "action.started": (event, context) => bridge.handleActionStarted(event, context),
41606
+ "model.call.completed": (event, context) => bridge.handleModelTerminal(event, context),
41607
+ "model.call.failed": (event, context) => bridge.handleModelTerminal(event, context),
41608
+ "model.call.started": (event, context) => bridge.handleModelStarted(event, context),
41609
+ "step.attempt.completed": (event) => bridge.handleStepAttemptTerminal(event),
41610
+ "step.attempt.failed": (event) => bridge.handleStepAttemptTerminal(event),
41611
+ "turn.cancelled": (event, context) => bridge.handleTurnTerminal(event, context),
41612
+ "turn.completed": (event, context) => bridge.handleTurnTerminal(event, context),
41613
+ "turn.failed": (event, context) => bridge.handleTurnTerminal(event, context),
41614
+ "turn.started": (event, context) => bridge.handleTurnStarted(event, context)
41615
+ },
41616
+ flush,
41617
+ setup: options.setup
41618
+ };
41619
+ }
41620
+ var EveProviderBridge = class {
41621
+ constructor(metadata) {
41622
+ this.metadata = metadata;
41623
+ }
41624
+ metadata;
41625
+ activeActions = /* @__PURE__ */ new Map();
41626
+ activeModels = /* @__PURE__ */ new Map();
41627
+ modelsByAttempt = /* @__PURE__ */ new Map();
41628
+ settledOperations = new LRUCache({
41629
+ max: MAX_EVE_PROVIDER_CACHE_ENTRIES
41630
+ });
41631
+ turns = new LRUCache({
41632
+ max: MAX_EVE_PROVIDER_CACHE_ENTRIES
41633
+ });
41634
+ async handleTurnStarted(event, context) {
41635
+ await this.contain("turn start", async () => {
41636
+ if (this.settledOperations.has(event.idempotencyKey)) {
41637
+ context.state.set({ skip: true });
41638
+ return;
41639
+ }
41640
+ const { rowId, spanId } = await generateEveIds(
41641
+ "turn",
41642
+ event.idempotencyKey
41643
+ );
41644
+ const key = turnKey3(event.sessionId, event.turnId);
41645
+ const stored = storedSpan(context);
41646
+ if (stored && "exported" in stored && stored.rootSpanId) {
41647
+ this.turns.set(key, { rootSpanId: stored.rootSpanId, spanId });
41648
+ return;
41649
+ }
41650
+ let rootSpanId = spanId;
41651
+ let parentSpanId;
41652
+ if (event.parentLineage) {
41653
+ const parentTurnKey = turnKey3(
41654
+ event.parentLineage.sessionId,
41655
+ event.parentLineage.turnId
41656
+ );
41657
+ const parentTurn = this.turns.get(parentTurnKey);
41658
+ rootSpanId = parentTurn?.rootSpanId ?? // Eve propagates the root session through every nested subagent. Use
41659
+ // it instead of the immediate parent session when no ancestor ran
41660
+ // in-process.
41661
+ (await generateEveIds(
41662
+ "turn",
41663
+ turnIdempotencyKey(
41664
+ event.rootSessionId,
41665
+ event.parentLineage.turnId
41666
+ )
41667
+ )).spanId;
41668
+ parentSpanId = (await generateEveIds(
41669
+ "subagent",
41670
+ actionIdempotencyKey(
41671
+ event.parentLineage.sessionId,
41672
+ event.parentLineage.turnId,
41673
+ event.parentLineage.callId
41674
+ )
41675
+ )).spanId;
41676
+ }
41677
+ const metadata = this.spanMetadata(event.sessionId);
41678
+ const span = await this.startSpan(
41679
+ context,
41680
+ {
41681
+ event: { id: rowId, metadata },
41682
+ name: "eve.turn",
41683
+ parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
41684
+ spanAttributes: { type: "task" /* TASK */ },
41685
+ spanId
41686
+ },
41687
+ rootSpanId
41688
+ );
41689
+ span?.log({ metadata });
41690
+ this.turns.set(key, {
41691
+ rootSpanId,
41692
+ spanId
41693
+ });
41694
+ });
41695
+ }
41696
+ async handleTurnTerminal(event, context) {
41697
+ await this.contain("turn terminal", async () => {
41698
+ if (this.settledOperations.has(event.idempotencyKey)) {
41699
+ context.state.set(void 0);
41700
+ return;
41701
+ }
41702
+ const error = event.type === "turn.failed" ? event.error : void 0;
41703
+ this.drainActionsForTurn(event.sessionId, event.turnId, error);
41704
+ const stored = storedSpan(context);
41705
+ if (stored && "exported" in stored) {
41706
+ updateSpan({
41707
+ exported: stored.exported,
41708
+ ...error !== void 0 ? { error } : {},
41709
+ metrics: { end: Date.now() / 1e3 }
41710
+ });
41711
+ }
41712
+ this.settledOperations.set(event.idempotencyKey, true);
41713
+ context.state.set(void 0);
41714
+ this.turns.delete(turnKey3(event.sessionId, event.turnId));
41715
+ });
41716
+ }
41717
+ async handleModelStarted(event, context) {
41718
+ await this.contain("model start", async () => {
41719
+ if (this.settledOperations.has(event.idempotencyKey)) {
41720
+ context.state.set({ skip: true });
41721
+ return;
41722
+ }
41723
+ const parent = await this.parentForScope(event.scope);
41724
+ const { rowId, spanId } = await generateEveIds(
41725
+ "step",
41726
+ event.idempotencyKey
41727
+ );
41728
+ const input = event.input ? capturedModelInput(event.input) : void 0;
41729
+ const metadata = {
41730
+ ...this.spanMetadata(event.scope.sessionId),
41731
+ model: event.model.modelId,
41732
+ provider: event.model.provider
41733
+ };
41734
+ const span = await this.startSpan(context, {
41735
+ event: {
41736
+ id: rowId,
41737
+ ...input !== void 0 ? { input } : {},
41738
+ metadata
41739
+ },
41740
+ name: "eve.step",
41741
+ parentSpanIds: parent,
41742
+ spanAttributes: { type: "llm" /* LLM */ },
41743
+ spanId
41744
+ });
41745
+ if (!span) return;
41746
+ span.log({ ...input !== void 0 ? { input } : {}, metadata });
41747
+ this.activeModels.set(event.idempotencyKey, {
41748
+ span,
41749
+ turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
41750
+ });
41751
+ const keys = this.modelsByAttempt.get(event.scope.attemptId) ?? /* @__PURE__ */ new Set();
41752
+ keys.add(event.idempotencyKey);
41753
+ this.modelsByAttempt.set(event.scope.attemptId, keys);
41754
+ });
41755
+ }
41756
+ async handleModelTerminal(event, context) {
41757
+ await this.contain("model terminal", async () => {
41758
+ if (this.settledOperations.has(event.idempotencyKey)) {
41759
+ context.state.set(void 0);
41760
+ return;
41761
+ }
41762
+ const active = this.activeModels.get(event.idempotencyKey);
41763
+ if (active) {
41764
+ const span = active.span;
41765
+ if (event.type === "model.call.failed") {
41766
+ if (event.error !== void 0) span.log({ error: event.error });
41767
+ } else {
41768
+ span.log({
41769
+ metrics: usageMetrics(event.usage),
41770
+ output: modelOutput(event)
41771
+ });
41772
+ }
41773
+ span.end();
41774
+ } else {
41775
+ const stored = storedSpan(context);
41776
+ if (stored && "exported" in stored) {
41777
+ updateSpan({
41778
+ exported: stored.exported,
41779
+ ...event.type === "model.call.failed" ? event.error !== void 0 ? { error: event.error } : {} : { output: modelOutput(event) },
41780
+ metrics: {
41781
+ ...event.type === "model.call.completed" ? usageMetrics(event.usage) : {},
41782
+ end: Date.now() / 1e3
41783
+ }
41784
+ });
41785
+ }
41786
+ }
41787
+ this.settledOperations.set(event.idempotencyKey, true);
41788
+ this.forgetModel(event.scope.attemptId, event.idempotencyKey);
41789
+ context.state.set(void 0);
41790
+ });
41791
+ }
41792
+ async handleActionStarted(event, context) {
41793
+ await this.contain("action start", async () => {
41794
+ if (event.kind === "load-skill" || this.settledOperations.has(event.idempotencyKey)) {
41795
+ context.state.set({ skip: true });
41796
+ return;
41797
+ }
41798
+ const parent = await this.parentForScope(event.scope);
41799
+ const { rowId, spanId } = await generateEveIds(
41800
+ event.kind === "subagent-call" ? "subagent" : "tool",
41801
+ event.idempotencyKey
41802
+ );
41803
+ const metadata = {
41804
+ ...this.spanMetadata(event.scope.sessionId),
41805
+ "eve.action_kind": event.kind
41806
+ };
41807
+ const span = await this.startSpan(context, {
41808
+ event: {
41809
+ id: rowId,
41810
+ ...event.input !== void 0 ? { input: event.input } : {},
41811
+ metadata
41812
+ },
41813
+ name: event.name,
41814
+ parentSpanIds: parent,
41815
+ spanAttributes: { type: "tool" /* TOOL */ },
41816
+ spanId
41817
+ });
41818
+ if (!span) return;
41819
+ span.log({
41820
+ ...event.input !== void 0 ? { input: event.input } : {},
41821
+ metadata
41822
+ });
41823
+ this.activeActions.set(event.idempotencyKey, {
41824
+ span,
41825
+ turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
41826
+ });
41827
+ });
41828
+ }
41829
+ async handleActionTerminal(event, context) {
41830
+ await this.contain("action terminal", async () => {
41831
+ if (this.settledOperations.has(event.idempotencyKey)) {
41832
+ context.state.set(void 0);
41833
+ return;
41834
+ }
41835
+ const stored = storedSpan(context);
41836
+ if (stored?.skip) {
41837
+ context.state.set(void 0);
41838
+ return;
41839
+ }
41840
+ const active = this.activeActions.get(event.idempotencyKey);
41841
+ const end = finiteTimestamp(event.acceptedAtMs) ?? Date.now();
41842
+ if (active) {
41843
+ const span = active.span;
41844
+ if (event.type === "action.failed") {
41845
+ span.log({
41846
+ error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
41847
+ });
41848
+ } else if (event.output.type === "error") {
41849
+ span.log({
41850
+ error: event.output.error ?? new Error("Eve action returned an error")
41851
+ });
41852
+ } else {
41853
+ span.log({ output: event.output.output });
41854
+ }
41855
+ span.end({ endTime: end / 1e3 });
41856
+ } else {
41857
+ const stored2 = storedSpan(context);
41858
+ if (stored2 && "exported" in stored2) {
41859
+ updateSpan({
41860
+ exported: stored2.exported,
41861
+ ...event.type === "action.failed" ? {
41862
+ error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
41863
+ } : event.output.type === "error" ? {
41864
+ error: event.output.error ?? new Error("Eve action returned an error")
41865
+ } : { output: event.output.output },
41866
+ metrics: { end: end / 1e3 }
41867
+ });
41868
+ }
41869
+ }
41870
+ this.settledOperations.set(event.idempotencyKey, true);
41871
+ this.activeActions.delete(event.idempotencyKey);
41872
+ context.state.set(void 0);
41873
+ });
41874
+ }
41875
+ handleStepAttemptTerminal(event) {
41876
+ void this.contain("step attempt terminal", () => {
41877
+ const keys = this.modelsByAttempt.get(event.scope.attemptId);
41878
+ if (!keys) return;
41879
+ for (const key of keys) {
41880
+ const active = this.activeModels.get(key);
41881
+ if (!active) continue;
41882
+ if (event.type === "step.attempt.failed" && event.error !== void 0) {
41883
+ active.span.log({ error: event.error });
41884
+ }
41885
+ active.span.end();
41886
+ this.activeModels.delete(key);
41887
+ }
41888
+ this.modelsByAttempt.delete(event.scope.attemptId);
41889
+ });
41890
+ }
41891
+ async parentForScope(scope) {
41892
+ const key = turnKey3(scope.sessionId, scope.turnId);
41893
+ const known = this.turns.get(key);
41894
+ if (known) {
41895
+ return { rootSpanId: known.rootSpanId, spanId: known.spanId };
41896
+ }
41897
+ const [{ spanId }, { spanId: rootSpanId }] = await Promise.all([
41898
+ generateEveIds("turn", turnIdempotencyKey(scope.sessionId, scope.turnId)),
41899
+ generateEveIds(
41900
+ "turn",
41901
+ turnIdempotencyKey(
41902
+ scope.rootSessionId ?? scope.sessionId,
41903
+ scope.turnId
41904
+ )
41905
+ )
41906
+ ]);
41907
+ return { rootSpanId, spanId };
41908
+ }
41909
+ async startSpan(context, args, rootSpanId) {
41910
+ const span = withCurrent(
41911
+ NOOP_SPAN,
41912
+ () => _internalStartSpanWithInitialMerge(
41913
+ withSpanInstrumentationName(args ?? {}, INSTRUMENTATION_NAMES.EVE)
41914
+ )
41915
+ );
41916
+ try {
41917
+ context.state.set({
41918
+ exported: await span.export(),
41919
+ ...rootSpanId ? { rootSpanId } : {}
41920
+ });
41921
+ } catch (error) {
41922
+ debugLogger.warn("Error exporting Eve provider span:", error);
41923
+ }
41924
+ return span;
41925
+ }
41926
+ drainActionsForTurn(sessionId, turnId, error) {
41927
+ const key = turnKey3(sessionId, turnId);
41928
+ for (const [idempotencyKey, active] of this.activeActions) {
41929
+ if (active.turnKey !== key) continue;
41930
+ if (error !== void 0) active.span.log({ error });
41931
+ active.span.end();
41932
+ this.activeActions.delete(idempotencyKey);
41933
+ }
41934
+ }
41935
+ forgetModel(attemptId, idempotencyKey) {
41936
+ this.activeModels.delete(idempotencyKey);
41937
+ const keys = this.modelsByAttempt.get(attemptId);
41938
+ keys?.delete(idempotencyKey);
41939
+ if (keys?.size === 0) this.modelsByAttempt.delete(attemptId);
41940
+ }
41941
+ spanMetadata(sessionId) {
41942
+ return {
41943
+ ...this.metadata ?? {},
41944
+ "eve.session_id": sessionId
41945
+ };
41946
+ }
41947
+ async contain(operation, fn) {
41948
+ try {
41949
+ await fn();
41950
+ } catch (error) {
41951
+ debugLogger.warn(`Error in Eve provider ${operation}:`, error);
41952
+ }
41953
+ }
41954
+ };
41955
+ function storedSpan(context) {
41956
+ const value = context.state.get();
41957
+ if (!isObject(value)) return void 0;
41958
+ if (value["skip"] === true) return { skip: true };
41959
+ return typeof value["exported"] === "string" ? {
41960
+ exported: value["exported"],
41961
+ ...typeof value["rootSpanId"] === "string" && value["rootSpanId"].length > 0 ? { rootSpanId: value["rootSpanId"] } : {}
41962
+ } : void 0;
41963
+ }
41964
+ function modelOutput(event) {
41965
+ const content = event.content ?? [];
41966
+ let text = "";
41967
+ const reasoning = [];
41968
+ const toolCalls2 = [];
41969
+ for (const part of content) {
41970
+ if (part.type === "text") {
41971
+ text += part.text;
41972
+ } else if (part.type === "reasoning" && part.text.trim().length > 0) {
41973
+ reasoning.push({ content: part.text });
41974
+ } else if (part.type === "tool-call") {
41975
+ toolCalls2.push({
41976
+ function: {
41977
+ arguments: safeJsonStringify(part.input),
41978
+ name: part.toolName
41979
+ },
41980
+ id: part.callId,
41981
+ type: "function"
41982
+ });
41983
+ }
41984
+ }
41985
+ return [
41986
+ {
41987
+ finish_reason: normalizeFinishReason3(event.finishReason),
41988
+ index: 0,
41989
+ message: {
41990
+ content: text || null,
41991
+ ...reasoning.length > 0 ? { reasoning } : {},
41992
+ role: "assistant",
41993
+ ...toolCalls2.length > 0 ? { tool_calls: toolCalls2 } : {}
41994
+ }
41995
+ }
41996
+ ];
41997
+ }
41998
+ function usageMetrics(usage) {
41999
+ const promptTokens = nonNegativeNumber(usage.inputTokens);
42000
+ const completionTokens = nonNegativeNumber(usage.outputTokens);
42001
+ const cachedTokens = nonNegativeNumber(
42002
+ usage.inputTokenDetails?.cacheReadTokens
42003
+ );
42004
+ const cacheCreationTokens = nonNegativeNumber(
42005
+ usage.inputTokenDetails?.cacheWriteTokens
42006
+ );
42007
+ return {
42008
+ ...promptTokens !== void 0 ? { prompt_tokens: promptTokens } : {},
42009
+ ...completionTokens !== void 0 ? { completion_tokens: completionTokens } : {},
42010
+ ...promptTokens !== void 0 && completionTokens !== void 0 ? { tokens: promptTokens + completionTokens } : {},
42011
+ ...cachedTokens !== void 0 ? { prompt_cached_tokens: cachedTokens } : {},
42012
+ ...cacheCreationTokens !== void 0 ? { prompt_cache_creation_tokens: cacheCreationTokens } : {}
42013
+ };
42014
+ }
42015
+ function nonNegativeNumber(value) {
42016
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
42017
+ }
42018
+ function finiteTimestamp(value) {
42019
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
42020
+ }
42021
+ function normalizeFinishReason3(value) {
42022
+ if (value === "content-filter") return "content_filter";
42023
+ if (value === "tool-calls") return "tool_calls";
42024
+ return value;
42025
+ }
42026
+ function safeJsonStringify(value) {
42027
+ try {
42028
+ return JSON.stringify(value) ?? "null";
42029
+ } catch {
42030
+ return "null";
42031
+ }
42032
+ }
42033
+ function turnKey3(sessionId, turnId) {
42034
+ return `${sessionId}:${turnId}`;
42035
+ }
42036
+ function turnIdempotencyKey(sessionId, turnId) {
42037
+ return `turn:${sessionId}:${turnId}`;
42038
+ }
42039
+ function actionIdempotencyKey(sessionId, turnId, callId) {
42040
+ return `action:${sessionId}:${turnId}:${callId}`;
42041
+ }
42042
+
42043
+ // src/instrumentation/plugins/eve-instrumentation.ts
42044
+ var EVE_INSTRUMENTATION_PROVIDER = /* @__PURE__ */ Symbol.for("eve.instrumentation.provider");
42045
+ function braintrustEveInstrumentation(options) {
42046
+ const definition = "defineState" in options ? createLegacyEveInstrumentation(options) : createEveInstrumentationProvider(options);
42047
+ const declaration = {
42048
+ ...definition,
42049
+ [EVE_INSTRUMENTATION_PROVIDER]: true
42050
+ };
42051
+ return declaration;
42052
+ }
42053
+
40389
42054
  // src/typed-instrumentation-helpers.ts
40390
42055
  var TypedApplyProxy = Proxy;
40391
42056
 
@@ -40787,11 +42452,11 @@ function wrapClaudeAgentQuery(queryFn, defaultThis) {
40787
42452
  }
40788
42453
  };
40789
42454
  const invocationTarget = thisArg === proxy || thisArg === void 0 ? defaultThis ?? thisArg : thisArg;
40790
- return claudeAgentSDKChannels.query.traceSync(
40791
- () => Reflect.apply(target, invocationTarget, [wrappedParams]),
40792
- // The channel carries no extra context fields, but the generated
40793
- // StartOf<> type for Record<string, never> is overly strict here.
40794
- { arguments: [wrappedParams] }
42455
+ return claudeAgentSDKChannels.query.invoke(
42456
+ target,
42457
+ invocationTarget,
42458
+ [wrappedParams],
42459
+ {}
40795
42460
  );
40796
42461
  }
40797
42462
  });
@@ -41406,13 +43071,11 @@ function wrapAgentInstance(agent) {
41406
43071
  if (prop === "stream" && typeof value === "function") {
41407
43072
  return function(args, options) {
41408
43073
  const callArgs = [args, options];
41409
- return strandsAgentSDKChannels.agentStream.traceSync(
41410
- () => Reflect.apply(value, target, callArgs),
41411
- {
41412
- agent: proxy,
41413
- arguments: callArgs,
41414
- self: proxy
41415
- }
43074
+ return strandsAgentSDKChannels.agentStream.invoke(
43075
+ value,
43076
+ target,
43077
+ callArgs,
43078
+ { agent: proxy }
41416
43079
  );
41417
43080
  };
41418
43081
  }
@@ -41443,12 +43106,12 @@ function wrapMultiAgentInstance(orchestrator, kind) {
41443
43106
  return function(input, options) {
41444
43107
  const callArgs = [input, options];
41445
43108
  const channel2 = kind === "graph" ? strandsAgentSDKChannels.graphStream : strandsAgentSDKChannels.swarmStream;
41446
- return channel2.traceSync(
41447
- () => Reflect.apply(value, target, callArgs),
43109
+ return channel2.invoke(
43110
+ value,
43111
+ target,
43112
+ callArgs,
41448
43113
  {
41449
- arguments: callArgs,
41450
- orchestrator: proxy,
41451
- self: proxy
43114
+ orchestrator: proxy
41452
43115
  }
41453
43116
  );
41454
43117
  };
@@ -43400,9 +45063,6 @@ var VitestContextManager = class {
43400
45063
  getCurrentContext() {
43401
45064
  return this.contextStorage.getStore();
43402
45065
  }
43403
- setContext(context) {
43404
- this.contextStorage.enterWith(context);
43405
- }
43406
45066
  runInContext(context, callback) {
43407
45067
  return this.contextStorage.run(context, callback);
43408
45068
  }
@@ -43788,8 +45448,7 @@ function wrapDescribe(originalDescribe, config, afterAll) {
43788
45448
  if (config.onProgress) {
43789
45449
  config.onProgress({ type: "suite_start", suiteName });
43790
45450
  }
43791
- contextManager.setContext(lazyContext);
43792
- factory();
45451
+ contextManager.runInContext(lazyContext, factory);
43793
45452
  if (afterAll) {
43794
45453
  afterAll(async () => {
43795
45454
  await flushExperimentWithSync(context, config);