braintrust 3.28.0 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +1 -1
  2. package/dev/dist/index.d.mts +356 -7
  3. package/dev/dist/index.d.ts +356 -7
  4. package/dev/dist/index.js +1815 -1548
  5. package/dev/dist/index.mjs +1054 -787
  6. package/dist/apply-auto-instrumentation.js +297 -264
  7. package/dist/apply-auto-instrumentation.mjs +84 -51
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +43 -5
  9. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  10. package/dist/auto-instrumentations/bundler/next.cjs +43 -5
  11. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  12. package/dist/auto-instrumentations/bundler/rollup.cjs +43 -5
  13. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.cjs +43 -5
  15. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  16. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +43 -5
  17. package/dist/auto-instrumentations/bundler/webpack.cjs +43 -5
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  19. package/dist/auto-instrumentations/{chunk-NP7V4XB2.mjs → chunk-AOIYCVEL.mjs} +32 -2
  20. package/dist/auto-instrumentations/{chunk-26PKVUKB.mjs → chunk-DKTGDNA7.mjs} +12 -4
  21. package/dist/auto-instrumentations/{chunk-HD35AM3M.mjs → chunk-OMCZ3MV2.mjs} +1 -1
  22. package/dist/auto-instrumentations/hook.mjs +952 -133
  23. package/dist/auto-instrumentations/index.cjs +32 -2
  24. package/dist/auto-instrumentations/index.mjs +1 -1
  25. package/dist/browser.d.mts +760 -22
  26. package/dist/browser.d.ts +760 -22
  27. package/dist/browser.js +1661 -848
  28. package/dist/browser.mjs +1661 -848
  29. package/dist/{chunk-BBE7SNRV.js → chunk-6Z5S7VOU.js} +143 -23
  30. package/dist/{chunk-ZHUHZWFY.mjs → chunk-7FA6VP2S.mjs} +140 -20
  31. package/dist/{chunk-UPFNQCGB.mjs → chunk-M6XPNJC4.mjs} +1144 -931
  32. package/dist/{chunk-OBBWQW6K.js → chunk-XLLGRXGR.js} +2335 -2122
  33. package/dist/cli.js +5134 -1090
  34. package/dist/edge-light.js +1661 -848
  35. package/dist/edge-light.mjs +1661 -848
  36. package/dist/index.d.mts +760 -22
  37. package/dist/index.d.ts +760 -22
  38. package/dist/index.js +1054 -567
  39. package/dist/index.mjs +514 -27
  40. package/dist/instrumentation/index.d.mts +548 -9
  41. package/dist/instrumentation/index.d.ts +548 -9
  42. package/dist/instrumentation/index.js +1975 -765
  43. package/dist/instrumentation/index.mjs +1975 -765
  44. package/dist/vitest-evals-reporter.js +16 -16
  45. package/dist/vitest-evals-reporter.mjs +2 -2
  46. package/dist/workerd.js +1661 -848
  47. package/dist/workerd.mjs +1661 -848
  48. package/package.json +1 -1
  49. package/util/dist/index.d.mts +42 -0
  50. package/util/dist/index.d.ts +42 -0
@@ -10,11 +10,13 @@ import {
10
10
  cloudflareThinkChannels,
11
11
  cohereChannels,
12
12
  cursorSDKChannels,
13
+ debugLogger,
13
14
  detectSpanOriginEnvironment,
14
15
  flueChannels,
15
16
  genkitChannels,
16
17
  genkitCoreChannels,
17
18
  getDefaultInstrumentationIntegrations,
19
+ getEnvDebugLogLevel,
18
20
  getHuggingFaceTransformersPipelineInfo,
19
21
  getSpanInstrumentationName,
20
22
  gitHubCopilotChannels,
@@ -32,6 +34,7 @@ import {
32
34
  langSmithChannels,
33
35
  mergeSpanOriginContext,
34
36
  mistralChannels,
37
+ normalizeDebugLogLevelOption,
35
38
  ollamaChannels,
36
39
  openAIAgentsCoreChannels,
37
40
  openAIChannels,
@@ -41,130 +44,18 @@ import {
41
44
  piCodingAgentChannels,
42
45
  readDisabledInstrumentationEnvConfig,
43
46
  registerHuggingFaceTransformersPipeline,
44
- setGlobalHookErrorReporter,
47
+ resetDebugLoggerForTests,
48
+ setDebugLogStateResolver,
49
+ setGlobalDebugLogLevel,
45
50
  smithyClientChannels,
46
51
  smithyCoreChannels,
47
52
  strandsAgentSDKChannels,
48
53
  voyageAIChannels,
49
54
  withSpanInstrumentationName
50
- } from "./chunk-ZHUHZWFY.mjs";
55
+ } from "./chunk-7FA6VP2S.mjs";
51
56
 
52
57
  // src/id-gen.ts
53
58
  import { v4 as uuidv4 } from "uuid";
54
-
55
- // src/debug-logger.ts
56
- var PREFIX = "[braintrust]";
57
- var DEBUG_LOG_LEVEL_SYMBOL = /* @__PURE__ */ Symbol.for("braintrust-debug-log-level");
58
- var LOG_LEVEL_PRIORITY = {
59
- error: 0,
60
- warn: 1,
61
- info: 2,
62
- debug: 3
63
- };
64
- var hasWarnedAboutInvalidEnvValue = false;
65
- var debugLogStateResolver = void 0;
66
- function warnInvalidEnvValue(value) {
67
- if (hasWarnedAboutInvalidEnvValue) {
68
- return;
69
- }
70
- hasWarnedAboutInvalidEnvValue = true;
71
- console.warn(
72
- PREFIX,
73
- `Invalid BRAINTRUST_DEBUG_LOG_LEVEL value "${value}". Expected "error", "warn", "info", or "debug".`
74
- );
75
- }
76
- function normalizeDebugLogLevelOption(option) {
77
- if (option === false) {
78
- return void 0;
79
- }
80
- if (option === "error" || option === "warn" || option === "info" || option === "debug") {
81
- return option;
82
- }
83
- throw new Error(
84
- `Invalid debugLogLevel value "${option}". Expected false, "error", "warn", "info", or "debug".`
85
- );
86
- }
87
- function parseDebugLogLevelEnv(value) {
88
- if (!value) {
89
- return void 0;
90
- }
91
- if (value === "error" || value === "warn" || value === "info" || value === "debug") {
92
- return value;
93
- }
94
- warnInvalidEnvValue(value);
95
- return void 0;
96
- }
97
- function getEnvDebugLogLevel() {
98
- return parseDebugLogLevelEnv(isomorph_default.getEnv("BRAINTRUST_DEBUG_LOG_LEVEL"));
99
- }
100
- function setGlobalDebugLogLevel(level) {
101
- globalThis[DEBUG_LOG_LEVEL_SYMBOL] = level;
102
- }
103
- function resetDebugLoggerForTests() {
104
- hasWarnedAboutInvalidEnvValue = false;
105
- setGlobalDebugLogLevel(void 0);
106
- }
107
- function setDebugLogStateResolver(resolver) {
108
- debugLogStateResolver = resolver;
109
- }
110
- function resolveDebugLogLevel(state) {
111
- const stateLevel = state?.getDebugLogLevel?.();
112
- const hasStateOverride = state?.hasDebugLogLevelOverride?.() ?? false;
113
- if (hasStateOverride) {
114
- return stateLevel;
115
- }
116
- const globalLevel = (
117
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
118
- globalThis[DEBUG_LOG_LEVEL_SYMBOL]
119
- );
120
- if (globalLevel !== void 0) {
121
- return globalLevel === false ? void 0 : globalLevel;
122
- }
123
- return getEnvDebugLogLevel();
124
- }
125
- function emit(method, state, args) {
126
- const level = resolveDebugLogLevel(state);
127
- if (!level || LOG_LEVEL_PRIORITY[method] > LOG_LEVEL_PRIORITY[level]) {
128
- return;
129
- }
130
- if (method === "info") {
131
- console.log(PREFIX, ...args);
132
- } else if (method === "debug") {
133
- console.debug(PREFIX, ...args);
134
- } else if (method === "warn") {
135
- console.warn(PREFIX, ...args);
136
- } else {
137
- console.error(PREFIX, ...args);
138
- }
139
- }
140
- function createDebugLogger(state) {
141
- const resolveState = () => state ?? debugLogStateResolver?.();
142
- return {
143
- info(...args) {
144
- emit("info", resolveState(), args);
145
- },
146
- debug(...args) {
147
- emit("debug", resolveState(), args);
148
- },
149
- warn(...args) {
150
- emit("warn", resolveState(), args);
151
- },
152
- error(...args) {
153
- emit("error", resolveState(), args);
154
- }
155
- };
156
- }
157
- var debugLogger = {
158
- ...createDebugLogger(),
159
- forState(state) {
160
- return createDebugLogger(state);
161
- }
162
- };
163
- setGlobalHookErrorReporter((error) => {
164
- debugLogger.error("Global instrumentation hook error:", error);
165
- });
166
-
167
- // src/id-gen.ts
168
59
  var IDGenerator = class {
169
60
  };
170
61
  var UUIDGenerator = class extends IDGenerator {
@@ -1782,7 +1673,9 @@ var AclObjectType = z6.union([
1782
1673
  "project_log",
1783
1674
  "org_project",
1784
1675
  "org_audit_logs",
1785
- "project_group"
1676
+ "project_group",
1677
+ "ai_secret",
1678
+ "org_ai_secret"
1786
1679
  ]),
1787
1680
  z6.null()
1788
1681
  ]);
@@ -2615,7 +2508,7 @@ var PromptParserNullish = z6.union([
2615
2508
  }),
2616
2509
  z6.null()
2617
2510
  ]);
2618
- var PreprocessorSavedFunctionId = z6.union([
2511
+ var PreprocessorId = z6.union([
2619
2512
  z6.object({
2620
2513
  type: z6.literal("function"),
2621
2514
  id: z6.string(),
@@ -2626,6 +2519,7 @@ var PreprocessorSavedFunctionId = z6.union([
2626
2519
  name: z6.string(),
2627
2520
  function_type: z6.literal("preprocessor").optional().default("preprocessor")
2628
2521
  }),
2522
+ z6.object({ type: z6.literal("inline"), code: z6.string().min(1) }),
2629
2523
  z6.null()
2630
2524
  ]);
2631
2525
  var PromptDataNullish = z6.union([
@@ -2633,7 +2527,7 @@ var PromptDataNullish = z6.union([
2633
2527
  prompt: PromptBlockDataNullish,
2634
2528
  options: PromptOptionsNullish,
2635
2529
  parser: PromptParserNullish,
2636
- preprocessor: PreprocessorSavedFunctionId,
2530
+ preprocessor: PreprocessorId,
2637
2531
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
2638
2532
  template_format: z6.union([
2639
2533
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -2835,7 +2729,7 @@ var PromptData = z6.object({
2835
2729
  prompt: PromptBlockDataNullish,
2836
2730
  options: PromptOptionsNullish,
2837
2731
  parser: PromptParserNullish,
2838
- preprocessor: PreprocessorSavedFunctionId,
2732
+ preprocessor: PreprocessorId,
2839
2733
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
2840
2734
  template_format: z6.union([
2841
2735
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -3779,6 +3673,7 @@ var View = z6.object({
3779
3673
  ]),
3780
3674
  name: z6.string(),
3781
3675
  description: z6.union([z6.string(), z6.null()]).optional(),
3676
+ starred: z6.boolean().optional(),
3782
3677
  created: z6.union([z6.string(), z6.null()]).optional(),
3783
3678
  updated_at: z6.union([z6.string(), z6.null()]).optional(),
3784
3679
  view_data: ViewData.optional(),
@@ -4539,44 +4434,72 @@ function createCacheLayers({
4539
4434
  }
4540
4435
 
4541
4436
  // src/prompt-cache/prompt-cache.ts
4542
- function createCacheKey(key) {
4437
+ function createCacheKey(key, namespace) {
4438
+ let cacheKey;
4543
4439
  if (key.id) {
4544
- return `id:${key.id}`;
4545
- }
4546
- const prefix = key.projectId ?? key.projectName;
4547
- if (!prefix) {
4548
- throw new Error("Either projectId or projectName must be provided");
4549
- }
4550
- if (!key.slug) {
4551
- throw new Error("Slug must be provided when not using ID");
4440
+ cacheKey = `id:${key.id}`;
4441
+ } else {
4442
+ const prefix = key.projectId ?? key.projectName;
4443
+ if (!prefix) {
4444
+ throw new Error("Either projectId or projectName must be provided");
4445
+ }
4446
+ if (!key.slug) {
4447
+ throw new Error("Slug must be provided when not using ID");
4448
+ }
4449
+ cacheKey = `${prefix}:${key.slug}:${key.version ?? "latest"}`;
4552
4450
  }
4553
- return `${prefix}:${key.slug}:${key.version ?? "latest"}`;
4451
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
4554
4452
  }
4555
- var PromptCache = class {
4453
+ var PromptCache = class _PromptCache {
4556
4454
  memoryCache;
4557
4455
  diskCache;
4456
+ namespace;
4457
+ expectedResolvedOrgIdentity;
4558
4458
  constructor(options) {
4559
4459
  this.memoryCache = options.memoryCache;
4560
4460
  this.diskCache = options.diskCache;
4461
+ this.namespace = options.namespace;
4462
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
4463
+ }
4464
+ /**
4465
+ * Returns a cache view that shares the same storage layers but isolates all
4466
+ * entries under the provided namespace.
4467
+ */
4468
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
4469
+ return new _PromptCache({
4470
+ memoryCache: this.memoryCache,
4471
+ diskCache: this.diskCache,
4472
+ namespace,
4473
+ expectedResolvedOrgIdentity
4474
+ });
4561
4475
  }
4562
4476
  /**
4563
4477
  * Retrieves a prompt from the cache.
4564
4478
  * First checks the in-memory LRU cache, then falls back to checking the disk cache if available.
4565
4479
  */
4566
4480
  async get(key) {
4567
- const cacheKey = createCacheKey(key);
4481
+ const cacheKey = createCacheKey(key, this.namespace);
4568
4482
  if (this.memoryCache) {
4569
- const memoryPrompt = this.memoryCache.get(cacheKey);
4570
- if (memoryPrompt !== void 0) {
4571
- return memoryPrompt;
4483
+ const memoryEntry = this.memoryCache.get(cacheKey);
4484
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
4485
+ return memoryEntry.value;
4572
4486
  }
4573
4487
  }
4574
4488
  if (this.diskCache) {
4575
- const diskPrompt = await this.diskCache.get(cacheKey);
4576
- if (!diskPrompt) {
4489
+ const diskEntry = await this.diskCache.get(cacheKey);
4490
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
4577
4491
  return void 0;
4578
4492
  }
4579
- this.memoryCache?.set(cacheKey, diskPrompt);
4493
+ const serializedPrompt = diskEntry.value;
4494
+ const diskPrompt = new Prompt2(
4495
+ serializedPrompt.metadata,
4496
+ serializedPrompt.defaults,
4497
+ serializedPrompt.noTrace
4498
+ );
4499
+ this.memoryCache?.set(cacheKey, {
4500
+ value: diskPrompt,
4501
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
4502
+ });
4580
4503
  return diskPrompt;
4581
4504
  }
4582
4505
  return void 0;
@@ -4590,58 +4513,91 @@ var PromptCache = class {
4590
4513
  * @throws If there is an error writing to the disk cache.
4591
4514
  */
4592
4515
  async set(key, value) {
4593
- const cacheKey = createCacheKey(key);
4594
- this.memoryCache?.set(cacheKey, value);
4516
+ const cacheKey = createCacheKey(key, this.namespace);
4517
+ const memoryEntry = {
4518
+ value,
4519
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
4520
+ };
4521
+ this.memoryCache?.set(cacheKey, memoryEntry);
4595
4522
  if (this.diskCache) {
4596
- await this.diskCache.set(cacheKey, value);
4523
+ await this.diskCache.set(cacheKey, {
4524
+ value: value._internalSerializeForCache(),
4525
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
4526
+ });
4597
4527
  }
4598
4528
  }
4599
4529
  };
4600
4530
 
4601
4531
  // src/prompt-cache/parameters-cache.ts
4602
- function createCacheKey2(key) {
4532
+ function createCacheKey2(key, namespace) {
4533
+ let cacheKey;
4603
4534
  if (key.id) {
4604
- return `parameters:id:${key.id}`;
4605
- }
4606
- const prefix = key.projectId ?? key.projectName;
4607
- if (!prefix) {
4608
- throw new Error("Either projectId or projectName must be provided");
4609
- }
4610
- if (!key.slug) {
4611
- throw new Error("Slug must be provided when not using ID");
4535
+ cacheKey = `parameters:id:${key.id}`;
4536
+ } else {
4537
+ const prefix = key.projectId ?? key.projectName;
4538
+ if (!prefix) {
4539
+ throw new Error("Either projectId or projectName must be provided");
4540
+ }
4541
+ if (!key.slug) {
4542
+ throw new Error("Slug must be provided when not using ID");
4543
+ }
4544
+ cacheKey = `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
4612
4545
  }
4613
- return `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
4546
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
4614
4547
  }
4615
- var ParametersCache = class {
4548
+ var ParametersCache = class _ParametersCache {
4616
4549
  memoryCache;
4617
4550
  diskCache;
4551
+ namespace;
4552
+ expectedResolvedOrgIdentity;
4618
4553
  constructor(options) {
4619
4554
  this.memoryCache = options.memoryCache;
4620
4555
  this.diskCache = options.diskCache;
4556
+ this.namespace = options.namespace;
4557
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
4558
+ }
4559
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
4560
+ return new _ParametersCache({
4561
+ memoryCache: this.memoryCache,
4562
+ diskCache: this.diskCache,
4563
+ namespace,
4564
+ expectedResolvedOrgIdentity
4565
+ });
4621
4566
  }
4622
4567
  async get(key) {
4623
- const cacheKey = createCacheKey2(key);
4568
+ const cacheKey = createCacheKey2(key, this.namespace);
4624
4569
  if (this.memoryCache) {
4625
- const memoryParams = this.memoryCache.get(cacheKey);
4626
- if (memoryParams !== void 0) {
4627
- return memoryParams;
4570
+ const memoryEntry = this.memoryCache.get(cacheKey);
4571
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
4572
+ return memoryEntry.value;
4628
4573
  }
4629
4574
  }
4630
4575
  if (this.diskCache) {
4631
- const diskParams = await this.diskCache.get(cacheKey);
4632
- if (!diskParams) {
4576
+ const diskEntry = await this.diskCache.get(cacheKey);
4577
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
4633
4578
  return void 0;
4634
4579
  }
4635
- this.memoryCache?.set(cacheKey, diskParams);
4636
- return diskParams;
4580
+ const diskParameters = new RemoteEvalParameters(diskEntry.value.metadata);
4581
+ this.memoryCache?.set(cacheKey, {
4582
+ value: diskParameters,
4583
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
4584
+ });
4585
+ return diskParameters;
4637
4586
  }
4638
4587
  return void 0;
4639
4588
  }
4640
4589
  async set(key, value) {
4641
- const cacheKey = createCacheKey2(key);
4642
- this.memoryCache?.set(cacheKey, value);
4590
+ const cacheKey = createCacheKey2(key, this.namespace);
4591
+ const memoryEntry = {
4592
+ value,
4593
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
4594
+ };
4595
+ this.memoryCache?.set(cacheKey, memoryEntry);
4643
4596
  if (this.diskCache) {
4644
- await this.diskCache.set(cacheKey, value);
4597
+ await this.diskCache.set(cacheKey, {
4598
+ value: value._internalSerializeForCache(),
4599
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
4600
+ });
4645
4601
  }
4646
4602
  }
4647
4603
  };
@@ -4946,6 +4902,16 @@ var datasetSnapshotRegisterResponseSchema = z8.object({
4946
4902
  dataset_snapshot: DatasetSnapshot,
4947
4903
  found_existing: z8.boolean().optional()
4948
4904
  });
4905
+ var datasetObjectInfoSchema = z8.object({
4906
+ object_id: z8.string(),
4907
+ object_name: z8.string(),
4908
+ parent_cols: z8.object({
4909
+ project: z8.object({
4910
+ id: z8.string(),
4911
+ name: z8.string()
4912
+ })
4913
+ })
4914
+ });
4949
4915
  var datasetRestorePreviewResultSchema = z8.object({
4950
4916
  rows_to_restore: z8.number(),
4951
4917
  rows_to_delete: z8.number()
@@ -5159,12 +5125,53 @@ var loginSchema = z8.strictObject({
5159
5125
  });
5160
5126
  var stateNonce = 0;
5161
5127
  var V1_PROXY_SUFFIX = "/v1/proxy";
5128
+ var LOADER_LOGIN_CACHE_MAX = 16;
5162
5129
  function normalizeProxyConnUrl(proxyUrl) {
5163
5130
  return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
5164
5131
  }
5165
5132
  var BraintrustState = class _BraintrustState {
5133
+ id;
5134
+ currentExperiment;
5135
+ // Note: the value of IsAsyncFlush doesn't really matter here, since we
5136
+ // (safely) dynamically cast it whenever retrieving the logger.
5137
+ currentLogger;
5138
+ currentParent;
5139
+ currentSpan;
5140
+ // Any time we re-log in, we directly update the apiConn inside the logger.
5141
+ // This is preferable to replacing the whole logger, which would create the
5142
+ // possibility of multiple loggers floating around, which may not log in a
5143
+ // deterministic order.
5144
+ _bgLogger;
5145
+ _overrideBgLogger = null;
5146
+ appUrl = null;
5147
+ appPublicUrl = null;
5148
+ loginToken = null;
5149
+ orgId = null;
5150
+ orgName = null;
5151
+ apiUrl = null;
5152
+ proxyUrl = null;
5153
+ loggedIn = false;
5154
+ gitMetadataSettings;
5155
+ debugLogLevel;
5156
+ debugLogLevelConfigured = false;
5157
+ fetch = globalThis.fetch;
5158
+ _appConn = null;
5159
+ _apiConn = null;
5160
+ _proxyConn = null;
5161
+ promptCache;
5162
+ parametersCache;
5163
+ spanCache;
5164
+ _idGenerator = null;
5165
+ _contextManager = null;
5166
+ _otelFlushCallback = null;
5167
+ spanOriginEnvironment;
5168
+ traceContextSigningSecret;
5169
+ loaderLoginCache = /* @__PURE__ */ new WeakMap();
5170
+ loginParams;
5171
+ activeLoginOrgNameSelector;
5166
5172
  constructor(loginParams) {
5167
- this.loginParams = loginParams;
5173
+ this.loginParams = { ...loginParams };
5174
+ this.activeLoginOrgNameSelector = loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
5168
5175
  this.id = `${(/* @__PURE__ */ new Date()).toLocaleString()}-${stateNonce++}`;
5169
5176
  this.currentExperiment = void 0;
5170
5177
  this.currentLogger = void 0;
@@ -5201,12 +5208,14 @@ var BraintrustState = class _BraintrustState {
5201
5208
  const {
5202
5209
  memoryCache: parametersMemoryCache,
5203
5210
  diskCache: parametersDiskCache
5204
- } = createCacheLayers({
5205
- memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
5206
- diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
5207
- diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
5208
- getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
5209
- });
5211
+ } = createCacheLayers(
5212
+ {
5213
+ memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
5214
+ diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
5215
+ diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
5216
+ getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
5217
+ }
5218
+ );
5210
5219
  this.parametersCache = new ParametersCache({
5211
5220
  memoryCache: parametersMemoryCache,
5212
5221
  diskCache: parametersDiskCache
@@ -5215,43 +5224,6 @@ var BraintrustState = class _BraintrustState {
5215
5224
  this.spanOriginEnvironment = detectSpanOriginEnvironment();
5216
5225
  this._internalSetTraceContextSigningSecret(loginParams.apiKey);
5217
5226
  }
5218
- loginParams;
5219
- id;
5220
- currentExperiment;
5221
- // Note: the value of IsAsyncFlush doesn't really matter here, since we
5222
- // (safely) dynamically cast it whenever retrieving the logger.
5223
- currentLogger;
5224
- currentParent;
5225
- currentSpan;
5226
- // Any time we re-log in, we directly update the apiConn inside the logger.
5227
- // This is preferable to replacing the whole logger, which would create the
5228
- // possibility of multiple loggers floating around, which may not log in a
5229
- // deterministic order.
5230
- _bgLogger;
5231
- _overrideBgLogger = null;
5232
- appUrl = null;
5233
- appPublicUrl = null;
5234
- loginToken = null;
5235
- orgId = null;
5236
- orgName = null;
5237
- apiUrl = null;
5238
- proxyUrl = null;
5239
- loggedIn = false;
5240
- gitMetadataSettings;
5241
- debugLogLevel;
5242
- debugLogLevelConfigured = false;
5243
- fetch = globalThis.fetch;
5244
- _appConn = null;
5245
- _apiConn = null;
5246
- _proxyConn = null;
5247
- promptCache;
5248
- parametersCache;
5249
- spanCache;
5250
- _idGenerator = null;
5251
- _contextManager = null;
5252
- _otelFlushCallback = null;
5253
- spanOriginEnvironment;
5254
- traceContextSigningSecret;
5255
5227
  /** @internal */
5256
5228
  _internalSetTraceContextSigningSecret(secret) {
5257
5229
  const normalizedSecret = secret?.trim();
@@ -5276,6 +5248,101 @@ var BraintrustState = class _BraintrustState {
5276
5248
  this._appConn = null;
5277
5249
  this._apiConn = null;
5278
5250
  this._proxyConn = null;
5251
+ this.loaderLoginCache = /* @__PURE__ */ new WeakMap();
5252
+ }
5253
+ /** @internal */
5254
+ async _internalResolveLoaderLoginOptions({
5255
+ apiKey,
5256
+ appUrl,
5257
+ orgName,
5258
+ fetch: fetch2,
5259
+ forceLogin
5260
+ }) {
5261
+ const resolvedAppUrl = appUrl ?? (this.loggedIn ? this.appUrl ?? void 0 : void 0) ?? this.loginParams.appUrl ?? isomorph_default.getEnv("BRAINTRUST_APP_URL") ?? "https://www.braintrust.dev";
5262
+ const resolvedApiKey = apiKey ?? (this.loggedIn ? this.loginToken ?? void 0 : void 0) ?? this.loginParams.apiKey ?? await isomorph_default.getBraintrustApiKey();
5263
+ if (!resolvedApiKey) {
5264
+ throw new Error(
5265
+ "Please specify an api key (e.g. by setting BRAINTRUST_API_KEY)."
5266
+ );
5267
+ }
5268
+ const normalizedApiKey = HTTPConnection.sanitize_token(resolvedApiKey);
5269
+ const usesActiveCredential = this.loggedIn && normalizedApiKey === this.loginToken;
5270
+ const requestedOrgName = orgName ?? (usesActiveCredential ? this.activeLoginOrgNameSelector : void 0) ?? this.loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
5271
+ const resolvedOrgName = orgName ?? (usesActiveCredential ? this.orgName ?? void 0 : void 0) ?? requestedOrgName;
5272
+ const resolvedFetch = fetch2 ?? (this.loggedIn ? this.fetch : void 0) ?? this.loginParams.fetch ?? globalThis.fetch;
5273
+ const credentialCacheNamespace = JSON.stringify([
5274
+ "loader-credential",
5275
+ resolvedAppUrl,
5276
+ requestedOrgName,
5277
+ normalizedApiKey
5278
+ ]);
5279
+ return {
5280
+ apiKey: normalizedApiKey,
5281
+ appUrl: resolvedAppUrl,
5282
+ orgName: resolvedOrgName,
5283
+ fetch: resolvedFetch,
5284
+ forceLogin,
5285
+ credentialCacheNamespace,
5286
+ existingState: !forceLogin && usesActiveCredential && resolvedAppUrl === this.appUrl && resolvedOrgName === this.orgName && resolvedFetch === this.fetch ? this : void 0
5287
+ };
5288
+ }
5289
+ /** @internal */
5290
+ _internalGetLoaderCacheViews(loginOptions, requestState) {
5291
+ const expectedResolvedOrgIdentity = requestState?.orgId && requestState.appUrl ? JSON.stringify([
5292
+ "loader-org",
5293
+ requestState.appUrl,
5294
+ requestState.orgId
5295
+ ]) : void 0;
5296
+ return {
5297
+ promptCache: this.promptCache.withNamespace(
5298
+ loginOptions.credentialCacheNamespace,
5299
+ expectedResolvedOrgIdentity
5300
+ ),
5301
+ parametersCache: this.parametersCache.withNamespace(
5302
+ loginOptions.credentialCacheNamespace,
5303
+ expectedResolvedOrgIdentity
5304
+ )
5305
+ };
5306
+ }
5307
+ /** @internal */
5308
+ async _internalGetLoaderState({
5309
+ apiKey,
5310
+ appUrl,
5311
+ orgName,
5312
+ fetch: fetch2,
5313
+ forceLogin,
5314
+ existingState
5315
+ }) {
5316
+ if (existingState) {
5317
+ return existingState;
5318
+ }
5319
+ let cache = this.loaderLoginCache.get(fetch2);
5320
+ if (!cache) {
5321
+ cache = new LRUCache({ max: LOADER_LOGIN_CACHE_MAX });
5322
+ this.loaderLoginCache.set(fetch2, cache);
5323
+ }
5324
+ const cacheKey = JSON.stringify([appUrl, orgName, apiKey]);
5325
+ if (!forceLogin) {
5326
+ const cachedState = cache.get(cacheKey);
5327
+ if (cachedState) {
5328
+ return cachedState;
5329
+ }
5330
+ }
5331
+ const statePromise = loginToLoaderRequestState({
5332
+ orgName,
5333
+ apiKey,
5334
+ appUrl,
5335
+ fetch: fetch2
5336
+ });
5337
+ cache.set(cacheKey, statePromise);
5338
+ try {
5339
+ return await statePromise;
5340
+ } catch (error) {
5341
+ if (cache.get(cacheKey) === statePromise) {
5342
+ cache.delete(cacheKey);
5343
+ }
5344
+ throw error;
5345
+ }
5279
5346
  }
5280
5347
  resetIdGenState() {
5281
5348
  this._idGenerator = null;
@@ -5324,6 +5391,8 @@ var BraintrustState = class _BraintrustState {
5324
5391
  this.debugLogLevel = other.debugLogLevel;
5325
5392
  this.debugLogLevelConfigured = other.debugLogLevelConfigured;
5326
5393
  this.traceContextSigningSecret = other.traceContextSigningSecret;
5394
+ this.fetch = other.fetch;
5395
+ this.activeLoginOrgNameSelector = other.activeLoginOrgNameSelector;
5327
5396
  setGlobalDebugLogLevel(
5328
5397
  this.debugLogLevelConfigured ? this.debugLogLevel ?? false : void 0
5329
5398
  );
@@ -5563,36 +5632,85 @@ var FailedHTTPResponse = class extends Error {
5563
5632
  status;
5564
5633
  text;
5565
5634
  data;
5566
- constructor(status, text, data) {
5635
+ cause;
5636
+ constructor(status, text, data, cause) {
5567
5637
  super(`${status}: ${text} (${data})`);
5568
5638
  this.status = status;
5569
5639
  this.text = text;
5570
5640
  this.data = data;
5641
+ this.cause = cause;
5642
+ }
5643
+ };
5644
+ var HTTPTransportError = class extends Error {
5645
+ cause;
5646
+ constructor(cause) {
5647
+ super(cause instanceof Error ? cause.message : String(cause));
5648
+ this.name = "HTTPTransportError";
5649
+ this.cause = cause;
5571
5650
  }
5572
5651
  };
5652
+ var httpTransportErrorCauses = /* @__PURE__ */ new WeakSet();
5653
+ function recordHTTPTransportError(error) {
5654
+ if (typeof error === "object" && error !== null || typeof error === "function") {
5655
+ httpTransportErrorCauses.add(error);
5656
+ }
5657
+ }
5658
+ function rethrowHTTPTransportError(error, classifyTransportErrors) {
5659
+ if (classifyTransportErrors) {
5660
+ throw new HTTPTransportError(error);
5661
+ }
5662
+ recordHTTPTransportError(error);
5663
+ throw error;
5664
+ }
5665
+ function isLoaderCacheFallbackError(error) {
5666
+ if (error instanceof FailedHTTPResponse) {
5667
+ return error.status === 408 || error.status === 429 || error.status >= 500;
5668
+ }
5669
+ if (error instanceof HTTPTransportError) {
5670
+ return true;
5671
+ }
5672
+ return (typeof error === "object" && error !== null || typeof error === "function") && httpTransportErrorCauses.has(error);
5673
+ }
5674
+ async function readJSONResponse(response, classifyTransportErrors = false) {
5675
+ let data;
5676
+ try {
5677
+ data = await response.text();
5678
+ } catch (error) {
5679
+ rethrowHTTPTransportError(error, classifyTransportErrors);
5680
+ }
5681
+ return JSON.parse(data);
5682
+ }
5573
5683
  async function checkResponse(resp) {
5574
5684
  if (resp.ok) {
5575
5685
  return resp;
5576
- } else {
5686
+ }
5687
+ let data;
5688
+ try {
5689
+ data = await resp.text();
5690
+ } catch (error) {
5577
5691
  throw new FailedHTTPResponse(
5578
5692
  resp.status,
5579
5693
  resp.statusText,
5580
- await resp.text()
5694
+ "Unable to read response body",
5695
+ error
5581
5696
  );
5582
5697
  }
5698
+ throw new FailedHTTPResponse(resp.status, resp.statusText, data);
5583
5699
  }
5584
5700
  var HTTPConnection = class _HTTPConnection {
5585
- base_url;
5586
- token;
5587
- headers;
5588
- fetch;
5589
- constructor(base_url, fetch2) {
5701
+ constructor(base_url, fetch2, classifyTransportErrors = false) {
5702
+ this.classifyTransportErrors = classifyTransportErrors;
5590
5703
  this.base_url = base_url;
5591
5704
  this.token = null;
5592
5705
  this.headers = {};
5593
5706
  this._reset();
5594
5707
  this.fetch = fetch2;
5595
5708
  }
5709
+ classifyTransportErrors;
5710
+ base_url;
5711
+ token;
5712
+ headers;
5713
+ fetch;
5596
5714
  setFetch(fetch2) {
5597
5715
  this.fetch = fetch2;
5598
5716
  }
@@ -5632,9 +5750,9 @@ var HTTPConnection = class _HTTPConnection {
5632
5750
  ).toString();
5633
5751
  const this_fetch = this.fetch;
5634
5752
  const this_headers = this.headers;
5635
- return await checkResponse(
5636
- // Using toString() here makes it work with isomorphic fetch
5637
- await this_fetch(url.toString(), {
5753
+ let response;
5754
+ try {
5755
+ response = await this_fetch(url.toString(), {
5638
5756
  headers: {
5639
5757
  Accept: "application/json",
5640
5758
  ...this_headers,
@@ -5642,8 +5760,14 @@ var HTTPConnection = class _HTTPConnection {
5642
5760
  },
5643
5761
  keepalive: true,
5644
5762
  ...rest
5645
- })
5646
- );
5763
+ });
5764
+ } catch (error) {
5765
+ if (config?.signal?.aborted) {
5766
+ throw getAbortReason(config.signal);
5767
+ }
5768
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
5769
+ }
5770
+ return await checkResponse(response);
5647
5771
  }
5648
5772
  async post(path3, params, config, retries = 0) {
5649
5773
  const { headers, ...rest } = config || {};
@@ -5653,8 +5777,9 @@ var HTTPConnection = class _HTTPConnection {
5653
5777
  const tries = retries + 1;
5654
5778
  for (let i = 0; i < tries; i++) {
5655
5779
  try {
5656
- return await checkResponse(
5657
- await this_fetch(_urljoin(this_base_url, path3), {
5780
+ let response;
5781
+ try {
5782
+ response = await this_fetch(_urljoin(this_base_url, path3), {
5658
5783
  method: "POST",
5659
5784
  headers: {
5660
5785
  Accept: "application/json",
@@ -5665,8 +5790,14 @@ var HTTPConnection = class _HTTPConnection {
5665
5790
  body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
5666
5791
  keepalive: true,
5667
5792
  ...rest
5668
- })
5669
- );
5793
+ });
5794
+ } catch (error) {
5795
+ if (config?.signal?.aborted) {
5796
+ throw getAbortReason(config.signal);
5797
+ }
5798
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
5799
+ }
5800
+ return await checkResponse(response);
5670
5801
  } catch (error) {
5671
5802
  if (config?.signal?.aborted) {
5672
5803
  throw getAbortReason(config.signal);
@@ -5691,7 +5822,7 @@ var HTTPConnection = class _HTTPConnection {
5691
5822
  for (let i = 0; i < tries; i++) {
5692
5823
  try {
5693
5824
  const resp = await this.get(`${object_type}`, args);
5694
- return await resp.json();
5825
+ return await readJSONResponse(resp, this.classifyTransportErrors);
5695
5826
  } catch (e) {
5696
5827
  if (i < tries - 1) {
5697
5828
  debugLogger.debug(
@@ -5714,7 +5845,7 @@ var HTTPConnection = class _HTTPConnection {
5714
5845
  const resp = await this.post(`${object_type}`, args, {
5715
5846
  headers: { "Content-Type": "application/json" }
5716
5847
  });
5717
- return await resp.json();
5848
+ return await readJSONResponse(resp, this.classifyTransportErrors);
5718
5849
  }
5719
5850
  // Custom inspect for Node.js console.log
5720
5851
  [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
@@ -7762,6 +7893,7 @@ function initDataset(projectOrOptions, optionalOptions) {
7762
7893
  const {
7763
7894
  project,
7764
7895
  dataset,
7896
+ datasetId,
7765
7897
  description,
7766
7898
  version,
7767
7899
  snapshotName,
@@ -7777,6 +7909,11 @@ function initDataset(projectOrOptions, optionalOptions) {
7777
7909
  state: stateArg,
7778
7910
  _internal_btql
7779
7911
  } = options;
7912
+ if (datasetId !== void 0 && (description !== void 0 || metadata !== void 0)) {
7913
+ throw new Error(
7914
+ "Cannot specify description or metadata when datasetId is provided"
7915
+ );
7916
+ }
7780
7917
  const selection = normalizeDatasetSelection({
7781
7918
  version,
7782
7919
  environment,
@@ -7797,6 +7934,35 @@ function initDataset(projectOrOptions, optionalOptions) {
7797
7934
  fetch: fetch2,
7798
7935
  forceLogin
7799
7936
  });
7937
+ if (datasetId !== void 0) {
7938
+ const objectInfo = datasetObjectInfoSchema.array().parse(
7939
+ await state.appConn().post_json("api/self/get_object_info", {
7940
+ object_type: "dataset",
7941
+ object_ids: [datasetId]
7942
+ })
7943
+ );
7944
+ if (objectInfo.length === 0) {
7945
+ throw new Error(`Dataset with ID ${datasetId} not found`);
7946
+ }
7947
+ if (objectInfo.length !== 1) {
7948
+ throw new Error(
7949
+ `Expected exactly one dataset with ID ${datasetId}, but found ${objectInfo.length}`
7950
+ );
7951
+ }
7952
+ const datasetInfo = objectInfo[0];
7953
+ return {
7954
+ project: {
7955
+ id: datasetInfo.parent_cols.project.id,
7956
+ name: datasetInfo.parent_cols.project.name,
7957
+ fullInfo: datasetInfo.parent_cols.project
7958
+ },
7959
+ dataset: {
7960
+ id: datasetInfo.object_id,
7961
+ name: datasetInfo.object_name,
7962
+ fullInfo: datasetInfo
7963
+ }
7964
+ };
7965
+ }
7800
7966
  const args = {
7801
7967
  org_id: state.orgId,
7802
7968
  project_name: project,
@@ -7950,6 +8116,24 @@ function initLogger(options = {}) {
7950
8116
  }
7951
8117
  return ret;
7952
8118
  }
8119
+ async function runCredentialScopedLoaderRequest(state, loginOptions, request) {
8120
+ const resolvedLoginOptions = await state._internalResolveLoaderLoginOptions(loginOptions);
8121
+ let cacheViews = state._internalGetLoaderCacheViews(resolvedLoginOptions);
8122
+ try {
8123
+ const requestState = await state._internalGetLoaderState(resolvedLoginOptions);
8124
+ cacheViews = state._internalGetLoaderCacheViews(
8125
+ resolvedLoginOptions,
8126
+ requestState
8127
+ );
8128
+ return {
8129
+ ok: true,
8130
+ response: await request(requestState),
8131
+ ...cacheViews
8132
+ };
8133
+ } catch (error) {
8134
+ return { ok: false, error, ...cacheViews };
8135
+ }
8136
+ }
7953
8137
  async function loadPrompt({
7954
8138
  projectName,
7955
8139
  projectId,
@@ -7974,43 +8158,47 @@ async function loadPrompt({
7974
8158
  throw new Error("Must specify slug");
7975
8159
  }
7976
8160
  const state = stateArg ?? _globalState;
7977
- let response;
7978
- try {
7979
- await state.login({
7980
- orgName,
7981
- apiKey,
7982
- appUrl,
7983
- fetch: fetch2,
7984
- forceLogin
7985
- });
7986
- if (id) {
7987
- response = await state.apiConn().get_json(`v1/prompt/${id}`, versionOrEnvironment);
7988
- if (response) {
7989
- response = { objects: [response] };
8161
+ const result = await runCredentialScopedLoaderRequest(
8162
+ state,
8163
+ { orgName, apiKey, appUrl, fetch: fetch2, forceLogin },
8164
+ async (requestState) => {
8165
+ let response2;
8166
+ if (id) {
8167
+ response2 = await requestState.apiConn().get_json(`v1/prompt/${id}`, versionOrEnvironment);
8168
+ if (response2) {
8169
+ response2 = { objects: [response2] };
8170
+ }
8171
+ } else {
8172
+ response2 = await requestState.apiConn().get_json("v1/prompt", {
8173
+ project_name: projectName,
8174
+ project_id: projectId,
8175
+ slug,
8176
+ ...versionOrEnvironment
8177
+ });
7990
8178
  }
7991
- } else {
7992
- response = await state.apiConn().get_json("v1/prompt", {
7993
- project_name: projectName,
7994
- project_id: projectId,
7995
- slug,
7996
- ...versionOrEnvironment
7997
- });
8179
+ return response2;
8180
+ }
8181
+ );
8182
+ const { promptCache } = result;
8183
+ if (!result.ok) {
8184
+ const e = result.error;
8185
+ if (!isLoaderCacheFallbackError(e)) {
8186
+ throw e;
7998
8187
  }
7999
- } catch (e) {
8000
8188
  if (version || environment) {
8001
8189
  throw new Error(`Prompt not found with specified parameters: ${e}`);
8002
8190
  }
8003
8191
  debugLogger.forState(state).warn("Failed to load prompt, attempting to fall back to cache:", e);
8004
8192
  let prompt2;
8005
8193
  if (id) {
8006
- prompt2 = await state.promptCache.get({ id });
8194
+ prompt2 = await promptCache.get({ id });
8007
8195
  if (!prompt2) {
8008
8196
  throw new Error(
8009
8197
  `Prompt with id ${id} not found (not found on server or in local cache): ${e}`
8010
8198
  );
8011
8199
  }
8012
8200
  } else {
8013
- prompt2 = await state.promptCache.get({
8201
+ prompt2 = await promptCache.get({
8014
8202
  slug,
8015
8203
  projectId,
8016
8204
  projectName,
@@ -8026,6 +8214,7 @@ async function loadPrompt({
8026
8214
  }
8027
8215
  return prompt2;
8028
8216
  }
8217
+ const { response } = result;
8029
8218
  if (!("objects" in response) || response.objects.length === 0) {
8030
8219
  if (id) {
8031
8220
  throw new Error(`Prompt with id ${id} not found.`);
@@ -8049,9 +8238,9 @@ async function loadPrompt({
8049
8238
  const prompt = new Prompt2(metadata, defaults || {}, noTrace);
8050
8239
  try {
8051
8240
  if (id) {
8052
- await state.promptCache.set({ id }, prompt);
8241
+ await promptCache.set({ id }, prompt);
8053
8242
  } else if (slug) {
8054
- await state.promptCache.set(
8243
+ await promptCache.set(
8055
8244
  { slug, projectId, projectName, version: version ?? "latest" },
8056
8245
  prompt
8057
8246
  );
@@ -8083,46 +8272,50 @@ async function loadParameters({
8083
8272
  throw new Error("Must specify slug");
8084
8273
  }
8085
8274
  const state = stateArg ?? _globalState;
8086
- let response;
8087
- try {
8088
- await state.login({
8089
- orgName,
8090
- apiKey,
8091
- appUrl,
8092
- fetch: fetch2,
8093
- forceLogin
8094
- });
8095
- if (id) {
8096
- response = await state.apiConn().get_json(`v1/function/${id}`, {
8097
- ...versionOrEnvironment
8098
- });
8099
- if (response) {
8100
- response = { objects: [response] };
8275
+ const result = await runCredentialScopedLoaderRequest(
8276
+ state,
8277
+ { orgName, apiKey, appUrl, fetch: fetch2, forceLogin },
8278
+ async (requestState) => {
8279
+ let response2;
8280
+ if (id) {
8281
+ response2 = await requestState.apiConn().get_json(`v1/function/${id}`, {
8282
+ ...versionOrEnvironment
8283
+ });
8284
+ if (response2) {
8285
+ response2 = { objects: [response2] };
8286
+ }
8287
+ } else {
8288
+ response2 = await requestState.apiConn().get_json("v1/function", {
8289
+ project_name: projectName,
8290
+ project_id: projectId,
8291
+ slug,
8292
+ function_type: "parameters",
8293
+ ...versionOrEnvironment
8294
+ });
8101
8295
  }
8102
- } else {
8103
- response = await state.apiConn().get_json("v1/function", {
8104
- project_name: projectName,
8105
- project_id: projectId,
8106
- slug,
8107
- function_type: "parameters",
8108
- ...versionOrEnvironment
8109
- });
8296
+ return response2;
8297
+ }
8298
+ );
8299
+ const { parametersCache } = result;
8300
+ if (!result.ok) {
8301
+ const e = result.error;
8302
+ if (!isLoaderCacheFallbackError(e)) {
8303
+ throw e;
8110
8304
  }
8111
- } catch (e) {
8112
8305
  if (version || environment) {
8113
8306
  throw new Error(`Parameters not found with specified parameters: ${e}`);
8114
8307
  }
8115
8308
  debugLogger.forState(state).warn("Failed to load parameters, attempting to fall back to cache:", e);
8116
8309
  let parameters2;
8117
8310
  if (id) {
8118
- parameters2 = await state.parametersCache.get({ id });
8311
+ parameters2 = await parametersCache.get({ id });
8119
8312
  if (!parameters2) {
8120
8313
  throw new Error(
8121
8314
  `Parameters with id ${id} not found (not found on server or in local cache): ${e}`
8122
8315
  );
8123
8316
  }
8124
8317
  } else {
8125
- parameters2 = await state.parametersCache.get({
8318
+ parameters2 = await parametersCache.get({
8126
8319
  slug,
8127
8320
  projectId,
8128
8321
  projectName,
@@ -8138,6 +8331,7 @@ async function loadParameters({
8138
8331
  }
8139
8332
  return parameters2;
8140
8333
  }
8334
+ const { response } = result;
8141
8335
  if (!("objects" in response) || response.objects.length === 0) {
8142
8336
  if (id) {
8143
8337
  throw new Error(`Parameters with id ${id} not found.`);
@@ -8161,9 +8355,9 @@ async function loadParameters({
8161
8355
  const parameters = new RemoteEvalParameters(metadata);
8162
8356
  try {
8163
8357
  if (id) {
8164
- await state.parametersCache.set({ id }, parameters);
8358
+ await parametersCache.set({ id }, parameters);
8165
8359
  } else if (slug) {
8166
- await state.parametersCache.set(
8360
+ await parametersCache.set(
8167
8361
  { slug, projectId, projectName, version: version ?? "latest" },
8168
8362
  parameters
8169
8363
  );
@@ -8204,6 +8398,52 @@ async function login(options = {}) {
8204
8398
  await state.login(options);
8205
8399
  return state;
8206
8400
  }
8401
+ async function loginToLoaderRequestState({
8402
+ appUrl,
8403
+ apiKey,
8404
+ orgName,
8405
+ fetch: fetch2
8406
+ }) {
8407
+ let orgId;
8408
+ let apiUrl;
8409
+ if (apiKey === TEST_API_KEY) {
8410
+ orgId = "test-org-id";
8411
+ apiUrl = "https://braintrust.dev/fake-api-url";
8412
+ } else {
8413
+ let loginResponse;
8414
+ try {
8415
+ loginResponse = await fetch2(_urljoin(appUrl, `/api/apikey/login`), {
8416
+ method: "POST",
8417
+ headers: {
8418
+ "Content-Type": "application/json",
8419
+ Authorization: `Bearer ${apiKey}`
8420
+ }
8421
+ });
8422
+ } catch (error) {
8423
+ throw new HTTPTransportError(error);
8424
+ }
8425
+ const info = await readJSONResponse(
8426
+ await checkResponse(loginResponse),
8427
+ true
8428
+ );
8429
+ const org = selectLoginOrg(info.org_info, orgName);
8430
+ orgId = org.id;
8431
+ apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
8432
+ if (!apiUrl) {
8433
+ throw new Error(
8434
+ 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."
8435
+ );
8436
+ }
8437
+ }
8438
+ const apiConnection = new HTTPConnection(apiUrl, fetch2, true);
8439
+ apiConnection.set_token(apiKey);
8440
+ apiConnection.make_long_lived();
8441
+ return {
8442
+ appUrl,
8443
+ orgId,
8444
+ apiConn: () => apiConnection
8445
+ };
8446
+ }
8207
8447
  async function loginToState(options = {}) {
8208
8448
  const {
8209
8449
  appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
@@ -8235,16 +8475,18 @@ async function loginToState(options = {}) {
8235
8475
  _saveOrgInfo(state, testOrgInfo, testOrgInfo[0].name);
8236
8476
  return state;
8237
8477
  } else {
8238
- const resp = await checkResponse(
8239
- await fetch2(_urljoin(state.appUrl, `/api/apikey/login`), {
8478
+ const loginResponse = await fetch2(
8479
+ _urljoin(state.appUrl, `/api/apikey/login`),
8480
+ {
8240
8481
  method: "POST",
8241
8482
  headers: {
8242
8483
  "Content-Type": "application/json",
8243
8484
  Authorization: `Bearer ${apiKey}`
8244
8485
  }
8245
- })
8486
+ }
8246
8487
  );
8247
- const info = await resp.json();
8488
+ const resp = await checkResponse(loginResponse);
8489
+ const info = await readJSONResponse(resp);
8248
8490
  _saveOrgInfo(state, info.org_info, orgName);
8249
8491
  if (!state.apiUrl) {
8250
8492
  if (orgName) {
@@ -8747,11 +8989,11 @@ function wrapTraced(fn, args) {
8747
8989
  }
8748
8990
  if (args?.asyncFlush) {
8749
8991
  return ((...fnArgs) => traced((span) => {
8750
- if (!hasExplicitInput) {
8992
+ if (!args?.noTraceIO && !hasExplicitInput) {
8751
8993
  span.log({ input: fnArgs });
8752
8994
  }
8753
8995
  const output = fn(...fnArgs);
8754
- if (!hasExplicitOutput) {
8996
+ if (!args?.noTraceIO && !hasExplicitOutput) {
8755
8997
  if (output instanceof Promise) {
8756
8998
  return (async () => {
8757
8999
  const result = await output;
@@ -8766,12 +9008,12 @@ function wrapTraced(fn, args) {
8766
9008
  }, spanArgs));
8767
9009
  } else {
8768
9010
  return ((...fnArgs) => traced(async (span) => {
8769
- if (!hasExplicitInput) {
9011
+ if (!args?.noTraceIO && !hasExplicitInput) {
8770
9012
  span.log({ input: fnArgs });
8771
9013
  }
8772
9014
  const outputResult = fn(...fnArgs);
8773
9015
  const output = await outputResult;
8774
- if (!hasExplicitOutput) {
9016
+ if (!args?.noTraceIO && !hasExplicitOutput) {
8775
9017
  span.log({ output });
8776
9018
  }
8777
9019
  return output;
@@ -8897,27 +9139,28 @@ async function* asyncGeneratorWithCurrent(span, gen, state = void 0) {
8897
9139
  function withParent(parent, callback, state = void 0) {
8898
9140
  return (state ?? _globalState).currentParent.run(parent, () => callback());
8899
9141
  }
8900
- function _saveOrgInfo(state, org_info, org_name) {
8901
- if (org_info.length === 0) {
9142
+ function _saveOrgInfo(state, orgInfo, orgName) {
9143
+ const org = selectLoginOrg(orgInfo, orgName);
9144
+ state.orgId = org.id;
9145
+ state.orgName = org.name;
9146
+ state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
9147
+ state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
9148
+ state.gitMetadataSettings = org.git_metadata || void 0;
9149
+ }
9150
+ function selectLoginOrg(orgInfo, orgName) {
9151
+ if (orgInfo.length === 0) {
8902
9152
  throw new LoginInvalidOrgError(
8903
9153
  "This user is not part of any organizations."
8904
9154
  );
8905
9155
  }
8906
- for (const org of org_info) {
8907
- if (org_name === void 0 || org.name === org_name) {
8908
- state.orgId = org.id;
8909
- state.orgName = org.name;
8910
- state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
8911
- state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
8912
- state.gitMetadataSettings = org.git_metadata || void 0;
8913
- break;
9156
+ for (const org of orgInfo) {
9157
+ if (orgName === void 0 || org.name === orgName) {
9158
+ return org;
8914
9159
  }
8915
9160
  }
8916
- if (state.orgId === void 0) {
8917
- throw new LoginInvalidOrgError(
8918
- `Organization ${org_name} not found. Must be one of ${org_info.map((x) => x.name).join(", ")}`
8919
- );
8920
- }
9161
+ throw new LoginInvalidOrgError(
9162
+ `Organization ${orgName} not found. Must be one of ${orgInfo.map((org) => org.name).join(", ")}`
9163
+ );
8921
9164
  }
8922
9165
  function validateTags(tags) {
8923
9166
  const seen = /* @__PURE__ */ new Set();
@@ -10823,6 +11066,14 @@ var Prompt2 = class _Prompt {
10823
11066
  static isPrompt(data) {
10824
11067
  return typeof data === "object" && data !== null && "__braintrust_prompt_marker" in data;
10825
11068
  }
11069
+ /** @internal */
11070
+ _internalSerializeForCache() {
11071
+ return {
11072
+ metadata: this.metadata,
11073
+ defaults: this.defaults,
11074
+ noTrace: this.noTrace
11075
+ };
11076
+ }
10826
11077
  static fromPromptData(name, promptData) {
10827
11078
  return new _Prompt(
10828
11079
  {
@@ -10863,6 +11114,10 @@ var RemoteEvalParameters = class {
10863
11114
  get data() {
10864
11115
  return this.metadata.function_data.data ?? {};
10865
11116
  }
11117
+ /** @internal */
11118
+ _internalSerializeForCache() {
11119
+ return { metadata: this.metadata };
11120
+ }
10866
11121
  validate(data) {
10867
11122
  if (typeof data !== "object" || data === null) {
10868
11123
  return false;
@@ -11723,56 +11978,14 @@ function suppressionStore() {
11723
11978
  autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
11724
11979
  return autoInstrumentationSuppressionStore;
11725
11980
  }
11726
- function currentFrames() {
11727
- return suppressionStore().getStore()?.frames ?? [];
11728
- }
11729
11981
  function isAutoInstrumentationSuppressed() {
11730
- const frames = currentFrames();
11731
- return frames[frames.length - 1]?.mode === "suppress";
11982
+ return suppressionStore().getStore() === true;
11732
11983
  }
11733
11984
  function runWithAutoInstrumentationSuppressed(callback) {
11734
- const frame = {
11735
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
11736
- mode: "suppress"
11737
- };
11738
- return suppressionStore().run(
11739
- { frames: [...currentFrames(), frame] },
11740
- callback
11741
- );
11985
+ return suppressionStore().run(true, callback);
11742
11986
  }
11743
- function bindAutoInstrumentationSuppressionToStart(tracingChannel) {
11744
- const startChannel = tracingChannel.start;
11745
- if (!startChannel) {
11746
- return void 0;
11747
- }
11748
- const store = suppressionStore();
11749
- startChannel.bindStore(store, () => ({
11750
- frames: [
11751
- ...currentFrames(),
11752
- {
11753
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
11754
- mode: "suppress"
11755
- }
11756
- ]
11757
- }));
11758
- return () => {
11759
- startChannel.unbindStore(store);
11760
- };
11761
- }
11762
- function enterAutoInstrumentationAllowed() {
11763
- const frame = {
11764
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
11765
- mode: "allow"
11766
- };
11767
- suppressionStore().enterWith({
11768
- frames: [...currentFrames(), frame]
11769
- });
11770
- return () => {
11771
- const frames = currentFrames().filter(
11772
- (candidate) => candidate.id !== frame.id
11773
- );
11774
- suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
11775
- };
11987
+ function runWithAutoInstrumentationAllowed(callback) {
11988
+ return suppressionStore().run(void 0, callback);
11776
11989
  }
11777
11990
 
11778
11991
  // src/instrumentation/core/channel-tracing.ts
@@ -13025,7 +13238,7 @@ var AISDKPlugin = class extends BasePlugin {
13025
13238
  }
13026
13239
  subscribeToAISDK() {
13027
13240
  const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
13028
- this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
13241
+ this.unsubscribers.push(interceptAISDKV7TelemetryDispatcher());
13029
13242
  this.unsubscribers.push(subscribeToHarnessAgentCreateSession());
13030
13243
  this.unsubscribers.push(
13031
13244
  subscribeToHarnessContinuation(
@@ -13053,6 +13266,18 @@ var AISDKPlugin = class extends BasePlugin {
13053
13266
  aggregateChunks: aggregateAISDKChunks
13054
13267
  })
13055
13268
  );
13269
+ this.unsubscribers.push(
13270
+ traceAsyncChannel(aiSDKChannels.generateImage, {
13271
+ name: "generateImage",
13272
+ type: "llm" /* LLM */,
13273
+ extractInput: ([params], event) => prepareAISDKGenerateImageInput(params, event.self),
13274
+ extractOutput: (result, endEvent) => processAISDKGenerateImageOutput(
13275
+ result,
13276
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
13277
+ ),
13278
+ extractMetrics: (result) => extractTokenMetrics(result)
13279
+ })
13280
+ );
13056
13281
  this.unsubscribers.push(
13057
13282
  traceStreamingChannel(aiSDKChannels.streamText, {
13058
13283
  name: "streamText",
@@ -13542,26 +13767,29 @@ function subscribeToHarnessContinuation(continuationChannel, defaultDenyOutputPa
13542
13767
  channel.unsubscribe(handlers);
13543
13768
  };
13544
13769
  }
13545
- function subscribeToAISDKV7TelemetryDispatcher() {
13546
- const channel = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
13770
+ function interceptAISDKV7TelemetryDispatcher() {
13547
13771
  const telemetry = braintrustAISDKTelemetry();
13548
- const handlers = {
13549
- end: (event) => {
13550
- const telemetryOptions = event.arguments?.[0]?.telemetry;
13551
- if (telemetryOptions?.isEnabled === false) {
13552
- return;
13772
+ return aiSDKChannels.v7CreateTelemetryDispatcher.intercept(
13773
+ (target, thisArg, args) => {
13774
+ const dispatcher = Reflect.apply(target, thisArg, args);
13775
+ const telemetryOptions = args[0]?.telemetry;
13776
+ if (telemetryOptions?.isEnabled !== false) {
13777
+ try {
13778
+ patchAISDKV7TelemetryDispatcher(
13779
+ dispatcher,
13780
+ telemetry,
13781
+ telemetryOptions
13782
+ );
13783
+ } catch (error) {
13784
+ debugLogger.error(
13785
+ "Error instrumenting AI SDK v7 telemetry dispatcher:",
13786
+ error
13787
+ );
13788
+ }
13553
13789
  }
13554
- patchAISDKV7TelemetryDispatcher(
13555
- event.result,
13556
- telemetry,
13557
- telemetryOptions
13558
- );
13790
+ return dispatcher;
13559
13791
  }
13560
- };
13561
- channel.subscribe(handlers);
13562
- return () => {
13563
- channel.unsubscribe(handlers);
13564
- };
13792
+ );
13565
13793
  }
13566
13794
  function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
13567
13795
  if (!isObject(dispatcher)) {
@@ -13886,16 +14114,10 @@ var convertImageToAttachment = (image, explicitMimeType) => {
13886
14114
  }
13887
14115
  }
13888
14116
  if (explicitMimeType) {
13889
- if (image instanceof Uint8Array) {
13890
- return new Attachment({
13891
- data: new Blob([image], { type: explicitMimeType }),
13892
- filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
13893
- contentType: explicitMimeType
13894
- });
13895
- }
13896
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
14117
+ const blob = convertDataToBlob(image, explicitMimeType);
14118
+ if (blob) {
13897
14119
  return new Attachment({
13898
- data: new Blob([image], { type: explicitMimeType }),
14120
+ data: blob,
13899
14121
  filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
13900
14122
  contentType: explicitMimeType
13901
14123
  });
@@ -13949,6 +14171,25 @@ var convertDataToAttachment = (data, mimeType, filename) => {
13949
14171
  function processAISDKCallInput(params) {
13950
14172
  return processInputAttachmentsSync(params);
13951
14173
  }
14174
+ function processAISDKGenerateImageInput(params) {
14175
+ const prompt = params.prompt;
14176
+ if (!isObject(prompt) || Array.isArray(prompt)) {
14177
+ return processAISDKCallInput(params);
14178
+ }
14179
+ const processedPrompt = { ...prompt };
14180
+ if (Array.isArray(prompt.images)) {
14181
+ processedPrompt.images = prompt.images.map(
14182
+ (image) => convertImageToAttachment(image, "image/png") ?? image
14183
+ );
14184
+ }
14185
+ if (prompt.mask !== void 0) {
14186
+ processedPrompt.mask = convertImageToAttachment(prompt.mask, "image/png") ?? prompt.mask;
14187
+ }
14188
+ return processAISDKCallInput({
14189
+ ...params,
14190
+ prompt: processedPrompt
14191
+ });
14192
+ }
13952
14193
  function processAISDKWorkflowAgentCallInput(params) {
13953
14194
  const processed = processAISDKCallInput(params);
13954
14195
  return {
@@ -14087,6 +14328,12 @@ function prepareAISDKEmbedInput(params, self) {
14087
14328
  metadata: extractMetadataFromEmbedParams(params, self)
14088
14329
  };
14089
14330
  }
14331
+ function prepareAISDKGenerateImageInput(params, self) {
14332
+ return {
14333
+ input: processAISDKGenerateImageInput(params).input,
14334
+ metadata: extractMetadataFromCallParams(params, self)
14335
+ };
14336
+ }
14090
14337
  function prepareAISDKRerankInput(params, self) {
14091
14338
  const { documents, query } = params;
14092
14339
  return {
@@ -15462,6 +15709,57 @@ function processAISDKOutput(output, denyOutputPaths) {
15462
15709
  }
15463
15710
  return normalizeAISDKLoggedOutput(sanitized);
15464
15711
  }
15712
+ function processAISDKGenerateImageOutput(output, denyOutputPaths) {
15713
+ if (!output || typeof output !== "object") {
15714
+ return output;
15715
+ }
15716
+ const summarized = {};
15717
+ for (const field of [
15718
+ "usage",
15719
+ "warnings",
15720
+ "providerMetadata",
15721
+ "experimental_providerMetadata",
15722
+ "responses"
15723
+ ]) {
15724
+ const value = safeSerializableFieldRead(output, field);
15725
+ if (value !== void 0 && isSerializableOutputValue(value)) {
15726
+ summarized[field] = value;
15727
+ }
15728
+ }
15729
+ const images = safeSerializableFieldRead(output, "images");
15730
+ const image = safeSerializableFieldRead(output, "image");
15731
+ const generatedFiles = Array.isArray(images) && images.length > 0 ? images : image !== void 0 ? [image] : [];
15732
+ const loggedOutput = normalizeAISDKLoggedOutput(
15733
+ omit(summarized, denyOutputPaths)
15734
+ );
15735
+ if (generatedFiles.length > 0) {
15736
+ loggedOutput.images = generatedFiles.map(
15737
+ (file, index) => convertAISDKGeneratedFileToAttachment(file, index)
15738
+ );
15739
+ }
15740
+ return loggedOutput;
15741
+ }
15742
+ function convertAISDKGeneratedFileToAttachment(file, index) {
15743
+ if (!file || typeof file !== "object") {
15744
+ return file;
15745
+ }
15746
+ const generatedFile = file;
15747
+ const generatedMediaType = safeSerializableFieldRead(
15748
+ generatedFile,
15749
+ "mediaType"
15750
+ );
15751
+ const mediaType = typeof generatedMediaType === "string" ? generatedMediaType : "application/octet-stream";
15752
+ const data = safeSerializableFieldRead(generatedFile, "base64") ?? safeSerializableFieldRead(generatedFile, "uint8Array");
15753
+ const blob = convertDataToBlob(data, mediaType);
15754
+ if (blob) {
15755
+ return new Attachment({
15756
+ data: blob,
15757
+ filename: `generated_image_${index}.${getExtensionFromMediaType(mediaType)}`,
15758
+ contentType: mediaType
15759
+ });
15760
+ }
15761
+ return file;
15762
+ }
15465
15763
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
15466
15764
  if (!output || typeof output !== "object") {
15467
15765
  return output;
@@ -15950,7 +16248,6 @@ function omit(obj, paths, deletePaths = []) {
15950
16248
  function braintrustAISDKTelemetry() {
15951
16249
  const operations = /* @__PURE__ */ new Map();
15952
16250
  const operationKeysByCallId = /* @__PURE__ */ new Map();
15953
- const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
15954
16251
  const modelSpans = /* @__PURE__ */ new Map();
15955
16252
  const objectSpans = /* @__PURE__ */ new Map();
15956
16253
  const embedSpans = /* @__PURE__ */ new Map();
@@ -15993,9 +16290,6 @@ function braintrustAISDKTelemetry() {
15993
16290
  return;
15994
16291
  }
15995
16292
  operations.delete(operationKey);
15996
- if (workflowOperationKeyStore.getStore() === operationKey) {
15997
- workflowOperationKeyStore.enterWith(void 0);
15998
- }
15999
16293
  const keys = operationKeysByCallId.get(state.callId);
16000
16294
  if (!keys) {
16001
16295
  return;
@@ -16043,14 +16337,7 @@ function braintrustAISDKTelemetry() {
16043
16337
  return key;
16044
16338
  }
16045
16339
  }
16046
- const workflowOperationKey = workflowOperationKeyStore.getStore();
16047
- if (workflowOperationKey && keys.includes(workflowOperationKey)) {
16048
- return workflowOperationKey;
16049
- }
16050
- if (callId === "workflow-agent") {
16051
- return void 0;
16052
- }
16053
- return mode === "finish" ? keys[0] : keys[keys.length - 1];
16340
+ return callId === "workflow-agent" || mode === "active" ? keys[keys.length - 1] : keys[0];
16054
16341
  };
16055
16342
  const operationKeyFromEvent = (event, mode = "active") => {
16056
16343
  const explicit = explicitOperationKey(event);
@@ -16064,17 +16351,13 @@ function braintrustAISDKTelemetry() {
16064
16351
  if (operationKey) {
16065
16352
  return operationKey;
16066
16353
  }
16067
- const workflowOperationKey2 = workflowOperationKeyStore.getStore();
16068
- if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
16069
- return workflowOperationKey2;
16354
+ const workflowAgentKeys2 = operationKeysByCallId.get("workflow-agent");
16355
+ if (workflowAgentKeys2?.length) {
16356
+ return workflowAgentKeys2[workflowAgentKeys2.length - 1];
16070
16357
  }
16071
16358
  return callId === "workflow-agent" ? void 0 : callId;
16072
16359
  }
16073
16360
  }
16074
- const workflowOperationKey = workflowOperationKeyStore.getStore();
16075
- if (workflowOperationKey && operations.has(workflowOperationKey)) {
16076
- return workflowOperationKey;
16077
- }
16078
16361
  const wrapperSpan = currentWorkflowAgentWrapperSpan();
16079
16362
  if (wrapperSpan?.spanId) {
16080
16363
  for (const [operationKey, state] of operations) {
@@ -16084,8 +16367,8 @@ function braintrustAISDKTelemetry() {
16084
16367
  }
16085
16368
  }
16086
16369
  const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
16087
- if (workflowAgentKeys?.length === 1) {
16088
- return workflowAgentKeys[0];
16370
+ if (workflowAgentKeys?.length) {
16371
+ return workflowAgentKeys[workflowAgentKeys.length - 1];
16089
16372
  }
16090
16373
  if (operations.size === 1) {
16091
16374
  return operations.keys().next().value;
@@ -16288,9 +16571,6 @@ function braintrustAISDKTelemetry() {
16288
16571
  if (!ownsSpan) {
16289
16572
  return;
16290
16573
  }
16291
- if (workflowAgent) {
16292
- workflowOperationKeyStore.enterWith(operationKey);
16293
- }
16294
16574
  let metadata = metadataFromEvent(event);
16295
16575
  const logPayload = { metadata };
16296
16576
  const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
@@ -18284,12 +18564,14 @@ function getMetricsFromResponse(response) {
18284
18564
  continue;
18285
18565
  }
18286
18566
  const inputTokenDetails = usageMetadata.input_token_details;
18567
+ const outputTokenDetails = usageMetadata.output_token_details;
18287
18568
  return normalizeTokenMetrics({
18288
18569
  total_tokens: usageMetadata.total_tokens,
18289
18570
  prompt_tokens: usageMetadata.input_tokens,
18290
18571
  completion_tokens: usageMetadata.output_tokens,
18291
18572
  prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
18292
- prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
18573
+ prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
18574
+ completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
18293
18575
  });
18294
18576
  }
18295
18577
  const llmOutput = response.llmOutput || {};
@@ -18667,13 +18949,33 @@ function aggregateChatLogprobs(existing, incoming) {
18667
18949
  }
18668
18950
  return aggregated;
18669
18951
  }
18952
+ function createAggregatedChatChoice(index) {
18953
+ return {
18954
+ index,
18955
+ role: void 0,
18956
+ content: void 0,
18957
+ refusal: void 0,
18958
+ toolCallsByIndex: /* @__PURE__ */ new Map(),
18959
+ logprobs: void 0,
18960
+ finish_reason: void 0
18961
+ };
18962
+ }
18963
+ function toChatChoice(choice) {
18964
+ const toolCalls = Array.from(choice.toolCallsByIndex.entries()).sort(([left], [right]) => left - right).map(([, toolCall]) => toolCall);
18965
+ return {
18966
+ index: choice.index,
18967
+ message: {
18968
+ role: choice.role,
18969
+ content: choice.content,
18970
+ ...choice.refusal !== void 0 ? { refusal: choice.refusal } : {},
18971
+ tool_calls: toolCalls.length > 0 ? toolCalls : void 0
18972
+ },
18973
+ logprobs: choice.logprobs ?? null,
18974
+ finish_reason: choice.finish_reason
18975
+ };
18976
+ }
18670
18977
  function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
18671
- let role = void 0;
18672
- let content = void 0;
18673
- let refusal = void 0;
18674
- let tool_calls = void 0;
18675
- let logprobs = void 0;
18676
- let finish_reason = void 0;
18978
+ const choicesByIndex = /* @__PURE__ */ new Map();
18677
18979
  let metrics = {};
18678
18980
  for (const chunk of chunks) {
18679
18981
  if (chunk.usage) {
@@ -18682,62 +18984,75 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
18682
18984
  ...parseMetricsFromUsage(chunk.usage)
18683
18985
  };
18684
18986
  }
18685
- const choice = chunk.choices?.[0];
18686
- if (!choice) {
18687
- continue;
18688
- }
18689
- if (choice.finish_reason) {
18690
- finish_reason = choice.finish_reason;
18691
- }
18692
- logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
18693
- const delta = choice.delta;
18694
- if (!delta) {
18987
+ const choices = chunk.choices;
18988
+ if (!choices?.length) {
18695
18989
  continue;
18696
18990
  }
18697
- if (delta.finish_reason) {
18698
- finish_reason = delta.finish_reason;
18699
- }
18700
- if (!role && delta.role) {
18701
- role = delta.role;
18702
- }
18703
- if (delta.content) {
18704
- content = (content || "") + delta.content;
18705
- }
18706
- if (delta.refusal) {
18707
- refusal = (refusal || "") + delta.refusal;
18708
- }
18709
- if (delta.tool_calls) {
18710
- const toolDelta = delta.tool_calls[0];
18711
- if (!tool_calls || toolDelta.id && tool_calls[tool_calls.length - 1].id !== toolDelta.id) {
18712
- tool_calls = [
18713
- ...tool_calls || [],
18714
- {
18715
- id: toolDelta.id,
18716
- type: toolDelta.type,
18717
- function: toolDelta.function
18991
+ for (const choice of choices) {
18992
+ const choiceIndex = choice.index;
18993
+ let aggregatedChoice = choicesByIndex.get(choiceIndex);
18994
+ if (!aggregatedChoice) {
18995
+ aggregatedChoice = createAggregatedChatChoice(choiceIndex);
18996
+ choicesByIndex.set(choiceIndex, aggregatedChoice);
18997
+ }
18998
+ if (choice.finish_reason) {
18999
+ aggregatedChoice.finish_reason = choice.finish_reason;
19000
+ }
19001
+ aggregatedChoice.logprobs = aggregateChatLogprobs(
19002
+ aggregatedChoice.logprobs,
19003
+ choice.logprobs
19004
+ );
19005
+ const delta = choice.delta;
19006
+ if (!delta) {
19007
+ continue;
19008
+ }
19009
+ if (delta.finish_reason) {
19010
+ aggregatedChoice.finish_reason = delta.finish_reason;
19011
+ }
19012
+ if (!aggregatedChoice.role && delta.role) {
19013
+ aggregatedChoice.role = delta.role;
19014
+ }
19015
+ if (delta.content) {
19016
+ aggregatedChoice.content = (aggregatedChoice.content || "") + delta.content;
19017
+ }
19018
+ if (delta.refusal) {
19019
+ aggregatedChoice.refusal = (aggregatedChoice.refusal || "") + delta.refusal;
19020
+ }
19021
+ if (delta.tool_calls) {
19022
+ for (const toolDelta of delta.tool_calls) {
19023
+ let aggregatedToolCall = aggregatedChoice.toolCallsByIndex.get(
19024
+ toolDelta.index
19025
+ );
19026
+ if (!aggregatedToolCall) {
19027
+ aggregatedToolCall = {
19028
+ function: { arguments: "" }
19029
+ };
19030
+ aggregatedChoice.toolCallsByIndex.set(
19031
+ toolDelta.index,
19032
+ aggregatedToolCall
19033
+ );
18718
19034
  }
18719
- ];
18720
- } else {
18721
- tool_calls[tool_calls.length - 1].function.arguments += toolDelta.function.arguments;
19035
+ if (toolDelta.id !== void 0) {
19036
+ aggregatedToolCall.id = toolDelta.id;
19037
+ }
19038
+ if (toolDelta.type !== void 0) {
19039
+ aggregatedToolCall.type = toolDelta.type;
19040
+ }
19041
+ if (toolDelta.function?.name !== void 0) {
19042
+ aggregatedToolCall.function.name = toolDelta.function.name;
19043
+ }
19044
+ if (toolDelta.function?.arguments !== void 0) {
19045
+ aggregatedToolCall.function.arguments += toolDelta.function.arguments;
19046
+ }
19047
+ }
18722
19048
  }
18723
19049
  }
18724
19050
  }
18725
19051
  metrics = withCachedMetric(metrics, streamResult, endEvent);
19052
+ const output = Array.from(choicesByIndex.values()).sort((left, right) => left.index - right.index).map(toChatChoice);
18726
19053
  return {
18727
19054
  metrics,
18728
- output: [
18729
- {
18730
- index: 0,
18731
- message: {
18732
- role,
18733
- content,
18734
- ...refusal !== void 0 ? { refusal } : {},
18735
- tool_calls
18736
- },
18737
- logprobs: logprobs ?? null,
18738
- finish_reason
18739
- }
18740
- ]
19055
+ output: output.length > 0 ? output : [toChatChoice(createAggregatedChatChoice(0))]
18741
19056
  };
18742
19057
  }
18743
19058
  function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
@@ -20010,6 +20325,12 @@ function parseMetricsFromUsage2(usage) {
20010
20325
  }
20011
20326
  }
20012
20327
  }
20328
+ if (isObject(usage.output_tokens_details)) {
20329
+ const thinkingTokens = usage.output_tokens_details.thinking_tokens;
20330
+ if (typeof thinkingTokens === "number") {
20331
+ metrics.completion_reasoning_tokens = thinkingTokens;
20332
+ }
20333
+ }
20013
20334
  if (isObject(usage.server_tool_use)) {
20014
20335
  for (const [name, value] of Object.entries(usage.server_tool_use)) {
20015
20336
  if (typeof value === "number") {
@@ -20575,118 +20896,22 @@ function coalesceInput(messages, system) {
20575
20896
  var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
20576
20897
 
20577
20898
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
20578
- var LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED = /* @__PURE__ */ Symbol.for(
20579
- "braintrust.claude_agent_sdk.local_tool_context_async_iterator_patched"
20580
- );
20581
- function createLocalToolContextStore() {
20582
- const maybeIsoWithAsyncLocalStorage = isomorph_default;
20583
- if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
20584
- return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
20585
- }
20586
- let currentStore;
20587
- return {
20588
- enterWith(store) {
20589
- currentStore = store;
20590
- },
20591
- getStore() {
20592
- return currentStore;
20593
- },
20594
- run(store, callback) {
20595
- const previousStore = currentStore;
20596
- currentStore = store;
20597
- try {
20598
- return callback();
20599
- } finally {
20600
- currentStore = previousStore;
20601
- }
20602
- }
20603
- };
20604
- }
20605
- var localToolContextStore = createLocalToolContextStore();
20606
- var fallbackLocalToolParentResolver;
20607
- function createClaudeLocalToolContext() {
20608
- return {};
20609
- }
20610
- function runWithClaudeLocalToolContext(callback, context) {
20611
- return localToolContextStore.run(
20612
- context ?? createClaudeLocalToolContext(),
20613
- callback
20614
- );
20899
+ var localToolContextStore = isomorph_default.newAsyncLocalStorage();
20900
+ var localToolParentResolversByToolUseId = /* @__PURE__ */ new Map();
20901
+ function runWithClaudeLocalToolContext(callback, resolver) {
20902
+ return localToolContextStore.run(resolver, callback);
20615
20903
  }
20616
- function ensureClaudeLocalToolContext() {
20617
- const existing = localToolContextStore.getStore();
20618
- if (existing) {
20619
- return existing;
20620
- }
20621
- const created = {};
20622
- localToolContextStore.enterWith(created);
20623
- return created;
20624
- }
20625
- function setClaudeLocalToolParentResolver(resolver) {
20626
- fallbackLocalToolParentResolver = resolver;
20627
- const context = ensureClaudeLocalToolContext();
20628
- if (!context) {
20629
- return;
20630
- }
20631
- context.resolveLocalToolParent = resolver;
20632
- }
20633
- function getClaudeLocalToolParentResolver() {
20634
- return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
20904
+ function registerClaudeLocalToolParentResolver(toolUseId, resolver) {
20905
+ localToolParentResolversByToolUseId.set(toolUseId, resolver);
20635
20906
  }
20636
- function isAsyncIterable3(value) {
20637
- return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
20638
- }
20639
- function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
20640
- if (!isAsyncIterable3(result) || Object.isFrozen(result) || Object.isSealed(result)) {
20641
- return result;
20642
- }
20643
- const stream = result;
20644
- const originalAsyncIterator = stream[Symbol.asyncIterator];
20645
- if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
20646
- return result;
20907
+ function getClaudeLocalToolParentResolver(toolUseId) {
20908
+ const currentResolver = localToolContextStore.getStore();
20909
+ if (!toolUseId) {
20910
+ return currentResolver;
20647
20911
  }
20648
- const patchedAsyncIterator = function() {
20649
- return runWithClaudeLocalToolContext(() => {
20650
- const iterator = Reflect.apply(originalAsyncIterator, this, []);
20651
- if (!iterator || typeof iterator !== "object") {
20652
- return iterator;
20653
- }
20654
- const patchMethod = (methodName) => {
20655
- const originalMethod = Reflect.get(iterator, methodName);
20656
- if (typeof originalMethod !== "function") {
20657
- return;
20658
- }
20659
- Reflect.set(
20660
- iterator,
20661
- methodName,
20662
- (...args) => runWithClaudeLocalToolContext(
20663
- () => Reflect.apply(
20664
- originalMethod,
20665
- iterator,
20666
- args
20667
- ),
20668
- localToolContext
20669
- )
20670
- );
20671
- };
20672
- patchMethod("next");
20673
- patchMethod("return");
20674
- patchMethod("throw");
20675
- return iterator;
20676
- }, localToolContext);
20677
- };
20678
- Object.defineProperty(
20679
- patchedAsyncIterator,
20680
- LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
20681
- {
20682
- configurable: false,
20683
- enumerable: false,
20684
- value: true,
20685
- writable: false
20686
- }
20687
- );
20688
- Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
20689
- return result;
20912
+ const registeredResolver = localToolParentResolversByToolUseId.get(toolUseId);
20913
+ localToolParentResolversByToolUseId.delete(toolUseId);
20914
+ return currentResolver ?? registeredResolver;
20690
20915
  }
20691
20916
 
20692
20917
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
@@ -20712,7 +20937,7 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
20712
20937
  const metadata = getMetadata();
20713
20938
  const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
20714
20939
  const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
20715
- const localToolParentResolver = getClaudeLocalToolParentResolver();
20940
+ const localToolParentResolver = getClaudeLocalToolParentResolver(toolUseId);
20716
20941
  const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
20717
20942
  const runWithResolvedParent = async () => {
20718
20943
  const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
@@ -21239,6 +21464,7 @@ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToP
21239
21464
  }
21240
21465
  }
21241
21466
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
21467
+ registerClaudeLocalToolParentResolver(toolUseID, resolveParentSpan);
21242
21468
  return {};
21243
21469
  }
21244
21470
  const parsed = parseToolName(input.tool_name);
@@ -21949,7 +22175,7 @@ async function finalizeQuerySpan(state) {
21949
22175
  }
21950
22176
  var ClaudeAgentSDKPlugin = class extends BasePlugin {
21951
22177
  onEnable() {
21952
- this.subscribeToQuery();
22178
+ this.interceptQuery();
21953
22179
  }
21954
22180
  onDisable() {
21955
22181
  for (const unsubscribe of this.unsubscribers) {
@@ -21957,211 +22183,218 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
21957
22183
  }
21958
22184
  this.unsubscribers = [];
21959
22185
  }
21960
- subscribeToQuery() {
21961
- const channel = claudeAgentSDKChannels.query.tracingChannel();
21962
- const spans = /* @__PURE__ */ new WeakMap();
21963
- const handlers = {
21964
- start: (event) => {
21965
- const params = event.arguments[0] ?? {};
21966
- const originalPrompt = params.prompt;
21967
- const options = params.options ?? {};
21968
- const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
21969
- let promptStarted = false;
21970
- let capturedPromptMessages;
21971
- let resolvePromptDone;
21972
- const promptDone = new Promise((resolve) => {
21973
- resolvePromptDone = resolve;
21974
- });
21975
- if (promptIsAsyncIterable) {
21976
- capturedPromptMessages = [];
21977
- const promptStream = originalPrompt;
21978
- params.prompt = (async function* () {
21979
- promptStarted = true;
21980
- try {
21981
- for await (const message of promptStream) {
21982
- capturedPromptMessages.push(message);
21983
- yield message;
21984
- }
21985
- } finally {
21986
- resolvePromptDone?.();
22186
+ interceptQuery() {
22187
+ const startQuery = (params) => {
22188
+ const originalPrompt = params.prompt;
22189
+ const options = params.options ?? {};
22190
+ const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
22191
+ let promptStarted = false;
22192
+ let capturedPromptMessages;
22193
+ let resolvePromptDone;
22194
+ const promptDone = new Promise((resolve) => {
22195
+ resolvePromptDone = resolve;
22196
+ });
22197
+ if (promptIsAsyncIterable) {
22198
+ capturedPromptMessages = [];
22199
+ const promptStream = originalPrompt;
22200
+ params.prompt = (async function* () {
22201
+ promptStarted = true;
22202
+ try {
22203
+ for await (const message of promptStream) {
22204
+ capturedPromptMessages.push(message);
22205
+ yield message;
21987
22206
  }
21988
- })();
21989
- }
21990
- const span = startSpan(
21991
- withSpanInstrumentationName(
21992
- {
21993
- name: "Claude Agent",
21994
- spanAttributes: {
21995
- type: "task" /* TASK */
21996
- }
21997
- },
21998
- INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
21999
- )
22000
- );
22001
- const startTime = getCurrentUnixTimestamp();
22002
- try {
22003
- span.log({
22004
- input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
22005
- metadata: filterSerializableOptions(options)
22006
- });
22007
- } catch (error) {
22008
- console.error("Error extracting input for Claude Agent SDK:", error);
22009
- }
22010
- const activeToolSpans = /* @__PURE__ */ new Map();
22011
- const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
22012
- const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
22013
- const subAgentSpans = /* @__PURE__ */ new Map();
22014
- const endedSubAgentSpans = /* @__PURE__ */ new Set();
22015
- const toolUseToParent = /* @__PURE__ */ new Map();
22016
- const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
22017
- const latestRootLlmParentRef = {
22018
- value: void 0
22019
- };
22020
- const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
22021
- const taskIdToToolUseId = /* @__PURE__ */ new Map();
22022
- const promptMessagesByParentKey = /* @__PURE__ */ new Map();
22023
- const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
22024
- const localToolContext = createClaudeLocalToolContext();
22025
- const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
22026
- const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
22027
- const resolveToolUseParentSpan = async (toolUseID, context) => {
22028
- const trackedParentToolUseId = toolUseToParent.get(toolUseID);
22029
- const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
22030
- const parentKey = llmParentKey(parentToolUseId);
22031
- const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
22032
- const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
22033
- if (!activeLlmSpan && !latestLlmParent) {
22034
- await ensureActiveLlmSpanForParentToolUse(
22035
- span,
22036
- activeLlmSpansByParentToolUse,
22037
- subAgentDetailsByToolUseId,
22038
- activeToolSpans,
22039
- subAgentSpans,
22040
- parentToolUseId,
22041
- getCurrentUnixTimestamp()
22042
- );
22043
- }
22044
- if (parentToolUseId) {
22045
- const subAgentSpan = await ensureSubAgentSpan(
22046
- subAgentDetailsByToolUseId,
22047
- span,
22048
- activeToolSpans,
22049
- subAgentSpans,
22050
- parentToolUseId
22051
- );
22052
- return subAgentSpan.export();
22207
+ } finally {
22208
+ resolvePromptDone?.();
22053
22209
  }
22054
- return span.export();
22055
- };
22056
- localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
22057
- setClaudeLocalToolParentResolver(resolveToolUseParentSpan);
22058
- const optionsWithHooks = injectTracingHooks(
22059
- options,
22060
- resolveToolUseParentSpan,
22061
- taskIdToToolUseId,
22062
- toolUseToParent,
22063
- activeToolSpans,
22064
- localToolHookNames,
22065
- skipLocalToolHooks,
22066
- subAgentDetailsByToolUseId,
22067
- subAgentSpans,
22068
- endedSubAgentSpans
22069
- );
22070
- params.options = optionsWithHooks;
22071
- event.arguments[0] = params;
22072
- spans.set(event, {
22073
- activeLlmSpansByParentToolUse,
22074
- activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
22075
- activeToolSpans,
22076
- conversationHistoryByParentKey,
22077
- capturedPromptMessages,
22078
- currentMessageId: void 0,
22079
- currentMessageStartTime: startTime,
22080
- currentMessages: [],
22081
- endedSubAgentSpans,
22082
- finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
22083
- finalResults: [],
22084
- options: optionsWithHooks,
22085
- originalPrompt,
22086
- processing: Promise.resolve(),
22087
- promptDone,
22088
- promptMessagesByParentKey,
22089
- promptStarted: () => promptStarted,
22090
- promptSourcePriorityByParentKey,
22091
- span,
22092
- subAgentDetailsByToolUseId,
22093
- subAgentSpans,
22094
- taskIdToToolUseId,
22095
- latestLlmParentBySubAgentToolUse,
22096
- latestRootLlmParentRef,
22097
- toolUseToParent,
22098
- usageByMessageId: /* @__PURE__ */ new Map(),
22099
- localToolContext
22210
+ })();
22211
+ }
22212
+ const span = startSpan(
22213
+ withSpanInstrumentationName(
22214
+ {
22215
+ name: "Claude Agent",
22216
+ spanAttributes: {
22217
+ type: "task" /* TASK */
22218
+ }
22219
+ },
22220
+ INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
22221
+ )
22222
+ );
22223
+ const startTime = getCurrentUnixTimestamp();
22224
+ try {
22225
+ span.log({
22226
+ input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
22227
+ metadata: filterSerializableOptions(options)
22100
22228
  });
22101
- },
22102
- end: (event) => {
22103
- const state = spans.get(event);
22104
- if (!state) {
22105
- return;
22106
- }
22107
- const eventResult = bindClaudeLocalToolContextToAsyncIterable(
22108
- event.result,
22109
- state.localToolContext
22110
- );
22111
- if (eventResult === void 0) {
22112
- state.span.end();
22113
- spans.delete(event);
22114
- return;
22115
- }
22116
- if (isAsyncIterable(eventResult)) {
22117
- patchStreamIfNeeded(eventResult, {
22118
- onChunk: (message) => {
22119
- maybeTrackToolUseContext(state, message);
22120
- state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
22121
- console.error(
22122
- "Error processing Claude Agent SDK stream chunk:",
22123
- error
22124
- );
22125
- });
22126
- },
22127
- onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
22128
- spans.delete(event);
22129
- }),
22130
- onError: (error) => state.processing.then(() => {
22131
- state.span.log({
22132
- error: error.message
22133
- });
22134
- }).then(() => finalizeQuerySpan(state)).finally(() => {
22135
- spans.delete(event);
22136
- })
22137
- });
22138
- return;
22139
- }
22140
- try {
22141
- state.span.log({ output: eventResult });
22142
- } catch (error) {
22143
- console.error("Error extracting output for Claude Agent SDK:", error);
22144
- } finally {
22145
- state.span.end();
22146
- spans.delete(event);
22229
+ } catch (error) {
22230
+ console.error("Error extracting input for Claude Agent SDK:", error);
22231
+ }
22232
+ const activeToolSpans = /* @__PURE__ */ new Map();
22233
+ const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
22234
+ const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
22235
+ const subAgentSpans = /* @__PURE__ */ new Map();
22236
+ const endedSubAgentSpans = /* @__PURE__ */ new Set();
22237
+ const toolUseToParent = /* @__PURE__ */ new Map();
22238
+ const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
22239
+ const latestRootLlmParentRef = {
22240
+ value: void 0
22241
+ };
22242
+ const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
22243
+ const taskIdToToolUseId = /* @__PURE__ */ new Map();
22244
+ const promptMessagesByParentKey = /* @__PURE__ */ new Map();
22245
+ const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
22246
+ const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
22247
+ const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
22248
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
22249
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
22250
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
22251
+ const parentKey = llmParentKey(parentToolUseId);
22252
+ const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
22253
+ const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
22254
+ if (!activeLlmSpan && !latestLlmParent) {
22255
+ await ensureActiveLlmSpanForParentToolUse(
22256
+ span,
22257
+ activeLlmSpansByParentToolUse,
22258
+ subAgentDetailsByToolUseId,
22259
+ activeToolSpans,
22260
+ subAgentSpans,
22261
+ parentToolUseId,
22262
+ getCurrentUnixTimestamp()
22263
+ );
22147
22264
  }
22148
- },
22149
- error: (event) => {
22150
- const state = spans.get(event);
22151
- if (!state || !event.error) {
22152
- return;
22265
+ if (parentToolUseId) {
22266
+ const subAgentSpan = await ensureSubAgentSpan(
22267
+ subAgentDetailsByToolUseId,
22268
+ span,
22269
+ activeToolSpans,
22270
+ subAgentSpans,
22271
+ parentToolUseId
22272
+ );
22273
+ return subAgentSpan.export();
22153
22274
  }
22154
- state.span.log({
22155
- error: event.error.message
22275
+ return span.export();
22276
+ };
22277
+ const optionsWithHooks = injectTracingHooks(
22278
+ options,
22279
+ resolveToolUseParentSpan,
22280
+ taskIdToToolUseId,
22281
+ toolUseToParent,
22282
+ activeToolSpans,
22283
+ localToolHookNames,
22284
+ skipLocalToolHooks,
22285
+ subAgentDetailsByToolUseId,
22286
+ subAgentSpans,
22287
+ endedSubAgentSpans
22288
+ );
22289
+ params.options = optionsWithHooks;
22290
+ return {
22291
+ activeLlmSpansByParentToolUse,
22292
+ activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
22293
+ activeToolSpans,
22294
+ conversationHistoryByParentKey,
22295
+ capturedPromptMessages,
22296
+ currentMessageId: void 0,
22297
+ currentMessageStartTime: startTime,
22298
+ currentMessages: [],
22299
+ endedSubAgentSpans,
22300
+ finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
22301
+ finalResults: [],
22302
+ options: optionsWithHooks,
22303
+ originalPrompt,
22304
+ processing: Promise.resolve(),
22305
+ promptDone,
22306
+ promptMessagesByParentKey,
22307
+ promptStarted: () => promptStarted,
22308
+ promptSourcePriorityByParentKey,
22309
+ span,
22310
+ subAgentDetailsByToolUseId,
22311
+ subAgentSpans,
22312
+ taskIdToToolUseId,
22313
+ latestLlmParentBySubAgentToolUse,
22314
+ latestRootLlmParentRef,
22315
+ toolUseToParent,
22316
+ usageByMessageId: /* @__PURE__ */ new Map(),
22317
+ localToolParentResolver: resolveToolUseParentSpan
22318
+ };
22319
+ };
22320
+ const finishQuery = (state, result) => {
22321
+ if (isAsyncIterable(result)) {
22322
+ patchStreamIfNeeded(result, {
22323
+ aroundNext: (callback) => runWithClaudeLocalToolContext(
22324
+ callback,
22325
+ state.localToolParentResolver
22326
+ ),
22327
+ onChunk: (message) => {
22328
+ maybeTrackToolUseContext(state, message);
22329
+ state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
22330
+ console.error(
22331
+ "Error processing Claude Agent SDK stream chunk:",
22332
+ error
22333
+ );
22334
+ });
22335
+ },
22336
+ onComplete: () => state.processing.then(() => finalizeQuerySpan(state)),
22337
+ onError: (error) => state.processing.then(() => {
22338
+ state.span.log({ error: error.message });
22339
+ }).then(() => finalizeQuerySpan(state))
22156
22340
  });
22341
+ return;
22342
+ }
22343
+ try {
22344
+ state.span.log({ output: result });
22345
+ } catch (error) {
22346
+ console.error("Error extracting output for Claude Agent SDK:", error);
22347
+ } finally {
22157
22348
  state.span.end();
22158
- spans.delete(event);
22159
22349
  }
22160
22350
  };
22161
- channel.subscribe(handlers);
22162
- this.unsubscribers.push(() => {
22163
- channel.unsubscribe(handlers);
22164
- });
22351
+ this.unsubscribers.push(
22352
+ claudeAgentSDKChannels.query.intercept((target, thisArg, args) => {
22353
+ let state;
22354
+ try {
22355
+ args[0] ??= {};
22356
+ state = startQuery(args[0]);
22357
+ } catch (error) {
22358
+ debugLogger.error(
22359
+ "Error starting Claude Agent SDK instrumentation:",
22360
+ error
22361
+ );
22362
+ }
22363
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
22364
+ try {
22365
+ const result = state ? runWithClaudeLocalToolContext(
22366
+ invokeTarget,
22367
+ state.localToolParentResolver
22368
+ ) : invokeTarget();
22369
+ if (state) {
22370
+ try {
22371
+ finishQuery(state, result);
22372
+ } catch (error) {
22373
+ debugLogger.error(
22374
+ "Error finalizing Claude Agent SDK instrumentation:",
22375
+ error
22376
+ );
22377
+ }
22378
+ }
22379
+ return result;
22380
+ } catch (error) {
22381
+ if (state) {
22382
+ try {
22383
+ state.span.log({
22384
+ error: error instanceof Error ? error.message : String(error)
22385
+ });
22386
+ state.span.end();
22387
+ } catch (instrumentationError) {
22388
+ debugLogger.error(
22389
+ "Error handling Claude Agent SDK instrumentation failure:",
22390
+ instrumentationError
22391
+ );
22392
+ }
22393
+ }
22394
+ throw error;
22395
+ }
22396
+ })
22397
+ );
22165
22398
  }
22166
22399
  };
22167
22400
 
@@ -26103,7 +26336,7 @@ function patchOpenRouterCallModelResult(args) {
26103
26336
  span,
26104
26337
  () => originalMethod.apply(resultLike, args2)
26105
26338
  );
26106
- if (!isAsyncIterable4(stream)) {
26339
+ if (!isAsyncIterable3(stream)) {
26107
26340
  return stream;
26108
26341
  }
26109
26342
  return wrapAsyncIterableWithSpan({
@@ -26298,7 +26531,7 @@ function wrapAsyncIterableWithSpan(args) {
26298
26531
  }
26299
26532
  };
26300
26533
  }
26301
- function isAsyncIterable4(value) {
26534
+ function isAsyncIterable3(value) {
26302
26535
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
26303
26536
  }
26304
26537
  function normalizeError(error) {
@@ -27140,7 +27373,7 @@ function patchOpenRouterCallModelResult2(args) {
27140
27373
  span,
27141
27374
  () => originalMethod.apply(resultLike, args2)
27142
27375
  );
27143
- if (!isAsyncIterable5(stream)) {
27376
+ if (!isAsyncIterable4(stream)) {
27144
27377
  return stream;
27145
27378
  }
27146
27379
  return wrapAsyncIterableWithSpan2({
@@ -27335,7 +27568,7 @@ function wrapAsyncIterableWithSpan2(args) {
27335
27568
  }
27336
27569
  };
27337
27570
  }
27338
- function isAsyncIterable5(value) {
27571
+ function isAsyncIterable4(value) {
27339
27572
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
27340
27573
  }
27341
27574
  function normalizeError2(error) {
@@ -32081,6 +32314,9 @@ function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth
32081
32314
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
32082
32315
  var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
32083
32316
  var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
32317
+ var PI_TOOL_EXECUTE_WRAPPED = /* @__PURE__ */ Symbol.for(
32318
+ "braintrust.pi_coding_agent.tool_execute_wrapped"
32319
+ );
32084
32320
  var piPromptContextStore;
32085
32321
  var PiCodingAgentPlugin = class extends BasePlugin {
32086
32322
  activePromptStates = /* @__PURE__ */ new Set();
@@ -32161,6 +32397,7 @@ function startPiPromptRun(event, onFinalize) {
32161
32397
  return void 0;
32162
32398
  }
32163
32399
  installPiAgentInstrumentation(agent);
32400
+ wrapPiToolExecutors(agent.state?.tools);
32164
32401
  const metadata = {
32165
32402
  ...extractSessionMetadata(session),
32166
32403
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -32257,6 +32494,7 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
32257
32494
  if (!state || state.agent !== agent || state.finalized) {
32258
32495
  return invokeOriginal();
32259
32496
  }
32497
+ wrapPiToolExecutors(context.tools);
32260
32498
  const llmState = await startPiLlmSpan(state, model, context, options);
32261
32499
  try {
32262
32500
  const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
@@ -32267,6 +32505,33 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
32267
32505
  }
32268
32506
  };
32269
32507
  }
32508
+ function wrapPiToolExecutors(tools) {
32509
+ if (!tools) {
32510
+ return;
32511
+ }
32512
+ for (const tool of tools) {
32513
+ try {
32514
+ const execute = tool.execute;
32515
+ if (typeof execute !== "function" || execute[PI_TOOL_EXECUTE_WRAPPED]) {
32516
+ continue;
32517
+ }
32518
+ const wrappedExecute = function(...args) {
32519
+ return runWithAutoInstrumentationAllowed(
32520
+ () => Reflect.apply(execute, this, args)
32521
+ );
32522
+ };
32523
+ Object.defineProperty(wrappedExecute, PI_TOOL_EXECUTE_WRAPPED, {
32524
+ configurable: false,
32525
+ enumerable: false,
32526
+ value: true,
32527
+ writable: false
32528
+ });
32529
+ tool.execute = wrappedExecute;
32530
+ } catch (error) {
32531
+ logInstrumentationError4("Pi Coding Agent tool wrapping", error);
32532
+ }
32533
+ }
32534
+ }
32270
32535
  async function startPiLlmSpan(state, model, context, options) {
32271
32536
  const metadata = {
32272
32537
  ...extractModelMetadata2(model),
@@ -32438,35 +32703,26 @@ async function startPiToolSpan(state, event) {
32438
32703
  if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
32439
32704
  return;
32440
32705
  }
32441
- const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
32442
32706
  const metadata = {
32443
32707
  "gen_ai.tool.call.id": event.toolCallId,
32444
32708
  "gen_ai.tool.name": event.toolName,
32445
32709
  "pi_coding_agent.tool.name": event.toolName
32446
32710
  };
32447
- try {
32448
- const span = startSpan(
32449
- withSpanInstrumentationName(
32450
- {
32451
- event: {
32452
- input: event.args,
32453
- metadata
32454
- },
32455
- name: event.toolName || "tool",
32456
- parent: await state.span.export(),
32457
- spanAttributes: { type: "tool" /* TOOL */ }
32711
+ const span = startSpan(
32712
+ withSpanInstrumentationName(
32713
+ {
32714
+ event: {
32715
+ input: event.args,
32716
+ metadata
32458
32717
  },
32459
- INSTRUMENTATION_NAMES.PI_CODING_AGENT
32460
- )
32461
- );
32462
- state.activeToolSpans.set(event.toolCallId, {
32463
- restoreAutoInstrumentation,
32464
- span
32465
- });
32466
- } catch (error) {
32467
- restoreAutoInstrumentation();
32468
- throw error;
32469
- }
32718
+ name: event.toolName || "tool",
32719
+ parent: await state.span.export(),
32720
+ spanAttributes: { type: "tool" /* TOOL */ }
32721
+ },
32722
+ INSTRUMENTATION_NAMES.PI_CODING_AGENT
32723
+ )
32724
+ );
32725
+ state.activeToolSpans.set(event.toolCallId, { span });
32470
32726
  }
32471
32727
  function finishPiToolSpan(state, event) {
32472
32728
  const toolState = state.activeToolSpans.get(event.toolCallId);
@@ -32487,11 +32743,7 @@ function finishPiToolSpan(state, event) {
32487
32743
  output: event.result
32488
32744
  });
32489
32745
  } finally {
32490
- try {
32491
- toolState.span.end();
32492
- } finally {
32493
- toolState.restoreAutoInstrumentation?.();
32494
- }
32746
+ toolState.span.end();
32495
32747
  }
32496
32748
  }
32497
32749
  function finishPiPromptRun(state, error) {
@@ -32562,14 +32814,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
32562
32814
  }
32563
32815
  function finishOpenToolSpans(state, error) {
32564
32816
  for (const [, toolState] of state.activeToolSpans) {
32565
- try {
32566
- safeLog4(toolState.span, {
32567
- error: error ? toLoggedError(error) : "Pi tool did not complete"
32568
- });
32569
- toolState.span.end();
32570
- } finally {
32571
- toolState.restoreAutoInstrumentation?.();
32572
- }
32817
+ safeLog4(toolState.span, {
32818
+ error: error ? toLoggedError(error) : "Pi tool did not complete"
32819
+ });
32820
+ toolState.span.end();
32573
32821
  }
32574
32822
  state.activeToolSpans.clear();
32575
32823
  }
@@ -32868,12 +33116,12 @@ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
32868
33116
  var StrandsAgentSDKPlugin = class extends BasePlugin {
32869
33117
  activeChildParents = /* @__PURE__ */ new WeakMap();
32870
33118
  onEnable() {
32871
- this.subscribeToAgentStream();
32872
- this.subscribeToMultiAgentStream(
33119
+ this.interceptAgentStream();
33120
+ this.interceptMultiAgentStream(
32873
33121
  strandsAgentSDKChannels.graphStream,
32874
33122
  "Graph.stream"
32875
33123
  );
32876
- this.subscribeToMultiAgentStream(
33124
+ this.interceptMultiAgentStream(
32877
33125
  strandsAgentSDKChannels.swarmStream,
32878
33126
  "Swarm.stream"
32879
33127
  );
@@ -32884,122 +33132,92 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
32884
33132
  }
32885
33133
  this.unsubscribers = [];
32886
33134
  }
32887
- subscribeToAgentStream() {
32888
- const channel = strandsAgentSDKChannels.agentStream.tracingChannel();
32889
- const states = /* @__PURE__ */ new WeakMap();
32890
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel);
32891
- const handlers = {
32892
- start: (event) => {
32893
- const state = startAgentStream(event, this.activeChildParents);
32894
- if (state) {
32895
- states.set(event, state);
32896
- }
32897
- },
32898
- end: (event) => {
32899
- const state = states.get(event);
32900
- if (!state) {
32901
- return;
32902
- }
32903
- const result = event.result;
32904
- if (isAsyncIterable(result)) {
32905
- patchStreamIfNeeded(result, {
32906
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
32907
- onChunk: (chunk) => handleAgentStreamEvent(state, chunk),
32908
- onComplete: () => {
32909
- finalizeAgentStream(state);
32910
- states.delete(event);
32911
- },
32912
- onError: (error) => {
32913
- finalizeAgentStream(state, error);
32914
- states.delete(event);
32915
- }
32916
- });
32917
- return;
32918
- }
32919
- finalizeAgentStream(state, void 0, result);
32920
- states.delete(event);
32921
- },
32922
- error: (event) => {
32923
- const state = states.get(event);
32924
- if (!state || !event.error) {
32925
- return;
32926
- }
32927
- finalizeAgentStream(state, event.error);
32928
- states.delete(event);
32929
- }
32930
- };
32931
- channel.subscribe(handlers);
32932
- this.unsubscribers.push(() => {
32933
- unbindAutoInstrumentationSuppression?.();
32934
- channel.unsubscribe(handlers);
32935
- });
33135
+ interceptAgentStream() {
33136
+ this.unsubscribers.push(
33137
+ strandsAgentSDKChannels.agentStream.intercept(
33138
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
33139
+ finalize: finalizeAgentStream,
33140
+ handleChunk: handleAgentStreamEvent,
33141
+ invoke: () => Reflect.apply(target, thisArg, args),
33142
+ name: "Strands Agent SDK",
33143
+ start: () => startAgentStream(
33144
+ args[0],
33145
+ extractAgent(additional.agent, thisArg),
33146
+ this.activeChildParents
33147
+ )
33148
+ })
33149
+ )
33150
+ );
32936
33151
  }
32937
- subscribeToMultiAgentStream(channel, operation) {
32938
- const tracingChannel = channel.tracingChannel();
32939
- const states = /* @__PURE__ */ new WeakMap();
32940
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(tracingChannel);
32941
- const handlers = {
32942
- start: (event) => {
32943
- const state = startMultiAgentStream(
32944
- event,
32945
- operation,
32946
- this.activeChildParents
32947
- );
32948
- if (state) {
32949
- states.set(event, state);
32950
- }
32951
- },
32952
- end: (event) => {
32953
- const state = states.get(event);
32954
- if (!state) {
32955
- return;
32956
- }
32957
- const result = event.result;
32958
- if (isAsyncIterable(result)) {
32959
- patchStreamIfNeeded(result, {
32960
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
32961
- onChunk: (chunk) => handleMultiAgentStreamEvent(
32962
- state,
32963
- chunk,
32964
- this.activeChildParents
32965
- ),
32966
- onComplete: () => {
32967
- finalizeMultiAgentStream(state, this.activeChildParents);
32968
- states.delete(event);
32969
- },
32970
- onError: (error) => {
32971
- finalizeMultiAgentStream(state, this.activeChildParents, error);
32972
- states.delete(event);
32973
- }
32974
- });
32975
- return;
32976
- }
32977
- finalizeMultiAgentStream(
32978
- state,
32979
- this.activeChildParents,
32980
- void 0,
32981
- result
33152
+ interceptMultiAgentStream(channel, operation) {
33153
+ this.unsubscribers.push(
33154
+ channel.intercept(
33155
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
33156
+ finalize: (state, error, output) => finalizeMultiAgentStream(
33157
+ state,
33158
+ this.activeChildParents,
33159
+ error,
33160
+ output
33161
+ ),
33162
+ handleChunk: (state, chunk) => handleMultiAgentStreamEvent(state, chunk, this.activeChildParents),
33163
+ invoke: () => Reflect.apply(target, thisArg, args),
33164
+ name: "Strands multi-agent",
33165
+ start: () => startMultiAgentStream(
33166
+ args[0],
33167
+ extractOrchestrator(additional.orchestrator, thisArg),
33168
+ operation,
33169
+ this.activeChildParents
33170
+ )
33171
+ })
33172
+ )
33173
+ );
33174
+ }
33175
+ };
33176
+ function instrumentStrandsStreamInvocation(options) {
33177
+ let state;
33178
+ try {
33179
+ state = options.start();
33180
+ } catch (error) {
33181
+ debugLogger.error(`Error starting ${options.name} instrumentation:`, error);
33182
+ }
33183
+ let result;
33184
+ try {
33185
+ result = runWithAutoInstrumentationSuppressed(options.invoke);
33186
+ } catch (error) {
33187
+ if (state) {
33188
+ try {
33189
+ options.finalize(state, error);
33190
+ } catch (instrumentationError) {
33191
+ debugLogger.error(
33192
+ `Error handling ${options.name} instrumentation failure:`,
33193
+ instrumentationError
32982
33194
  );
32983
- states.delete(event);
32984
- },
32985
- error: (event) => {
32986
- const state = states.get(event);
32987
- if (!state || !event.error) {
32988
- return;
32989
- }
32990
- finalizeMultiAgentStream(state, this.activeChildParents, event.error);
32991
- states.delete(event);
32992
33195
  }
32993
- };
32994
- tracingChannel.subscribe(handlers);
32995
- this.unsubscribers.push(() => {
32996
- unbindAutoInstrumentationSuppression?.();
32997
- tracingChannel.unsubscribe(handlers);
32998
- });
33196
+ }
33197
+ throw error;
32999
33198
  }
33000
- };
33001
- function startAgentStream(event, activeChildParents) {
33002
- const agent = extractAgent(event);
33199
+ if (state) {
33200
+ try {
33201
+ if (isAsyncIterable(result)) {
33202
+ patchStreamIfNeeded(result, {
33203
+ aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
33204
+ onChunk: (chunk) => options.handleChunk(state, chunk),
33205
+ onComplete: () => options.finalize(state),
33206
+ onError: (error) => options.finalize(state, error)
33207
+ });
33208
+ } else {
33209
+ options.finalize(state, void 0, result);
33210
+ }
33211
+ } catch (error) {
33212
+ debugLogger.error(
33213
+ `Error finalizing ${options.name} instrumentation:`,
33214
+ error
33215
+ );
33216
+ }
33217
+ }
33218
+ return result;
33219
+ }
33220
+ function startAgentStream(input, agent, activeChildParents) {
33003
33221
  const model = agent?.model;
33004
33222
  const metadata = {
33005
33223
  ...extractAgentMetadata2(agent),
@@ -33009,17 +33227,14 @@ function startAgentStream(event, activeChildParents) {
33009
33227
  };
33010
33228
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
33011
33229
  const attachmentCache = createStrandsAttachmentCache();
33012
- const input = processStrandsInputAttachments(
33013
- event.arguments[0],
33014
- attachmentCache
33015
- );
33230
+ const processedInput = processStrandsInputAttachments(input, attachmentCache);
33016
33231
  const span = parentSpan ? withCurrent(
33017
33232
  parentSpan,
33018
33233
  () => startSpan(
33019
33234
  withSpanInstrumentationName(
33020
33235
  {
33021
33236
  event: {
33022
- input,
33237
+ input: processedInput,
33023
33238
  metadata
33024
33239
  },
33025
33240
  name: formatAgentSpanName(agent),
@@ -33032,7 +33247,7 @@ function startAgentStream(event, activeChildParents) {
33032
33247
  withSpanInstrumentationName(
33033
33248
  {
33034
33249
  event: {
33035
- input,
33250
+ input: processedInput,
33036
33251
  metadata
33037
33252
  },
33038
33253
  name: formatAgentSpanName(agent),
@@ -33050,22 +33265,21 @@ function startAgentStream(event, activeChildParents) {
33050
33265
  startTime: getCurrentUnixTimestamp()
33051
33266
  };
33052
33267
  }
33053
- function startMultiAgentStream(event, operation, activeChildParents) {
33054
- const orchestrator = extractOrchestrator(event);
33268
+ function startMultiAgentStream(input, orchestrator, operation, activeChildParents) {
33055
33269
  const metadata = {
33056
33270
  "strands.operation": operation,
33057
33271
  provider: "strands",
33058
33272
  ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
33059
33273
  };
33060
33274
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
33061
- const input = processStrandsInputAttachments(event.arguments[0]);
33275
+ const processedInput = processStrandsInputAttachments(input);
33062
33276
  const span = parentSpan ? withCurrent(
33063
33277
  parentSpan,
33064
33278
  () => startSpan(
33065
33279
  withSpanInstrumentationName(
33066
33280
  {
33067
33281
  event: {
33068
- input,
33282
+ input: processedInput,
33069
33283
  metadata
33070
33284
  },
33071
33285
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -33078,7 +33292,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
33078
33292
  withSpanInstrumentationName(
33079
33293
  {
33080
33294
  event: {
33081
- input,
33295
+ input: processedInput,
33082
33296
  metadata
33083
33297
  },
33084
33298
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -33449,12 +33663,12 @@ function finalizeMultiAgentStream(state, activeChildParents, error, output) {
33449
33663
  });
33450
33664
  state.span.end();
33451
33665
  }
33452
- function extractAgent(event) {
33453
- const candidate = event.agent ?? event.self;
33666
+ function extractAgent(agent, self) {
33667
+ const candidate = agent ?? self;
33454
33668
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
33455
33669
  }
33456
- function extractOrchestrator(event) {
33457
- const candidate = event.orchestrator ?? event.self;
33670
+ function extractOrchestrator(orchestrator, self) {
33671
+ const candidate = orchestrator ?? self;
33458
33672
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
33459
33673
  }
33460
33674
  function extractAgentMetadata2(agent) {
@@ -35703,7 +35917,6 @@ async function summarizeAndFlush(experiment, options) {
35703
35917
  }
35704
35918
 
35705
35919
  export {
35706
- debugLogger,
35707
35920
  IDGenerator,
35708
35921
  UUIDGenerator,
35709
35922
  OTELIDGenerator,