braintrust 3.27.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 (54) hide show
  1. package/README.md +1 -1
  2. package/dev/dist/index.d.mts +879 -197
  3. package/dev/dist/index.d.ts +879 -197
  4. package/dev/dist/index.js +2960 -1865
  5. package/dev/dist/index.mjs +2217 -1122
  6. package/dist/apply-auto-instrumentation.js +345 -260
  7. package/dist/apply-auto-instrumentation.mjs +137 -52
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +124 -7
  9. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  10. package/dist/auto-instrumentations/bundler/next.cjs +124 -7
  11. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  12. package/dist/auto-instrumentations/bundler/rollup.cjs +124 -7
  13. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.cjs +124 -7
  15. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  16. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +124 -7
  17. package/dist/auto-instrumentations/bundler/webpack.cjs +124 -7
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  19. package/dist/auto-instrumentations/{chunk-ZNHTSSGI.mjs → chunk-AOIYCVEL.mjs} +34 -3
  20. package/dist/auto-instrumentations/{chunk-XEYKUBLY.mjs → chunk-DKTGDNA7.mjs} +91 -5
  21. package/dist/auto-instrumentations/{chunk-BW33ULMW.mjs → chunk-OMCZ3MV2.mjs} +1 -1
  22. package/dist/auto-instrumentations/hook.mjs +1186 -161
  23. package/dist/auto-instrumentations/index.cjs +34 -3
  24. package/dist/auto-instrumentations/index.mjs +1 -1
  25. package/dist/browser.d.mts +1388 -75
  26. package/dist/browser.d.ts +1388 -75
  27. package/dist/browser.js +3954 -1124
  28. package/dist/browser.mjs +3954 -1124
  29. package/dist/{chunk-MF7NU6BT.js → chunk-6Z5S7VOU.js} +175 -25
  30. package/dist/{chunk-CZM5JIQL.mjs → chunk-7FA6VP2S.mjs} +172 -22
  31. package/dist/{chunk-YKD22IMR.mjs → chunk-M6XPNJC4.mjs} +2102 -1113
  32. package/dist/{chunk-QRHGVBKU.js → chunk-XLLGRXGR.js} +3273 -2284
  33. package/dist/cli.js +6353 -1483
  34. package/dist/edge-light.d.mts +1 -1
  35. package/dist/edge-light.d.ts +1 -1
  36. package/dist/edge-light.js +3954 -1124
  37. package/dist/edge-light.mjs +3954 -1124
  38. package/dist/index.d.mts +1972 -659
  39. package/dist/index.d.ts +1972 -659
  40. package/dist/index.js +2453 -676
  41. package/dist/index.mjs +1973 -196
  42. package/dist/instrumentation/index.d.mts +738 -15
  43. package/dist/instrumentation/index.d.ts +738 -15
  44. package/dist/instrumentation/index.js +2791 -874
  45. package/dist/instrumentation/index.mjs +2791 -874
  46. package/dist/vitest-evals-reporter.js +16 -16
  47. package/dist/vitest-evals-reporter.mjs +2 -2
  48. package/dist/workerd.d.mts +1 -1
  49. package/dist/workerd.d.ts +1 -1
  50. package/dist/workerd.js +3954 -1124
  51. package/dist/workerd.mjs +3954 -1124
  52. package/package.json +2 -3
  53. package/util/dist/index.d.mts +1596 -109
  54. package/util/dist/index.d.ts +1596 -109
@@ -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,129 +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,
53
+ voyageAIChannels,
48
54
  withSpanInstrumentationName
49
- } from "./chunk-CZM5JIQL.mjs";
55
+ } from "./chunk-7FA6VP2S.mjs";
50
56
 
51
57
  // src/id-gen.ts
52
58
  import { v4 as uuidv4 } from "uuid";
53
-
54
- // src/debug-logger.ts
55
- var PREFIX = "[braintrust]";
56
- var DEBUG_LOG_LEVEL_SYMBOL = /* @__PURE__ */ Symbol.for("braintrust-debug-log-level");
57
- var LOG_LEVEL_PRIORITY = {
58
- error: 0,
59
- warn: 1,
60
- info: 2,
61
- debug: 3
62
- };
63
- var hasWarnedAboutInvalidEnvValue = false;
64
- var debugLogStateResolver = void 0;
65
- function warnInvalidEnvValue(value) {
66
- if (hasWarnedAboutInvalidEnvValue) {
67
- return;
68
- }
69
- hasWarnedAboutInvalidEnvValue = true;
70
- console.warn(
71
- PREFIX,
72
- `Invalid BRAINTRUST_DEBUG_LOG_LEVEL value "${value}". Expected "error", "warn", "info", or "debug".`
73
- );
74
- }
75
- function normalizeDebugLogLevelOption(option) {
76
- if (option === false) {
77
- return void 0;
78
- }
79
- if (option === "error" || option === "warn" || option === "info" || option === "debug") {
80
- return option;
81
- }
82
- throw new Error(
83
- `Invalid debugLogLevel value "${option}". Expected false, "error", "warn", "info", or "debug".`
84
- );
85
- }
86
- function parseDebugLogLevelEnv(value) {
87
- if (!value) {
88
- return void 0;
89
- }
90
- if (value === "error" || value === "warn" || value === "info" || value === "debug") {
91
- return value;
92
- }
93
- warnInvalidEnvValue(value);
94
- return void 0;
95
- }
96
- function getEnvDebugLogLevel() {
97
- return parseDebugLogLevelEnv(isomorph_default.getEnv("BRAINTRUST_DEBUG_LOG_LEVEL"));
98
- }
99
- function setGlobalDebugLogLevel(level) {
100
- globalThis[DEBUG_LOG_LEVEL_SYMBOL] = level;
101
- }
102
- function resetDebugLoggerForTests() {
103
- hasWarnedAboutInvalidEnvValue = false;
104
- setGlobalDebugLogLevel(void 0);
105
- }
106
- function setDebugLogStateResolver(resolver) {
107
- debugLogStateResolver = resolver;
108
- }
109
- function resolveDebugLogLevel(state) {
110
- const stateLevel = state?.getDebugLogLevel?.();
111
- const hasStateOverride = state?.hasDebugLogLevelOverride?.() ?? false;
112
- if (hasStateOverride) {
113
- return stateLevel;
114
- }
115
- const globalLevel = (
116
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
117
- globalThis[DEBUG_LOG_LEVEL_SYMBOL]
118
- );
119
- if (globalLevel !== void 0) {
120
- return globalLevel === false ? void 0 : globalLevel;
121
- }
122
- return getEnvDebugLogLevel();
123
- }
124
- function emit(method, state, args) {
125
- const level = resolveDebugLogLevel(state);
126
- if (!level || LOG_LEVEL_PRIORITY[method] > LOG_LEVEL_PRIORITY[level]) {
127
- return;
128
- }
129
- if (method === "info") {
130
- console.log(PREFIX, ...args);
131
- } else if (method === "debug") {
132
- console.debug(PREFIX, ...args);
133
- } else if (method === "warn") {
134
- console.warn(PREFIX, ...args);
135
- } else {
136
- console.error(PREFIX, ...args);
137
- }
138
- }
139
- function createDebugLogger(state) {
140
- const resolveState = () => state ?? debugLogStateResolver?.();
141
- return {
142
- info(...args) {
143
- emit("info", resolveState(), args);
144
- },
145
- debug(...args) {
146
- emit("debug", resolveState(), args);
147
- },
148
- warn(...args) {
149
- emit("warn", resolveState(), args);
150
- },
151
- error(...args) {
152
- emit("error", resolveState(), args);
153
- }
154
- };
155
- }
156
- var debugLogger = {
157
- ...createDebugLogger(),
158
- forState(state) {
159
- return createDebugLogger(state);
160
- }
161
- };
162
- setGlobalHookErrorReporter((error) => {
163
- debugLogger.error("Global instrumentation hook error:", error);
164
- });
165
-
166
- // src/id-gen.ts
167
59
  var IDGenerator = class {
168
60
  };
169
61
  var UUIDGenerator = class extends IDGenerator {
@@ -1121,15 +1013,15 @@ function mergeDictsWithPaths({
1121
1013
  function mergeDictsWithPathsHelper({
1122
1014
  mergeInto,
1123
1015
  mergeFrom,
1124
- path: path2,
1016
+ path: path3,
1125
1017
  mergePaths
1126
1018
  }) {
1127
1019
  Object.entries(mergeFrom).forEach(([k, mergeFromV]) => {
1128
1020
  if (FORBIDDEN_MERGE_KEYS.has(k)) return;
1129
- const fullPath = path2.concat([k]);
1021
+ const fullPath = path3.concat([k]);
1130
1022
  const fullPathSerialized = JSON.stringify(fullPath);
1131
1023
  const mergeIntoV = recordFind(mergeInto, k);
1132
- const isSetUnionField = path2.length === 0 && SET_UNION_FIELDS.has(k) && !mergePaths.has(fullPathSerialized);
1024
+ const isSetUnionField = path3.length === 0 && SET_UNION_FIELDS.has(k) && !mergePaths.has(fullPathSerialized);
1133
1025
  if (isSetUnionField && isArray(mergeIntoV) && isArray(mergeFromV)) {
1134
1026
  const seen = /* @__PURE__ */ new Set();
1135
1027
  const combined = [];
@@ -1162,9 +1054,9 @@ function mergeDicts(mergeInto, mergeFrom) {
1162
1054
  function recordFind(m, k) {
1163
1055
  return m[k];
1164
1056
  }
1165
- function getObjValueByPath(row, path2) {
1057
+ function getObjValueByPath(row, path3) {
1166
1058
  let curr = row;
1167
- for (const p of path2) {
1059
+ for (const p of path3) {
1168
1060
  if (!isObjectOrArray(curr)) {
1169
1061
  return null;
1170
1062
  }
@@ -1780,7 +1672,10 @@ var AclObjectType = z6.union([
1780
1672
  "org_member",
1781
1673
  "project_log",
1782
1674
  "org_project",
1783
- "org_audit_logs"
1675
+ "org_audit_logs",
1676
+ "project_group",
1677
+ "ai_secret",
1678
+ "org_ai_secret"
1784
1679
  ]),
1785
1680
  z6.null()
1786
1681
  ]);
@@ -1909,7 +1804,8 @@ var AsyncScoringState = z6.union([
1909
1804
  token: z6.string(),
1910
1805
  function_ids: z6.array(z6.unknown()),
1911
1806
  skip_logging: z6.union([z6.boolean(), z6.null()]).optional(),
1912
- triggered_functions: z6.union([z6.record(TriggeredFunctionState), z6.null()]).optional()
1807
+ triggered_functions: z6.union([z6.record(TriggeredFunctionState), z6.null()]).optional(),
1808
+ last_triggered_xact_id: z6.union([z6.string(), z6.number(), z6.null()]).optional()
1913
1809
  }),
1914
1810
  z6.object({ status: z6.literal("disabled") }),
1915
1811
  z6.null(),
@@ -1978,7 +1874,7 @@ var FunctionTypeEnum = z6.enum([
1978
1874
  "parameters",
1979
1875
  "sandbox"
1980
1876
  ]);
1981
- var NullableSavedFunctionId = z6.union([
1877
+ var FacetPreprocessorId = z6.union([
1982
1878
  z6.object({
1983
1879
  type: z6.literal("function"),
1984
1880
  id: z6.string(),
@@ -1989,10 +1885,23 @@ var NullableSavedFunctionId = z6.union([
1989
1885
  name: z6.string(),
1990
1886
  function_type: FunctionTypeEnum.optional().default("scorer")
1991
1887
  }),
1888
+ z6.object({ type: z6.literal("inline"), code: z6.string().min(1) }),
1992
1889
  z6.null()
1993
1890
  ]);
1891
+ var SavedFunctionId = z6.union([
1892
+ z6.object({
1893
+ type: z6.literal("function"),
1894
+ id: z6.string(),
1895
+ version: z6.string().optional()
1896
+ }),
1897
+ z6.object({
1898
+ type: z6.literal("global"),
1899
+ name: z6.string(),
1900
+ function_type: FunctionTypeEnum.optional().default("scorer")
1901
+ })
1902
+ ]);
1994
1903
  var TopicMapGenerationSettings = z6.object({
1995
- algorithm: z6.enum(["hdbscan", "kmeans"]),
1904
+ algorithm: z6.enum(["hdbscan", "kmeans", "community"]),
1996
1905
  dimension_reduction: z6.enum(["umap", "pca", "none"]),
1997
1906
  sample_size: z6.number().int().gt(0).optional(),
1998
1907
  n_clusters: z6.number().int().gt(0).optional(),
@@ -2004,6 +1913,7 @@ var TopicMapGenerationSettings = z6.object({
2004
1913
  var TopicMapData = z6.object({
2005
1914
  type: z6.literal("topic_map"),
2006
1915
  source_facet: z6.string(),
1916
+ source_facet_function: SavedFunctionId.and(z6.unknown()).optional(),
2007
1917
  embedding_model: z6.string(),
2008
1918
  bundle_key: z6.string().optional(),
2009
1919
  report_key: z6.string().optional(),
@@ -2017,7 +1927,7 @@ var TopicMapData = z6.object({
2017
1927
  });
2018
1928
  var BatchedFacetData = z6.object({
2019
1929
  type: z6.literal("batched_facet"),
2020
- preprocessor: NullableSavedFunctionId.and(z6.unknown()).optional(),
1930
+ preprocessor: FacetPreprocessorId.optional(),
2021
1931
  facets: z6.array(
2022
1932
  z6.object({
2023
1933
  name: z6.string(),
@@ -2278,18 +2188,6 @@ var ObjectReferenceNullish = z6.union([
2278
2188
  }),
2279
2189
  z6.null()
2280
2190
  ]);
2281
- var SavedFunctionId = z6.union([
2282
- z6.object({
2283
- type: z6.literal("function"),
2284
- id: z6.string(),
2285
- version: z6.string().optional()
2286
- }),
2287
- z6.object({
2288
- type: z6.literal("global"),
2289
- name: z6.string(),
2290
- function_type: FunctionTypeEnum.optional().default("scorer")
2291
- })
2292
- ]);
2293
2191
  var DatasetEvent = z6.object({
2294
2192
  id: z6.string(),
2295
2193
  _xact_id: z6.string(),
@@ -2511,7 +2409,7 @@ var ExtendedSavedFunctionId = z6.union([
2511
2409
  ]);
2512
2410
  var FacetData = z6.object({
2513
2411
  type: z6.literal("facet"),
2514
- preprocessor: NullableSavedFunctionId.and(z6.unknown()).optional(),
2412
+ preprocessor: FacetPreprocessorId.optional(),
2515
2413
  prompt: z6.string(),
2516
2414
  model: z6.string().optional(),
2517
2415
  embedding_model: z6.string().optional(),
@@ -2610,7 +2508,7 @@ var PromptParserNullish = z6.union([
2610
2508
  }),
2611
2509
  z6.null()
2612
2510
  ]);
2613
- var PreprocessorSavedFunctionId = z6.union([
2511
+ var PreprocessorId = z6.union([
2614
2512
  z6.object({
2615
2513
  type: z6.literal("function"),
2616
2514
  id: z6.string(),
@@ -2621,6 +2519,7 @@ var PreprocessorSavedFunctionId = z6.union([
2621
2519
  name: z6.string(),
2622
2520
  function_type: z6.literal("preprocessor").optional().default("preprocessor")
2623
2521
  }),
2522
+ z6.object({ type: z6.literal("inline"), code: z6.string().min(1) }),
2624
2523
  z6.null()
2625
2524
  ]);
2626
2525
  var PromptDataNullish = z6.union([
@@ -2628,7 +2527,7 @@ var PromptDataNullish = z6.union([
2628
2527
  prompt: PromptBlockDataNullish,
2629
2528
  options: PromptOptionsNullish,
2630
2529
  parser: PromptParserNullish,
2631
- preprocessor: PreprocessorSavedFunctionId,
2530
+ preprocessor: PreprocessorId,
2632
2531
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
2633
2532
  template_format: z6.union([
2634
2533
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -2830,7 +2729,7 @@ var PromptData = z6.object({
2830
2729
  prompt: PromptBlockDataNullish,
2831
2730
  options: PromptOptionsNullish,
2832
2731
  parser: PromptParserNullish,
2833
- preprocessor: PreprocessorSavedFunctionId,
2732
+ preprocessor: PreprocessorId,
2834
2733
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
2835
2734
  template_format: z6.union([
2836
2735
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -3016,6 +2915,19 @@ var MessageRole = z6.enum([
3016
2915
  "model",
3017
2916
  "developer"
3018
2917
  ]);
2918
+ var NullableSavedFunctionId = z6.union([
2919
+ z6.object({
2920
+ type: z6.literal("function"),
2921
+ id: z6.string(),
2922
+ version: z6.string().optional()
2923
+ }),
2924
+ z6.object({
2925
+ type: z6.literal("global"),
2926
+ name: z6.string(),
2927
+ function_type: FunctionTypeEnum.optional().default("scorer")
2928
+ }),
2929
+ z6.null()
2930
+ ]);
3019
2931
  var ObjectReference = z6.object({
3020
2932
  object_type: z6.enum([
3021
2933
  "project_logs",
@@ -3037,6 +2949,7 @@ var TraceScope = z6.object({
3037
2949
  });
3038
2950
  var OnlineScoreConfig = z6.union([
3039
2951
  z6.object({
2952
+ status: AutomationStatus.optional(),
3040
2953
  sampling_rate: z6.number().gte(0).lte(1),
3041
2954
  scorers: z6.array(SavedFunctionId),
3042
2955
  btql_filter: z6.union([z6.string(), z6.null()]).optional(),
@@ -3117,6 +3030,72 @@ var Project = z6.object({
3117
3030
  user_id: z6.union([z6.string(), z6.null()]).optional(),
3118
3031
  settings: ProjectSettings.optional()
3119
3032
  });
3033
+ var WindowedAutomationConfig = z6.object({
3034
+ event_type: z6.literal("windowed"),
3035
+ product_origin: z6.union([z6.literal("patterns"), z6.null()]).optional(),
3036
+ status: AutomationStatus.optional(),
3037
+ threshold: z6.object({
3038
+ calculation: z6.object({
3039
+ type: z6.literal("btql"),
3040
+ btql_query: z6.string().min(1),
3041
+ output: z6.object({
3042
+ type: z6.literal("scalar"),
3043
+ value_column: z6.string().min(1)
3044
+ })
3045
+ }),
3046
+ policy: z6.object({
3047
+ condition: z6.object({
3048
+ type: z6.literal("threshold"),
3049
+ operator: z6.enum(["lt", "lte", "gt", "gte", "eq", "neq"]),
3050
+ threshold: z6.number()
3051
+ }),
3052
+ pending_seconds: z6.number().int().gte(0).lte(2592e3),
3053
+ no_data_behavior: z6.enum(["keep_last", "resolve", "alert"]),
3054
+ renotify_interval_seconds: z6.union([z6.number(), z6.null()]).optional(),
3055
+ notify_on_recovery: z6.boolean().optional().default(true)
3056
+ })
3057
+ }).optional(),
3058
+ window: z6.object({
3059
+ window_seconds: z6.number().int().gte(1).lte(2592e3),
3060
+ schedule: z6.union([
3061
+ z6.object({
3062
+ type: z6.literal("interval"),
3063
+ evaluation_interval_seconds: z6.number().int().gte(1).lte(2592e3)
3064
+ }),
3065
+ z6.object({
3066
+ type: z6.literal("cron"),
3067
+ cron_expression: z6.string().min(1),
3068
+ timezone: z6.union([z6.string(), z6.null()]).optional()
3069
+ })
3070
+ ]),
3071
+ evaluation_delay_seconds: z6.number().int().gte(0).lte(2592e3)
3072
+ }),
3073
+ loop: z6.object({
3074
+ prompt: z6.string().min(1).max(1e4),
3075
+ include_trigger_input: z6.boolean().optional().default(false),
3076
+ agent_slug: z6.string().min(1),
3077
+ auto_approve_tools: z6.array(z6.string().min(1)).optional().default([]),
3078
+ harness: z6.enum(["native", "codex", "claude-code"]).optional(),
3079
+ model: z6.string().min(1).optional(),
3080
+ reasoning_effort: z6.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional()
3081
+ }).optional(),
3082
+ actions: z6.array(
3083
+ z6.union([
3084
+ z6.object({
3085
+ type: z6.literal("webhook"),
3086
+ url: z6.string(),
3087
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
3088
+ }),
3089
+ z6.object({
3090
+ type: z6.literal("slack"),
3091
+ workspace_id: z6.string(),
3092
+ channel: z6.string(),
3093
+ message_template: z6.string().optional(),
3094
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
3095
+ })
3096
+ ])
3097
+ ).max(20).optional().default([])
3098
+ });
3120
3099
  var TopicAutomationFacetModel = z6.union([
3121
3100
  z6.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3122
3101
  z6.null()
@@ -3158,7 +3137,8 @@ var TopicDigestAutomationConfig = z6.object({
3158
3137
  type: z6.literal("slack"),
3159
3138
  workspace_id: z6.string(),
3160
3139
  channel: z6.string(),
3161
- message_template: z6.string().optional()
3140
+ message_template: z6.string().optional(),
3141
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
3162
3142
  }),
3163
3143
  topic_map_function_ids: z6.array(z6.string()).max(10).optional()
3164
3144
  });
@@ -3172,15 +3152,21 @@ var ProjectAutomation = z6.object({
3172
3152
  config: z6.union([
3173
3153
  z6.object({
3174
3154
  event_type: z6.literal("logs"),
3155
+ status: AutomationStatus.optional(),
3175
3156
  btql_filter: z6.string(),
3176
3157
  interval_seconds: z6.number().gte(1).lte(2592e3),
3177
3158
  action: z6.union([
3178
- z6.object({ type: z6.literal("webhook"), url: z6.string() }),
3159
+ z6.object({
3160
+ type: z6.literal("webhook"),
3161
+ url: z6.string(),
3162
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
3163
+ }),
3179
3164
  z6.object({
3180
3165
  type: z6.literal("slack"),
3181
3166
  workspace_id: z6.string(),
3182
3167
  channel: z6.string(),
3183
- message_template: z6.string().optional()
3168
+ message_template: z6.string().optional(),
3169
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
3184
3170
  })
3185
3171
  ])
3186
3172
  }),
@@ -3231,21 +3217,38 @@ var ProjectAutomation = z6.object({
3231
3217
  }),
3232
3218
  z6.object({
3233
3219
  event_type: z6.literal("environment_update"),
3220
+ status: AutomationStatus.optional(),
3234
3221
  environment_filter: z6.array(z6.string()).optional(),
3235
3222
  action: z6.union([
3236
- z6.object({ type: z6.literal("webhook"), url: z6.string() }),
3223
+ z6.object({
3224
+ type: z6.literal("webhook"),
3225
+ url: z6.string(),
3226
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
3227
+ }),
3237
3228
  z6.object({
3238
3229
  type: z6.literal("slack"),
3239
3230
  workspace_id: z6.string(),
3240
3231
  channel: z6.string(),
3241
- message_template: z6.string().optional()
3232
+ message_template: z6.string().optional(),
3233
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
3242
3234
  })
3243
3235
  ])
3244
3236
  }),
3237
+ WindowedAutomationConfig,
3245
3238
  TopicAutomationConfig,
3246
3239
  TopicDigestAutomationConfig
3247
3240
  ])
3248
3241
  });
3242
+ var ProjectGroup = z6.object({
3243
+ id: z6.string().uuid(),
3244
+ org_id: z6.string().uuid(),
3245
+ user_id: z6.union([z6.string(), z6.null()]).optional(),
3246
+ created: z6.union([z6.string(), z6.null()]).optional(),
3247
+ name: z6.string(),
3248
+ description: z6.union([z6.string(), z6.null()]).optional(),
3249
+ deleted_at: z6.union([z6.string(), z6.null()]).optional(),
3250
+ member_projects: z6.array(z6.string().uuid()).max(1e4)
3251
+ });
3249
3252
  var ProjectLogsEvent = z6.object({
3250
3253
  id: z6.string(),
3251
3254
  _xact_id: z6.string(),
@@ -3463,7 +3466,8 @@ var RunEval = z6.object({
3463
3466
  dataset_environment: z6.union([z6.string(), z6.null()]).optional(),
3464
3467
  _internal_btql: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional()
3465
3468
  }),
3466
- z6.object({ data: z6.array(z6.unknown()) })
3469
+ z6.object({ data: z6.array(z6.unknown()) }),
3470
+ z6.object({ experiment_name: z6.string() })
3467
3471
  ]),
3468
3472
  name: z6.string().optional(),
3469
3473
  parameters: z6.object({}).partial().passthrough().optional(),
@@ -3668,7 +3672,10 @@ var View = z6.object({
3668
3672
  "for_review_datasets"
3669
3673
  ]),
3670
3674
  name: z6.string(),
3675
+ description: z6.union([z6.string(), z6.null()]).optional(),
3676
+ starred: z6.boolean().optional(),
3671
3677
  created: z6.union([z6.string(), z6.null()]).optional(),
3678
+ updated_at: z6.union([z6.string(), z6.null()]).optional(),
3672
3679
  view_data: ViewData.optional(),
3673
3680
  options: ViewOptions.optional(),
3674
3681
  user_id: z6.union([z6.string(), z6.null()]).optional(),
@@ -4252,10 +4259,10 @@ var DiskCache = class {
4252
4259
  return;
4253
4260
  }
4254
4261
  const stats = await Promise.all(
4255
- paths.map(async (path2) => {
4256
- const stat2 = await isomorph_default.stat(path2);
4262
+ paths.map(async (path3) => {
4263
+ const stat2 = await isomorph_default.stat(path3);
4257
4264
  return {
4258
- path: path2,
4265
+ path: path3,
4259
4266
  mtime: stat2.mtime.getTime()
4260
4267
  };
4261
4268
  })
@@ -4427,44 +4434,72 @@ function createCacheLayers({
4427
4434
  }
4428
4435
 
4429
4436
  // src/prompt-cache/prompt-cache.ts
4430
- function createCacheKey(key) {
4437
+ function createCacheKey(key, namespace) {
4438
+ let cacheKey;
4431
4439
  if (key.id) {
4432
- return `id:${key.id}`;
4433
- }
4434
- const prefix = key.projectId ?? key.projectName;
4435
- if (!prefix) {
4436
- throw new Error("Either projectId or projectName must be provided");
4437
- }
4438
- if (!key.slug) {
4439
- 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"}`;
4440
4450
  }
4441
- return `${prefix}:${key.slug}:${key.version ?? "latest"}`;
4451
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
4442
4452
  }
4443
- var PromptCache = class {
4453
+ var PromptCache = class _PromptCache {
4444
4454
  memoryCache;
4445
4455
  diskCache;
4456
+ namespace;
4457
+ expectedResolvedOrgIdentity;
4446
4458
  constructor(options) {
4447
4459
  this.memoryCache = options.memoryCache;
4448
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
+ });
4449
4475
  }
4450
4476
  /**
4451
4477
  * Retrieves a prompt from the cache.
4452
4478
  * First checks the in-memory LRU cache, then falls back to checking the disk cache if available.
4453
4479
  */
4454
4480
  async get(key) {
4455
- const cacheKey = createCacheKey(key);
4481
+ const cacheKey = createCacheKey(key, this.namespace);
4456
4482
  if (this.memoryCache) {
4457
- const memoryPrompt = this.memoryCache.get(cacheKey);
4458
- if (memoryPrompt !== void 0) {
4459
- 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;
4460
4486
  }
4461
4487
  }
4462
4488
  if (this.diskCache) {
4463
- const diskPrompt = await this.diskCache.get(cacheKey);
4464
- if (!diskPrompt) {
4489
+ const diskEntry = await this.diskCache.get(cacheKey);
4490
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
4465
4491
  return void 0;
4466
4492
  }
4467
- 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
+ });
4468
4503
  return diskPrompt;
4469
4504
  }
4470
4505
  return void 0;
@@ -4478,58 +4513,91 @@ var PromptCache = class {
4478
4513
  * @throws If there is an error writing to the disk cache.
4479
4514
  */
4480
4515
  async set(key, value) {
4481
- const cacheKey = createCacheKey(key);
4482
- 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);
4483
4522
  if (this.diskCache) {
4484
- await this.diskCache.set(cacheKey, value);
4523
+ await this.diskCache.set(cacheKey, {
4524
+ value: value._internalSerializeForCache(),
4525
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
4526
+ });
4485
4527
  }
4486
4528
  }
4487
4529
  };
4488
4530
 
4489
4531
  // src/prompt-cache/parameters-cache.ts
4490
- function createCacheKey2(key) {
4532
+ function createCacheKey2(key, namespace) {
4533
+ let cacheKey;
4491
4534
  if (key.id) {
4492
- return `parameters:id:${key.id}`;
4493
- }
4494
- const prefix = key.projectId ?? key.projectName;
4495
- if (!prefix) {
4496
- throw new Error("Either projectId or projectName must be provided");
4497
- }
4498
- if (!key.slug) {
4499
- 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"}`;
4500
4545
  }
4501
- return `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
4546
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
4502
4547
  }
4503
- var ParametersCache = class {
4548
+ var ParametersCache = class _ParametersCache {
4504
4549
  memoryCache;
4505
4550
  diskCache;
4551
+ namespace;
4552
+ expectedResolvedOrgIdentity;
4506
4553
  constructor(options) {
4507
4554
  this.memoryCache = options.memoryCache;
4508
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
+ });
4509
4566
  }
4510
4567
  async get(key) {
4511
- const cacheKey = createCacheKey2(key);
4568
+ const cacheKey = createCacheKey2(key, this.namespace);
4512
4569
  if (this.memoryCache) {
4513
- const memoryParams = this.memoryCache.get(cacheKey);
4514
- if (memoryParams !== void 0) {
4515
- 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;
4516
4573
  }
4517
4574
  }
4518
4575
  if (this.diskCache) {
4519
- const diskParams = await this.diskCache.get(cacheKey);
4520
- if (!diskParams) {
4576
+ const diskEntry = await this.diskCache.get(cacheKey);
4577
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
4521
4578
  return void 0;
4522
4579
  }
4523
- this.memoryCache?.set(cacheKey, diskParams);
4524
- 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;
4525
4586
  }
4526
4587
  return void 0;
4527
4588
  }
4528
4589
  async set(key, value) {
4529
- const cacheKey = createCacheKey2(key);
4530
- 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);
4531
4596
  if (this.diskCache) {
4532
- await this.diskCache.set(cacheKey, value);
4597
+ await this.diskCache.set(cacheKey, {
4598
+ value: value._internalSerializeForCache(),
4599
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
4600
+ });
4533
4601
  }
4534
4602
  }
4535
4603
  };
@@ -4834,6 +4902,16 @@ var datasetSnapshotRegisterResponseSchema = z8.object({
4834
4902
  dataset_snapshot: DatasetSnapshot,
4835
4903
  found_existing: z8.boolean().optional()
4836
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
+ });
4837
4915
  var datasetRestorePreviewResultSchema = z8.object({
4838
4916
  rows_to_restore: z8.number(),
4839
4917
  rows_to_delete: z8.number()
@@ -4910,6 +4988,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
4910
4988
  var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
4911
4989
  "braintrust.initial-span-write-as-merge"
4912
4990
  );
4991
+ var RESUME_SPAN_WITHOUT_INITIAL_WRITE = /* @__PURE__ */ Symbol(
4992
+ "braintrust.resume-span-without-initial-write"
4993
+ );
4913
4994
  var INTERNAL_SPAN_CONTEXT = /* @__PURE__ */ Symbol("braintrust.internal-span-context");
4914
4995
  var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
4915
4996
  "braintrust.currentSpanStore"
@@ -5044,12 +5125,53 @@ var loginSchema = z8.strictObject({
5044
5125
  });
5045
5126
  var stateNonce = 0;
5046
5127
  var V1_PROXY_SUFFIX = "/v1/proxy";
5128
+ var LOADER_LOGIN_CACHE_MAX = 16;
5047
5129
  function normalizeProxyConnUrl(proxyUrl) {
5048
5130
  return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
5049
5131
  }
5050
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;
5051
5172
  constructor(loginParams) {
5052
- this.loginParams = loginParams;
5173
+ this.loginParams = { ...loginParams };
5174
+ this.activeLoginOrgNameSelector = loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
5053
5175
  this.id = `${(/* @__PURE__ */ new Date()).toLocaleString()}-${stateNonce++}`;
5054
5176
  this.currentExperiment = void 0;
5055
5177
  this.currentLogger = void 0;
@@ -5086,12 +5208,14 @@ var BraintrustState = class _BraintrustState {
5086
5208
  const {
5087
5209
  memoryCache: parametersMemoryCache,
5088
5210
  diskCache: parametersDiskCache
5089
- } = createCacheLayers({
5090
- memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
5091
- diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
5092
- diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
5093
- getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
5094
- });
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
+ );
5095
5219
  this.parametersCache = new ParametersCache({
5096
5220
  memoryCache: parametersMemoryCache,
5097
5221
  diskCache: parametersDiskCache
@@ -5100,43 +5224,6 @@ var BraintrustState = class _BraintrustState {
5100
5224
  this.spanOriginEnvironment = detectSpanOriginEnvironment();
5101
5225
  this._internalSetTraceContextSigningSecret(loginParams.apiKey);
5102
5226
  }
5103
- loginParams;
5104
- id;
5105
- currentExperiment;
5106
- // Note: the value of IsAsyncFlush doesn't really matter here, since we
5107
- // (safely) dynamically cast it whenever retrieving the logger.
5108
- currentLogger;
5109
- currentParent;
5110
- currentSpan;
5111
- // Any time we re-log in, we directly update the apiConn inside the logger.
5112
- // This is preferable to replacing the whole logger, which would create the
5113
- // possibility of multiple loggers floating around, which may not log in a
5114
- // deterministic order.
5115
- _bgLogger;
5116
- _overrideBgLogger = null;
5117
- appUrl = null;
5118
- appPublicUrl = null;
5119
- loginToken = null;
5120
- orgId = null;
5121
- orgName = null;
5122
- apiUrl = null;
5123
- proxyUrl = null;
5124
- loggedIn = false;
5125
- gitMetadataSettings;
5126
- debugLogLevel;
5127
- debugLogLevelConfigured = false;
5128
- fetch = globalThis.fetch;
5129
- _appConn = null;
5130
- _apiConn = null;
5131
- _proxyConn = null;
5132
- promptCache;
5133
- parametersCache;
5134
- spanCache;
5135
- _idGenerator = null;
5136
- _contextManager = null;
5137
- _otelFlushCallback = null;
5138
- spanOriginEnvironment;
5139
- traceContextSigningSecret;
5140
5227
  /** @internal */
5141
5228
  _internalSetTraceContextSigningSecret(secret) {
5142
5229
  const normalizedSecret = secret?.trim();
@@ -5161,6 +5248,101 @@ var BraintrustState = class _BraintrustState {
5161
5248
  this._appConn = null;
5162
5249
  this._apiConn = null;
5163
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
+ }
5164
5346
  }
5165
5347
  resetIdGenState() {
5166
5348
  this._idGenerator = null;
@@ -5209,6 +5391,8 @@ var BraintrustState = class _BraintrustState {
5209
5391
  this.debugLogLevel = other.debugLogLevel;
5210
5392
  this.debugLogLevelConfigured = other.debugLogLevelConfigured;
5211
5393
  this.traceContextSigningSecret = other.traceContextSigningSecret;
5394
+ this.fetch = other.fetch;
5395
+ this.activeLoginOrgNameSelector = other.activeLoginOrgNameSelector;
5212
5396
  setGlobalDebugLogLevel(
5213
5397
  this.debugLogLevelConfigured ? this.debugLogLevel ?? false : void 0
5214
5398
  );
@@ -5448,36 +5632,85 @@ var FailedHTTPResponse = class extends Error {
5448
5632
  status;
5449
5633
  text;
5450
5634
  data;
5451
- constructor(status, text, data) {
5635
+ cause;
5636
+ constructor(status, text, data, cause) {
5452
5637
  super(`${status}: ${text} (${data})`);
5453
5638
  this.status = status;
5454
5639
  this.text = text;
5455
5640
  this.data = data;
5641
+ this.cause = cause;
5456
5642
  }
5457
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;
5650
+ }
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
+ }
5458
5683
  async function checkResponse(resp) {
5459
5684
  if (resp.ok) {
5460
5685
  return resp;
5461
- } else {
5686
+ }
5687
+ let data;
5688
+ try {
5689
+ data = await resp.text();
5690
+ } catch (error) {
5462
5691
  throw new FailedHTTPResponse(
5463
5692
  resp.status,
5464
5693
  resp.statusText,
5465
- await resp.text()
5694
+ "Unable to read response body",
5695
+ error
5466
5696
  );
5467
5697
  }
5698
+ throw new FailedHTTPResponse(resp.status, resp.statusText, data);
5468
5699
  }
5469
5700
  var HTTPConnection = class _HTTPConnection {
5470
- base_url;
5471
- token;
5472
- headers;
5473
- fetch;
5474
- constructor(base_url, fetch2) {
5701
+ constructor(base_url, fetch2, classifyTransportErrors = false) {
5702
+ this.classifyTransportErrors = classifyTransportErrors;
5475
5703
  this.base_url = base_url;
5476
5704
  this.token = null;
5477
5705
  this.headers = {};
5478
5706
  this._reset();
5479
5707
  this.fetch = fetch2;
5480
5708
  }
5709
+ classifyTransportErrors;
5710
+ base_url;
5711
+ token;
5712
+ headers;
5713
+ fetch;
5481
5714
  setFetch(fetch2) {
5482
5715
  this.fetch = fetch2;
5483
5716
  }
@@ -5507,9 +5740,9 @@ var HTTPConnection = class _HTTPConnection {
5507
5740
  this.headers["Authorization"] = `Bearer ${this.token}`;
5508
5741
  }
5509
5742
  }
5510
- async get(path2, params = void 0, config) {
5743
+ async get(path3, params = void 0, config) {
5511
5744
  const { headers, ...rest } = config || {};
5512
- const url = new URL(_urljoin(this.base_url, path2));
5745
+ const url = new URL(_urljoin(this.base_url, path3));
5513
5746
  url.search = new URLSearchParams(
5514
5747
  params ? Object.entries(params).filter(([_, v]) => v !== void 0).flatMap(
5515
5748
  ([k, v]) => v !== void 0 ? typeof v === "string" ? [[k, v]] : v.map((x) => [k, x]) : []
@@ -5517,9 +5750,9 @@ var HTTPConnection = class _HTTPConnection {
5517
5750
  ).toString();
5518
5751
  const this_fetch = this.fetch;
5519
5752
  const this_headers = this.headers;
5520
- return await checkResponse(
5521
- // Using toString() here makes it work with isomorphic fetch
5522
- await this_fetch(url.toString(), {
5753
+ let response;
5754
+ try {
5755
+ response = await this_fetch(url.toString(), {
5523
5756
  headers: {
5524
5757
  Accept: "application/json",
5525
5758
  ...this_headers,
@@ -5527,10 +5760,16 @@ var HTTPConnection = class _HTTPConnection {
5527
5760
  },
5528
5761
  keepalive: true,
5529
5762
  ...rest
5530
- })
5531
- );
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);
5532
5771
  }
5533
- async post(path2, params, config, retries = 0) {
5772
+ async post(path3, params, config, retries = 0) {
5534
5773
  const { headers, ...rest } = config || {};
5535
5774
  const this_fetch = this.fetch;
5536
5775
  const this_base_url = this.base_url;
@@ -5538,8 +5777,9 @@ var HTTPConnection = class _HTTPConnection {
5538
5777
  const tries = retries + 1;
5539
5778
  for (let i = 0; i < tries; i++) {
5540
5779
  try {
5541
- return await checkResponse(
5542
- await this_fetch(_urljoin(this_base_url, path2), {
5780
+ let response;
5781
+ try {
5782
+ response = await this_fetch(_urljoin(this_base_url, path3), {
5543
5783
  method: "POST",
5544
5784
  headers: {
5545
5785
  Accept: "application/json",
@@ -5550,8 +5790,14 @@ var HTTPConnection = class _HTTPConnection {
5550
5790
  body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
5551
5791
  keepalive: true,
5552
5792
  ...rest
5553
- })
5554
- );
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);
5555
5801
  } catch (error) {
5556
5802
  if (config?.signal?.aborted) {
5557
5803
  throw getAbortReason(config.signal);
@@ -5560,7 +5806,7 @@ var HTTPConnection = class _HTTPConnection {
5560
5806
  throw error;
5561
5807
  }
5562
5808
  debugLogger.debug(
5563
- `Retrying API request ${path2} after ${formatHTTPError(error)}`
5809
+ `Retrying API request ${path3} after ${formatHTTPError(error)}`
5564
5810
  );
5565
5811
  const sleepTimeMs = HTTP_RETRY_BASE_SLEEP_TIME_S * 1e3 * 2 ** i + Math.random() * HTTP_RETRY_JITTER_MS;
5566
5812
  debugLogger.info(
@@ -5576,7 +5822,7 @@ var HTTPConnection = class _HTTPConnection {
5576
5822
  for (let i = 0; i < tries; i++) {
5577
5823
  try {
5578
5824
  const resp = await this.get(`${object_type}`, args);
5579
- return await resp.json();
5825
+ return await readJSONResponse(resp, this.classifyTransportErrors);
5580
5826
  } catch (e) {
5581
5827
  if (i < tries - 1) {
5582
5828
  debugLogger.debug(
@@ -5599,7 +5845,7 @@ var HTTPConnection = class _HTTPConnection {
5599
5845
  const resp = await this.post(`${object_type}`, args, {
5600
5846
  headers: { "Content-Type": "application/json" }
5601
5847
  });
5602
- return await resp.json();
5848
+ return await readJSONResponse(resp, this.classifyTransportErrors);
5603
5849
  }
5604
5850
  // Custom inspect for Node.js console.log
5605
5851
  [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
@@ -6133,6 +6379,30 @@ function updateSpan({
6133
6379
  event
6134
6380
  });
6135
6381
  }
6382
+ function _internalResumeSpan({
6383
+ exported,
6384
+ state
6385
+ }) {
6386
+ const resolvedState = state ?? _globalState;
6387
+ const components = SpanComponentsV4.fromStr(exported);
6388
+ const { row_id, root_span_id, span_id } = components.data;
6389
+ if (!row_id || !root_span_id || !span_id) {
6390
+ throw new Error("Only exported root spans can be resumed");
6391
+ }
6392
+ return new SpanImpl({
6393
+ state: resolvedState,
6394
+ parentObjectType: components.data.object_type,
6395
+ parentObjectId: new LazyValue(
6396
+ spanComponentsToObjectIdLambda(resolvedState, components)
6397
+ ),
6398
+ parentComputeObjectMetadataArgs: void 0,
6399
+ parentSpanIds: { parentSpanIds: [], rootSpanId: root_span_id },
6400
+ spanId: span_id,
6401
+ event: { id: row_id },
6402
+ propagatedEvent: components.data.propagated_event ?? void 0,
6403
+ [RESUME_SPAN_WITHOUT_INITIAL_WRITE]: true
6404
+ });
6405
+ }
6136
6406
  function spanComponentsToObjectIdLambda(state, components) {
6137
6407
  if (components.data.object_id) {
6138
6408
  const ret = components.data.object_id;
@@ -7623,6 +7893,7 @@ function initDataset(projectOrOptions, optionalOptions) {
7623
7893
  const {
7624
7894
  project,
7625
7895
  dataset,
7896
+ datasetId,
7626
7897
  description,
7627
7898
  version,
7628
7899
  snapshotName,
@@ -7638,6 +7909,11 @@ function initDataset(projectOrOptions, optionalOptions) {
7638
7909
  state: stateArg,
7639
7910
  _internal_btql
7640
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
+ }
7641
7917
  const selection = normalizeDatasetSelection({
7642
7918
  version,
7643
7919
  environment,
@@ -7658,6 +7934,35 @@ function initDataset(projectOrOptions, optionalOptions) {
7658
7934
  fetch: fetch2,
7659
7935
  forceLogin
7660
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
+ }
7661
7966
  const args = {
7662
7967
  org_id: state.orgId,
7663
7968
  project_name: project,
@@ -7811,6 +8116,24 @@ function initLogger(options = {}) {
7811
8116
  }
7812
8117
  return ret;
7813
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
+ }
7814
8137
  async function loadPrompt({
7815
8138
  projectName,
7816
8139
  projectId,
@@ -7835,43 +8158,47 @@ async function loadPrompt({
7835
8158
  throw new Error("Must specify slug");
7836
8159
  }
7837
8160
  const state = stateArg ?? _globalState;
7838
- let response;
7839
- try {
7840
- await state.login({
7841
- orgName,
7842
- apiKey,
7843
- appUrl,
7844
- fetch: fetch2,
7845
- forceLogin
7846
- });
7847
- if (id) {
7848
- response = await state.apiConn().get_json(`v1/prompt/${id}`, versionOrEnvironment);
7849
- if (response) {
7850
- 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
+ });
7851
8178
  }
7852
- } else {
7853
- response = await state.apiConn().get_json("v1/prompt", {
7854
- project_name: projectName,
7855
- project_id: projectId,
7856
- slug,
7857
- ...versionOrEnvironment
7858
- });
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;
7859
8187
  }
7860
- } catch (e) {
7861
8188
  if (version || environment) {
7862
8189
  throw new Error(`Prompt not found with specified parameters: ${e}`);
7863
8190
  }
7864
8191
  debugLogger.forState(state).warn("Failed to load prompt, attempting to fall back to cache:", e);
7865
8192
  let prompt2;
7866
8193
  if (id) {
7867
- prompt2 = await state.promptCache.get({ id });
8194
+ prompt2 = await promptCache.get({ id });
7868
8195
  if (!prompt2) {
7869
8196
  throw new Error(
7870
8197
  `Prompt with id ${id} not found (not found on server or in local cache): ${e}`
7871
8198
  );
7872
8199
  }
7873
8200
  } else {
7874
- prompt2 = await state.promptCache.get({
8201
+ prompt2 = await promptCache.get({
7875
8202
  slug,
7876
8203
  projectId,
7877
8204
  projectName,
@@ -7887,6 +8214,7 @@ async function loadPrompt({
7887
8214
  }
7888
8215
  return prompt2;
7889
8216
  }
8217
+ const { response } = result;
7890
8218
  if (!("objects" in response) || response.objects.length === 0) {
7891
8219
  if (id) {
7892
8220
  throw new Error(`Prompt with id ${id} not found.`);
@@ -7910,9 +8238,9 @@ async function loadPrompt({
7910
8238
  const prompt = new Prompt2(metadata, defaults || {}, noTrace);
7911
8239
  try {
7912
8240
  if (id) {
7913
- await state.promptCache.set({ id }, prompt);
8241
+ await promptCache.set({ id }, prompt);
7914
8242
  } else if (slug) {
7915
- await state.promptCache.set(
8243
+ await promptCache.set(
7916
8244
  { slug, projectId, projectName, version: version ?? "latest" },
7917
8245
  prompt
7918
8246
  );
@@ -7944,46 +8272,50 @@ async function loadParameters({
7944
8272
  throw new Error("Must specify slug");
7945
8273
  }
7946
8274
  const state = stateArg ?? _globalState;
7947
- let response;
7948
- try {
7949
- await state.login({
7950
- orgName,
7951
- apiKey,
7952
- appUrl,
7953
- fetch: fetch2,
7954
- forceLogin
7955
- });
7956
- if (id) {
7957
- response = await state.apiConn().get_json(`v1/function/${id}`, {
7958
- ...versionOrEnvironment
7959
- });
7960
- if (response) {
7961
- 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
+ });
7962
8295
  }
7963
- } else {
7964
- response = await state.apiConn().get_json("v1/function", {
7965
- project_name: projectName,
7966
- project_id: projectId,
7967
- slug,
7968
- function_type: "parameters",
7969
- ...versionOrEnvironment
7970
- });
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;
7971
8304
  }
7972
- } catch (e) {
7973
8305
  if (version || environment) {
7974
8306
  throw new Error(`Parameters not found with specified parameters: ${e}`);
7975
8307
  }
7976
8308
  debugLogger.forState(state).warn("Failed to load parameters, attempting to fall back to cache:", e);
7977
8309
  let parameters2;
7978
8310
  if (id) {
7979
- parameters2 = await state.parametersCache.get({ id });
8311
+ parameters2 = await parametersCache.get({ id });
7980
8312
  if (!parameters2) {
7981
8313
  throw new Error(
7982
8314
  `Parameters with id ${id} not found (not found on server or in local cache): ${e}`
7983
8315
  );
7984
8316
  }
7985
8317
  } else {
7986
- parameters2 = await state.parametersCache.get({
8318
+ parameters2 = await parametersCache.get({
7987
8319
  slug,
7988
8320
  projectId,
7989
8321
  projectName,
@@ -7999,6 +8331,7 @@ async function loadParameters({
7999
8331
  }
8000
8332
  return parameters2;
8001
8333
  }
8334
+ const { response } = result;
8002
8335
  if (!("objects" in response) || response.objects.length === 0) {
8003
8336
  if (id) {
8004
8337
  throw new Error(`Parameters with id ${id} not found.`);
@@ -8022,9 +8355,9 @@ async function loadParameters({
8022
8355
  const parameters = new RemoteEvalParameters(metadata);
8023
8356
  try {
8024
8357
  if (id) {
8025
- await state.parametersCache.set({ id }, parameters);
8358
+ await parametersCache.set({ id }, parameters);
8026
8359
  } else if (slug) {
8027
- await state.parametersCache.set(
8360
+ await parametersCache.set(
8028
8361
  { slug, projectId, projectName, version: version ?? "latest" },
8029
8362
  parameters
8030
8363
  );
@@ -8065,6 +8398,52 @@ async function login(options = {}) {
8065
8398
  await state.login(options);
8066
8399
  return state;
8067
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
+ }
8068
8447
  async function loginToState(options = {}) {
8069
8448
  const {
8070
8449
  appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
@@ -8096,16 +8475,18 @@ async function loginToState(options = {}) {
8096
8475
  _saveOrgInfo(state, testOrgInfo, testOrgInfo[0].name);
8097
8476
  return state;
8098
8477
  } else {
8099
- const resp = await checkResponse(
8100
- await fetch2(_urljoin(state.appUrl, `/api/apikey/login`), {
8478
+ const loginResponse = await fetch2(
8479
+ _urljoin(state.appUrl, `/api/apikey/login`),
8480
+ {
8101
8481
  method: "POST",
8102
8482
  headers: {
8103
8483
  "Content-Type": "application/json",
8104
8484
  Authorization: `Bearer ${apiKey}`
8105
8485
  }
8106
- })
8486
+ }
8107
8487
  );
8108
- const info = await resp.json();
8488
+ const resp = await checkResponse(loginResponse);
8489
+ const info = await readJSONResponse(resp);
8109
8490
  _saveOrgInfo(state, info.org_info, orgName);
8110
8491
  if (!state.apiUrl) {
8111
8492
  if (orgName) {
@@ -8608,11 +8989,11 @@ function wrapTraced(fn, args) {
8608
8989
  }
8609
8990
  if (args?.asyncFlush) {
8610
8991
  return ((...fnArgs) => traced((span) => {
8611
- if (!hasExplicitInput) {
8992
+ if (!args?.noTraceIO && !hasExplicitInput) {
8612
8993
  span.log({ input: fnArgs });
8613
8994
  }
8614
8995
  const output = fn(...fnArgs);
8615
- if (!hasExplicitOutput) {
8996
+ if (!args?.noTraceIO && !hasExplicitOutput) {
8616
8997
  if (output instanceof Promise) {
8617
8998
  return (async () => {
8618
8999
  const result = await output;
@@ -8627,12 +9008,12 @@ function wrapTraced(fn, args) {
8627
9008
  }, spanArgs));
8628
9009
  } else {
8629
9010
  return ((...fnArgs) => traced(async (span) => {
8630
- if (!hasExplicitInput) {
9011
+ if (!args?.noTraceIO && !hasExplicitInput) {
8631
9012
  span.log({ input: fnArgs });
8632
9013
  }
8633
9014
  const outputResult = fn(...fnArgs);
8634
9015
  const output = await outputResult;
8635
- if (!hasExplicitOutput) {
9016
+ if (!args?.noTraceIO && !hasExplicitOutput) {
8636
9017
  span.log({ output });
8637
9018
  }
8638
9019
  return output;
@@ -8758,27 +9139,28 @@ async function* asyncGeneratorWithCurrent(span, gen, state = void 0) {
8758
9139
  function withParent(parent, callback, state = void 0) {
8759
9140
  return (state ?? _globalState).currentParent.run(parent, () => callback());
8760
9141
  }
8761
- function _saveOrgInfo(state, org_info, org_name) {
8762
- 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) {
8763
9152
  throw new LoginInvalidOrgError(
8764
9153
  "This user is not part of any organizations."
8765
9154
  );
8766
9155
  }
8767
- for (const org of org_info) {
8768
- if (org_name === void 0 || org.name === org_name) {
8769
- state.orgId = org.id;
8770
- state.orgName = org.name;
8771
- state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
8772
- state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
8773
- state.gitMetadataSettings = org.git_metadata || void 0;
8774
- break;
9156
+ for (const org of orgInfo) {
9157
+ if (orgName === void 0 || org.name === orgName) {
9158
+ return org;
8775
9159
  }
8776
9160
  }
8777
- if (state.orgId === void 0) {
8778
- throw new LoginInvalidOrgError(
8779
- `Organization ${org_name} not found. Must be one of ${org_info.map((x) => x.name).join(", ")}`
8780
- );
8781
- }
9161
+ throw new LoginInvalidOrgError(
9162
+ `Organization ${orgName} not found. Must be one of ${orgInfo.map((org) => org.name).join(", ")}`
9163
+ );
8782
9164
  }
8783
9165
  function validateTags(tags) {
8784
9166
  const seen = /* @__PURE__ */ new Set();
@@ -9013,7 +9395,7 @@ var ObjectFetcher = class {
9013
9395
  const objectId = await this.id;
9014
9396
  const batchLimit = batchSize ?? DEFAULT_FETCH_BATCH_SIZE;
9015
9397
  const internalLimit = getInternalBtqlLimit(this._internal_btql);
9016
- const limit = batchSize !== void 0 ? batchSize : internalLimit ?? batchLimit;
9398
+ let remainingLimit = internalLimit;
9017
9399
  const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
9018
9400
  Object.entries(this._internal_btql ?? {}).filter(
9019
9401
  ([key]) => key !== "cursor" && key !== "limit" && key !== "select" && key !== "from"
@@ -9022,6 +9404,10 @@ var ObjectFetcher = class {
9022
9404
  let cursor = void 0;
9023
9405
  let iterations = 0;
9024
9406
  while (true) {
9407
+ if (remainingLimit !== void 0 && remainingLimit <= 0) {
9408
+ return;
9409
+ }
9410
+ const limit = remainingLimit === void 0 ? batchLimit : Math.min(batchLimit, remainingLimit);
9025
9411
  const resp = await state.apiConn().post(
9026
9412
  `btql`,
9027
9413
  {
@@ -9061,7 +9447,14 @@ var ObjectFetcher = class {
9061
9447
  const respJson = await resp.json();
9062
9448
  const mutate = this.mutateRecord;
9063
9449
  for (const record of respJson.data ?? []) {
9064
- yield mutate ? mutate(record) : record;
9450
+ if (remainingLimit !== void 0 && remainingLimit <= 0) {
9451
+ return;
9452
+ }
9453
+ const mutatedRecord = mutate ? mutate(record) : record;
9454
+ if (remainingLimit !== void 0) {
9455
+ remainingLimit--;
9456
+ }
9457
+ yield mutatedRecord;
9065
9458
  }
9066
9459
  if (!respJson.cursor) {
9067
9460
  break;
@@ -9581,7 +9974,9 @@ var SpanImpl = class _SpanImpl {
9581
9974
  this._rootSpanId = resolvedIds.rootSpanId;
9582
9975
  this._spanParents = resolvedIds.spanParents;
9583
9976
  this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
9584
- this.logInternal({ event, internalData });
9977
+ if (!args[RESUME_SPAN_WITHOUT_INITIAL_WRITE]) {
9978
+ this.logInternal({ event, internalData });
9979
+ }
9585
9980
  this.isMerge = true;
9586
9981
  }
9587
9982
  getParentInfo() {
@@ -10671,6 +11066,14 @@ var Prompt2 = class _Prompt {
10671
11066
  static isPrompt(data) {
10672
11067
  return typeof data === "object" && data !== null && "__braintrust_prompt_marker" in data;
10673
11068
  }
11069
+ /** @internal */
11070
+ _internalSerializeForCache() {
11071
+ return {
11072
+ metadata: this.metadata,
11073
+ defaults: this.defaults,
11074
+ noTrace: this.noTrace
11075
+ };
11076
+ }
10674
11077
  static fromPromptData(name, promptData) {
10675
11078
  return new _Prompt(
10676
11079
  {
@@ -10711,6 +11114,10 @@ var RemoteEvalParameters = class {
10711
11114
  get data() {
10712
11115
  return this.metadata.function_data.data ?? {};
10713
11116
  }
11117
+ /** @internal */
11118
+ _internalSerializeForCache() {
11119
+ return { metadata: this.metadata };
11120
+ }
10714
11121
  validate(data) {
10715
11122
  if (typeof data !== "object" || data === null) {
10716
11123
  return false;
@@ -11571,56 +11978,14 @@ function suppressionStore() {
11571
11978
  autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
11572
11979
  return autoInstrumentationSuppressionStore;
11573
11980
  }
11574
- function currentFrames() {
11575
- return suppressionStore().getStore()?.frames ?? [];
11576
- }
11577
11981
  function isAutoInstrumentationSuppressed() {
11578
- const frames = currentFrames();
11579
- return frames[frames.length - 1]?.mode === "suppress";
11982
+ return suppressionStore().getStore() === true;
11580
11983
  }
11581
11984
  function runWithAutoInstrumentationSuppressed(callback) {
11582
- const frame = {
11583
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
11584
- mode: "suppress"
11585
- };
11586
- return suppressionStore().run(
11587
- { frames: [...currentFrames(), frame] },
11588
- callback
11589
- );
11590
- }
11591
- function bindAutoInstrumentationSuppressionToStart(tracingChannel) {
11592
- const startChannel = tracingChannel.start;
11593
- if (!startChannel) {
11594
- return void 0;
11595
- }
11596
- const store = suppressionStore();
11597
- startChannel.bindStore(store, () => ({
11598
- frames: [
11599
- ...currentFrames(),
11600
- {
11601
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
11602
- mode: "suppress"
11603
- }
11604
- ]
11605
- }));
11606
- return () => {
11607
- startChannel.unbindStore(store);
11608
- };
11985
+ return suppressionStore().run(true, callback);
11609
11986
  }
11610
- function enterAutoInstrumentationAllowed() {
11611
- const frame = {
11612
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
11613
- mode: "allow"
11614
- };
11615
- suppressionStore().enterWith({
11616
- frames: [...currentFrames(), frame]
11617
- });
11618
- return () => {
11619
- const frames = currentFrames().filter(
11620
- (candidate) => candidate.id !== frame.id
11621
- );
11622
- suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
11623
- };
11987
+ function runWithAutoInstrumentationAllowed(callback) {
11988
+ return suppressionStore().run(void 0, callback);
11624
11989
  }
11625
11990
 
11626
11991
  // src/instrumentation/core/channel-tracing.ts
@@ -12311,6 +12676,22 @@ function processInputAttachments(input) {
12311
12676
  };
12312
12677
  }
12313
12678
  }
12679
+ const voyageBase64Key = node.type === "image_base64" ? Object.hasOwn(node, "imageBase64") ? "imageBase64" : "image_base64" : node.type === "video_base64" ? Object.hasOwn(node, "videoBase64") ? "videoBase64" : "video_base64" : void 0;
12680
+ const voyageBase64Value = voyageBase64Key ? node[voyageBase64Key] : void 0;
12681
+ if (voyageBase64Key && typeof voyageBase64Value === "string" && voyageBase64Value.startsWith("data:")) {
12682
+ const mediaType = inferMediaTypeFromDataUrl(
12683
+ voyageBase64Value,
12684
+ node.type === "video_base64" ? "video/mp4" : "image/png"
12685
+ );
12686
+ const filename = `${node.type === "video_base64" ? "video" : "image"}.${getExtensionFromMediaType(mediaType)}`;
12687
+ const attachment = toAttachment(voyageBase64Value, mediaType, filename);
12688
+ if (attachment) {
12689
+ return {
12690
+ ...node,
12691
+ [voyageBase64Key]: attachment
12692
+ };
12693
+ }
12694
+ }
12314
12695
  if (node.type === "file" && node.file && typeof node.file === "object" && typeof node.file.file_data === "string" && node.file.file_data.startsWith("data:")) {
12315
12696
  const mediaType = inferMediaTypeFromDataUrl(
12316
12697
  node.file.file_data,
@@ -12857,7 +13238,7 @@ var AISDKPlugin = class extends BasePlugin {
12857
13238
  }
12858
13239
  subscribeToAISDK() {
12859
13240
  const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
12860
- this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
13241
+ this.unsubscribers.push(interceptAISDKV7TelemetryDispatcher());
12861
13242
  this.unsubscribers.push(subscribeToHarnessAgentCreateSession());
12862
13243
  this.unsubscribers.push(
12863
13244
  subscribeToHarnessContinuation(
@@ -12885,6 +13266,18 @@ var AISDKPlugin = class extends BasePlugin {
12885
13266
  aggregateChunks: aggregateAISDKChunks
12886
13267
  })
12887
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
+ );
12888
13281
  this.unsubscribers.push(
12889
13282
  traceStreamingChannel(aiSDKChannels.streamText, {
12890
13283
  name: "streamText",
@@ -13374,26 +13767,29 @@ function subscribeToHarnessContinuation(continuationChannel, defaultDenyOutputPa
13374
13767
  channel.unsubscribe(handlers);
13375
13768
  };
13376
13769
  }
13377
- function subscribeToAISDKV7TelemetryDispatcher() {
13378
- const channel = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
13770
+ function interceptAISDKV7TelemetryDispatcher() {
13379
13771
  const telemetry = braintrustAISDKTelemetry();
13380
- const handlers = {
13381
- end: (event) => {
13382
- const telemetryOptions = event.arguments?.[0]?.telemetry;
13383
- if (telemetryOptions?.isEnabled === false) {
13384
- 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
+ }
13385
13789
  }
13386
- patchAISDKV7TelemetryDispatcher(
13387
- event.result,
13388
- telemetry,
13389
- telemetryOptions
13390
- );
13790
+ return dispatcher;
13391
13791
  }
13392
- };
13393
- channel.subscribe(handlers);
13394
- return () => {
13395
- channel.unsubscribe(handlers);
13396
- };
13792
+ );
13397
13793
  }
13398
13794
  function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
13399
13795
  if (!isObject(dispatcher)) {
@@ -13493,7 +13889,7 @@ function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
13493
13889
  return defaultDenyOutputPaths;
13494
13890
  }
13495
13891
  const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
13496
- if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path2) => typeof path2 === "string")) {
13892
+ if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path3) => typeof path3 === "string")) {
13497
13893
  return runtimeDenyOutputPaths;
13498
13894
  }
13499
13895
  return defaultDenyOutputPaths;
@@ -13718,16 +14114,10 @@ var convertImageToAttachment = (image, explicitMimeType) => {
13718
14114
  }
13719
14115
  }
13720
14116
  if (explicitMimeType) {
13721
- if (image instanceof Uint8Array) {
13722
- return new Attachment({
13723
- data: new Blob([image], { type: explicitMimeType }),
13724
- filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
13725
- contentType: explicitMimeType
13726
- });
13727
- }
13728
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
14117
+ const blob = convertDataToBlob(image, explicitMimeType);
14118
+ if (blob) {
13729
14119
  return new Attachment({
13730
- data: new Blob([image], { type: explicitMimeType }),
14120
+ data: blob,
13731
14121
  filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
13732
14122
  contentType: explicitMimeType
13733
14123
  });
@@ -13781,6 +14171,25 @@ var convertDataToAttachment = (data, mimeType, filename) => {
13781
14171
  function processAISDKCallInput(params) {
13782
14172
  return processInputAttachmentsSync(params);
13783
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
+ }
13784
14193
  function processAISDKWorkflowAgentCallInput(params) {
13785
14194
  const processed = processAISDKCallInput(params);
13786
14195
  return {
@@ -13919,6 +14328,12 @@ function prepareAISDKEmbedInput(params, self) {
13919
14328
  metadata: extractMetadataFromEmbedParams(params, self)
13920
14329
  };
13921
14330
  }
14331
+ function prepareAISDKGenerateImageInput(params, self) {
14332
+ return {
14333
+ input: processAISDKGenerateImageInput(params).input,
14334
+ metadata: extractMetadataFromCallParams(params, self)
14335
+ };
14336
+ }
13922
14337
  function prepareAISDKRerankInput(params, self) {
13923
14338
  const { documents, query } = params;
13924
14339
  return {
@@ -15255,11 +15670,11 @@ function processAISDKOutput(output, denyOutputPaths) {
15255
15670
  if (!output) return output;
15256
15671
  const merged = extractSerializableOutputFields(output);
15257
15672
  const deleteOutputPaths = denyOutputPaths.filter(
15258
- (path2) => path2.toLowerCase().endsWith("headers")
15673
+ (path3) => path3.toLowerCase().endsWith("headers")
15259
15674
  );
15260
15675
  const sanitized = omit(merged, denyOutputPaths, deleteOutputPaths);
15261
- for (const path2 of TRANSPORT_PAYLOAD_ROOT_PATHS) {
15262
- const stack = [{ obj: sanitized, keys: parsePath(path2) }];
15676
+ for (const path3 of TRANSPORT_PAYLOAD_ROOT_PATHS) {
15677
+ const stack = [{ obj: sanitized, keys: parsePath(path3) }];
15263
15678
  while (stack.length > 0) {
15264
15679
  const entry = stack.pop();
15265
15680
  if (!entry || entry.keys.length === 0) {
@@ -15294,6 +15709,57 @@ function processAISDKOutput(output, denyOutputPaths) {
15294
15709
  }
15295
15710
  return normalizeAISDKLoggedOutput(sanitized);
15296
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
+ }
15297
15763
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
15298
15764
  if (!output || typeof output !== "object") {
15299
15765
  return output;
@@ -15698,11 +16164,11 @@ function firstNumber(...values) {
15698
16164
  function deepCopy(obj) {
15699
16165
  return JSON.parse(JSON.stringify(obj));
15700
16166
  }
15701
- function parsePath(path2) {
16167
+ function parsePath(path3) {
15702
16168
  const keys = [];
15703
16169
  let current = "";
15704
- for (let i = 0; i < path2.length; i++) {
15705
- const char = path2[i];
16170
+ for (let i = 0; i < path3.length; i++) {
16171
+ const char = path3[i];
15706
16172
  if (char === ".") {
15707
16173
  if (current) {
15708
16174
  keys.push(current);
@@ -15715,8 +16181,8 @@ function parsePath(path2) {
15715
16181
  }
15716
16182
  let bracketContent = "";
15717
16183
  i++;
15718
- while (i < path2.length && path2[i] !== "]") {
15719
- bracketContent += path2[i];
16184
+ while (i < path3.length && path3[i] !== "]") {
16185
+ bracketContent += path3[i];
15720
16186
  i++;
15721
16187
  }
15722
16188
  if (bracketContent === "") {
@@ -15771,9 +16237,9 @@ function omitAtPath(obj, keys, deleteLeaf = false) {
15771
16237
  function omit(obj, paths, deletePaths = []) {
15772
16238
  const result = deepCopy(obj);
15773
16239
  const deletePathSet = new Set(deletePaths);
15774
- for (const path2 of paths) {
15775
- const keys = parsePath(path2);
15776
- omitAtPath(result, keys, deletePathSet.has(path2));
16240
+ for (const path3 of paths) {
16241
+ const keys = parsePath(path3);
16242
+ omitAtPath(result, keys, deletePathSet.has(path3));
15777
16243
  }
15778
16244
  return result;
15779
16245
  }
@@ -15782,7 +16248,6 @@ function omit(obj, paths, deletePaths = []) {
15782
16248
  function braintrustAISDKTelemetry() {
15783
16249
  const operations = /* @__PURE__ */ new Map();
15784
16250
  const operationKeysByCallId = /* @__PURE__ */ new Map();
15785
- const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
15786
16251
  const modelSpans = /* @__PURE__ */ new Map();
15787
16252
  const objectSpans = /* @__PURE__ */ new Map();
15788
16253
  const embedSpans = /* @__PURE__ */ new Map();
@@ -15825,9 +16290,6 @@ function braintrustAISDKTelemetry() {
15825
16290
  return;
15826
16291
  }
15827
16292
  operations.delete(operationKey);
15828
- if (workflowOperationKeyStore.getStore() === operationKey) {
15829
- workflowOperationKeyStore.enterWith(void 0);
15830
- }
15831
16293
  const keys = operationKeysByCallId.get(state.callId);
15832
16294
  if (!keys) {
15833
16295
  return;
@@ -15875,14 +16337,7 @@ function braintrustAISDKTelemetry() {
15875
16337
  return key;
15876
16338
  }
15877
16339
  }
15878
- const workflowOperationKey = workflowOperationKeyStore.getStore();
15879
- if (workflowOperationKey && keys.includes(workflowOperationKey)) {
15880
- return workflowOperationKey;
15881
- }
15882
- if (callId === "workflow-agent") {
15883
- return void 0;
15884
- }
15885
- return mode === "finish" ? keys[0] : keys[keys.length - 1];
16340
+ return callId === "workflow-agent" || mode === "active" ? keys[keys.length - 1] : keys[0];
15886
16341
  };
15887
16342
  const operationKeyFromEvent = (event, mode = "active") => {
15888
16343
  const explicit = explicitOperationKey(event);
@@ -15896,17 +16351,13 @@ function braintrustAISDKTelemetry() {
15896
16351
  if (operationKey) {
15897
16352
  return operationKey;
15898
16353
  }
15899
- const workflowOperationKey2 = workflowOperationKeyStore.getStore();
15900
- if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
15901
- return workflowOperationKey2;
16354
+ const workflowAgentKeys2 = operationKeysByCallId.get("workflow-agent");
16355
+ if (workflowAgentKeys2?.length) {
16356
+ return workflowAgentKeys2[workflowAgentKeys2.length - 1];
15902
16357
  }
15903
16358
  return callId === "workflow-agent" ? void 0 : callId;
15904
16359
  }
15905
16360
  }
15906
- const workflowOperationKey = workflowOperationKeyStore.getStore();
15907
- if (workflowOperationKey && operations.has(workflowOperationKey)) {
15908
- return workflowOperationKey;
15909
- }
15910
16361
  const wrapperSpan = currentWorkflowAgentWrapperSpan();
15911
16362
  if (wrapperSpan?.spanId) {
15912
16363
  for (const [operationKey, state] of operations) {
@@ -15916,8 +16367,8 @@ function braintrustAISDKTelemetry() {
15916
16367
  }
15917
16368
  }
15918
16369
  const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
15919
- if (workflowAgentKeys?.length === 1) {
15920
- return workflowAgentKeys[0];
16370
+ if (workflowAgentKeys?.length) {
16371
+ return workflowAgentKeys[workflowAgentKeys.length - 1];
15921
16372
  }
15922
16373
  if (operations.size === 1) {
15923
16374
  return operations.keys().next().value;
@@ -16120,9 +16571,6 @@ function braintrustAISDKTelemetry() {
16120
16571
  if (!ownsSpan) {
16121
16572
  return;
16122
16573
  }
16123
- if (workflowAgent) {
16124
- workflowOperationKeyStore.enterWith(operationKey);
16125
- }
16126
16574
  let metadata = metadataFromEvent(event);
16127
16575
  const logPayload = { metadata };
16128
16576
  const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
@@ -16999,17 +17447,20 @@ var FlueObserveBridge = class {
16999
17447
  return;
17000
17448
  }
17001
17449
  const metadata = {
17450
+ ...event.runId ? this.runsById.get(event.runId)?.metadata : {},
17002
17451
  ...extractEventMetadata(event),
17003
17452
  "flue.operation": event.operationKind,
17004
17453
  provider: "flue"
17005
17454
  };
17006
17455
  const parent = this.parentSpanForEvent(event);
17007
- const span = startFlueSpan(parent, {
17456
+ const args = {
17008
17457
  name: `flue.${event.operationKind}`,
17009
17458
  spanAttributes: { type: "task" /* TASK */ },
17010
17459
  startTime: eventTime(event.timestamp),
17011
17460
  event: { metadata }
17012
- });
17461
+ };
17462
+ const runSpan = event.runId ? this.runsById.get(event.runId)?.span : void 0;
17463
+ const span = event.operationKind === "prompt" && (!parent || parent === runSpan) ? startFlueRootSpan(args) : startFlueSpan(parent, args);
17013
17464
  this.operationsById.set(event.operationId, { metadata, span });
17014
17465
  }
17015
17466
  handleOperation(event) {
@@ -17024,6 +17475,11 @@ var FlueObserveBridge = class {
17024
17475
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
17025
17476
  ...event.usage ? { "flue.usage": event.usage } : {}
17026
17477
  };
17478
+ const input = flueOperationInput(event);
17479
+ if (!state.loggedInput && input !== void 0) {
17480
+ safeLog(state.span, { input });
17481
+ state.loggedInput = true;
17482
+ }
17027
17483
  this.finishPendingChildrenForOperation(event, output);
17028
17484
  safeLog(state.span, {
17029
17485
  ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
@@ -17040,6 +17496,8 @@ var FlueObserveBridge = class {
17040
17496
  return;
17041
17497
  }
17042
17498
  const input = flueTurnRequestInput(event);
17499
+ const operation = event.operationId ? this.operationsById.get(event.operationId) : void 0;
17500
+ const turnInput = prepareFlueTurnInput(event, input, operation);
17043
17501
  const model = flueTurnRequestModel(event);
17044
17502
  const provider = flueTurnRequestProvider(event);
17045
17503
  const api = flueTurnRequestApi(event);
@@ -17052,8 +17510,7 @@ var FlueObserveBridge = class {
17052
17510
  ...provider ? { "flue.provider": provider } : {},
17053
17511
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
17054
17512
  ...reasoning ? { reasoning } : {},
17055
- ...input?.systemPrompt ? { "flue.system_prompt": input.systemPrompt } : {},
17056
- ...input?.tools ? { tools: input.tools } : {}
17513
+ ...turnInput.metadata
17057
17514
  };
17058
17515
  const parent = this.parentSpanForTurn(event);
17059
17516
  const span = startFlueSpan(parent, {
@@ -17061,11 +17518,14 @@ var FlueObserveBridge = class {
17061
17518
  spanAttributes: { type: "llm" /* LLM */ },
17062
17519
  startTime: eventTime(event.timestamp),
17063
17520
  event: {
17064
- input: input?.messages,
17521
+ input: turnInput.messages,
17065
17522
  metadata
17066
17523
  }
17067
17524
  });
17068
- this.logOperationInput(event.operationId, input?.messages ?? input);
17525
+ this.logOperationInput(
17526
+ event.operationId,
17527
+ latestUserMessageInput(input?.messages)
17528
+ );
17069
17529
  this.turnsByKey.set(key, { metadata, span });
17070
17530
  }
17071
17531
  handleTurn(event) {
@@ -17312,16 +17772,20 @@ var FlueObserveBridge = class {
17312
17772
  }
17313
17773
  startSyntheticOperation(event) {
17314
17774
  const metadata = {
17775
+ ...event.runId ? this.runsById.get(event.runId)?.metadata : {},
17315
17776
  ...extractEventMetadata(event),
17316
17777
  "flue.operation": event.operationKind,
17317
17778
  provider: "flue"
17318
17779
  };
17319
- const span = startFlueSpan(this.parentSpanForEvent(event), {
17780
+ const args = {
17320
17781
  name: `flue.${event.operationKind}`,
17321
17782
  spanAttributes: { type: "task" /* TASK */ },
17322
17783
  startTime: eventTime(event.timestamp),
17323
17784
  event: { metadata }
17324
- });
17785
+ };
17786
+ const parent = this.parentSpanForEvent(event);
17787
+ const runSpan = event.runId ? this.runsById.get(event.runId)?.span : void 0;
17788
+ const span = event.operationKind === "prompt" && (!parent || parent === runSpan) ? startFlueRootSpan(args) : startFlueSpan(parent, args);
17325
17789
  return { metadata, span };
17326
17790
  }
17327
17791
  startSyntheticTurn(event) {
@@ -17500,6 +17964,71 @@ function flueRunInput(event) {
17500
17964
  function flueTurnRequestInput(event) {
17501
17965
  return event.request?.input ?? event.input;
17502
17966
  }
17967
+ function prepareFlueTurnInput(event, input, operation) {
17968
+ const messages = input?.messages;
17969
+ const tracksUserTurn = event.purpose === "agent" && operation?.metadata["flue.operation"] === "prompt" && Array.isArray(messages);
17970
+ if (!tracksUserTurn) {
17971
+ return {
17972
+ messages,
17973
+ metadata: {
17974
+ ...input?.systemPrompt ? { "flue.system_prompt": input.systemPrompt } : {},
17975
+ ...input?.tools ? { tools: input.tools } : {}
17976
+ }
17977
+ };
17978
+ }
17979
+ const previous = operation.turnInputState;
17980
+ const previousMessageCount = previous?.messageCount ?? 0;
17981
+ const boundaryFingerprint = messages.length > 0 ? fingerprintJsonValue(messages[messages.length - 1]) : void 0;
17982
+ const continuesPreviousInput = previous !== void 0 && messages.length >= previousMessageCount && (previousMessageCount === 0 || previous.boundaryFingerprint !== void 0 && previous.boundaryFingerprint === fingerprintJsonValue(messages[previousMessageCount - 1]));
17983
+ const inputMode = previous === void 0 ? "full" : continuesPreviousInput ? "delta" : "reset";
17984
+ const systemPromptFingerprint = fingerprintJsonValue(input?.systemPrompt);
17985
+ const toolsFingerprint = fingerprintJsonValue(input?.tools);
17986
+ operation.turnInputState = {
17987
+ ...boundaryFingerprint !== void 0 ? { boundaryFingerprint } : {},
17988
+ messageCount: messages.length,
17989
+ ...systemPromptFingerprint !== void 0 ? { systemPromptFingerprint } : {},
17990
+ ...toolsFingerprint !== void 0 ? { toolsFingerprint } : {}
17991
+ };
17992
+ return {
17993
+ messages: continuesPreviousInput ? messages.slice(previousMessageCount) : messages,
17994
+ metadata: {
17995
+ "flue.input_mode": inputMode,
17996
+ ...continuesPreviousInput ? { "flue.input_message_offset": previousMessageCount } : {},
17997
+ ...input?.systemPrompt && (!continuesPreviousInput || systemPromptFingerprint !== previous?.systemPromptFingerprint) ? { "flue.system_prompt": input.systemPrompt } : {},
17998
+ ...input?.tools && (!continuesPreviousInput || toolsFingerprint !== previous?.toolsFingerprint) ? { tools: input.tools } : {}
17999
+ }
18000
+ };
18001
+ }
18002
+ function fingerprintJsonValue(value) {
18003
+ try {
18004
+ const serialized = JSON.stringify(value);
18005
+ if (serialized === void 0) {
18006
+ return void 0;
18007
+ }
18008
+ let hash = 2166136261;
18009
+ for (let i = 0; i < serialized.length; i++) {
18010
+ hash = Math.imul(hash ^ serialized.charCodeAt(i), 16777619);
18011
+ }
18012
+ return `${serialized.length}:${hash >>> 0}`;
18013
+ } catch {
18014
+ return void 0;
18015
+ }
18016
+ }
18017
+ function latestUserMessageInput(messages) {
18018
+ if (!messages) {
18019
+ return void 0;
18020
+ }
18021
+ for (let i = messages.length - 1; i >= 0; i--) {
18022
+ const message = messages[i];
18023
+ if (isObjectLike(message) && Reflect.get(message, "role") === "user") {
18024
+ return [message];
18025
+ }
18026
+ }
18027
+ return void 0;
18028
+ }
18029
+ function flueOperationInput(event) {
18030
+ return typeof event.agentInput?.text === "string" ? [{ content: event.agentInput.text, role: "user" }] : void 0;
18031
+ }
17503
18032
  function flueTurnRequestModel(event) {
17504
18033
  return event.request?.requestedModel ?? event.request?.model ?? event.model;
17505
18034
  }
@@ -17657,6 +18186,21 @@ function startFlueSpan(parent, args) {
17657
18186
  withSpanInstrumentationName(args, INSTRUMENTATION_NAMES.FLUE)
17658
18187
  );
17659
18188
  }
18189
+ function startFlueRootSpan(args) {
18190
+ const state = _internalGetGlobalState();
18191
+ const spanId = state.idGenerator.getSpanId();
18192
+ const rootSpanId = state.idGenerator.shareRootSpanId() ? spanId : state.idGenerator.getTraceId();
18193
+ return withCurrent(
18194
+ NOOP_SPAN,
18195
+ () => startSpan({
18196
+ ...withSpanInstrumentationName(args, INSTRUMENTATION_NAMES.FLUE),
18197
+ parentSpanIds: { parentSpanIds: [], rootSpanId },
18198
+ spanId,
18199
+ state
18200
+ }),
18201
+ state
18202
+ );
18203
+ }
17660
18204
  function runWithCurrentSpanStore(span, next) {
17661
18205
  const state = _internalGetGlobalState();
17662
18206
  const contextManager = state?.contextManager;
@@ -18020,12 +18564,14 @@ function getMetricsFromResponse(response) {
18020
18564
  continue;
18021
18565
  }
18022
18566
  const inputTokenDetails = usageMetadata.input_token_details;
18567
+ const outputTokenDetails = usageMetadata.output_token_details;
18023
18568
  return normalizeTokenMetrics({
18024
18569
  total_tokens: usageMetadata.total_tokens,
18025
18570
  prompt_tokens: usageMetadata.input_tokens,
18026
18571
  completion_tokens: usageMetadata.output_tokens,
18027
18572
  prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
18028
- 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
18029
18575
  });
18030
18576
  }
18031
18577
  const llmOutput = response.llmOutput || {};
@@ -18403,13 +18949,33 @@ function aggregateChatLogprobs(existing, incoming) {
18403
18949
  }
18404
18950
  return aggregated;
18405
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
+ }
18406
18977
  function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
18407
- let role = void 0;
18408
- let content = void 0;
18409
- let refusal = void 0;
18410
- let tool_calls = void 0;
18411
- let logprobs = void 0;
18412
- let finish_reason = void 0;
18978
+ const choicesByIndex = /* @__PURE__ */ new Map();
18413
18979
  let metrics = {};
18414
18980
  for (const chunk of chunks) {
18415
18981
  if (chunk.usage) {
@@ -18418,62 +18984,75 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
18418
18984
  ...parseMetricsFromUsage(chunk.usage)
18419
18985
  };
18420
18986
  }
18421
- const choice = chunk.choices?.[0];
18422
- if (!choice) {
18987
+ const choices = chunk.choices;
18988
+ if (!choices?.length) {
18423
18989
  continue;
18424
18990
  }
18425
- if (choice.finish_reason) {
18426
- finish_reason = choice.finish_reason;
18427
- }
18428
- logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
18429
- const delta = choice.delta;
18430
- if (!delta) {
18431
- continue;
18432
- }
18433
- if (delta.finish_reason) {
18434
- finish_reason = delta.finish_reason;
18435
- }
18436
- if (!role && delta.role) {
18437
- role = delta.role;
18438
- }
18439
- if (delta.content) {
18440
- content = (content || "") + delta.content;
18441
- }
18442
- if (delta.refusal) {
18443
- refusal = (refusal || "") + delta.refusal;
18444
- }
18445
- if (delta.tool_calls) {
18446
- const toolDelta = delta.tool_calls[0];
18447
- if (!tool_calls || toolDelta.id && tool_calls[tool_calls.length - 1].id !== toolDelta.id) {
18448
- tool_calls = [
18449
- ...tool_calls || [],
18450
- {
18451
- id: toolDelta.id,
18452
- type: toolDelta.type,
18453
- 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
+ );
18454
19034
  }
18455
- ];
18456
- } else {
18457
- 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
+ }
18458
19048
  }
18459
19049
  }
18460
19050
  }
18461
19051
  metrics = withCachedMetric(metrics, streamResult, endEvent);
19052
+ const output = Array.from(choicesByIndex.values()).sort((left, right) => left.index - right.index).map(toChatChoice);
18462
19053
  return {
18463
19054
  metrics,
18464
- output: [
18465
- {
18466
- index: 0,
18467
- message: {
18468
- role,
18469
- content,
18470
- ...refusal !== void 0 ? { refusal } : {},
18471
- tool_calls
18472
- },
18473
- logprobs: logprobs ?? null,
18474
- finish_reason
18475
- }
18476
- ]
19055
+ output: output.length > 0 ? output : [toChatChoice(createAggregatedChatChoice(0))]
18477
19056
  };
18478
19057
  }
18479
19058
  function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
@@ -19152,12 +19731,30 @@ function logInstrumentationError2(context, error) {
19152
19731
 
19153
19732
  // src/wrappers/anthropic-tokens-util.ts
19154
19733
  function finalizeAnthropicTokens(metrics) {
19155
- const prompt_tokens = (metrics.prompt_tokens || 0) + (metrics.prompt_cached_tokens || 0) + (metrics.prompt_cache_creation_tokens || 0);
19156
- return {
19734
+ const hasSplitCacheCreationTokens = metrics.prompt_cache_creation_5m_tokens !== void 0 || metrics.prompt_cache_creation_1h_tokens !== void 0;
19735
+ const splitCacheCreationTokens = (metrics.prompt_cache_creation_5m_tokens || 0) + (metrics.prompt_cache_creation_1h_tokens || 0);
19736
+ const aggregateCacheCreationTokens = metrics.prompt_cache_creation_tokens || 0;
19737
+ const effectiveCacheCreationTokens = Math.max(
19738
+ aggregateCacheCreationTokens,
19739
+ splitCacheCreationTokens
19740
+ );
19741
+ const prompt_tokens = (metrics.prompt_tokens || 0) + (metrics.prompt_cached_tokens || 0) + effectiveCacheCreationTokens;
19742
+ const finalized = {
19157
19743
  ...metrics,
19158
19744
  prompt_tokens,
19159
19745
  tokens: prompt_tokens + (metrics.completion_tokens || 0)
19160
19746
  };
19747
+ if (hasSplitCacheCreationTokens && splitCacheCreationTokens >= aggregateCacheCreationTokens) {
19748
+ delete finalized.prompt_cache_creation_tokens;
19749
+ }
19750
+ return finalized;
19751
+ }
19752
+ function toNumericMetrics(metrics) {
19753
+ return Object.fromEntries(
19754
+ Object.entries(metrics).filter(
19755
+ (entry) => entry[1] !== void 0
19756
+ )
19757
+ );
19161
19758
  }
19162
19759
  function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens = 0) {
19163
19760
  const cacheTokens = {};
@@ -19716,6 +20313,24 @@ function parseMetricsFromUsage2(usage) {
19716
20313
  saveIfExistsTo("output_tokens", "completion_tokens");
19717
20314
  saveIfExistsTo("cache_read_input_tokens", "prompt_cached_tokens");
19718
20315
  saveIfExistsTo("cache_creation_input_tokens", "prompt_cache_creation_tokens");
20316
+ if (isObject(usage.cache_creation)) {
20317
+ const cacheCreation = usage.cache_creation;
20318
+ for (const [source, target] of [
20319
+ ["ephemeral_5m_input_tokens", "prompt_cache_creation_5m_tokens"],
20320
+ ["ephemeral_1h_input_tokens", "prompt_cache_creation_1h_tokens"]
20321
+ ]) {
20322
+ const value = cacheCreation[source];
20323
+ if (typeof value === "number") {
20324
+ metrics[target] = value;
20325
+ }
20326
+ }
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
+ }
19719
20334
  if (isObject(usage.server_tool_use)) {
19720
20335
  for (const [name, value] of Object.entries(usage.server_tool_use)) {
19721
20336
  if (typeof value === "number") {
@@ -20281,118 +20896,22 @@ function coalesceInput(messages, system) {
20281
20896
  var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
20282
20897
 
20283
20898
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
20284
- var LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED = /* @__PURE__ */ Symbol.for(
20285
- "braintrust.claude_agent_sdk.local_tool_context_async_iterator_patched"
20286
- );
20287
- function createLocalToolContextStore() {
20288
- const maybeIsoWithAsyncLocalStorage = isomorph_default;
20289
- if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
20290
- return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
20291
- }
20292
- let currentStore;
20293
- return {
20294
- enterWith(store) {
20295
- currentStore = store;
20296
- },
20297
- getStore() {
20298
- return currentStore;
20299
- },
20300
- run(store, callback) {
20301
- const previousStore = currentStore;
20302
- currentStore = store;
20303
- try {
20304
- return callback();
20305
- } finally {
20306
- currentStore = previousStore;
20307
- }
20308
- }
20309
- };
20310
- }
20311
- var localToolContextStore = createLocalToolContextStore();
20312
- var fallbackLocalToolParentResolver;
20313
- function createClaudeLocalToolContext() {
20314
- return {};
20315
- }
20316
- function runWithClaudeLocalToolContext(callback, context) {
20317
- return localToolContextStore.run(
20318
- context ?? createClaudeLocalToolContext(),
20319
- callback
20320
- );
20321
- }
20322
- function ensureClaudeLocalToolContext() {
20323
- const existing = localToolContextStore.getStore();
20324
- if (existing) {
20325
- return existing;
20326
- }
20327
- const created = {};
20328
- localToolContextStore.enterWith(created);
20329
- return created;
20330
- }
20331
- function setClaudeLocalToolParentResolver(resolver) {
20332
- fallbackLocalToolParentResolver = resolver;
20333
- const context = ensureClaudeLocalToolContext();
20334
- if (!context) {
20335
- return;
20336
- }
20337
- context.resolveLocalToolParent = resolver;
20338
- }
20339
- function getClaudeLocalToolParentResolver() {
20340
- return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
20899
+ var localToolContextStore = isomorph_default.newAsyncLocalStorage();
20900
+ var localToolParentResolversByToolUseId = /* @__PURE__ */ new Map();
20901
+ function runWithClaudeLocalToolContext(callback, resolver) {
20902
+ return localToolContextStore.run(resolver, callback);
20341
20903
  }
20342
- function isAsyncIterable3(value) {
20343
- return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
20904
+ function registerClaudeLocalToolParentResolver(toolUseId, resolver) {
20905
+ localToolParentResolversByToolUseId.set(toolUseId, resolver);
20344
20906
  }
20345
- function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
20346
- if (!isAsyncIterable3(result) || Object.isFrozen(result) || Object.isSealed(result)) {
20347
- return result;
20348
- }
20349
- const stream = result;
20350
- const originalAsyncIterator = stream[Symbol.asyncIterator];
20351
- if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
20352
- return result;
20907
+ function getClaudeLocalToolParentResolver(toolUseId) {
20908
+ const currentResolver = localToolContextStore.getStore();
20909
+ if (!toolUseId) {
20910
+ return currentResolver;
20353
20911
  }
20354
- const patchedAsyncIterator = function() {
20355
- return runWithClaudeLocalToolContext(() => {
20356
- const iterator = Reflect.apply(originalAsyncIterator, this, []);
20357
- if (!iterator || typeof iterator !== "object") {
20358
- return iterator;
20359
- }
20360
- const patchMethod = (methodName) => {
20361
- const originalMethod = Reflect.get(iterator, methodName);
20362
- if (typeof originalMethod !== "function") {
20363
- return;
20364
- }
20365
- Reflect.set(
20366
- iterator,
20367
- methodName,
20368
- (...args) => runWithClaudeLocalToolContext(
20369
- () => Reflect.apply(
20370
- originalMethod,
20371
- iterator,
20372
- args
20373
- ),
20374
- localToolContext
20375
- )
20376
- );
20377
- };
20378
- patchMethod("next");
20379
- patchMethod("return");
20380
- patchMethod("throw");
20381
- return iterator;
20382
- }, localToolContext);
20383
- };
20384
- Object.defineProperty(
20385
- patchedAsyncIterator,
20386
- LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
20387
- {
20388
- configurable: false,
20389
- enumerable: false,
20390
- value: true,
20391
- writable: false
20392
- }
20393
- );
20394
- Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
20395
- return result;
20912
+ const registeredResolver = localToolParentResolversByToolUseId.get(toolUseId);
20913
+ localToolParentResolversByToolUseId.delete(toolUseId);
20914
+ return currentResolver ?? registeredResolver;
20396
20915
  }
20397
20916
 
20398
20917
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
@@ -20418,7 +20937,7 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
20418
20937
  const metadata = getMetadata();
20419
20938
  const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
20420
20939
  const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
20421
- const localToolParentResolver = getClaudeLocalToolParentResolver();
20940
+ const localToolParentResolver = getClaudeLocalToolParentResolver(toolUseId);
20422
20941
  const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
20423
20942
  const runWithResolvedParent = async () => {
20424
20943
  const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
@@ -20687,37 +21206,97 @@ function seedTaskToolUseIdMapping(taskIdToToolUseId, message) {
20687
21206
  taskIdToToolUseId.set(message.task_id, message.tool_use_id);
20688
21207
  }
20689
21208
  }
20690
- function extractUsageFromMessage(message) {
20691
- const metrics = {};
20692
- let usage;
20693
- if (message.type === "assistant") {
20694
- usage = message.message?.usage;
20695
- } else if (message.type === "result") {
20696
- usage = message.usage;
20697
- }
21209
+ function tokenCount(value) {
21210
+ return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0 ? value : void 0;
21211
+ }
21212
+ function copyUsage(usage) {
20698
21213
  if (!usage || typeof usage !== "object") {
20699
- return metrics;
21214
+ return void 0;
21215
+ }
21216
+ const copy = {};
21217
+ for (const key of [
21218
+ "input_tokens",
21219
+ "output_tokens",
21220
+ "cache_read_input_tokens",
21221
+ "cache_creation_input_tokens"
21222
+ ]) {
21223
+ const value = tokenCount(Reflect.get(usage, key));
21224
+ if (value !== void 0) {
21225
+ copy[key] = value;
21226
+ }
21227
+ }
21228
+ const cacheCreation = Reflect.get(usage, "cache_creation");
21229
+ if (cacheCreation && typeof cacheCreation === "object") {
21230
+ const cacheCreationCopy = {};
21231
+ for (const key of [
21232
+ "ephemeral_5m_input_tokens",
21233
+ "ephemeral_1h_input_tokens"
21234
+ ]) {
21235
+ const value = tokenCount(Reflect.get(cacheCreation, key));
21236
+ if (value !== void 0) {
21237
+ cacheCreationCopy[key] = value;
21238
+ }
21239
+ }
21240
+ if (Object.keys(cacheCreationCopy).length > 0) {
21241
+ copy.cache_creation = cacheCreationCopy;
21242
+ }
21243
+ }
21244
+ return Object.keys(copy).length > 0 ? copy : void 0;
21245
+ }
21246
+ function mergeUsage(base, override) {
21247
+ if (!base || !override) {
21248
+ return override ?? base;
21249
+ }
21250
+ const cacheCreation = base.cache_creation || override.cache_creation ? { ...base.cache_creation, ...override.cache_creation } : void 0;
21251
+ return {
21252
+ ...base,
21253
+ ...override,
21254
+ ...cacheCreation && { cache_creation: cacheCreation }
21255
+ };
21256
+ }
21257
+ function extractUsage(usage, includeOutput) {
21258
+ const metrics = {};
21259
+ if (!usage) {
21260
+ return {};
20700
21261
  }
20701
21262
  const inputTokens = getNumberProperty(usage, "input_tokens");
20702
21263
  if (inputTokens !== void 0) {
20703
21264
  metrics.prompt_tokens = inputTokens;
20704
21265
  }
20705
- const outputTokens = getNumberProperty(usage, "output_tokens");
20706
- if (outputTokens !== void 0) {
20707
- metrics.completion_tokens = outputTokens;
21266
+ if (includeOutput) {
21267
+ const outputTokens = getNumberProperty(usage, "output_tokens");
21268
+ if (outputTokens !== void 0) {
21269
+ metrics.completion_tokens = outputTokens;
21270
+ }
20708
21271
  }
20709
21272
  const cacheReadTokens = getNumberProperty(usage, "cache_read_input_tokens") || 0;
20710
21273
  const cacheCreationTokens = getNumberProperty(usage, "cache_creation_input_tokens") || 0;
20711
- if (cacheReadTokens > 0 || cacheCreationTokens > 0) {
20712
- Object.assign(
20713
- metrics,
20714
- extractAnthropicCacheTokens(cacheReadTokens, cacheCreationTokens)
20715
- );
21274
+ Object.assign(
21275
+ metrics,
21276
+ extractAnthropicCacheTokens(cacheReadTokens, cacheCreationTokens)
21277
+ );
21278
+ const cacheCreation5mTokens = getNumberProperty(
21279
+ usage.cache_creation,
21280
+ "ephemeral_5m_input_tokens"
21281
+ );
21282
+ const cacheCreation1hTokens = getNumberProperty(
21283
+ usage.cache_creation,
21284
+ "ephemeral_1h_input_tokens"
21285
+ );
21286
+ if (cacheCreation5mTokens !== void 0) {
21287
+ metrics.prompt_cache_creation_5m_tokens = cacheCreation5mTokens;
20716
21288
  }
20717
- if (Object.keys(metrics).length > 0) {
20718
- Object.assign(metrics, finalizeAnthropicTokens(metrics));
21289
+ if (cacheCreation1hTokens !== void 0) {
21290
+ metrics.prompt_cache_creation_1h_tokens = cacheCreation1hTokens;
20719
21291
  }
20720
- return metrics;
21292
+ if (Object.keys(metrics).length === 0) {
21293
+ return {};
21294
+ }
21295
+ const finalized = finalizeAnthropicTokens(metrics);
21296
+ if (metrics.completion_tokens === void 0) {
21297
+ delete finalized.tokens;
21298
+ }
21299
+ return toNumericMetrics(finalized);
20721
21300
  }
20722
21301
  function buildLLMInput(promptMessages, conversationHistory) {
20723
21302
  const inputParts = [...promptMessages, ...conversationHistory];
@@ -20751,16 +21330,16 @@ function buildRootPromptMessages(prompt, capturedPromptMessages) {
20751
21330
  function formatCapturedMessages(messages) {
20752
21331
  return messages.length > 0 ? messages : [];
20753
21332
  }
20754
- async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
21333
+ async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, usage, hasFinalOutputUsage, existingSpan) {
20755
21334
  if (messages.length === 0) {
20756
21335
  return void 0;
20757
21336
  }
20758
21337
  const lastMessage = messages[messages.length - 1];
20759
- if (lastMessage.type !== "assistant" || !lastMessage.message?.usage) {
21338
+ if (lastMessage.type !== "assistant") {
20760
21339
  return void 0;
20761
21340
  }
20762
- const model = lastMessage.message.model || options.model;
20763
- const usage = extractUsageFromMessage(lastMessage);
21341
+ const model = lastMessage.message?.model || options.model;
21342
+ const metrics = options.includePartialMessages ? extractUsage(usage, hasFinalOutputUsage) : {};
20764
21343
  const input = buildLLMInput(promptMessages, conversationHistory);
20765
21344
  const outputs = messages.map(
20766
21345
  (m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
@@ -20782,8 +21361,8 @@ async function createLLMSpanForMessages(messages, promptMessages, conversationHi
20782
21361
  );
20783
21362
  span.log({
20784
21363
  input,
20785
- metadata: model ? { model } : void 0,
20786
- metrics: usage,
21364
+ metadata: { ...model && { model }, provider: "anthropic" },
21365
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
20787
21366
  output: outputs
20788
21367
  });
20789
21368
  const spanExport = await span.export();
@@ -20873,12 +21452,19 @@ function prepareLocalToolHandlersInMcpServers(mcpServers) {
20873
21452
  }
20874
21453
  return { hasLocalToolHandlers, localToolHookNames };
20875
21454
  }
20876
- function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
21455
+ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToParent, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
20877
21456
  const preToolUse = async (input, toolUseID) => {
20878
21457
  if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
20879
21458
  return {};
20880
21459
  }
21460
+ if (!toolUseToParent.has(toolUseID) && input.agent_id) {
21461
+ const parentToolUseId = taskIdToToolUseId.get(input.agent_id);
21462
+ if (parentToolUseId) {
21463
+ toolUseToParent.set(toolUseID, parentToolUseId);
21464
+ }
21465
+ }
20881
21466
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
21467
+ registerClaudeLocalToolParentResolver(toolUseID, resolveParentSpan);
20882
21468
  return {};
20883
21469
  }
20884
21470
  const parsed = parseToolName(input.tool_name);
@@ -21073,9 +21659,6 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
21073
21659
  }
21074
21660
  const metadata = {
21075
21661
  ...subAgentDetailsToMetadata(details),
21076
- ...input.agent_transcript_path && {
21077
- "claude_agent_sdk.agent_transcript_path": input.agent_transcript_path
21078
- },
21079
21662
  "claude_agent_sdk.stop_hook_active": input.stop_hook_active
21080
21663
  };
21081
21664
  try {
@@ -21097,7 +21680,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
21097
21680
  subagentStop
21098
21681
  };
21099
21682
  }
21100
- function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
21683
+ function injectTracingHooks(options, resolveParentSpan, taskIdToToolUseId, toolUseToParent, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
21101
21684
  const {
21102
21685
  preToolUse,
21103
21686
  postToolUse,
@@ -21106,6 +21689,8 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
21106
21689
  subagentStop
21107
21690
  } = createToolTracingHooks(
21108
21691
  resolveParentSpan,
21692
+ taskIdToToolUseId,
21693
+ toolUseToParent,
21109
21694
  activeToolSpans,
21110
21695
  options.mcpServers,
21111
21696
  localToolHookNames,
@@ -21187,6 +21772,13 @@ async function finalizeCurrentMessageGroup(state) {
21187
21772
  }
21188
21773
  }
21189
21774
  const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
21775
+ const lastMessage = state.currentMessages[state.currentMessages.length - 1];
21776
+ const messageId = lastMessage?.message?.id;
21777
+ const usage = state.options.includePartialMessages ? mergeUsage(
21778
+ copyUsage(lastMessage?.message?.usage),
21779
+ messageId ? state.usageByMessageId.get(messageId) : void 0
21780
+ ) : void 0;
21781
+ const hasFinalOutputUsage = messageId !== void 0 && state.finalOutputUsageMessageIds.has(messageId);
21190
21782
  const llmSpanResult = await createLLMSpanForMessages(
21191
21783
  state.currentMessages,
21192
21784
  promptMessages,
@@ -21194,6 +21786,8 @@ async function finalizeCurrentMessageGroup(state) {
21194
21786
  state.options,
21195
21787
  state.currentMessageStartTime,
21196
21788
  parentSpan,
21789
+ usage,
21790
+ hasFinalOutputUsage,
21197
21791
  existingLlmSpan
21198
21792
  );
21199
21793
  if (llmSpanResult) {
@@ -21211,9 +21805,17 @@ async function finalizeCurrentMessageGroup(state) {
21211
21805
  }
21212
21806
  }
21213
21807
  state.activeLlmSpansByParentToolUse.delete(parentKey);
21214
- const lastMessage = state.currentMessages[state.currentMessages.length - 1];
21215
- if (lastMessage?.message?.usage) {
21216
- state.accumulatedOutputTokens += getNumberProperty(lastMessage.message.usage, "output_tokens") || 0;
21808
+ if (messageId) {
21809
+ state.usageByMessageId.delete(messageId);
21810
+ state.finalOutputUsageMessageIds.delete(messageId);
21811
+ for (const [
21812
+ parent,
21813
+ activeMessageId
21814
+ ] of state.activePartialMessageIdByParentKey) {
21815
+ if (activeMessageId === messageId) {
21816
+ state.activePartialMessageIdByParentKey.delete(parent);
21817
+ }
21818
+ }
21217
21819
  }
21218
21820
  state.currentMessages.length = 0;
21219
21821
  }
@@ -21304,6 +21906,10 @@ async function ensureActiveLlmSpanForParentToolUse(rootSpan, activeLlmSpansByPar
21304
21906
  );
21305
21907
  llmParentSpan = await subAgentSpan.export();
21306
21908
  }
21909
+ const racedLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
21910
+ if (racedLlmSpan) {
21911
+ return racedLlmSpan;
21912
+ }
21307
21913
  const llmSpan = startSpan(
21308
21914
  withSpanInstrumentationName(
21309
21915
  {
@@ -21423,7 +22029,49 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
21423
22029
  }
21424
22030
  return true;
21425
22031
  }
22032
+ function handlePartialUsageMessage(state, message) {
22033
+ if (message.type !== "stream_event") {
22034
+ return false;
22035
+ }
22036
+ const event = message.event;
22037
+ if (!event || typeof event !== "object") {
22038
+ return true;
22039
+ }
22040
+ const parentKey = llmParentKey(message.parent_tool_use_id ?? null);
22041
+ if (event.type === "message_start") {
22042
+ const messageId2 = event.message?.id;
22043
+ const usage = copyUsage(event.message?.usage);
22044
+ if (messageId2) {
22045
+ state.activePartialMessageIdByParentKey.set(parentKey, messageId2);
22046
+ if (usage) {
22047
+ state.usageByMessageId.set(messageId2, usage);
22048
+ }
22049
+ }
22050
+ return true;
22051
+ }
22052
+ const messageId = state.activePartialMessageIdByParentKey.get(parentKey);
22053
+ if (!messageId) {
22054
+ return true;
22055
+ }
22056
+ if (event.type === "message_delta") {
22057
+ const update = copyUsage(event.usage);
22058
+ if (update) {
22059
+ const usage = state.usageByMessageId.get(messageId) ?? {};
22060
+ Object.assign(usage, update);
22061
+ state.usageByMessageId.set(messageId, usage);
22062
+ if (update.output_tokens !== void 0) {
22063
+ state.finalOutputUsageMessageIds.add(messageId);
22064
+ }
22065
+ }
22066
+ } else if (event.type === "message_stop") {
22067
+ state.activePartialMessageIdByParentKey.delete(parentKey);
22068
+ }
22069
+ return true;
22070
+ }
21426
22071
  async function handleStreamMessage(state, message) {
22072
+ if (handlePartialUsageMessage(state, message)) {
22073
+ return;
22074
+ }
21427
22075
  maybeTrackToolUseContext(state, message);
21428
22076
  if (await maybeHandleTaskLifecycleMessage(state, message)) {
21429
22077
  return;
@@ -21470,36 +22118,9 @@ async function handleStreamMessage(state, message) {
21470
22118
  );
21471
22119
  state.currentMessages.push(message);
21472
22120
  }
21473
- if (message.type !== "result" || !message.usage) {
22121
+ if (message.type !== "result") {
21474
22122
  return;
21475
22123
  }
21476
- const finalUsageMetrics = extractUsageFromMessage(message);
21477
- if (state.currentMessages.length > 0 && finalUsageMetrics.completion_tokens !== void 0) {
21478
- const lastMessage = state.currentMessages[state.currentMessages.length - 1];
21479
- if (lastMessage?.message?.usage) {
21480
- const adjustedTokens = finalUsageMetrics.completion_tokens - state.accumulatedOutputTokens;
21481
- if (adjustedTokens >= 0) {
21482
- lastMessage.message.usage.output_tokens = adjustedTokens;
21483
- }
21484
- const resultUsage = message.usage;
21485
- if (resultUsage && typeof resultUsage === "object") {
21486
- const cacheReadTokens = getNumberProperty(
21487
- resultUsage,
21488
- "cache_read_input_tokens"
21489
- );
21490
- if (cacheReadTokens !== void 0) {
21491
- lastMessage.message.usage.cache_read_input_tokens = cacheReadTokens;
21492
- }
21493
- const cacheCreationTokens = getNumberProperty(
21494
- resultUsage,
21495
- "cache_creation_input_tokens"
21496
- );
21497
- if (cacheCreationTokens !== void 0) {
21498
- lastMessage.message.usage.cache_creation_input_tokens = cacheCreationTokens;
21499
- }
21500
- }
21501
- }
21502
- }
21503
22124
  const metadata = {};
21504
22125
  if (message.num_turns !== void 0) {
21505
22126
  metadata.num_turns = message.num_turns;
@@ -21507,8 +22128,12 @@ async function handleStreamMessage(state, message) {
21507
22128
  if (message.session_id !== void 0) {
21508
22129
  metadata.session_id = message.session_id;
21509
22130
  }
21510
- if (Object.keys(metadata).length > 0) {
21511
- state.span.log({ metadata });
22131
+ const metrics = state.options.includePartialMessages ? {} : extractUsage(copyUsage(message.usage), true);
22132
+ if (Object.keys(metadata).length > 0 || Object.keys(metrics).length > 0) {
22133
+ state.span.log({
22134
+ ...Object.keys(metadata).length > 0 ? { metadata } : {},
22135
+ ...Object.keys(metrics).length > 0 ? { metrics } : {}
22136
+ });
21512
22137
  }
21513
22138
  }
21514
22139
  async function finalizeQuerySpan(state) {
@@ -21532,6 +22157,9 @@ async function finalizeQuerySpan(state) {
21532
22157
  llmSpan.end();
21533
22158
  }
21534
22159
  state.activeLlmSpansByParentToolUse.clear();
22160
+ state.activePartialMessageIdByParentKey.clear();
22161
+ state.finalOutputUsageMessageIds.clear();
22162
+ state.usageByMessageId.clear();
21535
22163
  for (const toolSpan of state.activeToolSpans.values()) {
21536
22164
  toolSpan.end();
21537
22165
  }
@@ -21547,7 +22175,7 @@ async function finalizeQuerySpan(state) {
21547
22175
  }
21548
22176
  var ClaudeAgentSDKPlugin = class extends BasePlugin {
21549
22177
  onEnable() {
21550
- this.subscribeToQuery();
22178
+ this.interceptQuery();
21551
22179
  }
21552
22180
  onDisable() {
21553
22181
  for (const unsubscribe of this.unsubscribers) {
@@ -21555,207 +22183,218 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
21555
22183
  }
21556
22184
  this.unsubscribers = [];
21557
22185
  }
21558
- subscribeToQuery() {
21559
- const channel = claudeAgentSDKChannels.query.tracingChannel();
21560
- const spans = /* @__PURE__ */ new WeakMap();
21561
- const handlers = {
21562
- start: (event) => {
21563
- const params = event.arguments[0] ?? {};
21564
- const originalPrompt = params.prompt;
21565
- const options = params.options ?? {};
21566
- const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
21567
- let promptStarted = false;
21568
- let capturedPromptMessages;
21569
- let resolvePromptDone;
21570
- const promptDone = new Promise((resolve) => {
21571
- resolvePromptDone = resolve;
21572
- });
21573
- if (promptIsAsyncIterable) {
21574
- capturedPromptMessages = [];
21575
- const promptStream = originalPrompt;
21576
- params.prompt = (async function* () {
21577
- promptStarted = true;
21578
- try {
21579
- for await (const message of promptStream) {
21580
- capturedPromptMessages.push(message);
21581
- yield message;
21582
- }
21583
- } finally {
21584
- 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;
21585
22206
  }
21586
- })();
21587
- }
21588
- const span = startSpan(
21589
- withSpanInstrumentationName(
21590
- {
21591
- name: "Claude Agent",
21592
- spanAttributes: {
21593
- type: "task" /* TASK */
21594
- }
21595
- },
21596
- INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
21597
- )
21598
- );
21599
- const startTime = getCurrentUnixTimestamp();
21600
- try {
21601
- span.log({
21602
- input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
21603
- metadata: filterSerializableOptions(options)
21604
- });
21605
- } catch (error) {
21606
- console.error("Error extracting input for Claude Agent SDK:", error);
21607
- }
21608
- const activeToolSpans = /* @__PURE__ */ new Map();
21609
- const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
21610
- const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
21611
- const subAgentSpans = /* @__PURE__ */ new Map();
21612
- const endedSubAgentSpans = /* @__PURE__ */ new Set();
21613
- const toolUseToParent = /* @__PURE__ */ new Map();
21614
- const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
21615
- const latestRootLlmParentRef = {
21616
- value: void 0
21617
- };
21618
- const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
21619
- const taskIdToToolUseId = /* @__PURE__ */ new Map();
21620
- const promptMessagesByParentKey = /* @__PURE__ */ new Map();
21621
- const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
21622
- const localToolContext = createClaudeLocalToolContext();
21623
- const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
21624
- const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
21625
- const resolveToolUseParentSpan = async (toolUseID, context) => {
21626
- const trackedParentToolUseId = toolUseToParent.get(toolUseID);
21627
- const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
21628
- const parentKey = llmParentKey(parentToolUseId);
21629
- const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
21630
- const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
21631
- if (!activeLlmSpan && !latestLlmParent) {
21632
- await ensureActiveLlmSpanForParentToolUse(
21633
- span,
21634
- activeLlmSpansByParentToolUse,
21635
- subAgentDetailsByToolUseId,
21636
- activeToolSpans,
21637
- subAgentSpans,
21638
- parentToolUseId,
21639
- getCurrentUnixTimestamp()
21640
- );
21641
- }
21642
- if (parentToolUseId) {
21643
- const subAgentSpan = await ensureSubAgentSpan(
21644
- subAgentDetailsByToolUseId,
21645
- span,
21646
- activeToolSpans,
21647
- subAgentSpans,
21648
- parentToolUseId
21649
- );
21650
- return subAgentSpan.export();
22207
+ } finally {
22208
+ resolvePromptDone?.();
21651
22209
  }
21652
- return span.export();
21653
- };
21654
- localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
21655
- setClaudeLocalToolParentResolver(resolveToolUseParentSpan);
21656
- const optionsWithHooks = injectTracingHooks(
21657
- options,
21658
- resolveToolUseParentSpan,
21659
- activeToolSpans,
21660
- localToolHookNames,
21661
- skipLocalToolHooks,
21662
- subAgentDetailsByToolUseId,
21663
- subAgentSpans,
21664
- endedSubAgentSpans
21665
- );
21666
- params.options = optionsWithHooks;
21667
- event.arguments[0] = params;
21668
- spans.set(event, {
21669
- accumulatedOutputTokens: 0,
21670
- activeLlmSpansByParentToolUse,
21671
- activeToolSpans,
21672
- conversationHistoryByParentKey,
21673
- capturedPromptMessages,
21674
- currentMessageId: void 0,
21675
- currentMessageStartTime: startTime,
21676
- currentMessages: [],
21677
- endedSubAgentSpans,
21678
- finalResults: [],
21679
- options: optionsWithHooks,
21680
- originalPrompt,
21681
- processing: Promise.resolve(),
21682
- promptDone,
21683
- promptMessagesByParentKey,
21684
- promptStarted: () => promptStarted,
21685
- promptSourcePriorityByParentKey,
21686
- span,
21687
- subAgentDetailsByToolUseId,
21688
- subAgentSpans,
21689
- taskIdToToolUseId,
21690
- latestLlmParentBySubAgentToolUse,
21691
- latestRootLlmParentRef,
21692
- toolUseToParent,
21693
- 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)
21694
22228
  });
21695
- },
21696
- end: (event) => {
21697
- const state = spans.get(event);
21698
- if (!state) {
21699
- return;
21700
- }
21701
- const eventResult = bindClaudeLocalToolContextToAsyncIterable(
21702
- event.result,
21703
- state.localToolContext
21704
- );
21705
- if (eventResult === void 0) {
21706
- state.span.end();
21707
- spans.delete(event);
21708
- return;
21709
- }
21710
- if (isAsyncIterable(eventResult)) {
21711
- patchStreamIfNeeded(eventResult, {
21712
- onChunk: (message) => {
21713
- maybeTrackToolUseContext(state, message);
21714
- state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
21715
- console.error(
21716
- "Error processing Claude Agent SDK stream chunk:",
21717
- error
21718
- );
21719
- });
21720
- },
21721
- onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
21722
- spans.delete(event);
21723
- }),
21724
- onError: (error) => state.processing.then(() => {
21725
- state.span.log({
21726
- error: error.message
21727
- });
21728
- }).then(() => finalizeQuerySpan(state)).finally(() => {
21729
- spans.delete(event);
21730
- })
21731
- });
21732
- return;
21733
- }
21734
- try {
21735
- state.span.log({ output: eventResult });
21736
- } catch (error) {
21737
- console.error("Error extracting output for Claude Agent SDK:", error);
21738
- } finally {
21739
- state.span.end();
21740
- 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
+ );
21741
22264
  }
21742
- },
21743
- error: (event) => {
21744
- const state = spans.get(event);
21745
- if (!state || !event.error) {
21746
- return;
22265
+ if (parentToolUseId) {
22266
+ const subAgentSpan = await ensureSubAgentSpan(
22267
+ subAgentDetailsByToolUseId,
22268
+ span,
22269
+ activeToolSpans,
22270
+ subAgentSpans,
22271
+ parentToolUseId
22272
+ );
22273
+ return subAgentSpan.export();
21747
22274
  }
21748
- state.span.log({
21749
- 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))
21750
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 {
21751
22348
  state.span.end();
21752
- spans.delete(event);
21753
22349
  }
21754
22350
  };
21755
- channel.subscribe(handlers);
21756
- this.unsubscribers.push(() => {
21757
- channel.unsubscribe(handlers);
21758
- });
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
+ );
21759
22398
  }
21760
22399
  };
21761
22400
 
@@ -24080,9 +24719,9 @@ function extractEmbedPromptTokenCount(response) {
24080
24719
  let sawAny = false;
24081
24720
  for (const embedding of embeddings) {
24082
24721
  const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
24083
- const tokenCount = embeddingStats?.tokenCount;
24084
- if (typeof tokenCount === "number" && Number.isFinite(tokenCount)) {
24085
- total += tokenCount;
24722
+ const tokenCount2 = embeddingStats?.tokenCount;
24723
+ if (typeof tokenCount2 === "number" && Number.isFinite(tokenCount2)) {
24724
+ total += tokenCount2;
24086
24725
  sawAny = true;
24087
24726
  }
24088
24727
  }
@@ -25697,7 +26336,7 @@ function patchOpenRouterCallModelResult(args) {
25697
26336
  span,
25698
26337
  () => originalMethod.apply(resultLike, args2)
25699
26338
  );
25700
- if (!isAsyncIterable4(stream)) {
26339
+ if (!isAsyncIterable3(stream)) {
25701
26340
  return stream;
25702
26341
  }
25703
26342
  return wrapAsyncIterableWithSpan({
@@ -25892,7 +26531,7 @@ function wrapAsyncIterableWithSpan(args) {
25892
26531
  }
25893
26532
  };
25894
26533
  }
25895
- function isAsyncIterable4(value) {
26534
+ function isAsyncIterable3(value) {
25896
26535
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
25897
26536
  }
25898
26537
  function normalizeError(error) {
@@ -26734,7 +27373,7 @@ function patchOpenRouterCallModelResult2(args) {
26734
27373
  span,
26735
27374
  () => originalMethod.apply(resultLike, args2)
26736
27375
  );
26737
- if (!isAsyncIterable5(stream)) {
27376
+ if (!isAsyncIterable4(stream)) {
26738
27377
  return stream;
26739
27378
  }
26740
27379
  return wrapAsyncIterableWithSpan2({
@@ -26929,7 +27568,7 @@ function wrapAsyncIterableWithSpan2(args) {
26929
27568
  }
26930
27569
  };
26931
27570
  }
26932
- function isAsyncIterable5(value) {
27571
+ function isAsyncIterable4(value) {
26933
27572
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
26934
27573
  }
26935
27574
  function normalizeError2(error) {
@@ -30632,7 +31271,7 @@ function getStringProperty2(obj, key) {
30632
31271
  return typeof value === "string" ? value : void 0;
30633
31272
  }
30634
31273
  function extractMetricsFromUsage(usage) {
30635
- const metrics = {
31274
+ const rawMetrics = {
30636
31275
  prompt_tokens: usage.inputTokens,
30637
31276
  completion_tokens: usage.outputTokens,
30638
31277
  ...extractAnthropicCacheTokens(
@@ -30641,10 +31280,10 @@ function extractMetricsFromUsage(usage) {
30641
31280
  )
30642
31281
  };
30643
31282
  if (usage.reasoningTokens !== void 0) {
30644
- metrics.completion_reasoning_tokens = usage.reasoningTokens;
30645
- metrics.reasoning_tokens = usage.reasoningTokens;
31283
+ rawMetrics.completion_reasoning_tokens = usage.reasoningTokens;
31284
+ rawMetrics.reasoning_tokens = usage.reasoningTokens;
30646
31285
  }
30647
- Object.assign(metrics, finalizeAnthropicTokens(metrics));
31286
+ const metrics = finalizeAnthropicTokens(rawMetrics);
30648
31287
  const metadata = {
30649
31288
  model: usage.model
30650
31289
  };
@@ -31675,6 +32314,9 @@ function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth
31675
32314
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
31676
32315
  var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
31677
32316
  var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
32317
+ var PI_TOOL_EXECUTE_WRAPPED = /* @__PURE__ */ Symbol.for(
32318
+ "braintrust.pi_coding_agent.tool_execute_wrapped"
32319
+ );
31678
32320
  var piPromptContextStore;
31679
32321
  var PiCodingAgentPlugin = class extends BasePlugin {
31680
32322
  activePromptStates = /* @__PURE__ */ new Set();
@@ -31755,6 +32397,7 @@ function startPiPromptRun(event, onFinalize) {
31755
32397
  return void 0;
31756
32398
  }
31757
32399
  installPiAgentInstrumentation(agent);
32400
+ wrapPiToolExecutors(agent.state?.tools);
31758
32401
  const metadata = {
31759
32402
  ...extractSessionMetadata(session),
31760
32403
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -31851,6 +32494,7 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
31851
32494
  if (!state || state.agent !== agent || state.finalized) {
31852
32495
  return invokeOriginal();
31853
32496
  }
32497
+ wrapPiToolExecutors(context.tools);
31854
32498
  const llmState = await startPiLlmSpan(state, model, context, options);
31855
32499
  try {
31856
32500
  const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
@@ -31861,6 +32505,33 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
31861
32505
  }
31862
32506
  };
31863
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
+ }
31864
32535
  async function startPiLlmSpan(state, model, context, options) {
31865
32536
  const metadata = {
31866
32537
  ...extractModelMetadata2(model),
@@ -32032,35 +32703,26 @@ async function startPiToolSpan(state, event) {
32032
32703
  if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
32033
32704
  return;
32034
32705
  }
32035
- const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
32036
32706
  const metadata = {
32037
32707
  "gen_ai.tool.call.id": event.toolCallId,
32038
32708
  "gen_ai.tool.name": event.toolName,
32039
32709
  "pi_coding_agent.tool.name": event.toolName
32040
32710
  };
32041
- try {
32042
- const span = startSpan(
32043
- withSpanInstrumentationName(
32044
- {
32045
- event: {
32046
- input: event.args,
32047
- metadata
32048
- },
32049
- name: event.toolName || "tool",
32050
- parent: await state.span.export(),
32051
- spanAttributes: { type: "tool" /* TOOL */ }
32711
+ const span = startSpan(
32712
+ withSpanInstrumentationName(
32713
+ {
32714
+ event: {
32715
+ input: event.args,
32716
+ metadata
32052
32717
  },
32053
- INSTRUMENTATION_NAMES.PI_CODING_AGENT
32054
- )
32055
- );
32056
- state.activeToolSpans.set(event.toolCallId, {
32057
- restoreAutoInstrumentation,
32058
- span
32059
- });
32060
- } catch (error) {
32061
- restoreAutoInstrumentation();
32062
- throw error;
32063
- }
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 });
32064
32726
  }
32065
32727
  function finishPiToolSpan(state, event) {
32066
32728
  const toolState = state.activeToolSpans.get(event.toolCallId);
@@ -32081,11 +32743,7 @@ function finishPiToolSpan(state, event) {
32081
32743
  output: event.result
32082
32744
  });
32083
32745
  } finally {
32084
- try {
32085
- toolState.span.end();
32086
- } finally {
32087
- toolState.restoreAutoInstrumentation?.();
32088
- }
32746
+ toolState.span.end();
32089
32747
  }
32090
32748
  }
32091
32749
  function finishPiPromptRun(state, error) {
@@ -32156,14 +32814,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
32156
32814
  }
32157
32815
  function finishOpenToolSpans(state, error) {
32158
32816
  for (const [, toolState] of state.activeToolSpans) {
32159
- try {
32160
- safeLog4(toolState.span, {
32161
- error: error ? toLoggedError(error) : "Pi tool did not complete"
32162
- });
32163
- toolState.span.end();
32164
- } finally {
32165
- toolState.restoreAutoInstrumentation?.();
32166
- }
32817
+ safeLog4(toolState.span, {
32818
+ error: error ? toLoggedError(error) : "Pi tool did not complete"
32819
+ });
32820
+ toolState.span.end();
32167
32821
  }
32168
32822
  state.activeToolSpans.clear();
32169
32823
  }
@@ -32462,12 +33116,12 @@ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
32462
33116
  var StrandsAgentSDKPlugin = class extends BasePlugin {
32463
33117
  activeChildParents = /* @__PURE__ */ new WeakMap();
32464
33118
  onEnable() {
32465
- this.subscribeToAgentStream();
32466
- this.subscribeToMultiAgentStream(
33119
+ this.interceptAgentStream();
33120
+ this.interceptMultiAgentStream(
32467
33121
  strandsAgentSDKChannels.graphStream,
32468
33122
  "Graph.stream"
32469
33123
  );
32470
- this.subscribeToMultiAgentStream(
33124
+ this.interceptMultiAgentStream(
32471
33125
  strandsAgentSDKChannels.swarmStream,
32472
33126
  "Swarm.stream"
32473
33127
  );
@@ -32478,143 +33132,109 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
32478
33132
  }
32479
33133
  this.unsubscribers = [];
32480
33134
  }
32481
- subscribeToAgentStream() {
32482
- const channel = strandsAgentSDKChannels.agentStream.tracingChannel();
32483
- const states = /* @__PURE__ */ new WeakMap();
32484
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel);
32485
- const handlers = {
32486
- start: (event) => {
32487
- const state = startAgentStream(event, this.activeChildParents);
32488
- if (state) {
32489
- states.set(event, state);
32490
- }
32491
- },
32492
- end: (event) => {
32493
- const state = states.get(event);
32494
- if (!state) {
32495
- return;
32496
- }
32497
- const result = event.result;
32498
- if (isAsyncIterable(result)) {
32499
- patchStreamIfNeeded(result, {
32500
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
32501
- onChunk: (chunk) => handleAgentStreamEvent(state, chunk),
32502
- onComplete: () => {
32503
- finalizeAgentStream(state);
32504
- states.delete(event);
32505
- },
32506
- onError: (error) => {
32507
- finalizeAgentStream(state, error);
32508
- states.delete(event);
32509
- }
32510
- });
32511
- return;
32512
- }
32513
- finalizeAgentStream(state, void 0, result);
32514
- states.delete(event);
32515
- },
32516
- error: (event) => {
32517
- const state = states.get(event);
32518
- if (!state || !event.error) {
32519
- return;
32520
- }
32521
- finalizeAgentStream(state, event.error);
32522
- states.delete(event);
32523
- }
32524
- };
32525
- channel.subscribe(handlers);
32526
- this.unsubscribers.push(() => {
32527
- unbindAutoInstrumentationSuppression?.();
32528
- channel.unsubscribe(handlers);
32529
- });
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
+ );
32530
33151
  }
32531
- subscribeToMultiAgentStream(channel, operation) {
32532
- const tracingChannel = channel.tracingChannel();
32533
- const states = /* @__PURE__ */ new WeakMap();
32534
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(tracingChannel);
32535
- const handlers = {
32536
- start: (event) => {
32537
- const state = startMultiAgentStream(
32538
- event,
32539
- operation,
32540
- this.activeChildParents
32541
- );
32542
- if (state) {
32543
- states.set(event, state);
32544
- }
32545
- },
32546
- end: (event) => {
32547
- const state = states.get(event);
32548
- if (!state) {
32549
- return;
32550
- }
32551
- const result = event.result;
32552
- if (isAsyncIterable(result)) {
32553
- patchStreamIfNeeded(result, {
32554
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
32555
- onChunk: (chunk) => handleMultiAgentStreamEvent(
32556
- state,
32557
- chunk,
32558
- this.activeChildParents
32559
- ),
32560
- onComplete: () => {
32561
- finalizeMultiAgentStream(state, this.activeChildParents);
32562
- states.delete(event);
32563
- },
32564
- onError: (error) => {
32565
- finalizeMultiAgentStream(state, this.activeChildParents, error);
32566
- states.delete(event);
32567
- }
32568
- });
32569
- return;
32570
- }
32571
- finalizeMultiAgentStream(
32572
- state,
32573
- this.activeChildParents,
32574
- void 0,
32575
- 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
32576
33194
  );
32577
- states.delete(event);
32578
- },
32579
- error: (event) => {
32580
- const state = states.get(event);
32581
- if (!state || !event.error) {
32582
- return;
32583
- }
32584
- finalizeMultiAgentStream(state, this.activeChildParents, event.error);
32585
- states.delete(event);
32586
33195
  }
32587
- };
32588
- tracingChannel.subscribe(handlers);
32589
- this.unsubscribers.push(() => {
32590
- unbindAutoInstrumentationSuppression?.();
32591
- tracingChannel.unsubscribe(handlers);
32592
- });
33196
+ }
33197
+ throw error;
32593
33198
  }
32594
- };
32595
- function startAgentStream(event, activeChildParents) {
32596
- 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) {
32597
33221
  const model = agent?.model;
32598
33222
  const metadata = {
32599
33223
  ...extractAgentMetadata2(agent),
32600
33224
  ...extractModelMetadata3(model),
32601
33225
  "strands.operation": "Agent.stream",
32602
- provider: extractProvider(model),
32603
- ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
33226
+ provider: extractProvider(model)
32604
33227
  };
32605
33228
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
32606
33229
  const attachmentCache = createStrandsAttachmentCache();
32607
- const input = processStrandsInputAttachments(
32608
- event.arguments[0],
32609
- attachmentCache
32610
- );
33230
+ const processedInput = processStrandsInputAttachments(input, attachmentCache);
32611
33231
  const span = parentSpan ? withCurrent(
32612
33232
  parentSpan,
32613
33233
  () => startSpan(
32614
33234
  withSpanInstrumentationName(
32615
33235
  {
32616
33236
  event: {
32617
- input,
33237
+ input: processedInput,
32618
33238
  metadata
32619
33239
  },
32620
33240
  name: formatAgentSpanName(agent),
@@ -32627,7 +33247,7 @@ function startAgentStream(event, activeChildParents) {
32627
33247
  withSpanInstrumentationName(
32628
33248
  {
32629
33249
  event: {
32630
- input,
33250
+ input: processedInput,
32631
33251
  metadata
32632
33252
  },
32633
33253
  name: formatAgentSpanName(agent),
@@ -32645,23 +33265,21 @@ function startAgentStream(event, activeChildParents) {
32645
33265
  startTime: getCurrentUnixTimestamp()
32646
33266
  };
32647
33267
  }
32648
- function startMultiAgentStream(event, operation, activeChildParents) {
32649
- const orchestrator = extractOrchestrator(event);
33268
+ function startMultiAgentStream(input, orchestrator, operation, activeChildParents) {
32650
33269
  const metadata = {
32651
33270
  "strands.operation": operation,
32652
33271
  provider: "strands",
32653
- ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {},
32654
- ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
33272
+ ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
32655
33273
  };
32656
33274
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
32657
- const input = processStrandsInputAttachments(event.arguments[0]);
33275
+ const processedInput = processStrandsInputAttachments(input);
32658
33276
  const span = parentSpan ? withCurrent(
32659
33277
  parentSpan,
32660
33278
  () => startSpan(
32661
33279
  withSpanInstrumentationName(
32662
33280
  {
32663
33281
  event: {
32664
- input,
33282
+ input: processedInput,
32665
33283
  metadata
32666
33284
  },
32667
33285
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -32674,7 +33292,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
32674
33292
  withSpanInstrumentationName(
32675
33293
  {
32676
33294
  event: {
32677
- input,
33295
+ input: processedInput,
32678
33296
  metadata
32679
33297
  },
32680
33298
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -33045,12 +33663,12 @@ function finalizeMultiAgentStream(state, activeChildParents, error, output) {
33045
33663
  });
33046
33664
  state.span.end();
33047
33665
  }
33048
- function extractAgent(event) {
33049
- const candidate = event.agent ?? event.self;
33666
+ function extractAgent(agent, self) {
33667
+ const candidate = agent ?? self;
33050
33668
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
33051
33669
  }
33052
- function extractOrchestrator(event) {
33053
- const candidate = event.orchestrator ?? event.self;
33670
+ function extractOrchestrator(orchestrator, self) {
33671
+ const candidate = orchestrator ?? self;
33054
33672
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
33055
33673
  }
33056
33674
  function extractAgentMetadata2(agent) {
@@ -33437,6 +34055,296 @@ function logInstrumentationError5(context, error) {
33437
34055
  debugLogger.debug(`${context}:`, error);
33438
34056
  }
33439
34057
 
34058
+ // src/instrumentation/plugins/voyageai-plugin.ts
34059
+ var RERANK_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
34060
+ "model",
34061
+ "returnDocuments",
34062
+ "topK",
34063
+ "truncation"
34064
+ ]);
34065
+ var VoyageAIPlugin = class extends BasePlugin {
34066
+ onEnable() {
34067
+ this.unsubscribers.push(
34068
+ interceptVoyageAICall(
34069
+ voyageAIChannels.embed,
34070
+ "voyageai.embed",
34071
+ extractTextEmbeddingInput,
34072
+ summarizeEmbeddingOutput,
34073
+ extractEmbeddingUsageMetrics
34074
+ ),
34075
+ interceptVoyageAICall(
34076
+ voyageAIChannels.multimodalEmbed,
34077
+ "voyageai.multimodalEmbed",
34078
+ extractMultimodalEmbeddingInput,
34079
+ summarizeEmbeddingOutput,
34080
+ extractEmbeddingUsageMetrics
34081
+ ),
34082
+ interceptVoyageAICall(
34083
+ voyageAIChannels.rerank,
34084
+ "voyageai.rerank",
34085
+ extractRerankInput,
34086
+ summarizeRerankOutput
34087
+ ),
34088
+ interceptVoyageAICall(
34089
+ voyageAIChannels.contextualizedEmbed,
34090
+ "voyageai.contextualizedEmbed",
34091
+ extractContextualizedEmbeddingInput,
34092
+ summarizeContextualizedEmbeddingOutput,
34093
+ extractEmbeddingUsageMetrics
34094
+ )
34095
+ );
34096
+ }
34097
+ onDisable() {
34098
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
34099
+ }
34100
+ };
34101
+ function interceptVoyageAICall(channel, name, extractInput2, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
34102
+ return channel.intercept((target, thisArg, args) => {
34103
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
34104
+ if (isAutoInstrumentationSuppressed()) {
34105
+ return invokeTarget();
34106
+ }
34107
+ let span;
34108
+ try {
34109
+ const { input, metadata } = extractInput2(args);
34110
+ span = startSpan(
34111
+ withSpanInstrumentationName(
34112
+ {
34113
+ event: { input, metadata },
34114
+ name,
34115
+ spanAttributes: { type: "llm" /* LLM */ }
34116
+ },
34117
+ INSTRUMENTATION_NAMES.VOYAGEAI
34118
+ )
34119
+ );
34120
+ } catch (error) {
34121
+ debugLogger.error(`Error starting span for ${name}:`, error);
34122
+ return invokeTarget();
34123
+ }
34124
+ let result;
34125
+ try {
34126
+ result = withCurrent(
34127
+ span,
34128
+ () => runWithAutoInstrumentationSuppressed(invokeTarget)
34129
+ );
34130
+ } catch (error) {
34131
+ finishVoyageAISpan(span, name, () => span.log({ error }));
34132
+ throw error;
34133
+ }
34134
+ void Promise.resolve(result).then(
34135
+ (value) => finishVoyageAISpan(span, name, () => {
34136
+ const metadata = extractResponseMetadata3(value);
34137
+ span.log({
34138
+ output: extractOutput2(value),
34139
+ ...metadata ? { metadata } : {},
34140
+ metrics: extractMetrics2(value)
34141
+ });
34142
+ }),
34143
+ (error) => finishVoyageAISpan(span, name, () => span.log({ error }))
34144
+ );
34145
+ return result;
34146
+ });
34147
+ }
34148
+ function finishVoyageAISpan(span, name, log2) {
34149
+ try {
34150
+ log2();
34151
+ } catch (error) {
34152
+ debugLogger.error(`Error logging span for ${name}:`, error);
34153
+ }
34154
+ try {
34155
+ span.end();
34156
+ } catch (error) {
34157
+ debugLogger.error(`Error ending span for ${name}:`, error);
34158
+ }
34159
+ }
34160
+ function getRequestArg2(args) {
34161
+ if (Array.isArray(args)) {
34162
+ return isObject(args[0]) ? args[0] : void 0;
34163
+ }
34164
+ if (!isObject(args)) {
34165
+ return void 0;
34166
+ }
34167
+ const firstArg = Reflect.get(args, "0");
34168
+ return isObject(firstArg) ? firstArg : void 0;
34169
+ }
34170
+ function pickMetadata(request, allowlist) {
34171
+ const metadata = {};
34172
+ if (request) {
34173
+ for (const key of allowlist) {
34174
+ if (!Object.hasOwn(request, key)) {
34175
+ continue;
34176
+ }
34177
+ const value = request[key];
34178
+ if (value !== void 0) {
34179
+ metadata[key] = value;
34180
+ }
34181
+ }
34182
+ }
34183
+ return {
34184
+ ...metadata,
34185
+ provider: "voyage"
34186
+ };
34187
+ }
34188
+ function buildEmbeddingInput(inputs, request) {
34189
+ const outputDimensions = request?.outputDimension;
34190
+ return {
34191
+ inputs,
34192
+ ...typeof outputDimensions === "number" && Number.isFinite(outputDimensions) ? { output_dimensions: outputDimensions } : {}
34193
+ };
34194
+ }
34195
+ function embeddingMetadata(request) {
34196
+ return {
34197
+ ...typeof request?.model === "string" ? { model: request.model } : {},
34198
+ provider: "voyage"
34199
+ };
34200
+ }
34201
+ function extractTextEmbeddingInput(args) {
34202
+ const request = getRequestArg2(args);
34203
+ const rawInput = request?.input;
34204
+ const values = Array.isArray(rawInput) ? rawInput : [rawInput];
34205
+ return {
34206
+ input: buildEmbeddingInput(
34207
+ values.flatMap(
34208
+ (value) => typeof value === "string" ? [{ content: value }] : []
34209
+ ),
34210
+ request
34211
+ ),
34212
+ metadata: embeddingMetadata(request)
34213
+ };
34214
+ }
34215
+ function extractContextualizedEmbeddingInput(args) {
34216
+ const request = getRequestArg2(args);
34217
+ const rawInputs = request?.inputs;
34218
+ const values = Array.isArray(rawInputs) ? rawInputs.flatMap((value) => Array.isArray(value) ? value : [value]) : [];
34219
+ return {
34220
+ input: buildEmbeddingInput(
34221
+ values.flatMap(
34222
+ (value) => typeof value === "string" ? [{ content: value }] : []
34223
+ ),
34224
+ request
34225
+ ),
34226
+ metadata: embeddingMetadata(request)
34227
+ };
34228
+ }
34229
+ function extractMultimodalEmbeddingInput(args) {
34230
+ const request = getRequestArg2(args);
34231
+ const rawInputs = request?.inputs;
34232
+ const inputs = Array.isArray(rawInputs) ? rawInputs.map((rawInput) => {
34233
+ const rawContent = isObject(rawInput) ? rawInput.content : void 0;
34234
+ return {
34235
+ content: Array.isArray(rawContent) ? rawContent.flatMap(normalizeMultimodalContentPart) : []
34236
+ };
34237
+ }) : [];
34238
+ const input = buildEmbeddingInput(inputs, request);
34239
+ const processedInput = processInputAttachments(input);
34240
+ return {
34241
+ input: hasInlineEmbeddingMedia(processedInput) ? input : processedInput,
34242
+ metadata: embeddingMetadata(request)
34243
+ };
34244
+ }
34245
+ function normalizeMultimodalContentPart(part) {
34246
+ if (!isObject(part) || typeof part.type !== "string") {
34247
+ return [];
34248
+ }
34249
+ if (part.type === "text") {
34250
+ return typeof part.text === "string" ? [{ type: "text", text: part.text }] : [];
34251
+ }
34252
+ const camelCaseField = {
34253
+ image_base64: "imageBase64",
34254
+ image_url: "imageUrl",
34255
+ video_base64: "videoBase64",
34256
+ video_url: "videoUrl"
34257
+ };
34258
+ const field = camelCaseField[part.type];
34259
+ if (!field) {
34260
+ return [];
34261
+ }
34262
+ const data = typeof part[field] === "string" ? part[field] : part[part.type];
34263
+ if (typeof data !== "string") {
34264
+ return [];
34265
+ }
34266
+ return part.type.startsWith("image_") ? [{ type: "image_url", image_url: { url: data } }] : [{ type: "file", file: { file_data: data } }];
34267
+ }
34268
+ function hasInlineEmbeddingMedia(input) {
34269
+ return input.inputs.some(
34270
+ ({ content }) => Array.isArray(content) ? content.some((part) => {
34271
+ const value = part.type === "image_url" ? part.image_url.url : part.type === "file" ? part.file.file_data : void 0;
34272
+ return typeof value === "string" && value.startsWith("data:");
34273
+ }) : false
34274
+ );
34275
+ }
34276
+ function extractRerankInput(args) {
34277
+ const request = getRequestArg2(args);
34278
+ const documents = request?.documents;
34279
+ return {
34280
+ input: {
34281
+ documents,
34282
+ query: request?.query
34283
+ },
34284
+ metadata: {
34285
+ ...pickMetadata(request, RERANK_METADATA_ALLOWLIST),
34286
+ ...Array.isArray(documents) ? { document_count: documents.length } : {}
34287
+ }
34288
+ };
34289
+ }
34290
+ function extractResponseMetadata3(result) {
34291
+ if (!isObject(result)) {
34292
+ return void 0;
34293
+ }
34294
+ const rawResponse = isObject(result.rawResponse) ? result.rawResponse : void 0;
34295
+ const model = typeof result.model === "string" ? result.model : typeof rawResponse?.model === "string" ? rawResponse.model : void 0;
34296
+ return model ? { model } : void 0;
34297
+ }
34298
+ function summarizeEmbeddingOutput(result) {
34299
+ return {
34300
+ count: isObject(result) && Array.isArray(result.data) ? result.data.length : 0
34301
+ };
34302
+ }
34303
+ function summarizeRerankOutput(result) {
34304
+ if (!isObject(result) || !Array.isArray(result.data)) {
34305
+ return void 0;
34306
+ }
34307
+ return result.data.slice(0, 100).map((item) => ({
34308
+ index: isObject(item) ? item.index : void 0,
34309
+ relevance_score: isObject(item) ? (typeof item.relevanceScore === "number" ? item.relevanceScore : item.relevance_score) ?? null : null
34310
+ }));
34311
+ }
34312
+ function summarizeContextualizedEmbeddingOutput(result) {
34313
+ if (!isObject(result)) {
34314
+ return { count: 0 };
34315
+ }
34316
+ if (Array.isArray(result.results)) {
34317
+ return {
34318
+ count: result.results.reduce(
34319
+ (count, item) => count + (isObject(item) && Array.isArray(item.embeddings) ? item.embeddings.length : 0),
34320
+ 0
34321
+ )
34322
+ };
34323
+ }
34324
+ if (!Array.isArray(result.data)) {
34325
+ return { count: 0 };
34326
+ }
34327
+ return {
34328
+ count: result.data.reduce(
34329
+ (count, item) => count + (isObject(item) && Array.isArray(item.data) ? item.data.length : 0),
34330
+ 0
34331
+ )
34332
+ };
34333
+ }
34334
+ function extractEmbeddingUsageMetrics(result) {
34335
+ const metrics = extractUsageMetrics3(result);
34336
+ return typeof metrics.tokens === "number" ? { prompt_tokens: metrics.tokens, tokens: metrics.tokens } : {};
34337
+ }
34338
+ function extractUsageMetrics3(result) {
34339
+ if (!isObject(result)) {
34340
+ return {};
34341
+ }
34342
+ const rawResponse = isObject(result.rawResponse) ? result.rawResponse : void 0;
34343
+ const usage = isObject(result.usage) ? result.usage : isObject(rawResponse?.usage) ? rawResponse.usage : void 0;
34344
+ const tokens = typeof result.totalTokens === "number" ? result.totalTokens : usage?.totalTokens ?? usage?.total_tokens;
34345
+ return typeof tokens === "number" && Number.isFinite(tokens) && tokens >= 0 ? { tokens } : {};
34346
+ }
34347
+
33440
34348
  // src/instrumentation/plugins/cloudflare-ai-chat-instrumentation.ts
33441
34349
  var wrappedTurnRunners = /* @__PURE__ */ new WeakSet();
33442
34350
  var wrappedResponseHooks = /* @__PURE__ */ new WeakSet();
@@ -33987,6 +34895,7 @@ var BraintrustPlugin = class extends BasePlugin {
33987
34895
  langSmithPlugin = null;
33988
34896
  piCodingAgentPlugin = null;
33989
34897
  strandsAgentSDKPlugin = null;
34898
+ voyageAIPlugin = null;
33990
34899
  cloudflareAIChatPlugin = null;
33991
34900
  cloudflareAgentsPlugin = null;
33992
34901
  constructor(config = {}) {
@@ -34061,6 +34970,10 @@ var BraintrustPlugin = class extends BasePlugin {
34061
34970
  this.coherePlugin = new CoherePlugin();
34062
34971
  this.coherePlugin.enable();
34063
34972
  }
34973
+ if (integrations.voyageai !== false) {
34974
+ this.voyageAIPlugin = new VoyageAIPlugin();
34975
+ this.voyageAIPlugin.enable();
34976
+ }
34064
34977
  if (integrations.groq !== false) {
34065
34978
  this.groqPlugin = new GroqPlugin();
34066
34979
  this.groqPlugin.enable();
@@ -34177,6 +35090,10 @@ var BraintrustPlugin = class extends BasePlugin {
34177
35090
  this.coherePlugin.disable();
34178
35091
  this.coherePlugin = null;
34179
35092
  }
35093
+ if (this.voyageAIPlugin) {
35094
+ this.voyageAIPlugin.disable();
35095
+ this.voyageAIPlugin = null;
35096
+ }
34180
35097
  if (this.groqPlugin) {
34181
35098
  this.groqPlugin.disable();
34182
35099
  this.groqPlugin = null;
@@ -34543,7 +35460,7 @@ function wrapMastraAgent(agent, _options) {
34543
35460
 
34544
35461
  // src/node/config.ts
34545
35462
  import { AsyncLocalStorage } from "node:async_hooks";
34546
- import * as path from "node:path";
35463
+ import * as path2 from "node:path";
34547
35464
  import * as fs from "node:fs/promises";
34548
35465
  import * as os from "node:os";
34549
35466
  import * as fsSync from "node:fs";
@@ -34552,34 +35469,93 @@ import { promisify } from "node:util";
34552
35469
  import * as zlib from "node:zlib";
34553
35470
  import * as dotenv from "dotenv";
34554
35471
 
34555
- // src/gitutil.ts
34556
- import { simpleGit } from "simple-git";
34557
- var COMMON_BASE_BRANCHES = ["main", "master", "develop"];
34558
- async function currentRepo() {
34559
- try {
34560
- const git = simpleGit();
34561
- if (await git.checkIsRepo()) {
34562
- return git;
34563
- } else {
34564
- return null;
35472
+ // src/git-command.ts
35473
+ import { execFile } from "node:child_process";
35474
+ import { constants } from "node:fs";
35475
+ import { access } from "node:fs/promises";
35476
+ import * as path from "node:path";
35477
+ var GIT_EXECUTABLE_NAMES = process.platform === "win32" ? ["git.exe", "git"] : ["git"];
35478
+ var GIT_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
35479
+ var gitExecutablePromise;
35480
+ function executableSearchPath() {
35481
+ return Object.entries(process.env).find(
35482
+ ([name]) => name.toUpperCase() === "PATH"
35483
+ )?.[1];
35484
+ }
35485
+ async function findGitExecutable(searchPath = executableSearchPath()) {
35486
+ if (!searchPath) {
35487
+ return void 0;
35488
+ }
35489
+ for (const rawSearchDir of searchPath.split(path.delimiter)) {
35490
+ const searchDir = rawSearchDir.trim().replace(/^"(.*)"$/, "$1");
35491
+ if (!path.isAbsolute(searchDir)) {
35492
+ continue;
35493
+ }
35494
+ for (const executableName of GIT_EXECUTABLE_NAMES) {
35495
+ const candidate = path.join(searchDir, executableName);
35496
+ try {
35497
+ await access(
35498
+ candidate,
35499
+ process.platform === "win32" ? constants.F_OK : constants.X_OK
35500
+ );
35501
+ return candidate;
35502
+ } catch {
35503
+ }
34565
35504
  }
34566
- } catch {
34567
- return null;
34568
35505
  }
35506
+ return void 0;
35507
+ }
35508
+ async function resolveGitExecutable() {
35509
+ gitExecutablePromise ??= findGitExecutable();
35510
+ return await gitExecutablePromise;
34569
35511
  }
35512
+ async function runGitCommand(args, options = {}) {
35513
+ const executable = await resolveGitExecutable();
35514
+ if (!executable) {
35515
+ throw new Error("Could not find a git executable on PATH");
35516
+ }
35517
+ return await new Promise((resolve, reject) => {
35518
+ execFile(
35519
+ executable,
35520
+ args,
35521
+ {
35522
+ cwd: options.cwd,
35523
+ encoding: "utf8",
35524
+ maxBuffer: GIT_MAX_BUFFER_BYTES
35525
+ },
35526
+ (error, stdout) => {
35527
+ if (error) {
35528
+ reject(error);
35529
+ } else {
35530
+ resolve(stdout);
35531
+ }
35532
+ }
35533
+ );
35534
+ });
35535
+ }
35536
+
35537
+ // src/gitutil.ts
35538
+ var COMMON_BASE_BRANCHES = ["main", "master", "develop"];
34570
35539
  var _baseBranch = null;
34571
35540
  async function getBaseBranch(remote = void 0) {
34572
35541
  if (_baseBranch === null) {
34573
- const git = await currentRepo();
34574
- if (git === null) {
35542
+ const repoPath = await currentRepoPath();
35543
+ if (!repoPath) {
34575
35544
  throw new Error("Not in a git repo");
34576
35545
  }
34577
- const remoteName = remote ?? (await git.getRemotes())[0]?.name;
35546
+ const runGit = async (args) => await runGitCommand(args, { cwd: repoPath });
35547
+ const remoteName = remote ?? (await runGit(["remote"])).trim().split(/\r?\n/)[0];
34578
35548
  if (!remoteName) {
34579
35549
  throw new Error("No remote found");
34580
35550
  }
34581
35551
  let branch = null;
34582
- const repoBranches = new Set((await git.branchLocal()).all);
35552
+ const repoBranches = new Set(
35553
+ (await runGit([
35554
+ "for-each-ref",
35555
+ "--format=%(refname:short)",
35556
+ "refs/heads/"
35557
+ ])).trim().split(/\r?\n/)
35558
+ );
34583
35559
  const matchingBaseBranches = COMMON_BASE_BRANCHES.filter(
34584
35560
  (b) => repoBranches.has(b)
34585
35561
  );
@@ -34587,7 +35563,7 @@ async function getBaseBranch(remote = void 0) {
34587
35563
  branch = matchingBaseBranches[0];
34588
35564
  } else {
34589
35565
  try {
34590
- const remoteInfo = await git.remote(["show", remoteName]);
35566
+ const remoteInfo = await runGit(["remote", "show", remoteName]);
34591
35567
  if (!remoteInfo) {
34592
35568
  throw new Error(`Could not find remote ${remoteName}`);
34593
35569
  }
@@ -34605,27 +35581,28 @@ async function getBaseBranch(remote = void 0) {
34605
35581
  return _baseBranch;
34606
35582
  }
34607
35583
  async function getBaseBranchAncestor(remote = void 0) {
34608
- const git = await currentRepo();
34609
- if (git === null) {
35584
+ const repoPath = await currentRepoPath();
35585
+ if (!repoPath) {
34610
35586
  throw new Error("Not in a git repo");
34611
35587
  }
34612
35588
  const { remote: remoteName, branch: baseBranch } = await getBaseBranch(remote);
34613
- const isDirty = (await git.diffSummary()).files.length > 0;
35589
+ const isDirty = (await runGitCommand(["diff", "--name-only"], {
35590
+ cwd: repoPath
35591
+ })).trim().length > 0;
34614
35592
  const head = isDirty ? "HEAD" : "HEAD^";
34615
35593
  try {
34616
- const ancestor = await git.raw([
34617
- "merge-base",
34618
- head,
34619
- `${remoteName}/${baseBranch}`
34620
- ]);
35594
+ const ancestor = await runGitCommand(
35595
+ ["merge-base", head, `${remoteName}/${baseBranch}`],
35596
+ { cwd: repoPath }
35597
+ );
34621
35598
  return ancestor.trim();
34622
35599
  } catch {
34623
35600
  return void 0;
34624
35601
  }
34625
35602
  }
34626
35603
  async function getPastNAncestors(n = 1e3, remote = void 0) {
34627
- const git = await currentRepo();
34628
- if (git === null) {
35604
+ const repoPath = await currentRepoPath();
35605
+ if (!repoPath) {
34629
35606
  return [];
34630
35607
  }
34631
35608
  let ancestor = void 0;
@@ -34640,8 +35617,10 @@ async function getPastNAncestors(n = 1e3, remote = void 0) {
34640
35617
  if (!ancestor) {
34641
35618
  return [];
34642
35619
  }
34643
- const commits = await git.log({ from: ancestor, to: "HEAD", maxCount: n });
34644
- return commits.all.slice(0, n).map((c) => c.hash);
35620
+ const commits = (await runGitCommand(["rev-list", `--max-count=${n}`, `${ancestor}..HEAD`], {
35621
+ cwd: repoPath
35622
+ })).trim();
35623
+ return commits ? commits.split(/\r?\n/).slice(0, n) : [];
34645
35624
  }
34646
35625
  async function attempt(fn) {
34647
35626
  try {
@@ -34672,9 +35651,14 @@ async function getRepoInfo(settings) {
34672
35651
  });
34673
35652
  return sanitized;
34674
35653
  }
35654
+ async function currentRepoPath() {
35655
+ return await attempt(
35656
+ async () => (await runGitCommand(["rev-parse", "--show-toplevel"])).trim()
35657
+ );
35658
+ }
34675
35659
  async function repoInfo() {
34676
- const git = await currentRepo();
34677
- if (git === null) {
35660
+ const repoPath = await currentRepoPath();
35661
+ if (!repoPath) {
34678
35662
  return void 0;
34679
35663
  }
34680
35664
  let commit = void 0;
@@ -34685,29 +35669,32 @@ async function repoInfo() {
34685
35669
  let tag = void 0;
34686
35670
  let branch = void 0;
34687
35671
  let git_diff = void 0;
34688
- const dirty = (await git.diffSummary()).files.length > 0;
34689
- commit = await attempt(async () => await git.revparse(["HEAD"]));
35672
+ const runGit = async (args) => await runGitCommand(args, { cwd: repoPath });
35673
+ const dirty = (await runGit(["diff", "--name-only"])).trim().length > 0;
35674
+ commit = await attempt(
35675
+ async () => (await runGit(["rev-parse", "HEAD"])).trim()
35676
+ );
34690
35677
  commit_message = await attempt(
34691
- async () => (await git.raw(["log", "-1", "--pretty=%B"])).trim()
35678
+ async () => (await runGit(["log", "-1", "--pretty=%B"])).trim()
34692
35679
  );
34693
35680
  commit_time = await attempt(
34694
- async () => (await git.raw(["log", "-1", "--pretty=%cI"])).trim()
35681
+ async () => (await runGit(["log", "-1", "--pretty=%cI"])).trim()
34695
35682
  );
34696
35683
  author_name = await attempt(
34697
- async () => (await git.raw(["log", "-1", "--pretty=%aN"])).trim()
35684
+ async () => (await runGit(["log", "-1", "--pretty=%aN"])).trim()
34698
35685
  );
34699
35686
  author_email = await attempt(
34700
- async () => (await git.raw(["log", "-1", "--pretty=%aE"])).trim()
35687
+ async () => (await runGit(["log", "-1", "--pretty=%aE"])).trim()
34701
35688
  );
34702
35689
  tag = await attempt(
34703
- async () => (await git.raw(["describe", "--tags", "--exact-match", "--always"])).trim()
35690
+ async () => (await runGit(["describe", "--tags", "--exact-match", "--always"])).trim()
34704
35691
  );
34705
35692
  branch = await attempt(
34706
- async () => (await git.raw(["rev-parse", "--abbrev-ref", "HEAD"])).trim()
35693
+ async () => (await runGit(["rev-parse", "--abbrev-ref", "HEAD"])).trim()
34707
35694
  );
34708
35695
  if (dirty) {
34709
35696
  git_diff = await attempt(
34710
- async () => truncateToByteLimit(await git.raw(["--no-ext-diff", "diff", "HEAD"]))
35697
+ async () => truncateToByteLimit(await runGit(["diff", "--no-ext-diff", "HEAD"]))
34711
35698
  );
34712
35699
  }
34713
35700
  return {
@@ -34788,9 +35775,9 @@ function configureNode() {
34788
35775
  return value;
34789
35776
  }
34790
35777
  const envPaths = [];
34791
- for (let dir = process.cwd(), depth = 0; depth <= BRAINTRUST_ENV_SEARCH_PARENT_LIMIT; dir = path.dirname(dir), depth++) {
34792
- envPaths.push(path.join(dir, ".env.braintrust"));
34793
- if (path.dirname(dir) === dir) {
35778
+ for (let dir = process.cwd(), depth = 0; depth <= BRAINTRUST_ENV_SEARCH_PARENT_LIMIT; dir = path2.dirname(dir), depth++) {
35779
+ envPaths.push(path2.join(dir, ".env.braintrust"));
35780
+ if (path2.dirname(dir) === dir) {
34794
35781
  break;
34795
35782
  }
34796
35783
  }
@@ -34832,10 +35819,10 @@ function configureNode() {
34832
35819
  isomorph_default.processOn = (event, handler) => {
34833
35820
  process.on(event, handler);
34834
35821
  };
34835
- isomorph_default.basename = path.basename;
35822
+ isomorph_default.basename = path2.basename;
34836
35823
  isomorph_default.writeln = (text) => process.stdout.write(text + "\n");
34837
- isomorph_default.pathJoin = path.join;
34838
- isomorph_default.pathDirname = path.dirname;
35824
+ isomorph_default.pathJoin = path2.join;
35825
+ isomorph_default.pathDirname = path2.dirname;
34839
35826
  isomorph_default.mkdir = fs.mkdir;
34840
35827
  isomorph_default.writeFile = fs.writeFile;
34841
35828
  isomorph_default.readFile = fs.readFile;
@@ -34870,8 +35857,8 @@ function configureNode() {
34870
35857
  registry.enable();
34871
35858
  }
34872
35859
  function getNearestBraintrustEnvValue(name) {
34873
- for (let dir = process.cwd(), depth = 0; depth <= BRAINTRUST_ENV_SEARCH_PARENT_LIMIT; dir = path.dirname(dir), depth++) {
34874
- const envPath = path.join(dir, ".env.braintrust");
35860
+ for (let dir = process.cwd(), depth = 0; depth <= BRAINTRUST_ENV_SEARCH_PARENT_LIMIT; dir = path2.dirname(dir), depth++) {
35861
+ const envPath = path2.join(dir, ".env.braintrust");
34875
35862
  try {
34876
35863
  const parsed = dotenv.parse(fsSync.readFileSync(envPath, "utf8"));
34877
35864
  const value = parsed[name];
@@ -34881,7 +35868,7 @@ function getNearestBraintrustEnvValue(name) {
34881
35868
  return void 0;
34882
35869
  }
34883
35870
  }
34884
- if (path.dirname(dir) === dir) {
35871
+ if (path2.dirname(dir) === dir) {
34885
35872
  break;
34886
35873
  }
34887
35874
  }
@@ -34930,7 +35917,6 @@ async function summarizeAndFlush(experiment, options) {
34930
35917
  }
34931
35918
 
34932
35919
  export {
34933
- debugLogger,
34934
35920
  IDGenerator,
34935
35921
  UUIDGenerator,
34936
35922
  OTELIDGenerator,
@@ -34939,9 +35925,10 @@ export {
34939
35925
  TRACESTATE_HEADER,
34940
35926
  BAGGAGE_HEADER,
34941
35927
  BRAINTRUST_PARENT_KEY,
35928
+ uint8ArrayToBase64,
35929
+ base64ToUint8Array,
34942
35930
  spanObjectTypeV3ToTypedString,
34943
35931
  isObject,
34944
- mergeDicts,
34945
35932
  slugify,
34946
35933
  SpanComponentsV4,
34947
35934
  makeScorerPropagatedEvent,
@@ -34992,6 +35979,7 @@ export {
34992
35979
  ReadonlyAttachment,
34993
35980
  JSONAttachment,
34994
35981
  updateSpan,
35982
+ _internalResumeSpan,
34995
35983
  spanComponentsToObjectId,
34996
35984
  ERR_PERMALINK,
34997
35985
  permalink,
@@ -35053,6 +36041,7 @@ export {
35053
36041
  X_CACHED_HEADER,
35054
36042
  parseCachedHeader,
35055
36043
  finalizeAnthropicTokens,
36044
+ toNumericMetrics,
35056
36045
  extractAnthropicCacheTokens,
35057
36046
  collectAnthropicSession,
35058
36047
  zodToJsonSchema,