braintrust 3.25.0 → 3.27.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 (79) hide show
  1. package/NOTICE +6 -0
  2. package/dev/dist/index.d.mts +130 -2
  3. package/dev/dist/index.d.ts +130 -2
  4. package/dev/dist/index.js +4133 -1421
  5. package/dev/dist/index.mjs +3242 -530
  6. package/dist/apply-auto-instrumentation.js +526 -426
  7. package/dist/apply-auto-instrumentation.mjs +329 -229
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +1198 -364
  9. package/dist/auto-instrumentations/bundler/esbuild.d.mts +4 -4
  10. package/dist/auto-instrumentations/bundler/esbuild.d.ts +4 -4
  11. package/dist/auto-instrumentations/bundler/esbuild.mjs +6 -8
  12. package/dist/auto-instrumentations/bundler/next.cjs +1227 -413
  13. package/dist/auto-instrumentations/bundler/next.mjs +7 -29
  14. package/dist/auto-instrumentations/bundler/rollup.cjs +1198 -364
  15. package/dist/auto-instrumentations/bundler/rollup.d.mts +4 -4
  16. package/dist/auto-instrumentations/bundler/rollup.d.ts +4 -4
  17. package/dist/auto-instrumentations/bundler/rollup.mjs +6 -8
  18. package/dist/auto-instrumentations/bundler/vite.cjs +1249 -387
  19. package/dist/auto-instrumentations/bundler/vite.d.mts +4 -4
  20. package/dist/auto-instrumentations/bundler/vite.d.ts +4 -4
  21. package/dist/auto-instrumentations/bundler/vite.mjs +34 -8
  22. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +1368 -324
  23. package/dist/auto-instrumentations/bundler/webpack-loader.d.ts +20 -12
  24. package/dist/auto-instrumentations/bundler/webpack.cjs +1198 -364
  25. package/dist/auto-instrumentations/bundler/webpack.d.mts +4 -4
  26. package/dist/auto-instrumentations/bundler/webpack.d.ts +4 -4
  27. package/dist/auto-instrumentations/bundler/webpack.mjs +6 -4
  28. package/dist/auto-instrumentations/chunk-2AMDGD65.mjs +1396 -0
  29. package/dist/auto-instrumentations/{chunk-7P6563SW.mjs → chunk-BW33ULMW.mjs} +2 -6
  30. package/dist/auto-instrumentations/{chunk-M6DLIJ2Z.mjs → chunk-I55G56ZL.mjs} +114 -221
  31. package/dist/auto-instrumentations/chunk-JPUFNW7X.mjs +649 -0
  32. package/dist/auto-instrumentations/{chunk-JPVCUKTY.mjs → chunk-XEYKUBLY.mjs} +191 -73
  33. package/dist/auto-instrumentations/{chunk-CZ24KNHT.mjs → chunk-ZNHTSSGI.mjs} +231 -69
  34. package/dist/auto-instrumentations/hook.mjs +406 -183
  35. package/dist/auto-instrumentations/index.cjs +853 -49
  36. package/dist/auto-instrumentations/index.d.mts +10 -2
  37. package/dist/auto-instrumentations/index.d.ts +10 -2
  38. package/dist/auto-instrumentations/index.mjs +10 -1
  39. package/dist/auto-instrumentations/loader/cjs-patch.cjs +566 -221
  40. package/dist/auto-instrumentations/loader/cjs-patch.d.mts +2 -2
  41. package/dist/auto-instrumentations/loader/cjs-patch.d.ts +2 -2
  42. package/dist/auto-instrumentations/loader/cjs-patch.mjs +3 -2
  43. package/dist/auto-instrumentations/loader/esm-hook.mjs +1 -1
  44. package/dist/auto-instrumentations/plugin-B-aZh7EP.d.ts +30 -0
  45. package/dist/auto-instrumentations/plugin-Bnj4E_6B.d.mts +30 -0
  46. package/dist/auto-instrumentations/{types-RNPaKi9o.d.mts → types-C1fVeiCp.d.mts} +1 -1
  47. package/dist/auto-instrumentations/{types-RNPaKi9o.d.ts → types-C1fVeiCp.d.ts} +1 -1
  48. package/dist/browser.d.mts +871 -199
  49. package/dist/browser.d.ts +871 -199
  50. package/dist/browser.js +3737 -549
  51. package/dist/browser.mjs +3737 -549
  52. package/dist/{chunk-ABR2QWDP.mjs → chunk-CZM5JIQL.mjs} +788 -132
  53. package/dist/{chunk-P25IOOU4.js → chunk-MF7NU6BT.js} +795 -139
  54. package/dist/{chunk-GSIDVFE6.js → chunk-QRHGVBKU.js} +3580 -1463
  55. package/dist/{chunk-2SANLSWX.mjs → chunk-YKD22IMR.mjs} +2505 -388
  56. package/dist/cli.js +3244 -533
  57. package/dist/edge-light.d.mts +1 -1
  58. package/dist/edge-light.d.ts +1 -1
  59. package/dist/edge-light.js +3737 -552
  60. package/dist/edge-light.mjs +3737 -552
  61. package/dist/index.d.mts +871 -199
  62. package/dist/index.d.ts +871 -199
  63. package/dist/index.js +893 -446
  64. package/dist/index.mjs +463 -16
  65. package/dist/instrumentation/index.d.mts +138 -6
  66. package/dist/instrumentation/index.d.ts +138 -6
  67. package/dist/instrumentation/index.js +3362 -559
  68. package/dist/instrumentation/index.mjs +3362 -559
  69. package/dist/vitest-evals-reporter.js +45 -43
  70. package/dist/vitest-evals-reporter.mjs +5 -3
  71. package/dist/workerd.d.mts +1 -1
  72. package/dist/workerd.d.ts +1 -1
  73. package/dist/workerd.js +3737 -552
  74. package/dist/workerd.mjs +3737 -552
  75. package/licenses/node-diagnostics-channel/LICENSE +19 -0
  76. package/package.json +34 -35
  77. package/dist/auto-instrumentations/chunk-VT6DDNKM.mjs +0 -856
  78. package/dist/auto-instrumentations/plugin-D0KHwSJv.d.mts +0 -44
  79. package/dist/auto-instrumentations/plugin-G6fgxk1b.d.ts +0 -44
@@ -1,9 +1,13 @@
1
1
  import {
2
+ GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
2
3
  INSTRUMENTATION_NAMES,
3
4
  aiSDKChannels,
4
5
  anthropicChannels,
5
6
  bedrockRuntimeChannels,
6
7
  claudeAgentSDKChannels,
8
+ cloudflareAIChatChannels,
9
+ cloudflareAgentsChannels,
10
+ cloudflareThinkChannels,
7
11
  cohereChannels,
8
12
  cursorSDKChannels,
9
13
  detectSpanOriginEnvironment,
@@ -11,6 +15,7 @@ import {
11
15
  genkitChannels,
12
16
  genkitCoreChannels,
13
17
  getDefaultInstrumentationIntegrations,
18
+ getHuggingFaceTransformersPipelineInfo,
14
19
  getSpanInstrumentationName,
15
20
  gitHubCopilotChannels,
16
21
  googleADKChannels,
@@ -18,26 +23,30 @@ import {
18
23
  groqChannels,
19
24
  harnessAgentChannels,
20
25
  huggingFaceChannels,
26
+ huggingFaceTransformersChannels,
21
27
  installMastraExporterFactory,
22
28
  isInstrumentationIntegrationDisabled,
29
+ isSupportedHuggingFaceTransformersTask,
23
30
  isomorph_default,
24
31
  langChainChannels,
25
32
  langSmithChannels,
26
33
  mergeSpanOriginContext,
27
34
  mistralChannels,
35
+ ollamaChannels,
28
36
  openAIAgentsCoreChannels,
29
37
  openAIChannels,
30
38
  openAICodexChannels,
31
39
  openRouterAgentChannels,
32
40
  openRouterChannels,
33
- patchTracingChannel,
34
41
  piCodingAgentChannels,
35
42
  readDisabledInstrumentationEnvConfig,
43
+ registerHuggingFaceTransformersPipeline,
44
+ setGlobalHookErrorReporter,
36
45
  smithyClientChannels,
37
46
  smithyCoreChannels,
38
47
  strandsAgentSDKChannels,
39
48
  withSpanInstrumentationName
40
- } from "./chunk-ABR2QWDP.mjs";
49
+ } from "./chunk-CZM5JIQL.mjs";
41
50
 
42
51
  // src/id-gen.ts
43
52
  import { v4 as uuidv4 } from "uuid";
@@ -150,6 +159,9 @@ var debugLogger = {
150
159
  return createDebugLogger(state);
151
160
  }
152
161
  };
162
+ setGlobalHookErrorReporter((error) => {
163
+ debugLogger.error("Global instrumentation hook error:", error);
164
+ });
153
165
 
154
166
  // src/id-gen.ts
155
167
  var IDGenerator = class {
@@ -1877,7 +1889,8 @@ var ApiKey = z6.object({
1877
1889
  user_email: z6.union([z6.string(), z6.null()]).optional(),
1878
1890
  user_given_name: z6.union([z6.string(), z6.null()]).optional(),
1879
1891
  user_family_name: z6.union([z6.string(), z6.null()]).optional(),
1880
- org_id: z6.union([z6.string(), z6.null()]).optional()
1892
+ org_id: z6.union([z6.string(), z6.null()]).optional(),
1893
+ expires_at: z6.union([z6.string(), z6.null()]).optional()
1881
1894
  });
1882
1895
  var TriggeredFunctionState = z6.object({
1883
1896
  triggered_xact_id: z6.string(),
@@ -1997,6 +2010,7 @@ var TopicMapData = z6.object({
1997
2010
  topic_names: z6.record(z6.string()).optional(),
1998
2011
  generation_settings: TopicMapGenerationSettings.optional(),
1999
2012
  disable_reconciliation: z6.boolean().optional(),
2013
+ reconcile_mode: z6.enum(["evolve", "names_only"]).optional(),
2000
2014
  distance_threshold: z6.number().optional(),
2001
2015
  btql_filter: z6.string().optional(),
2002
2016
  automation_btql_filter: z6.string().optional()
@@ -2577,7 +2591,12 @@ var ModelParams = z6.union([
2577
2591
  }).partial().passthrough()
2578
2592
  ]);
2579
2593
  var PromptOptionsNullish = z6.union([
2580
- z6.object({ model: z6.string(), params: ModelParams, position: z6.string() }).partial(),
2594
+ z6.object({
2595
+ model: z6.string(),
2596
+ params: ModelParams,
2597
+ position: z6.string(),
2598
+ endpoint_name: z6.union([z6.string(), z6.null()])
2599
+ }).partial(),
2581
2600
  z6.null()
2582
2601
  ]);
2583
2602
  var PromptParserNullish = z6.union([
@@ -2591,11 +2610,25 @@ var PromptParserNullish = z6.union([
2591
2610
  }),
2592
2611
  z6.null()
2593
2612
  ]);
2613
+ var PreprocessorSavedFunctionId = z6.union([
2614
+ z6.object({
2615
+ type: z6.literal("function"),
2616
+ id: z6.string(),
2617
+ version: z6.string().optional()
2618
+ }),
2619
+ z6.object({
2620
+ type: z6.literal("global"),
2621
+ name: z6.string(),
2622
+ function_type: z6.literal("preprocessor").optional().default("preprocessor")
2623
+ }),
2624
+ z6.null()
2625
+ ]);
2594
2626
  var PromptDataNullish = z6.union([
2595
2627
  z6.object({
2596
2628
  prompt: PromptBlockDataNullish,
2597
2629
  options: PromptOptionsNullish,
2598
2630
  parser: PromptParserNullish,
2631
+ preprocessor: PreprocessorSavedFunctionId,
2599
2632
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
2600
2633
  template_format: z6.union([
2601
2634
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -2797,6 +2830,7 @@ var PromptData = z6.object({
2797
2830
  prompt: PromptBlockDataNullish,
2798
2831
  options: PromptOptionsNullish,
2799
2832
  parser: PromptParserNullish,
2833
+ preprocessor: PreprocessorSavedFunctionId,
2800
2834
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
2801
2835
  template_format: z6.union([
2802
2836
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -2959,7 +2993,8 @@ var InvokeFunction = FunctionId.and(
2959
2993
  mode: StreamingMode,
2960
2994
  strict: z6.union([z6.boolean(), z6.null()]),
2961
2995
  mcp_auth: z6.record(z6.object({ oauth_token: z6.string() }).partial()),
2962
- overrides: z6.union([z6.object({}).partial().passthrough(), z6.null()])
2996
+ overrides: z6.union([z6.object({}).partial().passthrough(), z6.null()]),
2997
+ endpoint_name: z6.union([z6.string(), z6.null()])
2963
2998
  }).partial()
2964
2999
  );
2965
3000
  var MCPServer = z6.object({
@@ -3023,6 +3058,24 @@ var Organization = z6.object({
3023
3058
  created: z6.union([z6.string(), z6.null()]).optional(),
3024
3059
  image_rendering_mode: ImageRenderingMode.optional()
3025
3060
  });
3061
+ var RetentionObjectType = z6.enum([
3062
+ "project_logs",
3063
+ "experiment",
3064
+ "dataset"
3065
+ ]);
3066
+ var OrgAutomation = z6.object({
3067
+ id: z6.string().uuid(),
3068
+ org_id: z6.string().uuid(),
3069
+ user_id: z6.union([z6.string(), z6.null()]).optional(),
3070
+ created: z6.union([z6.string(), z6.null()]).optional(),
3071
+ name: z6.string(),
3072
+ description: z6.union([z6.string(), z6.null()]).optional(),
3073
+ config: z6.object({
3074
+ event_type: z6.literal("retention"),
3075
+ object_type: RetentionObjectType,
3076
+ retention_days: z6.number().int().gte(0)
3077
+ })
3078
+ });
3026
3079
  var ProjectSettings = z6.union([
3027
3080
  z6.object({
3028
3081
  comparison_key: z6.union([z6.string(), z6.null()]),
@@ -3049,6 +3102,7 @@ var ProjectSettings = z6.union([
3049
3102
  z6.null()
3050
3103
  ]),
3051
3104
  disable_realtime_queries: z6.union([z6.boolean(), z6.null()]),
3105
+ monitor_charts_use_metrics_start: z6.union([z6.boolean(), z6.null()]),
3052
3106
  default_preprocessor: NullableSavedFunctionId
3053
3107
  }).partial(),
3054
3108
  z6.null()
@@ -3063,11 +3117,6 @@ var Project = z6.object({
3063
3117
  user_id: z6.union([z6.string(), z6.null()]).optional(),
3064
3118
  settings: ProjectSettings.optional()
3065
3119
  });
3066
- var RetentionObjectType = z6.enum([
3067
- "project_logs",
3068
- "experiment",
3069
- "dataset"
3070
- ]);
3071
3120
  var TopicAutomationFacetModel = z6.union([
3072
3121
  z6.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3073
3122
  z6.null()
@@ -3178,7 +3227,7 @@ var ProjectAutomation = z6.object({
3178
3227
  z6.object({
3179
3228
  event_type: z6.literal("retention"),
3180
3229
  object_type: RetentionObjectType,
3181
- retention_days: z6.number().gte(0)
3230
+ retention_days: z6.number().int().gte(0)
3182
3231
  }),
3183
3232
  z6.object({
3184
3233
  event_type: z6.literal("environment_update"),
@@ -3350,7 +3399,12 @@ var Prompt = z6.object({
3350
3399
  metadata: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
3351
3400
  function_type: FunctionTypeEnumNullish.optional()
3352
3401
  });
3353
- var PromptOptions = z6.object({ model: z6.string(), params: ModelParams, position: z6.string() }).partial();
3402
+ var PromptOptions = z6.object({
3403
+ model: z6.string(),
3404
+ params: ModelParams,
3405
+ position: z6.string(),
3406
+ endpoint_name: z6.union([z6.string(), z6.null()])
3407
+ }).partial();
3354
3408
  var PromptSessionEvent = z6.object({
3355
3409
  id: z6.string(),
3356
3410
  _xact_id: z6.string(),
@@ -3433,7 +3487,8 @@ var RunEval = z6.object({
3433
3487
  stop_token: z6.union([z6.string(), z6.null()]).optional(),
3434
3488
  extra_messages: z6.string().optional(),
3435
3489
  tags: z6.array(z6.string()).optional(),
3436
- mcp_auth: z6.record(z6.object({ oauth_token: z6.string() }).partial()).optional()
3490
+ mcp_auth: z6.record(z6.object({ oauth_token: z6.string() }).partial()).optional(),
3491
+ endpoint_name: z6.union([z6.string(), z6.null()]).optional()
3437
3492
  });
3438
3493
  var ServiceToken = z6.object({
3439
3494
  id: z6.string().uuid(),
@@ -3443,7 +3498,8 @@ var ServiceToken = z6.object({
3443
3498
  service_account_id: z6.union([z6.string(), z6.null()]).optional(),
3444
3499
  service_account_email: z6.union([z6.string(), z6.null()]).optional(),
3445
3500
  service_account_name: z6.union([z6.string(), z6.null()]).optional(),
3446
- org_id: z6.union([z6.string(), z6.null()]).optional()
3501
+ org_id: z6.union([z6.string(), z6.null()]).optional(),
3502
+ expires_at: z6.union([z6.string(), z6.null()]).optional()
3447
3503
  });
3448
3504
  var SpanIFrame = z6.object({
3449
3505
  id: z6.string().uuid(),
@@ -3565,6 +3621,13 @@ var ViewOptions = z6.union([
3565
3621
  }),
3566
3622
  z6.null()
3567
3623
  ]),
3624
+ pointSizeMetric: z6.union([
3625
+ z6.object({
3626
+ type: z6.enum(["none", "score", "metric", "metadata"]),
3627
+ value: z6.string()
3628
+ }),
3629
+ z6.null()
3630
+ ]),
3568
3631
  xAxisAggregation: z6.union([z6.string(), z6.null()]),
3569
3632
  chartAnnotations: z6.union([
3570
3633
  z6.array(z6.object({ id: z6.string(), text: z6.string() })),
@@ -4847,12 +4910,13 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
4847
4910
  var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
4848
4911
  "braintrust.initial-span-write-as-merge"
4849
4912
  );
4913
+ var INTERNAL_SPAN_CONTEXT = /* @__PURE__ */ Symbol("braintrust.internal-span-context");
4850
4914
  var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
4851
4915
  "braintrust.currentSpanStore"
4852
4916
  );
4853
4917
  var ContextManager = class {
4854
4918
  /**
4855
- * Returns the value to store in the ALS bound to a TracingChannel's start event.
4919
+ * Returns the value to store in the ALS bound to a global hook's start event.
4856
4920
  * In default mode this is the Span itself; in OTEL mode it is the OTEL Context
4857
4921
  * containing the span so that OTEL's own ALS stores a proper Context object.
4858
4922
  */
@@ -8585,6 +8649,12 @@ function _internalStartSpanWithInitialMerge(args) {
8585
8649
  [INITIAL_SPAN_WRITE_AS_MERGE]: true
8586
8650
  }).span;
8587
8651
  }
8652
+ function _internalStartSpanWithContext(args, context) {
8653
+ return startSpanAndIsLogger({
8654
+ ...args,
8655
+ [INTERNAL_SPAN_CONTEXT]: context
8656
+ }).span;
8657
+ }
8588
8658
  async function flush(options) {
8589
8659
  const state = options?.state ?? _globalState;
8590
8660
  return await state.bgLogger().flush();
@@ -9486,7 +9556,7 @@ var SpanImpl = class _SpanImpl {
9486
9556
  start: args.startTime ?? getCurrentUnixTimestamp()
9487
9557
  },
9488
9558
  context: mergeSpanOriginContext(
9489
- { ...callerLocation },
9559
+ { ...callerLocation, ...args[INTERNAL_SPAN_CONTEXT] },
9490
9560
  instrumentationName,
9491
9561
  this._state.spanOriginEnvironment
9492
9562
  ),
@@ -10815,6 +10885,25 @@ function getCachedMetricFromHeaders(headers) {
10815
10885
  return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
10816
10886
  }
10817
10887
 
10888
+ // src/wrappers/anthropic-session-collector.ts
10889
+ var sessionStreamCollectors = /* @__PURE__ */ new WeakMap();
10890
+ function registerAnthropicSessionStreamCollector(stream, collector) {
10891
+ sessionStreamCollectors.set(stream, collector);
10892
+ }
10893
+ function collectAnthropicSession(stream) {
10894
+ const collector = sessionStreamCollectors.get(stream);
10895
+ if (!collector) {
10896
+ return stream;
10897
+ }
10898
+ sessionStreamCollectors.delete(stream);
10899
+ try {
10900
+ collector();
10901
+ } catch (error) {
10902
+ debugLogger.error("Failed to collect Anthropic Sessions stream:", error);
10903
+ }
10904
+ return stream;
10905
+ }
10906
+
10818
10907
  // src/instrumentation/core/stream-patcher.ts
10819
10908
  function isAsyncIterable(value) {
10820
10909
  return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
@@ -10839,6 +10928,34 @@ function patchStreamIfNeeded(stream, options) {
10839
10928
  );
10840
10929
  return stream;
10841
10930
  }
10931
+ const chunks = [];
10932
+ let completed = false;
10933
+ const notifyCancellation = async () => {
10934
+ try {
10935
+ await (options.onCancel ?? options.onComplete)(chunks);
10936
+ } catch (error) {
10937
+ debugLogger.error("Error in stream cancellation handler:", error);
10938
+ }
10939
+ };
10940
+ const patchAbortIfPresent = () => {
10941
+ try {
10942
+ if ("abort" in stream && typeof stream.abort === "function") {
10943
+ const originalAbort = stream.abort.bind(stream);
10944
+ stream.abort = (...args) => {
10945
+ try {
10946
+ return originalAbort(...args);
10947
+ } finally {
10948
+ if (!completed) {
10949
+ completed = true;
10950
+ void notifyCancellation();
10951
+ }
10952
+ }
10953
+ };
10954
+ }
10955
+ } catch (error) {
10956
+ debugLogger.warn("Failed to patch stream abort method:", error);
10957
+ }
10958
+ };
10842
10959
  if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
10843
10960
  if ("__braintrust_patched_iterator_methods" in stream) {
10844
10961
  return stream;
@@ -10847,8 +10964,6 @@ function patchStreamIfNeeded(stream, options) {
10847
10964
  const originalNext = stream.next.bind(stream);
10848
10965
  const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
10849
10966
  const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
10850
- const chunks = [];
10851
- let completed = false;
10852
10967
  stream.next = async (...args) => {
10853
10968
  try {
10854
10969
  const result = await runNextWithWrapper(
@@ -10900,11 +11015,7 @@ function patchStreamIfNeeded(stream, options) {
10900
11015
  stream.return = async (...args) => {
10901
11016
  if (!completed) {
10902
11017
  completed = true;
10903
- try {
10904
- await options.onComplete(chunks);
10905
- } catch (error) {
10906
- console.error("Error in stream onComplete handler:", error);
10907
- }
11018
+ await notifyCancellation();
10908
11019
  }
10909
11020
  return originalReturn(...args);
10910
11021
  };
@@ -10929,6 +11040,7 @@ function patchStreamIfNeeded(stream, options) {
10929
11040
  Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
10930
11041
  value: true
10931
11042
  });
11043
+ patchAbortIfPresent();
10932
11044
  return stream;
10933
11045
  } catch (error) {
10934
11046
  console.warn("Failed to patch stream iterator methods:", error);
@@ -10942,8 +11054,6 @@ function patchStreamIfNeeded(stream, options) {
10942
11054
  const patchedIteratorFn = function() {
10943
11055
  const iterator = originalIteratorFn.call(this);
10944
11056
  const originalNext = iterator.next.bind(iterator);
10945
- const chunks = [];
10946
- let completed = false;
10947
11057
  iterator.next = async function(...args) {
10948
11058
  try {
10949
11059
  const result = await runNextWithWrapper(
@@ -10996,11 +11106,7 @@ function patchStreamIfNeeded(stream, options) {
10996
11106
  iterator.return = async function(...args) {
10997
11107
  if (!completed) {
10998
11108
  completed = true;
10999
- try {
11000
- await options.onComplete(chunks);
11001
- } catch (error) {
11002
- console.error("Error in stream onComplete handler:", error);
11003
- }
11109
+ await notifyCancellation();
11004
11110
  }
11005
11111
  return originalReturn(...args);
11006
11112
  };
@@ -11029,6 +11135,7 @@ function patchStreamIfNeeded(stream, options) {
11029
11135
  value: true
11030
11136
  });
11031
11137
  stream[Symbol.asyncIterator] = patchedIteratorFn;
11138
+ patchAbortIfPresent();
11032
11139
  return stream;
11033
11140
  } catch (error) {
11034
11141
  console.warn("Failed to patch stream:", error);
@@ -11481,8 +11588,8 @@ function runWithAutoInstrumentationSuppressed(callback) {
11481
11588
  callback
11482
11589
  );
11483
11590
  }
11484
- function bindAutoInstrumentationSuppressionToStart(tracingChannel2) {
11485
- const startChannel = tracingChannel2.start;
11591
+ function bindAutoInstrumentationSuppressionToStart(tracingChannel) {
11592
+ const startChannel = tracingChannel.start;
11486
11593
  if (!startChannel) {
11487
11594
  return void 0;
11488
11595
  }
@@ -11593,9 +11700,9 @@ function ensureSpanStateForEvent(states, config, event, channelName, instrumenta
11593
11700
  states.set(key, created);
11594
11701
  return created;
11595
11702
  }
11596
- function bindCurrentSpanStoreToStart(tracingChannel2, states, config, channelName, instrumentationName) {
11703
+ function bindCurrentSpanStoreToStart(tracingChannel, states, config, channelName, instrumentationName) {
11597
11704
  const state = _internalGetGlobalState();
11598
- const startChannel = tracingChannel2.start;
11705
+ const startChannel = tracingChannel.start;
11599
11706
  const contextManager = state?.contextManager;
11600
11707
  const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
11601
11708
  if (!currentSpanStore || !startChannel) {
@@ -11678,11 +11785,11 @@ function runStreamingErrorHook(args) {
11678
11785
  }
11679
11786
  }
11680
11787
  function traceAsyncChannel(channel, config) {
11681
- const tracingChannel2 = channel.tracingChannel();
11788
+ const tracingChannel = channel.tracingChannel();
11682
11789
  const states = /* @__PURE__ */ new WeakMap();
11683
11790
  const channelName = channel.channelName;
11684
11791
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart(
11685
- tracingChannel2,
11792
+ tracingChannel,
11686
11793
  states,
11687
11794
  config,
11688
11795
  channelName,
@@ -11738,18 +11845,18 @@ function traceAsyncChannel(channel, config) {
11738
11845
  logErrorAndEnd(states, event, channelName);
11739
11846
  }
11740
11847
  };
11741
- tracingChannel2.subscribe(handlers);
11848
+ tracingChannel.subscribe(handlers);
11742
11849
  return () => {
11743
11850
  unbindCurrentSpanStore?.();
11744
- tracingChannel2.unsubscribe(handlers);
11851
+ tracingChannel.unsubscribe(handlers);
11745
11852
  };
11746
11853
  }
11747
11854
  function traceStreamingChannel(channel, config) {
11748
- const tracingChannel2 = channel.tracingChannel();
11855
+ const tracingChannel = channel.tracingChannel();
11749
11856
  const states = /* @__PURE__ */ new WeakMap();
11750
11857
  const channelName = channel.channelName;
11751
11858
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart(
11752
- tracingChannel2,
11859
+ tracingChannel,
11753
11860
  states,
11754
11861
  config,
11755
11862
  channelName,
@@ -11777,6 +11884,33 @@ function traceStreamingChannel(channel, config) {
11777
11884
  const { span, startTime } = spanData;
11778
11885
  if (isAsyncIterable(asyncEndEvent.result)) {
11779
11886
  let firstChunkTime;
11887
+ const handleStreamError = (error) => {
11888
+ try {
11889
+ span.log({ error });
11890
+ } catch (loggingError) {
11891
+ debugLogger.error(
11892
+ `Error logging failure for ${channelName}:`,
11893
+ loggingError
11894
+ );
11895
+ }
11896
+ try {
11897
+ span.end();
11898
+ } catch (endingError) {
11899
+ debugLogger.error(
11900
+ `Error ending span for ${channelName}:`,
11901
+ endingError
11902
+ );
11903
+ }
11904
+ states.delete(event);
11905
+ runStreamingErrorHook({
11906
+ channelName,
11907
+ config,
11908
+ error,
11909
+ event: asyncEndEvent,
11910
+ span,
11911
+ startTime
11912
+ });
11913
+ };
11780
11914
  patchStreamIfNeeded(asyncEndEvent.result, {
11781
11915
  onChunk: () => {
11782
11916
  if (firstChunkTime === void 0) {
@@ -11856,33 +11990,12 @@ function traceStreamingChannel(channel, config) {
11856
11990
  });
11857
11991
  }
11858
11992
  },
11859
- onError: (error) => {
11860
- try {
11861
- span.log({ error });
11862
- } catch (loggingError) {
11863
- debugLogger.error(
11864
- `Error logging failure for ${channelName}:`,
11865
- loggingError
11866
- );
11867
- }
11868
- try {
11869
- span.end();
11870
- } catch (endingError) {
11871
- debugLogger.error(
11872
- `Error ending span for ${channelName}:`,
11873
- endingError
11874
- );
11875
- }
11876
- states.delete(event);
11877
- runStreamingErrorHook({
11878
- channelName,
11879
- config,
11880
- error,
11881
- event: asyncEndEvent,
11882
- span,
11883
- startTime
11884
- });
11885
- }
11993
+ onCancel: () => {
11994
+ const error = new Error("Stream cancelled before completion");
11995
+ error.name = "AbortError";
11996
+ handleStreamError(error);
11997
+ },
11998
+ onError: handleStreamError
11886
11999
  });
11887
12000
  return;
11888
12001
  }
@@ -11960,18 +12073,18 @@ function traceStreamingChannel(channel, config) {
11960
12073
  }
11961
12074
  }
11962
12075
  };
11963
- tracingChannel2.subscribe(handlers);
12076
+ tracingChannel.subscribe(handlers);
11964
12077
  return () => {
11965
12078
  unbindCurrentSpanStore?.();
11966
- tracingChannel2.unsubscribe(handlers);
12079
+ tracingChannel.unsubscribe(handlers);
11967
12080
  };
11968
12081
  }
11969
12082
  function traceSyncStreamChannel(channel, config) {
11970
- const tracingChannel2 = channel.tracingChannel();
12083
+ const tracingChannel = channel.tracingChannel();
11971
12084
  const states = /* @__PURE__ */ new WeakMap();
11972
12085
  const channelName = channel.channelName;
11973
12086
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart(
11974
- tracingChannel2,
12087
+ tracingChannel,
11975
12088
  states,
11976
12089
  config,
11977
12090
  channelName,
@@ -12084,10 +12197,10 @@ function traceSyncStreamChannel(channel, config) {
12084
12197
  logErrorAndEnd(states, event, channelName);
12085
12198
  }
12086
12199
  };
12087
- tracingChannel2.subscribe(handlers);
12200
+ tracingChannel.subscribe(handlers);
12088
12201
  return () => {
12089
12202
  unbindCurrentSpanStore?.();
12090
- tracingChannel2.unsubscribe(handlers);
12203
+ tracingChannel.unsubscribe(handlers);
12091
12204
  };
12092
12205
  }
12093
12206
  function unsubscribeAll(unsubscribers) {
@@ -12560,8 +12673,8 @@ function registerHarnessSessionParent(session, parent) {
12560
12673
  function currentHarnessTurnParent() {
12561
12674
  return harnessTurnParentStore?.getStore() ?? wrapperTurnParents.get(currentSpan());
12562
12675
  }
12563
- function bindHarnessTurnParentToStart(tracingChannel2, parentFromEvent) {
12564
- const startChannel = tracingChannel2.start;
12676
+ function bindHarnessTurnParentToStart(tracingChannel, parentFromEvent) {
12677
+ const startChannel = tracingChannel.start;
12565
12678
  if (!startChannel) {
12566
12679
  return () => {
12567
12680
  };
@@ -12642,6 +12755,29 @@ function currentWorkflowAgentWrapperSpan() {
12642
12755
  return void 0;
12643
12756
  }
12644
12757
 
12758
+ // src/instrumentation/plugins/cloudflare-think-context.ts
12759
+ var cloudflareThinkSpans = /* @__PURE__ */ new Map();
12760
+ function registerCloudflareThinkSpan(span) {
12761
+ if (span.spanId) {
12762
+ cloudflareThinkSpans.set(span.spanId, span);
12763
+ }
12764
+ }
12765
+ function unregisterCloudflareThinkSpan(span) {
12766
+ if (span.spanId) {
12767
+ cloudflareThinkSpans.delete(span.spanId);
12768
+ }
12769
+ }
12770
+ function currentCloudflareThinkSpan() {
12771
+ const parentSpanIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
12772
+ for (const parentSpanId of parentSpanIds) {
12773
+ const span = cloudflareThinkSpans.get(parentSpanId);
12774
+ if (span) {
12775
+ return span;
12776
+ }
12777
+ }
12778
+ return void 0;
12779
+ }
12780
+
12645
12781
  // src/vendor-sdk-types/ai-sdk-v7-telemetry.ts
12646
12782
  var BRAINTRUST_AI_SDK_V7_OPERATION_KEY = /* @__PURE__ */ Symbol.for(
12647
12783
  "braintrust.ai-sdk.v7.telemetry-operation-key"
@@ -12753,6 +12889,7 @@ var AISDKPlugin = class extends BasePlugin {
12753
12889
  traceStreamingChannel(aiSDKChannels.streamText, {
12754
12890
  name: "streamText",
12755
12891
  type: "function" /* FUNCTION */,
12892
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
12756
12893
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
12757
12894
  extractOutput: (result, endEvent) => processAISDKOutput(
12758
12895
  result,
@@ -12773,6 +12910,7 @@ var AISDKPlugin = class extends BasePlugin {
12773
12910
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
12774
12911
  name: "streamText",
12775
12912
  type: "function" /* FUNCTION */,
12913
+ shouldTrace: () => currentCloudflareThinkSpan() === void 0,
12776
12914
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
12777
12915
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
12778
12916
  defaultDenyOutputPaths: denyOutputPaths,
@@ -13758,6 +13896,23 @@ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOu
13758
13896
  metadata
13759
13897
  };
13760
13898
  }
13899
+ function prepareAISDKAgentCallInput(params, event, span, defaultDenyOutputPaths = DEFAULT_DENY_OUTPUT_PATHS) {
13900
+ const { input } = processAISDKWorkflowAgentCallInput(params);
13901
+ const metadata = extractMetadataFromCallParams(params, event.self);
13902
+ const childTracing = prepareAISDKChildTracing(
13903
+ params,
13904
+ event.self,
13905
+ span,
13906
+ defaultDenyOutputPaths,
13907
+ event.aiSDK,
13908
+ { agentOwner: true }
13909
+ );
13910
+ event.modelWrapped = childTracing.modelWrapped;
13911
+ if (childTracing.cleanup) {
13912
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
13913
+ }
13914
+ return { input, metadata };
13915
+ }
13761
13916
  function prepareAISDKEmbedInput(params, self) {
13762
13917
  return {
13763
13918
  input: { ...params },
@@ -13781,6 +13936,18 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
13781
13936
  }
13782
13937
  return metrics;
13783
13938
  }
13939
+ async function extractResolvedAISDKTokenMetrics(result) {
13940
+ for (const field of ["totalUsage", "usage"]) {
13941
+ try {
13942
+ const usage = await Promise.resolve(result[field]);
13943
+ if (usage !== void 0) {
13944
+ return extractTokenMetrics({ [field]: usage });
13945
+ }
13946
+ } catch {
13947
+ }
13948
+ }
13949
+ return extractTokenMetrics(result);
13950
+ }
13784
13951
  function hasModelChildTracing(event) {
13785
13952
  return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
13786
13953
  }
@@ -14598,13 +14765,15 @@ function patchAISDKStreamingResult(args) {
14598
14765
  const {
14599
14766
  defaultDenyOutputPaths,
14600
14767
  endEvent,
14768
+ forceTopLevelMetrics,
14601
14769
  onComplete,
14602
14770
  onCancel,
14603
14771
  onError,
14604
14772
  result,
14605
14773
  resolvePromiseUsage,
14606
14774
  span,
14607
- startTime
14775
+ startTime,
14776
+ transformOutput
14608
14777
  } = args;
14609
14778
  if (!result || typeof result !== "object") {
14610
14779
  return false;
@@ -14657,8 +14826,8 @@ function patchAISDKStreamingResult(args) {
14657
14826
  }
14658
14827
  outputLogged = true;
14659
14828
  try {
14660
- const metrics = extractTopLevelAISDKMetrics(result, endEvent);
14661
- if (resolvePromiseUsage) {
14829
+ const metrics = forceTopLevelMetrics ? await extractResolvedAISDKTokenMetrics(result) : extractTopLevelAISDKMetrics(result, endEvent);
14830
+ if (resolvePromiseUsage && !forceTopLevelMetrics) {
14662
14831
  try {
14663
14832
  const resultRecord2 = result;
14664
14833
  const pendingUsage = resultRecord2.totalUsage ?? resultRecord2.usage;
@@ -14677,10 +14846,11 @@ function patchAISDKStreamingResult(args) {
14677
14846
  if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
14678
14847
  metrics.time_to_first_token = firstChunkTime - startTime;
14679
14848
  }
14680
- const output = await processAISDKStreamingOutput(
14849
+ const processedOutput = await processAISDKStreamingOutput(
14681
14850
  result,
14682
14851
  resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
14683
14852
  );
14853
+ const output = transformOutput ? transformOutput(processedOutput) : processedOutput;
14684
14854
  const metadata = buildResolvedMetadataPayload(result).metadata;
14685
14855
  try {
14686
14856
  span.log({
@@ -16847,7 +17017,7 @@ var FlueObserveBridge = class {
16847
17017
  return;
16848
17018
  }
16849
17019
  const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
16850
- const output = operationOutput(event);
17020
+ const output = operationOutput(event) ?? outputFromAgentTurn(state.latestAgentOutput);
16851
17021
  const metadata = {
16852
17022
  ...state.metadata,
16853
17023
  ...extractEventMetadata(event),
@@ -16856,7 +17026,7 @@ var FlueObserveBridge = class {
16856
17026
  };
16857
17027
  this.finishPendingChildrenForOperation(event, output);
16858
17028
  safeLog(state.span, {
16859
- ...event.isError ? { error: toLoggedError(event.error) } : {},
17029
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
16860
17030
  metadata,
16861
17031
  metrics: durationMetrics(event.durationMs),
16862
17032
  output
@@ -16887,7 +17057,7 @@ var FlueObserveBridge = class {
16887
17057
  };
16888
17058
  const parent = this.parentSpanForTurn(event);
16889
17059
  const span = startFlueSpan(parent, {
16890
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
17060
+ name: "flue.turn",
16891
17061
  spanAttributes: { type: "llm" /* LLM */ },
16892
17062
  startTime: eventTime(event.timestamp),
16893
17063
  event: {
@@ -16931,6 +17101,12 @@ var FlueObserveBridge = class {
16931
17101
  },
16932
17102
  output
16933
17103
  });
17104
+ if (event.purpose === "agent" && event.operationId) {
17105
+ const operation = this.operationsById.get(event.operationId);
17106
+ if (operation) {
17107
+ operation.latestAgentOutput = output;
17108
+ }
17109
+ }
16934
17110
  safeEnd(state.span, eventTime(event.timestamp));
16935
17111
  this.turnsByKey.delete(key);
16936
17112
  }
@@ -17010,7 +17186,7 @@ var FlueObserveBridge = class {
17010
17186
  return;
17011
17187
  }
17012
17188
  safeLog(state.span, {
17013
- ...event.isError ? { error: toLoggedError(event.result) } : {},
17189
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.result) } : {},
17014
17190
  metadata: {
17015
17191
  ...state.metadata,
17016
17192
  ...extractEventMetadata(event),
@@ -17056,6 +17232,7 @@ var FlueObserveBridge = class {
17056
17232
  ...event.usage ? { "flue.usage": event.usage } : {}
17057
17233
  };
17058
17234
  safeLog(state.span, {
17235
+ ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
17059
17236
  metadata,
17060
17237
  metrics: {
17061
17238
  ...durationMetrics(event.durationMs),
@@ -17160,7 +17337,7 @@ var FlueObserveBridge = class {
17160
17337
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
17161
17338
  };
17162
17339
  const span = startFlueSpan(this.parentSpanForEvent(event), {
17163
- name: `llm:${model ?? event.purpose ?? "unknown"}`,
17340
+ name: "flue.turn",
17164
17341
  spanAttributes: { type: "llm" /* LLM */ },
17165
17342
  startTime: eventTime(event.timestamp),
17166
17343
  event: { metadata }
@@ -17292,7 +17469,10 @@ function extractEventMetadata(event, ctx) {
17292
17469
  return {
17293
17470
  ...event.runId ? { "flue.run_id": event.runId } : {},
17294
17471
  ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
17472
+ ...event.submissionId ? { "flue.submission_id": event.submissionId } : {},
17295
17473
  ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
17474
+ ...event.agentName ? { "flue.agent_name": event.agentName } : {},
17475
+ ...event.conversationId ? { "flue.conversation_id": event.conversationId } : {},
17296
17476
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
17297
17477
  ...event.session ? { "flue.session": event.session } : {},
17298
17478
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
@@ -17321,7 +17501,7 @@ function flueTurnRequestInput(event) {
17321
17501
  return event.request?.input ?? event.input;
17322
17502
  }
17323
17503
  function flueTurnRequestModel(event) {
17324
- return event.request?.model ?? event.model;
17504
+ return event.request?.requestedModel ?? event.request?.model ?? event.model;
17325
17505
  }
17326
17506
  function flueTurnRequestProvider(event) {
17327
17507
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -17330,10 +17510,10 @@ function flueTurnRequestApi(event) {
17330
17510
  return event.request?.api ?? event.api;
17331
17511
  }
17332
17512
  function flueTurnRequestReasoning(event) {
17333
- return event.request?.reasoning ?? event.reasoning;
17513
+ return event.request?.reasoningLevel ?? event.request?.reasoning ?? event.reasoning;
17334
17514
  }
17335
17515
  function flueTurnModel(event) {
17336
- return event.request?.model ?? event.model;
17516
+ return event.response?.responseModel ?? event.request?.requestedModel ?? event.request?.model ?? event.model;
17337
17517
  }
17338
17518
  function flueTurnProvider(event) {
17339
17519
  return event.request?.providerName ?? event.provider ?? event.request?.providerId;
@@ -17348,7 +17528,7 @@ function flueTurnOutput(event) {
17348
17528
  return event.response?.output ?? event.output;
17349
17529
  }
17350
17530
  function flueTurnStopReason(event) {
17351
- return event.response?.stopReason ?? event.stopReason;
17531
+ return event.response?.finishReason ?? event.response?.stopReason ?? event.stopReason;
17352
17532
  }
17353
17533
  function flueTurnError(event) {
17354
17534
  return event.response?.error ?? event.response?.errorInfo?.message ?? event.error;
@@ -17363,6 +17543,9 @@ function flueToolInput(event) {
17363
17543
  return event.input;
17364
17544
  }
17365
17545
  function flueToolOutput(event) {
17546
+ if (Object.hasOwn(event, "effectiveResult")) {
17547
+ return event.effectiveResult;
17548
+ }
17366
17549
  return event.output !== void 0 ? event.output : event.result;
17367
17550
  }
17368
17551
  function flueToolError(event) {
@@ -17370,10 +17553,36 @@ function flueToolError(event) {
17370
17553
  }
17371
17554
  function operationOutput(event) {
17372
17555
  if (event.operationKind === "prompt" || event.operationKind === "skill") {
17373
- return llmResultFromOperationResult(event.result);
17556
+ return outputFromAgentInvocation(event.agentOutput) ?? llmResultFromOperationResult(event.result);
17374
17557
  }
17375
17558
  return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
17376
17559
  }
17560
+ function outputFromAgentInvocation(output) {
17561
+ if (output?.type === "text") {
17562
+ return output.text;
17563
+ }
17564
+ if (output?.type === "data") {
17565
+ return output.data;
17566
+ }
17567
+ return void 0;
17568
+ }
17569
+ function outputFromAgentTurn(output) {
17570
+ if (!isObjectLike(output)) {
17571
+ return output;
17572
+ }
17573
+ const content = Reflect.get(output, "content");
17574
+ if (!Array.isArray(content)) {
17575
+ return output;
17576
+ }
17577
+ const text = content.flatMap((part) => {
17578
+ if (!isObjectLike(part) || Reflect.get(part, "type") !== "text") {
17579
+ return [];
17580
+ }
17581
+ const value = Reflect.get(part, "text");
17582
+ return typeof value === "string" ? [value] : [];
17583
+ });
17584
+ return text.length > 0 ? text.join("") : output;
17585
+ }
17377
17586
  function llmResultFromOperationResult(result) {
17378
17587
  if (!isObjectLike(result)) {
17379
17588
  return result;
@@ -17472,7 +17681,7 @@ function safeEnd(span, endTime) {
17472
17681
  }
17473
17682
  }
17474
17683
  function logInstrumentationError(label, error) {
17475
- console.error(`Error in ${label} instrumentation:`, error);
17684
+ debugLogger.debug(`Error in ${label} instrumentation:`, error);
17476
17685
  }
17477
17686
 
17478
17687
  // src/wrappers/langchain/callback-handler.ts
@@ -18969,6 +19178,7 @@ var AnthropicPlugin = class extends BasePlugin {
18969
19178
  onEnable() {
18970
19179
  this.subscribeToAnthropicChannels();
18971
19180
  this.subscribeToAnthropicToolRunner();
19181
+ this.subscribeToAnthropicSessionStreams();
18972
19182
  }
18973
19183
  onDisable() {
18974
19184
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -19024,7 +19234,7 @@ var AnthropicPlugin = class extends BasePlugin {
19024
19234
  );
19025
19235
  }
19026
19236
  subscribeToAnthropicToolRunner() {
19027
- const tracingChannel2 = anthropicChannels.betaMessagesToolRunner.tracingChannel();
19237
+ const tracingChannel = anthropicChannels.betaMessagesToolRunner.tracingChannel();
19028
19238
  const states = /* @__PURE__ */ new WeakMap();
19029
19239
  const handlers = {
19030
19240
  start: (event) => {
@@ -19081,12 +19291,416 @@ var AnthropicPlugin = class extends BasePlugin {
19081
19291
  states.delete(event);
19082
19292
  }
19083
19293
  };
19084
- tracingChannel2.subscribe(handlers);
19294
+ tracingChannel.subscribe(handlers);
19085
19295
  this.unsubscribers.push(() => {
19086
- tracingChannel2.unsubscribe(handlers);
19296
+ tracingChannel.unsubscribe(handlers);
19087
19297
  });
19088
19298
  }
19299
+ subscribeToAnthropicSessionStreams() {
19300
+ this.subscribeToAnthropicSessionStream(
19301
+ anthropicChannels.betaSessionsEventsStream,
19302
+ false
19303
+ );
19304
+ this.subscribeToAnthropicSessionStream(
19305
+ anthropicChannels.betaSessionsThreadsEventsStream,
19306
+ true
19307
+ );
19308
+ }
19309
+ subscribeToAnthropicSessionStream(channel, isThread) {
19310
+ const tracingChannel = channel.tracingChannel();
19311
+ const pending = /* @__PURE__ */ new WeakSet();
19312
+ const handlers = {
19313
+ start: (event) => {
19314
+ if (isAutoInstrumentationSuppressed()) {
19315
+ return;
19316
+ }
19317
+ pending.add(event);
19318
+ },
19319
+ asyncEnd: (event) => {
19320
+ if (!pending.delete(event)) {
19321
+ return;
19322
+ }
19323
+ const stream = event.result;
19324
+ if (!isAsyncIterable(stream)) {
19325
+ return;
19326
+ }
19327
+ registerAnthropicSessionStreamCollector(stream, () => {
19328
+ wrapAnthropicSessionEventStream(stream, isThread);
19329
+ });
19330
+ },
19331
+ error: (event) => {
19332
+ pending.delete(event);
19333
+ }
19334
+ };
19335
+ tracingChannel.subscribe(handlers);
19336
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
19337
+ }
19089
19338
  };
19339
+ function wrapAnthropicSessionEventStream(stream, isThread) {
19340
+ const state = {
19341
+ history: [],
19342
+ isThread,
19343
+ pendingInput: [],
19344
+ seenEventIds: /* @__PURE__ */ new Set()
19345
+ };
19346
+ patchStreamIfNeeded(stream, {
19347
+ onChunk: (event) => handleAnthropicSessionEvent(state, event),
19348
+ onComplete: () => finalizeAnthropicSessionTurn(state),
19349
+ onError: (error) => finalizeAnthropicSessionTurn(state, error)
19350
+ });
19351
+ return stream;
19352
+ }
19353
+ function handleAnthropicSessionEvent(state, event) {
19354
+ try {
19355
+ if (typeof event.id === "string" && event.type !== "event_delta" && state.seenEventIds.has(event.id)) {
19356
+ return;
19357
+ }
19358
+ if (typeof event.id === "string" && event.type !== "event_delta") {
19359
+ state.seenEventIds.add(event.id);
19360
+ }
19361
+ switch (event.type) {
19362
+ case "user.message":
19363
+ case "system.message":
19364
+ recordAnthropicSessionInput(
19365
+ state,
19366
+ event
19367
+ );
19368
+ break;
19369
+ case "session.status_running":
19370
+ if (!state.isThread) {
19371
+ ensureAnthropicSessionTurn(state);
19372
+ }
19373
+ break;
19374
+ case "session.thread_status_running":
19375
+ if (state.isThread) {
19376
+ ensureAnthropicSessionTurn(state);
19377
+ }
19378
+ break;
19379
+ case "span.model_request_start":
19380
+ if (typeof event.id === "string") {
19381
+ startAnthropicSessionModel(state, event.id);
19382
+ }
19383
+ break;
19384
+ case "event_delta":
19385
+ recordAnthropicSessionFirstToken(state, event);
19386
+ break;
19387
+ case "agent.message":
19388
+ recordAnthropicSessionMessage(
19389
+ state,
19390
+ event
19391
+ );
19392
+ break;
19393
+ case "agent.custom_tool_use":
19394
+ case "agent.mcp_tool_use":
19395
+ case "agent.tool_use":
19396
+ startAnthropicSessionTool(state, event);
19397
+ break;
19398
+ case "user.tool_confirmation":
19399
+ recordAnthropicSessionToolConfirmation(state, event);
19400
+ break;
19401
+ case "agent.mcp_tool_result":
19402
+ case "agent.tool_result":
19403
+ case "user.custom_tool_result":
19404
+ case "user.tool_result":
19405
+ finalizeAnthropicSessionTool(
19406
+ state,
19407
+ event
19408
+ );
19409
+ break;
19410
+ case "span.model_request_end":
19411
+ finalizeAnthropicSessionModel(
19412
+ state,
19413
+ event
19414
+ );
19415
+ break;
19416
+ case "session.status_idle":
19417
+ case "session.thread_status_idle": {
19418
+ if (event.type === "session.status_idle" && state.isThread || event.type === "session.thread_status_idle" && !state.isThread) {
19419
+ break;
19420
+ }
19421
+ const stopReason = isObject(event.stop_reason) ? event.stop_reason.type : void 0;
19422
+ if (stopReason === "end_turn") {
19423
+ finalizeAnthropicSessionTurn(state);
19424
+ } else if (stopReason === "retries_exhausted") {
19425
+ finalizeAnthropicSessionTurn(
19426
+ state,
19427
+ "Anthropic session retries exhausted"
19428
+ );
19429
+ }
19430
+ break;
19431
+ }
19432
+ case "session.error":
19433
+ finalizeAnthropicSessionTurn(state, event.error);
19434
+ break;
19435
+ case "session.deleted":
19436
+ case "session.status_terminated":
19437
+ case "session.thread_status_terminated":
19438
+ if (event.type === "session.deleted" || event.type === "session.status_terminated" && !state.isThread || event.type === "session.thread_status_terminated" && state.isThread) {
19439
+ finalizeAnthropicSessionTurn(state);
19440
+ }
19441
+ break;
19442
+ default:
19443
+ break;
19444
+ }
19445
+ } catch (error) {
19446
+ debugLogger.debug("Error processing Anthropic Sessions event:", error);
19447
+ }
19448
+ }
19449
+ function ensureAnthropicSessionTurn(state) {
19450
+ if (state.activeTurn) {
19451
+ return state.activeTurn;
19452
+ }
19453
+ const input = state.pendingInput;
19454
+ state.pendingInput = [];
19455
+ const span = startSpan(
19456
+ withSpanInstrumentationName(
19457
+ {
19458
+ event: {
19459
+ ...input.length > 0 ? { input } : {},
19460
+ metadata: { provider: "anthropic" }
19461
+ },
19462
+ name: state.isThread ? "anthropic.beta.sessions.thread.turn" : "anthropic.beta.sessions.turn",
19463
+ spanAttributes: { type: "task" /* TASK */ }
19464
+ },
19465
+ INSTRUMENTATION_NAMES.ANTHROPIC
19466
+ )
19467
+ );
19468
+ state.activeTurn = {
19469
+ activeTools: /* @__PURE__ */ new Map(),
19470
+ input: input.slice(),
19471
+ metrics: {},
19472
+ span
19473
+ };
19474
+ return state.activeTurn;
19475
+ }
19476
+ function recordAnthropicSessionInput(state, event) {
19477
+ const content = processAttachmentsInInput(event.content);
19478
+ const message = {
19479
+ role: event.type === "system.message" ? "system" : "user",
19480
+ content
19481
+ };
19482
+ state.history.push(message);
19483
+ if (state.activeTurn) {
19484
+ state.activeTurn.input.push(message);
19485
+ } else {
19486
+ state.pendingInput.push(message);
19487
+ }
19488
+ }
19489
+ function startAnthropicSessionModel(state, startEventId) {
19490
+ const turn = ensureAnthropicSessionTurn(state);
19491
+ if (turn.activeModel) {
19492
+ finalizeAnthropicSessionModelState(state, turn);
19493
+ }
19494
+ const span = withCurrent(
19495
+ turn.span,
19496
+ () => startSpan(
19497
+ withSpanInstrumentationName(
19498
+ {
19499
+ event: {
19500
+ ...state.history.length > 0 ? { input: state.history.slice() } : {},
19501
+ metadata: { provider: "anthropic" }
19502
+ },
19503
+ name: "anthropic.messages.create",
19504
+ spanAttributes: { type: "llm" /* LLM */ }
19505
+ },
19506
+ INSTRUMENTATION_NAMES.ANTHROPIC
19507
+ )
19508
+ )
19509
+ );
19510
+ turn.activeModel = {
19511
+ output: [],
19512
+ span,
19513
+ startEventId,
19514
+ startTime: getCurrentUnixTimestamp()
19515
+ };
19516
+ }
19517
+ function recordAnthropicSessionFirstToken(state, event) {
19518
+ const model = state.activeTurn?.activeModel;
19519
+ if (!model || model.firstTokenTime !== void 0 || !isObject(event.delta) || !isObject(event.delta.content) || typeof event.delta.content.text !== "string") {
19520
+ return;
19521
+ }
19522
+ model.firstTokenTime = getCurrentUnixTimestamp();
19523
+ }
19524
+ function recordAnthropicSessionMessage(state, event) {
19525
+ const turn = ensureAnthropicSessionTurn(state);
19526
+ const content = processAttachmentsInInput(
19527
+ event.content
19528
+ );
19529
+ if (turn.activeModel) {
19530
+ turn.activeModel.output.push(...content);
19531
+ } else {
19532
+ const output = { role: "assistant", content };
19533
+ turn.lastOutput = output;
19534
+ state.history.push(output);
19535
+ }
19536
+ }
19537
+ function startAnthropicSessionTool(state, event) {
19538
+ const turn = ensureAnthropicSessionTurn(state);
19539
+ if (turn.activeModel) {
19540
+ turn.activeModel.output.push({
19541
+ type: "tool_use",
19542
+ id: event.id,
19543
+ name: event.name,
19544
+ input: event.input
19545
+ });
19546
+ }
19547
+ const existing = turn.activeTools.get(event.id);
19548
+ if (existing) {
19549
+ existing.span.end();
19550
+ turn.activeTools.delete(event.id);
19551
+ }
19552
+ const span = withCurrent(
19553
+ turn.span,
19554
+ () => startSpan(
19555
+ withSpanInstrumentationName(
19556
+ {
19557
+ event: { input: event.input },
19558
+ name: event.name,
19559
+ spanAttributes: { type: "tool" /* TOOL */ }
19560
+ },
19561
+ INSTRUMENTATION_NAMES.ANTHROPIC
19562
+ )
19563
+ )
19564
+ );
19565
+ const toolState = {
19566
+ approval: event.evaluated_permission === "allow" ? "approved" : event.evaluated_permission === "deny" ? "denied" : void 0,
19567
+ span
19568
+ };
19569
+ turn.activeTools.set(event.id, toolState);
19570
+ if (toolState.approval === "denied") {
19571
+ finalizeAnthropicSessionToolState(toolState);
19572
+ turn.activeTools.delete(event.id);
19573
+ }
19574
+ }
19575
+ function recordAnthropicSessionToolConfirmation(state, event) {
19576
+ if (typeof event.tool_use_id !== "string" || event.result !== "allow" && event.result !== "deny") {
19577
+ return;
19578
+ }
19579
+ const turn = state.activeTurn;
19580
+ const tool = turn?.activeTools.get(event.tool_use_id);
19581
+ if (!turn || !tool) {
19582
+ return;
19583
+ }
19584
+ tool.approval = event.result === "allow" ? "approved" : "denied";
19585
+ if (tool.approval === "denied") {
19586
+ finalizeAnthropicSessionToolState(tool);
19587
+ turn.activeTools.delete(event.tool_use_id);
19588
+ }
19589
+ }
19590
+ function finalizeAnthropicSessionTool(state, event) {
19591
+ const toolUseId = event.tool_use_id ?? event.mcp_tool_use_id ?? event.custom_tool_use_id;
19592
+ if (!toolUseId) {
19593
+ return;
19594
+ }
19595
+ const content = processAttachmentsInInput(event.content);
19596
+ const turn = state.activeTurn;
19597
+ const tool = turn?.activeTools.get(toolUseId);
19598
+ if (turn && tool) {
19599
+ finalizeAnthropicSessionToolState(tool, event, content);
19600
+ turn.activeTools.delete(toolUseId);
19601
+ }
19602
+ const toolResult = {
19603
+ type: "tool_result",
19604
+ tool_use_id: toolUseId,
19605
+ ...content !== void 0 ? { content } : {},
19606
+ ...event.is_error === true ? { is_error: true } : {}
19607
+ };
19608
+ state.history.push({
19609
+ role: "user",
19610
+ content: [toolResult]
19611
+ });
19612
+ }
19613
+ function finalizeAnthropicSessionToolState(state, event, content = event?.content) {
19614
+ safeAnthropicSessionLog(state.span, {
19615
+ ...event?.is_error === true ? {
19616
+ error: content ?? "Anthropic session tool execution failed"
19617
+ } : {},
19618
+ ...state.approval ? { metadata: { tool_approval: state.approval } } : {},
19619
+ ...content !== void 0 ? { output: content } : {}
19620
+ });
19621
+ state.span.end();
19622
+ }
19623
+ function finalizeAnthropicSessionModel(state, event) {
19624
+ const turn = state.activeTurn;
19625
+ const model = turn?.activeModel;
19626
+ if (!turn || !model || model.startEventId !== event.model_request_start_id) {
19627
+ return;
19628
+ }
19629
+ finalizeAnthropicSessionModelState(state, turn, event);
19630
+ }
19631
+ function finalizeAnthropicSessionModelState(state, turn, event) {
19632
+ const model = turn.activeModel;
19633
+ if (!model) {
19634
+ return;
19635
+ }
19636
+ turn.activeModel = void 0;
19637
+ const metrics = event ? parseAnthropicSessionModelUsage(event.model_usage) : {};
19638
+ if (model.firstTokenTime !== void 0) {
19639
+ metrics.time_to_first_token = model.firstTokenTime - model.startTime;
19640
+ }
19641
+ const output = model.output.length > 0 ? { role: "assistant", content: model.output } : void 0;
19642
+ safeAnthropicSessionLog(model.span, {
19643
+ ...event?.is_error ? { error: "Anthropic session model request failed" } : {},
19644
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
19645
+ ...output ? { output } : {}
19646
+ });
19647
+ model.span.end();
19648
+ if (output) {
19649
+ turn.lastOutput = output;
19650
+ state.history.push(output);
19651
+ }
19652
+ for (const key of [
19653
+ "prompt_tokens",
19654
+ "completion_tokens",
19655
+ "tokens",
19656
+ "prompt_cached_tokens",
19657
+ "prompt_cache_creation_tokens"
19658
+ ]) {
19659
+ const value = metrics[key];
19660
+ if (typeof value === "number") {
19661
+ turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
19662
+ }
19663
+ }
19664
+ }
19665
+ function parseAnthropicSessionModelUsage(usage) {
19666
+ const finalized = finalizeAnthropicTokens({
19667
+ completion_tokens: usage.output_tokens,
19668
+ prompt_cache_creation_tokens: usage.cache_creation_input_tokens,
19669
+ prompt_cached_tokens: usage.cache_read_input_tokens,
19670
+ prompt_tokens: usage.input_tokens
19671
+ });
19672
+ return Object.fromEntries(
19673
+ Object.entries(finalized).filter(
19674
+ (entry) => entry[1] !== void 0
19675
+ )
19676
+ );
19677
+ }
19678
+ function finalizeAnthropicSessionTurn(state, error) {
19679
+ const turn = state.activeTurn;
19680
+ if (!turn) {
19681
+ return;
19682
+ }
19683
+ state.activeTurn = void 0;
19684
+ finalizeAnthropicSessionModelState(state, turn);
19685
+ for (const tool of turn.activeTools.values()) {
19686
+ finalizeAnthropicSessionToolState(tool);
19687
+ }
19688
+ turn.activeTools.clear();
19689
+ safeAnthropicSessionLog(turn.span, {
19690
+ ...error !== void 0 ? { error: error instanceof Error ? error : toLoggedError(error) } : {},
19691
+ ...turn.input.length > 0 ? { input: turn.input } : {},
19692
+ ...turn.lastOutput ? { output: turn.lastOutput } : {},
19693
+ ...Object.keys(turn.metrics).length > 0 ? { metrics: turn.metrics } : {}
19694
+ });
19695
+ turn.span.end();
19696
+ }
19697
+ function safeAnthropicSessionLog(span, event) {
19698
+ try {
19699
+ span.log(event);
19700
+ } catch (error) {
19701
+ debugLogger.debug("Error logging Anthropic Sessions span:", error);
19702
+ }
19703
+ }
19090
19704
  function parseMetricsFromUsage2(usage) {
19091
19705
  if (!usage) {
19092
19706
  return {};
@@ -21145,6 +21759,283 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
21145
21759
  }
21146
21760
  };
21147
21761
 
21762
+ // src/instrumentation/plugins/cloudflare-think-plugin.ts
21763
+ var THINK_STATE_ID = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.state-id");
21764
+ var CloudflareThinkPlugin = class extends BasePlugin {
21765
+ statesBySpanId = /* @__PURE__ */ new Map();
21766
+ onEnable() {
21767
+ this.subscribeToThinkRuns();
21768
+ this.subscribeToAISDKStreamTextSync();
21769
+ this.subscribeToAISDKStreamTextAsync();
21770
+ }
21771
+ onDisable() {
21772
+ for (const unsubscribe of this.unsubscribers) {
21773
+ unsubscribe();
21774
+ }
21775
+ this.unsubscribers = [];
21776
+ for (const state of this.statesBySpanId.values()) {
21777
+ this.finishState(state);
21778
+ }
21779
+ this.statesBySpanId.clear();
21780
+ }
21781
+ subscribeToThinkRuns() {
21782
+ const channel = cloudflareThinkChannels.runInferenceLoop.tracingChannel();
21783
+ const states = /* @__PURE__ */ new WeakMap();
21784
+ const state = _internalGetGlobalState();
21785
+ const contextManager = state?.contextManager;
21786
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
21787
+ const ensureState2 = (event) => {
21788
+ if (isAutoInstrumentationSuppressed()) {
21789
+ return void 0;
21790
+ }
21791
+ const existing = states.get(event);
21792
+ if (existing) {
21793
+ return existing;
21794
+ }
21795
+ const span = startSpan(
21796
+ withSpanInstrumentationName(
21797
+ {
21798
+ name: "Think.runTurn",
21799
+ spanAttributes: { type: "task" /* TASK */ }
21800
+ },
21801
+ INSTRUMENTATION_NAMES.CLOUDFLARE_THINK
21802
+ )
21803
+ );
21804
+ const runState = {
21805
+ aiResultPatched: false,
21806
+ fallbackInput: extractFallbackInput(event.self?.messages),
21807
+ finalized: false,
21808
+ inputLogged: false,
21809
+ span,
21810
+ startTime: getCurrentUnixTimestamp()
21811
+ };
21812
+ const metadata = {
21813
+ braintrust: {
21814
+ integration_name: "cloudflare-think",
21815
+ sdk_language: "typescript"
21816
+ }
21817
+ };
21818
+ if (typeof event.moduleVersion === "string") {
21819
+ metadata["cloudflare_think.version"] = event.moduleVersion;
21820
+ }
21821
+ span.log({ metadata });
21822
+ states.set(event, runState);
21823
+ if (span.spanId) {
21824
+ this.statesBySpanId.set(span.spanId, runState);
21825
+ }
21826
+ registerCloudflareThinkSpan(span);
21827
+ return runState;
21828
+ };
21829
+ if (contextManager && currentSpanStore && channel.start) {
21830
+ channel.start.bindStore(currentSpanStore, (event) => {
21831
+ const runState = ensureState2(event);
21832
+ return runState ? contextManager.wrapSpanForStore(runState.span) : currentSpanStore.getStore();
21833
+ });
21834
+ this.unsubscribers.push(
21835
+ () => channel.start?.unbindStore(currentSpanStore)
21836
+ );
21837
+ }
21838
+ const handlers = {
21839
+ start: (event) => {
21840
+ ensureState2(event);
21841
+ },
21842
+ asyncEnd: (event) => {
21843
+ const runState = states.get(event);
21844
+ states.delete(event);
21845
+ if (!runState || runState.finalized || runState.aiResultPatched) {
21846
+ return;
21847
+ }
21848
+ this.finishState(runState, void 0, event.result);
21849
+ },
21850
+ error: (event) => {
21851
+ const runState = states.get(event);
21852
+ states.delete(event);
21853
+ if (runState) {
21854
+ this.finishState(runState, event.error);
21855
+ }
21856
+ }
21857
+ };
21858
+ channel.subscribe(handlers);
21859
+ this.unsubscribers.push(() => channel.unsubscribe(handlers));
21860
+ }
21861
+ subscribeToAISDKStreamTextSync() {
21862
+ const channel = aiSDKChannels.streamTextSync.tracingChannel();
21863
+ const handlers = {
21864
+ start: (event) => {
21865
+ this.startAISDKStream(event);
21866
+ },
21867
+ end: (event) => {
21868
+ this.endAISDKStream(event);
21869
+ },
21870
+ error: (event) => {
21871
+ this.errorAISDKStream(event);
21872
+ }
21873
+ };
21874
+ channel.subscribe(handlers);
21875
+ this.unsubscribers.push(() => channel.unsubscribe(handlers));
21876
+ }
21877
+ subscribeToAISDKStreamTextAsync() {
21878
+ const channel = aiSDKChannels.streamText.tracingChannel();
21879
+ const handlers = {
21880
+ start: (event) => {
21881
+ this.startAISDKStream(event);
21882
+ },
21883
+ asyncEnd: (event) => {
21884
+ this.endAISDKStream(event);
21885
+ },
21886
+ error: (event) => {
21887
+ this.errorAISDKStream(event);
21888
+ }
21889
+ };
21890
+ channel.subscribe(handlers);
21891
+ this.unsubscribers.push(() => channel.unsubscribe(handlers));
21892
+ }
21893
+ startAISDKStream(event) {
21894
+ const runState = this.currentState();
21895
+ if (!runState || runState.finalized) {
21896
+ return;
21897
+ }
21898
+ try {
21899
+ const prepared = prepareAISDKAgentCallInput(
21900
+ event.arguments[0],
21901
+ event,
21902
+ runState.span
21903
+ );
21904
+ runState.span.log({
21905
+ input: extractThinkTaskInput(prepared.input),
21906
+ metadata: {
21907
+ ...prepared.metadata,
21908
+ braintrust: {
21909
+ integration_name: "cloudflare-think",
21910
+ sdk_language: "typescript"
21911
+ }
21912
+ }
21913
+ });
21914
+ runState.inputLogged = true;
21915
+ runState.aiEvent = event;
21916
+ Reflect.set(event, THINK_STATE_ID, runState.span.spanId);
21917
+ } catch (error) {
21918
+ debugLogger.error(
21919
+ "Error preparing @cloudflare/think AI SDK tracing:",
21920
+ error
21921
+ );
21922
+ }
21923
+ }
21924
+ endAISDKStream(event) {
21925
+ const runState = this.stateForAISDKEvent(event);
21926
+ if (!runState || runState.finalized) {
21927
+ return;
21928
+ }
21929
+ const patched = patchAISDKStreamingResult({
21930
+ defaultDenyOutputPaths: DEFAULT_DENY_OUTPUT_PATHS,
21931
+ endEvent: event,
21932
+ forceTopLevelMetrics: true,
21933
+ onComplete: () => this.releaseState(runState),
21934
+ result: event.result,
21935
+ span: runState.span,
21936
+ startTime: runState.startTime,
21937
+ transformOutput: extractThinkTaskOutput
21938
+ });
21939
+ runState.aiResultPatched = patched;
21940
+ if (!patched) {
21941
+ this.finishState(runState, void 0, event.result);
21942
+ }
21943
+ }
21944
+ errorAISDKStream(event) {
21945
+ const runState = this.stateForAISDKEvent(event);
21946
+ if (runState) {
21947
+ this.finishState(runState, event.error);
21948
+ }
21949
+ }
21950
+ currentState() {
21951
+ const parentIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
21952
+ for (const parentId of parentIds) {
21953
+ const state = this.statesBySpanId.get(parentId);
21954
+ if (state) {
21955
+ return state;
21956
+ }
21957
+ }
21958
+ return void 0;
21959
+ }
21960
+ stateForAISDKEvent(event) {
21961
+ const spanId = Reflect.get(event, THINK_STATE_ID);
21962
+ return typeof spanId === "string" ? this.statesBySpanId.get(spanId) : void 0;
21963
+ }
21964
+ finishState(state, error, output) {
21965
+ if (state.finalized) {
21966
+ return;
21967
+ }
21968
+ state.finalized = true;
21969
+ try {
21970
+ if (!state.inputLogged && state.fallbackInput !== void 0) {
21971
+ state.span.log({ input: state.fallbackInput });
21972
+ }
21973
+ if (error !== void 0) {
21974
+ state.span.log({ error });
21975
+ } else if (output !== void 0) {
21976
+ state.span.log({ output: extractThinkTaskOutput(output) });
21977
+ }
21978
+ finalizeAISDKChildTracing(state.aiEvent);
21979
+ state.span.end();
21980
+ } finally {
21981
+ this.releaseState(state);
21982
+ }
21983
+ }
21984
+ releaseState(state) {
21985
+ state.finalized = true;
21986
+ unregisterCloudflareThinkSpan(state.span);
21987
+ if (state.span.spanId) {
21988
+ this.statesBySpanId.delete(state.span.spanId);
21989
+ }
21990
+ }
21991
+ };
21992
+ function extractFallbackInput(messages) {
21993
+ if (!Array.isArray(messages) || messages.length === 0) {
21994
+ return void 0;
21995
+ }
21996
+ let latestUserIndex = -1;
21997
+ for (let index = messages.length - 1; index >= 0; index--) {
21998
+ if (messages[index]?.role === "user") {
21999
+ latestUserIndex = index;
22000
+ break;
22001
+ }
22002
+ }
22003
+ const selected = latestUserIndex >= 0 ? messages.slice(latestUserIndex) : [];
22004
+ return selected.map((message) => ({
22005
+ role: message.role,
22006
+ content: message.content ?? message.parts
22007
+ }));
22008
+ }
22009
+ function extractThinkTaskOutput(output) {
22010
+ if (!isObject(output)) {
22011
+ return output;
22012
+ }
22013
+ if (typeof output.text === "string") {
22014
+ return { role: "assistant", content: output.text };
22015
+ }
22016
+ if (output.object !== void 0) {
22017
+ return output.object;
22018
+ }
22019
+ return output;
22020
+ }
22021
+ function extractThinkTaskInput(input) {
22022
+ if (!isObject(input)) {
22023
+ return input;
22024
+ }
22025
+ const system = input.instructions ?? input.system;
22026
+ if (Array.isArray(input.messages)) {
22027
+ return system === void 0 ? input.messages : [{ role: "system", content: system }, ...input.messages];
22028
+ }
22029
+ if (Array.isArray(input.prompt)) {
22030
+ return system === void 0 ? input.prompt : [{ role: "system", content: system }, ...input.prompt];
22031
+ }
22032
+ if (typeof input.prompt === "string") {
22033
+ const messages = [{ role: "user", content: input.prompt }];
22034
+ return system === void 0 ? messages : [{ role: "system", content: system }, ...messages];
22035
+ }
22036
+ return input;
22037
+ }
22038
+
21148
22039
  // src/instrumentation/plugins/cursor-sdk-plugin.ts
21149
22040
  var PATCHED_AGENT = /* @__PURE__ */ Symbol.for("braintrust.cursor-sdk.auto-patched-agent");
21150
22041
  var PATCHED_RUN = /* @__PURE__ */ Symbol.for("braintrust.cursor-sdk.patched-run");
@@ -21168,7 +22059,7 @@ var CursorSDKPlugin = class extends BasePlugin {
21168
22059
  this.subscribeToAgentFactory(cursorSDKChannels.resume);
21169
22060
  }
21170
22061
  subscribeToAgentFactory(channel) {
21171
- const tracingChannel2 = channel.tracingChannel();
22062
+ const tracingChannel = channel.tracingChannel();
21172
22063
  const handlers = {
21173
22064
  asyncEnd: (event) => {
21174
22065
  patchCursorAgentInPlace(event.result);
@@ -21176,9 +22067,9 @@ var CursorSDKPlugin = class extends BasePlugin {
21176
22067
  error: () => {
21177
22068
  }
21178
22069
  };
21179
- tracingChannel2.subscribe(handlers);
22070
+ tracingChannel.subscribe(handlers);
21180
22071
  this.unsubscribers.push(() => {
21181
- tracingChannel2.unsubscribe(handlers);
22072
+ tracingChannel.unsubscribe(handlers);
21182
22073
  });
21183
22074
  }
21184
22075
  subscribeToPrompt() {
@@ -22486,10 +23377,10 @@ var GoogleGenAIPlugin = class extends BasePlugin {
22486
23377
  this.subscribeToInteractionsCreateChannel();
22487
23378
  }
22488
23379
  subscribeToGenerateContentChannel() {
22489
- const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
23380
+ const tracingChannel = googleGenAIChannels.generateContent.tracingChannel();
22490
23381
  const states = /* @__PURE__ */ new WeakMap();
22491
23382
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
22492
- tracingChannel2,
23383
+ tracingChannel,
22493
23384
  states,
22494
23385
  (event) => {
22495
23386
  const params = event.arguments[0];
@@ -22563,14 +23454,14 @@ var GoogleGenAIPlugin = class extends BasePlugin {
22563
23454
  logErrorAndEndSpan(states, event);
22564
23455
  }
22565
23456
  };
22566
- tracingChannel2.subscribe(handlers);
23457
+ tracingChannel.subscribe(handlers);
22567
23458
  this.unsubscribers.push(() => {
22568
23459
  unbindCurrentSpanStore?.();
22569
- tracingChannel2.unsubscribe(handlers);
23460
+ tracingChannel.unsubscribe(handlers);
22570
23461
  });
22571
23462
  }
22572
23463
  subscribeToGenerateContentStreamChannel() {
22573
- const tracingChannel2 = googleGenAIChannels.generateContentStream.tracingChannel();
23464
+ const tracingChannel = googleGenAIChannels.generateContentStream.tracingChannel();
22574
23465
  const handlers = {
22575
23466
  start: (event) => {
22576
23467
  const streamEvent = event;
@@ -22591,16 +23482,16 @@ var GoogleGenAIPlugin = class extends BasePlugin {
22591
23482
  error: () => {
22592
23483
  }
22593
23484
  };
22594
- tracingChannel2.subscribe(handlers);
23485
+ tracingChannel.subscribe(handlers);
22595
23486
  this.unsubscribers.push(() => {
22596
- tracingChannel2.unsubscribe(handlers);
23487
+ tracingChannel.unsubscribe(handlers);
22597
23488
  });
22598
23489
  }
22599
23490
  subscribeToEmbedContentChannel() {
22600
- const tracingChannel2 = googleGenAIChannels.embedContent.tracingChannel();
23491
+ const tracingChannel = googleGenAIChannels.embedContent.tracingChannel();
22601
23492
  const states = /* @__PURE__ */ new WeakMap();
22602
23493
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
22603
- tracingChannel2,
23494
+ tracingChannel,
22604
23495
  states,
22605
23496
  (event) => {
22606
23497
  const params = event.arguments[0];
@@ -22670,10 +23561,10 @@ var GoogleGenAIPlugin = class extends BasePlugin {
22670
23561
  logErrorAndEndSpan(states, event);
22671
23562
  }
22672
23563
  };
22673
- tracingChannel2.subscribe(handlers);
23564
+ tracingChannel.subscribe(handlers);
22674
23565
  this.unsubscribers.push(() => {
22675
23566
  unbindCurrentSpanStore?.();
22676
- tracingChannel2.unsubscribe(handlers);
23567
+ tracingChannel.unsubscribe(handlers);
22677
23568
  });
22678
23569
  }
22679
23570
  subscribeToInteractionsCreateChannel() {
@@ -22709,10 +23600,10 @@ function ensureSpanState(states, event, create) {
22709
23600
  states.set(event, created);
22710
23601
  return created;
22711
23602
  }
22712
- function bindCurrentSpanStoreToStart2(tracingChannel2, states, create) {
23603
+ function bindCurrentSpanStoreToStart2(tracingChannel, states, create) {
22713
23604
  const state = _internalGetGlobalState();
22714
23605
  const contextManager = state?.contextManager;
22715
- const startChannel = tracingChannel2.start;
23606
+ const startChannel = tracingChannel.start;
22716
23607
  const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
22717
23608
  if (!startChannel?.bindStore || !currentSpanStore) {
22718
23609
  return void 0;
@@ -23215,11 +24106,11 @@ function summarizeEmbedContentOutput(response) {
23215
24106
  };
23216
24107
  }
23217
24108
  function populateUsageMetrics(metrics, usage) {
23218
- if (usage.promptTokenCount !== void 0) {
23219
- metrics.prompt_tokens = usage.promptTokenCount;
24109
+ if (usage.promptTokenCount !== void 0 || usage.toolUsePromptTokenCount !== void 0) {
24110
+ metrics.prompt_tokens = (usage.promptTokenCount ?? 0) + (usage.toolUsePromptTokenCount ?? 0);
23220
24111
  }
23221
- if (usage.candidatesTokenCount !== void 0) {
23222
- metrics.completion_tokens = usage.candidatesTokenCount;
24112
+ if (usage.candidatesTokenCount !== void 0 || usage.thoughtsTokenCount !== void 0) {
24113
+ metrics.completion_tokens = (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0);
23223
24114
  }
23224
24115
  if (usage.totalTokenCount !== void 0) {
23225
24116
  metrics.tokens = usage.totalTokenCount;
@@ -23230,13 +24121,26 @@ function populateUsageMetrics(metrics, usage) {
23230
24121
  if (usage.thoughtsTokenCount !== void 0) {
23231
24122
  metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
23232
24123
  }
24124
+ for (const detail of usage.promptTokensDetails ?? []) {
24125
+ if (detail.modality === "AUDIO" && detail.tokenCount !== void 0) {
24126
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokenCount;
24127
+ }
24128
+ }
24129
+ for (const detail of usage.candidatesTokensDetails ?? []) {
24130
+ if (detail.modality === "AUDIO" && detail.tokenCount !== void 0) {
24131
+ metrics.completion_audio_tokens = (metrics.completion_audio_tokens ?? 0) + detail.tokenCount;
24132
+ }
24133
+ if (detail.modality === "IMAGE" && detail.tokenCount !== void 0) {
24134
+ metrics.completion_image_tokens = (metrics.completion_image_tokens ?? 0) + detail.tokenCount;
24135
+ }
24136
+ }
23233
24137
  }
23234
24138
  function populateInteractionUsageMetrics(metrics, usage) {
23235
24139
  if (typeof usage.total_input_tokens === "number") {
23236
24140
  metrics.prompt_tokens = usage.total_input_tokens;
23237
24141
  }
23238
24142
  if (typeof usage.total_output_tokens === "number") {
23239
- metrics.completion_tokens = usage.total_output_tokens;
24143
+ metrics.completion_tokens = usage.total_output_tokens + (typeof usage.total_thought_tokens === "number" ? usage.total_thought_tokens : 0);
23240
24144
  }
23241
24145
  if (typeof usage.total_tokens === "number") {
23242
24146
  metrics.tokens = usage.total_tokens;
@@ -23247,6 +24151,24 @@ function populateInteractionUsageMetrics(metrics, usage) {
23247
24151
  if (typeof usage.total_thought_tokens === "number") {
23248
24152
  metrics.completion_reasoning_tokens = usage.total_thought_tokens;
23249
24153
  }
24154
+ for (const detail of Array.isArray(usage.input_tokens_by_modality) ? usage.input_tokens_by_modality : []) {
24155
+ if (typeof detail?.modality === "string" && detail.modality.toLowerCase() === "audio" && typeof detail.tokens === "number") {
24156
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokens;
24157
+ }
24158
+ }
24159
+ for (const detail of Array.isArray(usage.output_tokens_by_modality) ? usage.output_tokens_by_modality : []) {
24160
+ if (typeof detail?.modality !== "string" || typeof detail.tokens !== "number") {
24161
+ continue;
24162
+ }
24163
+ switch (detail.modality.toLowerCase()) {
24164
+ case "audio":
24165
+ metrics.completion_audio_tokens = (metrics.completion_audio_tokens ?? 0) + detail.tokens;
24166
+ break;
24167
+ case "image":
24168
+ metrics.completion_image_tokens = (metrics.completion_image_tokens ?? 0) + detail.tokens;
24169
+ break;
24170
+ }
24171
+ }
23250
24172
  }
23251
24173
  function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
23252
24174
  const end = getCurrentUnixTimestamp();
@@ -23957,6 +24879,259 @@ function extractTextGenerationStreamMetadata(chunks) {
23957
24879
  return void 0;
23958
24880
  }
23959
24881
 
24882
+ // src/instrumentation/plugins/huggingface-transformers-plugin.ts
24883
+ var REQUEST_METADATA_KEYS = [
24884
+ "temperature",
24885
+ "top_p",
24886
+ "max_tokens",
24887
+ "stop"
24888
+ ];
24889
+ var HuggingFaceTransformersPlugin = class extends BasePlugin {
24890
+ onEnable() {
24891
+ this.subscribeToPipelineFactory();
24892
+ this.unsubscribers.push(
24893
+ traceAsyncChannel(huggingFaceTransformersChannels.pipelineCall, {
24894
+ name: (_args, event) => {
24895
+ const task = getTask(event);
24896
+ const operation = task?.replaceAll("-", "_") ?? "unknown";
24897
+ return `huggingface.transformers.${operation}`;
24898
+ },
24899
+ type: "llm" /* LLM */,
24900
+ shouldTrace: (_args, event) => isSupportedHuggingFaceTransformersTask(
24901
+ getTask(event)
24902
+ ),
24903
+ extractInput: (args, event) => ({
24904
+ input: extractInput(
24905
+ getTask(event),
24906
+ args
24907
+ ),
24908
+ metadata: extractMetadata(
24909
+ event,
24910
+ args
24911
+ )
24912
+ }),
24913
+ extractOutput: (result, event) => extractOutput(
24914
+ getTask(event),
24915
+ result
24916
+ ),
24917
+ extractMetrics: () => ({})
24918
+ })
24919
+ );
24920
+ }
24921
+ onDisable() {
24922
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
24923
+ }
24924
+ subscribeToPipelineFactory() {
24925
+ const channel = huggingFaceTransformersChannels.pipeline.tracingChannel();
24926
+ const handlers = {
24927
+ asyncEnd: (event) => {
24928
+ if (typeof event.result !== "function") {
24929
+ return;
24930
+ }
24931
+ registerHuggingFaceTransformersPipeline(
24932
+ event.result,
24933
+ event.arguments?.[0],
24934
+ event.arguments?.[1]
24935
+ );
24936
+ }
24937
+ };
24938
+ channel.subscribe(handlers);
24939
+ this.unsubscribers.push(() => channel.unsubscribe(handlers));
24940
+ }
24941
+ };
24942
+ function getTask(event) {
24943
+ const self = event.self;
24944
+ const registeredTask = getHuggingFaceTransformersPipelineInfo(self)?.task;
24945
+ if (registeredTask !== void 0) {
24946
+ return registeredTask;
24947
+ }
24948
+ if (typeof self?.task === "string") {
24949
+ return self.task;
24950
+ }
24951
+ return void 0;
24952
+ }
24953
+ function extractMetadata(event, args) {
24954
+ const metadata = {
24955
+ provider: "huggingface"
24956
+ };
24957
+ const registeredModel = getHuggingFaceTransformersPipelineInfo(
24958
+ event.self
24959
+ )?.model;
24960
+ const model = registeredModel ?? modelIdentifier(event.self);
24961
+ if (model) {
24962
+ metadata.model = model;
24963
+ }
24964
+ const task = getTask(event);
24965
+ const options = task === "question-answering" ? args[2] : args[1];
24966
+ if (isObject(options)) {
24967
+ for (const key of REQUEST_METADATA_KEYS) {
24968
+ if (options[key] !== void 0) {
24969
+ metadata[key] = options[key];
24970
+ }
24971
+ }
24972
+ }
24973
+ return metadata;
24974
+ }
24975
+ function modelIdentifier(pipeline) {
24976
+ const model = pipeline?.model;
24977
+ if (!isObject(model)) {
24978
+ return void 0;
24979
+ }
24980
+ const config = isObject(model.config) ? model.config : void 0;
24981
+ for (const value of [
24982
+ config?._name_or_path,
24983
+ config?.name_or_path,
24984
+ config?.model_id,
24985
+ config?.modelId,
24986
+ model.name
24987
+ ]) {
24988
+ if (typeof value === "string" && value.length > 0) {
24989
+ return value;
24990
+ }
24991
+ }
24992
+ return void 0;
24993
+ }
24994
+ function extractInput(task, args) {
24995
+ switch (task) {
24996
+ case "feature-extraction":
24997
+ return args[0];
24998
+ case "question-answering": {
24999
+ const question = args[0];
25000
+ const context = args[1];
25001
+ if (Array.isArray(question) && Array.isArray(context) && question.every((value) => typeof value === "string") && context.every((value) => typeof value === "string")) {
25002
+ return question.map((value, index) => [
25003
+ {
25004
+ role: "user",
25005
+ content: `Context:
25006
+ ${context[index] ?? ""}
25007
+
25008
+ Question:
25009
+ ${value}`
25010
+ }
25011
+ ]);
25012
+ }
25013
+ if (typeof question === "string" && typeof context === "string") {
25014
+ return [
25015
+ {
25016
+ role: "user",
25017
+ content: `Context:
25018
+ ${context}
25019
+
25020
+ Question:
25021
+ ${question}`
25022
+ }
25023
+ ];
25024
+ }
25025
+ return { context, question };
25026
+ }
25027
+ }
25028
+ const input = args[0];
25029
+ if (task === "text-generation" && isChat(input)) {
25030
+ return input;
25031
+ }
25032
+ if (task === "text-generation" && Array.isArray(input) && input.every(isChat)) {
25033
+ return input;
25034
+ }
25035
+ if (typeof input === "string") {
25036
+ return [{ role: "user", content: input }];
25037
+ }
25038
+ if (Array.isArray(input) && input.every((value) => typeof value === "string")) {
25039
+ return input.map((value) => [
25040
+ {
25041
+ role: "user",
25042
+ content: value
25043
+ }
25044
+ ]);
25045
+ }
25046
+ return input;
25047
+ }
25048
+ function isChat(value) {
25049
+ return Array.isArray(value) && value.length > 0 && value.every(
25050
+ (message) => isObject(message) && typeof message.role === "string" && "content" in message
25051
+ );
25052
+ }
25053
+ function extractOutput(task, result) {
25054
+ switch (task) {
25055
+ case "feature-extraction":
25056
+ return summarizeEmbedding(result);
25057
+ case "question-answering":
25058
+ return choicesFromAnswers(result);
25059
+ default:
25060
+ return choicesFromGenerations(result);
25061
+ }
25062
+ }
25063
+ function summarizeEmbedding(result) {
25064
+ if (!isObject(result) || !Array.isArray(result.dims)) {
25065
+ return void 0;
25066
+ }
25067
+ const { dims } = result;
25068
+ if (dims.length === 0 || !dims.every((dimension) => typeof dimension === "number")) {
25069
+ return void 0;
25070
+ }
25071
+ if (dims.length === 1) {
25072
+ return { embedding_length: dims[0] };
25073
+ }
25074
+ if (dims.length === 2) {
25075
+ return {
25076
+ embedding_count: dims[0],
25077
+ embedding_length: dims[1]
25078
+ };
25079
+ }
25080
+ return {
25081
+ embedding_batch_count: dims[0],
25082
+ embedding_count: dims[1],
25083
+ embedding_length: dims.at(-1) ?? 0
25084
+ };
25085
+ }
25086
+ function choicesFromAnswers(result) {
25087
+ const answers = Array.isArray(result) ? result.flat() : [result];
25088
+ const choices = answers.flatMap((answer, index) => {
25089
+ if (!isObject(answer) || typeof answer.answer !== "string") {
25090
+ return [];
25091
+ }
25092
+ return [
25093
+ {
25094
+ index,
25095
+ finish_reason: "stop",
25096
+ message: {
25097
+ role: "assistant",
25098
+ content: answer.answer
25099
+ }
25100
+ }
25101
+ ];
25102
+ });
25103
+ return choices.length > 0 ? choices : void 0;
25104
+ }
25105
+ function choicesFromGenerations(result) {
25106
+ const generations = Array.isArray(result) ? result.flat() : [result];
25107
+ const choices = generations.flatMap((generation, index) => {
25108
+ if (!isObject(generation)) {
25109
+ return [];
25110
+ }
25111
+ const generated = generation.generated_text ?? generation.summary_text;
25112
+ let content;
25113
+ if (typeof generated === "string") {
25114
+ content = generated;
25115
+ } else if (isChat(generated)) {
25116
+ content = generated.at(-1)?.content;
25117
+ }
25118
+ if (typeof content !== "string") {
25119
+ return [];
25120
+ }
25121
+ return [
25122
+ {
25123
+ index,
25124
+ finish_reason: "stop",
25125
+ message: {
25126
+ role: "assistant",
25127
+ content
25128
+ }
25129
+ }
25130
+ ];
25131
+ });
25132
+ return choices.length > 0 ? choices : void 0;
25133
+ }
25134
+
23960
25135
  // src/instrumentation/plugins/openrouter-agent-plugin.ts
23961
25136
  var OpenRouterAgentPlugin = class extends BasePlugin {
23962
25137
  onEnable() {
@@ -24336,7 +25511,7 @@ function isWrappedTool(tool) {
24336
25511
  return Boolean(tool[OPENROUTER_WRAPPED_TOOL]);
24337
25512
  }
24338
25513
  function traceToolExecution(args) {
24339
- const tracingChannel2 = openRouterAgentChannels.toolExecute.tracingChannel();
25514
+ const tracingChannel = openRouterAgentChannels.toolExecute.tracingChannel();
24340
25515
  const input = args.args.length > 0 ? args.args[0] : void 0;
24341
25516
  const event = {
24342
25517
  arguments: [input],
@@ -24346,33 +25521,33 @@ function traceToolExecution(args) {
24346
25521
  toolCallId: args.toolCallId,
24347
25522
  toolName: args.toolName
24348
25523
  };
24349
- tracingChannel2.start.publish(event);
25524
+ tracingChannel.start.publish(event);
24350
25525
  try {
24351
25526
  const result = args.execute();
24352
- return publishToolResult(tracingChannel2, event, result);
25527
+ return publishToolResult(tracingChannel, event, result);
24353
25528
  } catch (error) {
24354
25529
  event.error = normalizeError(error);
24355
- tracingChannel2.error.publish(event);
25530
+ tracingChannel.error.publish(event);
24356
25531
  throw error;
24357
25532
  }
24358
25533
  }
24359
- function publishToolResult(tracingChannel2, event, result) {
25534
+ function publishToolResult(tracingChannel, event, result) {
24360
25535
  if (isPromiseLike(result)) {
24361
25536
  return result.then(
24362
25537
  (resolved) => {
24363
25538
  event.result = resolved;
24364
- tracingChannel2.asyncEnd.publish(event);
25539
+ tracingChannel.asyncEnd.publish(event);
24365
25540
  return resolved;
24366
25541
  },
24367
25542
  (error) => {
24368
25543
  event.error = normalizeError(error);
24369
- tracingChannel2.error.publish(event);
25544
+ tracingChannel.error.publish(event);
24370
25545
  throw error;
24371
25546
  }
24372
25547
  );
24373
25548
  }
24374
25549
  event.result = result;
24375
- tracingChannel2.asyncEnd.publish(event);
25550
+ tracingChannel.asyncEnd.publish(event);
24376
25551
  return result;
24377
25552
  }
24378
25553
  function getToolCallId(context) {
@@ -25242,7 +26417,7 @@ function isWrappedTool2(tool) {
25242
26417
  return Boolean(tool[OPENROUTER_WRAPPED_TOOL2]);
25243
26418
  }
25244
26419
  function traceToolExecution2(args) {
25245
- const tracingChannel2 = openRouterChannels.toolExecute.tracingChannel();
26420
+ const tracingChannel = openRouterChannels.toolExecute.tracingChannel();
25246
26421
  const input = args.args.length > 0 ? args.args[0] : void 0;
25247
26422
  const event = {
25248
26423
  arguments: [input],
@@ -25252,33 +26427,33 @@ function traceToolExecution2(args) {
25252
26427
  toolCallId: args.toolCallId,
25253
26428
  toolName: args.toolName
25254
26429
  };
25255
- tracingChannel2.start.publish(event);
26430
+ tracingChannel.start.publish(event);
25256
26431
  try {
25257
26432
  const result = args.execute();
25258
- return publishToolResult2(tracingChannel2, event, result);
26433
+ return publishToolResult2(tracingChannel, event, result);
25259
26434
  } catch (error) {
25260
26435
  event.error = normalizeError2(error);
25261
- tracingChannel2.error.publish(event);
26436
+ tracingChannel.error.publish(event);
25262
26437
  throw error;
25263
26438
  }
25264
26439
  }
25265
- function publishToolResult2(tracingChannel2, event, result) {
26440
+ function publishToolResult2(tracingChannel, event, result) {
25266
26441
  if (isPromiseLike(result)) {
25267
26442
  return result.then(
25268
26443
  (resolved) => {
25269
26444
  event.result = resolved;
25270
- tracingChannel2.asyncEnd.publish(event);
26445
+ tracingChannel.asyncEnd.publish(event);
25271
26446
  return resolved;
25272
26447
  },
25273
26448
  (error) => {
25274
26449
  event.error = normalizeError2(error);
25275
- tracingChannel2.error.publish(event);
26450
+ tracingChannel.error.publish(event);
25276
26451
  throw error;
25277
26452
  }
25278
26453
  );
25279
26454
  }
25280
26455
  event.result = result;
25281
- tracingChannel2.asyncEnd.publish(event);
26456
+ tracingChannel.asyncEnd.publish(event);
25282
26457
  return result;
25283
26458
  }
25284
26459
  function getToolCallId2(context) {
@@ -26378,6 +27553,450 @@ function aggregateMistralStreamChunks(chunks) {
26378
27553
  };
26379
27554
  }
26380
27555
 
27556
+ // src/instrumentation/plugins/ollama-plugin.ts
27557
+ var OllamaPlugin = class extends BasePlugin {
27558
+ onEnable() {
27559
+ this.unsubscribers.push(
27560
+ traceStreamingChannel(ollamaChannels.chat, {
27561
+ name: "ollama.chat",
27562
+ type: "llm" /* LLM */,
27563
+ extractInput: extractOllamaChatInput,
27564
+ extractOutput: (result, event) => extractOllamaChatOutput(
27565
+ result,
27566
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
27567
+ ),
27568
+ extractMetadata: extractOllamaResponseMetadata,
27569
+ extractMetrics: extractOllamaMetrics,
27570
+ aggregateChunks: aggregateOllamaChatChunks
27571
+ }),
27572
+ traceStreamingChannel(ollamaChannels.generate, {
27573
+ name: "ollama.generate",
27574
+ type: "llm" /* LLM */,
27575
+ extractInput: extractOllamaGenerateInput,
27576
+ extractOutput: extractOllamaGenerateOutput,
27577
+ extractMetadata: extractOllamaResponseMetadata,
27578
+ extractMetrics: extractOllamaMetrics,
27579
+ aggregateChunks: aggregateOllamaGenerateChunks
27580
+ }),
27581
+ traceAsyncChannel(ollamaChannels.embed, {
27582
+ name: "ollama.embed",
27583
+ type: "llm" /* LLM */,
27584
+ extractInput: extractOllamaEmbedInput,
27585
+ extractOutput: extractOllamaEmbedOutput,
27586
+ extractMetadata: extractOllamaResponseMetadata,
27587
+ extractMetrics: extractOllamaMetrics
27588
+ })
27589
+ );
27590
+ }
27591
+ onDisable() {
27592
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
27593
+ }
27594
+ };
27595
+ function isNonNegativeNumber(value) {
27596
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
27597
+ }
27598
+ function normalizeFinishReason(response, hasToolCalls = false) {
27599
+ if (hasToolCalls) {
27600
+ return "tool_calls";
27601
+ }
27602
+ return response?.done_reason || "stop";
27603
+ }
27604
+ function stringifyArguments(value) {
27605
+ if (typeof value === "string") {
27606
+ return value;
27607
+ }
27608
+ try {
27609
+ return JSON.stringify(value ?? {});
27610
+ } catch {
27611
+ return String(value);
27612
+ }
27613
+ }
27614
+ function syntheticToolCallId(name, index) {
27615
+ const normalizedName = name.replace(/[^a-zA-Z0-9_-]/g, "_") || "tool";
27616
+ return `ollama_call_${normalizedName}_${index}`;
27617
+ }
27618
+ function normalizeToolCall(toolCall, index) {
27619
+ const name = toolCall.function?.name;
27620
+ if (typeof name !== "string" || name.length === 0) {
27621
+ return void 0;
27622
+ }
27623
+ return {
27624
+ id: typeof toolCall.id === "string" && toolCall.id.length > 0 ? toolCall.id : syntheticToolCallId(name, index),
27625
+ type: "function",
27626
+ function: {
27627
+ name,
27628
+ arguments: stringifyArguments(toolCall.function?.arguments)
27629
+ }
27630
+ };
27631
+ }
27632
+ function normalizeToolCalls(toolCalls, syntheticIdOffset = 0) {
27633
+ if (!Array.isArray(toolCalls)) {
27634
+ return [];
27635
+ }
27636
+ return toolCalls.flatMap((toolCall, index) => {
27637
+ const normalized = normalizeToolCall(toolCall, syntheticIdOffset + index);
27638
+ return normalized ? [normalized] : [];
27639
+ });
27640
+ }
27641
+ function countOllamaToolCalls(messages) {
27642
+ if (!Array.isArray(messages)) {
27643
+ return 0;
27644
+ }
27645
+ return messages.reduce(
27646
+ (count, message) => count + (isObject(message) && Array.isArray(message.tool_calls) ? message.tool_calls.length : 0),
27647
+ 0
27648
+ );
27649
+ }
27650
+ function imageBytes(value) {
27651
+ if (value instanceof Uint8Array) {
27652
+ return value;
27653
+ }
27654
+ if (value instanceof ArrayBuffer) {
27655
+ return new Uint8Array(value);
27656
+ }
27657
+ if (typeof value !== "string" || value.startsWith("data:")) {
27658
+ return void 0;
27659
+ }
27660
+ try {
27661
+ const decoded = atob(value.slice(0, 24));
27662
+ return Uint8Array.from(decoded, (character) => character.charCodeAt(0));
27663
+ } catch {
27664
+ return void 0;
27665
+ }
27666
+ }
27667
+ function inferImageMediaType(value) {
27668
+ if (typeof value === "string") {
27669
+ const dataUrlType = value.match(/^data:(image\/[^;]+);base64,/i)?.[1];
27670
+ if (dataUrlType) {
27671
+ return dataUrlType;
27672
+ }
27673
+ }
27674
+ const bytes = imageBytes(value);
27675
+ if (!bytes) {
27676
+ return void 0;
27677
+ }
27678
+ if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
27679
+ return "image/png";
27680
+ }
27681
+ if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
27682
+ return "image/jpeg";
27683
+ }
27684
+ const signature = String.fromCharCode(...bytes.slice(0, 12));
27685
+ if (signature.startsWith("GIF87a") || signature.startsWith("GIF89a")) {
27686
+ return "image/gif";
27687
+ }
27688
+ if (signature.startsWith("RIFF") && signature.slice(8, 12) === "WEBP") {
27689
+ return "image/webp";
27690
+ }
27691
+ return void 0;
27692
+ }
27693
+ function normalizeTextAndImages(content, images) {
27694
+ if (!images || images.length === 0) {
27695
+ return { content };
27696
+ }
27697
+ const imageParts = [];
27698
+ const unrecognizedImages = [];
27699
+ for (const image of images) {
27700
+ let localImagePath;
27701
+ let localPathMediaType;
27702
+ if (typeof image === "string" && !/^data:/i.test(image) && !/^https?:\/\//i.test(image)) {
27703
+ const extension = image.match(/\.([a-z0-9]+)$/i)?.[1]?.toLowerCase();
27704
+ const extensionMediaType = {
27705
+ png: "image/png",
27706
+ jpg: "image/jpeg",
27707
+ jpeg: "image/jpeg",
27708
+ gif: "image/gif",
27709
+ webp: "image/webp"
27710
+ }[extension ?? ""];
27711
+ if (extensionMediaType && isomorph_default.statSync) {
27712
+ try {
27713
+ if (isomorph_default.statSync(image).isFile()) {
27714
+ localImagePath = image;
27715
+ localPathMediaType = extensionMediaType;
27716
+ }
27717
+ } catch {
27718
+ }
27719
+ }
27720
+ }
27721
+ const mediaType = localPathMediaType ?? inferImageMediaType(image);
27722
+ if (!mediaType) {
27723
+ unrecognizedImages.push(image);
27724
+ continue;
27725
+ }
27726
+ const processedImage = localImagePath ? new Attachment({
27727
+ data: localImagePath,
27728
+ filename: localImagePath.split(/[\\/]/).at(-1) ?? "image",
27729
+ contentType: mediaType
27730
+ }) : processInputAttachments({
27731
+ type: "image",
27732
+ image,
27733
+ mediaType
27734
+ }).image;
27735
+ imageParts.push({
27736
+ type: "image_url",
27737
+ image_url: { url: processedImage }
27738
+ });
27739
+ }
27740
+ return {
27741
+ content: imageParts.length > 0 ? [...content ? [{ type: "text", text: content }] : [], ...imageParts] : content,
27742
+ ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
27743
+ };
27744
+ }
27745
+ function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
27746
+ if (typeof message.role !== "string") {
27747
+ return void 0;
27748
+ }
27749
+ const toolCalls = normalizeToolCalls(
27750
+ message.tool_calls,
27751
+ syntheticToolCallIdOffset
27752
+ );
27753
+ if (message.role === "tool") {
27754
+ const toolName = typeof message.tool_name === "string" && message.tool_name.length > 0 ? message.tool_name : "tool";
27755
+ return {
27756
+ role: "tool",
27757
+ tool_call_id: toolCallId ?? syntheticToolCallId(toolName, 0),
27758
+ content: typeof message.content === "string" ? message.content : ""
27759
+ };
27760
+ }
27761
+ const normalizedContent = normalizeTextAndImages(
27762
+ typeof message.content === "string" ? message.content || (toolCalls.length > 0 ? null : "") : toolCalls.length > 0 ? null : "",
27763
+ message.images
27764
+ );
27765
+ return {
27766
+ role: message.role,
27767
+ content: normalizedContent.content,
27768
+ ...typeof message.thinking === "string" && message.thinking.length > 0 ? { reasoning: message.thinking } : {},
27769
+ ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {},
27770
+ ...normalizedContent.unrecognizedImages ? { images: normalizedContent.unrecognizedImages } : {}
27771
+ };
27772
+ }
27773
+ function normalizeMessages(messages) {
27774
+ if (!Array.isArray(messages)) {
27775
+ return [];
27776
+ }
27777
+ const pendingToolCallIds = /* @__PURE__ */ new Map();
27778
+ let syntheticToolCallIdOffset = 0;
27779
+ return messages.flatMap((message) => {
27780
+ if (!isObject(message)) {
27781
+ return [];
27782
+ }
27783
+ const ollamaMessage = message;
27784
+ let toolCallId;
27785
+ if (ollamaMessage.role === "tool") {
27786
+ const toolName = ollamaMessage.tool_name;
27787
+ if (typeof toolName === "string") {
27788
+ toolCallId = pendingToolCallIds.get(toolName)?.shift();
27789
+ }
27790
+ }
27791
+ const normalized = normalizeMessage(
27792
+ ollamaMessage,
27793
+ toolCallId,
27794
+ syntheticToolCallIdOffset
27795
+ );
27796
+ if (Array.isArray(ollamaMessage.tool_calls)) {
27797
+ syntheticToolCallIdOffset += ollamaMessage.tool_calls.length;
27798
+ }
27799
+ if (ollamaMessage.role === "assistant" && normalized) {
27800
+ const toolCalls = Array.isArray(normalized.tool_calls) ? normalized.tool_calls : [];
27801
+ for (const toolCall of toolCalls) {
27802
+ if (!isObject(toolCall) || !isObject(toolCall.function)) {
27803
+ continue;
27804
+ }
27805
+ const name = toolCall.function.name;
27806
+ const id = toolCall.id;
27807
+ if (typeof name === "string" && typeof id === "string") {
27808
+ const ids = pendingToolCallIds.get(name) ?? [];
27809
+ ids.push(id);
27810
+ pendingToolCallIds.set(name, ids);
27811
+ }
27812
+ }
27813
+ }
27814
+ return normalized ? [normalized] : [];
27815
+ });
27816
+ }
27817
+ function normalizeToolDefinition(tool) {
27818
+ const fn = tool.function;
27819
+ if (!fn || typeof fn.name !== "string" || fn.name.length === 0) {
27820
+ return void 0;
27821
+ }
27822
+ return {
27823
+ type: "function",
27824
+ function: {
27825
+ name: fn.name,
27826
+ ...typeof fn.description === "string" ? { description: fn.description } : {},
27827
+ ...isObject(fn.parameters) ? { parameters: fn.parameters } : {}
27828
+ }
27829
+ };
27830
+ }
27831
+ function extractToolsMetadata(tools) {
27832
+ if (!Array.isArray(tools)) {
27833
+ return {};
27834
+ }
27835
+ const normalized = tools.flatMap((tool) => {
27836
+ if (!isObject(tool)) {
27837
+ return [];
27838
+ }
27839
+ const definition = normalizeToolDefinition(tool);
27840
+ return definition ? [definition] : [];
27841
+ });
27842
+ return normalized.length > 0 ? { tools: normalized } : {};
27843
+ }
27844
+ function extractOptionsMetadata(options) {
27845
+ if (!isObject(options)) {
27846
+ return {};
27847
+ }
27848
+ const metadata = {};
27849
+ const mappings = [
27850
+ ["temperature", "temperature"],
27851
+ ["top_p", "top_p"],
27852
+ ["num_predict", "max_tokens"],
27853
+ ["frequency_penalty", "frequency_penalty"],
27854
+ ["presence_penalty", "presence_penalty"],
27855
+ ["stop", "stop"]
27856
+ ];
27857
+ for (const [source, target] of mappings) {
27858
+ if (options[source] !== void 0) {
27859
+ metadata[target] = options[source];
27860
+ }
27861
+ }
27862
+ return metadata;
27863
+ }
27864
+ function extractRequestMetadata(request) {
27865
+ return {
27866
+ provider: "ollama",
27867
+ ...typeof request?.model === "string" ? { model: request.model } : {},
27868
+ ...extractOptionsMetadata(request?.options),
27869
+ ...request?.format !== void 0 ? { response_format: request.format } : {}
27870
+ };
27871
+ }
27872
+ function extractOllamaChatInput([request]) {
27873
+ return {
27874
+ input: normalizeMessages(request.messages),
27875
+ metadata: {
27876
+ ...extractRequestMetadata(request),
27877
+ ...extractToolsMetadata(request.tools)
27878
+ }
27879
+ };
27880
+ }
27881
+ function extractOllamaGenerateInput([request]) {
27882
+ const normalizedPrompt = normalizeTextAndImages(
27883
+ typeof request.prompt === "string" ? request.prompt : "",
27884
+ Array.isArray(request.images) ? request.images : void 0
27885
+ );
27886
+ const input = [
27887
+ ...typeof request.system === "string" ? [{ role: "system", content: request.system }] : [],
27888
+ {
27889
+ role: "user",
27890
+ content: normalizedPrompt.content,
27891
+ ...typeof request.suffix === "string" ? { suffix: request.suffix } : {},
27892
+ ...normalizedPrompt.unrecognizedImages ? { images: normalizedPrompt.unrecognizedImages } : {}
27893
+ }
27894
+ ];
27895
+ return {
27896
+ input,
27897
+ metadata: extractRequestMetadata(request)
27898
+ };
27899
+ }
27900
+ function extractOllamaEmbedInput([request]) {
27901
+ return {
27902
+ input: request.input,
27903
+ metadata: extractRequestMetadata(request)
27904
+ };
27905
+ }
27906
+ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
27907
+ if (!isObject(result) || !isObject(result.message)) {
27908
+ return void 0;
27909
+ }
27910
+ const message = normalizeMessage(
27911
+ result.message,
27912
+ void 0,
27913
+ syntheticToolCallIdOffset
27914
+ );
27915
+ if (!message) {
27916
+ return void 0;
27917
+ }
27918
+ const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
27919
+ return [
27920
+ {
27921
+ index: 0,
27922
+ finish_reason: normalizeFinishReason(result, toolCalls.length > 0),
27923
+ message
27924
+ }
27925
+ ];
27926
+ }
27927
+ function extractOllamaGenerateOutput(result) {
27928
+ if (!isObject(result) || typeof result.response !== "string") {
27929
+ return void 0;
27930
+ }
27931
+ return [
27932
+ {
27933
+ index: 0,
27934
+ finish_reason: normalizeFinishReason(result),
27935
+ message: {
27936
+ role: "assistant",
27937
+ content: result.response,
27938
+ ...typeof result.thinking === "string" && result.thinking.length > 0 ? { reasoning: result.thinking } : {}
27939
+ }
27940
+ }
27941
+ ];
27942
+ }
27943
+ function extractOllamaEmbedOutput(result) {
27944
+ const embedding = Array.isArray(result?.embeddings) ? result.embeddings[0] : void 0;
27945
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
27946
+ }
27947
+ function extractOllamaResponseMetadata(result) {
27948
+ return typeof result?.model === "string" ? { model: result.model } : void 0;
27949
+ }
27950
+ function extractOllamaMetrics(result) {
27951
+ const metrics = {};
27952
+ const promptTokens = result?.prompt_eval_count;
27953
+ const completionTokens = result?.eval_count;
27954
+ if (isNonNegativeNumber(promptTokens)) {
27955
+ metrics.prompt_tokens = promptTokens;
27956
+ }
27957
+ if (isNonNegativeNumber(completionTokens)) {
27958
+ metrics.completion_tokens = completionTokens;
27959
+ }
27960
+ if (isNonNegativeNumber(promptTokens) || isNonNegativeNumber(completionTokens)) {
27961
+ metrics.tokens = (isNonNegativeNumber(promptTokens) ? promptTokens : 0) + (isNonNegativeNumber(completionTokens) ? completionTokens : 0);
27962
+ }
27963
+ return metrics;
27964
+ }
27965
+ function aggregateOllamaChatChunks(chunks, _result, event, _startTime) {
27966
+ const last = chunks.at(-1);
27967
+ const message = {
27968
+ role: "assistant",
27969
+ content: chunks.map((chunk) => chunk.message?.content ?? "").join(""),
27970
+ thinking: chunks.map((chunk) => chunk.message?.thinking ?? "").join(""),
27971
+ tool_calls: chunks.flatMap((chunk) => chunk.message?.tool_calls ?? [])
27972
+ };
27973
+ const response = {
27974
+ ...last,
27975
+ message
27976
+ };
27977
+ return {
27978
+ output: extractOllamaChatOutput(
27979
+ response,
27980
+ countOllamaToolCalls(event?.arguments?.[0]?.messages)
27981
+ ),
27982
+ metrics: extractOllamaMetrics(last ?? {}),
27983
+ metadata: extractOllamaResponseMetadata(last ?? {})
27984
+ };
27985
+ }
27986
+ function aggregateOllamaGenerateChunks(chunks, _result, _event, _startTime) {
27987
+ const last = chunks.at(-1);
27988
+ const response = {
27989
+ ...last,
27990
+ response: chunks.map((chunk) => chunk.response ?? "").join(""),
27991
+ thinking: chunks.map((chunk) => chunk.thinking ?? "").join("")
27992
+ };
27993
+ return {
27994
+ output: extractOllamaGenerateOutput(response),
27995
+ metrics: extractOllamaMetrics(last ?? {}),
27996
+ metadata: extractOllamaResponseMetadata(last ?? {})
27997
+ };
27998
+ }
27999
+
26381
28000
  // src/instrumentation/plugins/google-adk-plugin.ts
26382
28001
  var GoogleADKPlugin = class extends BasePlugin {
26383
28002
  activeRunnerSpans = /* @__PURE__ */ new Map();
@@ -26396,7 +28015,7 @@ var GoogleADKPlugin = class extends BasePlugin {
26396
28015
  this.activeAgentSpans.clear();
26397
28016
  }
26398
28017
  subscribeToRunnerRunAsync() {
26399
- const tracingChannel2 = googleADKChannels.runnerRunAsync.tracingChannel();
28018
+ const tracingChannel = googleADKChannels.runnerRunAsync.tracingChannel();
26400
28019
  const states = /* @__PURE__ */ new WeakMap();
26401
28020
  const createState = (event) => {
26402
28021
  const params = event.arguments[0] ?? {};
@@ -26427,7 +28046,7 @@ var GoogleADKPlugin = class extends BasePlugin {
26427
28046
  return { span, startTime, events: [], contextKey };
26428
28047
  };
26429
28048
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart3(
26430
- tracingChannel2,
28049
+ tracingChannel,
26431
28050
  states,
26432
28051
  createState
26433
28052
  );
@@ -26479,14 +28098,14 @@ var GoogleADKPlugin = class extends BasePlugin {
26479
28098
  states.delete(event);
26480
28099
  }
26481
28100
  };
26482
- tracingChannel2.subscribe(handlers);
28101
+ tracingChannel.subscribe(handlers);
26483
28102
  this.unsubscribers.push(() => {
26484
28103
  unbindCurrentSpanStore?.();
26485
- tracingChannel2.unsubscribe(handlers);
28104
+ tracingChannel.unsubscribe(handlers);
26486
28105
  });
26487
28106
  }
26488
28107
  subscribeToAgentRunAsync() {
26489
- const tracingChannel2 = googleADKChannels.agentRunAsync.tracingChannel();
28108
+ const tracingChannel = googleADKChannels.agentRunAsync.tracingChannel();
26490
28109
  const states = /* @__PURE__ */ new WeakMap();
26491
28110
  const createState = (event) => {
26492
28111
  const parentContext = event.arguments[0];
@@ -26535,7 +28154,7 @@ var GoogleADKPlugin = class extends BasePlugin {
26535
28154
  return { span, startTime, events: [], contextKey, name: agentName };
26536
28155
  };
26537
28156
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart3(
26538
- tracingChannel2,
28157
+ tracingChannel,
26539
28158
  states,
26540
28159
  createState
26541
28160
  );
@@ -26587,14 +28206,14 @@ var GoogleADKPlugin = class extends BasePlugin {
26587
28206
  states.delete(event);
26588
28207
  }
26589
28208
  };
26590
- tracingChannel2.subscribe(handlers);
28209
+ tracingChannel.subscribe(handlers);
26591
28210
  this.unsubscribers.push(() => {
26592
28211
  unbindCurrentSpanStore?.();
26593
- tracingChannel2.unsubscribe(handlers);
28212
+ tracingChannel.unsubscribe(handlers);
26594
28213
  });
26595
28214
  }
26596
28215
  subscribeToToolRunAsync() {
26597
- const tracingChannel2 = googleADKChannels.toolRunAsync.tracingChannel();
28216
+ const tracingChannel = googleADKChannels.toolRunAsync.tracingChannel();
26598
28217
  const states = /* @__PURE__ */ new WeakMap();
26599
28218
  const handlers = {
26600
28219
  start: (event) => {
@@ -26661,9 +28280,9 @@ var GoogleADKPlugin = class extends BasePlugin {
26661
28280
  states.delete(event);
26662
28281
  }
26663
28282
  };
26664
- tracingChannel2.subscribe(handlers);
28283
+ tracingChannel.subscribe(handlers);
26665
28284
  this.unsubscribers.push(() => {
26666
- tracingChannel2.unsubscribe(handlers);
28285
+ tracingChannel.unsubscribe(handlers);
26667
28286
  });
26668
28287
  }
26669
28288
  };
@@ -26739,10 +28358,10 @@ function bindAsyncIterableToCurrentSpan(stream, span) {
26739
28358
  }
26740
28359
  return stream;
26741
28360
  }
26742
- function bindCurrentSpanStoreToStart3(tracingChannel2, states, create) {
28361
+ function bindCurrentSpanStoreToStart3(tracingChannel, states, create) {
26743
28362
  const state = _internalGetGlobalState();
26744
28363
  const contextManager = state?.contextManager;
26745
- const startChannel = tracingChannel2.start;
28364
+ const startChannel = tracingChannel.start;
26746
28365
  const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
26747
28366
  if (!startChannel?.bindStore || !currentSpanStore) {
26748
28367
  return void 0;
@@ -26994,15 +28613,32 @@ function aggregateUsageFromEvents(events) {
26994
28613
  if (usage.thoughtsTokenCount !== void 0) {
26995
28614
  aggregated.thoughtsTokenCount = (aggregated.thoughtsTokenCount ?? 0) + usage.thoughtsTokenCount;
26996
28615
  }
28616
+ if (usage.toolUsePromptTokenCount !== void 0) {
28617
+ aggregated.toolUsePromptTokenCount = (aggregated.toolUsePromptTokenCount ?? 0) + usage.toolUsePromptTokenCount;
28618
+ }
28619
+ for (const detailsField of [
28620
+ "promptTokensDetails",
28621
+ "cacheTokensDetails",
28622
+ "candidatesTokensDetails",
28623
+ "toolUsePromptTokensDetails"
28624
+ ]) {
28625
+ const details = usage[detailsField];
28626
+ if (details !== void 0) {
28627
+ aggregated[detailsField] = [
28628
+ ...aggregated[detailsField] ?? [],
28629
+ ...details
28630
+ ];
28631
+ }
28632
+ }
26997
28633
  }
26998
28634
  return hasUsage ? aggregated : void 0;
26999
28635
  }
27000
28636
  function populateUsageMetrics2(metrics, usage) {
27001
- if (usage.promptTokenCount !== void 0) {
27002
- metrics.prompt_tokens = usage.promptTokenCount;
28637
+ if (usage.promptTokenCount !== void 0 || usage.toolUsePromptTokenCount !== void 0) {
28638
+ metrics.prompt_tokens = (usage.promptTokenCount ?? 0) + (usage.toolUsePromptTokenCount ?? 0);
27003
28639
  }
27004
- if (usage.candidatesTokenCount !== void 0) {
27005
- metrics.completion_tokens = usage.candidatesTokenCount;
28640
+ if (usage.candidatesTokenCount !== void 0 || usage.thoughtsTokenCount !== void 0) {
28641
+ metrics.completion_tokens = (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0);
27006
28642
  }
27007
28643
  if (usage.totalTokenCount !== void 0) {
27008
28644
  metrics.tokens = usage.totalTokenCount;
@@ -27013,6 +28649,19 @@ function populateUsageMetrics2(metrics, usage) {
27013
28649
  if (usage.thoughtsTokenCount !== void 0) {
27014
28650
  metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
27015
28651
  }
28652
+ for (const detail of usage.promptTokensDetails ?? []) {
28653
+ if (detail.modality === "AUDIO" && detail.tokenCount !== void 0) {
28654
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokenCount;
28655
+ }
28656
+ }
28657
+ for (const detail of usage.candidatesTokensDetails ?? []) {
28658
+ if (detail.modality === "AUDIO" && detail.tokenCount !== void 0) {
28659
+ metrics.completion_audio_tokens = (metrics.completion_audio_tokens ?? 0) + detail.tokenCount;
28660
+ }
28661
+ if (detail.modality === "IMAGE" && detail.tokenCount !== void 0) {
28662
+ metrics.completion_image_tokens = (metrics.completion_image_tokens ?? 0) + detail.tokenCount;
28663
+ }
28664
+ }
27016
28665
  }
27017
28666
  function cleanMetrics4(metrics) {
27018
28667
  const cleaned = {};
@@ -28469,10 +30118,10 @@ var GenkitPlugin = class extends BasePlugin {
28469
30118
  this.subscribeToActionStream();
28470
30119
  }
28471
30120
  subscribeToActionRun() {
28472
- const tracingChannel2 = genkitChannels.actionRun.tracingChannel();
30121
+ const tracingChannel = genkitChannels.actionRun.tracingChannel();
28473
30122
  const states = /* @__PURE__ */ new WeakMap();
28474
30123
  const unbindCurrentSpanStore = bindActionCurrentSpanStoreToStart(
28475
- tracingChannel2,
30124
+ tracingChannel,
28476
30125
  states,
28477
30126
  (event) => startActionRunSpan(event)
28478
30127
  );
@@ -28509,17 +30158,17 @@ var GenkitPlugin = class extends BasePlugin {
28509
30158
  states.delete(event);
28510
30159
  }
28511
30160
  };
28512
- tracingChannel2.subscribe(handlers);
30161
+ tracingChannel.subscribe(handlers);
28513
30162
  this.unsubscribers.push(() => {
28514
30163
  unbindCurrentSpanStore?.();
28515
- tracingChannel2.unsubscribe(handlers);
30164
+ tracingChannel.unsubscribe(handlers);
28516
30165
  });
28517
30166
  }
28518
30167
  subscribeToActionSpan() {
28519
- const tracingChannel2 = genkitCoreChannels.actionSpan.tracingChannel();
30168
+ const tracingChannel = genkitCoreChannels.actionSpan.tracingChannel();
28520
30169
  const states = /* @__PURE__ */ new WeakMap();
28521
30170
  const unbindCurrentSpanStore = bindActionCurrentSpanStoreToStart(
28522
- tracingChannel2,
30171
+ tracingChannel,
28523
30172
  states,
28524
30173
  (event) => startActionSpan(event)
28525
30174
  );
@@ -28557,10 +30206,10 @@ var GenkitPlugin = class extends BasePlugin {
28557
30206
  states.delete(event);
28558
30207
  }
28559
30208
  };
28560
- tracingChannel2.subscribe(handlers);
30209
+ tracingChannel.subscribe(handlers);
28561
30210
  this.unsubscribers.push(() => {
28562
30211
  unbindCurrentSpanStore?.();
28563
- tracingChannel2.unsubscribe(handlers);
30212
+ tracingChannel.unsubscribe(handlers);
28564
30213
  });
28565
30214
  }
28566
30215
  subscribeToActionStream() {
@@ -28629,10 +30278,10 @@ function ensureActionSpanState(states, event, create) {
28629
30278
  }
28630
30279
  return created;
28631
30280
  }
28632
- function bindActionCurrentSpanStoreToStart(tracingChannel2, states, create) {
30281
+ function bindActionCurrentSpanStoreToStart(tracingChannel, states, create) {
28633
30282
  const state = _internalGetGlobalState();
28634
30283
  const contextManager = state?.contextManager;
28635
- const startChannel = tracingChannel2.start;
30284
+ const startChannel = tracingChannel.start;
28636
30285
  const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
28637
30286
  if (!startChannel?.bindStore || !currentSpanStore) {
28638
30287
  return void 0;
@@ -29524,7 +31173,7 @@ var LangChainPlugin = class extends BasePlugin {
29524
31173
  this.injectedManagers = /* @__PURE__ */ new WeakSet();
29525
31174
  }
29526
31175
  subscribeToConfigure(channel) {
29527
- const tracingChannel2 = channel.tracingChannel();
31176
+ const tracingChannel = channel.tracingChannel();
29528
31177
  const handlers = {
29529
31178
  start: (event) => {
29530
31179
  injectHandlerIntoArguments(event.arguments);
@@ -29533,9 +31182,9 @@ var LangChainPlugin = class extends BasePlugin {
29533
31182
  this.injectHandler(event.result);
29534
31183
  }
29535
31184
  };
29536
- tracingChannel2.subscribe(handlers);
31185
+ tracingChannel.subscribe(handlers);
29537
31186
  this.unsubscribers.push(() => {
29538
- tracingChannel2.unsubscribe(handlers);
31187
+ tracingChannel.unsubscribe(handlers);
29539
31188
  });
29540
31189
  }
29541
31190
  injectHandler(result) {
@@ -29779,7 +31428,7 @@ var LangSmithPlugin = class extends BasePlugin {
29779
31428
  const inputs = preferOwnValue(run, previous, "inputs");
29780
31429
  const outputs = preferOwnValue(run, previous, "outputs");
29781
31430
  const error = errorMessage(preferOwnValue(run, previous, "error"));
29782
- const metadata = extractMetadata(run, previous);
31431
+ const metadata = extractMetadata2(run, previous);
29783
31432
  const tags = extractTags(preferOwnValue(run, previous, "tags"));
29784
31433
  const metrics = extractMetrics(run, previous);
29785
31434
  span.log({
@@ -29884,7 +31533,7 @@ function mapRunType(runType) {
29884
31533
  return "task" /* TASK */;
29885
31534
  }
29886
31535
  }
29887
- function extractMetadata(run, previous) {
31536
+ function extractMetadata2(run, previous) {
29888
31537
  const extra = preferOwnValue(run, previous, "extra");
29889
31538
  const rawMetadata = ownValue(extra, "metadata");
29890
31539
  if (!isRecord2(rawMetadata)) {
@@ -30024,12 +31673,13 @@ function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth
30024
31673
  }
30025
31674
 
30026
31675
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
30027
- var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
31676
+ var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
31677
+ var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
30028
31678
  var piPromptContextStore;
30029
31679
  var PiCodingAgentPlugin = class extends BasePlugin {
30030
31680
  activePromptStates = /* @__PURE__ */ new Set();
30031
31681
  onEnable() {
30032
- this.subscribeToPrompt();
31682
+ this.interceptPrompt();
30033
31683
  }
30034
31684
  onDisable() {
30035
31685
  for (const unsubscribe of this.unsubscribers) {
@@ -30037,65 +31687,74 @@ var PiCodingAgentPlugin = class extends BasePlugin {
30037
31687
  }
30038
31688
  this.unsubscribers = [];
30039
31689
  for (const state of [...this.activePromptStates]) {
30040
- void finalizePiPromptRun(state).catch((error) => {
30041
- logInstrumentationError4("Pi Coding Agent disable cleanup", error);
30042
- });
31690
+ finishPiPromptRun(state);
30043
31691
  }
30044
31692
  }
30045
- subscribeToPrompt() {
30046
- const channel = piCodingAgentChannels.prompt.tracingChannel();
30047
- const states = /* @__PURE__ */ new WeakMap();
30048
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel);
30049
- const handlers = {
30050
- start: (event) => {
30051
- const state = startPiPromptRun(event, (state2) => {
30052
- this.activePromptStates.delete(state2);
30053
- });
30054
- if (state) {
30055
- this.activePromptStates.add(state);
30056
- states.set(event, state);
30057
- }
30058
- },
30059
- asyncEnd: async (event) => {
30060
- const state = states.get(event);
30061
- if (!state) {
30062
- return;
30063
- }
30064
- states.delete(event);
30065
- state.promptCallEnded = true;
30066
- if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
30067
- if (!state.sawStreamFn) {
30068
- state.queued = true;
30069
- if (!state.streamPatchState.queuedPromptStates.includes(state)) {
30070
- state.streamPatchState.queuedPromptStates.push(state);
30071
- }
31693
+ interceptPrompt() {
31694
+ this.unsubscribers.push(
31695
+ piCodingAgentChannels.prompt.intercept(
31696
+ (target, thisArg, args, additional) => {
31697
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
31698
+ let state;
31699
+ try {
31700
+ state = startPiPromptRun(
31701
+ {
31702
+ ...additional,
31703
+ arguments: args,
31704
+ self: thisArg
31705
+ },
31706
+ (finalizedState) => {
31707
+ this.activePromptStates.delete(finalizedState);
31708
+ }
31709
+ );
31710
+ } catch (error) {
31711
+ logInstrumentationError4("Pi Coding Agent prompt start", error);
30072
31712
  }
30073
- return;
30074
- }
30075
- await finalizePiPromptRun(state);
30076
- },
30077
- error: async (event) => {
30078
- const state = states.get(event);
30079
- if (!state) {
30080
- return;
31713
+ if (!state) {
31714
+ return runWithAutoInstrumentationSuppressed(invokeTarget);
31715
+ }
31716
+ this.activePromptStates.add(state);
31717
+ return promptContextStore().run(
31718
+ state,
31719
+ () => runWithAutoInstrumentationSuppressed(() => {
31720
+ let result;
31721
+ try {
31722
+ result = invokeTarget();
31723
+ } catch (error) {
31724
+ finishPiPromptRun(state, error);
31725
+ throw error;
31726
+ }
31727
+ return Promise.resolve(result).then(
31728
+ (value) => {
31729
+ finishPiPromptCall(state);
31730
+ return value;
31731
+ },
31732
+ (error) => {
31733
+ finishPiPromptRun(state, error);
31734
+ throw error;
31735
+ }
31736
+ );
31737
+ })
31738
+ );
30081
31739
  }
30082
- states.delete(event);
30083
- await finalizePiPromptRun(state, event.error);
30084
- }
30085
- };
30086
- channel.subscribe(handlers);
30087
- this.unsubscribers.push(() => {
30088
- unbindAutoInstrumentationSuppression?.();
30089
- channel.unsubscribe(handlers);
30090
- });
31740
+ )
31741
+ );
30091
31742
  }
30092
31743
  };
31744
+ function finishPiPromptCall(state) {
31745
+ state.promptCallEnded = true;
31746
+ if (state.deferCompletionUntilTurnEnd && !state.turnEnded) {
31747
+ return;
31748
+ }
31749
+ finishPiPromptRun(state);
31750
+ }
30093
31751
  function startPiPromptRun(event, onFinalize) {
30094
31752
  const session = extractSession(event);
30095
31753
  const agent = session?.agent;
30096
31754
  if (!session || !isPiAgent(agent)) {
30097
31755
  return void 0;
30098
31756
  }
31757
+ installPiAgentInstrumentation(agent);
30099
31758
  const metadata = {
30100
31759
  ...extractSessionMetadata(session),
30101
31760
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -30117,9 +31776,7 @@ function startPiPromptRun(event, onFinalize) {
30117
31776
  INSTRUMENTATION_NAMES.PI_CODING_AGENT
30118
31777
  )
30119
31778
  );
30120
- const streamPatchState = installPiStreamPatch(agent);
30121
31779
  const options = event.arguments[1];
30122
- const promptText = event.arguments[0];
30123
31780
  const state = {
30124
31781
  activeLlmSpans: /* @__PURE__ */ new Set(),
30125
31782
  activeToolSpans: /* @__PURE__ */ new Map(),
@@ -30131,29 +31788,10 @@ function startPiPromptRun(event, onFinalize) {
30131
31788
  metrics: {},
30132
31789
  onFinalize,
30133
31790
  promptCallEnded: false,
30134
- ...typeof promptText === "string" ? { promptText } : {},
30135
- queued: false,
30136
31791
  span,
30137
- sawStreamFn: false,
30138
31792
  startTime: getCurrentUnixTimestamp(),
30139
- streamPatchState,
30140
31793
  turnEnded: false
30141
31794
  };
30142
- state.restorePromptContext = enterPiPromptContext(state);
30143
- streamPatchState.activePromptStates.add(state);
30144
- try {
30145
- state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
30146
- try {
30147
- await runWithAutoInstrumentationSuppressed(
30148
- () => handlePiAgentEvent(state, agentEvent)
30149
- );
30150
- } catch (error) {
30151
- logInstrumentationError4("Pi Coding Agent event", error);
30152
- }
30153
- });
30154
- } catch (error) {
30155
- logInstrumentationError4("Pi Coding Agent event subscription", error);
30156
- }
30157
31795
  return state;
30158
31796
  }
30159
31797
  function extractSession(event) {
@@ -30167,111 +31805,55 @@ function promptContextStore() {
30167
31805
  piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
30168
31806
  return piPromptContextStore;
30169
31807
  }
30170
- function currentPromptContextFrames() {
30171
- return promptContextStore().getStore()?.frames ?? [];
30172
- }
30173
31808
  function currentPiPromptState() {
30174
- const frames = currentPromptContextFrames();
30175
- return frames[frames.length - 1]?.state;
30176
- }
30177
- function enterPiPromptContext(state) {
30178
- const frame = {
30179
- id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
30180
- state
30181
- };
30182
- promptContextStore().enterWith({
30183
- frames: [...currentPromptContextFrames(), frame]
30184
- });
30185
- return () => {
30186
- const frames = currentPromptContextFrames().filter(
30187
- (candidate) => candidate.id !== frame.id
30188
- );
30189
- promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
30190
- };
30191
- }
30192
- function installPiStreamPatch(agent) {
30193
- const existing = piStreamPatchStates.get(agent);
30194
- if (existing) {
30195
- if (agent.streamFn !== existing.wrappedStreamFn) {
30196
- debugLogger.debug(
30197
- "Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
30198
- );
30199
- }
30200
- return existing;
30201
- }
30202
- const patchState = {
30203
- activePromptStates: /* @__PURE__ */ new Set(),
30204
- agent,
30205
- originalStreamFn: agent.streamFn,
30206
- queuedPromptStates: [],
30207
- wrappedStreamFn: agent.streamFn
30208
- };
30209
- patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
30210
- agent.streamFn = patchState.wrappedStreamFn;
30211
- piStreamPatchStates.set(agent, patchState);
30212
- return patchState;
30213
- }
30214
- function resolveStreamPromptState(patchState, context) {
30215
- let lastUserText;
30216
- if (Array.isArray(context.messages)) {
30217
- for (let i = context.messages.length - 1; i >= 0; i--) {
30218
- const message = context.messages[i];
30219
- if (isPiUserMessage(message)) {
30220
- if (typeof message.content === "string") {
30221
- lastUserText = message.content;
30222
- } else {
30223
- lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
30224
- }
30225
- break;
30226
- }
30227
- }
30228
- }
30229
- if (lastUserText !== void 0) {
30230
- const queuedMatch = patchState.queuedPromptStates.find(
30231
- (state) => state.promptText === lastUserText
30232
- );
30233
- if (queuedMatch) {
30234
- return queuedMatch;
30235
- }
30236
- const matches = [...patchState.activePromptStates].filter(
30237
- (state) => state.promptText === lastUserText
31809
+ return promptContextStore().getStore();
31810
+ }
31811
+ function installPiAgentInstrumentation(agent) {
31812
+ const existing = piAgentPatchStates.get(agent);
31813
+ if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
31814
+ const patchState = {
31815
+ originalStreamFn: agent.streamFn,
31816
+ wrappedStreamFn: agent.streamFn
31817
+ };
31818
+ patchState.wrappedStreamFn = makeInstrumentedStreamFn(
31819
+ agent,
31820
+ patchState.originalStreamFn
30238
31821
  );
30239
- if (matches.length === 1) {
30240
- return matches[0];
30241
- }
31822
+ agent.streamFn = patchState.wrappedStreamFn;
31823
+ piAgentPatchStates.set(agent, patchState);
30242
31824
  }
30243
- const contextState = currentPiPromptState();
30244
- if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
30245
- return contextState;
31825
+ if (piAgentEventSubscriptions.has(agent)) {
31826
+ return;
30246
31827
  }
30247
- if (patchState.activePromptStates.size === 1) {
30248
- return [...patchState.activePromptStates][0];
31828
+ try {
31829
+ agent.subscribe(async (event) => {
31830
+ const state = currentPiPromptState();
31831
+ if (!state || state.agent !== agent || state.finalized) {
31832
+ return;
31833
+ }
31834
+ try {
31835
+ await runWithAutoInstrumentationSuppressed(
31836
+ () => handlePiAgentEvent(state, event)
31837
+ );
31838
+ } catch (error) {
31839
+ logInstrumentationError4("Pi Coding Agent event", error);
31840
+ }
31841
+ });
31842
+ piAgentEventSubscriptions.add(agent);
31843
+ } catch (error) {
31844
+ logInstrumentationError4("Pi Coding Agent event subscription", error);
30249
31845
  }
30250
- return void 0;
30251
31846
  }
30252
- function makeSharedInstrumentedStreamFn(patchState) {
31847
+ function makeInstrumentedStreamFn(agent, originalStreamFn) {
30253
31848
  return async function instrumentedPiStreamFn(model, context, options) {
30254
- const state = resolveStreamPromptState(patchState, context);
30255
- if (!state) {
30256
- const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
30257
- model,
30258
- context,
30259
- options
30260
- ]);
30261
- return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
31849
+ const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
31850
+ const state = currentPiPromptState();
31851
+ if (!state || state.agent !== agent || state.finalized) {
31852
+ return invokeOriginal();
30262
31853
  }
30263
- state.sawStreamFn = true;
30264
- removeQueuedPromptState(state);
30265
- state.streamPatchState.eventPromptState = state;
30266
31854
  const llmState = await startPiLlmSpan(state, model, context, options);
30267
31855
  try {
30268
- const stream = await runWithAutoInstrumentationSuppressed(
30269
- () => Reflect.apply(patchState.originalStreamFn, this, [
30270
- model,
30271
- context,
30272
- options
30273
- ])
30274
- );
31856
+ const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
30275
31857
  return patchAssistantMessageStream(stream, state, llmState);
30276
31858
  } catch (error) {
30277
31859
  finishPiLlmSpan(state, llmState, void 0, error);
@@ -30418,13 +32000,6 @@ async function handlePiAgentEvent(state, event) {
30418
32000
  if (state.finalized) {
30419
32001
  return;
30420
32002
  }
30421
- const eventPromptState = state.streamPatchState.eventPromptState;
30422
- if (eventPromptState && eventPromptState !== state) {
30423
- return;
30424
- }
30425
- if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
30426
- return;
30427
- }
30428
32003
  switch (event.type) {
30429
32004
  case "message_end":
30430
32005
  if (isPiAssistantMessage(event.message)) {
@@ -30439,11 +32014,8 @@ async function handlePiAgentEvent(state, event) {
30439
32014
  addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
30440
32015
  }
30441
32016
  }
30442
- if (state.streamPatchState.eventPromptState === state) {
30443
- state.streamPatchState.eventPromptState = void 0;
30444
- }
30445
32017
  if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
30446
- await finalizePiPromptRun(state);
32018
+ finishPiPromptRun(state);
30447
32019
  }
30448
32020
  return;
30449
32021
  case "tool_execution_start":
@@ -30516,19 +32088,13 @@ function finishPiToolSpan(state, event) {
30516
32088
  }
30517
32089
  }
30518
32090
  }
30519
- async function finalizePiPromptRun(state, error) {
32091
+ function finishPiPromptRun(state, error) {
30520
32092
  if (state.finalized) {
30521
32093
  return;
30522
32094
  }
30523
32095
  state.finalized = true;
30524
32096
  state.onFinalize?.(state);
30525
- restorePiStreamFn(state);
30526
- try {
30527
- state.unsubscribeAgent?.();
30528
- } catch (unsubscribeError) {
30529
- logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
30530
- }
30531
- await finishOpenLlmSpans(state, error);
32097
+ finishOpenLlmSpans(state, error);
30532
32098
  finishOpenToolSpans(state, error);
30533
32099
  const metadata = {
30534
32100
  ...state.metadata,
@@ -30545,34 +32111,14 @@ async function finalizePiPromptRun(state, error) {
30545
32111
  output: state.output
30546
32112
  });
30547
32113
  } finally {
30548
- state.span.end();
30549
- }
30550
- }
30551
- function restorePiStreamFn(state) {
30552
- const patchState = state.streamPatchState;
30553
- patchState.activePromptStates.delete(state);
30554
- removeQueuedPromptState(state);
30555
- if (patchState.eventPromptState === state) {
30556
- patchState.eventPromptState = void 0;
30557
- }
30558
- state.restorePromptContext?.();
30559
- if (patchState.activePromptStates.size > 0) {
30560
- return;
30561
- }
30562
- if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
30563
- patchState.agent.streamFn = patchState.originalStreamFn;
30564
- }
30565
- piStreamPatchStates.delete(patchState.agent);
30566
- }
30567
- function removeQueuedPromptState(state) {
30568
- state.queued = false;
30569
- const queuedPromptStates = state.streamPatchState.queuedPromptStates;
30570
- const index = queuedPromptStates.indexOf(state);
30571
- if (index >= 0) {
30572
- queuedPromptStates.splice(index, 1);
32114
+ try {
32115
+ state.span.end();
32116
+ } catch (endError) {
32117
+ logInstrumentationError4("Pi Coding Agent prompt end", endError);
32118
+ }
30573
32119
  }
30574
32120
  }
30575
- async function finishOpenLlmSpans(state, error) {
32121
+ function finishOpenLlmSpans(state, error) {
30576
32122
  for (const llmState of [...state.activeLlmSpans]) {
30577
32123
  finishPiLlmSpan(state, llmState, void 0, error);
30578
32124
  }
@@ -30653,7 +32199,7 @@ function normalizeAssistantMessage(message) {
30653
32199
  (part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
30654
32200
  ).join("");
30655
32201
  const toolCalls = message.content.flatMap(
30656
- (part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
32202
+ (part) => part.type === "toolCall" ? [normalizeToolCall2(part)] : []
30657
32203
  );
30658
32204
  return {
30659
32205
  role: "assistant",
@@ -30688,13 +32234,13 @@ function normalizeUserContent(content) {
30688
32234
  return part;
30689
32235
  });
30690
32236
  }
30691
- function normalizeToolCall(toolCall) {
32237
+ function normalizeToolCall2(toolCall) {
30692
32238
  return {
30693
32239
  id: toolCall.id,
30694
32240
  type: "function",
30695
32241
  function: {
30696
32242
  name: toolCall.name,
30697
- arguments: stringifyArguments(toolCall.arguments)
32243
+ arguments: stringifyArguments2(toolCall.arguments)
30698
32244
  }
30699
32245
  };
30700
32246
  }
@@ -30877,7 +32423,7 @@ function cleanMetrics5(metrics) {
30877
32423
  }
30878
32424
  return cleaned;
30879
32425
  }
30880
- function stringifyArguments(value) {
32426
+ function stringifyArguments2(value) {
30881
32427
  if (typeof value === "string") {
30882
32428
  return value;
30883
32429
  }
@@ -30983,9 +32529,9 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
30983
32529
  });
30984
32530
  }
30985
32531
  subscribeToMultiAgentStream(channel, operation) {
30986
- const tracingChannel2 = channel.tracingChannel();
32532
+ const tracingChannel = channel.tracingChannel();
30987
32533
  const states = /* @__PURE__ */ new WeakMap();
30988
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(tracingChannel2);
32534
+ const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(tracingChannel);
30989
32535
  const handlers = {
30990
32536
  start: (event) => {
30991
32537
  const state = startMultiAgentStream(
@@ -31039,10 +32585,10 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
31039
32585
  states.delete(event);
31040
32586
  }
31041
32587
  };
31042
- tracingChannel2.subscribe(handlers);
32588
+ tracingChannel.subscribe(handlers);
31043
32589
  this.unsubscribers.push(() => {
31044
32590
  unbindAutoInstrumentationSuppression?.();
31045
- tracingChannel2.unsubscribe(handlers);
32591
+ tracingChannel.unsubscribe(handlers);
31046
32592
  });
31047
32593
  }
31048
32594
  };
@@ -31225,6 +32771,15 @@ function handleMultiAgentStreamEvent(state, event, activeChildParents) {
31225
32771
  logInstrumentationError5("Strands Agent SDK multi-agent event", error);
31226
32772
  }
31227
32773
  }
32774
+ function buildModelSpanInput(event, attachmentCache) {
32775
+ const systemPrompt = typeof event.agent?.systemPrompt === "string" && event.agent.systemPrompt.length > 0 ? event.agent.systemPrompt : void 0;
32776
+ const processedMessages = Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(event.agent.messages, attachmentCache) : void 0;
32777
+ if (!systemPrompt) {
32778
+ return processedMessages;
32779
+ }
32780
+ const systemMessage = { role: "system", content: systemPrompt };
32781
+ return Array.isArray(processedMessages) ? [systemMessage, ...processedMessages] : [systemMessage];
32782
+ }
31228
32783
  function startModelSpan(state, event) {
31229
32784
  if (state.activeModel) {
31230
32785
  finalizeModelSpan(state);
@@ -31242,10 +32797,7 @@ function startModelSpan(state, event) {
31242
32797
  withSpanInstrumentationName(
31243
32798
  {
31244
32799
  event: {
31245
- input: Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(
31246
- event.agent.messages,
31247
- state.attachmentCache
31248
- ) : void 0,
32800
+ input: buildModelSpanInput(event, state.attachmentCache),
31249
32801
  metadata
31250
32802
  },
31251
32803
  name: formatModelSpanName(model),
@@ -31885,6 +33437,527 @@ function logInstrumentationError5(context, error) {
31885
33437
  debugLogger.debug(`${context}:`, error);
31886
33438
  }
31887
33439
 
33440
+ // src/instrumentation/plugins/cloudflare-ai-chat-instrumentation.ts
33441
+ var wrappedTurnRunners = /* @__PURE__ */ new WeakSet();
33442
+ var wrappedResponseHooks = /* @__PURE__ */ new WeakSet();
33443
+ function instrumentCloudflareAIChatAgent(agent) {
33444
+ try {
33445
+ const original = Reflect.get(agent, "_runExclusiveChatTurn");
33446
+ if (typeof original !== "function" || wrappedTurnRunners.has(original)) {
33447
+ return agent;
33448
+ }
33449
+ const wrapped = async function(...args) {
33450
+ return cloudflareAIChatChannels.runExclusiveChatTurn.tracePromise(
33451
+ () => Reflect.apply(original, this, args),
33452
+ {
33453
+ arguments: args,
33454
+ self: this
33455
+ }
33456
+ );
33457
+ };
33458
+ wrappedTurnRunners.add(wrapped);
33459
+ defineWrappedMethod(agent, "_runExclusiveChatTurn", original, wrapped);
33460
+ } catch (error) {
33461
+ debugLogger.debug("Failed to wrap @cloudflare/ai-chat turn runner:", error);
33462
+ }
33463
+ return agent;
33464
+ }
33465
+ function instrumentCloudflareAIChatResponseHook(agent) {
33466
+ try {
33467
+ const original = Reflect.get(agent, "onChatResponse");
33468
+ if (typeof original !== "function" || wrappedResponseHooks.has(original)) {
33469
+ return;
33470
+ }
33471
+ const wrapped = function(result) {
33472
+ const args = [result];
33473
+ return cloudflareAIChatChannels.onChatResponse.traceSync(
33474
+ () => Reflect.apply(original, this, args),
33475
+ {
33476
+ arguments: args,
33477
+ self: this
33478
+ }
33479
+ );
33480
+ };
33481
+ wrappedResponseHooks.add(wrapped);
33482
+ defineWrappedMethod(agent, "onChatResponse", original, wrapped);
33483
+ } catch (error) {
33484
+ debugLogger.debug(
33485
+ "Failed to wrap @cloudflare/ai-chat response hook:",
33486
+ error
33487
+ );
33488
+ }
33489
+ }
33490
+ function defineWrappedMethod(target, property, original, wrapped) {
33491
+ const ownDescriptor = Object.getOwnPropertyDescriptor(target, property);
33492
+ Object.defineProperty(target, property, {
33493
+ configurable: ownDescriptor?.configurable ?? true,
33494
+ enumerable: ownDescriptor?.enumerable ?? false,
33495
+ value: wrapped,
33496
+ writable: ownDescriptor && "writable" in ownDescriptor ? ownDescriptor.writable : true
33497
+ });
33498
+ try {
33499
+ Object.defineProperty(wrapped, "name", {
33500
+ configurable: true,
33501
+ value: original.name
33502
+ });
33503
+ } catch {
33504
+ }
33505
+ }
33506
+
33507
+ // src/instrumentation/plugins/cloudflare-ai-chat-plugin.ts
33508
+ var BLOCKED_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
33509
+ var RESPONSE_STATE_RETENTION_MS = 6e4;
33510
+ var CloudflareAIChatPlugin = class extends BasePlugin {
33511
+ activeStates = /* @__PURE__ */ new Set();
33512
+ activeTurns = /* @__PURE__ */ new WeakMap();
33513
+ eventStates = /* @__PURE__ */ new WeakMap();
33514
+ onEnable() {
33515
+ this.subscribeToResponseHook();
33516
+ this.subscribeToTurnRunner();
33517
+ }
33518
+ onDisable() {
33519
+ for (const unsubscribe of this.unsubscribers) {
33520
+ unsubscribe();
33521
+ }
33522
+ this.unsubscribers = [];
33523
+ for (const state of this.activeStates) {
33524
+ this.cleanupState(state);
33525
+ }
33526
+ this.activeStates.clear();
33527
+ }
33528
+ subscribeToTurnRunner() {
33529
+ const tracingChannel = cloudflareAIChatChannels.runExclusiveChatTurn.tracingChannel();
33530
+ const unbindCurrentSpanStore = this.bindCurrentSpanStore(tracingChannel);
33531
+ const handlers = {
33532
+ start: (event) => {
33533
+ this.ensureEventState(event);
33534
+ },
33535
+ asyncEnd: (event) => {
33536
+ this.finishEvent(event);
33537
+ },
33538
+ error: (event) => {
33539
+ this.finishEvent(event, event.error);
33540
+ }
33541
+ };
33542
+ tracingChannel.subscribe(handlers);
33543
+ this.unsubscribers.push(() => {
33544
+ unbindCurrentSpanStore?.();
33545
+ tracingChannel.unsubscribe(handlers);
33546
+ });
33547
+ }
33548
+ subscribeToResponseHook() {
33549
+ const tracingChannel = cloudflareAIChatChannels.onChatResponse.tracingChannel();
33550
+ const handlers = {
33551
+ start: (event) => {
33552
+ let state;
33553
+ try {
33554
+ const agent = asObject(event.self);
33555
+ const result = event.arguments[0];
33556
+ state = agent ? this.findResponseState(
33557
+ agent,
33558
+ stringValue3(ownValue2(result, "requestId"))
33559
+ ) : void 0;
33560
+ if (!state) {
33561
+ return;
33562
+ }
33563
+ state.responseObserved = true;
33564
+ const output = serializeMessage(ownValue2(result, "message"));
33565
+ const status = stringValue3(ownValue2(result, "status"));
33566
+ const error = ownValue2(result, "error");
33567
+ const input = ownValue2(result, "continuation") === true ? state.input : serializeMessages(readProperty(agent, "messages"))?.filter(
33568
+ (message) => typeof output?.id !== "string" || message.id !== output.id
33569
+ );
33570
+ state.span.log({
33571
+ ...input !== void 0 ? { input } : {},
33572
+ ...output !== void 0 ? { output } : {},
33573
+ ...status === "error" && error !== void 0 ? { error } : {}
33574
+ });
33575
+ } catch (error) {
33576
+ debugLogger.debug(
33577
+ "Failed to process @cloudflare/ai-chat response hook:",
33578
+ error
33579
+ );
33580
+ } finally {
33581
+ if (state?.settled) {
33582
+ this.cleanupState(state);
33583
+ }
33584
+ }
33585
+ }
33586
+ };
33587
+ tracingChannel.subscribe(handlers);
33588
+ this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
33589
+ }
33590
+ bindCurrentSpanStore(tracingChannel) {
33591
+ const globalState = _internalGetGlobalState();
33592
+ const contextManager = globalState?.contextManager;
33593
+ const startChannel = tracingChannel.start;
33594
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
33595
+ if (!startChannel || !currentSpanStore || !contextManager) {
33596
+ return void 0;
33597
+ }
33598
+ startChannel.bindStore(currentSpanStore, (event) => {
33599
+ const state = this.ensureEventState(event);
33600
+ return state ? contextManager.wrapSpanForStore(state.span) : currentSpanStore.getStore();
33601
+ });
33602
+ return () => startChannel.unbindStore(currentSpanStore);
33603
+ }
33604
+ ensureEventState(event) {
33605
+ const eventKey = event;
33606
+ const known = this.eventStates.get(eventKey);
33607
+ if (known) {
33608
+ return known;
33609
+ }
33610
+ try {
33611
+ const agent = asObject(event.self);
33612
+ const requestId = stringValue3(event.arguments[0]);
33613
+ const key = requestId ?? /* @__PURE__ */ Symbol("cloudflare-ai-chat-turn");
33614
+ const activeForAgent = agent ? this.getActiveTurns(agent) : void 0;
33615
+ const existing = activeForAgent?.get(key);
33616
+ const state = existing && !existing.settled ? existing : this.createTurnState(agent, key);
33617
+ if (existing && !existing.settled) {
33618
+ state.depth += 1;
33619
+ }
33620
+ this.eventStates.set(eventKey, state);
33621
+ this.bindTurnCallback(event, agent, state);
33622
+ if (agent) {
33623
+ instrumentCloudflareAIChatResponseHook(agent);
33624
+ }
33625
+ return state;
33626
+ } catch (error) {
33627
+ debugLogger.debug(
33628
+ "Failed to start @cloudflare/ai-chat instrumentation:",
33629
+ error
33630
+ );
33631
+ return void 0;
33632
+ }
33633
+ }
33634
+ createTurnState(agent, key) {
33635
+ const span = startSpan(
33636
+ withSpanInstrumentationName(
33637
+ {
33638
+ name: "AIChatAgent.onChatMessage",
33639
+ spanAttributes: { type: "task" /* TASK */ }
33640
+ },
33641
+ INSTRUMENTATION_NAMES.CLOUDFLARE_AI_CHAT
33642
+ )
33643
+ );
33644
+ const state = {
33645
+ agent,
33646
+ depth: 1,
33647
+ ended: false,
33648
+ key,
33649
+ responseObserved: false,
33650
+ settled: false,
33651
+ span
33652
+ };
33653
+ this.activeStates.add(state);
33654
+ if (agent) {
33655
+ this.getActiveTurns(agent).set(key, state);
33656
+ }
33657
+ return state;
33658
+ }
33659
+ bindTurnCallback(event, agent, state) {
33660
+ const callback = event.arguments[1];
33661
+ if (typeof callback !== "function") {
33662
+ return;
33663
+ }
33664
+ try {
33665
+ event.arguments[1] = function(...args) {
33666
+ return withCurrent(state.span, () => {
33667
+ try {
33668
+ const input = serializeMessages(readProperty(agent, "messages"));
33669
+ if (input !== void 0 && state.input === void 0) {
33670
+ state.input = input;
33671
+ state.span.log({ input });
33672
+ }
33673
+ } catch (error) {
33674
+ debugLogger.debug(
33675
+ "Failed to capture @cloudflare/ai-chat messages:",
33676
+ error
33677
+ );
33678
+ }
33679
+ return Reflect.apply(callback, this, args);
33680
+ });
33681
+ };
33682
+ } catch (error) {
33683
+ debugLogger.debug(
33684
+ "Failed to bind @cloudflare/ai-chat turn callback context:",
33685
+ error
33686
+ );
33687
+ }
33688
+ }
33689
+ finishEvent(event, error) {
33690
+ const eventKey = event;
33691
+ const state = this.eventStates.get(eventKey);
33692
+ if (!state || state.ended) {
33693
+ return;
33694
+ }
33695
+ this.eventStates.delete(eventKey);
33696
+ if (error !== void 0 && state.pendingError === void 0) {
33697
+ state.pendingError = error;
33698
+ }
33699
+ state.depth -= 1;
33700
+ if (state.depth === 0) {
33701
+ state.settled = true;
33702
+ this.endState(state);
33703
+ if (state.responseObserved || error !== void 0) {
33704
+ this.cleanupState(state);
33705
+ } else {
33706
+ state.cleanupTimer = setTimeout(
33707
+ () => this.cleanupState(state),
33708
+ RESPONSE_STATE_RETENTION_MS
33709
+ );
33710
+ if (typeof state.cleanupTimer === "object" && state.cleanupTimer !== null && "unref" in state.cleanupTimer && typeof state.cleanupTimer.unref === "function") {
33711
+ state.cleanupTimer.unref();
33712
+ }
33713
+ }
33714
+ }
33715
+ }
33716
+ endState(state) {
33717
+ if (state.ended) {
33718
+ return;
33719
+ }
33720
+ state.ended = true;
33721
+ try {
33722
+ if (state.pendingError !== void 0) {
33723
+ state.span.log({ error: state.pendingError });
33724
+ }
33725
+ } finally {
33726
+ state.span.end();
33727
+ }
33728
+ }
33729
+ cleanupState(state) {
33730
+ if (state.cleanupTimer !== void 0) {
33731
+ clearTimeout(state.cleanupTimer);
33732
+ state.cleanupTimer = void 0;
33733
+ }
33734
+ try {
33735
+ this.endState(state);
33736
+ } finally {
33737
+ this.activeStates.delete(state);
33738
+ if (state.agent) {
33739
+ const activeForAgent = this.activeTurns.get(state.agent);
33740
+ if (activeForAgent?.get(state.key) === state) {
33741
+ activeForAgent.delete(state.key);
33742
+ }
33743
+ }
33744
+ }
33745
+ }
33746
+ getActiveTurns(agent) {
33747
+ let turns = this.activeTurns.get(agent);
33748
+ if (!turns) {
33749
+ turns = /* @__PURE__ */ new Map();
33750
+ this.activeTurns.set(agent, turns);
33751
+ }
33752
+ return turns;
33753
+ }
33754
+ findResponseState(agent, requestId) {
33755
+ const turns = this.activeTurns.get(agent);
33756
+ if (!turns) {
33757
+ return void 0;
33758
+ }
33759
+ if (requestId !== void 0) {
33760
+ return turns.get(requestId);
33761
+ }
33762
+ const active = [...turns.values()];
33763
+ return active.length === 1 ? active[0] : void 0;
33764
+ }
33765
+ };
33766
+ function asObject(value) {
33767
+ return value !== null && (typeof value === "object" || typeof value === "function") ? value : void 0;
33768
+ }
33769
+ function readProperty(value, key) {
33770
+ const object = asObject(value);
33771
+ return object ? Reflect.get(object, key) : void 0;
33772
+ }
33773
+ function ownValue2(value, key) {
33774
+ const object = asObject(value);
33775
+ if (!object) {
33776
+ return void 0;
33777
+ }
33778
+ const descriptor = Object.getOwnPropertyDescriptor(object, key);
33779
+ return descriptor && "value" in descriptor ? descriptor.value : void 0;
33780
+ }
33781
+ function stringValue3(value) {
33782
+ return typeof value === "string" ? value : void 0;
33783
+ }
33784
+ function serializeMessages(value) {
33785
+ if (!Array.isArray(value)) {
33786
+ return void 0;
33787
+ }
33788
+ return value.flatMap((message) => {
33789
+ const serialized = serializeMessage(message);
33790
+ return serialized === void 0 ? [] : [serialized];
33791
+ });
33792
+ }
33793
+ function serializeMessage(value) {
33794
+ const message = asObject(value);
33795
+ if (!message) {
33796
+ return void 0;
33797
+ }
33798
+ const serialized = [];
33799
+ const id = ownValue2(message, "id");
33800
+ const role = ownValue2(message, "role");
33801
+ const parts = ownValue2(message, "parts");
33802
+ if (typeof id === "string") {
33803
+ serialized.push(["id", id]);
33804
+ }
33805
+ if (typeof role === "string") {
33806
+ serialized.push(["role", role]);
33807
+ }
33808
+ const sanitizedParts = sanitizeLoggedValue2(parts);
33809
+ if (sanitizedParts !== void 0) {
33810
+ serialized.push(["parts", sanitizedParts]);
33811
+ }
33812
+ return serialized.length > 0 ? Object.fromEntries(serialized) : void 0;
33813
+ }
33814
+ function sanitizeLoggedValue2(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
33815
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
33816
+ return value;
33817
+ }
33818
+ if (typeof value === "number") {
33819
+ return Number.isFinite(value) ? value : void 0;
33820
+ }
33821
+ const object = asObject(value);
33822
+ if (!object || depth >= 20 || typeof value === "function") {
33823
+ return void 0;
33824
+ }
33825
+ if (seen.has(object)) {
33826
+ return "[Circular]";
33827
+ }
33828
+ seen.add(object);
33829
+ if (Array.isArray(value)) {
33830
+ return value.map((entry) => sanitizeLoggedValue2(entry, seen, depth + 1));
33831
+ }
33832
+ const entries = [];
33833
+ for (const [key, descriptor] of Object.entries(
33834
+ Object.getOwnPropertyDescriptors(object)
33835
+ )) {
33836
+ if (BLOCKED_KEYS.has(key) || !descriptor.enumerable || !("value" in descriptor)) {
33837
+ continue;
33838
+ }
33839
+ const sanitized = sanitizeLoggedValue2(descriptor.value, seen, depth + 1);
33840
+ if (sanitized !== void 0) {
33841
+ entries.push([key, sanitized]);
33842
+ }
33843
+ }
33844
+ return Object.fromEntries(entries);
33845
+ }
33846
+
33847
+ // src/instrumentation/plugins/cloudflare-agents-plugin.ts
33848
+ var CLOUDFLARE_WORKERS_CONTEXT = {
33849
+ span_origin: {
33850
+ environment: { type: "server", name: "cloudflare_workers" }
33851
+ }
33852
+ };
33853
+ var CloudflareAgentsPlugin = class extends BasePlugin {
33854
+ onEnable() {
33855
+ const channel = cloudflareAgentsChannels.runAgentTool.tracingChannel();
33856
+ const spans = /* @__PURE__ */ new WeakMap();
33857
+ const handlers = {
33858
+ start: (event) => {
33859
+ try {
33860
+ const agentClass = event.arguments[0];
33861
+ const options = event.arguments[1];
33862
+ if (ownValue3(options, "detached")) {
33863
+ return;
33864
+ }
33865
+ const name = ownValue3(agentClass, "name");
33866
+ if (typeof name !== "string" || name.length === 0) {
33867
+ debugLogger.warn(
33868
+ "Skipping Cloudflare Agents runAgentTool span because the child agent class has no name."
33869
+ );
33870
+ return;
33871
+ }
33872
+ const span = _internalStartSpanWithContext(
33873
+ withSpanInstrumentationName(
33874
+ {
33875
+ name,
33876
+ spanAttributes: { type: "tool" /* TOOL */ },
33877
+ event: {
33878
+ input: ownValue3(options, "input")
33879
+ }
33880
+ },
33881
+ INSTRUMENTATION_NAMES.CLOUDFLARE_AGENTS
33882
+ ),
33883
+ CLOUDFLARE_WORKERS_CONTEXT
33884
+ );
33885
+ spans.set(event, span);
33886
+ } catch (error) {
33887
+ logInstrumentationError6("start", error);
33888
+ }
33889
+ },
33890
+ asyncEnd: (event) => {
33891
+ const span = spans.get(event);
33892
+ if (!span) {
33893
+ return;
33894
+ }
33895
+ spans.delete(event);
33896
+ try {
33897
+ const status = ownValue3(event.result, "status");
33898
+ if (status === "completed") {
33899
+ span.log({ output: ownValue3(event.result, "output") });
33900
+ } else {
33901
+ const error = ownValue3(event.result, "error");
33902
+ if (typeof error === "string") {
33903
+ span.log({ error });
33904
+ }
33905
+ }
33906
+ } catch (error) {
33907
+ logInstrumentationError6("completion", error);
33908
+ } finally {
33909
+ safelyEndSpan(span);
33910
+ }
33911
+ },
33912
+ error: (event) => {
33913
+ const span = spans.get(event);
33914
+ if (!span) {
33915
+ return;
33916
+ }
33917
+ spans.delete(event);
33918
+ try {
33919
+ span.log({ error: event.error });
33920
+ } catch (error) {
33921
+ logInstrumentationError6("rejection", error);
33922
+ } finally {
33923
+ safelyEndSpan(span);
33924
+ }
33925
+ }
33926
+ };
33927
+ channel.subscribe(handlers);
33928
+ this.unsubscribers.push(() => channel.unsubscribe(handlers));
33929
+ }
33930
+ onDisable() {
33931
+ for (const unsubscribe of this.unsubscribers) {
33932
+ unsubscribe();
33933
+ }
33934
+ this.unsubscribers = [];
33935
+ }
33936
+ };
33937
+ function ownValue3(value, key) {
33938
+ if (!isObjectLike2(value)) {
33939
+ return void 0;
33940
+ }
33941
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
33942
+ return descriptor && "value" in descriptor ? descriptor.value : void 0;
33943
+ }
33944
+ function isObjectLike2(value) {
33945
+ return typeof value === "object" && value !== null || typeof value === "function";
33946
+ }
33947
+ function safelyEndSpan(span) {
33948
+ try {
33949
+ span.end();
33950
+ } catch (error) {
33951
+ logInstrumentationError6("span end", error);
33952
+ }
33953
+ }
33954
+ function logInstrumentationError6(operation, error) {
33955
+ debugLogger.error(
33956
+ `Failed to process Cloudflare Agents ${operation} instrumentation:`,
33957
+ error
33958
+ );
33959
+ }
33960
+
31888
33961
  // src/instrumentation/braintrust-plugin.ts
31889
33962
  var BraintrustPlugin = class extends BasePlugin {
31890
33963
  config;
@@ -31893,13 +33966,16 @@ var BraintrustPlugin = class extends BasePlugin {
31893
33966
  anthropicPlugin = null;
31894
33967
  aiSDKPlugin = null;
31895
33968
  claudeAgentSDKPlugin = null;
33969
+ cloudflareThinkPlugin = null;
31896
33970
  cursorSDKPlugin = null;
31897
33971
  openAIAgentsPlugin = null;
31898
33972
  googleGenAIPlugin = null;
31899
33973
  huggingFacePlugin = null;
33974
+ huggingFaceTransformersPlugin = null;
31900
33975
  openRouterPlugin = null;
31901
33976
  openRouterAgentPlugin = null;
31902
33977
  mistralPlugin = null;
33978
+ ollamaPlugin = null;
31903
33979
  googleADKPlugin = null;
31904
33980
  coherePlugin = null;
31905
33981
  groqPlugin = null;
@@ -31911,6 +33987,8 @@ var BraintrustPlugin = class extends BasePlugin {
31911
33987
  langSmithPlugin = null;
31912
33988
  piCodingAgentPlugin = null;
31913
33989
  strandsAgentSDKPlugin = null;
33990
+ cloudflareAIChatPlugin = null;
33991
+ cloudflareAgentsPlugin = null;
31914
33992
  constructor(config = {}) {
31915
33993
  super();
31916
33994
  this.config = config;
@@ -31937,6 +34015,10 @@ var BraintrustPlugin = class extends BasePlugin {
31937
34015
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
31938
34016
  this.claudeAgentSDKPlugin.enable();
31939
34017
  }
34018
+ if (integrations.cloudflareThink !== false) {
34019
+ this.cloudflareThinkPlugin = new CloudflareThinkPlugin();
34020
+ this.cloudflareThinkPlugin.enable();
34021
+ }
31940
34022
  if (integrations.cursorSDK !== false && integrations.cursor !== false) {
31941
34023
  this.cursorSDKPlugin = new CursorSDKPlugin();
31942
34024
  this.cursorSDKPlugin.enable();
@@ -31952,6 +34034,8 @@ var BraintrustPlugin = class extends BasePlugin {
31952
34034
  if (integrations.huggingface !== false) {
31953
34035
  this.huggingFacePlugin = new HuggingFacePlugin();
31954
34036
  this.huggingFacePlugin.enable();
34037
+ this.huggingFaceTransformersPlugin = new HuggingFaceTransformersPlugin();
34038
+ this.huggingFaceTransformersPlugin.enable();
31955
34039
  }
31956
34040
  if (integrations.openrouter !== false) {
31957
34041
  this.openRouterPlugin = new OpenRouterPlugin();
@@ -31965,6 +34049,10 @@ var BraintrustPlugin = class extends BasePlugin {
31965
34049
  this.mistralPlugin = new MistralPlugin();
31966
34050
  this.mistralPlugin.enable();
31967
34051
  }
34052
+ if (integrations.ollama !== false) {
34053
+ this.ollamaPlugin = new OllamaPlugin();
34054
+ this.ollamaPlugin.enable();
34055
+ }
31968
34056
  if (integrations.googleADK !== false) {
31969
34057
  this.googleADKPlugin = new GoogleADKPlugin();
31970
34058
  this.googleADKPlugin.enable();
@@ -31997,6 +34085,14 @@ var BraintrustPlugin = class extends BasePlugin {
31997
34085
  this.strandsAgentSDKPlugin = new StrandsAgentSDKPlugin();
31998
34086
  this.strandsAgentSDKPlugin.enable();
31999
34087
  }
34088
+ if (integrations.cloudflareAIChat !== false) {
34089
+ this.cloudflareAIChatPlugin = new CloudflareAIChatPlugin();
34090
+ this.cloudflareAIChatPlugin.enable();
34091
+ }
34092
+ if (integrations.cloudflareAgents !== false) {
34093
+ this.cloudflareAgentsPlugin = new CloudflareAgentsPlugin();
34094
+ this.cloudflareAgentsPlugin.enable();
34095
+ }
32000
34096
  if (integrations.flue !== false) {
32001
34097
  this.fluePlugin = new FluePlugin();
32002
34098
  this.fluePlugin.enable();
@@ -32033,6 +34129,10 @@ var BraintrustPlugin = class extends BasePlugin {
32033
34129
  this.claudeAgentSDKPlugin.disable();
32034
34130
  this.claudeAgentSDKPlugin = null;
32035
34131
  }
34132
+ if (this.cloudflareThinkPlugin) {
34133
+ this.cloudflareThinkPlugin.disable();
34134
+ this.cloudflareThinkPlugin = null;
34135
+ }
32036
34136
  if (this.cursorSDKPlugin) {
32037
34137
  this.cursorSDKPlugin.disable();
32038
34138
  this.cursorSDKPlugin = null;
@@ -32049,6 +34149,10 @@ var BraintrustPlugin = class extends BasePlugin {
32049
34149
  this.huggingFacePlugin.disable();
32050
34150
  this.huggingFacePlugin = null;
32051
34151
  }
34152
+ if (this.huggingFaceTransformersPlugin) {
34153
+ this.huggingFaceTransformersPlugin.disable();
34154
+ this.huggingFaceTransformersPlugin = null;
34155
+ }
32052
34156
  if (this.openRouterPlugin) {
32053
34157
  this.openRouterPlugin.disable();
32054
34158
  this.openRouterPlugin = null;
@@ -32061,6 +34165,10 @@ var BraintrustPlugin = class extends BasePlugin {
32061
34165
  this.mistralPlugin.disable();
32062
34166
  this.mistralPlugin = null;
32063
34167
  }
34168
+ if (this.ollamaPlugin) {
34169
+ this.ollamaPlugin.disable();
34170
+ this.ollamaPlugin = null;
34171
+ }
32064
34172
  if (this.googleADKPlugin) {
32065
34173
  this.googleADKPlugin.disable();
32066
34174
  this.googleADKPlugin = null;
@@ -32093,6 +34201,14 @@ var BraintrustPlugin = class extends BasePlugin {
32093
34201
  this.strandsAgentSDKPlugin.disable();
32094
34202
  this.strandsAgentSDKPlugin = null;
32095
34203
  }
34204
+ if (this.cloudflareAIChatPlugin) {
34205
+ this.cloudflareAIChatPlugin.disable();
34206
+ this.cloudflareAIChatPlugin = null;
34207
+ }
34208
+ if (this.cloudflareAgentsPlugin) {
34209
+ this.cloudflareAgentsPlugin.disable();
34210
+ this.cloudflareAgentsPlugin = null;
34211
+ }
32096
34212
  if (this.fluePlugin) {
32097
34213
  this.fluePlugin.disable();
32098
34214
  this.fluePlugin = null;
@@ -32109,7 +34225,9 @@ var BraintrustPlugin = class extends BasePlugin {
32109
34225
  };
32110
34226
 
32111
34227
  // src/instrumentation/registry.ts
32112
- var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for("braintrust.registry");
34228
+ var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for(
34229
+ `braintrust.registry.global-hooks.v${GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION}`
34230
+ );
32113
34231
  function getSharedState() {
32114
34232
  const state = globalThis[/* @__PURE__ */ Symbol.for("braintrust-state")];
32115
34233
  return state && typeof state === "object" ? state : void 0;
@@ -32425,7 +34543,6 @@ function wrapMastraAgent(agent, _options) {
32425
34543
 
32426
34544
  // src/node/config.ts
32427
34545
  import { AsyncLocalStorage } from "node:async_hooks";
32428
- import * as diagnostics_channel from "node:diagnostics_channel";
32429
34546
  import * as path from "node:path";
32430
34547
  import * as fs from "node:fs/promises";
32431
34548
  import * as os from "node:os";
@@ -32712,8 +34829,6 @@ function configureNode() {
32712
34829
  };
32713
34830
  isomorph_default.getCallerLocation = getCallerLocation;
32714
34831
  isomorph_default.newAsyncLocalStorage = () => new AsyncLocalStorage();
32715
- isomorph_default.newTracingChannel = (nameOrChannels) => diagnostics_channel.tracingChannel(nameOrChannels);
32716
- patchTracingChannel(diagnostics_channel.tracingChannel);
32717
34832
  isomorph_default.processOn = (event, handler) => {
32718
34833
  process.on(event, handler);
32719
34834
  };
@@ -32939,6 +35054,7 @@ export {
32939
35054
  parseCachedHeader,
32940
35055
  finalizeAnthropicTokens,
32941
35056
  extractAnthropicCacheTokens,
35057
+ collectAnthropicSession,
32942
35058
  zodToJsonSchema,
32943
35059
  currentWorkflowAgentWrapperSpan,
32944
35060
  braintrustAISDKTelemetry,
@@ -32950,6 +35066,7 @@ export {
32950
35066
  braintrustFlueObserver,
32951
35067
  BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
32952
35068
  BraintrustLangChainCallbackHandler,
35069
+ instrumentCloudflareAIChatAgent,
32953
35070
  configureInstrumentation,
32954
35071
  BraintrustObservabilityExporter,
32955
35072
  wrapMastraAgent,