braintrust 3.28.0 → 3.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +1 -1
  2. package/dev/dist/index.d.mts +356 -7
  3. package/dev/dist/index.d.ts +356 -7
  4. package/dev/dist/index.js +2679 -1828
  5. package/dev/dist/index.mjs +1862 -1011
  6. package/dist/apply-auto-instrumentation.js +298 -265
  7. package/dist/apply-auto-instrumentation.mjs +85 -52
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +56 -6
  9. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  10. package/dist/auto-instrumentations/bundler/next.cjs +56 -6
  11. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  12. package/dist/auto-instrumentations/bundler/rollup.cjs +56 -6
  13. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.cjs +56 -6
  15. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  16. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +56 -6
  17. package/dist/auto-instrumentations/bundler/webpack.cjs +56 -6
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  19. package/dist/auto-instrumentations/{chunk-26PKVUKB.mjs → chunk-LW4HDHXT.mjs} +12 -4
  20. package/dist/auto-instrumentations/{chunk-HD35AM3M.mjs → chunk-OXINGIEZ.mjs} +1 -1
  21. package/dist/auto-instrumentations/{chunk-NP7V4XB2.mjs → chunk-U64OYU4Q.mjs} +45 -3
  22. package/dist/auto-instrumentations/hook.mjs +967 -136
  23. package/dist/auto-instrumentations/index.cjs +45 -3
  24. package/dist/auto-instrumentations/index.mjs +1 -1
  25. package/dist/browser.d.mts +893 -24
  26. package/dist/browser.d.ts +893 -24
  27. package/dist/browser.js +2795 -1136
  28. package/dist/browser.mjs +2795 -1136
  29. package/dist/{chunk-BBE7SNRV.js → chunk-2XDW3UCG.js} +155 -23
  30. package/dist/{chunk-UPFNQCGB.mjs → chunk-BU6SM54N.mjs} +1830 -1045
  31. package/dist/{chunk-ZHUHZWFY.mjs → chunk-N3JKQ3D3.mjs} +152 -20
  32. package/dist/{chunk-OBBWQW6K.js → chunk-TWCDSYJN.js} +2890 -2105
  33. package/dist/cli.js +5976 -1348
  34. package/dist/edge-light.d.mts +1 -1
  35. package/dist/edge-light.d.ts +1 -1
  36. package/dist/edge-light.js +2795 -1136
  37. package/dist/edge-light.mjs +2795 -1136
  38. package/dist/index.d.mts +893 -24
  39. package/dist/index.d.ts +893 -24
  40. package/dist/index.js +1448 -699
  41. package/dist/index.mjs +848 -99
  42. package/dist/instrumentation/index.d.mts +563 -9
  43. package/dist/instrumentation/index.d.ts +563 -9
  44. package/dist/instrumentation/index.js +2794 -989
  45. package/dist/instrumentation/index.mjs +2794 -989
  46. package/dist/vitest-evals-reporter.js +16 -16
  47. package/dist/vitest-evals-reporter.mjs +2 -2
  48. package/dist/workerd.d.mts +1 -1
  49. package/dist/workerd.d.ts +1 -1
  50. package/dist/workerd.js +2795 -1136
  51. package/dist/workerd.mjs +2795 -1136
  52. package/package.json +1 -1
  53. package/util/dist/index.d.mts +42 -0
  54. package/util/dist/index.d.ts +42 -0
package/dist/browser.mjs CHANGED
@@ -659,8 +659,6 @@ function newGlobalTracingChannel(nameOrChannels) {
659
659
  var DefaultAsyncLocalStorage = class {
660
660
  constructor() {
661
661
  }
662
- enterWith(_) {
663
- }
664
662
  run(_, callback) {
665
663
  return callback();
666
664
  }
@@ -2477,7 +2475,9 @@ var AclObjectType = z6.union([
2477
2475
  "project_log",
2478
2476
  "org_project",
2479
2477
  "org_audit_logs",
2480
- "project_group"
2478
+ "project_group",
2479
+ "ai_secret",
2480
+ "org_ai_secret"
2481
2481
  ]),
2482
2482
  z6.null()
2483
2483
  ]);
@@ -3310,7 +3310,7 @@ var PromptParserNullish = z6.union([
3310
3310
  }),
3311
3311
  z6.null()
3312
3312
  ]);
3313
- var PreprocessorSavedFunctionId = z6.union([
3313
+ var PreprocessorId = z6.union([
3314
3314
  z6.object({
3315
3315
  type: z6.literal("function"),
3316
3316
  id: z6.string(),
@@ -3321,6 +3321,7 @@ var PreprocessorSavedFunctionId = z6.union([
3321
3321
  name: z6.string(),
3322
3322
  function_type: z6.literal("preprocessor").optional().default("preprocessor")
3323
3323
  }),
3324
+ z6.object({ type: z6.literal("inline"), code: z6.string().min(1) }),
3324
3325
  z6.null()
3325
3326
  ]);
3326
3327
  var PromptDataNullish = z6.union([
@@ -3328,7 +3329,7 @@ var PromptDataNullish = z6.union([
3328
3329
  prompt: PromptBlockDataNullish,
3329
3330
  options: PromptOptionsNullish,
3330
3331
  parser: PromptParserNullish,
3331
- preprocessor: PreprocessorSavedFunctionId,
3332
+ preprocessor: PreprocessorId,
3332
3333
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
3333
3334
  template_format: z6.union([
3334
3335
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -3530,7 +3531,7 @@ var PromptData = z6.object({
3530
3531
  prompt: PromptBlockDataNullish,
3531
3532
  options: PromptOptionsNullish,
3532
3533
  parser: PromptParserNullish,
3533
- preprocessor: PreprocessorSavedFunctionId,
3534
+ preprocessor: PreprocessorId,
3534
3535
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
3535
3536
  template_format: z6.union([
3536
3537
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -4474,6 +4475,7 @@ var View = z6.object({
4474
4475
  ]),
4475
4476
  name: z6.string(),
4476
4477
  description: z6.union([z6.string(), z6.null()]).optional(),
4478
+ starred: z6.boolean().optional(),
4477
4479
  created: z6.union([z6.string(), z6.null()]).optional(),
4478
4480
  updated_at: z6.union([z6.string(), z6.null()]).optional(),
4479
4481
  view_data: ViewData.optional(),
@@ -5177,44 +5179,72 @@ function createCacheLayers({
5177
5179
  }
5178
5180
 
5179
5181
  // src/prompt-cache/prompt-cache.ts
5180
- function createCacheKey(key) {
5182
+ function createCacheKey(key, namespace) {
5183
+ let cacheKey;
5181
5184
  if (key.id) {
5182
- return `id:${key.id}`;
5183
- }
5184
- const prefix = key.projectId ?? key.projectName;
5185
- if (!prefix) {
5186
- throw new Error("Either projectId or projectName must be provided");
5187
- }
5188
- if (!key.slug) {
5189
- throw new Error("Slug must be provided when not using ID");
5185
+ cacheKey = `id:${key.id}`;
5186
+ } else {
5187
+ const prefix = key.projectId ?? key.projectName;
5188
+ if (!prefix) {
5189
+ throw new Error("Either projectId or projectName must be provided");
5190
+ }
5191
+ if (!key.slug) {
5192
+ throw new Error("Slug must be provided when not using ID");
5193
+ }
5194
+ cacheKey = `${prefix}:${key.slug}:${key.version ?? "latest"}`;
5190
5195
  }
5191
- return `${prefix}:${key.slug}:${key.version ?? "latest"}`;
5196
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
5192
5197
  }
5193
- var PromptCache = class {
5198
+ var PromptCache = class _PromptCache {
5194
5199
  memoryCache;
5195
5200
  diskCache;
5201
+ namespace;
5202
+ expectedResolvedOrgIdentity;
5196
5203
  constructor(options) {
5197
5204
  this.memoryCache = options.memoryCache;
5198
5205
  this.diskCache = options.diskCache;
5206
+ this.namespace = options.namespace;
5207
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
5208
+ }
5209
+ /**
5210
+ * Returns a cache view that shares the same storage layers but isolates all
5211
+ * entries under the provided namespace.
5212
+ */
5213
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
5214
+ return new _PromptCache({
5215
+ memoryCache: this.memoryCache,
5216
+ diskCache: this.diskCache,
5217
+ namespace,
5218
+ expectedResolvedOrgIdentity
5219
+ });
5199
5220
  }
5200
5221
  /**
5201
5222
  * Retrieves a prompt from the cache.
5202
5223
  * First checks the in-memory LRU cache, then falls back to checking the disk cache if available.
5203
5224
  */
5204
5225
  async get(key) {
5205
- const cacheKey = createCacheKey(key);
5226
+ const cacheKey = createCacheKey(key, this.namespace);
5206
5227
  if (this.memoryCache) {
5207
- const memoryPrompt = this.memoryCache.get(cacheKey);
5208
- if (memoryPrompt !== void 0) {
5209
- return memoryPrompt;
5228
+ const memoryEntry = this.memoryCache.get(cacheKey);
5229
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
5230
+ return memoryEntry.value;
5210
5231
  }
5211
5232
  }
5212
5233
  if (this.diskCache) {
5213
- const diskPrompt = await this.diskCache.get(cacheKey);
5214
- if (!diskPrompt) {
5234
+ const diskEntry = await this.diskCache.get(cacheKey);
5235
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
5215
5236
  return void 0;
5216
5237
  }
5217
- this.memoryCache?.set(cacheKey, diskPrompt);
5238
+ const serializedPrompt = diskEntry.value;
5239
+ const diskPrompt = new Prompt2(
5240
+ serializedPrompt.metadata,
5241
+ serializedPrompt.defaults,
5242
+ serializedPrompt.noTrace
5243
+ );
5244
+ this.memoryCache?.set(cacheKey, {
5245
+ value: diskPrompt,
5246
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
5247
+ });
5218
5248
  return diskPrompt;
5219
5249
  }
5220
5250
  return void 0;
@@ -5228,58 +5258,91 @@ var PromptCache = class {
5228
5258
  * @throws If there is an error writing to the disk cache.
5229
5259
  */
5230
5260
  async set(key, value) {
5231
- const cacheKey = createCacheKey(key);
5232
- this.memoryCache?.set(cacheKey, value);
5261
+ const cacheKey = createCacheKey(key, this.namespace);
5262
+ const memoryEntry = {
5263
+ value,
5264
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5265
+ };
5266
+ this.memoryCache?.set(cacheKey, memoryEntry);
5233
5267
  if (this.diskCache) {
5234
- await this.diskCache.set(cacheKey, value);
5268
+ await this.diskCache.set(cacheKey, {
5269
+ value: value._internalSerializeForCache(),
5270
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5271
+ });
5235
5272
  }
5236
5273
  }
5237
5274
  };
5238
5275
 
5239
5276
  // src/prompt-cache/parameters-cache.ts
5240
- function createCacheKey2(key) {
5277
+ function createCacheKey2(key, namespace) {
5278
+ let cacheKey;
5241
5279
  if (key.id) {
5242
- return `parameters:id:${key.id}`;
5243
- }
5244
- const prefix = key.projectId ?? key.projectName;
5245
- if (!prefix) {
5246
- throw new Error("Either projectId or projectName must be provided");
5247
- }
5248
- if (!key.slug) {
5249
- throw new Error("Slug must be provided when not using ID");
5280
+ cacheKey = `parameters:id:${key.id}`;
5281
+ } else {
5282
+ const prefix = key.projectId ?? key.projectName;
5283
+ if (!prefix) {
5284
+ throw new Error("Either projectId or projectName must be provided");
5285
+ }
5286
+ if (!key.slug) {
5287
+ throw new Error("Slug must be provided when not using ID");
5288
+ }
5289
+ cacheKey = `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
5250
5290
  }
5251
- return `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
5291
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
5252
5292
  }
5253
- var ParametersCache = class {
5293
+ var ParametersCache = class _ParametersCache {
5254
5294
  memoryCache;
5255
5295
  diskCache;
5296
+ namespace;
5297
+ expectedResolvedOrgIdentity;
5256
5298
  constructor(options) {
5257
5299
  this.memoryCache = options.memoryCache;
5258
5300
  this.diskCache = options.diskCache;
5301
+ this.namespace = options.namespace;
5302
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
5303
+ }
5304
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
5305
+ return new _ParametersCache({
5306
+ memoryCache: this.memoryCache,
5307
+ diskCache: this.diskCache,
5308
+ namespace,
5309
+ expectedResolvedOrgIdentity
5310
+ });
5259
5311
  }
5260
5312
  async get(key) {
5261
- const cacheKey = createCacheKey2(key);
5313
+ const cacheKey = createCacheKey2(key, this.namespace);
5262
5314
  if (this.memoryCache) {
5263
- const memoryParams = this.memoryCache.get(cacheKey);
5264
- if (memoryParams !== void 0) {
5265
- return memoryParams;
5315
+ const memoryEntry = this.memoryCache.get(cacheKey);
5316
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
5317
+ return memoryEntry.value;
5266
5318
  }
5267
5319
  }
5268
5320
  if (this.diskCache) {
5269
- const diskParams = await this.diskCache.get(cacheKey);
5270
- if (!diskParams) {
5321
+ const diskEntry = await this.diskCache.get(cacheKey);
5322
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
5271
5323
  return void 0;
5272
5324
  }
5273
- this.memoryCache?.set(cacheKey, diskParams);
5274
- return diskParams;
5325
+ const diskParameters = new RemoteEvalParameters(diskEntry.value.metadata);
5326
+ this.memoryCache?.set(cacheKey, {
5327
+ value: diskParameters,
5328
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
5329
+ });
5330
+ return diskParameters;
5275
5331
  }
5276
5332
  return void 0;
5277
5333
  }
5278
5334
  async set(key, value) {
5279
- const cacheKey = createCacheKey2(key);
5280
- this.memoryCache?.set(cacheKey, value);
5335
+ const cacheKey = createCacheKey2(key, this.namespace);
5336
+ const memoryEntry = {
5337
+ value,
5338
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5339
+ };
5340
+ this.memoryCache?.set(cacheKey, memoryEntry);
5281
5341
  if (this.diskCache) {
5282
- await this.diskCache.set(cacheKey, value);
5342
+ await this.diskCache.set(cacheKey, {
5343
+ value: value._internalSerializeForCache(),
5344
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5345
+ });
5283
5346
  }
5284
5347
  }
5285
5348
  };
@@ -5583,6 +5646,7 @@ var INSTRUMENTATION_NAMES = {
5583
5646
  CLOUDFLARE_THINK: "cloudflare-think",
5584
5647
  COHERE: "cohere",
5585
5648
  CURSOR_SDK: "cursor-sdk",
5649
+ DEEPSEEK_HARNESS: "deepseek-harness",
5586
5650
  EVE: "eve",
5587
5651
  FLUE: "flue",
5588
5652
  GENKIT: "genkit",
@@ -5608,7 +5672,7 @@ var INSTRUMENTATION_NAMES = {
5608
5672
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5609
5673
  "braintrust.spanInstrumentationName"
5610
5674
  );
5611
- var SDK_VERSION = true ? "3.28.0" : "0.0.0";
5675
+ var SDK_VERSION = true ? "3.30.0" : "0.0.0";
5612
5676
  function withSpanInstrumentationName(args, instrumentationName) {
5613
5677
  return {
5614
5678
  ...args,
@@ -5727,6 +5791,16 @@ var datasetSnapshotRegisterResponseSchema = z8.object({
5727
5791
  dataset_snapshot: DatasetSnapshot,
5728
5792
  found_existing: z8.boolean().optional()
5729
5793
  });
5794
+ var datasetObjectInfoSchema = z8.object({
5795
+ object_id: z8.string(),
5796
+ object_name: z8.string(),
5797
+ parent_cols: z8.object({
5798
+ project: z8.object({
5799
+ id: z8.string(),
5800
+ name: z8.string()
5801
+ })
5802
+ })
5803
+ });
5730
5804
  var datasetRestorePreviewResultSchema = z8.object({
5731
5805
  rows_to_restore: z8.number(),
5732
5806
  rows_to_delete: z8.number()
@@ -5940,12 +6014,53 @@ var loginSchema = z8.strictObject({
5940
6014
  });
5941
6015
  var stateNonce = 0;
5942
6016
  var V1_PROXY_SUFFIX = "/v1/proxy";
6017
+ var LOADER_LOGIN_CACHE_MAX = 16;
5943
6018
  function normalizeProxyConnUrl(proxyUrl) {
5944
6019
  return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
5945
6020
  }
5946
6021
  var BraintrustState = class _BraintrustState {
6022
+ id;
6023
+ currentExperiment;
6024
+ // Note: the value of IsAsyncFlush doesn't really matter here, since we
6025
+ // (safely) dynamically cast it whenever retrieving the logger.
6026
+ currentLogger;
6027
+ currentParent;
6028
+ currentSpan;
6029
+ // Any time we re-log in, we directly update the apiConn inside the logger.
6030
+ // This is preferable to replacing the whole logger, which would create the
6031
+ // possibility of multiple loggers floating around, which may not log in a
6032
+ // deterministic order.
6033
+ _bgLogger;
6034
+ _overrideBgLogger = null;
6035
+ appUrl = null;
6036
+ appPublicUrl = null;
6037
+ loginToken = null;
6038
+ orgId = null;
6039
+ orgName = null;
6040
+ apiUrl = null;
6041
+ proxyUrl = null;
6042
+ loggedIn = false;
6043
+ gitMetadataSettings;
6044
+ debugLogLevel;
6045
+ debugLogLevelConfigured = false;
6046
+ fetch = globalThis.fetch;
6047
+ _appConn = null;
6048
+ _apiConn = null;
6049
+ _proxyConn = null;
6050
+ promptCache;
6051
+ parametersCache;
6052
+ spanCache;
6053
+ _idGenerator = null;
6054
+ _contextManager = null;
6055
+ _otelFlushCallback = null;
6056
+ spanOriginEnvironment;
6057
+ traceContextSigningSecret;
6058
+ loaderLoginCache = /* @__PURE__ */ new WeakMap();
6059
+ loginParams;
6060
+ activeLoginOrgNameSelector;
5947
6061
  constructor(loginParams) {
5948
- this.loginParams = loginParams;
6062
+ this.loginParams = { ...loginParams };
6063
+ this.activeLoginOrgNameSelector = loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
5949
6064
  this.id = `${(/* @__PURE__ */ new Date()).toLocaleString()}-${stateNonce++}`;
5950
6065
  this.currentExperiment = void 0;
5951
6066
  this.currentLogger = void 0;
@@ -5982,12 +6097,14 @@ var BraintrustState = class _BraintrustState {
5982
6097
  const {
5983
6098
  memoryCache: parametersMemoryCache,
5984
6099
  diskCache: parametersDiskCache
5985
- } = createCacheLayers({
5986
- memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
5987
- diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
5988
- diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
5989
- getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
5990
- });
6100
+ } = createCacheLayers(
6101
+ {
6102
+ memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
6103
+ diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
6104
+ diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
6105
+ getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
6106
+ }
6107
+ );
5991
6108
  this.parametersCache = new ParametersCache({
5992
6109
  memoryCache: parametersMemoryCache,
5993
6110
  diskCache: parametersDiskCache
@@ -5996,43 +6113,6 @@ var BraintrustState = class _BraintrustState {
5996
6113
  this.spanOriginEnvironment = detectSpanOriginEnvironment();
5997
6114
  this._internalSetTraceContextSigningSecret(loginParams.apiKey);
5998
6115
  }
5999
- loginParams;
6000
- id;
6001
- currentExperiment;
6002
- // Note: the value of IsAsyncFlush doesn't really matter here, since we
6003
- // (safely) dynamically cast it whenever retrieving the logger.
6004
- currentLogger;
6005
- currentParent;
6006
- currentSpan;
6007
- // Any time we re-log in, we directly update the apiConn inside the logger.
6008
- // This is preferable to replacing the whole logger, which would create the
6009
- // possibility of multiple loggers floating around, which may not log in a
6010
- // deterministic order.
6011
- _bgLogger;
6012
- _overrideBgLogger = null;
6013
- appUrl = null;
6014
- appPublicUrl = null;
6015
- loginToken = null;
6016
- orgId = null;
6017
- orgName = null;
6018
- apiUrl = null;
6019
- proxyUrl = null;
6020
- loggedIn = false;
6021
- gitMetadataSettings;
6022
- debugLogLevel;
6023
- debugLogLevelConfigured = false;
6024
- fetch = globalThis.fetch;
6025
- _appConn = null;
6026
- _apiConn = null;
6027
- _proxyConn = null;
6028
- promptCache;
6029
- parametersCache;
6030
- spanCache;
6031
- _idGenerator = null;
6032
- _contextManager = null;
6033
- _otelFlushCallback = null;
6034
- spanOriginEnvironment;
6035
- traceContextSigningSecret;
6036
6116
  /** @internal */
6037
6117
  _internalSetTraceContextSigningSecret(secret) {
6038
6118
  const normalizedSecret = secret?.trim();
@@ -6057,6 +6137,101 @@ var BraintrustState = class _BraintrustState {
6057
6137
  this._appConn = null;
6058
6138
  this._apiConn = null;
6059
6139
  this._proxyConn = null;
6140
+ this.loaderLoginCache = /* @__PURE__ */ new WeakMap();
6141
+ }
6142
+ /** @internal */
6143
+ async _internalResolveLoaderLoginOptions({
6144
+ apiKey,
6145
+ appUrl,
6146
+ orgName,
6147
+ fetch: fetch2,
6148
+ forceLogin
6149
+ }) {
6150
+ const resolvedAppUrl = appUrl ?? (this.loggedIn ? this.appUrl ?? void 0 : void 0) ?? this.loginParams.appUrl ?? isomorph_default.getEnv("BRAINTRUST_APP_URL") ?? "https://www.braintrust.dev";
6151
+ const resolvedApiKey = apiKey ?? (this.loggedIn ? this.loginToken ?? void 0 : void 0) ?? this.loginParams.apiKey ?? await isomorph_default.getBraintrustApiKey();
6152
+ if (!resolvedApiKey) {
6153
+ throw new Error(
6154
+ "Please specify an api key (e.g. by setting BRAINTRUST_API_KEY)."
6155
+ );
6156
+ }
6157
+ const normalizedApiKey = HTTPConnection.sanitize_token(resolvedApiKey);
6158
+ const usesActiveCredential = this.loggedIn && normalizedApiKey === this.loginToken;
6159
+ const requestedOrgName = orgName ?? (usesActiveCredential ? this.activeLoginOrgNameSelector : void 0) ?? this.loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
6160
+ const resolvedOrgName = orgName ?? (usesActiveCredential ? this.orgName ?? void 0 : void 0) ?? requestedOrgName;
6161
+ const resolvedFetch = fetch2 ?? (this.loggedIn ? this.fetch : void 0) ?? this.loginParams.fetch ?? globalThis.fetch;
6162
+ const credentialCacheNamespace = JSON.stringify([
6163
+ "loader-credential",
6164
+ resolvedAppUrl,
6165
+ requestedOrgName,
6166
+ normalizedApiKey
6167
+ ]);
6168
+ return {
6169
+ apiKey: normalizedApiKey,
6170
+ appUrl: resolvedAppUrl,
6171
+ orgName: resolvedOrgName,
6172
+ fetch: resolvedFetch,
6173
+ forceLogin,
6174
+ credentialCacheNamespace,
6175
+ existingState: !forceLogin && usesActiveCredential && resolvedAppUrl === this.appUrl && resolvedOrgName === this.orgName && resolvedFetch === this.fetch ? this : void 0
6176
+ };
6177
+ }
6178
+ /** @internal */
6179
+ _internalGetLoaderCacheViews(loginOptions, requestState) {
6180
+ const expectedResolvedOrgIdentity = requestState?.orgId && requestState.appUrl ? JSON.stringify([
6181
+ "loader-org",
6182
+ requestState.appUrl,
6183
+ requestState.orgId
6184
+ ]) : void 0;
6185
+ return {
6186
+ promptCache: this.promptCache.withNamespace(
6187
+ loginOptions.credentialCacheNamespace,
6188
+ expectedResolvedOrgIdentity
6189
+ ),
6190
+ parametersCache: this.parametersCache.withNamespace(
6191
+ loginOptions.credentialCacheNamespace,
6192
+ expectedResolvedOrgIdentity
6193
+ )
6194
+ };
6195
+ }
6196
+ /** @internal */
6197
+ async _internalGetLoaderState({
6198
+ apiKey,
6199
+ appUrl,
6200
+ orgName,
6201
+ fetch: fetch2,
6202
+ forceLogin,
6203
+ existingState
6204
+ }) {
6205
+ if (existingState) {
6206
+ return existingState;
6207
+ }
6208
+ let cache = this.loaderLoginCache.get(fetch2);
6209
+ if (!cache) {
6210
+ cache = new LRUCache({ max: LOADER_LOGIN_CACHE_MAX });
6211
+ this.loaderLoginCache.set(fetch2, cache);
6212
+ }
6213
+ const cacheKey = JSON.stringify([appUrl, orgName, apiKey]);
6214
+ if (!forceLogin) {
6215
+ const cachedState = cache.get(cacheKey);
6216
+ if (cachedState) {
6217
+ return cachedState;
6218
+ }
6219
+ }
6220
+ const statePromise = loginToLoaderRequestState({
6221
+ orgName,
6222
+ apiKey,
6223
+ appUrl,
6224
+ fetch: fetch2
6225
+ });
6226
+ cache.set(cacheKey, statePromise);
6227
+ try {
6228
+ return await statePromise;
6229
+ } catch (error) {
6230
+ if (cache.get(cacheKey) === statePromise) {
6231
+ cache.delete(cacheKey);
6232
+ }
6233
+ throw error;
6234
+ }
6060
6235
  }
6061
6236
  resetIdGenState() {
6062
6237
  this._idGenerator = null;
@@ -6105,6 +6280,8 @@ var BraintrustState = class _BraintrustState {
6105
6280
  this.debugLogLevel = other.debugLogLevel;
6106
6281
  this.debugLogLevelConfigured = other.debugLogLevelConfigured;
6107
6282
  this.traceContextSigningSecret = other.traceContextSigningSecret;
6283
+ this.fetch = other.fetch;
6284
+ this.activeLoginOrgNameSelector = other.activeLoginOrgNameSelector;
6108
6285
  setGlobalDebugLogLevel(
6109
6286
  this.debugLogLevelConfigured ? this.debugLogLevel ?? false : void 0
6110
6287
  );
@@ -6344,36 +6521,85 @@ var FailedHTTPResponse = class extends Error {
6344
6521
  status;
6345
6522
  text;
6346
6523
  data;
6347
- constructor(status, text, data) {
6524
+ cause;
6525
+ constructor(status, text, data, cause) {
6348
6526
  super(`${status}: ${text} (${data})`);
6349
6527
  this.status = status;
6350
6528
  this.text = text;
6351
6529
  this.data = data;
6530
+ this.cause = cause;
6531
+ }
6532
+ };
6533
+ var HTTPTransportError = class extends Error {
6534
+ cause;
6535
+ constructor(cause) {
6536
+ super(cause instanceof Error ? cause.message : String(cause));
6537
+ this.name = "HTTPTransportError";
6538
+ this.cause = cause;
6352
6539
  }
6353
6540
  };
6541
+ var httpTransportErrorCauses = /* @__PURE__ */ new WeakSet();
6542
+ function recordHTTPTransportError(error) {
6543
+ if (typeof error === "object" && error !== null || typeof error === "function") {
6544
+ httpTransportErrorCauses.add(error);
6545
+ }
6546
+ }
6547
+ function rethrowHTTPTransportError(error, classifyTransportErrors) {
6548
+ if (classifyTransportErrors) {
6549
+ throw new HTTPTransportError(error);
6550
+ }
6551
+ recordHTTPTransportError(error);
6552
+ throw error;
6553
+ }
6554
+ function isLoaderCacheFallbackError(error) {
6555
+ if (error instanceof FailedHTTPResponse) {
6556
+ return error.status === 408 || error.status === 429 || error.status >= 500;
6557
+ }
6558
+ if (error instanceof HTTPTransportError) {
6559
+ return true;
6560
+ }
6561
+ return (typeof error === "object" && error !== null || typeof error === "function") && httpTransportErrorCauses.has(error);
6562
+ }
6563
+ async function readJSONResponse(response, classifyTransportErrors = false) {
6564
+ let data;
6565
+ try {
6566
+ data = await response.text();
6567
+ } catch (error) {
6568
+ rethrowHTTPTransportError(error, classifyTransportErrors);
6569
+ }
6570
+ return JSON.parse(data);
6571
+ }
6354
6572
  async function checkResponse(resp) {
6355
6573
  if (resp.ok) {
6356
6574
  return resp;
6357
- } else {
6575
+ }
6576
+ let data;
6577
+ try {
6578
+ data = await resp.text();
6579
+ } catch (error) {
6358
6580
  throw new FailedHTTPResponse(
6359
6581
  resp.status,
6360
6582
  resp.statusText,
6361
- await resp.text()
6583
+ "Unable to read response body",
6584
+ error
6362
6585
  );
6363
6586
  }
6587
+ throw new FailedHTTPResponse(resp.status, resp.statusText, data);
6364
6588
  }
6365
6589
  var HTTPConnection = class _HTTPConnection {
6366
- base_url;
6367
- token;
6368
- headers;
6369
- fetch;
6370
- constructor(base_url, fetch2) {
6590
+ constructor(base_url, fetch2, classifyTransportErrors = false) {
6591
+ this.classifyTransportErrors = classifyTransportErrors;
6371
6592
  this.base_url = base_url;
6372
6593
  this.token = null;
6373
6594
  this.headers = {};
6374
6595
  this._reset();
6375
6596
  this.fetch = fetch2;
6376
6597
  }
6598
+ classifyTransportErrors;
6599
+ base_url;
6600
+ token;
6601
+ headers;
6602
+ fetch;
6377
6603
  setFetch(fetch2) {
6378
6604
  this.fetch = fetch2;
6379
6605
  }
@@ -6413,9 +6639,9 @@ var HTTPConnection = class _HTTPConnection {
6413
6639
  ).toString();
6414
6640
  const this_fetch = this.fetch;
6415
6641
  const this_headers = this.headers;
6416
- return await checkResponse(
6417
- // Using toString() here makes it work with isomorphic fetch
6418
- await this_fetch(url.toString(), {
6642
+ let response;
6643
+ try {
6644
+ response = await this_fetch(url.toString(), {
6419
6645
  headers: {
6420
6646
  Accept: "application/json",
6421
6647
  ...this_headers,
@@ -6423,8 +6649,14 @@ var HTTPConnection = class _HTTPConnection {
6423
6649
  },
6424
6650
  keepalive: true,
6425
6651
  ...rest
6426
- })
6427
- );
6652
+ });
6653
+ } catch (error) {
6654
+ if (config?.signal?.aborted) {
6655
+ throw getAbortReason(config.signal);
6656
+ }
6657
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
6658
+ }
6659
+ return await checkResponse(response);
6428
6660
  }
6429
6661
  async post(path, params, config, retries = 0) {
6430
6662
  const { headers, ...rest } = config || {};
@@ -6434,8 +6666,9 @@ var HTTPConnection = class _HTTPConnection {
6434
6666
  const tries = retries + 1;
6435
6667
  for (let i = 0; i < tries; i++) {
6436
6668
  try {
6437
- return await checkResponse(
6438
- await this_fetch(_urljoin(this_base_url, path), {
6669
+ let response;
6670
+ try {
6671
+ response = await this_fetch(_urljoin(this_base_url, path), {
6439
6672
  method: "POST",
6440
6673
  headers: {
6441
6674
  Accept: "application/json",
@@ -6446,8 +6679,14 @@ var HTTPConnection = class _HTTPConnection {
6446
6679
  body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
6447
6680
  keepalive: true,
6448
6681
  ...rest
6449
- })
6450
- );
6682
+ });
6683
+ } catch (error) {
6684
+ if (config?.signal?.aborted) {
6685
+ throw getAbortReason(config.signal);
6686
+ }
6687
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
6688
+ }
6689
+ return await checkResponse(response);
6451
6690
  } catch (error) {
6452
6691
  if (config?.signal?.aborted) {
6453
6692
  throw getAbortReason(config.signal);
@@ -6472,7 +6711,7 @@ var HTTPConnection = class _HTTPConnection {
6472
6711
  for (let i = 0; i < tries; i++) {
6473
6712
  try {
6474
6713
  const resp = await this.get(`${object_type}`, args);
6475
- return await resp.json();
6714
+ return await readJSONResponse(resp, this.classifyTransportErrors);
6476
6715
  } catch (e) {
6477
6716
  if (i < tries - 1) {
6478
6717
  debugLogger.debug(
@@ -6495,7 +6734,7 @@ var HTTPConnection = class _HTTPConnection {
6495
6734
  const resp = await this.post(`${object_type}`, args, {
6496
6735
  headers: { "Content-Type": "application/json" }
6497
6736
  });
6498
- return await resp.json();
6737
+ return await readJSONResponse(resp, this.classifyTransportErrors);
6499
6738
  }
6500
6739
  // Custom inspect for Node.js console.log
6501
6740
  [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
@@ -8543,6 +8782,7 @@ function initDataset(projectOrOptions, optionalOptions) {
8543
8782
  const {
8544
8783
  project,
8545
8784
  dataset,
8785
+ datasetId,
8546
8786
  description,
8547
8787
  version,
8548
8788
  snapshotName,
@@ -8558,6 +8798,11 @@ function initDataset(projectOrOptions, optionalOptions) {
8558
8798
  state: stateArg,
8559
8799
  _internal_btql
8560
8800
  } = options;
8801
+ if (datasetId !== void 0 && (description !== void 0 || metadata !== void 0)) {
8802
+ throw new Error(
8803
+ "Cannot specify description or metadata when datasetId is provided"
8804
+ );
8805
+ }
8561
8806
  const selection = normalizeDatasetSelection({
8562
8807
  version,
8563
8808
  environment,
@@ -8578,6 +8823,35 @@ function initDataset(projectOrOptions, optionalOptions) {
8578
8823
  fetch: fetch2,
8579
8824
  forceLogin
8580
8825
  });
8826
+ if (datasetId !== void 0) {
8827
+ const objectInfo = datasetObjectInfoSchema.array().parse(
8828
+ await state.appConn().post_json("api/self/get_object_info", {
8829
+ object_type: "dataset",
8830
+ object_ids: [datasetId]
8831
+ })
8832
+ );
8833
+ if (objectInfo.length === 0) {
8834
+ throw new Error(`Dataset with ID ${datasetId} not found`);
8835
+ }
8836
+ if (objectInfo.length !== 1) {
8837
+ throw new Error(
8838
+ `Expected exactly one dataset with ID ${datasetId}, but found ${objectInfo.length}`
8839
+ );
8840
+ }
8841
+ const datasetInfo = objectInfo[0];
8842
+ return {
8843
+ project: {
8844
+ id: datasetInfo.parent_cols.project.id,
8845
+ name: datasetInfo.parent_cols.project.name,
8846
+ fullInfo: datasetInfo.parent_cols.project
8847
+ },
8848
+ dataset: {
8849
+ id: datasetInfo.object_id,
8850
+ name: datasetInfo.object_name,
8851
+ fullInfo: datasetInfo
8852
+ }
8853
+ };
8854
+ }
8581
8855
  const args = {
8582
8856
  org_id: state.orgId,
8583
8857
  project_name: project,
@@ -8731,6 +9005,24 @@ function initLogger(options = {}) {
8731
9005
  }
8732
9006
  return ret;
8733
9007
  }
9008
+ async function runCredentialScopedLoaderRequest(state, loginOptions, request) {
9009
+ const resolvedLoginOptions = await state._internalResolveLoaderLoginOptions(loginOptions);
9010
+ let cacheViews = state._internalGetLoaderCacheViews(resolvedLoginOptions);
9011
+ try {
9012
+ const requestState = await state._internalGetLoaderState(resolvedLoginOptions);
9013
+ cacheViews = state._internalGetLoaderCacheViews(
9014
+ resolvedLoginOptions,
9015
+ requestState
9016
+ );
9017
+ return {
9018
+ ok: true,
9019
+ response: await request(requestState),
9020
+ ...cacheViews
9021
+ };
9022
+ } catch (error) {
9023
+ return { ok: false, error, ...cacheViews };
9024
+ }
9025
+ }
8734
9026
  async function loadPrompt({
8735
9027
  projectName,
8736
9028
  projectId,
@@ -8755,43 +9047,47 @@ async function loadPrompt({
8755
9047
  throw new Error("Must specify slug");
8756
9048
  }
8757
9049
  const state = stateArg ?? _globalState;
8758
- let response;
8759
- try {
8760
- await state.login({
8761
- orgName,
8762
- apiKey,
8763
- appUrl,
8764
- fetch: fetch2,
8765
- forceLogin
8766
- });
8767
- if (id) {
8768
- response = await state.apiConn().get_json(`v1/prompt/${id}`, versionOrEnvironment);
8769
- if (response) {
8770
- response = { objects: [response] };
9050
+ const result = await runCredentialScopedLoaderRequest(
9051
+ state,
9052
+ { orgName, apiKey, appUrl, fetch: fetch2, forceLogin },
9053
+ async (requestState) => {
9054
+ let response2;
9055
+ if (id) {
9056
+ response2 = await requestState.apiConn().get_json(`v1/prompt/${id}`, versionOrEnvironment);
9057
+ if (response2) {
9058
+ response2 = { objects: [response2] };
9059
+ }
9060
+ } else {
9061
+ response2 = await requestState.apiConn().get_json("v1/prompt", {
9062
+ project_name: projectName,
9063
+ project_id: projectId,
9064
+ slug,
9065
+ ...versionOrEnvironment
9066
+ });
8771
9067
  }
8772
- } else {
8773
- response = await state.apiConn().get_json("v1/prompt", {
8774
- project_name: projectName,
8775
- project_id: projectId,
8776
- slug,
8777
- ...versionOrEnvironment
8778
- });
9068
+ return response2;
9069
+ }
9070
+ );
9071
+ const { promptCache } = result;
9072
+ if (!result.ok) {
9073
+ const e = result.error;
9074
+ if (!isLoaderCacheFallbackError(e)) {
9075
+ throw e;
8779
9076
  }
8780
- } catch (e) {
8781
9077
  if (version || environment) {
8782
9078
  throw new Error(`Prompt not found with specified parameters: ${e}`);
8783
9079
  }
8784
9080
  debugLogger.forState(state).warn("Failed to load prompt, attempting to fall back to cache:", e);
8785
9081
  let prompt2;
8786
9082
  if (id) {
8787
- prompt2 = await state.promptCache.get({ id });
9083
+ prompt2 = await promptCache.get({ id });
8788
9084
  if (!prompt2) {
8789
9085
  throw new Error(
8790
9086
  `Prompt with id ${id} not found (not found on server or in local cache): ${e}`
8791
9087
  );
8792
9088
  }
8793
9089
  } else {
8794
- prompt2 = await state.promptCache.get({
9090
+ prompt2 = await promptCache.get({
8795
9091
  slug,
8796
9092
  projectId,
8797
9093
  projectName,
@@ -8807,6 +9103,7 @@ async function loadPrompt({
8807
9103
  }
8808
9104
  return prompt2;
8809
9105
  }
9106
+ const { response } = result;
8810
9107
  if (!("objects" in response) || response.objects.length === 0) {
8811
9108
  if (id) {
8812
9109
  throw new Error(`Prompt with id ${id} not found.`);
@@ -8830,9 +9127,9 @@ async function loadPrompt({
8830
9127
  const prompt = new Prompt2(metadata, defaults || {}, noTrace);
8831
9128
  try {
8832
9129
  if (id) {
8833
- await state.promptCache.set({ id }, prompt);
9130
+ await promptCache.set({ id }, prompt);
8834
9131
  } else if (slug) {
8835
- await state.promptCache.set(
9132
+ await promptCache.set(
8836
9133
  { slug, projectId, projectName, version: version ?? "latest" },
8837
9134
  prompt
8838
9135
  );
@@ -8864,46 +9161,50 @@ async function loadParameters({
8864
9161
  throw new Error("Must specify slug");
8865
9162
  }
8866
9163
  const state = stateArg ?? _globalState;
8867
- let response;
8868
- try {
8869
- await state.login({
8870
- orgName,
8871
- apiKey,
8872
- appUrl,
8873
- fetch: fetch2,
8874
- forceLogin
8875
- });
8876
- if (id) {
8877
- response = await state.apiConn().get_json(`v1/function/${id}`, {
8878
- ...versionOrEnvironment
8879
- });
8880
- if (response) {
8881
- response = { objects: [response] };
9164
+ const result = await runCredentialScopedLoaderRequest(
9165
+ state,
9166
+ { orgName, apiKey, appUrl, fetch: fetch2, forceLogin },
9167
+ async (requestState) => {
9168
+ let response2;
9169
+ if (id) {
9170
+ response2 = await requestState.apiConn().get_json(`v1/function/${id}`, {
9171
+ ...versionOrEnvironment
9172
+ });
9173
+ if (response2) {
9174
+ response2 = { objects: [response2] };
9175
+ }
9176
+ } else {
9177
+ response2 = await requestState.apiConn().get_json("v1/function", {
9178
+ project_name: projectName,
9179
+ project_id: projectId,
9180
+ slug,
9181
+ function_type: "parameters",
9182
+ ...versionOrEnvironment
9183
+ });
8882
9184
  }
8883
- } else {
8884
- response = await state.apiConn().get_json("v1/function", {
8885
- project_name: projectName,
8886
- project_id: projectId,
8887
- slug,
8888
- function_type: "parameters",
8889
- ...versionOrEnvironment
8890
- });
9185
+ return response2;
9186
+ }
9187
+ );
9188
+ const { parametersCache } = result;
9189
+ if (!result.ok) {
9190
+ const e = result.error;
9191
+ if (!isLoaderCacheFallbackError(e)) {
9192
+ throw e;
8891
9193
  }
8892
- } catch (e) {
8893
9194
  if (version || environment) {
8894
9195
  throw new Error(`Parameters not found with specified parameters: ${e}`);
8895
9196
  }
8896
9197
  debugLogger.forState(state).warn("Failed to load parameters, attempting to fall back to cache:", e);
8897
9198
  let parameters2;
8898
9199
  if (id) {
8899
- parameters2 = await state.parametersCache.get({ id });
9200
+ parameters2 = await parametersCache.get({ id });
8900
9201
  if (!parameters2) {
8901
9202
  throw new Error(
8902
9203
  `Parameters with id ${id} not found (not found on server or in local cache): ${e}`
8903
9204
  );
8904
9205
  }
8905
9206
  } else {
8906
- parameters2 = await state.parametersCache.get({
9207
+ parameters2 = await parametersCache.get({
8907
9208
  slug,
8908
9209
  projectId,
8909
9210
  projectName,
@@ -8919,6 +9220,7 @@ async function loadParameters({
8919
9220
  }
8920
9221
  return parameters2;
8921
9222
  }
9223
+ const { response } = result;
8922
9224
  if (!("objects" in response) || response.objects.length === 0) {
8923
9225
  if (id) {
8924
9226
  throw new Error(`Parameters with id ${id} not found.`);
@@ -8942,9 +9244,9 @@ async function loadParameters({
8942
9244
  const parameters = new RemoteEvalParameters(metadata);
8943
9245
  try {
8944
9246
  if (id) {
8945
- await state.parametersCache.set({ id }, parameters);
9247
+ await parametersCache.set({ id }, parameters);
8946
9248
  } else if (slug) {
8947
- await state.parametersCache.set(
9249
+ await parametersCache.set(
8948
9250
  { slug, projectId, projectName, version: version ?? "latest" },
8949
9251
  parameters
8950
9252
  );
@@ -8985,6 +9287,52 @@ async function login(options = {}) {
8985
9287
  await state.login(options);
8986
9288
  return state;
8987
9289
  }
9290
+ async function loginToLoaderRequestState({
9291
+ appUrl,
9292
+ apiKey,
9293
+ orgName,
9294
+ fetch: fetch2
9295
+ }) {
9296
+ let orgId;
9297
+ let apiUrl;
9298
+ if (apiKey === TEST_API_KEY) {
9299
+ orgId = "test-org-id";
9300
+ apiUrl = "https://braintrust.dev/fake-api-url";
9301
+ } else {
9302
+ let loginResponse;
9303
+ try {
9304
+ loginResponse = await fetch2(_urljoin(appUrl, `/api/apikey/login`), {
9305
+ method: "POST",
9306
+ headers: {
9307
+ "Content-Type": "application/json",
9308
+ Authorization: `Bearer ${apiKey}`
9309
+ }
9310
+ });
9311
+ } catch (error) {
9312
+ throw new HTTPTransportError(error);
9313
+ }
9314
+ const info = await readJSONResponse(
9315
+ await checkResponse(loginResponse),
9316
+ true
9317
+ );
9318
+ const org = selectLoginOrg(info.org_info, orgName);
9319
+ orgId = org.id;
9320
+ apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
9321
+ if (!apiUrl) {
9322
+ throw new Error(
9323
+ 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."
9324
+ );
9325
+ }
9326
+ }
9327
+ const apiConnection = new HTTPConnection(apiUrl, fetch2, true);
9328
+ apiConnection.set_token(apiKey);
9329
+ apiConnection.make_long_lived();
9330
+ return {
9331
+ appUrl,
9332
+ orgId,
9333
+ apiConn: () => apiConnection
9334
+ };
9335
+ }
8988
9336
  async function loginToState(options = {}) {
8989
9337
  const {
8990
9338
  appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
@@ -9016,16 +9364,18 @@ async function loginToState(options = {}) {
9016
9364
  _saveOrgInfo(state, testOrgInfo, testOrgInfo[0].name);
9017
9365
  return state;
9018
9366
  } else {
9019
- const resp = await checkResponse(
9020
- await fetch2(_urljoin(state.appUrl, `/api/apikey/login`), {
9367
+ const loginResponse = await fetch2(
9368
+ _urljoin(state.appUrl, `/api/apikey/login`),
9369
+ {
9021
9370
  method: "POST",
9022
9371
  headers: {
9023
9372
  "Content-Type": "application/json",
9024
9373
  Authorization: `Bearer ${apiKey}`
9025
9374
  }
9026
- })
9375
+ }
9027
9376
  );
9028
- const info = await resp.json();
9377
+ const resp = await checkResponse(loginResponse);
9378
+ const info = await readJSONResponse(resp);
9029
9379
  _saveOrgInfo(state, info.org_info, orgName);
9030
9380
  if (!state.apiUrl) {
9031
9381
  if (orgName) {
@@ -9528,11 +9878,11 @@ function wrapTraced(fn, args) {
9528
9878
  }
9529
9879
  if (args?.asyncFlush) {
9530
9880
  return ((...fnArgs) => traced((span) => {
9531
- if (!hasExplicitInput) {
9881
+ if (!args?.noTraceIO && !hasExplicitInput) {
9532
9882
  span.log({ input: fnArgs });
9533
9883
  }
9534
9884
  const output = fn(...fnArgs);
9535
- if (!hasExplicitOutput) {
9885
+ if (!args?.noTraceIO && !hasExplicitOutput) {
9536
9886
  if (output instanceof Promise) {
9537
9887
  return (async () => {
9538
9888
  const result = await output;
@@ -9547,12 +9897,12 @@ function wrapTraced(fn, args) {
9547
9897
  }, spanArgs));
9548
9898
  } else {
9549
9899
  return ((...fnArgs) => traced(async (span) => {
9550
- if (!hasExplicitInput) {
9900
+ if (!args?.noTraceIO && !hasExplicitInput) {
9551
9901
  span.log({ input: fnArgs });
9552
9902
  }
9553
9903
  const outputResult = fn(...fnArgs);
9554
9904
  const output = await outputResult;
9555
- if (!hasExplicitOutput) {
9905
+ if (!args?.noTraceIO && !hasExplicitOutput) {
9556
9906
  span.log({ output });
9557
9907
  }
9558
9908
  return output;
@@ -9569,6 +9919,15 @@ function _internalStartSpanWithInitialMerge(args) {
9569
9919
  [INITIAL_SPAN_WRITE_AS_MERGE]: true
9570
9920
  }).span;
9571
9921
  }
9922
+ function _internalStartSpanWithInitialMergeAndParentSpanIds(args) {
9923
+ return startSpanAndIsLogger(
9924
+ {
9925
+ ...args,
9926
+ [INITIAL_SPAN_WRITE_AS_MERGE]: true
9927
+ },
9928
+ { useParentSpanIdsForObjectParent: true }
9929
+ ).span;
9930
+ }
9572
9931
  function _internalStartSpanWithContext(args, context) {
9573
9932
  return startSpanAndIsLogger({
9574
9933
  ...args,
@@ -9582,7 +9941,7 @@ async function flush(options) {
9582
9941
  function setFetch(fetch2) {
9583
9942
  _internalGetGlobalState().setFetch(fetch2);
9584
9943
  }
9585
- function startSpanAndIsLogger(args) {
9944
+ function startSpanAndIsLogger(args, internalOptions) {
9586
9945
  const state = args?.state ?? _globalState;
9587
9946
  const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
9588
9947
  asyncFlush: args?.asyncFlush,
@@ -9596,7 +9955,7 @@ function startSpanAndIsLogger(args) {
9596
9955
  ) ? {
9597
9956
  spanId: parentObject.data.span_id,
9598
9957
  rootSpanId: parentObject.data.root_span_id
9599
- } : void 0;
9958
+ } : internalOptions?.useParentSpanIdsForObjectParent ? args?.parentSpanIds : void 0;
9600
9959
  const { parent: _ignoredParent, ...spanArgs } = args ?? {};
9601
9960
  const span = new SpanImpl({
9602
9961
  state,
@@ -9678,27 +10037,28 @@ async function* asyncGeneratorWithCurrent(span, gen, state = void 0) {
9678
10037
  function withParent(parent, callback, state = void 0) {
9679
10038
  return (state ?? _globalState).currentParent.run(parent, () => callback());
9680
10039
  }
9681
- function _saveOrgInfo(state, org_info, org_name) {
9682
- if (org_info.length === 0) {
10040
+ function _saveOrgInfo(state, orgInfo, orgName) {
10041
+ const org = selectLoginOrg(orgInfo, orgName);
10042
+ state.orgId = org.id;
10043
+ state.orgName = org.name;
10044
+ state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
10045
+ state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
10046
+ state.gitMetadataSettings = org.git_metadata || void 0;
10047
+ }
10048
+ function selectLoginOrg(orgInfo, orgName) {
10049
+ if (orgInfo.length === 0) {
9683
10050
  throw new LoginInvalidOrgError(
9684
10051
  "This user is not part of any organizations."
9685
10052
  );
9686
10053
  }
9687
- for (const org of org_info) {
9688
- if (org_name === void 0 || org.name === org_name) {
9689
- state.orgId = org.id;
9690
- state.orgName = org.name;
9691
- state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
9692
- state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
9693
- state.gitMetadataSettings = org.git_metadata || void 0;
9694
- break;
10054
+ for (const org of orgInfo) {
10055
+ if (orgName === void 0 || org.name === orgName) {
10056
+ return org;
9695
10057
  }
9696
10058
  }
9697
- if (state.orgId === void 0) {
9698
- throw new LoginInvalidOrgError(
9699
- `Organization ${org_name} not found. Must be one of ${org_info.map((x) => x.name).join(", ")}`
9700
- );
9701
- }
10059
+ throw new LoginInvalidOrgError(
10060
+ `Organization ${orgName} not found. Must be one of ${orgInfo.map((org) => org.name).join(", ")}`
10061
+ );
9702
10062
  }
9703
10063
  function validateTags(tags) {
9704
10064
  const seen = /* @__PURE__ */ new Set();
@@ -11604,6 +11964,14 @@ var Prompt2 = class _Prompt {
11604
11964
  static isPrompt(data) {
11605
11965
  return typeof data === "object" && data !== null && "__braintrust_prompt_marker" in data;
11606
11966
  }
11967
+ /** @internal */
11968
+ _internalSerializeForCache() {
11969
+ return {
11970
+ metadata: this.metadata,
11971
+ defaults: this.defaults,
11972
+ noTrace: this.noTrace
11973
+ };
11974
+ }
11607
11975
  static fromPromptData(name, promptData) {
11608
11976
  return new _Prompt(
11609
11977
  {
@@ -11644,6 +12012,10 @@ var RemoteEvalParameters = class {
11644
12012
  get data() {
11645
12013
  return this.metadata.function_data.data ?? {};
11646
12014
  }
12015
+ /** @internal */
12016
+ _internalSerializeForCache() {
12017
+ return { metadata: this.metadata };
12018
+ }
11647
12019
  validate(data) {
11648
12020
  if (typeof data !== "object" || data === null) {
11649
12021
  return false;
@@ -12430,56 +12802,14 @@ function suppressionStore() {
12430
12802
  autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
12431
12803
  return autoInstrumentationSuppressionStore;
12432
12804
  }
12433
- function currentFrames() {
12434
- return suppressionStore().getStore()?.frames ?? [];
12435
- }
12436
12805
  function isAutoInstrumentationSuppressed() {
12437
- const frames = currentFrames();
12438
- return frames[frames.length - 1]?.mode === "suppress";
12806
+ return suppressionStore().getStore() === true;
12439
12807
  }
12440
12808
  function runWithAutoInstrumentationSuppressed(callback) {
12441
- const frame = {
12442
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
12443
- mode: "suppress"
12444
- };
12445
- return suppressionStore().run(
12446
- { frames: [...currentFrames(), frame] },
12447
- callback
12448
- );
12449
- }
12450
- function bindAutoInstrumentationSuppressionToStart(tracingChannel) {
12451
- const startChannel = tracingChannel.start;
12452
- if (!startChannel) {
12453
- return void 0;
12454
- }
12455
- const store = suppressionStore();
12456
- startChannel.bindStore(store, () => ({
12457
- frames: [
12458
- ...currentFrames(),
12459
- {
12460
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
12461
- mode: "suppress"
12462
- }
12463
- ]
12464
- }));
12465
- return () => {
12466
- startChannel.unbindStore(store);
12467
- };
12809
+ return suppressionStore().run(true, callback);
12468
12810
  }
12469
- function enterAutoInstrumentationAllowed() {
12470
- const frame = {
12471
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
12472
- mode: "allow"
12473
- };
12474
- suppressionStore().enterWith({
12475
- frames: [...currentFrames(), frame]
12476
- });
12477
- return () => {
12478
- const frames = currentFrames().filter(
12479
- (candidate) => candidate.id !== frame.id
12480
- );
12481
- suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
12482
- };
12811
+ function runWithAutoInstrumentationAllowed(callback) {
12812
+ return suppressionStore().run(void 0, callback);
12483
12813
  }
12484
12814
 
12485
12815
  // src/instrumentation/core/channel-tracing.ts
@@ -13069,6 +13399,131 @@ function unsubscribeAll(unsubscribers) {
13069
13399
  return [];
13070
13400
  }
13071
13401
 
13402
+ // src/instrumentation/core/channel-definitions.ts
13403
+ function channel(spec) {
13404
+ return spec;
13405
+ }
13406
+ function defineChannels(pkg, channels, options) {
13407
+ const { instrumentationName } = options;
13408
+ return Object.fromEntries(
13409
+ Object.entries(channels).map(([key, spec]) => {
13410
+ const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
13411
+ if (spec.kind === "async") {
13412
+ const asyncSpec = spec;
13413
+ const tracingChannel2 = () => isomorph_default.newTracingChannel(
13414
+ fullChannelName
13415
+ );
13416
+ const intercept2 = (interceptor) => {
13417
+ const hook = tracingChannel2();
13418
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13419
+ };
13420
+ };
13421
+ return [
13422
+ key,
13423
+ {
13424
+ ...asyncSpec,
13425
+ instrumentationName,
13426
+ intercept: intercept2,
13427
+ invoke: (target, thisArg, args, additional) => {
13428
+ const hook = tracingChannel2();
13429
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13430
+ },
13431
+ tracingChannel: tracingChannel2,
13432
+ tracePromise: (fn, context) => tracingChannel2().tracePromise(
13433
+ fn,
13434
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13435
+ context
13436
+ )
13437
+ }
13438
+ ];
13439
+ }
13440
+ const syncSpec = spec;
13441
+ const tracingChannel = () => isomorph_default.newTracingChannel(
13442
+ fullChannelName
13443
+ );
13444
+ const intercept = (interceptor) => {
13445
+ const hook = tracingChannel();
13446
+ return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13447
+ };
13448
+ };
13449
+ return [
13450
+ key,
13451
+ {
13452
+ ...syncSpec,
13453
+ instrumentationName,
13454
+ intercept,
13455
+ invoke: (target, thisArg, args, additional) => {
13456
+ const hook = tracingChannel();
13457
+ return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13458
+ },
13459
+ tracingChannel,
13460
+ traceSync: (fn, context) => tracingChannel().traceSync(
13461
+ fn,
13462
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13463
+ context
13464
+ )
13465
+ }
13466
+ ];
13467
+ })
13468
+ );
13469
+ }
13470
+
13471
+ // src/instrumentation/plugins/openai-channels.ts
13472
+ var openAIChannels = defineChannels(
13473
+ "openai",
13474
+ {
13475
+ filesCreateTraced: channel({
13476
+ channelName: "files.create-traced",
13477
+ kind: "async"
13478
+ }),
13479
+ batchesRetrieveTraced: channel({
13480
+ channelName: "batches.retrieve-traced",
13481
+ kind: "async"
13482
+ }),
13483
+ batchesCompleteTrace: channel({
13484
+ channelName: "batches.complete-trace",
13485
+ kind: "async"
13486
+ }),
13487
+ chatCompletionsCreate: channel({
13488
+ channelName: "chat.completions.create",
13489
+ kind: "async"
13490
+ }),
13491
+ embeddingsCreate: channel({
13492
+ channelName: "embeddings.create",
13493
+ kind: "async"
13494
+ }),
13495
+ betaChatCompletionsParse: channel({
13496
+ channelName: "beta.chat.completions.parse",
13497
+ kind: "async"
13498
+ }),
13499
+ betaChatCompletionsStream: channel({
13500
+ channelName: "beta.chat.completions.stream",
13501
+ kind: "sync-stream"
13502
+ }),
13503
+ moderationsCreate: channel({
13504
+ channelName: "moderations.create",
13505
+ kind: "async"
13506
+ }),
13507
+ responsesCreate: channel({
13508
+ channelName: "responses.create",
13509
+ kind: "async"
13510
+ }),
13511
+ responsesStream: channel({
13512
+ channelName: "responses.stream",
13513
+ kind: "sync-stream"
13514
+ }),
13515
+ responsesParse: channel({
13516
+ channelName: "responses.parse",
13517
+ kind: "async"
13518
+ }),
13519
+ responsesCompact: channel({
13520
+ channelName: "responses.compact",
13521
+ kind: "async"
13522
+ })
13523
+ },
13524
+ { instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
13525
+ );
13526
+
13072
13527
  // src/wrappers/attachment-utils.ts
13073
13528
  function getExtensionFromMediaType(mediaType) {
13074
13529
  const extensionMap = {
@@ -13244,118 +13699,91 @@ function processInputAttachments(input) {
13244
13699
  return processNode(input);
13245
13700
  }
13246
13701
 
13247
- // src/instrumentation/core/channel-definitions.ts
13248
- function channel(spec) {
13249
- return spec;
13250
- }
13251
- function defineChannels(pkg, channels, options) {
13252
- const { instrumentationName } = options;
13253
- return Object.fromEntries(
13254
- Object.entries(channels).map(([key, spec]) => {
13255
- const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
13256
- if (spec.kind === "async") {
13257
- const asyncSpec = spec;
13258
- const tracingChannel2 = () => isomorph_default.newTracingChannel(
13259
- fullChannelName
13260
- );
13261
- const intercept2 = (interceptor) => {
13262
- const hook = tracingChannel2();
13263
- return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13264
- };
13265
- };
13266
- return [
13267
- key,
13268
- {
13269
- ...asyncSpec,
13270
- instrumentationName,
13271
- intercept: intercept2,
13272
- invoke: (target, thisArg, args, additional) => {
13273
- const hook = tracingChannel2();
13274
- return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13275
- },
13276
- tracingChannel: tracingChannel2,
13277
- tracePromise: (fn, context) => tracingChannel2().tracePromise(
13278
- fn,
13279
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13280
- context
13281
- )
13282
- }
13283
- ];
13702
+ // src/instrumentation/plugins/openai-span-data.ts
13703
+ var OPENAI_METADATA_KEYS = [
13704
+ "model",
13705
+ "temperature",
13706
+ "top_p",
13707
+ "max_tokens",
13708
+ "frequency_penalty",
13709
+ "presence_penalty",
13710
+ "stop",
13711
+ "response_format",
13712
+ "tools",
13713
+ "tool_choice",
13714
+ "parallel_tool_calls",
13715
+ "max_tool_calls"
13716
+ ];
13717
+ function batchMetadata(params) {
13718
+ const metadata = { provider: "openai" };
13719
+ for (const key of OPENAI_METADATA_KEYS) {
13720
+ try {
13721
+ const value = Reflect.get(params, key);
13722
+ if (value !== void 0) {
13723
+ metadata[key] = value;
13284
13724
  }
13285
- const syncSpec = spec;
13286
- const tracingChannel = () => isomorph_default.newTracingChannel(
13287
- fullChannelName
13288
- );
13289
- const intercept = (interceptor) => {
13290
- const hook = tracingChannel();
13291
- return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
13292
- };
13293
- };
13294
- return [
13295
- key,
13296
- {
13297
- ...syncSpec,
13298
- instrumentationName,
13299
- intercept,
13300
- invoke: (target, thisArg, args, additional) => {
13301
- const hook = tracingChannel();
13302
- return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
13303
- },
13304
- tracingChannel,
13305
- traceSync: (fn, context) => tracingChannel().traceSync(
13306
- fn,
13307
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13308
- context
13309
- )
13310
- }
13311
- ];
13312
- })
13313
- );
13725
+ } catch {
13726
+ }
13727
+ }
13728
+ return metadata;
13729
+ }
13730
+ function extractOpenAIBatchInput(endpoint, params) {
13731
+ const input = endpoint === "/v1/chat/completions" ? params.messages : params.input;
13732
+ return {
13733
+ input: processInputAttachments(input),
13734
+ metadata: batchMetadata(params)
13735
+ };
13736
+ }
13737
+ function extractOpenAIChatInput(params) {
13738
+ const { messages, ...metadata } = params;
13739
+ return {
13740
+ input: processInputAttachments(messages),
13741
+ metadata: { ...metadata, provider: "openai" }
13742
+ };
13743
+ }
13744
+ function extractOpenAIResponsesInput(params) {
13745
+ const { input, ...metadata } = params;
13746
+ return {
13747
+ input: processInputAttachments(input),
13748
+ metadata: { ...metadata, provider: "openai" }
13749
+ };
13750
+ }
13751
+ function extractOpenAIResponsesMetadata(result) {
13752
+ if (!result) {
13753
+ return void 0;
13754
+ }
13755
+ const { output: _output, usage: _usage, ...metadata } = result;
13756
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
13757
+ }
13758
+ function processImagesInOutput(output) {
13759
+ if (Array.isArray(output)) {
13760
+ return output.map(processImagesInOutput);
13761
+ }
13762
+ if (isObject(output) && output.type === "image_generation_call" && typeof output.result === "string" && output.result) {
13763
+ const fileExtension = output.output_format || "png";
13764
+ const contentType = `image/${fileExtension}`;
13765
+ const baseFilename = typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
13766
+ let binaryString;
13767
+ try {
13768
+ binaryString = atob(output.result);
13769
+ } catch {
13770
+ return output;
13771
+ }
13772
+ const bytes = new Uint8Array(binaryString.length);
13773
+ for (let i = 0; i < binaryString.length; i++) {
13774
+ bytes[i] = binaryString.charCodeAt(i);
13775
+ }
13776
+ return {
13777
+ ...output,
13778
+ result: new Attachment({
13779
+ data: new Blob([bytes], { type: contentType }),
13780
+ filename: `${baseFilename}.${fileExtension}`,
13781
+ contentType
13782
+ })
13783
+ };
13784
+ }
13785
+ return output;
13314
13786
  }
13315
-
13316
- // src/instrumentation/plugins/openai-channels.ts
13317
- var openAIChannels = defineChannels(
13318
- "openai",
13319
- {
13320
- chatCompletionsCreate: channel({
13321
- channelName: "chat.completions.create",
13322
- kind: "async"
13323
- }),
13324
- embeddingsCreate: channel({
13325
- channelName: "embeddings.create",
13326
- kind: "async"
13327
- }),
13328
- betaChatCompletionsParse: channel({
13329
- channelName: "beta.chat.completions.parse",
13330
- kind: "async"
13331
- }),
13332
- betaChatCompletionsStream: channel({
13333
- channelName: "beta.chat.completions.stream",
13334
- kind: "sync-stream"
13335
- }),
13336
- moderationsCreate: channel({
13337
- channelName: "moderations.create",
13338
- kind: "async"
13339
- }),
13340
- responsesCreate: channel({
13341
- channelName: "responses.create",
13342
- kind: "async"
13343
- }),
13344
- responsesStream: channel({
13345
- channelName: "responses.stream",
13346
- kind: "sync-stream"
13347
- }),
13348
- responsesParse: channel({
13349
- channelName: "responses.parse",
13350
- kind: "async"
13351
- }),
13352
- responsesCompact: channel({
13353
- channelName: "responses.compact",
13354
- kind: "async"
13355
- })
13356
- },
13357
- { instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
13358
- );
13359
13787
 
13360
13788
  // src/openai-utils.ts
13361
13789
  var BRAINTRUST_CACHED_STREAM_METRIC = "__braintrust_cached_metric";
@@ -13412,23 +13840,573 @@ function getCachedMetricFromHeaders(headers) {
13412
13840
  return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
13413
13841
  }
13414
13842
 
13843
+ // src/instrumentation/plugins/openai-batch-instrumentation.ts
13844
+ var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
13845
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
13846
+ "completed",
13847
+ "failed",
13848
+ "expired",
13849
+ "cancelled"
13850
+ ]);
13851
+ var pendingBatchTraces = /* @__PURE__ */ new Map();
13852
+ function read(value, key) {
13853
+ if (!isObject(value)) {
13854
+ return void 0;
13855
+ }
13856
+ try {
13857
+ return Reflect.get(value, key);
13858
+ } catch {
13859
+ return void 0;
13860
+ }
13861
+ }
13862
+ function isBatchRecordIterable(value) {
13863
+ if (value === null || typeof value !== "object" && typeof value !== "function") {
13864
+ return false;
13865
+ }
13866
+ return typeof read(value, Symbol.iterator) === "function" || typeof read(value, Symbol.asyncIterator) === "function";
13867
+ }
13868
+ function validCustomId(value) {
13869
+ return typeof value === "string" && value.length > 0 && value.length <= 64;
13870
+ }
13871
+ function logBatchInstrumentationError(context, error) {
13872
+ debugLogger.debug(`OpenAI Batch instrumentation ${context}:`, error);
13873
+ }
13874
+ async function exportParent(parent) {
13875
+ if ("toStr" in parent && typeof parent.toStr === "function") {
13876
+ return parent.toStr();
13877
+ }
13878
+ if ("export" in parent && typeof parent.export === "function") {
13879
+ return await parent.export();
13880
+ }
13881
+ return void 0;
13882
+ }
13883
+ async function deterministicDigest(namespace, ...parts) {
13884
+ const encoded = new TextEncoder().encode(
13885
+ [namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
13886
+ );
13887
+ return new Uint8Array(
13888
+ await globalThis.crypto.subtle.digest("SHA-256", encoded)
13889
+ );
13890
+ }
13891
+ function digestHex(bytes, length) {
13892
+ return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
13893
+ }
13894
+ function digestUuid(bytes) {
13895
+ const hex = digestHex(bytes, 16);
13896
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
13897
+ }
13898
+ async function batchSpanIds(inputFileId) {
13899
+ const [row, span, root] = await Promise.all([
13900
+ deterministicDigest("openai:batch:row", inputFileId),
13901
+ deterministicDigest("openai:batch:span", inputFileId),
13902
+ deterministicDigest("openai:batch:root", inputFileId)
13903
+ ]);
13904
+ return {
13905
+ rowId: digestUuid(row),
13906
+ spanId: digestHex(span, 8),
13907
+ rootSpanId: digestHex(root, 16)
13908
+ };
13909
+ }
13910
+ async function childSpanIds(inputFileId, customId) {
13911
+ const [row, span] = await Promise.all([
13912
+ deterministicDigest("openai:batch:child:row", inputFileId, customId),
13913
+ deterministicDigest("openai:batch:child:span", inputFileId, customId)
13914
+ ]);
13915
+ return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
13916
+ }
13917
+ async function startBatchSpan(context) {
13918
+ const ids = await batchSpanIds(context.inputFileId);
13919
+ const parent = SpanComponentsV4.fromStr(context.parent);
13920
+ const hasParentSpan = Boolean(
13921
+ parent.data.row_id && parent.data.span_id && parent.data.root_span_id
13922
+ );
13923
+ return withCurrent(
13924
+ NOOP_SPAN,
13925
+ () => _internalStartSpanWithInitialMergeAndParentSpanIds(
13926
+ withSpanInstrumentationName(
13927
+ {
13928
+ name: "openai.batch",
13929
+ type: "task" /* TASK */,
13930
+ parent: context.parent,
13931
+ ...!hasParentSpan ? {
13932
+ parentSpanIds: {
13933
+ parentSpanIds: [],
13934
+ rootSpanId: ids.rootSpanId
13935
+ }
13936
+ } : {},
13937
+ spanId: ids.spanId,
13938
+ startTime: context.taskStartTime,
13939
+ event: {
13940
+ id: ids.rowId,
13941
+ metadata: {
13942
+ endpoint: context.endpoint,
13943
+ input_file_id: context.inputFileId,
13944
+ provider: "openai"
13945
+ }
13946
+ }
13947
+ },
13948
+ INSTRUMENTATION_NAMES.OPENAI
13949
+ )
13950
+ )
13951
+ );
13952
+ }
13953
+ async function startBatchChild(context, taskParent, input) {
13954
+ const ids = await childSpanIds(context.inputFileId, input.customId);
13955
+ return withCurrent(
13956
+ NOOP_SPAN,
13957
+ () => _internalStartSpanWithInitialMerge(
13958
+ withSpanInstrumentationName(
13959
+ {
13960
+ name: context.endpoint === "/v1/chat/completions" ? "Chat Completion" : "openai.responses.create",
13961
+ type: "llm" /* LLM */,
13962
+ parent: taskParent,
13963
+ spanId: ids.spanId,
13964
+ startTime: context.childStartTime,
13965
+ event: {
13966
+ id: ids.rowId,
13967
+ ...input.spanData?.input !== void 0 ? { input: input.spanData.input } : {},
13968
+ metadata: {
13969
+ ...input.spanData?.metadata,
13970
+ custom_id: input.customId,
13971
+ provider: "openai"
13972
+ }
13973
+ }
13974
+ },
13975
+ INSTRUMENTATION_NAMES.OPENAI
13976
+ )
13977
+ )
13978
+ );
13979
+ }
13980
+ async function* jsonlRecords(file, onIssue = () => {
13981
+ }) {
13982
+ const resolvedFile = await file;
13983
+ if (typeof resolvedFile === "string") {
13984
+ for (const line of resolvedFile.split("\n")) {
13985
+ if (!line.trim()) {
13986
+ continue;
13987
+ }
13988
+ try {
13989
+ yield JSON.parse(line.replace(/\r$/, ""));
13990
+ } catch (error) {
13991
+ logBatchInstrumentationError("skipped malformed JSONL", error);
13992
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
13993
+ }
13994
+ }
13995
+ return;
13996
+ }
13997
+ const body = read(resolvedFile, "body");
13998
+ const getReader = read(body, "getReader");
13999
+ if (isObject(body) && typeof getReader === "function") {
14000
+ let reader;
14001
+ try {
14002
+ reader = Reflect.apply(getReader, body, []);
14003
+ const decoder2 = new TextDecoder();
14004
+ let pending = "";
14005
+ while (true) {
14006
+ const readChunk = read(reader, "read");
14007
+ if (typeof readChunk !== "function") {
14008
+ throw new Error("Response body stream has no read method");
14009
+ }
14010
+ const chunk = await Reflect.apply(readChunk, reader, []);
14011
+ if (!isObject(chunk)) {
14012
+ throw new Error("Response body stream returned an invalid chunk");
14013
+ }
14014
+ if (chunk.done === true) {
14015
+ pending += decoder2.decode();
14016
+ break;
14017
+ }
14018
+ if (!(chunk.value instanceof Uint8Array)) {
14019
+ throw new Error("Response body stream returned a non-byte chunk");
14020
+ }
14021
+ pending += decoder2.decode(chunk.value, { stream: true });
14022
+ let newline = pending.indexOf("\n");
14023
+ while (newline !== -1) {
14024
+ const line = pending.slice(0, newline).replace(/\r$/, "");
14025
+ pending = pending.slice(newline + 1);
14026
+ if (line.trim()) {
14027
+ try {
14028
+ yield JSON.parse(line);
14029
+ } catch (error) {
14030
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14031
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14032
+ }
14033
+ }
14034
+ newline = pending.indexOf("\n");
14035
+ }
14036
+ }
14037
+ if (pending.trim()) {
14038
+ try {
14039
+ yield JSON.parse(pending.replace(/\r$/, ""));
14040
+ } catch (error) {
14041
+ logBatchInstrumentationError("skipped malformed JSONL", error);
14042
+ onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
14043
+ }
14044
+ }
14045
+ } catch (error) {
14046
+ logBatchInstrumentationError("could not read JSONL response body", error);
14047
+ onIssue(new Error("OpenAI Batch response body could not be read"));
14048
+ } finally {
14049
+ const releaseLock = read(reader, "releaseLock");
14050
+ if (typeof releaseLock === "function") {
14051
+ try {
14052
+ Reflect.apply(releaseLock, reader, []);
14053
+ } catch (error) {
14054
+ logBatchInstrumentationError(
14055
+ "could not release stream reader",
14056
+ error
14057
+ );
14058
+ }
14059
+ }
14060
+ }
14061
+ return;
14062
+ }
14063
+ if (isBatchRecordIterable(resolvedFile)) {
14064
+ for await (const record of resolvedFile) {
14065
+ yield record;
14066
+ }
14067
+ return;
14068
+ }
14069
+ logBatchInstrumentationError("skipped invalid JSONL source", resolvedFile);
14070
+ onIssue(new Error("OpenAI Batch file source is invalid"));
14071
+ }
14072
+ async function readBatchInputs(file) {
14073
+ const inputs = /* @__PURE__ */ new Map();
14074
+ const issues = [];
14075
+ let endpoint;
14076
+ try {
14077
+ for await (const value of jsonlRecords(
14078
+ file,
14079
+ (issue) => issues.push(issue)
14080
+ )) {
14081
+ const customId = read(value, "custom_id");
14082
+ const url = read(value, "url");
14083
+ const body = read(value, "body");
14084
+ if (!validCustomId(customId) || inputs.has(customId) || read(value, "method") !== "POST" || typeof url !== "string" || !SUPPORTED_ENDPOINTS.has(url) || endpoint !== void 0 && endpoint !== url || !isObject(body)) {
14085
+ issues.push(new Error("OpenAI Batch input contains an invalid record"));
14086
+ continue;
14087
+ }
14088
+ endpoint = url;
14089
+ let spanData;
14090
+ try {
14091
+ spanData = extractOpenAIBatchInput(url, body);
14092
+ } catch (error) {
14093
+ logBatchInstrumentationError("could not extract batch input", error);
14094
+ }
14095
+ inputs.set(customId, { customId, spanData });
14096
+ }
14097
+ } catch (error) {
14098
+ logBatchInstrumentationError("could not process input file", error);
14099
+ issues.push(new Error("OpenAI Batch input file could not be processed"));
14100
+ }
14101
+ if (!endpoint || inputs.size === 0) {
14102
+ issues.push(new Error("OpenAI Batch input contains no supported records"));
14103
+ }
14104
+ return { endpoint, inputs, issues };
14105
+ }
14106
+ async function writePendingSpans(trace, endTime) {
14107
+ const task = await startBatchSpan(trace.context);
14108
+ const taskParent = await task.export();
14109
+ for (const input of trace.inputs.values()) {
14110
+ try {
14111
+ const child = await startBatchChild(trace.context, taskParent, input);
14112
+ if (endTime !== void 0) {
14113
+ child.end({ endTime });
14114
+ }
14115
+ } catch (error) {
14116
+ logBatchInstrumentationError("could not write batch request span", error);
14117
+ }
14118
+ }
14119
+ if (endTime !== void 0) {
14120
+ if (trace.status && trace.status !== "completed") {
14121
+ task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14122
+ }
14123
+ task.end({ endTime });
14124
+ }
14125
+ }
14126
+ var interceptOpenAIFilesCreateTraced = async (target, thisArg, args) => {
14127
+ const startTime = getCurrentUnixTimestamp();
14128
+ const inputPromise = readBatchInputs(args[0].inputFileContent);
14129
+ const parentPromise = exportParent(args[0].parent);
14130
+ const file = await Reflect.apply(target, thisArg, args);
14131
+ try {
14132
+ const inputFileId = read(file, "id");
14133
+ const [inputData, exportedParent2] = await Promise.all([
14134
+ inputPromise,
14135
+ parentPromise
14136
+ ]);
14137
+ if (typeof inputFileId !== "string" || !exportedParent2 || !inputData.endpoint || inputData.issues.length > 0) {
14138
+ if (inputData.issues[0]) {
14139
+ logBatchInstrumentationError(
14140
+ "skipped invalid input file",
14141
+ inputData.issues[0]
14142
+ );
14143
+ }
14144
+ return file;
14145
+ }
14146
+ const trace = {
14147
+ context: {
14148
+ inputFileId,
14149
+ endpoint: inputData.endpoint,
14150
+ parent: exportedParent2,
14151
+ taskStartTime: startTime,
14152
+ childStartTime: startTime
14153
+ },
14154
+ inputs: inputData.inputs
14155
+ };
14156
+ pendingBatchTraces.set(inputFileId, trace);
14157
+ await writePendingSpans(trace);
14158
+ } catch (error) {
14159
+ logBatchInstrumentationError("could not start batch spans", error);
14160
+ }
14161
+ return file;
14162
+ };
14163
+ function validTimestamp(value) {
14164
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
14165
+ }
14166
+ function terminalEndTime(batch, startTime) {
14167
+ let timestamp;
14168
+ switch (batch.status) {
14169
+ case "completed":
14170
+ timestamp = batch.completed_at;
14171
+ break;
14172
+ case "failed":
14173
+ timestamp = batch.failed_at;
14174
+ break;
14175
+ case "expired":
14176
+ timestamp = batch.expired_at;
14177
+ break;
14178
+ default:
14179
+ timestamp = batch.cancelled_at;
14180
+ }
14181
+ return validTimestamp(timestamp) ? Math.max(timestamp, startTime) : Math.max(getCurrentUnixTimestamp(), startTime);
14182
+ }
14183
+ async function updateBatchTimestamps(batch) {
14184
+ const trace = pendingBatchTraces.get(batch.input_file_id);
14185
+ if (!trace || trace.context.endpoint !== batch.endpoint) {
14186
+ return;
14187
+ }
14188
+ if (validTimestamp(batch.created_at)) {
14189
+ trace.context.taskStartTime = batch.created_at;
14190
+ }
14191
+ trace.context.childStartTime = validTimestamp(batch.in_progress_at) ? Math.max(batch.in_progress_at, trace.context.taskStartTime) : trace.context.taskStartTime;
14192
+ trace.status = batch.status;
14193
+ if (TERMINAL_STATUSES.has(batch.status)) {
14194
+ trace.endTime = terminalEndTime(batch, trace.context.childStartTime);
14195
+ }
14196
+ await writePendingSpans(trace, trace.endTime);
14197
+ }
14198
+ var interceptOpenAIBatchesRetrieveTraced = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (batch) => {
14199
+ try {
14200
+ await updateBatchTimestamps(batch);
14201
+ } catch (error) {
14202
+ logBatchInstrumentationError("could not update batch timestamps", error);
14203
+ }
14204
+ return batch;
14205
+ });
14206
+ function errorFromResult(result) {
14207
+ const error = read(result.value, "error");
14208
+ if (isObject(error)) {
14209
+ const message = read(error, "message");
14210
+ return new Error(
14211
+ typeof message === "string" ? message : "OpenAI Batch request failed"
14212
+ );
14213
+ }
14214
+ const response = read(result.value, "response");
14215
+ const statusCode = read(response, "status_code");
14216
+ if (result.source === "error" || typeof statusCode === "number" && (statusCode < 200 || statusCode >= 300)) {
14217
+ const message = read(read(read(response, "body"), "error"), "message");
14218
+ return new Error(
14219
+ typeof message === "string" ? message : "OpenAI Batch request failed"
14220
+ );
14221
+ }
14222
+ return void 0;
14223
+ }
14224
+ async function completeBatchResult(context, taskParent, endTime, input, result) {
14225
+ const child = await startBatchChild(context, taskParent, input);
14226
+ try {
14227
+ const resultError = errorFromResult(result);
14228
+ const responseBody = read(read(result.value, "response"), "body");
14229
+ if (resultError) {
14230
+ child.log({ error: resultError });
14231
+ } else if (isObject(responseBody)) {
14232
+ const model = read(responseBody, "model");
14233
+ child.log({
14234
+ output: context.endpoint === "/v1/chat/completions" ? read(responseBody, "choices") : processImagesInOutput(read(responseBody, "output")),
14235
+ ...typeof model === "string" ? { metadata: { model } } : {},
14236
+ metrics: parseMetricsFromUsage(read(responseBody, "usage"))
14237
+ });
14238
+ } else {
14239
+ child.log({ error: new Error("OpenAI Batch response body is missing") });
14240
+ }
14241
+ } catch (error) {
14242
+ child.log({ error });
14243
+ } finally {
14244
+ child.end({ endTime });
14245
+ }
14246
+ }
14247
+ async function completeResultFile({
14248
+ context,
14249
+ endTime,
14250
+ file,
14251
+ inputs,
14252
+ issues,
14253
+ seen,
14254
+ source,
14255
+ taskParent
14256
+ }) {
14257
+ if (file === void 0) {
14258
+ return;
14259
+ }
14260
+ for await (const value of jsonlRecords(file, (issue) => issues.push(issue))) {
14261
+ const customId = read(value, "custom_id");
14262
+ if (!validCustomId(customId) || !isObject(value)) {
14263
+ issues.push(
14264
+ new Error("OpenAI Batch result is missing a valid custom_id")
14265
+ );
14266
+ continue;
14267
+ }
14268
+ if (seen.has(customId)) {
14269
+ issues.push(new Error("OpenAI Batch result contains a duplicate"));
14270
+ continue;
14271
+ }
14272
+ const input = inputs.get(customId);
14273
+ if (!input) {
14274
+ issues.push(
14275
+ new Error("OpenAI Batch result does not match an input record")
14276
+ );
14277
+ continue;
14278
+ }
14279
+ seen.add(customId);
14280
+ await completeBatchResult(context, taskParent, endTime, input, {
14281
+ value,
14282
+ source
14283
+ });
14284
+ }
14285
+ }
14286
+ function sameInputs(first, second) {
14287
+ return first.size === second.size && [...first.keys()].every((customId) => second.has(customId));
14288
+ }
14289
+ async function contextForCompletion(inputFileId, inputData) {
14290
+ if (!inputData.endpoint || inputData.issues.length > 0) {
14291
+ return void 0;
14292
+ }
14293
+ const existing = pendingBatchTraces.get(inputFileId);
14294
+ if (existing) {
14295
+ if (existing.context.endpoint !== inputData.endpoint || !sameInputs(existing.inputs, inputData.inputs)) {
14296
+ return void 0;
14297
+ }
14298
+ return { ...existing, inputs: inputData.inputs };
14299
+ }
14300
+ const parent = await exportParent(getSpanParentObject());
14301
+ if (!parent) {
14302
+ return void 0;
14303
+ }
14304
+ const startTime = getCurrentUnixTimestamp();
14305
+ return {
14306
+ context: {
14307
+ inputFileId,
14308
+ endpoint: inputData.endpoint,
14309
+ parent,
14310
+ taskStartTime: startTime,
14311
+ childStartTime: startTime
14312
+ },
14313
+ inputs: inputData.inputs
14314
+ };
14315
+ }
14316
+ async function completeBatch(args) {
14317
+ const inputData = await readBatchInputs(args.inputFileContent);
14318
+ const trace = await contextForCompletion(args.inputFileId, inputData);
14319
+ if (!trace) {
14320
+ logBatchInstrumentationError(
14321
+ "left batch spans pending",
14322
+ inputData.issues[0] ?? new Error("OpenAI Batch input does not match")
14323
+ );
14324
+ return;
14325
+ }
14326
+ const endTime = trace.endTime ?? getCurrentUnixTimestamp();
14327
+ const task = await startBatchSpan(trace.context);
14328
+ const taskParent = await task.export();
14329
+ const issues = [];
14330
+ const seen = /* @__PURE__ */ new Set();
14331
+ await Promise.all([
14332
+ completeResultFile({
14333
+ context: trace.context,
14334
+ endTime,
14335
+ file: args.outputFileContent,
14336
+ inputs: trace.inputs,
14337
+ issues,
14338
+ seen,
14339
+ source: "output",
14340
+ taskParent
14341
+ }),
14342
+ completeResultFile({
14343
+ context: trace.context,
14344
+ endTime,
14345
+ file: args.errorFileContent,
14346
+ inputs: trace.inputs,
14347
+ issues,
14348
+ seen,
14349
+ source: "error",
14350
+ taskParent
14351
+ })
14352
+ ]);
14353
+ if (issues.length > 0) {
14354
+ logBatchInstrumentationError("left batch spans pending", issues[0]);
14355
+ return;
14356
+ }
14357
+ const missing = [...trace.inputs.values()].filter(
14358
+ ({ customId }) => !seen.has(customId)
14359
+ );
14360
+ if (!trace.status || trace.status === "completed") {
14361
+ if (missing.length > 0) {
14362
+ logBatchInstrumentationError(
14363
+ "left batch spans pending",
14364
+ new Error("OpenAI Batch result files are incomplete")
14365
+ );
14366
+ return;
14367
+ }
14368
+ } else {
14369
+ for (const input of missing) {
14370
+ const child = await startBatchChild(trace.context, taskParent, input);
14371
+ child.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14372
+ child.end({ endTime });
14373
+ }
14374
+ task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
14375
+ }
14376
+ task.end({ endTime });
14377
+ pendingBatchTraces.delete(args.inputFileId);
14378
+ }
14379
+ var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (result) => {
14380
+ try {
14381
+ await completeBatch(args[0]);
14382
+ } catch (error) {
14383
+ logBatchInstrumentationError("could not complete batch", error);
14384
+ }
14385
+ return result;
14386
+ });
14387
+
13415
14388
  // src/instrumentation/plugins/openai-plugin.ts
13416
14389
  var OpenAIPlugin = class extends BasePlugin {
13417
14390
  constructor() {
13418
14391
  super();
13419
14392
  }
13420
14393
  onEnable() {
14394
+ this.unsubscribers.push(
14395
+ openAIChannels.filesCreateTraced.intercept(
14396
+ interceptOpenAIFilesCreateTraced
14397
+ ),
14398
+ openAIChannels.batchesRetrieveTraced.intercept(
14399
+ interceptOpenAIBatchesRetrieveTraced
14400
+ ),
14401
+ openAIChannels.batchesCompleteTrace.intercept(
14402
+ interceptOpenAIBatchTraceComplete
14403
+ )
14404
+ );
13421
14405
  this.unsubscribers.push(
13422
14406
  traceStreamingChannel(openAIChannels.chatCompletionsCreate, {
13423
14407
  name: "Chat Completion",
13424
14408
  type: "llm" /* LLM */,
13425
- extractInput: ([params]) => {
13426
- const { messages, ...metadata } = params;
13427
- return {
13428
- input: processInputAttachments(messages),
13429
- metadata: { ...metadata, provider: "openai" }
13430
- };
13431
- },
14409
+ extractInput: ([params]) => extractOpenAIChatInput(params),
13432
14410
  extractOutput: (result) => {
13433
14411
  return result?.choices;
13434
14412
  },
@@ -13474,13 +14452,7 @@ var OpenAIPlugin = class extends BasePlugin {
13474
14452
  traceStreamingChannel(openAIChannels.betaChatCompletionsParse, {
13475
14453
  name: "Chat Completion",
13476
14454
  type: "llm" /* LLM */,
13477
- extractInput: ([params]) => {
13478
- const { messages, ...metadata } = params;
13479
- return {
13480
- input: processInputAttachments(messages),
13481
- metadata: { ...metadata, provider: "openai" }
13482
- };
13483
- },
14455
+ extractInput: ([params]) => extractOpenAIChatInput(params),
13484
14456
  extractOutput: (result) => {
13485
14457
  return result?.choices;
13486
14458
  },
@@ -13502,13 +14474,7 @@ var OpenAIPlugin = class extends BasePlugin {
13502
14474
  traceSyncStreamChannel(openAIChannels.betaChatCompletionsStream, {
13503
14475
  name: "Chat Completion",
13504
14476
  type: "llm" /* LLM */,
13505
- extractInput: ([params]) => {
13506
- const { messages, ...metadata } = params;
13507
- return {
13508
- input: processInputAttachments(messages),
13509
- metadata: { ...metadata, provider: "openai" }
13510
- };
13511
- }
14477
+ extractInput: ([params]) => extractOpenAIChatInput(params)
13512
14478
  })
13513
14479
  );
13514
14480
  this.unsubscribers.push(
@@ -13538,23 +14504,11 @@ var OpenAIPlugin = class extends BasePlugin {
13538
14504
  traceStreamingChannel(openAIChannels.responsesCreate, {
13539
14505
  name: "openai.responses.create",
13540
14506
  type: "llm" /* LLM */,
13541
- extractInput: ([params]) => {
13542
- const { input, ...metadata } = params;
13543
- return {
13544
- input: processInputAttachments(input),
13545
- metadata: { ...metadata, provider: "openai" }
13546
- };
13547
- },
14507
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13548
14508
  extractOutput: (result) => {
13549
14509
  return processImagesInOutput(result?.output);
13550
14510
  },
13551
- extractMetadata: (result) => {
13552
- if (!result) {
13553
- return void 0;
13554
- }
13555
- const { output: _output, usage: _usage, ...metadata } = result;
13556
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13557
- },
14511
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13558
14512
  extractMetrics: (result, startTime, endEvent) => {
13559
14513
  const metrics = withCachedMetric(
13560
14514
  parseMetricsFromUsage(result?.usage),
@@ -13573,13 +14527,7 @@ var OpenAIPlugin = class extends BasePlugin {
13573
14527
  traceSyncStreamChannel(openAIChannels.responsesStream, {
13574
14528
  name: "openai.responses.create",
13575
14529
  type: "llm" /* LLM */,
13576
- extractInput: ([params]) => {
13577
- const { input, ...metadata } = params;
13578
- return {
13579
- input: processInputAttachments(input),
13580
- metadata: { ...metadata, provider: "openai" }
13581
- };
13582
- },
14530
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13583
14531
  extractFromEvent: (event) => {
13584
14532
  if (event.type !== "response.completed" || !event.response) {
13585
14533
  return {};
@@ -13602,23 +14550,11 @@ var OpenAIPlugin = class extends BasePlugin {
13602
14550
  traceStreamingChannel(openAIChannels.responsesParse, {
13603
14551
  name: "openai.responses.parse",
13604
14552
  type: "llm" /* LLM */,
13605
- extractInput: ([params]) => {
13606
- const { input, ...metadata } = params;
13607
- return {
13608
- input: processInputAttachments(input),
13609
- metadata: { ...metadata, provider: "openai" }
13610
- };
13611
- },
14553
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13612
14554
  extractOutput: (result) => {
13613
14555
  return processImagesInOutput(result?.output);
13614
14556
  },
13615
- extractMetadata: (result) => {
13616
- if (!result) {
13617
- return void 0;
13618
- }
13619
- const { output: _output, usage: _usage, ...metadata } = result;
13620
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13621
- },
14557
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13622
14558
  extractMetrics: (result, startTime, endEvent) => {
13623
14559
  const metrics = withCachedMetric(
13624
14560
  parseMetricsFromUsage(result?.usage),
@@ -13637,23 +14573,11 @@ var OpenAIPlugin = class extends BasePlugin {
13637
14573
  traceAsyncChannel(openAIChannels.responsesCompact, {
13638
14574
  name: "openai.responses.compact",
13639
14575
  type: "llm" /* LLM */,
13640
- extractInput: ([params]) => {
13641
- const { input, ...metadata } = params;
13642
- return {
13643
- input: processInputAttachments(input),
13644
- metadata: { ...metadata, provider: "openai" }
13645
- };
13646
- },
14576
+ extractInput: ([params]) => extractOpenAIResponsesInput(params),
13647
14577
  extractOutput: (result) => {
13648
14578
  return processImagesInOutput(result?.output);
13649
14579
  },
13650
- extractMetadata: (result) => {
13651
- if (!result) {
13652
- return void 0;
13653
- }
13654
- const { output: _output, usage: _usage, ...metadata } = result;
13655
- return Object.keys(metadata).length > 0 ? metadata : void 0;
13656
- },
14580
+ extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
13657
14581
  extractMetrics: (result, startTime, endEvent) => {
13658
14582
  const metrics = withCachedMetric(
13659
14583
  parseMetricsFromUsage(result?.usage),
@@ -13709,35 +14633,6 @@ function withCachedMetric(metrics, result, endEvent) {
13709
14633
  cached
13710
14634
  };
13711
14635
  }
13712
- function processImagesInOutput(output) {
13713
- if (Array.isArray(output)) {
13714
- return output.map(processImagesInOutput);
13715
- }
13716
- if (isObject(output)) {
13717
- if (output.type === "image_generation_call" && output.result && typeof output.result === "string") {
13718
- const fileExtension = output.output_format || "png";
13719
- const contentType = `image/${fileExtension}`;
13720
- const baseFilename = output.revised_prompt && typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
13721
- const filename = `${baseFilename}.${fileExtension}`;
13722
- const binaryString = atob(output.result);
13723
- const bytes = new Uint8Array(binaryString.length);
13724
- for (let i = 0; i < binaryString.length; i++) {
13725
- bytes[i] = binaryString.charCodeAt(i);
13726
- }
13727
- const blob = new Blob([bytes], { type: contentType });
13728
- const attachment = new Attachment({
13729
- data: blob,
13730
- filename,
13731
- contentType
13732
- });
13733
- return {
13734
- ...output,
13735
- result: attachment
13736
- };
13737
- }
13738
- }
13739
- return output;
13740
- }
13741
14636
  function mergeLogprobTokens(existing, incoming) {
13742
14637
  if (incoming === void 0) {
13743
14638
  return existing;
@@ -13768,13 +14663,33 @@ function aggregateChatLogprobs(existing, incoming) {
13768
14663
  }
13769
14664
  return aggregated;
13770
14665
  }
14666
+ function createAggregatedChatChoice(index) {
14667
+ return {
14668
+ index,
14669
+ role: void 0,
14670
+ content: void 0,
14671
+ refusal: void 0,
14672
+ toolCallsByIndex: /* @__PURE__ */ new Map(),
14673
+ logprobs: void 0,
14674
+ finish_reason: void 0
14675
+ };
14676
+ }
14677
+ function toChatChoice(choice) {
14678
+ const toolCalls2 = Array.from(choice.toolCallsByIndex.entries()).sort(([left], [right]) => left - right).map(([, toolCall]) => toolCall);
14679
+ return {
14680
+ index: choice.index,
14681
+ message: {
14682
+ role: choice.role,
14683
+ content: choice.content,
14684
+ ...choice.refusal !== void 0 ? { refusal: choice.refusal } : {},
14685
+ tool_calls: toolCalls2.length > 0 ? toolCalls2 : void 0
14686
+ },
14687
+ logprobs: choice.logprobs ?? null,
14688
+ finish_reason: choice.finish_reason
14689
+ };
14690
+ }
13771
14691
  function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
13772
- let role = void 0;
13773
- let content = void 0;
13774
- let refusal = void 0;
13775
- let tool_calls = void 0;
13776
- let logprobs = void 0;
13777
- let finish_reason = void 0;
14692
+ const choicesByIndex = /* @__PURE__ */ new Map();
13778
14693
  let metrics = {};
13779
14694
  for (const chunk of chunks) {
13780
14695
  if (chunk.usage) {
@@ -13783,62 +14698,75 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
13783
14698
  ...parseMetricsFromUsage(chunk.usage)
13784
14699
  };
13785
14700
  }
13786
- const choice = chunk.choices?.[0];
13787
- if (!choice) {
14701
+ const choices = chunk.choices;
14702
+ if (!choices?.length) {
13788
14703
  continue;
13789
14704
  }
13790
- if (choice.finish_reason) {
13791
- finish_reason = choice.finish_reason;
13792
- }
13793
- logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
13794
- const delta = choice.delta;
13795
- if (!delta) {
13796
- continue;
13797
- }
13798
- if (delta.finish_reason) {
13799
- finish_reason = delta.finish_reason;
13800
- }
13801
- if (!role && delta.role) {
13802
- role = delta.role;
13803
- }
13804
- if (delta.content) {
13805
- content = (content || "") + delta.content;
13806
- }
13807
- if (delta.refusal) {
13808
- refusal = (refusal || "") + delta.refusal;
13809
- }
13810
- if (delta.tool_calls) {
13811
- const toolDelta = delta.tool_calls[0];
13812
- if (!tool_calls || toolDelta.id && tool_calls[tool_calls.length - 1].id !== toolDelta.id) {
13813
- tool_calls = [
13814
- ...tool_calls || [],
13815
- {
13816
- id: toolDelta.id,
13817
- type: toolDelta.type,
13818
- function: toolDelta.function
14705
+ for (const choice of choices) {
14706
+ const choiceIndex = choice.index;
14707
+ let aggregatedChoice = choicesByIndex.get(choiceIndex);
14708
+ if (!aggregatedChoice) {
14709
+ aggregatedChoice = createAggregatedChatChoice(choiceIndex);
14710
+ choicesByIndex.set(choiceIndex, aggregatedChoice);
14711
+ }
14712
+ if (choice.finish_reason) {
14713
+ aggregatedChoice.finish_reason = choice.finish_reason;
14714
+ }
14715
+ aggregatedChoice.logprobs = aggregateChatLogprobs(
14716
+ aggregatedChoice.logprobs,
14717
+ choice.logprobs
14718
+ );
14719
+ const delta = choice.delta;
14720
+ if (!delta) {
14721
+ continue;
14722
+ }
14723
+ if (delta.finish_reason) {
14724
+ aggregatedChoice.finish_reason = delta.finish_reason;
14725
+ }
14726
+ if (!aggregatedChoice.role && delta.role) {
14727
+ aggregatedChoice.role = delta.role;
14728
+ }
14729
+ if (delta.content) {
14730
+ aggregatedChoice.content = (aggregatedChoice.content || "") + delta.content;
14731
+ }
14732
+ if (delta.refusal) {
14733
+ aggregatedChoice.refusal = (aggregatedChoice.refusal || "") + delta.refusal;
14734
+ }
14735
+ if (delta.tool_calls) {
14736
+ for (const toolDelta of delta.tool_calls) {
14737
+ let aggregatedToolCall = aggregatedChoice.toolCallsByIndex.get(
14738
+ toolDelta.index
14739
+ );
14740
+ if (!aggregatedToolCall) {
14741
+ aggregatedToolCall = {
14742
+ function: { arguments: "" }
14743
+ };
14744
+ aggregatedChoice.toolCallsByIndex.set(
14745
+ toolDelta.index,
14746
+ aggregatedToolCall
14747
+ );
13819
14748
  }
13820
- ];
13821
- } else {
13822
- tool_calls[tool_calls.length - 1].function.arguments += toolDelta.function.arguments;
14749
+ if (toolDelta.id !== void 0) {
14750
+ aggregatedToolCall.id = toolDelta.id;
14751
+ }
14752
+ if (toolDelta.type !== void 0) {
14753
+ aggregatedToolCall.type = toolDelta.type;
14754
+ }
14755
+ if (toolDelta.function?.name !== void 0) {
14756
+ aggregatedToolCall.function.name = toolDelta.function.name;
14757
+ }
14758
+ if (toolDelta.function?.arguments !== void 0) {
14759
+ aggregatedToolCall.function.arguments += toolDelta.function.arguments;
14760
+ }
14761
+ }
13823
14762
  }
13824
14763
  }
13825
14764
  }
13826
14765
  metrics = withCachedMetric(metrics, streamResult, endEvent);
14766
+ const output = Array.from(choicesByIndex.values()).sort((left, right) => left.index - right.index).map(toChatChoice);
13827
14767
  return {
13828
14768
  metrics,
13829
- output: [
13830
- {
13831
- index: 0,
13832
- message: {
13833
- role,
13834
- content,
13835
- ...refusal !== void 0 ? { refusal } : {},
13836
- tool_calls
13837
- },
13838
- logprobs: logprobs ?? null,
13839
- finish_reason
13840
- }
13841
- ]
14769
+ output: output.length > 0 ? output : [toChatChoice(createAggregatedChatChoice(0))]
13842
14770
  };
13843
14771
  }
13844
14772
  function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
@@ -15174,6 +16102,12 @@ function parseMetricsFromUsage2(usage) {
15174
16102
  }
15175
16103
  }
15176
16104
  }
16105
+ if (isObject(usage.output_tokens_details)) {
16106
+ const thinkingTokens = usage.output_tokens_details.thinking_tokens;
16107
+ if (typeof thinkingTokens === "number") {
16108
+ metrics.completion_reasoning_tokens = thinkingTokens;
16109
+ }
16110
+ }
15177
16111
  if (isObject(usage.server_tool_use)) {
15178
16112
  for (const [name, value] of Object.entries(usage.server_tool_use)) {
15179
16113
  if (typeof value === "number") {
@@ -16130,7 +17064,6 @@ function endHarnessTurn(parent) {
16130
17064
  function braintrustAISDKTelemetry() {
16131
17065
  const operations = /* @__PURE__ */ new Map();
16132
17066
  const operationKeysByCallId = /* @__PURE__ */ new Map();
16133
- const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
16134
17067
  const modelSpans = /* @__PURE__ */ new Map();
16135
17068
  const objectSpans = /* @__PURE__ */ new Map();
16136
17069
  const embedSpans = /* @__PURE__ */ new Map();
@@ -16173,9 +17106,6 @@ function braintrustAISDKTelemetry() {
16173
17106
  return;
16174
17107
  }
16175
17108
  operations.delete(operationKey);
16176
- if (workflowOperationKeyStore.getStore() === operationKey) {
16177
- workflowOperationKeyStore.enterWith(void 0);
16178
- }
16179
17109
  const keys = operationKeysByCallId.get(state.callId);
16180
17110
  if (!keys) {
16181
17111
  return;
@@ -16223,14 +17153,7 @@ function braintrustAISDKTelemetry() {
16223
17153
  return key;
16224
17154
  }
16225
17155
  }
16226
- const workflowOperationKey = workflowOperationKeyStore.getStore();
16227
- if (workflowOperationKey && keys.includes(workflowOperationKey)) {
16228
- return workflowOperationKey;
16229
- }
16230
- if (callId === "workflow-agent") {
16231
- return void 0;
16232
- }
16233
- return mode === "finish" ? keys[0] : keys[keys.length - 1];
17156
+ return callId === "workflow-agent" || mode === "active" ? keys[keys.length - 1] : keys[0];
16234
17157
  };
16235
17158
  const operationKeyFromEvent = (event, mode = "active") => {
16236
17159
  const explicit = explicitOperationKey(event);
@@ -16244,17 +17167,13 @@ function braintrustAISDKTelemetry() {
16244
17167
  if (operationKey) {
16245
17168
  return operationKey;
16246
17169
  }
16247
- const workflowOperationKey2 = workflowOperationKeyStore.getStore();
16248
- if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
16249
- return workflowOperationKey2;
17170
+ const workflowAgentKeys2 = operationKeysByCallId.get("workflow-agent");
17171
+ if (workflowAgentKeys2?.length) {
17172
+ return workflowAgentKeys2[workflowAgentKeys2.length - 1];
16250
17173
  }
16251
17174
  return callId === "workflow-agent" ? void 0 : callId;
16252
17175
  }
16253
17176
  }
16254
- const workflowOperationKey = workflowOperationKeyStore.getStore();
16255
- if (workflowOperationKey && operations.has(workflowOperationKey)) {
16256
- return workflowOperationKey;
16257
- }
16258
17177
  const wrapperSpan = currentWorkflowAgentWrapperSpan();
16259
17178
  if (wrapperSpan?.spanId) {
16260
17179
  for (const [operationKey, state] of operations) {
@@ -16264,8 +17183,8 @@ function braintrustAISDKTelemetry() {
16264
17183
  }
16265
17184
  }
16266
17185
  const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
16267
- if (workflowAgentKeys?.length === 1) {
16268
- return workflowAgentKeys[0];
17186
+ if (workflowAgentKeys?.length) {
17187
+ return workflowAgentKeys[workflowAgentKeys.length - 1];
16269
17188
  }
16270
17189
  if (operations.size === 1) {
16271
17190
  return operations.keys().next().value;
@@ -16468,9 +17387,6 @@ function braintrustAISDKTelemetry() {
16468
17387
  if (!ownsSpan) {
16469
17388
  return;
16470
17389
  }
16471
- if (workflowAgent) {
16472
- workflowOperationKeyStore.enterWith(operationKey);
16473
- }
16474
17390
  let metadata = metadataFromEvent(event);
16475
17391
  const logPayload = { metadata };
16476
17392
  const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
@@ -16942,6 +17858,10 @@ var aiSDKChannels = defineChannels(
16942
17858
  channelName: "generateText",
16943
17859
  kind: "async"
16944
17860
  }),
17861
+ generateImage: channel({
17862
+ channelName: "generateImage",
17863
+ kind: "async"
17864
+ }),
16945
17865
  streamText: channel({
16946
17866
  channelName: "streamText",
16947
17867
  kind: "async"
@@ -17129,7 +18049,7 @@ var AISDKPlugin = class extends BasePlugin {
17129
18049
  }
17130
18050
  subscribeToAISDK() {
17131
18051
  const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
17132
- this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
18052
+ this.unsubscribers.push(interceptAISDKV7TelemetryDispatcher());
17133
18053
  this.unsubscribers.push(subscribeToHarnessAgentCreateSession());
17134
18054
  this.unsubscribers.push(
17135
18055
  subscribeToHarnessContinuation(
@@ -17157,6 +18077,18 @@ var AISDKPlugin = class extends BasePlugin {
17157
18077
  aggregateChunks: aggregateAISDKChunks
17158
18078
  })
17159
18079
  );
18080
+ this.unsubscribers.push(
18081
+ traceAsyncChannel(aiSDKChannels.generateImage, {
18082
+ name: "generateImage",
18083
+ type: "llm" /* LLM */,
18084
+ extractInput: ([params], event) => prepareAISDKGenerateImageInput(params, event.self),
18085
+ extractOutput: (result, endEvent) => processAISDKGenerateImageOutput(
18086
+ result,
18087
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
18088
+ ),
18089
+ extractMetrics: (result) => extractTokenMetrics(result)
18090
+ })
18091
+ );
17160
18092
  this.unsubscribers.push(
17161
18093
  traceStreamingChannel(aiSDKChannels.streamText, {
17162
18094
  name: "streamText",
@@ -17646,26 +18578,29 @@ function subscribeToHarnessContinuation(continuationChannel, defaultDenyOutputPa
17646
18578
  channel2.unsubscribe(handlers);
17647
18579
  };
17648
18580
  }
17649
- function subscribeToAISDKV7TelemetryDispatcher() {
17650
- const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
18581
+ function interceptAISDKV7TelemetryDispatcher() {
17651
18582
  const telemetry = braintrustAISDKTelemetry();
17652
- const handlers = {
17653
- end: (event) => {
17654
- const telemetryOptions = event.arguments?.[0]?.telemetry;
17655
- if (telemetryOptions?.isEnabled === false) {
17656
- return;
18583
+ return aiSDKChannels.v7CreateTelemetryDispatcher.intercept(
18584
+ (target, thisArg, args) => {
18585
+ const dispatcher = Reflect.apply(target, thisArg, args);
18586
+ const telemetryOptions = args[0]?.telemetry;
18587
+ if (telemetryOptions?.isEnabled !== false) {
18588
+ try {
18589
+ patchAISDKV7TelemetryDispatcher(
18590
+ dispatcher,
18591
+ telemetry,
18592
+ telemetryOptions
18593
+ );
18594
+ } catch (error) {
18595
+ debugLogger.error(
18596
+ "Error instrumenting AI SDK v7 telemetry dispatcher:",
18597
+ error
18598
+ );
18599
+ }
17657
18600
  }
17658
- patchAISDKV7TelemetryDispatcher(
17659
- event.result,
17660
- telemetry,
17661
- telemetryOptions
17662
- );
18601
+ return dispatcher;
17663
18602
  }
17664
- };
17665
- channel2.subscribe(handlers);
17666
- return () => {
17667
- channel2.unsubscribe(handlers);
17668
- };
18603
+ );
17669
18604
  }
17670
18605
  function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
17671
18606
  if (!isObject(dispatcher)) {
@@ -17990,16 +18925,10 @@ var convertImageToAttachment = (image, explicitMimeType) => {
17990
18925
  }
17991
18926
  }
17992
18927
  if (explicitMimeType) {
17993
- if (image instanceof Uint8Array) {
17994
- return new Attachment({
17995
- data: new Blob([image], { type: explicitMimeType }),
17996
- filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
17997
- contentType: explicitMimeType
17998
- });
17999
- }
18000
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
18928
+ const blob = convertDataToBlob(image, explicitMimeType);
18929
+ if (blob) {
18001
18930
  return new Attachment({
18002
- data: new Blob([image], { type: explicitMimeType }),
18931
+ data: blob,
18003
18932
  filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
18004
18933
  contentType: explicitMimeType
18005
18934
  });
@@ -18053,6 +18982,25 @@ var convertDataToAttachment = (data, mimeType, filename) => {
18053
18982
  function processAISDKCallInput(params) {
18054
18983
  return processInputAttachmentsSync(params);
18055
18984
  }
18985
+ function processAISDKGenerateImageInput(params) {
18986
+ const prompt = params.prompt;
18987
+ if (!isObject(prompt) || Array.isArray(prompt)) {
18988
+ return processAISDKCallInput(params);
18989
+ }
18990
+ const processedPrompt = { ...prompt };
18991
+ if (Array.isArray(prompt.images)) {
18992
+ processedPrompt.images = prompt.images.map(
18993
+ (image) => convertImageToAttachment(image, "image/png") ?? image
18994
+ );
18995
+ }
18996
+ if (prompt.mask !== void 0) {
18997
+ processedPrompt.mask = convertImageToAttachment(prompt.mask, "image/png") ?? prompt.mask;
18998
+ }
18999
+ return processAISDKCallInput({
19000
+ ...params,
19001
+ prompt: processedPrompt
19002
+ });
19003
+ }
18056
19004
  function processAISDKWorkflowAgentCallInput(params) {
18057
19005
  const processed = processAISDKCallInput(params);
18058
19006
  return {
@@ -18191,6 +19139,12 @@ function prepareAISDKEmbedInput(params, self) {
18191
19139
  metadata: extractMetadataFromEmbedParams(params, self)
18192
19140
  };
18193
19141
  }
19142
+ function prepareAISDKGenerateImageInput(params, self) {
19143
+ return {
19144
+ input: processAISDKGenerateImageInput(params).input,
19145
+ metadata: extractMetadataFromCallParams(params, self)
19146
+ };
19147
+ }
18194
19148
  function prepareAISDKRerankInput(params, self) {
18195
19149
  const { documents, query } = params;
18196
19150
  return {
@@ -19566,6 +20520,57 @@ function processAISDKOutput(output, denyOutputPaths) {
19566
20520
  }
19567
20521
  return normalizeAISDKLoggedOutput(sanitized);
19568
20522
  }
20523
+ function processAISDKGenerateImageOutput(output, denyOutputPaths) {
20524
+ if (!output || typeof output !== "object") {
20525
+ return output;
20526
+ }
20527
+ const summarized = {};
20528
+ for (const field of [
20529
+ "usage",
20530
+ "warnings",
20531
+ "providerMetadata",
20532
+ "experimental_providerMetadata",
20533
+ "responses"
20534
+ ]) {
20535
+ const value = safeSerializableFieldRead(output, field);
20536
+ if (value !== void 0 && isSerializableOutputValue(value)) {
20537
+ summarized[field] = value;
20538
+ }
20539
+ }
20540
+ const images = safeSerializableFieldRead(output, "images");
20541
+ const image = safeSerializableFieldRead(output, "image");
20542
+ const generatedFiles = Array.isArray(images) && images.length > 0 ? images : image !== void 0 ? [image] : [];
20543
+ const loggedOutput = normalizeAISDKLoggedOutput(
20544
+ omit(summarized, denyOutputPaths)
20545
+ );
20546
+ if (generatedFiles.length > 0) {
20547
+ loggedOutput.images = generatedFiles.map(
20548
+ (file, index) => convertAISDKGeneratedFileToAttachment(file, index)
20549
+ );
20550
+ }
20551
+ return loggedOutput;
20552
+ }
20553
+ function convertAISDKGeneratedFileToAttachment(file, index) {
20554
+ if (!file || typeof file !== "object") {
20555
+ return file;
20556
+ }
20557
+ const generatedFile = file;
20558
+ const generatedMediaType = safeSerializableFieldRead(
20559
+ generatedFile,
20560
+ "mediaType"
20561
+ );
20562
+ const mediaType = typeof generatedMediaType === "string" ? generatedMediaType : "application/octet-stream";
20563
+ const data = safeSerializableFieldRead(generatedFile, "base64") ?? safeSerializableFieldRead(generatedFile, "uint8Array");
20564
+ const blob = convertDataToBlob(data, mediaType);
20565
+ if (blob) {
20566
+ return new Attachment({
20567
+ data: blob,
20568
+ filename: `generated_image_${index}.${getExtensionFromMediaType(mediaType)}`,
20569
+ contentType: mediaType
20570
+ });
20571
+ }
20572
+ return file;
20573
+ }
19569
20574
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
19570
20575
  if (!output || typeof output !== "object") {
19571
20576
  return output;
@@ -20066,118 +21071,22 @@ var claudeAgentSDKChannels = defineChannels(
20066
21071
  var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
20067
21072
 
20068
21073
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
20069
- var LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED = /* @__PURE__ */ Symbol.for(
20070
- "braintrust.claude_agent_sdk.local_tool_context_async_iterator_patched"
20071
- );
20072
- function createLocalToolContextStore() {
20073
- const maybeIsoWithAsyncLocalStorage = isomorph_default;
20074
- if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
20075
- return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
20076
- }
20077
- let currentStore;
20078
- return {
20079
- enterWith(store) {
20080
- currentStore = store;
20081
- },
20082
- getStore() {
20083
- return currentStore;
20084
- },
20085
- run(store, callback) {
20086
- const previousStore = currentStore;
20087
- currentStore = store;
20088
- try {
20089
- return callback();
20090
- } finally {
20091
- currentStore = previousStore;
20092
- }
20093
- }
20094
- };
20095
- }
20096
- var localToolContextStore = createLocalToolContextStore();
20097
- var fallbackLocalToolParentResolver;
20098
- function createClaudeLocalToolContext() {
20099
- return {};
20100
- }
20101
- function runWithClaudeLocalToolContext(callback, context) {
20102
- return localToolContextStore.run(
20103
- context ?? createClaudeLocalToolContext(),
20104
- callback
20105
- );
21074
+ var localToolContextStore = isomorph_default.newAsyncLocalStorage();
21075
+ var localToolParentResolversByToolUseId = /* @__PURE__ */ new Map();
21076
+ function runWithClaudeLocalToolContext(callback, resolver) {
21077
+ return localToolContextStore.run(resolver, callback);
20106
21078
  }
20107
- function ensureClaudeLocalToolContext() {
20108
- const existing = localToolContextStore.getStore();
20109
- if (existing) {
20110
- return existing;
20111
- }
20112
- const created = {};
20113
- localToolContextStore.enterWith(created);
20114
- return created;
21079
+ function registerClaudeLocalToolParentResolver(toolUseId, resolver) {
21080
+ localToolParentResolversByToolUseId.set(toolUseId, resolver);
20115
21081
  }
20116
- function setClaudeLocalToolParentResolver(resolver) {
20117
- fallbackLocalToolParentResolver = resolver;
20118
- const context = ensureClaudeLocalToolContext();
20119
- if (!context) {
20120
- return;
21082
+ function getClaudeLocalToolParentResolver(toolUseId) {
21083
+ const currentResolver = localToolContextStore.getStore();
21084
+ if (!toolUseId) {
21085
+ return currentResolver;
20121
21086
  }
20122
- context.resolveLocalToolParent = resolver;
20123
- }
20124
- function getClaudeLocalToolParentResolver() {
20125
- return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
20126
- }
20127
- function isAsyncIterable3(value) {
20128
- return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
20129
- }
20130
- function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
20131
- if (!isAsyncIterable3(result) || Object.isFrozen(result) || Object.isSealed(result)) {
20132
- return result;
20133
- }
20134
- const stream = result;
20135
- const originalAsyncIterator = stream[Symbol.asyncIterator];
20136
- if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
20137
- return result;
20138
- }
20139
- const patchedAsyncIterator = function() {
20140
- return runWithClaudeLocalToolContext(() => {
20141
- const iterator = Reflect.apply(originalAsyncIterator, this, []);
20142
- if (!iterator || typeof iterator !== "object") {
20143
- return iterator;
20144
- }
20145
- const patchMethod = (methodName) => {
20146
- const originalMethod = Reflect.get(iterator, methodName);
20147
- if (typeof originalMethod !== "function") {
20148
- return;
20149
- }
20150
- Reflect.set(
20151
- iterator,
20152
- methodName,
20153
- (...args) => runWithClaudeLocalToolContext(
20154
- () => Reflect.apply(
20155
- originalMethod,
20156
- iterator,
20157
- args
20158
- ),
20159
- localToolContext
20160
- )
20161
- );
20162
- };
20163
- patchMethod("next");
20164
- patchMethod("return");
20165
- patchMethod("throw");
20166
- return iterator;
20167
- }, localToolContext);
20168
- };
20169
- Object.defineProperty(
20170
- patchedAsyncIterator,
20171
- LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
20172
- {
20173
- configurable: false,
20174
- enumerable: false,
20175
- value: true,
20176
- writable: false
20177
- }
20178
- );
20179
- Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
20180
- return result;
21087
+ const registeredResolver = localToolParentResolversByToolUseId.get(toolUseId);
21088
+ localToolParentResolversByToolUseId.delete(toolUseId);
21089
+ return currentResolver ?? registeredResolver;
20181
21090
  }
20182
21091
 
20183
21092
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
@@ -20203,7 +21112,7 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
20203
21112
  const metadata = getMetadata();
20204
21113
  const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
20205
21114
  const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
20206
- const localToolParentResolver = getClaudeLocalToolParentResolver();
21115
+ const localToolParentResolver = getClaudeLocalToolParentResolver(toolUseId);
20207
21116
  const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
20208
21117
  const runWithResolvedParent = async () => {
20209
21118
  const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
@@ -20730,6 +21639,7 @@ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToP
20730
21639
  }
20731
21640
  }
20732
21641
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
21642
+ registerClaudeLocalToolParentResolver(toolUseID, resolveParentSpan);
20733
21643
  return {};
20734
21644
  }
20735
21645
  const parsed = parseToolName(input.tool_name);
@@ -21440,7 +22350,7 @@ async function finalizeQuerySpan(state) {
21440
22350
  }
21441
22351
  var ClaudeAgentSDKPlugin = class extends BasePlugin {
21442
22352
  onEnable() {
21443
- this.subscribeToQuery();
22353
+ this.interceptQuery();
21444
22354
  }
21445
22355
  onDisable() {
21446
22356
  for (const unsubscribe of this.unsubscribers) {
@@ -21448,211 +22358,218 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
21448
22358
  }
21449
22359
  this.unsubscribers = [];
21450
22360
  }
21451
- subscribeToQuery() {
21452
- const channel2 = claudeAgentSDKChannels.query.tracingChannel();
21453
- const spans = /* @__PURE__ */ new WeakMap();
21454
- const handlers = {
21455
- start: (event) => {
21456
- const params = event.arguments[0] ?? {};
21457
- const originalPrompt = params.prompt;
21458
- const options = params.options ?? {};
21459
- const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
21460
- let promptStarted = false;
21461
- let capturedPromptMessages;
21462
- let resolvePromptDone;
21463
- const promptDone = new Promise((resolve) => {
21464
- resolvePromptDone = resolve;
21465
- });
21466
- if (promptIsAsyncIterable) {
21467
- capturedPromptMessages = [];
21468
- const promptStream = originalPrompt;
21469
- params.prompt = (async function* () {
21470
- promptStarted = true;
21471
- try {
21472
- for await (const message of promptStream) {
21473
- capturedPromptMessages.push(message);
21474
- yield message;
21475
- }
21476
- } finally {
21477
- resolvePromptDone?.();
22361
+ interceptQuery() {
22362
+ const startQuery = (params) => {
22363
+ const originalPrompt = params.prompt;
22364
+ const options = params.options ?? {};
22365
+ const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
22366
+ let promptStarted = false;
22367
+ let capturedPromptMessages;
22368
+ let resolvePromptDone;
22369
+ const promptDone = new Promise((resolve) => {
22370
+ resolvePromptDone = resolve;
22371
+ });
22372
+ if (promptIsAsyncIterable) {
22373
+ capturedPromptMessages = [];
22374
+ const promptStream = originalPrompt;
22375
+ params.prompt = (async function* () {
22376
+ promptStarted = true;
22377
+ try {
22378
+ for await (const message of promptStream) {
22379
+ capturedPromptMessages.push(message);
22380
+ yield message;
21478
22381
  }
21479
- })();
21480
- }
21481
- const span = startSpan(
21482
- withSpanInstrumentationName(
21483
- {
21484
- name: "Claude Agent",
21485
- spanAttributes: {
21486
- type: "task" /* TASK */
21487
- }
21488
- },
21489
- INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
21490
- )
21491
- );
21492
- const startTime = getCurrentUnixTimestamp();
21493
- try {
21494
- span.log({
21495
- input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
21496
- metadata: filterSerializableOptions(options)
21497
- });
21498
- } catch (error) {
21499
- console.error("Error extracting input for Claude Agent SDK:", error);
21500
- }
21501
- const activeToolSpans = /* @__PURE__ */ new Map();
21502
- const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
21503
- const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
21504
- const subAgentSpans = /* @__PURE__ */ new Map();
21505
- const endedSubAgentSpans = /* @__PURE__ */ new Set();
21506
- const toolUseToParent = /* @__PURE__ */ new Map();
21507
- const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
21508
- const latestRootLlmParentRef = {
21509
- value: void 0
21510
- };
21511
- const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
21512
- const taskIdToToolUseId = /* @__PURE__ */ new Map();
21513
- const promptMessagesByParentKey = /* @__PURE__ */ new Map();
21514
- const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
21515
- const localToolContext = createClaudeLocalToolContext();
21516
- const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
21517
- const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
21518
- const resolveToolUseParentSpan = async (toolUseID, context) => {
21519
- const trackedParentToolUseId = toolUseToParent.get(toolUseID);
21520
- const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
21521
- const parentKey = llmParentKey(parentToolUseId);
21522
- const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
21523
- const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
21524
- if (!activeLlmSpan && !latestLlmParent) {
21525
- await ensureActiveLlmSpanForParentToolUse(
21526
- span,
21527
- activeLlmSpansByParentToolUse,
21528
- subAgentDetailsByToolUseId,
21529
- activeToolSpans,
21530
- subAgentSpans,
21531
- parentToolUseId,
21532
- getCurrentUnixTimestamp()
21533
- );
21534
- }
21535
- if (parentToolUseId) {
21536
- const subAgentSpan = await ensureSubAgentSpan(
21537
- subAgentDetailsByToolUseId,
21538
- span,
21539
- activeToolSpans,
21540
- subAgentSpans,
21541
- parentToolUseId
21542
- );
21543
- return subAgentSpan.export();
22382
+ } finally {
22383
+ resolvePromptDone?.();
21544
22384
  }
21545
- return span.export();
21546
- };
21547
- localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
21548
- setClaudeLocalToolParentResolver(resolveToolUseParentSpan);
21549
- const optionsWithHooks = injectTracingHooks(
21550
- options,
21551
- resolveToolUseParentSpan,
21552
- taskIdToToolUseId,
21553
- toolUseToParent,
21554
- activeToolSpans,
21555
- localToolHookNames,
21556
- skipLocalToolHooks,
21557
- subAgentDetailsByToolUseId,
21558
- subAgentSpans,
21559
- endedSubAgentSpans
21560
- );
21561
- params.options = optionsWithHooks;
21562
- event.arguments[0] = params;
21563
- spans.set(event, {
21564
- activeLlmSpansByParentToolUse,
21565
- activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
21566
- activeToolSpans,
21567
- conversationHistoryByParentKey,
21568
- capturedPromptMessages,
21569
- currentMessageId: void 0,
21570
- currentMessageStartTime: startTime,
21571
- currentMessages: [],
21572
- endedSubAgentSpans,
21573
- finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
21574
- finalResults: [],
21575
- options: optionsWithHooks,
21576
- originalPrompt,
21577
- processing: Promise.resolve(),
21578
- promptDone,
21579
- promptMessagesByParentKey,
21580
- promptStarted: () => promptStarted,
21581
- promptSourcePriorityByParentKey,
21582
- span,
21583
- subAgentDetailsByToolUseId,
21584
- subAgentSpans,
21585
- taskIdToToolUseId,
21586
- latestLlmParentBySubAgentToolUse,
21587
- latestRootLlmParentRef,
21588
- toolUseToParent,
21589
- usageByMessageId: /* @__PURE__ */ new Map(),
21590
- localToolContext
22385
+ })();
22386
+ }
22387
+ const span = startSpan(
22388
+ withSpanInstrumentationName(
22389
+ {
22390
+ name: "Claude Agent",
22391
+ spanAttributes: {
22392
+ type: "task" /* TASK */
22393
+ }
22394
+ },
22395
+ INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
22396
+ )
22397
+ );
22398
+ const startTime = getCurrentUnixTimestamp();
22399
+ try {
22400
+ span.log({
22401
+ input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
22402
+ metadata: filterSerializableOptions(options)
21591
22403
  });
21592
- },
21593
- end: (event) => {
21594
- const state = spans.get(event);
21595
- if (!state) {
21596
- return;
21597
- }
21598
- const eventResult = bindClaudeLocalToolContextToAsyncIterable(
21599
- event.result,
21600
- state.localToolContext
21601
- );
21602
- if (eventResult === void 0) {
21603
- state.span.end();
21604
- spans.delete(event);
21605
- return;
21606
- }
21607
- if (isAsyncIterable(eventResult)) {
21608
- patchStreamIfNeeded(eventResult, {
21609
- onChunk: (message) => {
21610
- maybeTrackToolUseContext(state, message);
21611
- state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
21612
- console.error(
21613
- "Error processing Claude Agent SDK stream chunk:",
21614
- error
21615
- );
21616
- });
21617
- },
21618
- onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
21619
- spans.delete(event);
21620
- }),
21621
- onError: (error) => state.processing.then(() => {
21622
- state.span.log({
21623
- error: error.message
21624
- });
21625
- }).then(() => finalizeQuerySpan(state)).finally(() => {
21626
- spans.delete(event);
21627
- })
21628
- });
21629
- return;
21630
- }
21631
- try {
21632
- state.span.log({ output: eventResult });
21633
- } catch (error) {
21634
- console.error("Error extracting output for Claude Agent SDK:", error);
21635
- } finally {
21636
- state.span.end();
21637
- spans.delete(event);
22404
+ } catch (error) {
22405
+ console.error("Error extracting input for Claude Agent SDK:", error);
22406
+ }
22407
+ const activeToolSpans = /* @__PURE__ */ new Map();
22408
+ const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
22409
+ const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
22410
+ const subAgentSpans = /* @__PURE__ */ new Map();
22411
+ const endedSubAgentSpans = /* @__PURE__ */ new Set();
22412
+ const toolUseToParent = /* @__PURE__ */ new Map();
22413
+ const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
22414
+ const latestRootLlmParentRef = {
22415
+ value: void 0
22416
+ };
22417
+ const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
22418
+ const taskIdToToolUseId = /* @__PURE__ */ new Map();
22419
+ const promptMessagesByParentKey = /* @__PURE__ */ new Map();
22420
+ const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
22421
+ const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
22422
+ const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
22423
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
22424
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
22425
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
22426
+ const parentKey = llmParentKey(parentToolUseId);
22427
+ const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
22428
+ const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
22429
+ if (!activeLlmSpan && !latestLlmParent) {
22430
+ await ensureActiveLlmSpanForParentToolUse(
22431
+ span,
22432
+ activeLlmSpansByParentToolUse,
22433
+ subAgentDetailsByToolUseId,
22434
+ activeToolSpans,
22435
+ subAgentSpans,
22436
+ parentToolUseId,
22437
+ getCurrentUnixTimestamp()
22438
+ );
21638
22439
  }
21639
- },
21640
- error: (event) => {
21641
- const state = spans.get(event);
21642
- if (!state || !event.error) {
21643
- return;
22440
+ if (parentToolUseId) {
22441
+ const subAgentSpan = await ensureSubAgentSpan(
22442
+ subAgentDetailsByToolUseId,
22443
+ span,
22444
+ activeToolSpans,
22445
+ subAgentSpans,
22446
+ parentToolUseId
22447
+ );
22448
+ return subAgentSpan.export();
21644
22449
  }
21645
- state.span.log({
21646
- error: event.error.message
22450
+ return span.export();
22451
+ };
22452
+ const optionsWithHooks = injectTracingHooks(
22453
+ options,
22454
+ resolveToolUseParentSpan,
22455
+ taskIdToToolUseId,
22456
+ toolUseToParent,
22457
+ activeToolSpans,
22458
+ localToolHookNames,
22459
+ skipLocalToolHooks,
22460
+ subAgentDetailsByToolUseId,
22461
+ subAgentSpans,
22462
+ endedSubAgentSpans
22463
+ );
22464
+ params.options = optionsWithHooks;
22465
+ return {
22466
+ activeLlmSpansByParentToolUse,
22467
+ activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
22468
+ activeToolSpans,
22469
+ conversationHistoryByParentKey,
22470
+ capturedPromptMessages,
22471
+ currentMessageId: void 0,
22472
+ currentMessageStartTime: startTime,
22473
+ currentMessages: [],
22474
+ endedSubAgentSpans,
22475
+ finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
22476
+ finalResults: [],
22477
+ options: optionsWithHooks,
22478
+ originalPrompt,
22479
+ processing: Promise.resolve(),
22480
+ promptDone,
22481
+ promptMessagesByParentKey,
22482
+ promptStarted: () => promptStarted,
22483
+ promptSourcePriorityByParentKey,
22484
+ span,
22485
+ subAgentDetailsByToolUseId,
22486
+ subAgentSpans,
22487
+ taskIdToToolUseId,
22488
+ latestLlmParentBySubAgentToolUse,
22489
+ latestRootLlmParentRef,
22490
+ toolUseToParent,
22491
+ usageByMessageId: /* @__PURE__ */ new Map(),
22492
+ localToolParentResolver: resolveToolUseParentSpan
22493
+ };
22494
+ };
22495
+ const finishQuery = (state, result) => {
22496
+ if (isAsyncIterable(result)) {
22497
+ patchStreamIfNeeded(result, {
22498
+ aroundNext: (callback) => runWithClaudeLocalToolContext(
22499
+ callback,
22500
+ state.localToolParentResolver
22501
+ ),
22502
+ onChunk: (message) => {
22503
+ maybeTrackToolUseContext(state, message);
22504
+ state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
22505
+ console.error(
22506
+ "Error processing Claude Agent SDK stream chunk:",
22507
+ error
22508
+ );
22509
+ });
22510
+ },
22511
+ onComplete: () => state.processing.then(() => finalizeQuerySpan(state)),
22512
+ onError: (error) => state.processing.then(() => {
22513
+ state.span.log({ error: error.message });
22514
+ }).then(() => finalizeQuerySpan(state))
21647
22515
  });
22516
+ return;
22517
+ }
22518
+ try {
22519
+ state.span.log({ output: result });
22520
+ } catch (error) {
22521
+ console.error("Error extracting output for Claude Agent SDK:", error);
22522
+ } finally {
21648
22523
  state.span.end();
21649
- spans.delete(event);
21650
22524
  }
21651
22525
  };
21652
- channel2.subscribe(handlers);
21653
- this.unsubscribers.push(() => {
21654
- channel2.unsubscribe(handlers);
21655
- });
22526
+ this.unsubscribers.push(
22527
+ claudeAgentSDKChannels.query.intercept((target, thisArg, args) => {
22528
+ let state;
22529
+ try {
22530
+ args[0] ??= {};
22531
+ state = startQuery(args[0]);
22532
+ } catch (error) {
22533
+ debugLogger.error(
22534
+ "Error starting Claude Agent SDK instrumentation:",
22535
+ error
22536
+ );
22537
+ }
22538
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
22539
+ try {
22540
+ const result = state ? runWithClaudeLocalToolContext(
22541
+ invokeTarget,
22542
+ state.localToolParentResolver
22543
+ ) : invokeTarget();
22544
+ if (state) {
22545
+ try {
22546
+ finishQuery(state, result);
22547
+ } catch (error) {
22548
+ debugLogger.error(
22549
+ "Error finalizing Claude Agent SDK instrumentation:",
22550
+ error
22551
+ );
22552
+ }
22553
+ }
22554
+ return result;
22555
+ } catch (error) {
22556
+ if (state) {
22557
+ try {
22558
+ state.span.log({
22559
+ error: error instanceof Error ? error.message : String(error)
22560
+ });
22561
+ state.span.end();
22562
+ } catch (instrumentationError) {
22563
+ debugLogger.error(
22564
+ "Error handling Claude Agent SDK instrumentation failure:",
22565
+ instrumentationError
22566
+ );
22567
+ }
22568
+ }
22569
+ throw error;
22570
+ }
22571
+ })
22572
+ );
21656
22573
  }
21657
22574
  };
21658
22575
 
@@ -25766,7 +26683,7 @@ function patchOpenRouterCallModelResult(args) {
25766
26683
  span,
25767
26684
  () => originalMethod.apply(resultLike, args2)
25768
26685
  );
25769
- if (!isAsyncIterable4(stream)) {
26686
+ if (!isAsyncIterable3(stream)) {
25770
26687
  return stream;
25771
26688
  }
25772
26689
  return wrapAsyncIterableWithSpan({
@@ -25961,7 +26878,7 @@ function wrapAsyncIterableWithSpan(args) {
25961
26878
  }
25962
26879
  };
25963
26880
  }
25964
- function isAsyncIterable4(value) {
26881
+ function isAsyncIterable3(value) {
25965
26882
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
25966
26883
  }
25967
26884
  function normalizeError(error) {
@@ -26839,7 +27756,7 @@ function patchOpenRouterCallModelResult2(args) {
26839
27756
  span,
26840
27757
  () => originalMethod.apply(resultLike, args2)
26841
27758
  );
26842
- if (!isAsyncIterable5(stream)) {
27759
+ if (!isAsyncIterable4(stream)) {
26843
27760
  return stream;
26844
27761
  }
26845
27762
  return wrapAsyncIterableWithSpan2({
@@ -27034,7 +27951,7 @@ function wrapAsyncIterableWithSpan2(args) {
27034
27951
  }
27035
27952
  };
27036
27953
  }
27037
- function isAsyncIterable5(value) {
27954
+ function isAsyncIterable4(value) {
27038
27955
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
27039
27956
  }
27040
27957
  function normalizeError2(error) {
@@ -33026,12 +33943,14 @@ function getMetricsFromResponse(response) {
33026
33943
  continue;
33027
33944
  }
33028
33945
  const inputTokenDetails = usageMetadata.input_token_details;
33946
+ const outputTokenDetails = usageMetadata.output_token_details;
33029
33947
  return normalizeTokenMetrics({
33030
33948
  total_tokens: usageMetadata.total_tokens,
33031
33949
  prompt_tokens: usageMetadata.input_tokens,
33032
33950
  completion_tokens: usageMetadata.output_tokens,
33033
33951
  prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
33034
- prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
33952
+ prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
33953
+ completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
33035
33954
  });
33036
33955
  }
33037
33956
  const llmOutput = response.llmOutput || {};
@@ -33618,6 +34537,9 @@ var piCodingAgentChannels = defineChannels(
33618
34537
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
33619
34538
  var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
33620
34539
  var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
34540
+ var PI_TOOL_EXECUTE_WRAPPED = /* @__PURE__ */ Symbol.for(
34541
+ "braintrust.pi_coding_agent.tool_execute_wrapped"
34542
+ );
33621
34543
  var piPromptContextStore;
33622
34544
  var PiCodingAgentPlugin = class extends BasePlugin {
33623
34545
  activePromptStates = /* @__PURE__ */ new Set();
@@ -33698,6 +34620,7 @@ function startPiPromptRun(event, onFinalize) {
33698
34620
  return void 0;
33699
34621
  }
33700
34622
  installPiAgentInstrumentation(agent);
34623
+ wrapPiToolExecutors(agent.state?.tools);
33701
34624
  const metadata = {
33702
34625
  ...extractSessionMetadata(session),
33703
34626
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -33742,7 +34665,7 @@ function extractSession(event) {
33742
34665
  return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
33743
34666
  }
33744
34667
  function isPiAgent(value) {
33745
- return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
34668
+ return isObject(value) && (typeof value.streamFunction === "function" || typeof value.streamFn === "function") && typeof value.subscribe === "function";
33746
34669
  }
33747
34670
  function promptContextStore() {
33748
34671
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
@@ -33752,17 +34675,21 @@ function currentPiPromptState() {
33752
34675
  return promptContextStore().getStore();
33753
34676
  }
33754
34677
  function installPiAgentInstrumentation(agent) {
34678
+ const property = typeof agent.streamFunction === "function" ? "streamFunction" : "streamFn";
34679
+ const streamFunction = agent[property];
33755
34680
  const existing = piAgentPatchStates.get(agent);
33756
- if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
34681
+ if (streamFunction && (!existing || existing.property !== property || streamFunction !== existing.wrappedStreamFunction)) {
33757
34682
  const patchState = {
33758
- originalStreamFn: agent.streamFn,
33759
- wrappedStreamFn: agent.streamFn
34683
+ originalStreamFunction: streamFunction,
34684
+ property,
34685
+ wrappedStreamFunction: streamFunction
33760
34686
  };
33761
- patchState.wrappedStreamFn = makeInstrumentedStreamFn(
34687
+ patchState.wrappedStreamFunction = makeInstrumentedStreamFunction(
33762
34688
  agent,
33763
- patchState.originalStreamFn
34689
+ patchState.originalStreamFunction,
34690
+ property
33764
34691
  );
33765
- agent.streamFn = patchState.wrappedStreamFn;
34692
+ agent[property] = patchState.wrappedStreamFunction;
33766
34693
  piAgentPatchStates.set(agent, patchState);
33767
34694
  }
33768
34695
  if (piAgentEventSubscriptions.has(agent)) {
@@ -33787,14 +34714,21 @@ function installPiAgentInstrumentation(agent) {
33787
34714
  logInstrumentationError4("Pi Coding Agent event subscription", error);
33788
34715
  }
33789
34716
  }
33790
- function makeInstrumentedStreamFn(agent, originalStreamFn) {
33791
- return async function instrumentedPiStreamFn(model, context, options) {
33792
- const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
34717
+ function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
34718
+ return async function instrumentedPiStreamFunction(model, context, options) {
34719
+ const invokeOriginal = () => Reflect.apply(originalStreamFunction, this, [model, context, options]);
33793
34720
  const state = currentPiPromptState();
33794
34721
  if (!state || state.agent !== agent || state.finalized) {
33795
34722
  return invokeOriginal();
33796
34723
  }
33797
- const llmState = await startPiLlmSpan(state, model, context, options);
34724
+ wrapPiToolExecutors(context.tools);
34725
+ const llmState = await startPiLlmSpan(
34726
+ state,
34727
+ model,
34728
+ context,
34729
+ property,
34730
+ options
34731
+ );
33798
34732
  try {
33799
34733
  const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
33800
34734
  return patchAssistantMessageStream(stream, state, llmState);
@@ -33804,12 +34738,39 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
33804
34738
  }
33805
34739
  };
33806
34740
  }
33807
- async function startPiLlmSpan(state, model, context, options) {
34741
+ function wrapPiToolExecutors(tools) {
34742
+ if (!tools) {
34743
+ return;
34744
+ }
34745
+ for (const tool of tools) {
34746
+ try {
34747
+ const execute = tool.execute;
34748
+ if (typeof execute !== "function" || execute[PI_TOOL_EXECUTE_WRAPPED]) {
34749
+ continue;
34750
+ }
34751
+ const wrappedExecute = function(...args) {
34752
+ return runWithAutoInstrumentationAllowed(
34753
+ () => Reflect.apply(execute, this, args)
34754
+ );
34755
+ };
34756
+ Object.defineProperty(wrappedExecute, PI_TOOL_EXECUTE_WRAPPED, {
34757
+ configurable: false,
34758
+ enumerable: false,
34759
+ value: true,
34760
+ writable: false
34761
+ });
34762
+ tool.execute = wrappedExecute;
34763
+ } catch (error) {
34764
+ logInstrumentationError4("Pi Coding Agent tool wrapping", error);
34765
+ }
34766
+ }
34767
+ }
34768
+ async function startPiLlmSpan(state, model, context, property, options) {
33808
34769
  const metadata = {
33809
34770
  ...extractModelMetadata2(model),
33810
34771
  ...extractStreamOptionsMetadata(options),
33811
34772
  ...extractToolMetadata(context.tools),
33812
- "pi_coding_agent.operation": "agent.streamFn"
34773
+ "pi_coding_agent.operation": `agent.${property}`
33813
34774
  };
33814
34775
  const span = startSpan(
33815
34776
  withSpanInstrumentationName(
@@ -33975,35 +34936,26 @@ async function startPiToolSpan(state, event) {
33975
34936
  if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
33976
34937
  return;
33977
34938
  }
33978
- const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
33979
34939
  const metadata = {
33980
34940
  "gen_ai.tool.call.id": event.toolCallId,
33981
34941
  "gen_ai.tool.name": event.toolName,
33982
34942
  "pi_coding_agent.tool.name": event.toolName
33983
34943
  };
33984
- try {
33985
- const span = startSpan(
33986
- withSpanInstrumentationName(
33987
- {
33988
- event: {
33989
- input: event.args,
33990
- metadata
33991
- },
33992
- name: event.toolName || "tool",
33993
- parent: await state.span.export(),
33994
- spanAttributes: { type: "tool" /* TOOL */ }
34944
+ const span = startSpan(
34945
+ withSpanInstrumentationName(
34946
+ {
34947
+ event: {
34948
+ input: event.args,
34949
+ metadata
33995
34950
  },
33996
- INSTRUMENTATION_NAMES.PI_CODING_AGENT
33997
- )
33998
- );
33999
- state.activeToolSpans.set(event.toolCallId, {
34000
- restoreAutoInstrumentation,
34001
- span
34002
- });
34003
- } catch (error) {
34004
- restoreAutoInstrumentation();
34005
- throw error;
34006
- }
34951
+ name: event.toolName || "tool",
34952
+ parent: await state.span.export(),
34953
+ spanAttributes: { type: "tool" /* TOOL */ }
34954
+ },
34955
+ INSTRUMENTATION_NAMES.PI_CODING_AGENT
34956
+ )
34957
+ );
34958
+ state.activeToolSpans.set(event.toolCallId, { span });
34007
34959
  }
34008
34960
  function finishPiToolSpan(state, event) {
34009
34961
  const toolState = state.activeToolSpans.get(event.toolCallId);
@@ -34024,11 +34976,7 @@ function finishPiToolSpan(state, event) {
34024
34976
  output: event.result
34025
34977
  });
34026
34978
  } finally {
34027
- try {
34028
- toolState.span.end();
34029
- } finally {
34030
- toolState.restoreAutoInstrumentation?.();
34031
- }
34979
+ toolState.span.end();
34032
34980
  }
34033
34981
  }
34034
34982
  function finishPiPromptRun(state, error) {
@@ -34078,10 +35026,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
34078
35026
  ...cleanMetrics5(llmState.metrics),
34079
35027
  ...buildDurationMetrics3(llmState.startTime)
34080
35028
  };
34081
- const usageMetrics = extractUsageMetrics2(message?.usage);
34082
- if (Object.keys(usageMetrics).length > 0) {
35029
+ const usageMetrics2 = extractUsageMetrics2(message?.usage);
35030
+ if (Object.keys(usageMetrics2).length > 0) {
34083
35031
  promptState.collectedLlmUsageMetrics = true;
34084
- addMetrics(promptState.metrics, usageMetrics);
35032
+ addMetrics(promptState.metrics, usageMetrics2);
34085
35033
  }
34086
35034
  try {
34087
35035
  safeLog4(llmState.span, {
@@ -34099,14 +35047,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
34099
35047
  }
34100
35048
  function finishOpenToolSpans(state, error) {
34101
35049
  for (const [, toolState] of state.activeToolSpans) {
34102
- try {
34103
- safeLog4(toolState.span, {
34104
- error: error ? toLoggedError(error) : "Pi tool did not complete"
34105
- });
34106
- toolState.span.end();
34107
- } finally {
34108
- toolState.restoreAutoInstrumentation?.();
34109
- }
35050
+ safeLog4(toolState.span, {
35051
+ error: error ? toLoggedError(error) : "Pi tool did not complete"
35052
+ });
35053
+ toolState.span.end();
34110
35054
  }
34111
35055
  state.activeToolSpans.clear();
34112
35056
  }
@@ -34425,12 +35369,12 @@ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
34425
35369
  var StrandsAgentSDKPlugin = class extends BasePlugin {
34426
35370
  activeChildParents = /* @__PURE__ */ new WeakMap();
34427
35371
  onEnable() {
34428
- this.subscribeToAgentStream();
34429
- this.subscribeToMultiAgentStream(
35372
+ this.interceptAgentStream();
35373
+ this.interceptMultiAgentStream(
34430
35374
  strandsAgentSDKChannels.graphStream,
34431
35375
  "Graph.stream"
34432
35376
  );
34433
- this.subscribeToMultiAgentStream(
35377
+ this.interceptMultiAgentStream(
34434
35378
  strandsAgentSDKChannels.swarmStream,
34435
35379
  "Swarm.stream"
34436
35380
  );
@@ -34441,122 +35385,92 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
34441
35385
  }
34442
35386
  this.unsubscribers = [];
34443
35387
  }
34444
- subscribeToAgentStream() {
34445
- const channel2 = strandsAgentSDKChannels.agentStream.tracingChannel();
34446
- const states = /* @__PURE__ */ new WeakMap();
34447
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
34448
- const handlers = {
34449
- start: (event) => {
34450
- const state = startAgentStream(event, this.activeChildParents);
34451
- if (state) {
34452
- states.set(event, state);
34453
- }
34454
- },
34455
- end: (event) => {
34456
- const state = states.get(event);
34457
- if (!state) {
34458
- return;
34459
- }
34460
- const result = event.result;
34461
- if (isAsyncIterable(result)) {
34462
- patchStreamIfNeeded(result, {
34463
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
34464
- onChunk: (chunk) => handleAgentStreamEvent(state, chunk),
34465
- onComplete: () => {
34466
- finalizeAgentStream(state);
34467
- states.delete(event);
34468
- },
34469
- onError: (error) => {
34470
- finalizeAgentStream(state, error);
34471
- states.delete(event);
34472
- }
34473
- });
34474
- return;
34475
- }
34476
- finalizeAgentStream(state, void 0, result);
34477
- states.delete(event);
34478
- },
34479
- error: (event) => {
34480
- const state = states.get(event);
34481
- if (!state || !event.error) {
34482
- return;
34483
- }
34484
- finalizeAgentStream(state, event.error);
34485
- states.delete(event);
34486
- }
34487
- };
34488
- channel2.subscribe(handlers);
34489
- this.unsubscribers.push(() => {
34490
- unbindAutoInstrumentationSuppression?.();
34491
- channel2.unsubscribe(handlers);
34492
- });
35388
+ interceptAgentStream() {
35389
+ this.unsubscribers.push(
35390
+ strandsAgentSDKChannels.agentStream.intercept(
35391
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
35392
+ finalize: finalizeAgentStream,
35393
+ handleChunk: handleAgentStreamEvent,
35394
+ invoke: () => Reflect.apply(target, thisArg, args),
35395
+ name: "Strands Agent SDK",
35396
+ start: () => startAgentStream(
35397
+ args[0],
35398
+ extractAgent(additional.agent, thisArg),
35399
+ this.activeChildParents
35400
+ )
35401
+ })
35402
+ )
35403
+ );
34493
35404
  }
34494
- subscribeToMultiAgentStream(channel2, operation) {
34495
- const tracingChannel = channel2.tracingChannel();
34496
- const states = /* @__PURE__ */ new WeakMap();
34497
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(tracingChannel);
34498
- const handlers = {
34499
- start: (event) => {
34500
- const state = startMultiAgentStream(
34501
- event,
34502
- operation,
34503
- this.activeChildParents
34504
- );
34505
- if (state) {
34506
- states.set(event, state);
34507
- }
34508
- },
34509
- end: (event) => {
34510
- const state = states.get(event);
34511
- if (!state) {
34512
- return;
34513
- }
34514
- const result = event.result;
34515
- if (isAsyncIterable(result)) {
34516
- patchStreamIfNeeded(result, {
34517
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
34518
- onChunk: (chunk) => handleMultiAgentStreamEvent(
34519
- state,
34520
- chunk,
34521
- this.activeChildParents
34522
- ),
34523
- onComplete: () => {
34524
- finalizeMultiAgentStream(state, this.activeChildParents);
34525
- states.delete(event);
34526
- },
34527
- onError: (error) => {
34528
- finalizeMultiAgentStream(state, this.activeChildParents, error);
34529
- states.delete(event);
34530
- }
34531
- });
34532
- return;
34533
- }
34534
- finalizeMultiAgentStream(
34535
- state,
34536
- this.activeChildParents,
34537
- void 0,
34538
- result
35405
+ interceptMultiAgentStream(channel2, operation) {
35406
+ this.unsubscribers.push(
35407
+ channel2.intercept(
35408
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
35409
+ finalize: (state, error, output) => finalizeMultiAgentStream(
35410
+ state,
35411
+ this.activeChildParents,
35412
+ error,
35413
+ output
35414
+ ),
35415
+ handleChunk: (state, chunk) => handleMultiAgentStreamEvent(state, chunk, this.activeChildParents),
35416
+ invoke: () => Reflect.apply(target, thisArg, args),
35417
+ name: "Strands multi-agent",
35418
+ start: () => startMultiAgentStream(
35419
+ args[0],
35420
+ extractOrchestrator(additional.orchestrator, thisArg),
35421
+ operation,
35422
+ this.activeChildParents
35423
+ )
35424
+ })
35425
+ )
35426
+ );
35427
+ }
35428
+ };
35429
+ function instrumentStrandsStreamInvocation(options) {
35430
+ let state;
35431
+ try {
35432
+ state = options.start();
35433
+ } catch (error) {
35434
+ debugLogger.error(`Error starting ${options.name} instrumentation:`, error);
35435
+ }
35436
+ let result;
35437
+ try {
35438
+ result = runWithAutoInstrumentationSuppressed(options.invoke);
35439
+ } catch (error) {
35440
+ if (state) {
35441
+ try {
35442
+ options.finalize(state, error);
35443
+ } catch (instrumentationError) {
35444
+ debugLogger.error(
35445
+ `Error handling ${options.name} instrumentation failure:`,
35446
+ instrumentationError
34539
35447
  );
34540
- states.delete(event);
34541
- },
34542
- error: (event) => {
34543
- const state = states.get(event);
34544
- if (!state || !event.error) {
34545
- return;
34546
- }
34547
- finalizeMultiAgentStream(state, this.activeChildParents, event.error);
34548
- states.delete(event);
34549
35448
  }
34550
- };
34551
- tracingChannel.subscribe(handlers);
34552
- this.unsubscribers.push(() => {
34553
- unbindAutoInstrumentationSuppression?.();
34554
- tracingChannel.unsubscribe(handlers);
34555
- });
35449
+ }
35450
+ throw error;
34556
35451
  }
34557
- };
34558
- function startAgentStream(event, activeChildParents) {
34559
- const agent = extractAgent(event);
35452
+ if (state) {
35453
+ try {
35454
+ if (isAsyncIterable(result)) {
35455
+ patchStreamIfNeeded(result, {
35456
+ aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
35457
+ onChunk: (chunk) => options.handleChunk(state, chunk),
35458
+ onComplete: () => options.finalize(state),
35459
+ onError: (error) => options.finalize(state, error)
35460
+ });
35461
+ } else {
35462
+ options.finalize(state, void 0, result);
35463
+ }
35464
+ } catch (error) {
35465
+ debugLogger.error(
35466
+ `Error finalizing ${options.name} instrumentation:`,
35467
+ error
35468
+ );
35469
+ }
35470
+ }
35471
+ return result;
35472
+ }
35473
+ function startAgentStream(input, agent, activeChildParents) {
34560
35474
  const model = agent?.model;
34561
35475
  const metadata = {
34562
35476
  ...extractAgentMetadata2(agent),
@@ -34566,17 +35480,14 @@ function startAgentStream(event, activeChildParents) {
34566
35480
  };
34567
35481
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
34568
35482
  const attachmentCache = createStrandsAttachmentCache();
34569
- const input = processStrandsInputAttachments(
34570
- event.arguments[0],
34571
- attachmentCache
34572
- );
35483
+ const processedInput = processStrandsInputAttachments(input, attachmentCache);
34573
35484
  const span = parentSpan ? withCurrent(
34574
35485
  parentSpan,
34575
35486
  () => startSpan(
34576
35487
  withSpanInstrumentationName(
34577
35488
  {
34578
35489
  event: {
34579
- input,
35490
+ input: processedInput,
34580
35491
  metadata
34581
35492
  },
34582
35493
  name: formatAgentSpanName(agent),
@@ -34589,7 +35500,7 @@ function startAgentStream(event, activeChildParents) {
34589
35500
  withSpanInstrumentationName(
34590
35501
  {
34591
35502
  event: {
34592
- input,
35503
+ input: processedInput,
34593
35504
  metadata
34594
35505
  },
34595
35506
  name: formatAgentSpanName(agent),
@@ -34607,22 +35518,21 @@ function startAgentStream(event, activeChildParents) {
34607
35518
  startTime: getCurrentUnixTimestamp()
34608
35519
  };
34609
35520
  }
34610
- function startMultiAgentStream(event, operation, activeChildParents) {
34611
- const orchestrator = extractOrchestrator(event);
35521
+ function startMultiAgentStream(input, orchestrator, operation, activeChildParents) {
34612
35522
  const metadata = {
34613
35523
  "strands.operation": operation,
34614
35524
  provider: "strands",
34615
35525
  ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
34616
35526
  };
34617
35527
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
34618
- const input = processStrandsInputAttachments(event.arguments[0]);
35528
+ const processedInput = processStrandsInputAttachments(input);
34619
35529
  const span = parentSpan ? withCurrent(
34620
35530
  parentSpan,
34621
35531
  () => startSpan(
34622
35532
  withSpanInstrumentationName(
34623
35533
  {
34624
35534
  event: {
34625
- input,
35535
+ input: processedInput,
34626
35536
  metadata
34627
35537
  },
34628
35538
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -34635,7 +35545,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
34635
35545
  withSpanInstrumentationName(
34636
35546
  {
34637
35547
  event: {
34638
- input,
35548
+ input: processedInput,
34639
35549
  metadata
34640
35550
  },
34641
35551
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -35006,12 +35916,12 @@ function finalizeMultiAgentStream(state, activeChildParents, error, output) {
35006
35916
  });
35007
35917
  state.span.end();
35008
35918
  }
35009
- function extractAgent(event) {
35010
- const candidate = event.agent ?? event.self;
35919
+ function extractAgent(agent, self) {
35920
+ const candidate = agent ?? self;
35011
35921
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
35012
35922
  }
35013
- function extractOrchestrator(event) {
35014
- const candidate = event.orchestrator ?? event.self;
35923
+ function extractOrchestrator(orchestrator, self) {
35924
+ const candidate = orchestrator ?? self;
35015
35925
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
35016
35926
  }
35017
35927
  function extractAgentMetadata2(agent) {
@@ -36878,6 +37788,7 @@ __export(exports_exports, {
36878
37788
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
36879
37789
  buildLocalSummary: () => buildLocalSummary,
36880
37790
  collectAnthropicSession: () => collectAnthropicSession,
37791
+ completeOpenAIBatchTrace: () => completeOpenAIBatchTrace,
36881
37792
  configureInstrumentation: () => configureInstrumentation,
36882
37793
  constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
36883
37794
  createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
@@ -36916,6 +37827,8 @@ __export(exports_exports, {
36916
37827
  loginToState: () => loginToState,
36917
37828
  logs3OverflowUploadSchema: () => logs3OverflowUploadSchema,
36918
37829
  newId: () => newId,
37830
+ openaiBatchesRetrieveTraced: () => openaiBatchesRetrieveTraced,
37831
+ openaiFilesCreateTraced: () => openaiFilesCreateTraced,
36919
37832
  parseCachedHeader: () => parseCachedHeader,
36920
37833
  parseTemplateFormat: () => parseTemplateFormat,
36921
37834
  permalink: () => permalink,
@@ -37080,6 +37993,260 @@ async function registerSandbox(options) {
37080
37993
  };
37081
37994
  }
37082
37995
 
37996
+ // src/wrappers/openai-promise-utils.ts
37997
+ function splitSpanInfo(allParams) {
37998
+ const { span_info, ...params } = allParams;
37999
+ return {
38000
+ params,
38001
+ span_info
38002
+ };
38003
+ }
38004
+ function createChannelContext(_channel, params, span_info) {
38005
+ return {
38006
+ arguments: (
38007
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38008
+ [params]
38009
+ ),
38010
+ span_info
38011
+ };
38012
+ }
38013
+ async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
38014
+ let enhancedResponse;
38015
+ const tracePromise = (
38016
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38017
+ channel2.tracePromise
38018
+ );
38019
+ const data = await tracePromise(async () => {
38020
+ enhancedResponse = await apiPromise.withResponse();
38021
+ traceContext.response = enhancedResponse.response;
38022
+ return enhancedResponse.data;
38023
+ }, traceContext);
38024
+ if (!enhancedResponse) {
38025
+ throw new Error("Expected withResponse() to provide response");
38026
+ }
38027
+ return {
38028
+ data,
38029
+ response: enhancedResponse.response,
38030
+ request_id: enhancedResponse.request_id
38031
+ };
38032
+ }
38033
+ async function tracePromiseAsResponse(channel2, traceContext, apiPromise) {
38034
+ const tracePromise = (
38035
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38036
+ channel2.tracePromise
38037
+ );
38038
+ let response;
38039
+ await tracePromise(async () => {
38040
+ response = await apiPromise.asResponse();
38041
+ traceContext.response = response;
38042
+ return void 0;
38043
+ }, traceContext);
38044
+ if (!response) {
38045
+ throw new Error("Expected asResponse() to provide response");
38046
+ }
38047
+ return response;
38048
+ }
38049
+ function createLazyAPIPromise(ensureExecuted, ensureResponse, getAPIPromise) {
38050
+ let firstConsumption;
38051
+ let enhancedResponsePromise;
38052
+ let dataPromise;
38053
+ let responsePromise;
38054
+ const withResponse = () => {
38055
+ firstConsumption ??= "data";
38056
+ enhancedResponsePromise ??= firstConsumption === "data" ? ensureExecuted() : getAPIPromise().withResponse();
38057
+ return enhancedResponsePromise;
38058
+ };
38059
+ const asResponse = () => {
38060
+ firstConsumption ??= "response";
38061
+ responsePromise ??= firstConsumption === "response" ? ensureResponse() : getAPIPromise().asResponse();
38062
+ return responsePromise;
38063
+ };
38064
+ return new Proxy({}, {
38065
+ get(target, prop, receiver) {
38066
+ if (prop === "withResponse") {
38067
+ return withResponse;
38068
+ }
38069
+ if (prop === "asResponse") {
38070
+ return asResponse;
38071
+ }
38072
+ if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
38073
+ dataPromise ??= withResponse().then((result) => result.data);
38074
+ const value = Reflect.get(dataPromise, prop, receiver);
38075
+ return typeof value === "function" ? value.bind(dataPromise) : value;
38076
+ }
38077
+ return Reflect.get(target, prop, receiver);
38078
+ }
38079
+ });
38080
+ }
38081
+
38082
+ // src/openai-batch.ts
38083
+ function read2(value, key) {
38084
+ if (value === null || typeof value !== "object" && typeof value !== "function") {
38085
+ return void 0;
38086
+ }
38087
+ try {
38088
+ return Reflect.get(value, key);
38089
+ } catch {
38090
+ return void 0;
38091
+ }
38092
+ }
38093
+ function isAsyncIterable5(value) {
38094
+ return typeof read2(value, Symbol.asyncIterator) === "function";
38095
+ }
38096
+ function teeAsyncIterable(source) {
38097
+ const iterator = source[Symbol.asyncIterator]();
38098
+ const stream = new ReadableStream({
38099
+ async pull(controller) {
38100
+ try {
38101
+ const result = await iterator.next();
38102
+ if (result.done) {
38103
+ controller.close();
38104
+ return;
38105
+ }
38106
+ if (!(result.value instanceof Uint8Array)) {
38107
+ throw new TypeError(
38108
+ "OpenAI upload streams must yield Uint8Array chunks"
38109
+ );
38110
+ }
38111
+ controller.enqueue(result.value);
38112
+ } catch (error) {
38113
+ controller.error(error);
38114
+ }
38115
+ },
38116
+ async cancel(reason) {
38117
+ await iterator.return?.(reason);
38118
+ }
38119
+ });
38120
+ const [uploadStream, trace] = stream.tee();
38121
+ const upload = {
38122
+ async *[Symbol.asyncIterator]() {
38123
+ const reader = uploadStream.getReader();
38124
+ try {
38125
+ while (true) {
38126
+ const result = await reader.read();
38127
+ if (result.done) {
38128
+ return;
38129
+ }
38130
+ yield result.value;
38131
+ }
38132
+ } finally {
38133
+ reader.releaseLock();
38134
+ }
38135
+ }
38136
+ };
38137
+ const path = read2(source, "path");
38138
+ if (typeof path === "string") {
38139
+ Object.defineProperty(upload, "path", { value: path });
38140
+ }
38141
+ return { upload, trace: new Response(trace) };
38142
+ }
38143
+ function teeUpload(upload) {
38144
+ if (upload instanceof Blob) {
38145
+ return { upload, trace: new Response(upload) };
38146
+ }
38147
+ if (upload instanceof Response) {
38148
+ return { upload, trace: upload.clone() };
38149
+ }
38150
+ if (isAsyncIterable5(upload)) {
38151
+ return teeAsyncIterable(upload);
38152
+ }
38153
+ return void 0;
38154
+ }
38155
+ function openaiFilesCreateTraced(files) {
38156
+ return (params, options) => {
38157
+ const parent = getSpanParentObject();
38158
+ const purpose = read2(params, "purpose");
38159
+ const file = read2(params, "file");
38160
+ if (purpose !== "batch") {
38161
+ return files.create(params, options);
38162
+ }
38163
+ let branches;
38164
+ try {
38165
+ branches = teeUpload(file);
38166
+ } catch {
38167
+ return files.create(params, options);
38168
+ }
38169
+ if (!branches) {
38170
+ return files.create(params, options);
38171
+ }
38172
+ const tracedParams = {
38173
+ ...Object(params),
38174
+ file: branches.upload
38175
+ };
38176
+ const apiPromise = files.create(tracedParams, options);
38177
+ let enhancedResponse;
38178
+ const tracedResponse = openAIChannels.filesCreateTraced.invoke(
38179
+ async () => {
38180
+ enhancedResponse = await apiPromise.withResponse();
38181
+ return enhancedResponse.data;
38182
+ },
38183
+ files,
38184
+ [{ params, inputFileContent: branches.trace, parent }],
38185
+ {}
38186
+ ).then((data) => {
38187
+ if (!enhancedResponse) {
38188
+ throw new Error(
38189
+ "Expected OpenAI withResponse() to provide a response"
38190
+ );
38191
+ }
38192
+ return { ...enhancedResponse, data };
38193
+ });
38194
+ return createLazyAPIPromise(
38195
+ () => tracedResponse,
38196
+ () => tracedResponse.then(({ response }) => response),
38197
+ () => apiPromise
38198
+ );
38199
+ };
38200
+ }
38201
+ function openaiBatchesRetrieveTraced(batches) {
38202
+ return (batchId, options) => {
38203
+ const apiPromise = batches.retrieve(batchId, options);
38204
+ let enhancedResponse;
38205
+ const tracedResponse = openAIChannels.batchesRetrieveTraced.invoke(
38206
+ async () => {
38207
+ enhancedResponse = await apiPromise.withResponse();
38208
+ return enhancedResponse.data;
38209
+ },
38210
+ batches,
38211
+ [{ batchId }],
38212
+ {}
38213
+ ).then((data) => {
38214
+ if (!enhancedResponse) {
38215
+ throw new Error(
38216
+ "Expected OpenAI withResponse() to provide a response"
38217
+ );
38218
+ }
38219
+ return { ...enhancedResponse, data };
38220
+ });
38221
+ return createLazyAPIPromise(
38222
+ () => tracedResponse,
38223
+ () => tracedResponse.then(({ response }) => response),
38224
+ () => apiPromise
38225
+ );
38226
+ };
38227
+ }
38228
+ async function completeOpenAIBatchTrace(args) {
38229
+ const inputFileContent = Promise.resolve(args.inputFileContent);
38230
+ const outputFileContent = args.outputFileContent === void 0 ? void 0 : Promise.resolve(args.outputFileContent);
38231
+ const errorFileContent = args.errorFileContent === void 0 ? void 0 : Promise.resolve(args.errorFileContent);
38232
+ void inputFileContent.catch(() => void 0);
38233
+ void outputFileContent?.catch(() => void 0);
38234
+ void errorFileContent?.catch(() => void 0);
38235
+ await openAIChannels.batchesCompleteTrace.invoke(
38236
+ async () => void 0,
38237
+ void 0,
38238
+ [
38239
+ {
38240
+ ...args,
38241
+ inputFileContent,
38242
+ outputFileContent,
38243
+ errorFileContent
38244
+ }
38245
+ ],
38246
+ {}
38247
+ );
38248
+ }
38249
+
37083
38250
  // src/functions/invoke.ts
37084
38251
  async function invoke(args) {
37085
38252
  const {
@@ -37182,58 +38349,6 @@ function initFunction({
37182
38349
  return f;
37183
38350
  }
37184
38351
 
37185
- // src/wrappers/openai-promise-utils.ts
37186
- function splitSpanInfo(allParams) {
37187
- const { span_info, ...params } = allParams;
37188
- return {
37189
- params,
37190
- span_info
37191
- };
37192
- }
37193
- function createChannelContext(_channel, params, span_info) {
37194
- return {
37195
- arguments: (
37196
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37197
- [params]
37198
- ),
37199
- span_info
37200
- };
37201
- }
37202
- async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
37203
- let enhancedResponse;
37204
- const tracePromise = (
37205
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37206
- channel2.tracePromise
37207
- );
37208
- const data = await tracePromise(async () => {
37209
- enhancedResponse = await apiPromise.withResponse();
37210
- traceContext.response = enhancedResponse.response;
37211
- return enhancedResponse.data;
37212
- }, traceContext);
37213
- if (!enhancedResponse) {
37214
- throw new Error("Expected withResponse() to provide response");
37215
- }
37216
- return { data, response: enhancedResponse.response };
37217
- }
37218
- function createLazyAPIPromise(ensureExecuted) {
37219
- let dataPromise = null;
37220
- return new Proxy({}, {
37221
- get(target, prop, receiver) {
37222
- if (prop === "withResponse") {
37223
- return () => ensureExecuted();
37224
- }
37225
- if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
37226
- if (!dataPromise) {
37227
- dataPromise = ensureExecuted().then((result) => result.data);
37228
- }
37229
- const value = Reflect.get(dataPromise, prop, receiver);
37230
- return typeof value === "function" ? value.bind(dataPromise) : value;
37231
- }
37232
- return Reflect.get(target, prop, receiver);
37233
- }
37234
- });
37235
- }
37236
-
37237
38352
  // src/wrappers/oai_responses.ts
37238
38353
  function responsesProxy(openai) {
37239
38354
  if (!openai.responses) {
@@ -37270,17 +38385,33 @@ function wrapResponsesAsync(target, channel2) {
37270
38385
  return (allParams, options) => {
37271
38386
  const { span_info, params } = splitSpanInfo(allParams);
37272
38387
  let executionPromise = null;
38388
+ let apiPromise = null;
38389
+ const getAPIPromise = () => {
38390
+ apiPromise ??= target(params, options);
38391
+ return apiPromise;
38392
+ };
37273
38393
  const ensureExecuted = () => {
37274
38394
  if (!executionPromise) {
37275
38395
  executionPromise = (async () => {
37276
38396
  const traceContext = createChannelContext(channel2, params, span_info);
37277
- const apiPromise = target(params, options);
37278
- return tracePromiseWithResponse(channel2, traceContext, apiPromise);
38397
+ return tracePromiseWithResponse(
38398
+ channel2,
38399
+ traceContext,
38400
+ getAPIPromise()
38401
+ );
37279
38402
  })();
37280
38403
  }
37281
38404
  return executionPromise;
37282
38405
  };
37283
- return createLazyAPIPromise(ensureExecuted);
38406
+ return createLazyAPIPromise(
38407
+ ensureExecuted,
38408
+ () => tracePromiseAsResponse(
38409
+ channel2,
38410
+ createChannelContext(channel2, params, span_info),
38411
+ getAPIPromise()
38412
+ ),
38413
+ getAPIPromise
38414
+ );
37284
38415
  };
37285
38416
  }
37286
38417
  function wrapResponsesSyncStream(target, channel2) {
@@ -37426,6 +38557,11 @@ function wrapChatCompletion(completion) {
37426
38557
  allParams
37427
38558
  );
37428
38559
  let executionPromise = null;
38560
+ let apiPromise = null;
38561
+ const getAPIPromise = () => {
38562
+ apiPromise ??= completion(params, options);
38563
+ return apiPromise;
38564
+ };
37429
38565
  const ensureExecuted = () => {
37430
38566
  if (!executionPromise) {
37431
38567
  executionPromise = (async () => {
@@ -37435,32 +38571,44 @@ function wrapChatCompletion(completion) {
37435
38571
  span_info
37436
38572
  );
37437
38573
  if (params.stream) {
37438
- const completionPromise = completion(
37439
- params,
37440
- options
38574
+ const completionPromise = (
38575
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38576
+ getAPIPromise()
37441
38577
  );
37442
- const { data: data2, response: response2 } = await tracePromiseWithResponse(
38578
+ const { data: data2, response: response2, request_id: request_id2 } = await tracePromiseWithResponse(
37443
38579
  openAIChannels.chatCompletionsCreate,
37444
38580
  traceContext,
37445
38581
  completionPromise
37446
38582
  );
37447
- return { data: data2, response: response2 };
38583
+ return { data: data2, response: response2, request_id: request_id2 };
37448
38584
  }
37449
- const completionResponse = completion(
37450
- params,
37451
- options
38585
+ const completionResponse = (
38586
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
38587
+ getAPIPromise()
37452
38588
  );
37453
- const { data, response } = await tracePromiseWithResponse(
38589
+ const { data, response, request_id } = await tracePromiseWithResponse(
37454
38590
  openAIChannels.chatCompletionsCreate,
37455
38591
  traceContext,
37456
38592
  completionResponse
37457
38593
  );
37458
- return { data, response };
38594
+ return { data, response, request_id };
37459
38595
  })();
37460
38596
  }
37461
38597
  return executionPromise;
37462
38598
  };
37463
- return createLazyAPIPromise(ensureExecuted);
38599
+ return createLazyAPIPromise(
38600
+ ensureExecuted,
38601
+ () => tracePromiseAsResponse(
38602
+ openAIChannels.chatCompletionsCreate,
38603
+ createChannelContext(
38604
+ openAIChannels.chatCompletionsCreate,
38605
+ params,
38606
+ span_info
38607
+ ),
38608
+ getAPIPromise()
38609
+ ),
38610
+ getAPIPromise
38611
+ );
37464
38612
  };
37465
38613
  }
37466
38614
  function createEndpointProxy(target, wrapperFn) {
@@ -37478,6 +38626,11 @@ function wrapApiCreateWithChannel(create, channel2) {
37478
38626
  return (allParams, options) => {
37479
38627
  const { span_info, params } = splitSpanInfo(allParams);
37480
38628
  let executionPromise = null;
38629
+ let apiPromise = null;
38630
+ const getAPIPromise = () => {
38631
+ apiPromise ??= create(params, options);
38632
+ return apiPromise;
38633
+ };
37481
38634
  const ensureExecuted = () => {
37482
38635
  if (!executionPromise) {
37483
38636
  executionPromise = (async () => {
@@ -37485,13 +38638,21 @@ function wrapApiCreateWithChannel(create, channel2) {
37485
38638
  return tracePromiseWithResponse(
37486
38639
  channel2,
37487
38640
  traceContext,
37488
- create(params, options)
38641
+ getAPIPromise()
37489
38642
  );
37490
38643
  })();
37491
38644
  }
37492
38645
  return executionPromise;
37493
38646
  };
37494
- return createLazyAPIPromise(ensureExecuted);
38647
+ return createLazyAPIPromise(
38648
+ ensureExecuted,
38649
+ () => tracePromiseAsResponse(
38650
+ channel2,
38651
+ createChannelContext(channel2, params, span_info),
38652
+ getAPIPromise()
38653
+ ),
38654
+ getAPIPromise
38655
+ );
37495
38656
  };
37496
38657
  }
37497
38658
  var wrapEmbeddings = (create) => wrapApiCreateWithChannel(create, openAIChannels.embeddingsCreate);
@@ -37527,6 +38688,13 @@ function wrapAISDK(aiSDK, options = {}) {
37527
38688
  switch (prop) {
37528
38689
  case "generateText":
37529
38690
  return wrapGenerateText(typedAISDK.generateText, options, typedAISDK);
38691
+ case "generateImage":
38692
+ case "experimental_generateImage":
38693
+ return typeof original === "function" ? wrapGenerateImage(
38694
+ original,
38695
+ options,
38696
+ typedAISDK
38697
+ ) : original;
37530
38698
  case "streamText":
37531
38699
  return wrapStreamText(typedAISDK.streamText, options, typedAISDK);
37532
38700
  case "generateObject":
@@ -37763,6 +38931,32 @@ var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
37763
38931
  options
37764
38932
  );
37765
38933
  };
38934
+ var wrapGenerateImage = (generateImage, options = {}, aiSDK) => {
38935
+ return makeGenerateImageWrapper(generateImage, { aiSDK }, options);
38936
+ };
38937
+ var makeGenerateImageWrapper = (generateImage, contextOptions = {}, options = {}) => {
38938
+ const wrapper = async function(allParams) {
38939
+ const { span_info, ...params } = allParams;
38940
+ const tracedParams = { ...params };
38941
+ return aiSDKChannels.generateImage.tracePromise(
38942
+ () => generateImage(tracedParams),
38943
+ createAISDKChannelContext(tracedParams, {
38944
+ aiSDK: contextOptions.aiSDK,
38945
+ denyOutputPaths: options.denyOutputPaths,
38946
+ self: contextOptions.self,
38947
+ span_info: mergeSpanInfo(span_info, {
38948
+ name: "generateImage",
38949
+ spanType: contextOptions.spanType
38950
+ })
38951
+ })
38952
+ );
38953
+ };
38954
+ Object.defineProperty(wrapper, "name", {
38955
+ value: "generateImage",
38956
+ writable: false
38957
+ });
38958
+ return wrapper;
38959
+ };
37766
38960
  var makeEmbedWrapper = (channel2, name, embed, contextOptions = {}, options = {}) => {
37767
38961
  const wrapper = async function(allParams) {
37768
38962
  const { span_info, ...params } = allParams;
@@ -38513,7 +39707,7 @@ function braintrustEveHook(options) {
38513
39707
  }
38514
39708
  };
38515
39709
  }
38516
- function braintrustEveInstrumentation(options) {
39710
+ function createLegacyEveInstrumentation(options) {
38517
39711
  const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
38518
39712
  return {
38519
39713
  events: {
@@ -39901,8 +41095,10 @@ function capturedModelInput(modelInput) {
39901
41095
  const value = [];
39902
41096
  if (typeof instructions === "string") {
39903
41097
  value.push({ content: instructions, role: "system" });
39904
- } else if (instructions) {
41098
+ } else if (Array.isArray(instructions)) {
39905
41099
  value.push(...instructions.map(capturedEveModelMessage));
41100
+ } else if (instructions) {
41101
+ value.push(capturedEveModelMessage(instructions));
39906
41102
  }
39907
41103
  value.push(...messages.map(capturedEveModelMessage));
39908
41104
  try {
@@ -40146,6 +41342,472 @@ async function deterministicEveId(...parts) {
40146
41342
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
40147
41343
  }
40148
41344
 
41345
+ // src/instrumentation/plugins/eve-provider.ts
41346
+ var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
41347
+ function createEveInstrumentationProvider(options = {}) {
41348
+ const bridge = new EveProviderBridge(options.metadata);
41349
+ return {
41350
+ // Eve versions before tracePolicy use capture to decide whether provider
41351
+ // events include content. Newer versions prefer tracePolicy when both are
41352
+ // present, so keep the deprecated field for backwards compatibility.
41353
+ capture: "content",
41354
+ tracePolicy: () => ({
41355
+ emit: true,
41356
+ recordInputs: true,
41357
+ recordOutputs: true
41358
+ }),
41359
+ events: {
41360
+ "action.completed": (event, context) => bridge.handleActionTerminal(event, context),
41361
+ "action.failed": (event, context) => bridge.handleActionTerminal(event, context),
41362
+ "action.started": (event, context) => bridge.handleActionStarted(event, context),
41363
+ "model.call.completed": (event, context) => bridge.handleModelTerminal(event, context),
41364
+ "model.call.failed": (event, context) => bridge.handleModelTerminal(event, context),
41365
+ "model.call.started": (event, context) => bridge.handleModelStarted(event, context),
41366
+ "step.attempt.completed": (event) => bridge.handleStepAttemptTerminal(event),
41367
+ "step.attempt.failed": (event) => bridge.handleStepAttemptTerminal(event),
41368
+ "turn.cancelled": (event, context) => bridge.handleTurnTerminal(event, context),
41369
+ "turn.completed": (event, context) => bridge.handleTurnTerminal(event, context),
41370
+ "turn.failed": (event, context) => bridge.handleTurnTerminal(event, context),
41371
+ "turn.started": (event, context) => bridge.handleTurnStarted(event, context)
41372
+ },
41373
+ flush,
41374
+ setup: options.setup
41375
+ };
41376
+ }
41377
+ var EveProviderBridge = class {
41378
+ constructor(metadata) {
41379
+ this.metadata = metadata;
41380
+ }
41381
+ metadata;
41382
+ activeActions = /* @__PURE__ */ new Map();
41383
+ activeModels = /* @__PURE__ */ new Map();
41384
+ modelsByAttempt = /* @__PURE__ */ new Map();
41385
+ settledOperations = new LRUCache({
41386
+ max: MAX_EVE_PROVIDER_CACHE_ENTRIES
41387
+ });
41388
+ turns = new LRUCache({
41389
+ max: MAX_EVE_PROVIDER_CACHE_ENTRIES
41390
+ });
41391
+ async handleTurnStarted(event, context) {
41392
+ await this.contain("turn start", async () => {
41393
+ if (this.settledOperations.has(event.idempotencyKey)) {
41394
+ context.state.set({ skip: true });
41395
+ return;
41396
+ }
41397
+ const { rowId, spanId } = await generateEveIds(
41398
+ "turn",
41399
+ event.idempotencyKey
41400
+ );
41401
+ const key = turnKey3(event.sessionId, event.turnId);
41402
+ const stored = storedSpan(context);
41403
+ if (stored && "exported" in stored && stored.rootSpanId) {
41404
+ this.turns.set(key, { rootSpanId: stored.rootSpanId, spanId });
41405
+ return;
41406
+ }
41407
+ let rootSpanId = spanId;
41408
+ let parentSpanId;
41409
+ if (event.parentLineage) {
41410
+ const parentTurnKey = turnKey3(
41411
+ event.parentLineage.sessionId,
41412
+ event.parentLineage.turnId
41413
+ );
41414
+ const parentTurn = this.turns.get(parentTurnKey);
41415
+ rootSpanId = parentTurn?.rootSpanId ?? // Eve propagates the root session through every nested subagent. Use
41416
+ // it instead of the immediate parent session when no ancestor ran
41417
+ // in-process.
41418
+ (await generateEveIds(
41419
+ "turn",
41420
+ turnIdempotencyKey(
41421
+ event.rootSessionId,
41422
+ event.parentLineage.turnId
41423
+ )
41424
+ )).spanId;
41425
+ parentSpanId = (await generateEveIds(
41426
+ "subagent",
41427
+ actionIdempotencyKey(
41428
+ event.parentLineage.sessionId,
41429
+ event.parentLineage.turnId,
41430
+ event.parentLineage.callId
41431
+ )
41432
+ )).spanId;
41433
+ }
41434
+ const metadata = this.spanMetadata(event.sessionId);
41435
+ const span = await this.startSpan(
41436
+ context,
41437
+ {
41438
+ event: { id: rowId, metadata },
41439
+ name: "eve.turn",
41440
+ parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
41441
+ spanAttributes: { type: "task" /* TASK */ },
41442
+ spanId
41443
+ },
41444
+ rootSpanId
41445
+ );
41446
+ span?.log({ metadata });
41447
+ this.turns.set(key, {
41448
+ rootSpanId,
41449
+ spanId
41450
+ });
41451
+ });
41452
+ }
41453
+ async handleTurnTerminal(event, context) {
41454
+ await this.contain("turn terminal", async () => {
41455
+ if (this.settledOperations.has(event.idempotencyKey)) {
41456
+ context.state.set(void 0);
41457
+ return;
41458
+ }
41459
+ const error = event.type === "turn.failed" ? event.error : void 0;
41460
+ this.drainActionsForTurn(event.sessionId, event.turnId, error);
41461
+ const stored = storedSpan(context);
41462
+ if (stored && "exported" in stored) {
41463
+ updateSpan({
41464
+ exported: stored.exported,
41465
+ ...error !== void 0 ? { error } : {},
41466
+ metrics: { end: Date.now() / 1e3 }
41467
+ });
41468
+ }
41469
+ this.settledOperations.set(event.idempotencyKey, true);
41470
+ context.state.set(void 0);
41471
+ this.turns.delete(turnKey3(event.sessionId, event.turnId));
41472
+ });
41473
+ }
41474
+ async handleModelStarted(event, context) {
41475
+ await this.contain("model start", async () => {
41476
+ if (this.settledOperations.has(event.idempotencyKey)) {
41477
+ context.state.set({ skip: true });
41478
+ return;
41479
+ }
41480
+ const parent = await this.parentForScope(event.scope);
41481
+ const { rowId, spanId } = await generateEveIds(
41482
+ "step",
41483
+ event.idempotencyKey
41484
+ );
41485
+ const input = event.input ? capturedModelInput(event.input) : void 0;
41486
+ const metadata = {
41487
+ ...this.spanMetadata(event.scope.sessionId),
41488
+ model: event.model.modelId,
41489
+ provider: event.model.provider
41490
+ };
41491
+ const span = await this.startSpan(context, {
41492
+ event: {
41493
+ id: rowId,
41494
+ ...input !== void 0 ? { input } : {},
41495
+ metadata
41496
+ },
41497
+ name: "eve.step",
41498
+ parentSpanIds: parent,
41499
+ spanAttributes: { type: "llm" /* LLM */ },
41500
+ spanId
41501
+ });
41502
+ if (!span) return;
41503
+ span.log({ ...input !== void 0 ? { input } : {}, metadata });
41504
+ this.activeModels.set(event.idempotencyKey, {
41505
+ span,
41506
+ turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
41507
+ });
41508
+ const keys = this.modelsByAttempt.get(event.scope.attemptId) ?? /* @__PURE__ */ new Set();
41509
+ keys.add(event.idempotencyKey);
41510
+ this.modelsByAttempt.set(event.scope.attemptId, keys);
41511
+ });
41512
+ }
41513
+ async handleModelTerminal(event, context) {
41514
+ await this.contain("model terminal", async () => {
41515
+ if (this.settledOperations.has(event.idempotencyKey)) {
41516
+ context.state.set(void 0);
41517
+ return;
41518
+ }
41519
+ const active = this.activeModels.get(event.idempotencyKey);
41520
+ if (active) {
41521
+ const span = active.span;
41522
+ if (event.type === "model.call.failed") {
41523
+ if (event.error !== void 0) span.log({ error: event.error });
41524
+ } else {
41525
+ span.log({
41526
+ metrics: usageMetrics(event.usage),
41527
+ output: modelOutput(event)
41528
+ });
41529
+ }
41530
+ span.end();
41531
+ } else {
41532
+ const stored = storedSpan(context);
41533
+ if (stored && "exported" in stored) {
41534
+ updateSpan({
41535
+ exported: stored.exported,
41536
+ ...event.type === "model.call.failed" ? event.error !== void 0 ? { error: event.error } : {} : { output: modelOutput(event) },
41537
+ metrics: {
41538
+ ...event.type === "model.call.completed" ? usageMetrics(event.usage) : {},
41539
+ end: Date.now() / 1e3
41540
+ }
41541
+ });
41542
+ }
41543
+ }
41544
+ this.settledOperations.set(event.idempotencyKey, true);
41545
+ this.forgetModel(event.scope.attemptId, event.idempotencyKey);
41546
+ context.state.set(void 0);
41547
+ });
41548
+ }
41549
+ async handleActionStarted(event, context) {
41550
+ await this.contain("action start", async () => {
41551
+ if (event.kind === "load-skill" || this.settledOperations.has(event.idempotencyKey)) {
41552
+ context.state.set({ skip: true });
41553
+ return;
41554
+ }
41555
+ const parent = await this.parentForScope(event.scope);
41556
+ const { rowId, spanId } = await generateEveIds(
41557
+ event.kind === "subagent-call" ? "subagent" : "tool",
41558
+ event.idempotencyKey
41559
+ );
41560
+ const metadata = {
41561
+ ...this.spanMetadata(event.scope.sessionId),
41562
+ "eve.action_kind": event.kind
41563
+ };
41564
+ const span = await this.startSpan(context, {
41565
+ event: {
41566
+ id: rowId,
41567
+ ...event.input !== void 0 ? { input: event.input } : {},
41568
+ metadata
41569
+ },
41570
+ name: event.name,
41571
+ parentSpanIds: parent,
41572
+ spanAttributes: { type: "tool" /* TOOL */ },
41573
+ spanId
41574
+ });
41575
+ if (!span) return;
41576
+ span.log({
41577
+ ...event.input !== void 0 ? { input: event.input } : {},
41578
+ metadata
41579
+ });
41580
+ this.activeActions.set(event.idempotencyKey, {
41581
+ span,
41582
+ turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
41583
+ });
41584
+ });
41585
+ }
41586
+ async handleActionTerminal(event, context) {
41587
+ await this.contain("action terminal", async () => {
41588
+ if (this.settledOperations.has(event.idempotencyKey)) {
41589
+ context.state.set(void 0);
41590
+ return;
41591
+ }
41592
+ const stored = storedSpan(context);
41593
+ if (stored?.skip) {
41594
+ context.state.set(void 0);
41595
+ return;
41596
+ }
41597
+ const active = this.activeActions.get(event.idempotencyKey);
41598
+ const end = finiteTimestamp(event.acceptedAtMs) ?? Date.now();
41599
+ if (active) {
41600
+ const span = active.span;
41601
+ if (event.type === "action.failed") {
41602
+ span.log({
41603
+ error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
41604
+ });
41605
+ } else if (event.output.type === "error") {
41606
+ span.log({
41607
+ error: event.output.error ?? new Error("Eve action returned an error")
41608
+ });
41609
+ } else {
41610
+ span.log({ output: event.output.output });
41611
+ }
41612
+ span.end({ endTime: end / 1e3 });
41613
+ } else {
41614
+ const stored2 = storedSpan(context);
41615
+ if (stored2 && "exported" in stored2) {
41616
+ updateSpan({
41617
+ exported: stored2.exported,
41618
+ ...event.type === "action.failed" ? {
41619
+ error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
41620
+ } : event.output.type === "error" ? {
41621
+ error: event.output.error ?? new Error("Eve action returned an error")
41622
+ } : { output: event.output.output },
41623
+ metrics: { end: end / 1e3 }
41624
+ });
41625
+ }
41626
+ }
41627
+ this.settledOperations.set(event.idempotencyKey, true);
41628
+ this.activeActions.delete(event.idempotencyKey);
41629
+ context.state.set(void 0);
41630
+ });
41631
+ }
41632
+ handleStepAttemptTerminal(event) {
41633
+ void this.contain("step attempt terminal", () => {
41634
+ const keys = this.modelsByAttempt.get(event.scope.attemptId);
41635
+ if (!keys) return;
41636
+ for (const key of keys) {
41637
+ const active = this.activeModels.get(key);
41638
+ if (!active) continue;
41639
+ if (event.type === "step.attempt.failed" && event.error !== void 0) {
41640
+ active.span.log({ error: event.error });
41641
+ }
41642
+ active.span.end();
41643
+ this.activeModels.delete(key);
41644
+ }
41645
+ this.modelsByAttempt.delete(event.scope.attemptId);
41646
+ });
41647
+ }
41648
+ async parentForScope(scope) {
41649
+ const key = turnKey3(scope.sessionId, scope.turnId);
41650
+ const known = this.turns.get(key);
41651
+ if (known) {
41652
+ return { rootSpanId: known.rootSpanId, spanId: known.spanId };
41653
+ }
41654
+ const [{ spanId }, { spanId: rootSpanId }] = await Promise.all([
41655
+ generateEveIds("turn", turnIdempotencyKey(scope.sessionId, scope.turnId)),
41656
+ generateEveIds(
41657
+ "turn",
41658
+ turnIdempotencyKey(
41659
+ scope.rootSessionId ?? scope.sessionId,
41660
+ scope.turnId
41661
+ )
41662
+ )
41663
+ ]);
41664
+ return { rootSpanId, spanId };
41665
+ }
41666
+ async startSpan(context, args, rootSpanId) {
41667
+ const span = withCurrent(
41668
+ NOOP_SPAN,
41669
+ () => _internalStartSpanWithInitialMerge(
41670
+ withSpanInstrumentationName(args ?? {}, INSTRUMENTATION_NAMES.EVE)
41671
+ )
41672
+ );
41673
+ try {
41674
+ context.state.set({
41675
+ exported: await span.export(),
41676
+ ...rootSpanId ? { rootSpanId } : {}
41677
+ });
41678
+ } catch (error) {
41679
+ debugLogger.warn("Error exporting Eve provider span:", error);
41680
+ }
41681
+ return span;
41682
+ }
41683
+ drainActionsForTurn(sessionId, turnId, error) {
41684
+ const key = turnKey3(sessionId, turnId);
41685
+ for (const [idempotencyKey, active] of this.activeActions) {
41686
+ if (active.turnKey !== key) continue;
41687
+ if (error !== void 0) active.span.log({ error });
41688
+ active.span.end();
41689
+ this.activeActions.delete(idempotencyKey);
41690
+ }
41691
+ }
41692
+ forgetModel(attemptId, idempotencyKey) {
41693
+ this.activeModels.delete(idempotencyKey);
41694
+ const keys = this.modelsByAttempt.get(attemptId);
41695
+ keys?.delete(idempotencyKey);
41696
+ if (keys?.size === 0) this.modelsByAttempt.delete(attemptId);
41697
+ }
41698
+ spanMetadata(sessionId) {
41699
+ return {
41700
+ ...this.metadata ?? {},
41701
+ "eve.session_id": sessionId
41702
+ };
41703
+ }
41704
+ async contain(operation, fn) {
41705
+ try {
41706
+ await fn();
41707
+ } catch (error) {
41708
+ debugLogger.warn(`Error in Eve provider ${operation}:`, error);
41709
+ }
41710
+ }
41711
+ };
41712
+ function storedSpan(context) {
41713
+ const value = context.state.get();
41714
+ if (!isObject(value)) return void 0;
41715
+ if (value["skip"] === true) return { skip: true };
41716
+ return typeof value["exported"] === "string" ? {
41717
+ exported: value["exported"],
41718
+ ...typeof value["rootSpanId"] === "string" && value["rootSpanId"].length > 0 ? { rootSpanId: value["rootSpanId"] } : {}
41719
+ } : void 0;
41720
+ }
41721
+ function modelOutput(event) {
41722
+ const content = event.content ?? [];
41723
+ let text = "";
41724
+ const reasoning = [];
41725
+ const toolCalls2 = [];
41726
+ for (const part of content) {
41727
+ if (part.type === "text") {
41728
+ text += part.text;
41729
+ } else if (part.type === "reasoning" && part.text.trim().length > 0) {
41730
+ reasoning.push({ content: part.text });
41731
+ } else if (part.type === "tool-call") {
41732
+ toolCalls2.push({
41733
+ function: {
41734
+ arguments: safeJsonStringify(part.input),
41735
+ name: part.toolName
41736
+ },
41737
+ id: part.callId,
41738
+ type: "function"
41739
+ });
41740
+ }
41741
+ }
41742
+ return [
41743
+ {
41744
+ finish_reason: normalizeFinishReason3(event.finishReason),
41745
+ index: 0,
41746
+ message: {
41747
+ content: text || null,
41748
+ ...reasoning.length > 0 ? { reasoning } : {},
41749
+ role: "assistant",
41750
+ ...toolCalls2.length > 0 ? { tool_calls: toolCalls2 } : {}
41751
+ }
41752
+ }
41753
+ ];
41754
+ }
41755
+ function usageMetrics(usage) {
41756
+ const promptTokens = nonNegativeNumber(usage.inputTokens);
41757
+ const completionTokens = nonNegativeNumber(usage.outputTokens);
41758
+ const cachedTokens = nonNegativeNumber(
41759
+ usage.inputTokenDetails?.cacheReadTokens
41760
+ );
41761
+ const cacheCreationTokens = nonNegativeNumber(
41762
+ usage.inputTokenDetails?.cacheWriteTokens
41763
+ );
41764
+ return {
41765
+ ...promptTokens !== void 0 ? { prompt_tokens: promptTokens } : {},
41766
+ ...completionTokens !== void 0 ? { completion_tokens: completionTokens } : {},
41767
+ ...promptTokens !== void 0 && completionTokens !== void 0 ? { tokens: promptTokens + completionTokens } : {},
41768
+ ...cachedTokens !== void 0 ? { prompt_cached_tokens: cachedTokens } : {},
41769
+ ...cacheCreationTokens !== void 0 ? { prompt_cache_creation_tokens: cacheCreationTokens } : {}
41770
+ };
41771
+ }
41772
+ function nonNegativeNumber(value) {
41773
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
41774
+ }
41775
+ function finiteTimestamp(value) {
41776
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
41777
+ }
41778
+ function normalizeFinishReason3(value) {
41779
+ if (value === "content-filter") return "content_filter";
41780
+ if (value === "tool-calls") return "tool_calls";
41781
+ return value;
41782
+ }
41783
+ function safeJsonStringify(value) {
41784
+ try {
41785
+ return JSON.stringify(value) ?? "null";
41786
+ } catch {
41787
+ return "null";
41788
+ }
41789
+ }
41790
+ function turnKey3(sessionId, turnId) {
41791
+ return `${sessionId}:${turnId}`;
41792
+ }
41793
+ function turnIdempotencyKey(sessionId, turnId) {
41794
+ return `turn:${sessionId}:${turnId}`;
41795
+ }
41796
+ function actionIdempotencyKey(sessionId, turnId, callId) {
41797
+ return `action:${sessionId}:${turnId}:${callId}`;
41798
+ }
41799
+
41800
+ // src/instrumentation/plugins/eve-instrumentation.ts
41801
+ var EVE_INSTRUMENTATION_PROVIDER = /* @__PURE__ */ Symbol.for("eve.instrumentation.provider");
41802
+ function braintrustEveInstrumentation(options) {
41803
+ const definition = "defineState" in options ? createLegacyEveInstrumentation(options) : createEveInstrumentationProvider(options);
41804
+ const declaration = {
41805
+ ...definition,
41806
+ [EVE_INSTRUMENTATION_PROVIDER]: true
41807
+ };
41808
+ return declaration;
41809
+ }
41810
+
40149
41811
  // src/typed-instrumentation-helpers.ts
40150
41812
  var TypedApplyProxy = Proxy;
40151
41813
 
@@ -40547,11 +42209,11 @@ function wrapClaudeAgentQuery(queryFn, defaultThis) {
40547
42209
  }
40548
42210
  };
40549
42211
  const invocationTarget = thisArg === proxy || thisArg === void 0 ? defaultThis ?? thisArg : thisArg;
40550
- return claudeAgentSDKChannels.query.traceSync(
40551
- () => Reflect.apply(target, invocationTarget, [wrappedParams]),
40552
- // The channel carries no extra context fields, but the generated
40553
- // StartOf<> type for Record<string, never> is overly strict here.
40554
- { arguments: [wrappedParams] }
42212
+ return claudeAgentSDKChannels.query.invoke(
42213
+ target,
42214
+ invocationTarget,
42215
+ [wrappedParams],
42216
+ {}
40555
42217
  );
40556
42218
  }
40557
42219
  });
@@ -41166,13 +42828,11 @@ function wrapAgentInstance(agent) {
41166
42828
  if (prop === "stream" && typeof value === "function") {
41167
42829
  return function(args, options) {
41168
42830
  const callArgs = [args, options];
41169
- return strandsAgentSDKChannels.agentStream.traceSync(
41170
- () => Reflect.apply(value, target, callArgs),
41171
- {
41172
- agent: proxy,
41173
- arguments: callArgs,
41174
- self: proxy
41175
- }
42831
+ return strandsAgentSDKChannels.agentStream.invoke(
42832
+ value,
42833
+ target,
42834
+ callArgs,
42835
+ { agent: proxy }
41176
42836
  );
41177
42837
  };
41178
42838
  }
@@ -41203,12 +42863,12 @@ function wrapMultiAgentInstance(orchestrator, kind) {
41203
42863
  return function(input, options) {
41204
42864
  const callArgs = [input, options];
41205
42865
  const channel2 = kind === "graph" ? strandsAgentSDKChannels.graphStream : strandsAgentSDKChannels.swarmStream;
41206
- return channel2.traceSync(
41207
- () => Reflect.apply(value, target, callArgs),
42866
+ return channel2.invoke(
42867
+ value,
42868
+ target,
42869
+ callArgs,
41208
42870
  {
41209
- arguments: callArgs,
41210
- orchestrator: proxy,
41211
- self: proxy
42871
+ orchestrator: proxy
41212
42872
  }
41213
42873
  );
41214
42874
  };
@@ -43160,9 +44820,6 @@ var VitestContextManager = class {
43160
44820
  getCurrentContext() {
43161
44821
  return this.contextStorage.getStore();
43162
44822
  }
43163
- setContext(context) {
43164
- this.contextStorage.enterWith(context);
43165
- }
43166
44823
  runInContext(context, callback) {
43167
44824
  return this.contextStorage.run(context, callback);
43168
44825
  }
@@ -43548,8 +45205,7 @@ function wrapDescribe(originalDescribe, config, afterAll) {
43548
45205
  if (config.onProgress) {
43549
45206
  config.onProgress({ type: "suite_start", suiteName });
43550
45207
  }
43551
- contextManager.setContext(lazyContext);
43552
- factory();
45208
+ contextManager.runInContext(lazyContext, factory);
43553
45209
  if (afterAll) {
43554
45210
  afterAll(async () => {
43555
45211
  await flushExperimentWithSync(context, config);
@@ -48738,6 +50394,7 @@ export {
48738
50394
  braintrustStreamChunkSchema,
48739
50395
  buildLocalSummary,
48740
50396
  collectAnthropicSession,
50397
+ completeOpenAIBatchTrace,
48741
50398
  configureInstrumentation,
48742
50399
  constructLogs3OverflowRequest,
48743
50400
  createFinalValuePassThroughStream,
@@ -48777,6 +50434,8 @@ export {
48777
50434
  loginToState,
48778
50435
  logs3OverflowUploadSchema,
48779
50436
  newId,
50437
+ openaiBatchesRetrieveTraced,
50438
+ openaiFilesCreateTraced,
48780
50439
  parseCachedHeader,
48781
50440
  parseTemplateFormat,
48782
50441
  permalink,