braintrust 3.27.0 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +1 -1
  2. package/dev/dist/index.d.mts +879 -197
  3. package/dev/dist/index.d.ts +879 -197
  4. package/dev/dist/index.js +2960 -1865
  5. package/dev/dist/index.mjs +2217 -1122
  6. package/dist/apply-auto-instrumentation.js +345 -260
  7. package/dist/apply-auto-instrumentation.mjs +137 -52
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +124 -7
  9. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  10. package/dist/auto-instrumentations/bundler/next.cjs +124 -7
  11. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  12. package/dist/auto-instrumentations/bundler/rollup.cjs +124 -7
  13. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.cjs +124 -7
  15. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  16. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +124 -7
  17. package/dist/auto-instrumentations/bundler/webpack.cjs +124 -7
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  19. package/dist/auto-instrumentations/{chunk-ZNHTSSGI.mjs → chunk-AOIYCVEL.mjs} +34 -3
  20. package/dist/auto-instrumentations/{chunk-XEYKUBLY.mjs → chunk-DKTGDNA7.mjs} +91 -5
  21. package/dist/auto-instrumentations/{chunk-BW33ULMW.mjs → chunk-OMCZ3MV2.mjs} +1 -1
  22. package/dist/auto-instrumentations/hook.mjs +1186 -161
  23. package/dist/auto-instrumentations/index.cjs +34 -3
  24. package/dist/auto-instrumentations/index.mjs +1 -1
  25. package/dist/browser.d.mts +1388 -75
  26. package/dist/browser.d.ts +1388 -75
  27. package/dist/browser.js +3954 -1124
  28. package/dist/browser.mjs +3954 -1124
  29. package/dist/{chunk-MF7NU6BT.js → chunk-6Z5S7VOU.js} +175 -25
  30. package/dist/{chunk-CZM5JIQL.mjs → chunk-7FA6VP2S.mjs} +172 -22
  31. package/dist/{chunk-YKD22IMR.mjs → chunk-M6XPNJC4.mjs} +2102 -1113
  32. package/dist/{chunk-QRHGVBKU.js → chunk-XLLGRXGR.js} +3273 -2284
  33. package/dist/cli.js +6353 -1483
  34. package/dist/edge-light.d.mts +1 -1
  35. package/dist/edge-light.d.ts +1 -1
  36. package/dist/edge-light.js +3954 -1124
  37. package/dist/edge-light.mjs +3954 -1124
  38. package/dist/index.d.mts +1972 -659
  39. package/dist/index.d.ts +1972 -659
  40. package/dist/index.js +2453 -676
  41. package/dist/index.mjs +1973 -196
  42. package/dist/instrumentation/index.d.mts +738 -15
  43. package/dist/instrumentation/index.d.ts +738 -15
  44. package/dist/instrumentation/index.js +2791 -874
  45. package/dist/instrumentation/index.mjs +2791 -874
  46. package/dist/vitest-evals-reporter.js +16 -16
  47. package/dist/vitest-evals-reporter.mjs +2 -2
  48. package/dist/workerd.d.mts +1 -1
  49. package/dist/workerd.d.ts +1 -1
  50. package/dist/workerd.js +3954 -1124
  51. package/dist/workerd.mjs +3954 -1124
  52. package/package.json +2 -3
  53. package/util/dist/index.d.mts +1596 -109
  54. package/util/dist/index.d.ts +1596 -109
@@ -653,8 +653,6 @@ function newGlobalTracingChannel(nameOrChannels) {
653
653
  var DefaultAsyncLocalStorage = class {
654
654
  constructor() {
655
655
  }
656
- enterWith(_) {
657
- }
658
656
  run(_, callback) {
659
657
  return callback();
660
658
  }
@@ -2575,7 +2573,10 @@ var AclObjectType = z6.union([
2575
2573
  "org_member",
2576
2574
  "project_log",
2577
2575
  "org_project",
2578
- "org_audit_logs"
2576
+ "org_audit_logs",
2577
+ "project_group",
2578
+ "ai_secret",
2579
+ "org_ai_secret"
2579
2580
  ]),
2580
2581
  z6.null()
2581
2582
  ]);
@@ -2704,7 +2705,8 @@ var AsyncScoringState = z6.union([
2704
2705
  token: z6.string(),
2705
2706
  function_ids: z6.array(z6.unknown()),
2706
2707
  skip_logging: z6.union([z6.boolean(), z6.null()]).optional(),
2707
- triggered_functions: z6.union([z6.record(TriggeredFunctionState), z6.null()]).optional()
2708
+ triggered_functions: z6.union([z6.record(TriggeredFunctionState), z6.null()]).optional(),
2709
+ last_triggered_xact_id: z6.union([z6.string(), z6.number(), z6.null()]).optional()
2708
2710
  }),
2709
2711
  z6.object({ status: z6.literal("disabled") }),
2710
2712
  z6.null(),
@@ -2773,7 +2775,7 @@ var FunctionTypeEnum = z6.enum([
2773
2775
  "parameters",
2774
2776
  "sandbox"
2775
2777
  ]);
2776
- var NullableSavedFunctionId = z6.union([
2778
+ var FacetPreprocessorId = z6.union([
2777
2779
  z6.object({
2778
2780
  type: z6.literal("function"),
2779
2781
  id: z6.string(),
@@ -2784,10 +2786,23 @@ var NullableSavedFunctionId = z6.union([
2784
2786
  name: z6.string(),
2785
2787
  function_type: FunctionTypeEnum.optional().default("scorer")
2786
2788
  }),
2789
+ z6.object({ type: z6.literal("inline"), code: z6.string().min(1) }),
2787
2790
  z6.null()
2788
2791
  ]);
2792
+ var SavedFunctionId = z6.union([
2793
+ z6.object({
2794
+ type: z6.literal("function"),
2795
+ id: z6.string(),
2796
+ version: z6.string().optional()
2797
+ }),
2798
+ z6.object({
2799
+ type: z6.literal("global"),
2800
+ name: z6.string(),
2801
+ function_type: FunctionTypeEnum.optional().default("scorer")
2802
+ })
2803
+ ]);
2789
2804
  var TopicMapGenerationSettings = z6.object({
2790
- algorithm: z6.enum(["hdbscan", "kmeans"]),
2805
+ algorithm: z6.enum(["hdbscan", "kmeans", "community"]),
2791
2806
  dimension_reduction: z6.enum(["umap", "pca", "none"]),
2792
2807
  sample_size: z6.number().int().gt(0).optional(),
2793
2808
  n_clusters: z6.number().int().gt(0).optional(),
@@ -2799,6 +2814,7 @@ var TopicMapGenerationSettings = z6.object({
2799
2814
  var TopicMapData = z6.object({
2800
2815
  type: z6.literal("topic_map"),
2801
2816
  source_facet: z6.string(),
2817
+ source_facet_function: SavedFunctionId.and(z6.unknown()).optional(),
2802
2818
  embedding_model: z6.string(),
2803
2819
  bundle_key: z6.string().optional(),
2804
2820
  report_key: z6.string().optional(),
@@ -2812,7 +2828,7 @@ var TopicMapData = z6.object({
2812
2828
  });
2813
2829
  var BatchedFacetData = z6.object({
2814
2830
  type: z6.literal("batched_facet"),
2815
- preprocessor: NullableSavedFunctionId.and(z6.unknown()).optional(),
2831
+ preprocessor: FacetPreprocessorId.optional(),
2816
2832
  facets: z6.array(
2817
2833
  z6.object({
2818
2834
  name: z6.string(),
@@ -3073,18 +3089,6 @@ var ObjectReferenceNullish = z6.union([
3073
3089
  }),
3074
3090
  z6.null()
3075
3091
  ]);
3076
- var SavedFunctionId = z6.union([
3077
- z6.object({
3078
- type: z6.literal("function"),
3079
- id: z6.string(),
3080
- version: z6.string().optional()
3081
- }),
3082
- z6.object({
3083
- type: z6.literal("global"),
3084
- name: z6.string(),
3085
- function_type: FunctionTypeEnum.optional().default("scorer")
3086
- })
3087
- ]);
3088
3092
  var DatasetEvent = z6.object({
3089
3093
  id: z6.string(),
3090
3094
  _xact_id: z6.string(),
@@ -3306,7 +3310,7 @@ var ExtendedSavedFunctionId = z6.union([
3306
3310
  ]);
3307
3311
  var FacetData = z6.object({
3308
3312
  type: z6.literal("facet"),
3309
- preprocessor: NullableSavedFunctionId.and(z6.unknown()).optional(),
3313
+ preprocessor: FacetPreprocessorId.optional(),
3310
3314
  prompt: z6.string(),
3311
3315
  model: z6.string().optional(),
3312
3316
  embedding_model: z6.string().optional(),
@@ -3405,7 +3409,7 @@ var PromptParserNullish = z6.union([
3405
3409
  }),
3406
3410
  z6.null()
3407
3411
  ]);
3408
- var PreprocessorSavedFunctionId = z6.union([
3412
+ var PreprocessorId = z6.union([
3409
3413
  z6.object({
3410
3414
  type: z6.literal("function"),
3411
3415
  id: z6.string(),
@@ -3416,6 +3420,7 @@ var PreprocessorSavedFunctionId = z6.union([
3416
3420
  name: z6.string(),
3417
3421
  function_type: z6.literal("preprocessor").optional().default("preprocessor")
3418
3422
  }),
3423
+ z6.object({ type: z6.literal("inline"), code: z6.string().min(1) }),
3419
3424
  z6.null()
3420
3425
  ]);
3421
3426
  var PromptDataNullish = z6.union([
@@ -3423,7 +3428,7 @@ var PromptDataNullish = z6.union([
3423
3428
  prompt: PromptBlockDataNullish,
3424
3429
  options: PromptOptionsNullish,
3425
3430
  parser: PromptParserNullish,
3426
- preprocessor: PreprocessorSavedFunctionId,
3431
+ preprocessor: PreprocessorId,
3427
3432
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
3428
3433
  template_format: z6.union([
3429
3434
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -3625,7 +3630,7 @@ var PromptData = z6.object({
3625
3630
  prompt: PromptBlockDataNullish,
3626
3631
  options: PromptOptionsNullish,
3627
3632
  parser: PromptParserNullish,
3628
- preprocessor: PreprocessorSavedFunctionId,
3633
+ preprocessor: PreprocessorId,
3629
3634
  tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
3630
3635
  template_format: z6.union([
3631
3636
  z6.enum(["mustache", "nunjucks", "none"]),
@@ -3811,6 +3816,19 @@ var MessageRole = z6.enum([
3811
3816
  "model",
3812
3817
  "developer"
3813
3818
  ]);
3819
+ var NullableSavedFunctionId = z6.union([
3820
+ z6.object({
3821
+ type: z6.literal("function"),
3822
+ id: z6.string(),
3823
+ version: z6.string().optional()
3824
+ }),
3825
+ z6.object({
3826
+ type: z6.literal("global"),
3827
+ name: z6.string(),
3828
+ function_type: FunctionTypeEnum.optional().default("scorer")
3829
+ }),
3830
+ z6.null()
3831
+ ]);
3814
3832
  var ObjectReference = z6.object({
3815
3833
  object_type: z6.enum([
3816
3834
  "project_logs",
@@ -3832,6 +3850,7 @@ var TraceScope = z6.object({
3832
3850
  });
3833
3851
  var OnlineScoreConfig = z6.union([
3834
3852
  z6.object({
3853
+ status: AutomationStatus.optional(),
3835
3854
  sampling_rate: z6.number().gte(0).lte(1),
3836
3855
  scorers: z6.array(SavedFunctionId),
3837
3856
  btql_filter: z6.union([z6.string(), z6.null()]).optional(),
@@ -3912,6 +3931,72 @@ var Project = z6.object({
3912
3931
  user_id: z6.union([z6.string(), z6.null()]).optional(),
3913
3932
  settings: ProjectSettings.optional()
3914
3933
  });
3934
+ var WindowedAutomationConfig = z6.object({
3935
+ event_type: z6.literal("windowed"),
3936
+ product_origin: z6.union([z6.literal("patterns"), z6.null()]).optional(),
3937
+ status: AutomationStatus.optional(),
3938
+ threshold: z6.object({
3939
+ calculation: z6.object({
3940
+ type: z6.literal("btql"),
3941
+ btql_query: z6.string().min(1),
3942
+ output: z6.object({
3943
+ type: z6.literal("scalar"),
3944
+ value_column: z6.string().min(1)
3945
+ })
3946
+ }),
3947
+ policy: z6.object({
3948
+ condition: z6.object({
3949
+ type: z6.literal("threshold"),
3950
+ operator: z6.enum(["lt", "lte", "gt", "gte", "eq", "neq"]),
3951
+ threshold: z6.number()
3952
+ }),
3953
+ pending_seconds: z6.number().int().gte(0).lte(2592e3),
3954
+ no_data_behavior: z6.enum(["keep_last", "resolve", "alert"]),
3955
+ renotify_interval_seconds: z6.union([z6.number(), z6.null()]).optional(),
3956
+ notify_on_recovery: z6.boolean().optional().default(true)
3957
+ })
3958
+ }).optional(),
3959
+ window: z6.object({
3960
+ window_seconds: z6.number().int().gte(1).lte(2592e3),
3961
+ schedule: z6.union([
3962
+ z6.object({
3963
+ type: z6.literal("interval"),
3964
+ evaluation_interval_seconds: z6.number().int().gte(1).lte(2592e3)
3965
+ }),
3966
+ z6.object({
3967
+ type: z6.literal("cron"),
3968
+ cron_expression: z6.string().min(1),
3969
+ timezone: z6.union([z6.string(), z6.null()]).optional()
3970
+ })
3971
+ ]),
3972
+ evaluation_delay_seconds: z6.number().int().gte(0).lte(2592e3)
3973
+ }),
3974
+ loop: z6.object({
3975
+ prompt: z6.string().min(1).max(1e4),
3976
+ include_trigger_input: z6.boolean().optional().default(false),
3977
+ agent_slug: z6.string().min(1),
3978
+ auto_approve_tools: z6.array(z6.string().min(1)).optional().default([]),
3979
+ harness: z6.enum(["native", "codex", "claude-code"]).optional(),
3980
+ model: z6.string().min(1).optional(),
3981
+ reasoning_effort: z6.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional()
3982
+ }).optional(),
3983
+ actions: z6.array(
3984
+ z6.union([
3985
+ z6.object({
3986
+ type: z6.literal("webhook"),
3987
+ url: z6.string(),
3988
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
3989
+ }),
3990
+ z6.object({
3991
+ type: z6.literal("slack"),
3992
+ workspace_id: z6.string(),
3993
+ channel: z6.string(),
3994
+ message_template: z6.string().optional(),
3995
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
3996
+ })
3997
+ ])
3998
+ ).max(20).optional().default([])
3999
+ });
3915
4000
  var TopicAutomationFacetModel = z6.union([
3916
4001
  z6.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3917
4002
  z6.null()
@@ -3953,7 +4038,8 @@ var TopicDigestAutomationConfig = z6.object({
3953
4038
  type: z6.literal("slack"),
3954
4039
  workspace_id: z6.string(),
3955
4040
  channel: z6.string(),
3956
- message_template: z6.string().optional()
4041
+ message_template: z6.string().optional(),
4042
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
3957
4043
  }),
3958
4044
  topic_map_function_ids: z6.array(z6.string()).max(10).optional()
3959
4045
  });
@@ -3967,15 +4053,21 @@ var ProjectAutomation = z6.object({
3967
4053
  config: z6.union([
3968
4054
  z6.object({
3969
4055
  event_type: z6.literal("logs"),
4056
+ status: AutomationStatus.optional(),
3970
4057
  btql_filter: z6.string(),
3971
4058
  interval_seconds: z6.number().gte(1).lte(2592e3),
3972
4059
  action: z6.union([
3973
- z6.object({ type: z6.literal("webhook"), url: z6.string() }),
4060
+ z6.object({
4061
+ type: z6.literal("webhook"),
4062
+ url: z6.string(),
4063
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
4064
+ }),
3974
4065
  z6.object({
3975
4066
  type: z6.literal("slack"),
3976
4067
  workspace_id: z6.string(),
3977
4068
  channel: z6.string(),
3978
- message_template: z6.string().optional()
4069
+ message_template: z6.string().optional(),
4070
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
3979
4071
  })
3980
4072
  ])
3981
4073
  }),
@@ -4026,21 +4118,38 @@ var ProjectAutomation = z6.object({
4026
4118
  }),
4027
4119
  z6.object({
4028
4120
  event_type: z6.literal("environment_update"),
4121
+ status: AutomationStatus.optional(),
4029
4122
  environment_filter: z6.array(z6.string()).optional(),
4030
4123
  action: z6.union([
4031
- z6.object({ type: z6.literal("webhook"), url: z6.string() }),
4124
+ z6.object({
4125
+ type: z6.literal("webhook"),
4126
+ url: z6.string(),
4127
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
4128
+ }),
4032
4129
  z6.object({
4033
4130
  type: z6.literal("slack"),
4034
4131
  workspace_id: z6.string(),
4035
4132
  channel: z6.string(),
4036
- message_template: z6.string().optional()
4133
+ message_template: z6.string().optional(),
4134
+ formatting_prompt: z6.string().min(1).max(1e4).optional()
4037
4135
  })
4038
4136
  ])
4039
4137
  }),
4138
+ WindowedAutomationConfig,
4040
4139
  TopicAutomationConfig,
4041
4140
  TopicDigestAutomationConfig
4042
4141
  ])
4043
4142
  });
4143
+ var ProjectGroup = z6.object({
4144
+ id: z6.string().uuid(),
4145
+ org_id: z6.string().uuid(),
4146
+ user_id: z6.union([z6.string(), z6.null()]).optional(),
4147
+ created: z6.union([z6.string(), z6.null()]).optional(),
4148
+ name: z6.string(),
4149
+ description: z6.union([z6.string(), z6.null()]).optional(),
4150
+ deleted_at: z6.union([z6.string(), z6.null()]).optional(),
4151
+ member_projects: z6.array(z6.string().uuid()).max(1e4)
4152
+ });
4044
4153
  var ProjectLogsEvent = z6.object({
4045
4154
  id: z6.string(),
4046
4155
  _xact_id: z6.string(),
@@ -4258,7 +4367,8 @@ var RunEval = z6.object({
4258
4367
  dataset_environment: z6.union([z6.string(), z6.null()]).optional(),
4259
4368
  _internal_btql: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional()
4260
4369
  }),
4261
- z6.object({ data: z6.array(z6.unknown()) })
4370
+ z6.object({ data: z6.array(z6.unknown()) }),
4371
+ z6.object({ experiment_name: z6.string() })
4262
4372
  ]),
4263
4373
  name: z6.string().optional(),
4264
4374
  parameters: z6.object({}).partial().passthrough().optional(),
@@ -4463,7 +4573,10 @@ var View = z6.object({
4463
4573
  "for_review_datasets"
4464
4574
  ]),
4465
4575
  name: z6.string(),
4576
+ description: z6.union([z6.string(), z6.null()]).optional(),
4577
+ starred: z6.boolean().optional(),
4466
4578
  created: z6.union([z6.string(), z6.null()]).optional(),
4579
+ updated_at: z6.union([z6.string(), z6.null()]).optional(),
4467
4580
  view_data: ViewData.optional(),
4468
4581
  options: ViewOptions.optional(),
4469
4582
  user_id: z6.union([z6.string(), z6.null()]).optional(),
@@ -4551,6 +4664,34 @@ var registerTemplatePlugin = templateRegistry.register.bind(templateRegistry);
4551
4664
  var getTemplateRenderer = templateRegistry.get.bind(templateRegistry);
4552
4665
  registerTemplatePlugin(mustachePlugin);
4553
4666
 
4667
+ // src/template/renderer.ts
4668
+ function isTemplateFormat(v) {
4669
+ return v === "mustache" || v === "nunjucks" || v === "none";
4670
+ }
4671
+ function parseTemplateFormat(value, defaultFormat = "mustache") {
4672
+ return isTemplateFormat(value) ? value : defaultFormat;
4673
+ }
4674
+ function renderTemplateContent(template, variables, escape, options) {
4675
+ const strict = !!options.strict;
4676
+ const templateFormat = parseTemplateFormat(options.templateFormat);
4677
+ if (templateFormat === "none") {
4678
+ return template;
4679
+ }
4680
+ const renderer = getTemplateRenderer(templateFormat);
4681
+ if (!renderer) {
4682
+ if (templateFormat === "nunjucks") {
4683
+ throw new Error(
4684
+ "Nunjucks templating requires @braintrust/template-nunjucks. Install and import it to enable templateFormat: 'nunjucks'."
4685
+ );
4686
+ }
4687
+ throw new Error(`No template renderer registered for ${templateFormat}`);
4688
+ }
4689
+ if (strict && renderer.lint) {
4690
+ renderer.lint(template, variables);
4691
+ }
4692
+ return renderer.render(template, variables, escape, strict);
4693
+ }
4694
+
4554
4695
  // src/logger.ts
4555
4696
  import { z as z8, ZodError } from "zod/v3";
4556
4697
 
@@ -5137,44 +5278,72 @@ function createCacheLayers({
5137
5278
  }
5138
5279
 
5139
5280
  // src/prompt-cache/prompt-cache.ts
5140
- function createCacheKey(key) {
5281
+ function createCacheKey(key, namespace) {
5282
+ let cacheKey;
5141
5283
  if (key.id) {
5142
- return `id:${key.id}`;
5143
- }
5144
- const prefix = key.projectId ?? key.projectName;
5145
- if (!prefix) {
5146
- throw new Error("Either projectId or projectName must be provided");
5147
- }
5148
- if (!key.slug) {
5149
- throw new Error("Slug must be provided when not using ID");
5284
+ cacheKey = `id:${key.id}`;
5285
+ } else {
5286
+ const prefix = key.projectId ?? key.projectName;
5287
+ if (!prefix) {
5288
+ throw new Error("Either projectId or projectName must be provided");
5289
+ }
5290
+ if (!key.slug) {
5291
+ throw new Error("Slug must be provided when not using ID");
5292
+ }
5293
+ cacheKey = `${prefix}:${key.slug}:${key.version ?? "latest"}`;
5150
5294
  }
5151
- return `${prefix}:${key.slug}:${key.version ?? "latest"}`;
5295
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
5152
5296
  }
5153
- var PromptCache = class {
5297
+ var PromptCache = class _PromptCache {
5154
5298
  memoryCache;
5155
5299
  diskCache;
5300
+ namespace;
5301
+ expectedResolvedOrgIdentity;
5156
5302
  constructor(options) {
5157
5303
  this.memoryCache = options.memoryCache;
5158
5304
  this.diskCache = options.diskCache;
5305
+ this.namespace = options.namespace;
5306
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
5307
+ }
5308
+ /**
5309
+ * Returns a cache view that shares the same storage layers but isolates all
5310
+ * entries under the provided namespace.
5311
+ */
5312
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
5313
+ return new _PromptCache({
5314
+ memoryCache: this.memoryCache,
5315
+ diskCache: this.diskCache,
5316
+ namespace,
5317
+ expectedResolvedOrgIdentity
5318
+ });
5159
5319
  }
5160
5320
  /**
5161
5321
  * Retrieves a prompt from the cache.
5162
5322
  * First checks the in-memory LRU cache, then falls back to checking the disk cache if available.
5163
5323
  */
5164
5324
  async get(key) {
5165
- const cacheKey = createCacheKey(key);
5325
+ const cacheKey = createCacheKey(key, this.namespace);
5166
5326
  if (this.memoryCache) {
5167
- const memoryPrompt = this.memoryCache.get(cacheKey);
5168
- if (memoryPrompt !== void 0) {
5169
- return memoryPrompt;
5327
+ const memoryEntry = this.memoryCache.get(cacheKey);
5328
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
5329
+ return memoryEntry.value;
5170
5330
  }
5171
5331
  }
5172
5332
  if (this.diskCache) {
5173
- const diskPrompt = await this.diskCache.get(cacheKey);
5174
- if (!diskPrompt) {
5333
+ const diskEntry = await this.diskCache.get(cacheKey);
5334
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
5175
5335
  return void 0;
5176
5336
  }
5177
- this.memoryCache?.set(cacheKey, diskPrompt);
5337
+ const serializedPrompt = diskEntry.value;
5338
+ const diskPrompt = new Prompt2(
5339
+ serializedPrompt.metadata,
5340
+ serializedPrompt.defaults,
5341
+ serializedPrompt.noTrace
5342
+ );
5343
+ this.memoryCache?.set(cacheKey, {
5344
+ value: diskPrompt,
5345
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
5346
+ });
5178
5347
  return diskPrompt;
5179
5348
  }
5180
5349
  return void 0;
@@ -5188,58 +5357,91 @@ var PromptCache = class {
5188
5357
  * @throws If there is an error writing to the disk cache.
5189
5358
  */
5190
5359
  async set(key, value) {
5191
- const cacheKey = createCacheKey(key);
5192
- this.memoryCache?.set(cacheKey, value);
5360
+ const cacheKey = createCacheKey(key, this.namespace);
5361
+ const memoryEntry = {
5362
+ value,
5363
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5364
+ };
5365
+ this.memoryCache?.set(cacheKey, memoryEntry);
5193
5366
  if (this.diskCache) {
5194
- await this.diskCache.set(cacheKey, value);
5367
+ await this.diskCache.set(cacheKey, {
5368
+ value: value._internalSerializeForCache(),
5369
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5370
+ });
5195
5371
  }
5196
5372
  }
5197
5373
  };
5198
5374
 
5199
5375
  // src/prompt-cache/parameters-cache.ts
5200
- function createCacheKey2(key) {
5376
+ function createCacheKey2(key, namespace) {
5377
+ let cacheKey;
5201
5378
  if (key.id) {
5202
- return `parameters:id:${key.id}`;
5203
- }
5204
- const prefix = key.projectId ?? key.projectName;
5205
- if (!prefix) {
5206
- throw new Error("Either projectId or projectName must be provided");
5207
- }
5208
- if (!key.slug) {
5209
- throw new Error("Slug must be provided when not using ID");
5379
+ cacheKey = `parameters:id:${key.id}`;
5380
+ } else {
5381
+ const prefix = key.projectId ?? key.projectName;
5382
+ if (!prefix) {
5383
+ throw new Error("Either projectId or projectName must be provided");
5384
+ }
5385
+ if (!key.slug) {
5386
+ throw new Error("Slug must be provided when not using ID");
5387
+ }
5388
+ cacheKey = `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
5210
5389
  }
5211
- return `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
5390
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
5212
5391
  }
5213
- var ParametersCache = class {
5392
+ var ParametersCache = class _ParametersCache {
5214
5393
  memoryCache;
5215
5394
  diskCache;
5395
+ namespace;
5396
+ expectedResolvedOrgIdentity;
5216
5397
  constructor(options) {
5217
5398
  this.memoryCache = options.memoryCache;
5218
5399
  this.diskCache = options.diskCache;
5400
+ this.namespace = options.namespace;
5401
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
5402
+ }
5403
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
5404
+ return new _ParametersCache({
5405
+ memoryCache: this.memoryCache,
5406
+ diskCache: this.diskCache,
5407
+ namespace,
5408
+ expectedResolvedOrgIdentity
5409
+ });
5219
5410
  }
5220
5411
  async get(key) {
5221
- const cacheKey = createCacheKey2(key);
5412
+ const cacheKey = createCacheKey2(key, this.namespace);
5222
5413
  if (this.memoryCache) {
5223
- const memoryParams = this.memoryCache.get(cacheKey);
5224
- if (memoryParams !== void 0) {
5225
- return memoryParams;
5414
+ const memoryEntry = this.memoryCache.get(cacheKey);
5415
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
5416
+ return memoryEntry.value;
5226
5417
  }
5227
5418
  }
5228
5419
  if (this.diskCache) {
5229
- const diskParams = await this.diskCache.get(cacheKey);
5230
- if (!diskParams) {
5420
+ const diskEntry = await this.diskCache.get(cacheKey);
5421
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
5231
5422
  return void 0;
5232
5423
  }
5233
- this.memoryCache?.set(cacheKey, diskParams);
5234
- return diskParams;
5424
+ const diskParameters = new RemoteEvalParameters(diskEntry.value.metadata);
5425
+ this.memoryCache?.set(cacheKey, {
5426
+ value: diskParameters,
5427
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
5428
+ });
5429
+ return diskParameters;
5235
5430
  }
5236
5431
  return void 0;
5237
5432
  }
5238
5433
  async set(key, value) {
5239
- const cacheKey = createCacheKey2(key);
5240
- this.memoryCache?.set(cacheKey, value);
5434
+ const cacheKey = createCacheKey2(key, this.namespace);
5435
+ const memoryEntry = {
5436
+ value,
5437
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5438
+ };
5439
+ this.memoryCache?.set(cacheKey, memoryEntry);
5241
5440
  if (this.diskCache) {
5242
- await this.diskCache.set(cacheKey, value);
5441
+ await this.diskCache.set(cacheKey, {
5442
+ value: value._internalSerializeForCache(),
5443
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5444
+ });
5243
5445
  }
5244
5446
  }
5245
5447
  };
@@ -5543,6 +5745,7 @@ var INSTRUMENTATION_NAMES = {
5543
5745
  CLOUDFLARE_THINK: "cloudflare-think",
5544
5746
  COHERE: "cohere",
5545
5747
  CURSOR_SDK: "cursor-sdk",
5748
+ DEEPSEEK_HARNESS: "deepseek-harness",
5546
5749
  EVE: "eve",
5547
5750
  FLUE: "flue",
5548
5751
  GENKIT: "genkit",
@@ -5562,12 +5765,13 @@ var INSTRUMENTATION_NAMES = {
5562
5765
  OPENROUTER: "openrouter",
5563
5766
  OPENROUTER_AGENT: "openrouter-agent",
5564
5767
  PI_CODING_AGENT: "pi-coding-agent",
5565
- STRANDS_AGENT_SDK: "strands-agent-sdk"
5768
+ STRANDS_AGENT_SDK: "strands-agent-sdk",
5769
+ VOYAGEAI: "voyageai"
5566
5770
  };
5567
5771
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5568
5772
  "braintrust.spanInstrumentationName"
5569
5773
  );
5570
- var SDK_VERSION = true ? "3.27.0" : "0.0.0";
5774
+ var SDK_VERSION = true ? "3.29.0" : "0.0.0";
5571
5775
  function withSpanInstrumentationName(args, instrumentationName) {
5572
5776
  return {
5573
5777
  ...args,
@@ -5686,6 +5890,16 @@ var datasetSnapshotRegisterResponseSchema = z8.object({
5686
5890
  dataset_snapshot: DatasetSnapshot,
5687
5891
  found_existing: z8.boolean().optional()
5688
5892
  });
5893
+ var datasetObjectInfoSchema = z8.object({
5894
+ object_id: z8.string(),
5895
+ object_name: z8.string(),
5896
+ parent_cols: z8.object({
5897
+ project: z8.object({
5898
+ id: z8.string(),
5899
+ name: z8.string()
5900
+ })
5901
+ })
5902
+ });
5689
5903
  var datasetRestorePreviewResultSchema = z8.object({
5690
5904
  rows_to_restore: z8.number(),
5691
5905
  rows_to_delete: z8.number()
@@ -5762,6 +5976,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
5762
5976
  var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
5763
5977
  "braintrust.initial-span-write-as-merge"
5764
5978
  );
5979
+ var RESUME_SPAN_WITHOUT_INITIAL_WRITE = /* @__PURE__ */ Symbol(
5980
+ "braintrust.resume-span-without-initial-write"
5981
+ );
5765
5982
  var INTERNAL_SPAN_CONTEXT = /* @__PURE__ */ Symbol("braintrust.internal-span-context");
5766
5983
  var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
5767
5984
  "braintrust.currentSpanStore"
@@ -5896,12 +6113,53 @@ var loginSchema = z8.strictObject({
5896
6113
  });
5897
6114
  var stateNonce = 0;
5898
6115
  var V1_PROXY_SUFFIX = "/v1/proxy";
6116
+ var LOADER_LOGIN_CACHE_MAX = 16;
5899
6117
  function normalizeProxyConnUrl(proxyUrl) {
5900
6118
  return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
5901
6119
  }
5902
6120
  var BraintrustState = class _BraintrustState {
6121
+ id;
6122
+ currentExperiment;
6123
+ // Note: the value of IsAsyncFlush doesn't really matter here, since we
6124
+ // (safely) dynamically cast it whenever retrieving the logger.
6125
+ currentLogger;
6126
+ currentParent;
6127
+ currentSpan;
6128
+ // Any time we re-log in, we directly update the apiConn inside the logger.
6129
+ // This is preferable to replacing the whole logger, which would create the
6130
+ // possibility of multiple loggers floating around, which may not log in a
6131
+ // deterministic order.
6132
+ _bgLogger;
6133
+ _overrideBgLogger = null;
6134
+ appUrl = null;
6135
+ appPublicUrl = null;
6136
+ loginToken = null;
6137
+ orgId = null;
6138
+ orgName = null;
6139
+ apiUrl = null;
6140
+ proxyUrl = null;
6141
+ loggedIn = false;
6142
+ gitMetadataSettings;
6143
+ debugLogLevel;
6144
+ debugLogLevelConfigured = false;
6145
+ fetch = globalThis.fetch;
6146
+ _appConn = null;
6147
+ _apiConn = null;
6148
+ _proxyConn = null;
6149
+ promptCache;
6150
+ parametersCache;
6151
+ spanCache;
6152
+ _idGenerator = null;
6153
+ _contextManager = null;
6154
+ _otelFlushCallback = null;
6155
+ spanOriginEnvironment;
6156
+ traceContextSigningSecret;
6157
+ loaderLoginCache = /* @__PURE__ */ new WeakMap();
6158
+ loginParams;
6159
+ activeLoginOrgNameSelector;
5903
6160
  constructor(loginParams) {
5904
- this.loginParams = loginParams;
6161
+ this.loginParams = { ...loginParams };
6162
+ this.activeLoginOrgNameSelector = loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
5905
6163
  this.id = `${(/* @__PURE__ */ new Date()).toLocaleString()}-${stateNonce++}`;
5906
6164
  this.currentExperiment = void 0;
5907
6165
  this.currentLogger = void 0;
@@ -5938,12 +6196,14 @@ var BraintrustState = class _BraintrustState {
5938
6196
  const {
5939
6197
  memoryCache: parametersMemoryCache,
5940
6198
  diskCache: parametersDiskCache
5941
- } = createCacheLayers({
5942
- memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
5943
- diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
5944
- diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
5945
- getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
5946
- });
6199
+ } = createCacheLayers(
6200
+ {
6201
+ memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
6202
+ diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
6203
+ diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
6204
+ getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
6205
+ }
6206
+ );
5947
6207
  this.parametersCache = new ParametersCache({
5948
6208
  memoryCache: parametersMemoryCache,
5949
6209
  diskCache: parametersDiskCache
@@ -5952,43 +6212,6 @@ var BraintrustState = class _BraintrustState {
5952
6212
  this.spanOriginEnvironment = detectSpanOriginEnvironment();
5953
6213
  this._internalSetTraceContextSigningSecret(loginParams.apiKey);
5954
6214
  }
5955
- loginParams;
5956
- id;
5957
- currentExperiment;
5958
- // Note: the value of IsAsyncFlush doesn't really matter here, since we
5959
- // (safely) dynamically cast it whenever retrieving the logger.
5960
- currentLogger;
5961
- currentParent;
5962
- currentSpan;
5963
- // Any time we re-log in, we directly update the apiConn inside the logger.
5964
- // This is preferable to replacing the whole logger, which would create the
5965
- // possibility of multiple loggers floating around, which may not log in a
5966
- // deterministic order.
5967
- _bgLogger;
5968
- _overrideBgLogger = null;
5969
- appUrl = null;
5970
- appPublicUrl = null;
5971
- loginToken = null;
5972
- orgId = null;
5973
- orgName = null;
5974
- apiUrl = null;
5975
- proxyUrl = null;
5976
- loggedIn = false;
5977
- gitMetadataSettings;
5978
- debugLogLevel;
5979
- debugLogLevelConfigured = false;
5980
- fetch = globalThis.fetch;
5981
- _appConn = null;
5982
- _apiConn = null;
5983
- _proxyConn = null;
5984
- promptCache;
5985
- parametersCache;
5986
- spanCache;
5987
- _idGenerator = null;
5988
- _contextManager = null;
5989
- _otelFlushCallback = null;
5990
- spanOriginEnvironment;
5991
- traceContextSigningSecret;
5992
6215
  /** @internal */
5993
6216
  _internalSetTraceContextSigningSecret(secret) {
5994
6217
  const normalizedSecret = secret?.trim();
@@ -6013,6 +6236,101 @@ var BraintrustState = class _BraintrustState {
6013
6236
  this._appConn = null;
6014
6237
  this._apiConn = null;
6015
6238
  this._proxyConn = null;
6239
+ this.loaderLoginCache = /* @__PURE__ */ new WeakMap();
6240
+ }
6241
+ /** @internal */
6242
+ async _internalResolveLoaderLoginOptions({
6243
+ apiKey,
6244
+ appUrl,
6245
+ orgName,
6246
+ fetch: fetch2,
6247
+ forceLogin
6248
+ }) {
6249
+ const resolvedAppUrl = appUrl ?? (this.loggedIn ? this.appUrl ?? void 0 : void 0) ?? this.loginParams.appUrl ?? isomorph_default.getEnv("BRAINTRUST_APP_URL") ?? "https://www.braintrust.dev";
6250
+ const resolvedApiKey = apiKey ?? (this.loggedIn ? this.loginToken ?? void 0 : void 0) ?? this.loginParams.apiKey ?? await isomorph_default.getBraintrustApiKey();
6251
+ if (!resolvedApiKey) {
6252
+ throw new Error(
6253
+ "Please specify an api key (e.g. by setting BRAINTRUST_API_KEY)."
6254
+ );
6255
+ }
6256
+ const normalizedApiKey = HTTPConnection.sanitize_token(resolvedApiKey);
6257
+ const usesActiveCredential = this.loggedIn && normalizedApiKey === this.loginToken;
6258
+ const requestedOrgName = orgName ?? (usesActiveCredential ? this.activeLoginOrgNameSelector : void 0) ?? this.loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
6259
+ const resolvedOrgName = orgName ?? (usesActiveCredential ? this.orgName ?? void 0 : void 0) ?? requestedOrgName;
6260
+ const resolvedFetch = fetch2 ?? (this.loggedIn ? this.fetch : void 0) ?? this.loginParams.fetch ?? globalThis.fetch;
6261
+ const credentialCacheNamespace = JSON.stringify([
6262
+ "loader-credential",
6263
+ resolvedAppUrl,
6264
+ requestedOrgName,
6265
+ normalizedApiKey
6266
+ ]);
6267
+ return {
6268
+ apiKey: normalizedApiKey,
6269
+ appUrl: resolvedAppUrl,
6270
+ orgName: resolvedOrgName,
6271
+ fetch: resolvedFetch,
6272
+ forceLogin,
6273
+ credentialCacheNamespace,
6274
+ existingState: !forceLogin && usesActiveCredential && resolvedAppUrl === this.appUrl && resolvedOrgName === this.orgName && resolvedFetch === this.fetch ? this : void 0
6275
+ };
6276
+ }
6277
+ /** @internal */
6278
+ _internalGetLoaderCacheViews(loginOptions, requestState) {
6279
+ const expectedResolvedOrgIdentity = requestState?.orgId && requestState.appUrl ? JSON.stringify([
6280
+ "loader-org",
6281
+ requestState.appUrl,
6282
+ requestState.orgId
6283
+ ]) : void 0;
6284
+ return {
6285
+ promptCache: this.promptCache.withNamespace(
6286
+ loginOptions.credentialCacheNamespace,
6287
+ expectedResolvedOrgIdentity
6288
+ ),
6289
+ parametersCache: this.parametersCache.withNamespace(
6290
+ loginOptions.credentialCacheNamespace,
6291
+ expectedResolvedOrgIdentity
6292
+ )
6293
+ };
6294
+ }
6295
+ /** @internal */
6296
+ async _internalGetLoaderState({
6297
+ apiKey,
6298
+ appUrl,
6299
+ orgName,
6300
+ fetch: fetch2,
6301
+ forceLogin,
6302
+ existingState
6303
+ }) {
6304
+ if (existingState) {
6305
+ return existingState;
6306
+ }
6307
+ let cache = this.loaderLoginCache.get(fetch2);
6308
+ if (!cache) {
6309
+ cache = new LRUCache({ max: LOADER_LOGIN_CACHE_MAX });
6310
+ this.loaderLoginCache.set(fetch2, cache);
6311
+ }
6312
+ const cacheKey = JSON.stringify([appUrl, orgName, apiKey]);
6313
+ if (!forceLogin) {
6314
+ const cachedState = cache.get(cacheKey);
6315
+ if (cachedState) {
6316
+ return cachedState;
6317
+ }
6318
+ }
6319
+ const statePromise = loginToLoaderRequestState({
6320
+ orgName,
6321
+ apiKey,
6322
+ appUrl,
6323
+ fetch: fetch2
6324
+ });
6325
+ cache.set(cacheKey, statePromise);
6326
+ try {
6327
+ return await statePromise;
6328
+ } catch (error) {
6329
+ if (cache.get(cacheKey) === statePromise) {
6330
+ cache.delete(cacheKey);
6331
+ }
6332
+ throw error;
6333
+ }
6016
6334
  }
6017
6335
  resetIdGenState() {
6018
6336
  this._idGenerator = null;
@@ -6061,6 +6379,8 @@ var BraintrustState = class _BraintrustState {
6061
6379
  this.debugLogLevel = other.debugLogLevel;
6062
6380
  this.debugLogLevelConfigured = other.debugLogLevelConfigured;
6063
6381
  this.traceContextSigningSecret = other.traceContextSigningSecret;
6382
+ this.fetch = other.fetch;
6383
+ this.activeLoginOrgNameSelector = other.activeLoginOrgNameSelector;
6064
6384
  setGlobalDebugLogLevel(
6065
6385
  this.debugLogLevelConfigured ? this.debugLogLevel ?? false : void 0
6066
6386
  );
@@ -6255,36 +6575,76 @@ var FailedHTTPResponse = class extends Error {
6255
6575
  status;
6256
6576
  text;
6257
6577
  data;
6258
- constructor(status, text, data) {
6578
+ cause;
6579
+ constructor(status, text, data, cause) {
6259
6580
  super(`${status}: ${text} (${data})`);
6260
6581
  this.status = status;
6261
6582
  this.text = text;
6262
6583
  this.data = data;
6584
+ this.cause = cause;
6585
+ }
6586
+ };
6587
+ var HTTPTransportError = class extends Error {
6588
+ cause;
6589
+ constructor(cause) {
6590
+ super(cause instanceof Error ? cause.message : String(cause));
6591
+ this.name = "HTTPTransportError";
6592
+ this.cause = cause;
6263
6593
  }
6264
6594
  };
6595
+ var httpTransportErrorCauses = /* @__PURE__ */ new WeakSet();
6596
+ function recordHTTPTransportError(error) {
6597
+ if (typeof error === "object" && error !== null || typeof error === "function") {
6598
+ httpTransportErrorCauses.add(error);
6599
+ }
6600
+ }
6601
+ function rethrowHTTPTransportError(error, classifyTransportErrors) {
6602
+ if (classifyTransportErrors) {
6603
+ throw new HTTPTransportError(error);
6604
+ }
6605
+ recordHTTPTransportError(error);
6606
+ throw error;
6607
+ }
6608
+ async function readJSONResponse(response, classifyTransportErrors = false) {
6609
+ let data;
6610
+ try {
6611
+ data = await response.text();
6612
+ } catch (error) {
6613
+ rethrowHTTPTransportError(error, classifyTransportErrors);
6614
+ }
6615
+ return JSON.parse(data);
6616
+ }
6265
6617
  async function checkResponse(resp) {
6266
6618
  if (resp.ok) {
6267
6619
  return resp;
6268
- } else {
6620
+ }
6621
+ let data;
6622
+ try {
6623
+ data = await resp.text();
6624
+ } catch (error) {
6269
6625
  throw new FailedHTTPResponse(
6270
6626
  resp.status,
6271
6627
  resp.statusText,
6272
- await resp.text()
6628
+ "Unable to read response body",
6629
+ error
6273
6630
  );
6274
6631
  }
6632
+ throw new FailedHTTPResponse(resp.status, resp.statusText, data);
6275
6633
  }
6276
6634
  var HTTPConnection = class _HTTPConnection {
6277
- base_url;
6278
- token;
6279
- headers;
6280
- fetch;
6281
- constructor(base_url, fetch2) {
6635
+ constructor(base_url, fetch2, classifyTransportErrors = false) {
6636
+ this.classifyTransportErrors = classifyTransportErrors;
6282
6637
  this.base_url = base_url;
6283
6638
  this.token = null;
6284
6639
  this.headers = {};
6285
6640
  this._reset();
6286
6641
  this.fetch = fetch2;
6287
6642
  }
6643
+ classifyTransportErrors;
6644
+ base_url;
6645
+ token;
6646
+ headers;
6647
+ fetch;
6288
6648
  setFetch(fetch2) {
6289
6649
  this.fetch = fetch2;
6290
6650
  }
@@ -6324,9 +6684,9 @@ var HTTPConnection = class _HTTPConnection {
6324
6684
  ).toString();
6325
6685
  const this_fetch = this.fetch;
6326
6686
  const this_headers = this.headers;
6327
- return await checkResponse(
6328
- // Using toString() here makes it work with isomorphic fetch
6329
- await this_fetch(url.toString(), {
6687
+ let response;
6688
+ try {
6689
+ response = await this_fetch(url.toString(), {
6330
6690
  headers: {
6331
6691
  Accept: "application/json",
6332
6692
  ...this_headers,
@@ -6334,8 +6694,14 @@ var HTTPConnection = class _HTTPConnection {
6334
6694
  },
6335
6695
  keepalive: true,
6336
6696
  ...rest
6337
- })
6338
- );
6697
+ });
6698
+ } catch (error) {
6699
+ if (config?.signal?.aborted) {
6700
+ throw getAbortReason(config.signal);
6701
+ }
6702
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
6703
+ }
6704
+ return await checkResponse(response);
6339
6705
  }
6340
6706
  async post(path, params, config, retries = 0) {
6341
6707
  const { headers, ...rest } = config || {};
@@ -6345,8 +6711,9 @@ var HTTPConnection = class _HTTPConnection {
6345
6711
  const tries = retries + 1;
6346
6712
  for (let i = 0; i < tries; i++) {
6347
6713
  try {
6348
- return await checkResponse(
6349
- await this_fetch(_urljoin(this_base_url, path), {
6714
+ let response;
6715
+ try {
6716
+ response = await this_fetch(_urljoin(this_base_url, path), {
6350
6717
  method: "POST",
6351
6718
  headers: {
6352
6719
  Accept: "application/json",
@@ -6357,8 +6724,14 @@ var HTTPConnection = class _HTTPConnection {
6357
6724
  body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
6358
6725
  keepalive: true,
6359
6726
  ...rest
6360
- })
6361
- );
6727
+ });
6728
+ } catch (error) {
6729
+ if (config?.signal?.aborted) {
6730
+ throw getAbortReason(config.signal);
6731
+ }
6732
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
6733
+ }
6734
+ return await checkResponse(response);
6362
6735
  } catch (error) {
6363
6736
  if (config?.signal?.aborted) {
6364
6737
  throw getAbortReason(config.signal);
@@ -6383,7 +6756,7 @@ var HTTPConnection = class _HTTPConnection {
6383
6756
  for (let i = 0; i < tries; i++) {
6384
6757
  try {
6385
6758
  const resp = await this.get(`${object_type}`, args);
6386
- return await resp.json();
6759
+ return await readJSONResponse(resp, this.classifyTransportErrors);
6387
6760
  } catch (e) {
6388
6761
  if (i < tries - 1) {
6389
6762
  debugLogger.debug(
@@ -6406,7 +6779,7 @@ var HTTPConnection = class _HTTPConnection {
6406
6779
  const resp = await this.post(`${object_type}`, args, {
6407
6780
  headers: { "Content-Type": "application/json" }
6408
6781
  });
6409
- return await resp.json();
6782
+ return await readJSONResponse(resp, this.classifyTransportErrors);
6410
6783
  }
6411
6784
  // Custom inspect for Node.js console.log
6412
6785
  [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
@@ -7961,6 +8334,52 @@ function initLogger(options = {}) {
7961
8334
  }
7962
8335
  return ret;
7963
8336
  }
8337
+ async function loginToLoaderRequestState({
8338
+ appUrl,
8339
+ apiKey,
8340
+ orgName,
8341
+ fetch: fetch2
8342
+ }) {
8343
+ let orgId;
8344
+ let apiUrl;
8345
+ if (apiKey === TEST_API_KEY) {
8346
+ orgId = "test-org-id";
8347
+ apiUrl = "https://braintrust.dev/fake-api-url";
8348
+ } else {
8349
+ let loginResponse;
8350
+ try {
8351
+ loginResponse = await fetch2(_urljoin(appUrl, `/api/apikey/login`), {
8352
+ method: "POST",
8353
+ headers: {
8354
+ "Content-Type": "application/json",
8355
+ Authorization: `Bearer ${apiKey}`
8356
+ }
8357
+ });
8358
+ } catch (error) {
8359
+ throw new HTTPTransportError(error);
8360
+ }
8361
+ const info = await readJSONResponse(
8362
+ await checkResponse(loginResponse),
8363
+ true
8364
+ );
8365
+ const org = selectLoginOrg(info.org_info, orgName);
8366
+ orgId = org.id;
8367
+ apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
8368
+ if (!apiUrl) {
8369
+ throw new Error(
8370
+ orgName ? `Unable to log into organization '${orgName}'. Are you sure this credential is scoped to the organization?` : "Unable to log into any organization with the provided credential."
8371
+ );
8372
+ }
8373
+ }
8374
+ const apiConnection = new HTTPConnection(apiUrl, fetch2, true);
8375
+ apiConnection.set_token(apiKey);
8376
+ apiConnection.make_long_lived();
8377
+ return {
8378
+ appUrl,
8379
+ orgId,
8380
+ apiConn: () => apiConnection
8381
+ };
8382
+ }
7964
8383
  async function loginToState(options = {}) {
7965
8384
  const {
7966
8385
  appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
@@ -7992,16 +8411,18 @@ async function loginToState(options = {}) {
7992
8411
  _saveOrgInfo(state, testOrgInfo, testOrgInfo[0].name);
7993
8412
  return state;
7994
8413
  } else {
7995
- const resp = await checkResponse(
7996
- await fetch2(_urljoin(state.appUrl, `/api/apikey/login`), {
8414
+ const loginResponse = await fetch2(
8415
+ _urljoin(state.appUrl, `/api/apikey/login`),
8416
+ {
7997
8417
  method: "POST",
7998
8418
  headers: {
7999
8419
  "Content-Type": "application/json",
8000
8420
  Authorization: `Bearer ${apiKey}`
8001
8421
  }
8002
- })
8422
+ }
8003
8423
  );
8004
- const info = await resp.json();
8424
+ const resp = await checkResponse(loginResponse);
8425
+ const info = await readJSONResponse(resp);
8005
8426
  _saveOrgInfo(state, info.org_info, orgName);
8006
8427
  if (!state.apiUrl) {
8007
8428
  if (orgName) {
@@ -8369,27 +8790,28 @@ function withCurrent(span, callback, state = void 0) {
8369
8790
  const currentState = state ?? _globalState;
8370
8791
  return currentState.contextManager.runInContext(span, () => callback(span));
8371
8792
  }
8372
- function _saveOrgInfo(state, org_info, org_name) {
8373
- if (org_info.length === 0) {
8793
+ function _saveOrgInfo(state, orgInfo, orgName) {
8794
+ const org = selectLoginOrg(orgInfo, orgName);
8795
+ state.orgId = org.id;
8796
+ state.orgName = org.name;
8797
+ state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
8798
+ state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
8799
+ state.gitMetadataSettings = org.git_metadata || void 0;
8800
+ }
8801
+ function selectLoginOrg(orgInfo, orgName) {
8802
+ if (orgInfo.length === 0) {
8374
8803
  throw new LoginInvalidOrgError(
8375
8804
  "This user is not part of any organizations."
8376
8805
  );
8377
8806
  }
8378
- for (const org of org_info) {
8379
- if (org_name === void 0 || org.name === org_name) {
8380
- state.orgId = org.id;
8381
- state.orgName = org.name;
8382
- state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
8383
- state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
8384
- state.gitMetadataSettings = org.git_metadata || void 0;
8385
- break;
8807
+ for (const org of orgInfo) {
8808
+ if (orgName === void 0 || org.name === orgName) {
8809
+ return org;
8386
8810
  }
8387
8811
  }
8388
- if (state.orgId === void 0) {
8389
- throw new LoginInvalidOrgError(
8390
- `Organization ${org_name} not found. Must be one of ${org_info.map((x) => x.name).join(", ")}`
8391
- );
8392
- }
8812
+ throw new LoginInvalidOrgError(
8813
+ `Organization ${orgName} not found. Must be one of ${orgInfo.map((org) => org.name).join(", ")}`
8814
+ );
8393
8815
  }
8394
8816
  function validateTags(tags) {
8395
8817
  const seen = /* @__PURE__ */ new Set();
@@ -8554,6 +8976,19 @@ function enrichAttachments(event, state) {
8554
8976
  }
8555
8977
  return event;
8556
8978
  }
8979
+ async function resolveAttachmentsToBase64(event, state) {
8980
+ for (const [key, value] of Object.entries(event)) {
8981
+ if (value instanceof ReadonlyAttachment) {
8982
+ event[key] = await value.asBase64Url();
8983
+ continue;
8984
+ }
8985
+ if (!(value instanceof Object)) {
8986
+ continue;
8987
+ }
8988
+ await resolveAttachmentsToBase64(value, state);
8989
+ }
8990
+ return event;
8991
+ }
8557
8992
  function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
8558
8993
  if ("input" in event && !isEmpty2(event.input) && "inputs" in event && !isEmpty2(event.inputs) || !("input" in event) && !("inputs" in event)) {
8559
8994
  throw new Error(
@@ -8611,7 +9046,7 @@ var ObjectFetcher = class {
8611
9046
  const objectId = await this.id;
8612
9047
  const batchLimit = batchSize ?? DEFAULT_FETCH_BATCH_SIZE;
8613
9048
  const internalLimit = getInternalBtqlLimit(this._internal_btql);
8614
- const limit = batchSize !== void 0 ? batchSize : internalLimit ?? batchLimit;
9049
+ let remainingLimit = internalLimit;
8615
9050
  const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
8616
9051
  Object.entries(this._internal_btql ?? {}).filter(
8617
9052
  ([key]) => key !== "cursor" && key !== "limit" && key !== "select" && key !== "from"
@@ -8620,6 +9055,10 @@ var ObjectFetcher = class {
8620
9055
  let cursor = void 0;
8621
9056
  let iterations = 0;
8622
9057
  while (true) {
9058
+ if (remainingLimit !== void 0 && remainingLimit <= 0) {
9059
+ return;
9060
+ }
9061
+ const limit = remainingLimit === void 0 ? batchLimit : Math.min(batchLimit, remainingLimit);
8623
9062
  const resp = await state.apiConn().post(
8624
9063
  `btql`,
8625
9064
  {
@@ -8659,7 +9098,14 @@ var ObjectFetcher = class {
8659
9098
  const respJson = await resp.json();
8660
9099
  const mutate = this.mutateRecord;
8661
9100
  for (const record of respJson.data ?? []) {
8662
- yield mutate ? mutate(record) : record;
9101
+ if (remainingLimit !== void 0 && remainingLimit <= 0) {
9102
+ return;
9103
+ }
9104
+ const mutatedRecord = mutate ? mutate(record) : record;
9105
+ if (remainingLimit !== void 0) {
9106
+ remainingLimit--;
9107
+ }
9108
+ yield mutatedRecord;
8663
9109
  }
8664
9110
  if (!respJson.cursor) {
8665
9111
  break;
@@ -9136,7 +9582,9 @@ var SpanImpl = class _SpanImpl {
9136
9582
  this._rootSpanId = resolvedIds.rootSpanId;
9137
9583
  this._spanParents = resolvedIds.spanParents;
9138
9584
  this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
9139
- this.logInternal({ event, internalData });
9585
+ if (!args[RESUME_SPAN_WITHOUT_INITIAL_WRITE]) {
9586
+ this.logInternal({ event, internalData });
9587
+ }
9140
9588
  this.isMerge = true;
9141
9589
  }
9142
9590
  getParentInfo() {
@@ -9830,6 +10278,473 @@ var Dataset2 = class extends ObjectFetcher {
9830
10278
  return typeof data === "object" && data !== null && "__braintrust_dataset_marker" in data;
9831
10279
  }
9832
10280
  };
10281
+ function isAttachmentObject(value) {
10282
+ return BraintrustAttachmentReference.safeParse(value).success || InlineAttachmentReferenceSchema.safeParse(value).success || ExternalAttachmentReference.safeParse(value).success;
10283
+ }
10284
+ function isURL(url) {
10285
+ try {
10286
+ const parsedUrl = new URL(url.trim());
10287
+ return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";
10288
+ } catch {
10289
+ return false;
10290
+ }
10291
+ }
10292
+ function expandAttachmentArrayPreTemplate(content, variables) {
10293
+ if (typeof content !== "string") return null;
10294
+ const match = content.match(/^\{\{\s*([\w.]+)\s*\}\}$/);
10295
+ if (!match) return null;
10296
+ const varPath = match[1];
10297
+ const value = varPath.includes(".") ? getObjValueByPath(variables, varPath.split(".")) : variables[varPath];
10298
+ if (!Array.isArray(value)) return null;
10299
+ const allValid = value.every(
10300
+ (v) => isAttachmentObject(v) || typeof v === "string" && isURL(v)
10301
+ );
10302
+ if (!allValid) return null;
10303
+ return value.map((item) => ({
10304
+ type: "image_url",
10305
+ image_url: { url: item }
10306
+ }));
10307
+ }
10308
+ function renderMessageImpl(render, message, variables) {
10309
+ return {
10310
+ ...message,
10311
+ ..."content" in message ? {
10312
+ content: isEmpty2(message.content) ? void 0 : typeof message.content === "string" ? render(message.content) : message.content.flatMap((c) => {
10313
+ switch (c.type) {
10314
+ case "text":
10315
+ return [{ ...c, text: render(c.text) }];
10316
+ case "image_url":
10317
+ if (isObject(c.image_url.url)) {
10318
+ throw new Error(
10319
+ "Attachments must be replaced with URLs before calling `build()`"
10320
+ );
10321
+ }
10322
+ if (variables) {
10323
+ const expanded = expandAttachmentArrayPreTemplate(
10324
+ c.image_url.url,
10325
+ variables
10326
+ );
10327
+ if (expanded) {
10328
+ return expanded;
10329
+ }
10330
+ }
10331
+ return [
10332
+ {
10333
+ ...c,
10334
+ image_url: {
10335
+ ...c.image_url,
10336
+ url: render(c.image_url.url)
10337
+ }
10338
+ }
10339
+ ];
10340
+ case "file":
10341
+ return [
10342
+ {
10343
+ ...c,
10344
+ file: {
10345
+ ...c.file.file_data && {
10346
+ file_data: render(c.file.file_data)
10347
+ },
10348
+ ...c.file.file_id && {
10349
+ file_id: render(c.file.file_id)
10350
+ },
10351
+ ...c.file.filename && {
10352
+ filename: render(c.file.filename)
10353
+ }
10354
+ }
10355
+ }
10356
+ ];
10357
+ default:
10358
+ const _exhaustiveCheck = c;
10359
+ return _exhaustiveCheck;
10360
+ }
10361
+ })
10362
+ } : {},
10363
+ ..."tool_calls" in message ? {
10364
+ tool_calls: isEmpty2(message.tool_calls) ? void 0 : message.tool_calls.map((t) => {
10365
+ return {
10366
+ type: t.type,
10367
+ id: render(t.id),
10368
+ function: {
10369
+ name: render(t.function.name),
10370
+ arguments: render(t.function.arguments)
10371
+ }
10372
+ };
10373
+ })
10374
+ } : {},
10375
+ ..."tool_call_id" in message ? {
10376
+ tool_call_id: render(message.tool_call_id)
10377
+ } : {}
10378
+ };
10379
+ }
10380
+ function deserializePlainStringAsJSON(s) {
10381
+ if (s.trim() === "") {
10382
+ return { value: null, error: void 0 };
10383
+ }
10384
+ try {
10385
+ return { value: JSON.parse(s), error: void 0 };
10386
+ } catch (e) {
10387
+ return { value: s, error: e };
10388
+ }
10389
+ }
10390
+ function renderTemplatedObject(obj, args, options) {
10391
+ if (typeof obj === "string") {
10392
+ return renderTemplateContent(
10393
+ obj,
10394
+ args,
10395
+ (value) => typeof value === "string" ? value : JSON.stringify(value),
10396
+ {
10397
+ strict: options.strict,
10398
+ templateFormat: options.templateFormat
10399
+ }
10400
+ );
10401
+ } else if (isArray(obj)) {
10402
+ return obj.map((item) => renderTemplatedObject(item, args, options));
10403
+ } else if (isObject(obj)) {
10404
+ return Object.fromEntries(
10405
+ Object.entries(obj).map(([key, value]) => [
10406
+ key,
10407
+ renderTemplatedObject(value, args, options)
10408
+ ])
10409
+ );
10410
+ }
10411
+ return obj;
10412
+ }
10413
+ function renderPromptParams(params, args, options = {}) {
10414
+ const templateFormat = parseTemplateFormat(options.templateFormat);
10415
+ const strict = !!options.strict;
10416
+ const schemaParsed = z8.object({
10417
+ response_format: z8.object({
10418
+ type: z8.literal("json_schema"),
10419
+ json_schema: ResponseFormatJsonSchema.omit({ schema: true }).extend({
10420
+ schema: z8.unknown()
10421
+ })
10422
+ })
10423
+ }).safeParse(params);
10424
+ if (schemaParsed.success) {
10425
+ const rawSchema = schemaParsed.data.response_format.json_schema.schema;
10426
+ const templatedSchema = renderTemplatedObject(rawSchema, args, {
10427
+ strict,
10428
+ templateFormat
10429
+ });
10430
+ const parsedSchema = typeof templatedSchema === "string" ? deserializePlainStringAsJSON(templatedSchema).value : templatedSchema;
10431
+ return {
10432
+ ...params,
10433
+ response_format: {
10434
+ ...schemaParsed.data.response_format,
10435
+ json_schema: {
10436
+ ...schemaParsed.data.response_format.json_schema,
10437
+ schema: parsedSchema
10438
+ }
10439
+ }
10440
+ };
10441
+ }
10442
+ return params;
10443
+ }
10444
+ var Prompt2 = class _Prompt {
10445
+ constructor(metadata, defaults, noTrace) {
10446
+ this.metadata = metadata;
10447
+ this.defaults = defaults;
10448
+ this.noTrace = noTrace;
10449
+ void this.__braintrust_prompt_marker;
10450
+ }
10451
+ metadata;
10452
+ defaults;
10453
+ noTrace;
10454
+ parsedPromptData;
10455
+ hasParsedPromptData = false;
10456
+ __braintrust_prompt_marker = true;
10457
+ get id() {
10458
+ return this.metadata.id;
10459
+ }
10460
+ get projectId() {
10461
+ return this.metadata.project_id;
10462
+ }
10463
+ get name() {
10464
+ return "name" in this.metadata ? this.metadata.name : `Playground function ${this.metadata.id}`;
10465
+ }
10466
+ get slug() {
10467
+ return "slug" in this.metadata ? this.metadata.slug : this.metadata.id;
10468
+ }
10469
+ get prompt() {
10470
+ return this.getParsedPromptData()?.prompt;
10471
+ }
10472
+ get version() {
10473
+ return this.metadata[TRANSACTION_ID_FIELD];
10474
+ }
10475
+ get options() {
10476
+ return this.getParsedPromptData()?.options || {};
10477
+ }
10478
+ get templateFormat() {
10479
+ return this.getParsedPromptData()?.template_format;
10480
+ }
10481
+ get promptData() {
10482
+ return this.getParsedPromptData();
10483
+ }
10484
+ /**
10485
+ * Build the prompt with the given formatting options. The args you pass in will
10486
+ * be forwarded to the mustache template that defines the prompt and rendered with
10487
+ * the `mustache-js` library.
10488
+ *
10489
+ * @param buildArgs Args to forward along to the prompt template.
10490
+ */
10491
+ build(buildArgs, options = {}) {
10492
+ return this.runBuild(buildArgs, {
10493
+ flavor: options.flavor ?? "chat",
10494
+ messages: options.messages,
10495
+ strict: options.strict,
10496
+ templateFormat: options.templateFormat
10497
+ });
10498
+ }
10499
+ /**
10500
+ * This is a special build method that first resolves attachment references, and then
10501
+ * calls the regular build method. You should use this if you are building prompts from
10502
+ * dataset rows that contain attachments.
10503
+ *
10504
+ * @param buildArgs Args to forward along to the prompt template.
10505
+ */
10506
+ async buildWithAttachments(buildArgs, options = {}) {
10507
+ const hydrated = buildArgs instanceof Object ? await resolveAttachmentsToBase64(buildArgs, options.state) : buildArgs;
10508
+ return this.runBuild(hydrated, {
10509
+ flavor: options.flavor ?? "chat",
10510
+ messages: options.messages,
10511
+ strict: options.strict,
10512
+ templateFormat: options.templateFormat
10513
+ });
10514
+ }
10515
+ runBuild(buildArgs, options) {
10516
+ const { flavor } = options;
10517
+ const params = Object.fromEntries(
10518
+ Object.entries({
10519
+ ...this.defaults,
10520
+ ...Object.fromEntries(
10521
+ Object.entries(this.options.params || {}).filter(
10522
+ ([k, _v]) => !BRAINTRUST_PARAMS.includes(k)
10523
+ )
10524
+ ),
10525
+ ...!isEmpty2(this.options.model) ? {
10526
+ model: this.options.model
10527
+ } : {}
10528
+ }).filter(([key, value]) => key !== "response_format" || value !== null)
10529
+ );
10530
+ if (!("model" in params) || isEmpty2(params.model)) {
10531
+ throw new Error(
10532
+ "No model specified. Either specify it in the prompt or as a default"
10533
+ );
10534
+ }
10535
+ const spanInfo = this.noTrace ? {} : {
10536
+ span_info: {
10537
+ metadata: {
10538
+ prompt: this.id ? {
10539
+ variables: buildArgs,
10540
+ id: this.id,
10541
+ project_id: this.projectId,
10542
+ version: this.version,
10543
+ ..."prompt_session_id" in this.metadata ? { prompt_session_id: this.metadata.prompt_session_id } : {}
10544
+ } : void 0
10545
+ }
10546
+ }
10547
+ };
10548
+ const prompt = this.prompt;
10549
+ if (!prompt) {
10550
+ throw new Error("Empty prompt");
10551
+ }
10552
+ const dictArgParsed = z8.record(z8.unknown()).safeParse(buildArgs);
10553
+ const variables = {
10554
+ input: buildArgs,
10555
+ ...dictArgParsed.success ? dictArgParsed.data : {}
10556
+ };
10557
+ const promptDataTemplateFormat = this.templateFormat;
10558
+ const resolvedTemplateFormat = parseTemplateFormat(
10559
+ options.templateFormat ?? promptDataTemplateFormat
10560
+ );
10561
+ const renderedPrompt = _Prompt.renderPrompt({
10562
+ prompt,
10563
+ buildArgs,
10564
+ options: { ...options, templateFormat: resolvedTemplateFormat }
10565
+ });
10566
+ if (flavor === "chat") {
10567
+ if (renderedPrompt.type !== "chat") {
10568
+ throw new Error(
10569
+ "Prompt is a completion prompt. Use buildCompletion() instead"
10570
+ );
10571
+ }
10572
+ return {
10573
+ ...renderPromptParams(params, variables, {
10574
+ strict: options.strict,
10575
+ templateFormat: resolvedTemplateFormat
10576
+ }),
10577
+ ...spanInfo,
10578
+ messages: renderedPrompt.messages,
10579
+ ...renderedPrompt.tools ? {
10580
+ tools: ChatCompletionTool.array().parse(JSON.parse(renderedPrompt.tools))
10581
+ } : void 0
10582
+ };
10583
+ } else if (flavor === "completion") {
10584
+ if (renderedPrompt.type !== "completion") {
10585
+ throw new Error(`Prompt is a chat prompt. Use flavor: 'chat' instead`);
10586
+ }
10587
+ return {
10588
+ ...renderPromptParams(params, variables, {
10589
+ strict: options.strict,
10590
+ templateFormat: resolvedTemplateFormat
10591
+ }),
10592
+ ...spanInfo,
10593
+ prompt: renderedPrompt.content
10594
+ };
10595
+ } else {
10596
+ throw new Error("never!");
10597
+ }
10598
+ }
10599
+ static renderPrompt({
10600
+ prompt,
10601
+ buildArgs,
10602
+ options
10603
+ }) {
10604
+ const escape = (v) => {
10605
+ if (v === void 0) {
10606
+ throw new Error("Missing!");
10607
+ } else if (typeof v === "string") {
10608
+ return v;
10609
+ } else if (v instanceof ReadonlyAttachment) {
10610
+ throw new Error(
10611
+ "Use buildWithAttachments() to build prompts with attachments"
10612
+ );
10613
+ } else {
10614
+ return JSON.stringify(v);
10615
+ }
10616
+ };
10617
+ const dictArgParsed = z8.record(z8.unknown()).safeParse(buildArgs);
10618
+ const variables = {
10619
+ input: buildArgs,
10620
+ ...dictArgParsed.success ? dictArgParsed.data : {}
10621
+ };
10622
+ const templateFormat = parseTemplateFormat(options.templateFormat);
10623
+ if (prompt.type === "chat") {
10624
+ const render = (template) => renderTemplateContent(template, variables, escape, {
10625
+ strict: options.strict,
10626
+ templateFormat
10627
+ });
10628
+ const baseMessages = (prompt.messages || []).map(
10629
+ (m) => renderMessageImpl(render, m, variables)
10630
+ );
10631
+ const hasSystemPrompt = baseMessages.some((m) => m.role === "system");
10632
+ const messages = [
10633
+ ...baseMessages,
10634
+ ...(options.messages ?? []).filter(
10635
+ (m) => !(hasSystemPrompt && m.role === "system")
10636
+ )
10637
+ ];
10638
+ return {
10639
+ type: "chat",
10640
+ messages,
10641
+ ...prompt.tools?.trim() ? {
10642
+ tools: render(prompt.tools)
10643
+ } : void 0
10644
+ };
10645
+ } else if (prompt.type === "completion") {
10646
+ if (options.messages) {
10647
+ throw new Error(
10648
+ "extra messages are not supported for completion prompts"
10649
+ );
10650
+ }
10651
+ const content = renderTemplateContent(prompt.content, variables, escape, {
10652
+ strict: options.strict,
10653
+ templateFormat
10654
+ });
10655
+ return {
10656
+ type: "completion",
10657
+ content
10658
+ };
10659
+ } else {
10660
+ const _ = prompt;
10661
+ throw new Error(`Invalid prompt type: ${_}`);
10662
+ }
10663
+ }
10664
+ getParsedPromptData() {
10665
+ if (!this.hasParsedPromptData) {
10666
+ this.parsedPromptData = PromptData.parse(this.metadata.prompt_data);
10667
+ this.hasParsedPromptData = true;
10668
+ }
10669
+ return this.parsedPromptData;
10670
+ }
10671
+ static isPrompt(data) {
10672
+ return typeof data === "object" && data !== null && "__braintrust_prompt_marker" in data;
10673
+ }
10674
+ /** @internal */
10675
+ _internalSerializeForCache() {
10676
+ return {
10677
+ metadata: this.metadata,
10678
+ defaults: this.defaults,
10679
+ noTrace: this.noTrace
10680
+ };
10681
+ }
10682
+ static fromPromptData(name, promptData) {
10683
+ return new _Prompt(
10684
+ {
10685
+ name,
10686
+ slug: name,
10687
+ prompt_data: promptData
10688
+ },
10689
+ {},
10690
+ false
10691
+ );
10692
+ }
10693
+ };
10694
+ var RemoteEvalParameters = class {
10695
+ constructor(metadata) {
10696
+ this.metadata = metadata;
10697
+ void this.__braintrust_parameters_marker;
10698
+ }
10699
+ metadata;
10700
+ __braintrust_parameters_marker = true;
10701
+ get id() {
10702
+ return this.metadata.id;
10703
+ }
10704
+ get projectId() {
10705
+ return this.metadata.project_id;
10706
+ }
10707
+ get name() {
10708
+ return this.metadata.name;
10709
+ }
10710
+ get slug() {
10711
+ return this.metadata.slug;
10712
+ }
10713
+ get version() {
10714
+ return this.metadata[TRANSACTION_ID_FIELD];
10715
+ }
10716
+ get schema() {
10717
+ return this.metadata.function_data.__schema;
10718
+ }
10719
+ get data() {
10720
+ return this.metadata.function_data.data ?? {};
10721
+ }
10722
+ /** @internal */
10723
+ _internalSerializeForCache() {
10724
+ return { metadata: this.metadata };
10725
+ }
10726
+ validate(data) {
10727
+ if (typeof data !== "object" || data === null) {
10728
+ return false;
10729
+ }
10730
+ const schemaProps = this.schema.properties;
10731
+ if (typeof schemaProps !== "object" || schemaProps === null) {
10732
+ return true;
10733
+ }
10734
+ for (const key of Object.keys(schemaProps)) {
10735
+ if (!(key in data)) {
10736
+ const required = Array.isArray(this.schema.required) ? this.schema.required : [];
10737
+ if (required.includes(key)) {
10738
+ return false;
10739
+ }
10740
+ }
10741
+ }
10742
+ return true;
10743
+ }
10744
+ static isParameters(x) {
10745
+ return typeof x === "object" && x !== null && "__braintrust_parameters_marker" in x && x.__braintrust_parameters_marker === true;
10746
+ }
10747
+ };
9833
10748
  var TEST_API_KEY = "___TEST_API_KEY__THIS_IS_NOT_REAL___";
9834
10749
 
9835
10750
  // src/instrumentation/core/channel-tracing-utils.ts
@@ -10275,56 +11190,14 @@ function suppressionStore() {
10275
11190
  autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
10276
11191
  return autoInstrumentationSuppressionStore;
10277
11192
  }
10278
- function currentFrames() {
10279
- return suppressionStore().getStore()?.frames ?? [];
10280
- }
10281
11193
  function isAutoInstrumentationSuppressed() {
10282
- const frames = currentFrames();
10283
- return frames[frames.length - 1]?.mode === "suppress";
11194
+ return suppressionStore().getStore() === true;
10284
11195
  }
10285
11196
  function runWithAutoInstrumentationSuppressed(callback) {
10286
- const frame = {
10287
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
10288
- mode: "suppress"
10289
- };
10290
- return suppressionStore().run(
10291
- { frames: [...currentFrames(), frame] },
10292
- callback
10293
- );
11197
+ return suppressionStore().run(true, callback);
10294
11198
  }
10295
- function bindAutoInstrumentationSuppressionToStart(tracingChannel) {
10296
- const startChannel = tracingChannel.start;
10297
- if (!startChannel) {
10298
- return void 0;
10299
- }
10300
- const store = suppressionStore();
10301
- startChannel.bindStore(store, () => ({
10302
- frames: [
10303
- ...currentFrames(),
10304
- {
10305
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
10306
- mode: "suppress"
10307
- }
10308
- ]
10309
- }));
10310
- return () => {
10311
- startChannel.unbindStore(store);
10312
- };
10313
- }
10314
- function enterAutoInstrumentationAllowed() {
10315
- const frame = {
10316
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
10317
- mode: "allow"
10318
- };
10319
- suppressionStore().enterWith({
10320
- frames: [...currentFrames(), frame]
10321
- });
10322
- return () => {
10323
- const frames = currentFrames().filter(
10324
- (candidate) => candidate.id !== frame.id
10325
- );
10326
- suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
10327
- };
11199
+ function runWithAutoInstrumentationAllowed(callback) {
11200
+ return suppressionStore().run(void 0, callback);
10328
11201
  }
10329
11202
 
10330
11203
  // src/instrumentation/core/channel-tracing.ts
@@ -11015,6 +11888,22 @@ function processInputAttachments(input) {
11015
11888
  };
11016
11889
  }
11017
11890
  }
11891
+ const voyageBase64Key = node.type === "image_base64" ? Object.hasOwn(node, "imageBase64") ? "imageBase64" : "image_base64" : node.type === "video_base64" ? Object.hasOwn(node, "videoBase64") ? "videoBase64" : "video_base64" : void 0;
11892
+ const voyageBase64Value = voyageBase64Key ? node[voyageBase64Key] : void 0;
11893
+ if (voyageBase64Key && typeof voyageBase64Value === "string" && voyageBase64Value.startsWith("data:")) {
11894
+ const mediaType = inferMediaTypeFromDataUrl(
11895
+ voyageBase64Value,
11896
+ node.type === "video_base64" ? "video/mp4" : "image/png"
11897
+ );
11898
+ const filename = `${node.type === "video_base64" ? "video" : "image"}.${getExtensionFromMediaType(mediaType)}`;
11899
+ const attachment = toAttachment(voyageBase64Value, mediaType, filename);
11900
+ if (attachment) {
11901
+ return {
11902
+ ...node,
11903
+ [voyageBase64Key]: attachment
11904
+ };
11905
+ }
11906
+ }
11018
11907
  if (node.type === "file" && node.file && typeof node.file === "object" && typeof node.file.file_data === "string" && node.file.file_data.startsWith("data:")) {
11019
11908
  const mediaType = inferMediaTypeFromDataUrl(
11020
11909
  node.file.file_data,
@@ -11597,13 +12486,33 @@ function aggregateChatLogprobs(existing, incoming) {
11597
12486
  }
11598
12487
  return aggregated;
11599
12488
  }
12489
+ function createAggregatedChatChoice(index) {
12490
+ return {
12491
+ index,
12492
+ role: void 0,
12493
+ content: void 0,
12494
+ refusal: void 0,
12495
+ toolCallsByIndex: /* @__PURE__ */ new Map(),
12496
+ logprobs: void 0,
12497
+ finish_reason: void 0
12498
+ };
12499
+ }
12500
+ function toChatChoice(choice) {
12501
+ const toolCalls = Array.from(choice.toolCallsByIndex.entries()).sort(([left], [right]) => left - right).map(([, toolCall]) => toolCall);
12502
+ return {
12503
+ index: choice.index,
12504
+ message: {
12505
+ role: choice.role,
12506
+ content: choice.content,
12507
+ ...choice.refusal !== void 0 ? { refusal: choice.refusal } : {},
12508
+ tool_calls: toolCalls.length > 0 ? toolCalls : void 0
12509
+ },
12510
+ logprobs: choice.logprobs ?? null,
12511
+ finish_reason: choice.finish_reason
12512
+ };
12513
+ }
11600
12514
  function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
11601
- let role = void 0;
11602
- let content = void 0;
11603
- let refusal = void 0;
11604
- let tool_calls = void 0;
11605
- let logprobs = void 0;
11606
- let finish_reason = void 0;
12515
+ const choicesByIndex = /* @__PURE__ */ new Map();
11607
12516
  let metrics = {};
11608
12517
  for (const chunk of chunks) {
11609
12518
  if (chunk.usage) {
@@ -11612,62 +12521,75 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
11612
12521
  ...parseMetricsFromUsage(chunk.usage)
11613
12522
  };
11614
12523
  }
11615
- const choice = chunk.choices?.[0];
11616
- if (!choice) {
11617
- continue;
11618
- }
11619
- if (choice.finish_reason) {
11620
- finish_reason = choice.finish_reason;
11621
- }
11622
- logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
11623
- const delta = choice.delta;
11624
- if (!delta) {
12524
+ const choices = chunk.choices;
12525
+ if (!choices?.length) {
11625
12526
  continue;
11626
12527
  }
11627
- if (delta.finish_reason) {
11628
- finish_reason = delta.finish_reason;
11629
- }
11630
- if (!role && delta.role) {
11631
- role = delta.role;
11632
- }
11633
- if (delta.content) {
11634
- content = (content || "") + delta.content;
11635
- }
11636
- if (delta.refusal) {
11637
- refusal = (refusal || "") + delta.refusal;
11638
- }
11639
- if (delta.tool_calls) {
11640
- const toolDelta = delta.tool_calls[0];
11641
- if (!tool_calls || toolDelta.id && tool_calls[tool_calls.length - 1].id !== toolDelta.id) {
11642
- tool_calls = [
11643
- ...tool_calls || [],
11644
- {
11645
- id: toolDelta.id,
11646
- type: toolDelta.type,
11647
- function: toolDelta.function
12528
+ for (const choice of choices) {
12529
+ const choiceIndex = choice.index;
12530
+ let aggregatedChoice = choicesByIndex.get(choiceIndex);
12531
+ if (!aggregatedChoice) {
12532
+ aggregatedChoice = createAggregatedChatChoice(choiceIndex);
12533
+ choicesByIndex.set(choiceIndex, aggregatedChoice);
12534
+ }
12535
+ if (choice.finish_reason) {
12536
+ aggregatedChoice.finish_reason = choice.finish_reason;
12537
+ }
12538
+ aggregatedChoice.logprobs = aggregateChatLogprobs(
12539
+ aggregatedChoice.logprobs,
12540
+ choice.logprobs
12541
+ );
12542
+ const delta = choice.delta;
12543
+ if (!delta) {
12544
+ continue;
12545
+ }
12546
+ if (delta.finish_reason) {
12547
+ aggregatedChoice.finish_reason = delta.finish_reason;
12548
+ }
12549
+ if (!aggregatedChoice.role && delta.role) {
12550
+ aggregatedChoice.role = delta.role;
12551
+ }
12552
+ if (delta.content) {
12553
+ aggregatedChoice.content = (aggregatedChoice.content || "") + delta.content;
12554
+ }
12555
+ if (delta.refusal) {
12556
+ aggregatedChoice.refusal = (aggregatedChoice.refusal || "") + delta.refusal;
12557
+ }
12558
+ if (delta.tool_calls) {
12559
+ for (const toolDelta of delta.tool_calls) {
12560
+ let aggregatedToolCall = aggregatedChoice.toolCallsByIndex.get(
12561
+ toolDelta.index
12562
+ );
12563
+ if (!aggregatedToolCall) {
12564
+ aggregatedToolCall = {
12565
+ function: { arguments: "" }
12566
+ };
12567
+ aggregatedChoice.toolCallsByIndex.set(
12568
+ toolDelta.index,
12569
+ aggregatedToolCall
12570
+ );
11648
12571
  }
11649
- ];
11650
- } else {
11651
- tool_calls[tool_calls.length - 1].function.arguments += toolDelta.function.arguments;
12572
+ if (toolDelta.id !== void 0) {
12573
+ aggregatedToolCall.id = toolDelta.id;
12574
+ }
12575
+ if (toolDelta.type !== void 0) {
12576
+ aggregatedToolCall.type = toolDelta.type;
12577
+ }
12578
+ if (toolDelta.function?.name !== void 0) {
12579
+ aggregatedToolCall.function.name = toolDelta.function.name;
12580
+ }
12581
+ if (toolDelta.function?.arguments !== void 0) {
12582
+ aggregatedToolCall.function.arguments += toolDelta.function.arguments;
12583
+ }
12584
+ }
11652
12585
  }
11653
12586
  }
11654
12587
  }
11655
12588
  metrics = withCachedMetric(metrics, streamResult, endEvent);
12589
+ const output = Array.from(choicesByIndex.values()).sort((left, right) => left.index - right.index).map(toChatChoice);
11656
12590
  return {
11657
12591
  metrics,
11658
- output: [
11659
- {
11660
- index: 0,
11661
- message: {
11662
- role,
11663
- content,
11664
- ...refusal !== void 0 ? { refusal } : {},
11665
- tool_calls
11666
- },
11667
- logprobs: logprobs ?? null,
11668
- finish_reason
11669
- }
11670
- ]
12592
+ output: output.length > 0 ? output : [toChatChoice(createAggregatedChatChoice(0))]
11671
12593
  };
11672
12594
  }
11673
12595
  function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
@@ -12362,12 +13284,30 @@ function logInstrumentationError(context, error) {
12362
13284
 
12363
13285
  // src/wrappers/anthropic-tokens-util.ts
12364
13286
  function finalizeAnthropicTokens(metrics) {
12365
- const prompt_tokens = (metrics.prompt_tokens || 0) + (metrics.prompt_cached_tokens || 0) + (metrics.prompt_cache_creation_tokens || 0);
12366
- return {
13287
+ const hasSplitCacheCreationTokens = metrics.prompt_cache_creation_5m_tokens !== void 0 || metrics.prompt_cache_creation_1h_tokens !== void 0;
13288
+ const splitCacheCreationTokens = (metrics.prompt_cache_creation_5m_tokens || 0) + (metrics.prompt_cache_creation_1h_tokens || 0);
13289
+ const aggregateCacheCreationTokens = metrics.prompt_cache_creation_tokens || 0;
13290
+ const effectiveCacheCreationTokens = Math.max(
13291
+ aggregateCacheCreationTokens,
13292
+ splitCacheCreationTokens
13293
+ );
13294
+ const prompt_tokens = (metrics.prompt_tokens || 0) + (metrics.prompt_cached_tokens || 0) + effectiveCacheCreationTokens;
13295
+ const finalized = {
12367
13296
  ...metrics,
12368
13297
  prompt_tokens,
12369
13298
  tokens: prompt_tokens + (metrics.completion_tokens || 0)
12370
13299
  };
13300
+ if (hasSplitCacheCreationTokens && splitCacheCreationTokens >= aggregateCacheCreationTokens) {
13301
+ delete finalized.prompt_cache_creation_tokens;
13302
+ }
13303
+ return finalized;
13304
+ }
13305
+ function toNumericMetrics(metrics) {
13306
+ return Object.fromEntries(
13307
+ Object.entries(metrics).filter(
13308
+ (entry) => entry[1] !== void 0
13309
+ )
13310
+ );
12371
13311
  }
12372
13312
  function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens = 0) {
12373
13313
  const cacheTokens = {};
@@ -12960,6 +13900,24 @@ function parseMetricsFromUsage2(usage) {
12960
13900
  saveIfExistsTo("output_tokens", "completion_tokens");
12961
13901
  saveIfExistsTo("cache_read_input_tokens", "prompt_cached_tokens");
12962
13902
  saveIfExistsTo("cache_creation_input_tokens", "prompt_cache_creation_tokens");
13903
+ if (isObject(usage.cache_creation)) {
13904
+ const cacheCreation = usage.cache_creation;
13905
+ for (const [source, target] of [
13906
+ ["ephemeral_5m_input_tokens", "prompt_cache_creation_5m_tokens"],
13907
+ ["ephemeral_1h_input_tokens", "prompt_cache_creation_1h_tokens"]
13908
+ ]) {
13909
+ const value = cacheCreation[source];
13910
+ if (typeof value === "number") {
13911
+ metrics[target] = value;
13912
+ }
13913
+ }
13914
+ }
13915
+ if (isObject(usage.output_tokens_details)) {
13916
+ const thinkingTokens = usage.output_tokens_details.thinking_tokens;
13917
+ if (typeof thinkingTokens === "number") {
13918
+ metrics.completion_reasoning_tokens = thinkingTokens;
13919
+ }
13920
+ }
12963
13921
  if (isObject(usage.server_tool_use)) {
12964
13922
  for (const [name, value] of Object.entries(usage.server_tool_use)) {
12965
13923
  if (typeof value === "number") {
@@ -13916,7 +14874,6 @@ function endHarnessTurn(parent) {
13916
14874
  function braintrustAISDKTelemetry() {
13917
14875
  const operations = /* @__PURE__ */ new Map();
13918
14876
  const operationKeysByCallId = /* @__PURE__ */ new Map();
13919
- const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
13920
14877
  const modelSpans = /* @__PURE__ */ new Map();
13921
14878
  const objectSpans = /* @__PURE__ */ new Map();
13922
14879
  const embedSpans = /* @__PURE__ */ new Map();
@@ -13959,9 +14916,6 @@ function braintrustAISDKTelemetry() {
13959
14916
  return;
13960
14917
  }
13961
14918
  operations.delete(operationKey);
13962
- if (workflowOperationKeyStore.getStore() === operationKey) {
13963
- workflowOperationKeyStore.enterWith(void 0);
13964
- }
13965
14919
  const keys = operationKeysByCallId.get(state.callId);
13966
14920
  if (!keys) {
13967
14921
  return;
@@ -14009,14 +14963,7 @@ function braintrustAISDKTelemetry() {
14009
14963
  return key;
14010
14964
  }
14011
14965
  }
14012
- const workflowOperationKey = workflowOperationKeyStore.getStore();
14013
- if (workflowOperationKey && keys.includes(workflowOperationKey)) {
14014
- return workflowOperationKey;
14015
- }
14016
- if (callId === "workflow-agent") {
14017
- return void 0;
14018
- }
14019
- return mode === "finish" ? keys[0] : keys[keys.length - 1];
14966
+ return callId === "workflow-agent" || mode === "active" ? keys[keys.length - 1] : keys[0];
14020
14967
  };
14021
14968
  const operationKeyFromEvent = (event, mode = "active") => {
14022
14969
  const explicit = explicitOperationKey(event);
@@ -14030,17 +14977,13 @@ function braintrustAISDKTelemetry() {
14030
14977
  if (operationKey) {
14031
14978
  return operationKey;
14032
14979
  }
14033
- const workflowOperationKey2 = workflowOperationKeyStore.getStore();
14034
- if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
14035
- return workflowOperationKey2;
14980
+ const workflowAgentKeys2 = operationKeysByCallId.get("workflow-agent");
14981
+ if (workflowAgentKeys2?.length) {
14982
+ return workflowAgentKeys2[workflowAgentKeys2.length - 1];
14036
14983
  }
14037
14984
  return callId === "workflow-agent" ? void 0 : callId;
14038
14985
  }
14039
14986
  }
14040
- const workflowOperationKey = workflowOperationKeyStore.getStore();
14041
- if (workflowOperationKey && operations.has(workflowOperationKey)) {
14042
- return workflowOperationKey;
14043
- }
14044
14987
  const wrapperSpan = currentWorkflowAgentWrapperSpan();
14045
14988
  if (wrapperSpan?.spanId) {
14046
14989
  for (const [operationKey, state] of operations) {
@@ -14050,8 +14993,8 @@ function braintrustAISDKTelemetry() {
14050
14993
  }
14051
14994
  }
14052
14995
  const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
14053
- if (workflowAgentKeys?.length === 1) {
14054
- return workflowAgentKeys[0];
14996
+ if (workflowAgentKeys?.length) {
14997
+ return workflowAgentKeys[workflowAgentKeys.length - 1];
14055
14998
  }
14056
14999
  if (operations.size === 1) {
14057
15000
  return operations.keys().next().value;
@@ -14254,9 +15197,6 @@ function braintrustAISDKTelemetry() {
14254
15197
  if (!ownsSpan) {
14255
15198
  return;
14256
15199
  }
14257
- if (workflowAgent) {
14258
- workflowOperationKeyStore.enterWith(operationKey);
14259
- }
14260
15200
  let metadata = metadataFromEvent(event);
14261
15201
  const logPayload = { metadata };
14262
15202
  const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
@@ -14728,6 +15668,10 @@ var aiSDKChannels = defineChannels(
14728
15668
  channelName: "generateText",
14729
15669
  kind: "async"
14730
15670
  }),
15671
+ generateImage: channel({
15672
+ channelName: "generateImage",
15673
+ kind: "async"
15674
+ }),
14731
15675
  streamText: channel({
14732
15676
  channelName: "streamText",
14733
15677
  kind: "async"
@@ -14915,7 +15859,7 @@ var AISDKPlugin = class extends BasePlugin {
14915
15859
  }
14916
15860
  subscribeToAISDK() {
14917
15861
  const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
14918
- this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
15862
+ this.unsubscribers.push(interceptAISDKV7TelemetryDispatcher());
14919
15863
  this.unsubscribers.push(subscribeToHarnessAgentCreateSession());
14920
15864
  this.unsubscribers.push(
14921
15865
  subscribeToHarnessContinuation(
@@ -14943,6 +15887,18 @@ var AISDKPlugin = class extends BasePlugin {
14943
15887
  aggregateChunks: aggregateAISDKChunks
14944
15888
  })
14945
15889
  );
15890
+ this.unsubscribers.push(
15891
+ traceAsyncChannel(aiSDKChannels.generateImage, {
15892
+ name: "generateImage",
15893
+ type: "llm" /* LLM */,
15894
+ extractInput: ([params], event) => prepareAISDKGenerateImageInput(params, event.self),
15895
+ extractOutput: (result, endEvent) => processAISDKGenerateImageOutput(
15896
+ result,
15897
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
15898
+ ),
15899
+ extractMetrics: (result) => extractTokenMetrics(result)
15900
+ })
15901
+ );
14946
15902
  this.unsubscribers.push(
14947
15903
  traceStreamingChannel(aiSDKChannels.streamText, {
14948
15904
  name: "streamText",
@@ -15432,26 +16388,29 @@ function subscribeToHarnessContinuation(continuationChannel, defaultDenyOutputPa
15432
16388
  channel2.unsubscribe(handlers);
15433
16389
  };
15434
16390
  }
15435
- function subscribeToAISDKV7TelemetryDispatcher() {
15436
- const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
16391
+ function interceptAISDKV7TelemetryDispatcher() {
15437
16392
  const telemetry = braintrustAISDKTelemetry();
15438
- const handlers = {
15439
- end: (event) => {
15440
- const telemetryOptions = event.arguments?.[0]?.telemetry;
15441
- if (telemetryOptions?.isEnabled === false) {
15442
- return;
16393
+ return aiSDKChannels.v7CreateTelemetryDispatcher.intercept(
16394
+ (target, thisArg, args) => {
16395
+ const dispatcher = Reflect.apply(target, thisArg, args);
16396
+ const telemetryOptions = args[0]?.telemetry;
16397
+ if (telemetryOptions?.isEnabled !== false) {
16398
+ try {
16399
+ patchAISDKV7TelemetryDispatcher(
16400
+ dispatcher,
16401
+ telemetry,
16402
+ telemetryOptions
16403
+ );
16404
+ } catch (error) {
16405
+ debugLogger.error(
16406
+ "Error instrumenting AI SDK v7 telemetry dispatcher:",
16407
+ error
16408
+ );
16409
+ }
15443
16410
  }
15444
- patchAISDKV7TelemetryDispatcher(
15445
- event.result,
15446
- telemetry,
15447
- telemetryOptions
15448
- );
16411
+ return dispatcher;
15449
16412
  }
15450
- };
15451
- channel2.subscribe(handlers);
15452
- return () => {
15453
- channel2.unsubscribe(handlers);
15454
- };
16413
+ );
15455
16414
  }
15456
16415
  function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
15457
16416
  if (!isObject(dispatcher)) {
@@ -15776,16 +16735,10 @@ var convertImageToAttachment = (image, explicitMimeType) => {
15776
16735
  }
15777
16736
  }
15778
16737
  if (explicitMimeType) {
15779
- if (image instanceof Uint8Array) {
16738
+ const blob = convertDataToBlob(image, explicitMimeType);
16739
+ if (blob) {
15780
16740
  return new Attachment({
15781
- data: new Blob([image], { type: explicitMimeType }),
15782
- filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
15783
- contentType: explicitMimeType
15784
- });
15785
- }
15786
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
15787
- return new Attachment({
15788
- data: new Blob([image], { type: explicitMimeType }),
16741
+ data: blob,
15789
16742
  filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
15790
16743
  contentType: explicitMimeType
15791
16744
  });
@@ -15839,6 +16792,25 @@ var convertDataToAttachment = (data, mimeType, filename) => {
15839
16792
  function processAISDKCallInput(params) {
15840
16793
  return processInputAttachmentsSync(params);
15841
16794
  }
16795
+ function processAISDKGenerateImageInput(params) {
16796
+ const prompt = params.prompt;
16797
+ if (!isObject(prompt) || Array.isArray(prompt)) {
16798
+ return processAISDKCallInput(params);
16799
+ }
16800
+ const processedPrompt = { ...prompt };
16801
+ if (Array.isArray(prompt.images)) {
16802
+ processedPrompt.images = prompt.images.map(
16803
+ (image) => convertImageToAttachment(image, "image/png") ?? image
16804
+ );
16805
+ }
16806
+ if (prompt.mask !== void 0) {
16807
+ processedPrompt.mask = convertImageToAttachment(prompt.mask, "image/png") ?? prompt.mask;
16808
+ }
16809
+ return processAISDKCallInput({
16810
+ ...params,
16811
+ prompt: processedPrompt
16812
+ });
16813
+ }
15842
16814
  function processAISDKWorkflowAgentCallInput(params) {
15843
16815
  const processed = processAISDKCallInput(params);
15844
16816
  return {
@@ -15977,6 +16949,12 @@ function prepareAISDKEmbedInput(params, self) {
15977
16949
  metadata: extractMetadataFromEmbedParams(params, self)
15978
16950
  };
15979
16951
  }
16952
+ function prepareAISDKGenerateImageInput(params, self) {
16953
+ return {
16954
+ input: processAISDKGenerateImageInput(params).input,
16955
+ metadata: extractMetadataFromCallParams(params, self)
16956
+ };
16957
+ }
15980
16958
  function prepareAISDKRerankInput(params, self) {
15981
16959
  const { documents, query } = params;
15982
16960
  return {
@@ -17352,6 +18330,57 @@ function processAISDKOutput(output, denyOutputPaths) {
17352
18330
  }
17353
18331
  return normalizeAISDKLoggedOutput(sanitized);
17354
18332
  }
18333
+ function processAISDKGenerateImageOutput(output, denyOutputPaths) {
18334
+ if (!output || typeof output !== "object") {
18335
+ return output;
18336
+ }
18337
+ const summarized = {};
18338
+ for (const field of [
18339
+ "usage",
18340
+ "warnings",
18341
+ "providerMetadata",
18342
+ "experimental_providerMetadata",
18343
+ "responses"
18344
+ ]) {
18345
+ const value = safeSerializableFieldRead(output, field);
18346
+ if (value !== void 0 && isSerializableOutputValue(value)) {
18347
+ summarized[field] = value;
18348
+ }
18349
+ }
18350
+ const images = safeSerializableFieldRead(output, "images");
18351
+ const image = safeSerializableFieldRead(output, "image");
18352
+ const generatedFiles = Array.isArray(images) && images.length > 0 ? images : image !== void 0 ? [image] : [];
18353
+ const loggedOutput = normalizeAISDKLoggedOutput(
18354
+ omit(summarized, denyOutputPaths)
18355
+ );
18356
+ if (generatedFiles.length > 0) {
18357
+ loggedOutput.images = generatedFiles.map(
18358
+ (file, index) => convertAISDKGeneratedFileToAttachment(file, index)
18359
+ );
18360
+ }
18361
+ return loggedOutput;
18362
+ }
18363
+ function convertAISDKGeneratedFileToAttachment(file, index) {
18364
+ if (!file || typeof file !== "object") {
18365
+ return file;
18366
+ }
18367
+ const generatedFile = file;
18368
+ const generatedMediaType = safeSerializableFieldRead(
18369
+ generatedFile,
18370
+ "mediaType"
18371
+ );
18372
+ const mediaType = typeof generatedMediaType === "string" ? generatedMediaType : "application/octet-stream";
18373
+ const data = safeSerializableFieldRead(generatedFile, "base64") ?? safeSerializableFieldRead(generatedFile, "uint8Array");
18374
+ const blob = convertDataToBlob(data, mediaType);
18375
+ if (blob) {
18376
+ return new Attachment({
18377
+ data: blob,
18378
+ filename: `generated_image_${index}.${getExtensionFromMediaType(mediaType)}`,
18379
+ contentType: mediaType
18380
+ });
18381
+ }
18382
+ return file;
18383
+ }
17355
18384
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
17356
18385
  if (!output || typeof output !== "object") {
17357
18386
  return output;
@@ -17852,118 +18881,22 @@ var claudeAgentSDKChannels = defineChannels(
17852
18881
  var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
17853
18882
 
17854
18883
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
17855
- var LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED = /* @__PURE__ */ Symbol.for(
17856
- "braintrust.claude_agent_sdk.local_tool_context_async_iterator_patched"
17857
- );
17858
- function createLocalToolContextStore() {
17859
- const maybeIsoWithAsyncLocalStorage = isomorph_default;
17860
- if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
17861
- return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
17862
- }
17863
- let currentStore;
17864
- return {
17865
- enterWith(store) {
17866
- currentStore = store;
17867
- },
17868
- getStore() {
17869
- return currentStore;
17870
- },
17871
- run(store, callback) {
17872
- const previousStore = currentStore;
17873
- currentStore = store;
17874
- try {
17875
- return callback();
17876
- } finally {
17877
- currentStore = previousStore;
17878
- }
17879
- }
17880
- };
17881
- }
17882
- var localToolContextStore = createLocalToolContextStore();
17883
- var fallbackLocalToolParentResolver;
17884
- function createClaudeLocalToolContext() {
17885
- return {};
17886
- }
17887
- function runWithClaudeLocalToolContext(callback, context) {
17888
- return localToolContextStore.run(
17889
- context ?? createClaudeLocalToolContext(),
17890
- callback
17891
- );
17892
- }
17893
- function ensureClaudeLocalToolContext() {
17894
- const existing = localToolContextStore.getStore();
17895
- if (existing) {
17896
- return existing;
17897
- }
17898
- const created = {};
17899
- localToolContextStore.enterWith(created);
17900
- return created;
17901
- }
17902
- function setClaudeLocalToolParentResolver(resolver) {
17903
- fallbackLocalToolParentResolver = resolver;
17904
- const context = ensureClaudeLocalToolContext();
17905
- if (!context) {
17906
- return;
17907
- }
17908
- context.resolveLocalToolParent = resolver;
18884
+ var localToolContextStore = isomorph_default.newAsyncLocalStorage();
18885
+ var localToolParentResolversByToolUseId = /* @__PURE__ */ new Map();
18886
+ function runWithClaudeLocalToolContext(callback, resolver) {
18887
+ return localToolContextStore.run(resolver, callback);
17909
18888
  }
17910
- function getClaudeLocalToolParentResolver() {
17911
- return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
18889
+ function registerClaudeLocalToolParentResolver(toolUseId, resolver) {
18890
+ localToolParentResolversByToolUseId.set(toolUseId, resolver);
17912
18891
  }
17913
- function isAsyncIterable3(value) {
17914
- return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
17915
- }
17916
- function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
17917
- if (!isAsyncIterable3(result) || Object.isFrozen(result) || Object.isSealed(result)) {
17918
- return result;
17919
- }
17920
- const stream = result;
17921
- const originalAsyncIterator = stream[Symbol.asyncIterator];
17922
- if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
17923
- return result;
18892
+ function getClaudeLocalToolParentResolver(toolUseId) {
18893
+ const currentResolver = localToolContextStore.getStore();
18894
+ if (!toolUseId) {
18895
+ return currentResolver;
17924
18896
  }
17925
- const patchedAsyncIterator = function() {
17926
- return runWithClaudeLocalToolContext(() => {
17927
- const iterator = Reflect.apply(originalAsyncIterator, this, []);
17928
- if (!iterator || typeof iterator !== "object") {
17929
- return iterator;
17930
- }
17931
- const patchMethod = (methodName) => {
17932
- const originalMethod = Reflect.get(iterator, methodName);
17933
- if (typeof originalMethod !== "function") {
17934
- return;
17935
- }
17936
- Reflect.set(
17937
- iterator,
17938
- methodName,
17939
- (...args) => runWithClaudeLocalToolContext(
17940
- () => Reflect.apply(
17941
- originalMethod,
17942
- iterator,
17943
- args
17944
- ),
17945
- localToolContext
17946
- )
17947
- );
17948
- };
17949
- patchMethod("next");
17950
- patchMethod("return");
17951
- patchMethod("throw");
17952
- return iterator;
17953
- }, localToolContext);
17954
- };
17955
- Object.defineProperty(
17956
- patchedAsyncIterator,
17957
- LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
17958
- {
17959
- configurable: false,
17960
- enumerable: false,
17961
- value: true,
17962
- writable: false
17963
- }
17964
- );
17965
- Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
17966
- return result;
18897
+ const registeredResolver = localToolParentResolversByToolUseId.get(toolUseId);
18898
+ localToolParentResolversByToolUseId.delete(toolUseId);
18899
+ return currentResolver ?? registeredResolver;
17967
18900
  }
17968
18901
 
17969
18902
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
@@ -17989,7 +18922,7 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
17989
18922
  const metadata = getMetadata();
17990
18923
  const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
17991
18924
  const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
17992
- const localToolParentResolver = getClaudeLocalToolParentResolver();
18925
+ const localToolParentResolver = getClaudeLocalToolParentResolver(toolUseId);
17993
18926
  const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
17994
18927
  const runWithResolvedParent = async () => {
17995
18928
  const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
@@ -18258,37 +19191,97 @@ function seedTaskToolUseIdMapping(taskIdToToolUseId, message) {
18258
19191
  taskIdToToolUseId.set(message.task_id, message.tool_use_id);
18259
19192
  }
18260
19193
  }
18261
- function extractUsageFromMessage(message) {
18262
- const metrics = {};
18263
- let usage;
18264
- if (message.type === "assistant") {
18265
- usage = message.message?.usage;
18266
- } else if (message.type === "result") {
18267
- usage = message.usage;
18268
- }
19194
+ function tokenCount(value) {
19195
+ return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0 ? value : void 0;
19196
+ }
19197
+ function copyUsage(usage) {
18269
19198
  if (!usage || typeof usage !== "object") {
18270
- return metrics;
19199
+ return void 0;
19200
+ }
19201
+ const copy = {};
19202
+ for (const key of [
19203
+ "input_tokens",
19204
+ "output_tokens",
19205
+ "cache_read_input_tokens",
19206
+ "cache_creation_input_tokens"
19207
+ ]) {
19208
+ const value = tokenCount(Reflect.get(usage, key));
19209
+ if (value !== void 0) {
19210
+ copy[key] = value;
19211
+ }
19212
+ }
19213
+ const cacheCreation = Reflect.get(usage, "cache_creation");
19214
+ if (cacheCreation && typeof cacheCreation === "object") {
19215
+ const cacheCreationCopy = {};
19216
+ for (const key of [
19217
+ "ephemeral_5m_input_tokens",
19218
+ "ephemeral_1h_input_tokens"
19219
+ ]) {
19220
+ const value = tokenCount(Reflect.get(cacheCreation, key));
19221
+ if (value !== void 0) {
19222
+ cacheCreationCopy[key] = value;
19223
+ }
19224
+ }
19225
+ if (Object.keys(cacheCreationCopy).length > 0) {
19226
+ copy.cache_creation = cacheCreationCopy;
19227
+ }
19228
+ }
19229
+ return Object.keys(copy).length > 0 ? copy : void 0;
19230
+ }
19231
+ function mergeUsage(base, override) {
19232
+ if (!base || !override) {
19233
+ return override ?? base;
19234
+ }
19235
+ const cacheCreation = base.cache_creation || override.cache_creation ? { ...base.cache_creation, ...override.cache_creation } : void 0;
19236
+ return {
19237
+ ...base,
19238
+ ...override,
19239
+ ...cacheCreation && { cache_creation: cacheCreation }
19240
+ };
19241
+ }
19242
+ function extractUsage(usage, includeOutput) {
19243
+ const metrics = {};
19244
+ if (!usage) {
19245
+ return {};
18271
19246
  }
18272
19247
  const inputTokens = getNumberProperty(usage, "input_tokens");
18273
19248
  if (inputTokens !== void 0) {
18274
19249
  metrics.prompt_tokens = inputTokens;
18275
19250
  }
18276
- const outputTokens = getNumberProperty(usage, "output_tokens");
18277
- if (outputTokens !== void 0) {
18278
- metrics.completion_tokens = outputTokens;
19251
+ if (includeOutput) {
19252
+ const outputTokens = getNumberProperty(usage, "output_tokens");
19253
+ if (outputTokens !== void 0) {
19254
+ metrics.completion_tokens = outputTokens;
19255
+ }
18279
19256
  }
18280
19257
  const cacheReadTokens = getNumberProperty(usage, "cache_read_input_tokens") || 0;
18281
19258
  const cacheCreationTokens = getNumberProperty(usage, "cache_creation_input_tokens") || 0;
18282
- if (cacheReadTokens > 0 || cacheCreationTokens > 0) {
18283
- Object.assign(
18284
- metrics,
18285
- extractAnthropicCacheTokens(cacheReadTokens, cacheCreationTokens)
18286
- );
19259
+ Object.assign(
19260
+ metrics,
19261
+ extractAnthropicCacheTokens(cacheReadTokens, cacheCreationTokens)
19262
+ );
19263
+ const cacheCreation5mTokens = getNumberProperty(
19264
+ usage.cache_creation,
19265
+ "ephemeral_5m_input_tokens"
19266
+ );
19267
+ const cacheCreation1hTokens = getNumberProperty(
19268
+ usage.cache_creation,
19269
+ "ephemeral_1h_input_tokens"
19270
+ );
19271
+ if (cacheCreation5mTokens !== void 0) {
19272
+ metrics.prompt_cache_creation_5m_tokens = cacheCreation5mTokens;
18287
19273
  }
18288
- if (Object.keys(metrics).length > 0) {
18289
- Object.assign(metrics, finalizeAnthropicTokens(metrics));
19274
+ if (cacheCreation1hTokens !== void 0) {
19275
+ metrics.prompt_cache_creation_1h_tokens = cacheCreation1hTokens;
18290
19276
  }
18291
- return metrics;
19277
+ if (Object.keys(metrics).length === 0) {
19278
+ return {};
19279
+ }
19280
+ const finalized = finalizeAnthropicTokens(metrics);
19281
+ if (metrics.completion_tokens === void 0) {
19282
+ delete finalized.tokens;
19283
+ }
19284
+ return toNumericMetrics(finalized);
18292
19285
  }
18293
19286
  function buildLLMInput(promptMessages, conversationHistory) {
18294
19287
  const inputParts = [...promptMessages, ...conversationHistory];
@@ -18322,16 +19315,16 @@ function buildRootPromptMessages(prompt, capturedPromptMessages) {
18322
19315
  function formatCapturedMessages(messages) {
18323
19316
  return messages.length > 0 ? messages : [];
18324
19317
  }
18325
- async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
19318
+ async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, usage, hasFinalOutputUsage, existingSpan) {
18326
19319
  if (messages.length === 0) {
18327
19320
  return void 0;
18328
19321
  }
18329
19322
  const lastMessage = messages[messages.length - 1];
18330
- if (lastMessage.type !== "assistant" || !lastMessage.message?.usage) {
19323
+ if (lastMessage.type !== "assistant") {
18331
19324
  return void 0;
18332
19325
  }
18333
- const model = lastMessage.message.model || options.model;
18334
- const usage = extractUsageFromMessage(lastMessage);
19326
+ const model = lastMessage.message?.model || options.model;
19327
+ const metrics = options.includePartialMessages ? extractUsage(usage, hasFinalOutputUsage) : {};
18335
19328
  const input = buildLLMInput(promptMessages, conversationHistory);
18336
19329
  const outputs = messages.map(
18337
19330
  (m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
@@ -18353,8 +19346,8 @@ async function createLLMSpanForMessages(messages, promptMessages, conversationHi
18353
19346
  );
18354
19347
  span.log({
18355
19348
  input,
18356
- metadata: model ? { model } : void 0,
18357
- metrics: usage,
19349
+ metadata: { ...model && { model }, provider: "anthropic" },
19350
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
18358
19351
  output: outputs
18359
19352
  });
18360
19353
  const spanExport = await span.export();
@@ -18444,12 +19437,19 @@ function prepareLocalToolHandlersInMcpServers(mcpServers) {
18444
19437
  }
18445
19438
  return { hasLocalToolHandlers, localToolHookNames };
18446
19439
  }
18447
- function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
19440
+ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToParent, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
18448
19441
  const preToolUse = async (input, toolUseID) => {
18449
19442
  if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
18450
19443
  return {};
18451
19444
  }
19445
+ if (!toolUseToParent.has(toolUseID) && input.agent_id) {
19446
+ const parentToolUseId = taskIdToToolUseId.get(input.agent_id);
19447
+ if (parentToolUseId) {
19448
+ toolUseToParent.set(toolUseID, parentToolUseId);
19449
+ }
19450
+ }
18452
19451
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
19452
+ registerClaudeLocalToolParentResolver(toolUseID, resolveParentSpan);
18453
19453
  return {};
18454
19454
  }
18455
19455
  const parsed = parseToolName(input.tool_name);
@@ -18644,9 +19644,6 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
18644
19644
  }
18645
19645
  const metadata = {
18646
19646
  ...subAgentDetailsToMetadata(details),
18647
- ...input.agent_transcript_path && {
18648
- "claude_agent_sdk.agent_transcript_path": input.agent_transcript_path
18649
- },
18650
19647
  "claude_agent_sdk.stop_hook_active": input.stop_hook_active
18651
19648
  };
18652
19649
  try {
@@ -18668,7 +19665,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
18668
19665
  subagentStop
18669
19666
  };
18670
19667
  }
18671
- function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
19668
+ function injectTracingHooks(options, resolveParentSpan, taskIdToToolUseId, toolUseToParent, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
18672
19669
  const {
18673
19670
  preToolUse,
18674
19671
  postToolUse,
@@ -18677,6 +19674,8 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
18677
19674
  subagentStop
18678
19675
  } = createToolTracingHooks(
18679
19676
  resolveParentSpan,
19677
+ taskIdToToolUseId,
19678
+ toolUseToParent,
18680
19679
  activeToolSpans,
18681
19680
  options.mcpServers,
18682
19681
  localToolHookNames,
@@ -18758,6 +19757,13 @@ async function finalizeCurrentMessageGroup(state) {
18758
19757
  }
18759
19758
  }
18760
19759
  const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
19760
+ const lastMessage = state.currentMessages[state.currentMessages.length - 1];
19761
+ const messageId = lastMessage?.message?.id;
19762
+ const usage = state.options.includePartialMessages ? mergeUsage(
19763
+ copyUsage(lastMessage?.message?.usage),
19764
+ messageId ? state.usageByMessageId.get(messageId) : void 0
19765
+ ) : void 0;
19766
+ const hasFinalOutputUsage = messageId !== void 0 && state.finalOutputUsageMessageIds.has(messageId);
18761
19767
  const llmSpanResult = await createLLMSpanForMessages(
18762
19768
  state.currentMessages,
18763
19769
  promptMessages,
@@ -18765,6 +19771,8 @@ async function finalizeCurrentMessageGroup(state) {
18765
19771
  state.options,
18766
19772
  state.currentMessageStartTime,
18767
19773
  parentSpan,
19774
+ usage,
19775
+ hasFinalOutputUsage,
18768
19776
  existingLlmSpan
18769
19777
  );
18770
19778
  if (llmSpanResult) {
@@ -18782,9 +19790,17 @@ async function finalizeCurrentMessageGroup(state) {
18782
19790
  }
18783
19791
  }
18784
19792
  state.activeLlmSpansByParentToolUse.delete(parentKey);
18785
- const lastMessage = state.currentMessages[state.currentMessages.length - 1];
18786
- if (lastMessage?.message?.usage) {
18787
- state.accumulatedOutputTokens += getNumberProperty(lastMessage.message.usage, "output_tokens") || 0;
19793
+ if (messageId) {
19794
+ state.usageByMessageId.delete(messageId);
19795
+ state.finalOutputUsageMessageIds.delete(messageId);
19796
+ for (const [
19797
+ parent,
19798
+ activeMessageId
19799
+ ] of state.activePartialMessageIdByParentKey) {
19800
+ if (activeMessageId === messageId) {
19801
+ state.activePartialMessageIdByParentKey.delete(parent);
19802
+ }
19803
+ }
18788
19804
  }
18789
19805
  state.currentMessages.length = 0;
18790
19806
  }
@@ -18875,6 +19891,10 @@ async function ensureActiveLlmSpanForParentToolUse(rootSpan, activeLlmSpansByPar
18875
19891
  );
18876
19892
  llmParentSpan = await subAgentSpan.export();
18877
19893
  }
19894
+ const racedLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
19895
+ if (racedLlmSpan) {
19896
+ return racedLlmSpan;
19897
+ }
18878
19898
  const llmSpan = startSpan(
18879
19899
  withSpanInstrumentationName(
18880
19900
  {
@@ -18994,7 +20014,49 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
18994
20014
  }
18995
20015
  return true;
18996
20016
  }
20017
+ function handlePartialUsageMessage(state, message) {
20018
+ if (message.type !== "stream_event") {
20019
+ return false;
20020
+ }
20021
+ const event = message.event;
20022
+ if (!event || typeof event !== "object") {
20023
+ return true;
20024
+ }
20025
+ const parentKey = llmParentKey(message.parent_tool_use_id ?? null);
20026
+ if (event.type === "message_start") {
20027
+ const messageId2 = event.message?.id;
20028
+ const usage = copyUsage(event.message?.usage);
20029
+ if (messageId2) {
20030
+ state.activePartialMessageIdByParentKey.set(parentKey, messageId2);
20031
+ if (usage) {
20032
+ state.usageByMessageId.set(messageId2, usage);
20033
+ }
20034
+ }
20035
+ return true;
20036
+ }
20037
+ const messageId = state.activePartialMessageIdByParentKey.get(parentKey);
20038
+ if (!messageId) {
20039
+ return true;
20040
+ }
20041
+ if (event.type === "message_delta") {
20042
+ const update = copyUsage(event.usage);
20043
+ if (update) {
20044
+ const usage = state.usageByMessageId.get(messageId) ?? {};
20045
+ Object.assign(usage, update);
20046
+ state.usageByMessageId.set(messageId, usage);
20047
+ if (update.output_tokens !== void 0) {
20048
+ state.finalOutputUsageMessageIds.add(messageId);
20049
+ }
20050
+ }
20051
+ } else if (event.type === "message_stop") {
20052
+ state.activePartialMessageIdByParentKey.delete(parentKey);
20053
+ }
20054
+ return true;
20055
+ }
18997
20056
  async function handleStreamMessage(state, message) {
20057
+ if (handlePartialUsageMessage(state, message)) {
20058
+ return;
20059
+ }
18998
20060
  maybeTrackToolUseContext(state, message);
18999
20061
  if (await maybeHandleTaskLifecycleMessage(state, message)) {
19000
20062
  return;
@@ -19041,36 +20103,9 @@ async function handleStreamMessage(state, message) {
19041
20103
  );
19042
20104
  state.currentMessages.push(message);
19043
20105
  }
19044
- if (message.type !== "result" || !message.usage) {
20106
+ if (message.type !== "result") {
19045
20107
  return;
19046
20108
  }
19047
- const finalUsageMetrics = extractUsageFromMessage(message);
19048
- if (state.currentMessages.length > 0 && finalUsageMetrics.completion_tokens !== void 0) {
19049
- const lastMessage = state.currentMessages[state.currentMessages.length - 1];
19050
- if (lastMessage?.message?.usage) {
19051
- const adjustedTokens = finalUsageMetrics.completion_tokens - state.accumulatedOutputTokens;
19052
- if (adjustedTokens >= 0) {
19053
- lastMessage.message.usage.output_tokens = adjustedTokens;
19054
- }
19055
- const resultUsage = message.usage;
19056
- if (resultUsage && typeof resultUsage === "object") {
19057
- const cacheReadTokens = getNumberProperty(
19058
- resultUsage,
19059
- "cache_read_input_tokens"
19060
- );
19061
- if (cacheReadTokens !== void 0) {
19062
- lastMessage.message.usage.cache_read_input_tokens = cacheReadTokens;
19063
- }
19064
- const cacheCreationTokens = getNumberProperty(
19065
- resultUsage,
19066
- "cache_creation_input_tokens"
19067
- );
19068
- if (cacheCreationTokens !== void 0) {
19069
- lastMessage.message.usage.cache_creation_input_tokens = cacheCreationTokens;
19070
- }
19071
- }
19072
- }
19073
- }
19074
20109
  const metadata = {};
19075
20110
  if (message.num_turns !== void 0) {
19076
20111
  metadata.num_turns = message.num_turns;
@@ -19078,8 +20113,12 @@ async function handleStreamMessage(state, message) {
19078
20113
  if (message.session_id !== void 0) {
19079
20114
  metadata.session_id = message.session_id;
19080
20115
  }
19081
- if (Object.keys(metadata).length > 0) {
19082
- state.span.log({ metadata });
20116
+ const metrics = state.options.includePartialMessages ? {} : extractUsage(copyUsage(message.usage), true);
20117
+ if (Object.keys(metadata).length > 0 || Object.keys(metrics).length > 0) {
20118
+ state.span.log({
20119
+ ...Object.keys(metadata).length > 0 ? { metadata } : {},
20120
+ ...Object.keys(metrics).length > 0 ? { metrics } : {}
20121
+ });
19083
20122
  }
19084
20123
  }
19085
20124
  async function finalizeQuerySpan(state) {
@@ -19103,6 +20142,9 @@ async function finalizeQuerySpan(state) {
19103
20142
  llmSpan.end();
19104
20143
  }
19105
20144
  state.activeLlmSpansByParentToolUse.clear();
20145
+ state.activePartialMessageIdByParentKey.clear();
20146
+ state.finalOutputUsageMessageIds.clear();
20147
+ state.usageByMessageId.clear();
19106
20148
  for (const toolSpan of state.activeToolSpans.values()) {
19107
20149
  toolSpan.end();
19108
20150
  }
@@ -19118,7 +20160,7 @@ async function finalizeQuerySpan(state) {
19118
20160
  }
19119
20161
  var ClaudeAgentSDKPlugin = class extends BasePlugin {
19120
20162
  onEnable() {
19121
- this.subscribeToQuery();
20163
+ this.interceptQuery();
19122
20164
  }
19123
20165
  onDisable() {
19124
20166
  for (const unsubscribe of this.unsubscribers) {
@@ -19126,207 +20168,218 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
19126
20168
  }
19127
20169
  this.unsubscribers = [];
19128
20170
  }
19129
- subscribeToQuery() {
19130
- const channel2 = claudeAgentSDKChannels.query.tracingChannel();
19131
- const spans = /* @__PURE__ */ new WeakMap();
19132
- const handlers = {
19133
- start: (event) => {
19134
- const params = event.arguments[0] ?? {};
19135
- const originalPrompt = params.prompt;
19136
- const options = params.options ?? {};
19137
- const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
19138
- let promptStarted = false;
19139
- let capturedPromptMessages;
19140
- let resolvePromptDone;
19141
- const promptDone = new Promise((resolve) => {
19142
- resolvePromptDone = resolve;
19143
- });
19144
- if (promptIsAsyncIterable) {
19145
- capturedPromptMessages = [];
19146
- const promptStream = originalPrompt;
19147
- params.prompt = (async function* () {
19148
- promptStarted = true;
19149
- try {
19150
- for await (const message of promptStream) {
19151
- capturedPromptMessages.push(message);
19152
- yield message;
19153
- }
19154
- } finally {
19155
- resolvePromptDone?.();
20171
+ interceptQuery() {
20172
+ const startQuery = (params) => {
20173
+ const originalPrompt = params.prompt;
20174
+ const options = params.options ?? {};
20175
+ const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
20176
+ let promptStarted = false;
20177
+ let capturedPromptMessages;
20178
+ let resolvePromptDone;
20179
+ const promptDone = new Promise((resolve) => {
20180
+ resolvePromptDone = resolve;
20181
+ });
20182
+ if (promptIsAsyncIterable) {
20183
+ capturedPromptMessages = [];
20184
+ const promptStream = originalPrompt;
20185
+ params.prompt = (async function* () {
20186
+ promptStarted = true;
20187
+ try {
20188
+ for await (const message of promptStream) {
20189
+ capturedPromptMessages.push(message);
20190
+ yield message;
19156
20191
  }
19157
- })();
19158
- }
19159
- const span = startSpan(
19160
- withSpanInstrumentationName(
19161
- {
19162
- name: "Claude Agent",
19163
- spanAttributes: {
19164
- type: "task" /* TASK */
19165
- }
19166
- },
19167
- INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
19168
- )
19169
- );
19170
- const startTime = getCurrentUnixTimestamp();
19171
- try {
19172
- span.log({
19173
- input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
19174
- metadata: filterSerializableOptions(options)
19175
- });
19176
- } catch (error) {
19177
- console.error("Error extracting input for Claude Agent SDK:", error);
19178
- }
19179
- const activeToolSpans = /* @__PURE__ */ new Map();
19180
- const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
19181
- const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
19182
- const subAgentSpans = /* @__PURE__ */ new Map();
19183
- const endedSubAgentSpans = /* @__PURE__ */ new Set();
19184
- const toolUseToParent = /* @__PURE__ */ new Map();
19185
- const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
19186
- const latestRootLlmParentRef = {
19187
- value: void 0
19188
- };
19189
- const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
19190
- const taskIdToToolUseId = /* @__PURE__ */ new Map();
19191
- const promptMessagesByParentKey = /* @__PURE__ */ new Map();
19192
- const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
19193
- const localToolContext = createClaudeLocalToolContext();
19194
- const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
19195
- const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
19196
- const resolveToolUseParentSpan = async (toolUseID, context) => {
19197
- const trackedParentToolUseId = toolUseToParent.get(toolUseID);
19198
- const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
19199
- const parentKey = llmParentKey(parentToolUseId);
19200
- const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
19201
- const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
19202
- if (!activeLlmSpan && !latestLlmParent) {
19203
- await ensureActiveLlmSpanForParentToolUse(
19204
- span,
19205
- activeLlmSpansByParentToolUse,
19206
- subAgentDetailsByToolUseId,
19207
- activeToolSpans,
19208
- subAgentSpans,
19209
- parentToolUseId,
19210
- getCurrentUnixTimestamp()
19211
- );
19212
- }
19213
- if (parentToolUseId) {
19214
- const subAgentSpan = await ensureSubAgentSpan(
19215
- subAgentDetailsByToolUseId,
19216
- span,
19217
- activeToolSpans,
19218
- subAgentSpans,
19219
- parentToolUseId
19220
- );
19221
- return subAgentSpan.export();
20192
+ } finally {
20193
+ resolvePromptDone?.();
19222
20194
  }
19223
- return span.export();
19224
- };
19225
- localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
19226
- setClaudeLocalToolParentResolver(resolveToolUseParentSpan);
19227
- const optionsWithHooks = injectTracingHooks(
19228
- options,
19229
- resolveToolUseParentSpan,
19230
- activeToolSpans,
19231
- localToolHookNames,
19232
- skipLocalToolHooks,
19233
- subAgentDetailsByToolUseId,
19234
- subAgentSpans,
19235
- endedSubAgentSpans
19236
- );
19237
- params.options = optionsWithHooks;
19238
- event.arguments[0] = params;
19239
- spans.set(event, {
19240
- accumulatedOutputTokens: 0,
19241
- activeLlmSpansByParentToolUse,
19242
- activeToolSpans,
19243
- conversationHistoryByParentKey,
19244
- capturedPromptMessages,
19245
- currentMessageId: void 0,
19246
- currentMessageStartTime: startTime,
19247
- currentMessages: [],
19248
- endedSubAgentSpans,
19249
- finalResults: [],
19250
- options: optionsWithHooks,
19251
- originalPrompt,
19252
- processing: Promise.resolve(),
19253
- promptDone,
19254
- promptMessagesByParentKey,
19255
- promptStarted: () => promptStarted,
19256
- promptSourcePriorityByParentKey,
19257
- span,
19258
- subAgentDetailsByToolUseId,
19259
- subAgentSpans,
19260
- taskIdToToolUseId,
19261
- latestLlmParentBySubAgentToolUse,
19262
- latestRootLlmParentRef,
19263
- toolUseToParent,
19264
- localToolContext
20195
+ })();
20196
+ }
20197
+ const span = startSpan(
20198
+ withSpanInstrumentationName(
20199
+ {
20200
+ name: "Claude Agent",
20201
+ spanAttributes: {
20202
+ type: "task" /* TASK */
20203
+ }
20204
+ },
20205
+ INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
20206
+ )
20207
+ );
20208
+ const startTime = getCurrentUnixTimestamp();
20209
+ try {
20210
+ span.log({
20211
+ input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
20212
+ metadata: filterSerializableOptions(options)
19265
20213
  });
19266
- },
19267
- end: (event) => {
19268
- const state = spans.get(event);
19269
- if (!state) {
19270
- return;
19271
- }
19272
- const eventResult = bindClaudeLocalToolContextToAsyncIterable(
19273
- event.result,
19274
- state.localToolContext
19275
- );
19276
- if (eventResult === void 0) {
19277
- state.span.end();
19278
- spans.delete(event);
19279
- return;
19280
- }
19281
- if (isAsyncIterable(eventResult)) {
19282
- patchStreamIfNeeded(eventResult, {
19283
- onChunk: (message) => {
19284
- maybeTrackToolUseContext(state, message);
19285
- state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
19286
- console.error(
19287
- "Error processing Claude Agent SDK stream chunk:",
19288
- error
19289
- );
19290
- });
19291
- },
19292
- onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
19293
- spans.delete(event);
19294
- }),
19295
- onError: (error) => state.processing.then(() => {
19296
- state.span.log({
19297
- error: error.message
19298
- });
19299
- }).then(() => finalizeQuerySpan(state)).finally(() => {
19300
- spans.delete(event);
19301
- })
19302
- });
19303
- return;
19304
- }
19305
- try {
19306
- state.span.log({ output: eventResult });
19307
- } catch (error) {
19308
- console.error("Error extracting output for Claude Agent SDK:", error);
19309
- } finally {
19310
- state.span.end();
19311
- spans.delete(event);
20214
+ } catch (error) {
20215
+ console.error("Error extracting input for Claude Agent SDK:", error);
20216
+ }
20217
+ const activeToolSpans = /* @__PURE__ */ new Map();
20218
+ const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
20219
+ const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
20220
+ const subAgentSpans = /* @__PURE__ */ new Map();
20221
+ const endedSubAgentSpans = /* @__PURE__ */ new Set();
20222
+ const toolUseToParent = /* @__PURE__ */ new Map();
20223
+ const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
20224
+ const latestRootLlmParentRef = {
20225
+ value: void 0
20226
+ };
20227
+ const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
20228
+ const taskIdToToolUseId = /* @__PURE__ */ new Map();
20229
+ const promptMessagesByParentKey = /* @__PURE__ */ new Map();
20230
+ const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
20231
+ const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
20232
+ const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
20233
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
20234
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
20235
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
20236
+ const parentKey = llmParentKey(parentToolUseId);
20237
+ const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
20238
+ const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
20239
+ if (!activeLlmSpan && !latestLlmParent) {
20240
+ await ensureActiveLlmSpanForParentToolUse(
20241
+ span,
20242
+ activeLlmSpansByParentToolUse,
20243
+ subAgentDetailsByToolUseId,
20244
+ activeToolSpans,
20245
+ subAgentSpans,
20246
+ parentToolUseId,
20247
+ getCurrentUnixTimestamp()
20248
+ );
19312
20249
  }
19313
- },
19314
- error: (event) => {
19315
- const state = spans.get(event);
19316
- if (!state || !event.error) {
19317
- return;
20250
+ if (parentToolUseId) {
20251
+ const subAgentSpan = await ensureSubAgentSpan(
20252
+ subAgentDetailsByToolUseId,
20253
+ span,
20254
+ activeToolSpans,
20255
+ subAgentSpans,
20256
+ parentToolUseId
20257
+ );
20258
+ return subAgentSpan.export();
19318
20259
  }
19319
- state.span.log({
19320
- error: event.error.message
20260
+ return span.export();
20261
+ };
20262
+ const optionsWithHooks = injectTracingHooks(
20263
+ options,
20264
+ resolveToolUseParentSpan,
20265
+ taskIdToToolUseId,
20266
+ toolUseToParent,
20267
+ activeToolSpans,
20268
+ localToolHookNames,
20269
+ skipLocalToolHooks,
20270
+ subAgentDetailsByToolUseId,
20271
+ subAgentSpans,
20272
+ endedSubAgentSpans
20273
+ );
20274
+ params.options = optionsWithHooks;
20275
+ return {
20276
+ activeLlmSpansByParentToolUse,
20277
+ activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
20278
+ activeToolSpans,
20279
+ conversationHistoryByParentKey,
20280
+ capturedPromptMessages,
20281
+ currentMessageId: void 0,
20282
+ currentMessageStartTime: startTime,
20283
+ currentMessages: [],
20284
+ endedSubAgentSpans,
20285
+ finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
20286
+ finalResults: [],
20287
+ options: optionsWithHooks,
20288
+ originalPrompt,
20289
+ processing: Promise.resolve(),
20290
+ promptDone,
20291
+ promptMessagesByParentKey,
20292
+ promptStarted: () => promptStarted,
20293
+ promptSourcePriorityByParentKey,
20294
+ span,
20295
+ subAgentDetailsByToolUseId,
20296
+ subAgentSpans,
20297
+ taskIdToToolUseId,
20298
+ latestLlmParentBySubAgentToolUse,
20299
+ latestRootLlmParentRef,
20300
+ toolUseToParent,
20301
+ usageByMessageId: /* @__PURE__ */ new Map(),
20302
+ localToolParentResolver: resolveToolUseParentSpan
20303
+ };
20304
+ };
20305
+ const finishQuery = (state, result) => {
20306
+ if (isAsyncIterable(result)) {
20307
+ patchStreamIfNeeded(result, {
20308
+ aroundNext: (callback) => runWithClaudeLocalToolContext(
20309
+ callback,
20310
+ state.localToolParentResolver
20311
+ ),
20312
+ onChunk: (message) => {
20313
+ maybeTrackToolUseContext(state, message);
20314
+ state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
20315
+ console.error(
20316
+ "Error processing Claude Agent SDK stream chunk:",
20317
+ error
20318
+ );
20319
+ });
20320
+ },
20321
+ onComplete: () => state.processing.then(() => finalizeQuerySpan(state)),
20322
+ onError: (error) => state.processing.then(() => {
20323
+ state.span.log({ error: error.message });
20324
+ }).then(() => finalizeQuerySpan(state))
19321
20325
  });
20326
+ return;
20327
+ }
20328
+ try {
20329
+ state.span.log({ output: result });
20330
+ } catch (error) {
20331
+ console.error("Error extracting output for Claude Agent SDK:", error);
20332
+ } finally {
19322
20333
  state.span.end();
19323
- spans.delete(event);
19324
20334
  }
19325
20335
  };
19326
- channel2.subscribe(handlers);
19327
- this.unsubscribers.push(() => {
19328
- channel2.unsubscribe(handlers);
19329
- });
20336
+ this.unsubscribers.push(
20337
+ claudeAgentSDKChannels.query.intercept((target, thisArg, args) => {
20338
+ let state;
20339
+ try {
20340
+ args[0] ??= {};
20341
+ state = startQuery(args[0]);
20342
+ } catch (error) {
20343
+ debugLogger.error(
20344
+ "Error starting Claude Agent SDK instrumentation:",
20345
+ error
20346
+ );
20347
+ }
20348
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
20349
+ try {
20350
+ const result = state ? runWithClaudeLocalToolContext(
20351
+ invokeTarget,
20352
+ state.localToolParentResolver
20353
+ ) : invokeTarget();
20354
+ if (state) {
20355
+ try {
20356
+ finishQuery(state, result);
20357
+ } catch (error) {
20358
+ debugLogger.error(
20359
+ "Error finalizing Claude Agent SDK instrumentation:",
20360
+ error
20361
+ );
20362
+ }
20363
+ }
20364
+ return result;
20365
+ } catch (error) {
20366
+ if (state) {
20367
+ try {
20368
+ state.span.log({
20369
+ error: error instanceof Error ? error.message : String(error)
20370
+ });
20371
+ state.span.end();
20372
+ } catch (instrumentationError) {
20373
+ debugLogger.error(
20374
+ "Error handling Claude Agent SDK instrumentation failure:",
20375
+ instrumentationError
20376
+ );
20377
+ }
20378
+ }
20379
+ throw error;
20380
+ }
20381
+ })
20382
+ );
19330
20383
  }
19331
20384
  };
19332
20385
 
@@ -21735,9 +22788,9 @@ function extractEmbedPromptTokenCount(response) {
21735
22788
  let sawAny = false;
21736
22789
  for (const embedding of embeddings) {
21737
22790
  const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
21738
- const tokenCount = embeddingStats?.tokenCount;
21739
- if (typeof tokenCount === "number" && Number.isFinite(tokenCount)) {
21740
- total += tokenCount;
22791
+ const tokenCount2 = embeddingStats?.tokenCount;
22792
+ if (typeof tokenCount2 === "number" && Number.isFinite(tokenCount2)) {
22793
+ total += tokenCount2;
21741
22794
  sawAny = true;
21742
22795
  }
21743
22796
  }
@@ -23440,7 +24493,7 @@ function patchOpenRouterCallModelResult(args) {
23440
24493
  span,
23441
24494
  () => originalMethod.apply(resultLike, args2)
23442
24495
  );
23443
- if (!isAsyncIterable4(stream)) {
24496
+ if (!isAsyncIterable3(stream)) {
23444
24497
  return stream;
23445
24498
  }
23446
24499
  return wrapAsyncIterableWithSpan({
@@ -23635,7 +24688,7 @@ function wrapAsyncIterableWithSpan(args) {
23635
24688
  }
23636
24689
  };
23637
24690
  }
23638
- function isAsyncIterable4(value) {
24691
+ function isAsyncIterable3(value) {
23639
24692
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
23640
24693
  }
23641
24694
  function normalizeError(error) {
@@ -24513,7 +25566,7 @@ function patchOpenRouterCallModelResult2(args) {
24513
25566
  span,
24514
25567
  () => originalMethod.apply(resultLike, args2)
24515
25568
  );
24516
- if (!isAsyncIterable5(stream)) {
25569
+ if (!isAsyncIterable4(stream)) {
24517
25570
  return stream;
24518
25571
  }
24519
25572
  return wrapAsyncIterableWithSpan2({
@@ -24708,7 +25761,7 @@ function wrapAsyncIterableWithSpan2(args) {
24708
25761
  }
24709
25762
  };
24710
25763
  }
24711
- function isAsyncIterable5(value) {
25764
+ function isAsyncIterable4(value) {
24712
25765
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
24713
25766
  }
24714
25767
  function normalizeError2(error) {
@@ -28632,7 +29685,7 @@ function getStringProperty2(obj, key) {
28632
29685
  return typeof value === "string" ? value : void 0;
28633
29686
  }
28634
29687
  function extractMetricsFromUsage(usage) {
28635
- const metrics = {
29688
+ const rawMetrics = {
28636
29689
  prompt_tokens: usage.inputTokens,
28637
29690
  completion_tokens: usage.outputTokens,
28638
29691
  ...extractAnthropicCacheTokens(
@@ -28641,10 +29694,10 @@ function extractMetricsFromUsage(usage) {
28641
29694
  )
28642
29695
  };
28643
29696
  if (usage.reasoningTokens !== void 0) {
28644
- metrics.completion_reasoning_tokens = usage.reasoningTokens;
28645
- metrics.reasoning_tokens = usage.reasoningTokens;
29697
+ rawMetrics.completion_reasoning_tokens = usage.reasoningTokens;
29698
+ rawMetrics.reasoning_tokens = usage.reasoningTokens;
28646
29699
  }
28647
- Object.assign(metrics, finalizeAnthropicTokens(metrics));
29700
+ const metrics = finalizeAnthropicTokens(rawMetrics);
28648
29701
  const metadata = {
28649
29702
  model: usage.model
28650
29703
  };
@@ -29583,17 +30636,20 @@ var FlueObserveBridge = class {
29583
30636
  return;
29584
30637
  }
29585
30638
  const metadata = {
30639
+ ...event.runId ? this.runsById.get(event.runId)?.metadata : {},
29586
30640
  ...extractEventMetadata(event),
29587
30641
  "flue.operation": event.operationKind,
29588
30642
  provider: "flue"
29589
30643
  };
29590
30644
  const parent = this.parentSpanForEvent(event);
29591
- const span = startFlueSpan(parent, {
30645
+ const args = {
29592
30646
  name: `flue.${event.operationKind}`,
29593
30647
  spanAttributes: { type: "task" /* TASK */ },
29594
30648
  startTime: eventTime(event.timestamp),
29595
30649
  event: { metadata }
29596
- });
30650
+ };
30651
+ const runSpan = event.runId ? this.runsById.get(event.runId)?.span : void 0;
30652
+ const span = event.operationKind === "prompt" && (!parent || parent === runSpan) ? startFlueRootSpan(args) : startFlueSpan(parent, args);
29597
30653
  this.operationsById.set(event.operationId, { metadata, span });
29598
30654
  }
29599
30655
  handleOperation(event) {
@@ -29608,6 +30664,11 @@ var FlueObserveBridge = class {
29608
30664
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
29609
30665
  ...event.usage ? { "flue.usage": event.usage } : {}
29610
30666
  };
30667
+ const input = flueOperationInput(event);
30668
+ if (!state.loggedInput && input !== void 0) {
30669
+ safeLog3(state.span, { input });
30670
+ state.loggedInput = true;
30671
+ }
29611
30672
  this.finishPendingChildrenForOperation(event, output);
29612
30673
  safeLog3(state.span, {
29613
30674
  ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
@@ -29624,6 +30685,8 @@ var FlueObserveBridge = class {
29624
30685
  return;
29625
30686
  }
29626
30687
  const input = flueTurnRequestInput(event);
30688
+ const operation = event.operationId ? this.operationsById.get(event.operationId) : void 0;
30689
+ const turnInput = prepareFlueTurnInput(event, input, operation);
29627
30690
  const model = flueTurnRequestModel(event);
29628
30691
  const provider = flueTurnRequestProvider(event);
29629
30692
  const api = flueTurnRequestApi(event);
@@ -29636,8 +30699,7 @@ var FlueObserveBridge = class {
29636
30699
  ...provider ? { "flue.provider": provider } : {},
29637
30700
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
29638
30701
  ...reasoning ? { reasoning } : {},
29639
- ...input?.systemPrompt ? { "flue.system_prompt": input.systemPrompt } : {},
29640
- ...input?.tools ? { tools: input.tools } : {}
30702
+ ...turnInput.metadata
29641
30703
  };
29642
30704
  const parent = this.parentSpanForTurn(event);
29643
30705
  const span = startFlueSpan(parent, {
@@ -29645,11 +30707,14 @@ var FlueObserveBridge = class {
29645
30707
  spanAttributes: { type: "llm" /* LLM */ },
29646
30708
  startTime: eventTime(event.timestamp),
29647
30709
  event: {
29648
- input: input?.messages,
30710
+ input: turnInput.messages,
29649
30711
  metadata
29650
30712
  }
29651
30713
  });
29652
- this.logOperationInput(event.operationId, input?.messages ?? input);
30714
+ this.logOperationInput(
30715
+ event.operationId,
30716
+ latestUserMessageInput(input?.messages)
30717
+ );
29653
30718
  this.turnsByKey.set(key, { metadata, span });
29654
30719
  }
29655
30720
  handleTurn(event) {
@@ -29896,16 +30961,20 @@ var FlueObserveBridge = class {
29896
30961
  }
29897
30962
  startSyntheticOperation(event) {
29898
30963
  const metadata = {
30964
+ ...event.runId ? this.runsById.get(event.runId)?.metadata : {},
29899
30965
  ...extractEventMetadata(event),
29900
30966
  "flue.operation": event.operationKind,
29901
30967
  provider: "flue"
29902
30968
  };
29903
- const span = startFlueSpan(this.parentSpanForEvent(event), {
30969
+ const args = {
29904
30970
  name: `flue.${event.operationKind}`,
29905
30971
  spanAttributes: { type: "task" /* TASK */ },
29906
30972
  startTime: eventTime(event.timestamp),
29907
30973
  event: { metadata }
29908
- });
30974
+ };
30975
+ const parent = this.parentSpanForEvent(event);
30976
+ const runSpan = event.runId ? this.runsById.get(event.runId)?.span : void 0;
30977
+ const span = event.operationKind === "prompt" && (!parent || parent === runSpan) ? startFlueRootSpan(args) : startFlueSpan(parent, args);
29909
30978
  return { metadata, span };
29910
30979
  }
29911
30980
  startSyntheticTurn(event) {
@@ -30084,6 +31153,71 @@ function flueRunInput(event) {
30084
31153
  function flueTurnRequestInput(event) {
30085
31154
  return event.request?.input ?? event.input;
30086
31155
  }
31156
+ function prepareFlueTurnInput(event, input, operation) {
31157
+ const messages = input?.messages;
31158
+ const tracksUserTurn = event.purpose === "agent" && operation?.metadata["flue.operation"] === "prompt" && Array.isArray(messages);
31159
+ if (!tracksUserTurn) {
31160
+ return {
31161
+ messages,
31162
+ metadata: {
31163
+ ...input?.systemPrompt ? { "flue.system_prompt": input.systemPrompt } : {},
31164
+ ...input?.tools ? { tools: input.tools } : {}
31165
+ }
31166
+ };
31167
+ }
31168
+ const previous = operation.turnInputState;
31169
+ const previousMessageCount = previous?.messageCount ?? 0;
31170
+ const boundaryFingerprint = messages.length > 0 ? fingerprintJsonValue(messages[messages.length - 1]) : void 0;
31171
+ const continuesPreviousInput = previous !== void 0 && messages.length >= previousMessageCount && (previousMessageCount === 0 || previous.boundaryFingerprint !== void 0 && previous.boundaryFingerprint === fingerprintJsonValue(messages[previousMessageCount - 1]));
31172
+ const inputMode = previous === void 0 ? "full" : continuesPreviousInput ? "delta" : "reset";
31173
+ const systemPromptFingerprint = fingerprintJsonValue(input?.systemPrompt);
31174
+ const toolsFingerprint = fingerprintJsonValue(input?.tools);
31175
+ operation.turnInputState = {
31176
+ ...boundaryFingerprint !== void 0 ? { boundaryFingerprint } : {},
31177
+ messageCount: messages.length,
31178
+ ...systemPromptFingerprint !== void 0 ? { systemPromptFingerprint } : {},
31179
+ ...toolsFingerprint !== void 0 ? { toolsFingerprint } : {}
31180
+ };
31181
+ return {
31182
+ messages: continuesPreviousInput ? messages.slice(previousMessageCount) : messages,
31183
+ metadata: {
31184
+ "flue.input_mode": inputMode,
31185
+ ...continuesPreviousInput ? { "flue.input_message_offset": previousMessageCount } : {},
31186
+ ...input?.systemPrompt && (!continuesPreviousInput || systemPromptFingerprint !== previous?.systemPromptFingerprint) ? { "flue.system_prompt": input.systemPrompt } : {},
31187
+ ...input?.tools && (!continuesPreviousInput || toolsFingerprint !== previous?.toolsFingerprint) ? { tools: input.tools } : {}
31188
+ }
31189
+ };
31190
+ }
31191
+ function fingerprintJsonValue(value) {
31192
+ try {
31193
+ const serialized = JSON.stringify(value);
31194
+ if (serialized === void 0) {
31195
+ return void 0;
31196
+ }
31197
+ let hash = 2166136261;
31198
+ for (let i = 0; i < serialized.length; i++) {
31199
+ hash = Math.imul(hash ^ serialized.charCodeAt(i), 16777619);
31200
+ }
31201
+ return `${serialized.length}:${hash >>> 0}`;
31202
+ } catch {
31203
+ return void 0;
31204
+ }
31205
+ }
31206
+ function latestUserMessageInput(messages) {
31207
+ if (!messages) {
31208
+ return void 0;
31209
+ }
31210
+ for (let i = messages.length - 1; i >= 0; i--) {
31211
+ const message = messages[i];
31212
+ if (isObjectLike(message) && Reflect.get(message, "role") === "user") {
31213
+ return [message];
31214
+ }
31215
+ }
31216
+ return void 0;
31217
+ }
31218
+ function flueOperationInput(event) {
31219
+ return typeof event.agentInput?.text === "string" ? [{ content: event.agentInput.text, role: "user" }] : void 0;
31220
+ }
30087
31221
  function flueTurnRequestModel(event) {
30088
31222
  return event.request?.requestedModel ?? event.request?.model ?? event.model;
30089
31223
  }
@@ -30241,6 +31375,21 @@ function startFlueSpan(parent, args) {
30241
31375
  withSpanInstrumentationName(args, INSTRUMENTATION_NAMES.FLUE)
30242
31376
  );
30243
31377
  }
31378
+ function startFlueRootSpan(args) {
31379
+ const state = _internalGetGlobalState();
31380
+ const spanId = state.idGenerator.getSpanId();
31381
+ const rootSpanId = state.idGenerator.shareRootSpanId() ? spanId : state.idGenerator.getTraceId();
31382
+ return withCurrent(
31383
+ NOOP_SPAN,
31384
+ () => startSpan({
31385
+ ...withSpanInstrumentationName(args, INSTRUMENTATION_NAMES.FLUE),
31386
+ parentSpanIds: { parentSpanIds: [], rootSpanId },
31387
+ spanId,
31388
+ state
31389
+ }),
31390
+ state
31391
+ );
31392
+ }
30244
31393
  function runWithCurrentSpanStore(span, next) {
30245
31394
  const state = _internalGetGlobalState();
30246
31395
  const contextManager = state?.contextManager;
@@ -30604,12 +31753,14 @@ function getMetricsFromResponse(response) {
30604
31753
  continue;
30605
31754
  }
30606
31755
  const inputTokenDetails = usageMetadata.input_token_details;
31756
+ const outputTokenDetails = usageMetadata.output_token_details;
30607
31757
  return normalizeTokenMetrics({
30608
31758
  total_tokens: usageMetadata.total_tokens,
30609
31759
  prompt_tokens: usageMetadata.input_tokens,
30610
31760
  completion_tokens: usageMetadata.output_tokens,
30611
31761
  prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
30612
- prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
31762
+ prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
31763
+ completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
30613
31764
  });
30614
31765
  }
30615
31766
  const llmOutput = response.llmOutput || {};
@@ -31196,6 +32347,9 @@ var piCodingAgentChannels = defineChannels(
31196
32347
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
31197
32348
  var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
31198
32349
  var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
32350
+ var PI_TOOL_EXECUTE_WRAPPED = /* @__PURE__ */ Symbol.for(
32351
+ "braintrust.pi_coding_agent.tool_execute_wrapped"
32352
+ );
31199
32353
  var piPromptContextStore;
31200
32354
  var PiCodingAgentPlugin = class extends BasePlugin {
31201
32355
  activePromptStates = /* @__PURE__ */ new Set();
@@ -31276,6 +32430,7 @@ function startPiPromptRun(event, onFinalize) {
31276
32430
  return void 0;
31277
32431
  }
31278
32432
  installPiAgentInstrumentation(agent);
32433
+ wrapPiToolExecutors(agent.state?.tools);
31279
32434
  const metadata = {
31280
32435
  ...extractSessionMetadata(session),
31281
32436
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -31372,6 +32527,7 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
31372
32527
  if (!state || state.agent !== agent || state.finalized) {
31373
32528
  return invokeOriginal();
31374
32529
  }
32530
+ wrapPiToolExecutors(context.tools);
31375
32531
  const llmState = await startPiLlmSpan(state, model, context, options);
31376
32532
  try {
31377
32533
  const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
@@ -31382,6 +32538,33 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
31382
32538
  }
31383
32539
  };
31384
32540
  }
32541
+ function wrapPiToolExecutors(tools) {
32542
+ if (!tools) {
32543
+ return;
32544
+ }
32545
+ for (const tool of tools) {
32546
+ try {
32547
+ const execute = tool.execute;
32548
+ if (typeof execute !== "function" || execute[PI_TOOL_EXECUTE_WRAPPED]) {
32549
+ continue;
32550
+ }
32551
+ const wrappedExecute = function(...args) {
32552
+ return runWithAutoInstrumentationAllowed(
32553
+ () => Reflect.apply(execute, this, args)
32554
+ );
32555
+ };
32556
+ Object.defineProperty(wrappedExecute, PI_TOOL_EXECUTE_WRAPPED, {
32557
+ configurable: false,
32558
+ enumerable: false,
32559
+ value: true,
32560
+ writable: false
32561
+ });
32562
+ tool.execute = wrappedExecute;
32563
+ } catch (error) {
32564
+ logInstrumentationError4("Pi Coding Agent tool wrapping", error);
32565
+ }
32566
+ }
32567
+ }
31385
32568
  async function startPiLlmSpan(state, model, context, options) {
31386
32569
  const metadata = {
31387
32570
  ...extractModelMetadata2(model),
@@ -31553,35 +32736,26 @@ async function startPiToolSpan(state, event) {
31553
32736
  if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
31554
32737
  return;
31555
32738
  }
31556
- const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
31557
32739
  const metadata = {
31558
32740
  "gen_ai.tool.call.id": event.toolCallId,
31559
32741
  "gen_ai.tool.name": event.toolName,
31560
32742
  "pi_coding_agent.tool.name": event.toolName
31561
32743
  };
31562
- try {
31563
- const span = startSpan(
31564
- withSpanInstrumentationName(
31565
- {
31566
- event: {
31567
- input: event.args,
31568
- metadata
31569
- },
31570
- name: event.toolName || "tool",
31571
- parent: await state.span.export(),
31572
- spanAttributes: { type: "tool" /* TOOL */ }
32744
+ const span = startSpan(
32745
+ withSpanInstrumentationName(
32746
+ {
32747
+ event: {
32748
+ input: event.args,
32749
+ metadata
31573
32750
  },
31574
- INSTRUMENTATION_NAMES.PI_CODING_AGENT
31575
- )
31576
- );
31577
- state.activeToolSpans.set(event.toolCallId, {
31578
- restoreAutoInstrumentation,
31579
- span
31580
- });
31581
- } catch (error) {
31582
- restoreAutoInstrumentation();
31583
- throw error;
31584
- }
32751
+ name: event.toolName || "tool",
32752
+ parent: await state.span.export(),
32753
+ spanAttributes: { type: "tool" /* TOOL */ }
32754
+ },
32755
+ INSTRUMENTATION_NAMES.PI_CODING_AGENT
32756
+ )
32757
+ );
32758
+ state.activeToolSpans.set(event.toolCallId, { span });
31585
32759
  }
31586
32760
  function finishPiToolSpan(state, event) {
31587
32761
  const toolState = state.activeToolSpans.get(event.toolCallId);
@@ -31602,11 +32776,7 @@ function finishPiToolSpan(state, event) {
31602
32776
  output: event.result
31603
32777
  });
31604
32778
  } finally {
31605
- try {
31606
- toolState.span.end();
31607
- } finally {
31608
- toolState.restoreAutoInstrumentation?.();
31609
- }
32779
+ toolState.span.end();
31610
32780
  }
31611
32781
  }
31612
32782
  function finishPiPromptRun(state, error) {
@@ -31656,10 +32826,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
31656
32826
  ...cleanMetrics5(llmState.metrics),
31657
32827
  ...buildDurationMetrics3(llmState.startTime)
31658
32828
  };
31659
- const usageMetrics = extractUsageMetrics2(message?.usage);
31660
- if (Object.keys(usageMetrics).length > 0) {
32829
+ const usageMetrics2 = extractUsageMetrics2(message?.usage);
32830
+ if (Object.keys(usageMetrics2).length > 0) {
31661
32831
  promptState.collectedLlmUsageMetrics = true;
31662
- addMetrics(promptState.metrics, usageMetrics);
32832
+ addMetrics(promptState.metrics, usageMetrics2);
31663
32833
  }
31664
32834
  try {
31665
32835
  safeLog4(llmState.span, {
@@ -31677,14 +32847,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
31677
32847
  }
31678
32848
  function finishOpenToolSpans(state, error) {
31679
32849
  for (const [, toolState] of state.activeToolSpans) {
31680
- try {
31681
- safeLog4(toolState.span, {
31682
- error: error ? toLoggedError(error) : "Pi tool did not complete"
31683
- });
31684
- toolState.span.end();
31685
- } finally {
31686
- toolState.restoreAutoInstrumentation?.();
31687
- }
32850
+ safeLog4(toolState.span, {
32851
+ error: error ? toLoggedError(error) : "Pi tool did not complete"
32852
+ });
32853
+ toolState.span.end();
31688
32854
  }
31689
32855
  state.activeToolSpans.clear();
31690
32856
  }
@@ -32003,12 +33169,12 @@ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
32003
33169
  var StrandsAgentSDKPlugin = class extends BasePlugin {
32004
33170
  activeChildParents = /* @__PURE__ */ new WeakMap();
32005
33171
  onEnable() {
32006
- this.subscribeToAgentStream();
32007
- this.subscribeToMultiAgentStream(
33172
+ this.interceptAgentStream();
33173
+ this.interceptMultiAgentStream(
32008
33174
  strandsAgentSDKChannels.graphStream,
32009
33175
  "Graph.stream"
32010
33176
  );
32011
- this.subscribeToMultiAgentStream(
33177
+ this.interceptMultiAgentStream(
32012
33178
  strandsAgentSDKChannels.swarmStream,
32013
33179
  "Swarm.stream"
32014
33180
  );
@@ -32019,143 +33185,109 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
32019
33185
  }
32020
33186
  this.unsubscribers = [];
32021
33187
  }
32022
- subscribeToAgentStream() {
32023
- const channel2 = strandsAgentSDKChannels.agentStream.tracingChannel();
32024
- const states = /* @__PURE__ */ new WeakMap();
32025
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
32026
- const handlers = {
32027
- start: (event) => {
32028
- const state = startAgentStream(event, this.activeChildParents);
32029
- if (state) {
32030
- states.set(event, state);
32031
- }
32032
- },
32033
- end: (event) => {
32034
- const state = states.get(event);
32035
- if (!state) {
32036
- return;
32037
- }
32038
- const result = event.result;
32039
- if (isAsyncIterable(result)) {
32040
- patchStreamIfNeeded(result, {
32041
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
32042
- onChunk: (chunk) => handleAgentStreamEvent(state, chunk),
32043
- onComplete: () => {
32044
- finalizeAgentStream(state);
32045
- states.delete(event);
32046
- },
32047
- onError: (error) => {
32048
- finalizeAgentStream(state, error);
32049
- states.delete(event);
32050
- }
32051
- });
32052
- return;
32053
- }
32054
- finalizeAgentStream(state, void 0, result);
32055
- states.delete(event);
32056
- },
32057
- error: (event) => {
32058
- const state = states.get(event);
32059
- if (!state || !event.error) {
32060
- return;
32061
- }
32062
- finalizeAgentStream(state, event.error);
32063
- states.delete(event);
32064
- }
32065
- };
32066
- channel2.subscribe(handlers);
32067
- this.unsubscribers.push(() => {
32068
- unbindAutoInstrumentationSuppression?.();
32069
- channel2.unsubscribe(handlers);
32070
- });
33188
+ interceptAgentStream() {
33189
+ this.unsubscribers.push(
33190
+ strandsAgentSDKChannels.agentStream.intercept(
33191
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
33192
+ finalize: finalizeAgentStream,
33193
+ handleChunk: handleAgentStreamEvent,
33194
+ invoke: () => Reflect.apply(target, thisArg, args),
33195
+ name: "Strands Agent SDK",
33196
+ start: () => startAgentStream(
33197
+ args[0],
33198
+ extractAgent(additional.agent, thisArg),
33199
+ this.activeChildParents
33200
+ )
33201
+ })
33202
+ )
33203
+ );
32071
33204
  }
32072
- subscribeToMultiAgentStream(channel2, operation) {
32073
- const tracingChannel = channel2.tracingChannel();
32074
- const states = /* @__PURE__ */ new WeakMap();
32075
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(tracingChannel);
32076
- const handlers = {
32077
- start: (event) => {
32078
- const state = startMultiAgentStream(
32079
- event,
32080
- operation,
32081
- this.activeChildParents
32082
- );
32083
- if (state) {
32084
- states.set(event, state);
32085
- }
32086
- },
32087
- end: (event) => {
32088
- const state = states.get(event);
32089
- if (!state) {
32090
- return;
32091
- }
32092
- const result = event.result;
32093
- if (isAsyncIterable(result)) {
32094
- patchStreamIfNeeded(result, {
32095
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
32096
- onChunk: (chunk) => handleMultiAgentStreamEvent(
32097
- state,
32098
- chunk,
32099
- this.activeChildParents
32100
- ),
32101
- onComplete: () => {
32102
- finalizeMultiAgentStream(state, this.activeChildParents);
32103
- states.delete(event);
32104
- },
32105
- onError: (error) => {
32106
- finalizeMultiAgentStream(state, this.activeChildParents, error);
32107
- states.delete(event);
32108
- }
32109
- });
32110
- return;
32111
- }
32112
- finalizeMultiAgentStream(
32113
- state,
32114
- this.activeChildParents,
32115
- void 0,
32116
- result
33205
+ interceptMultiAgentStream(channel2, operation) {
33206
+ this.unsubscribers.push(
33207
+ channel2.intercept(
33208
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
33209
+ finalize: (state, error, output) => finalizeMultiAgentStream(
33210
+ state,
33211
+ this.activeChildParents,
33212
+ error,
33213
+ output
33214
+ ),
33215
+ handleChunk: (state, chunk) => handleMultiAgentStreamEvent(state, chunk, this.activeChildParents),
33216
+ invoke: () => Reflect.apply(target, thisArg, args),
33217
+ name: "Strands multi-agent",
33218
+ start: () => startMultiAgentStream(
33219
+ args[0],
33220
+ extractOrchestrator(additional.orchestrator, thisArg),
33221
+ operation,
33222
+ this.activeChildParents
33223
+ )
33224
+ })
33225
+ )
33226
+ );
33227
+ }
33228
+ };
33229
+ function instrumentStrandsStreamInvocation(options) {
33230
+ let state;
33231
+ try {
33232
+ state = options.start();
33233
+ } catch (error) {
33234
+ debugLogger.error(`Error starting ${options.name} instrumentation:`, error);
33235
+ }
33236
+ let result;
33237
+ try {
33238
+ result = runWithAutoInstrumentationSuppressed(options.invoke);
33239
+ } catch (error) {
33240
+ if (state) {
33241
+ try {
33242
+ options.finalize(state, error);
33243
+ } catch (instrumentationError) {
33244
+ debugLogger.error(
33245
+ `Error handling ${options.name} instrumentation failure:`,
33246
+ instrumentationError
32117
33247
  );
32118
- states.delete(event);
32119
- },
32120
- error: (event) => {
32121
- const state = states.get(event);
32122
- if (!state || !event.error) {
32123
- return;
32124
- }
32125
- finalizeMultiAgentStream(state, this.activeChildParents, event.error);
32126
- states.delete(event);
32127
33248
  }
32128
- };
32129
- tracingChannel.subscribe(handlers);
32130
- this.unsubscribers.push(() => {
32131
- unbindAutoInstrumentationSuppression?.();
32132
- tracingChannel.unsubscribe(handlers);
32133
- });
33249
+ }
33250
+ throw error;
32134
33251
  }
32135
- };
32136
- function startAgentStream(event, activeChildParents) {
32137
- const agent = extractAgent(event);
33252
+ if (state) {
33253
+ try {
33254
+ if (isAsyncIterable(result)) {
33255
+ patchStreamIfNeeded(result, {
33256
+ aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
33257
+ onChunk: (chunk) => options.handleChunk(state, chunk),
33258
+ onComplete: () => options.finalize(state),
33259
+ onError: (error) => options.finalize(state, error)
33260
+ });
33261
+ } else {
33262
+ options.finalize(state, void 0, result);
33263
+ }
33264
+ } catch (error) {
33265
+ debugLogger.error(
33266
+ `Error finalizing ${options.name} instrumentation:`,
33267
+ error
33268
+ );
33269
+ }
33270
+ }
33271
+ return result;
33272
+ }
33273
+ function startAgentStream(input, agent, activeChildParents) {
32138
33274
  const model = agent?.model;
32139
33275
  const metadata = {
32140
33276
  ...extractAgentMetadata2(agent),
32141
33277
  ...extractModelMetadata3(model),
32142
33278
  "strands.operation": "Agent.stream",
32143
- provider: extractProvider(model),
32144
- ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
33279
+ provider: extractProvider(model)
32145
33280
  };
32146
33281
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
32147
33282
  const attachmentCache = createStrandsAttachmentCache();
32148
- const input = processStrandsInputAttachments(
32149
- event.arguments[0],
32150
- attachmentCache
32151
- );
33283
+ const processedInput = processStrandsInputAttachments(input, attachmentCache);
32152
33284
  const span = parentSpan ? withCurrent(
32153
33285
  parentSpan,
32154
33286
  () => startSpan(
32155
33287
  withSpanInstrumentationName(
32156
33288
  {
32157
33289
  event: {
32158
- input,
33290
+ input: processedInput,
32159
33291
  metadata
32160
33292
  },
32161
33293
  name: formatAgentSpanName(agent),
@@ -32168,7 +33300,7 @@ function startAgentStream(event, activeChildParents) {
32168
33300
  withSpanInstrumentationName(
32169
33301
  {
32170
33302
  event: {
32171
- input,
33303
+ input: processedInput,
32172
33304
  metadata
32173
33305
  },
32174
33306
  name: formatAgentSpanName(agent),
@@ -32186,23 +33318,21 @@ function startAgentStream(event, activeChildParents) {
32186
33318
  startTime: getCurrentUnixTimestamp()
32187
33319
  };
32188
33320
  }
32189
- function startMultiAgentStream(event, operation, activeChildParents) {
32190
- const orchestrator = extractOrchestrator(event);
33321
+ function startMultiAgentStream(input, orchestrator, operation, activeChildParents) {
32191
33322
  const metadata = {
32192
33323
  "strands.operation": operation,
32193
33324
  provider: "strands",
32194
- ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {},
32195
- ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
33325
+ ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
32196
33326
  };
32197
33327
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
32198
- const input = processStrandsInputAttachments(event.arguments[0]);
33328
+ const processedInput = processStrandsInputAttachments(input);
32199
33329
  const span = parentSpan ? withCurrent(
32200
33330
  parentSpan,
32201
33331
  () => startSpan(
32202
33332
  withSpanInstrumentationName(
32203
33333
  {
32204
33334
  event: {
32205
- input,
33335
+ input: processedInput,
32206
33336
  metadata
32207
33337
  },
32208
33338
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -32215,7 +33345,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
32215
33345
  withSpanInstrumentationName(
32216
33346
  {
32217
33347
  event: {
32218
- input,
33348
+ input: processedInput,
32219
33349
  metadata
32220
33350
  },
32221
33351
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -32586,12 +33716,12 @@ function finalizeMultiAgentStream(state, activeChildParents, error, output) {
32586
33716
  });
32587
33717
  state.span.end();
32588
33718
  }
32589
- function extractAgent(event) {
32590
- const candidate = event.agent ?? event.self;
33719
+ function extractAgent(agent, self) {
33720
+ const candidate = agent ?? self;
32591
33721
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
32592
33722
  }
32593
- function extractOrchestrator(event) {
32594
- const candidate = event.orchestrator ?? event.self;
33723
+ function extractOrchestrator(orchestrator, self) {
33724
+ const candidate = orchestrator ?? self;
32595
33725
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
32596
33726
  }
32597
33727
  function extractAgentMetadata2(agent) {
@@ -32978,6 +34108,320 @@ function logInstrumentationError5(context, error) {
32978
34108
  debugLogger.debug(`${context}:`, error);
32979
34109
  }
32980
34110
 
34111
+ // src/instrumentation/plugins/voyageai-channels.ts
34112
+ var voyageAIChannels = defineChannels(
34113
+ "voyageai",
34114
+ {
34115
+ embed: channel({
34116
+ channelName: "embed",
34117
+ kind: "async"
34118
+ }),
34119
+ multimodalEmbed: channel({
34120
+ channelName: "multimodalEmbed",
34121
+ kind: "async"
34122
+ }),
34123
+ rerank: channel({
34124
+ channelName: "rerank",
34125
+ kind: "async"
34126
+ }),
34127
+ contextualizedEmbed: channel({
34128
+ channelName: "contextualizedEmbed",
34129
+ kind: "async"
34130
+ })
34131
+ },
34132
+ { instrumentationName: INSTRUMENTATION_NAMES.VOYAGEAI }
34133
+ );
34134
+
34135
+ // src/instrumentation/plugins/voyageai-plugin.ts
34136
+ var RERANK_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
34137
+ "model",
34138
+ "returnDocuments",
34139
+ "topK",
34140
+ "truncation"
34141
+ ]);
34142
+ var VoyageAIPlugin = class extends BasePlugin {
34143
+ onEnable() {
34144
+ this.unsubscribers.push(
34145
+ interceptVoyageAICall(
34146
+ voyageAIChannels.embed,
34147
+ "voyageai.embed",
34148
+ extractTextEmbeddingInput,
34149
+ summarizeEmbeddingOutput,
34150
+ extractEmbeddingUsageMetrics
34151
+ ),
34152
+ interceptVoyageAICall(
34153
+ voyageAIChannels.multimodalEmbed,
34154
+ "voyageai.multimodalEmbed",
34155
+ extractMultimodalEmbeddingInput,
34156
+ summarizeEmbeddingOutput,
34157
+ extractEmbeddingUsageMetrics
34158
+ ),
34159
+ interceptVoyageAICall(
34160
+ voyageAIChannels.rerank,
34161
+ "voyageai.rerank",
34162
+ extractRerankInput,
34163
+ summarizeRerankOutput
34164
+ ),
34165
+ interceptVoyageAICall(
34166
+ voyageAIChannels.contextualizedEmbed,
34167
+ "voyageai.contextualizedEmbed",
34168
+ extractContextualizedEmbeddingInput,
34169
+ summarizeContextualizedEmbeddingOutput,
34170
+ extractEmbeddingUsageMetrics
34171
+ )
34172
+ );
34173
+ }
34174
+ onDisable() {
34175
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
34176
+ }
34177
+ };
34178
+ function interceptVoyageAICall(channel2, name, extractInput2, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
34179
+ return channel2.intercept((target, thisArg, args) => {
34180
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
34181
+ if (isAutoInstrumentationSuppressed()) {
34182
+ return invokeTarget();
34183
+ }
34184
+ let span;
34185
+ try {
34186
+ const { input, metadata } = extractInput2(args);
34187
+ span = startSpan(
34188
+ withSpanInstrumentationName(
34189
+ {
34190
+ event: { input, metadata },
34191
+ name,
34192
+ spanAttributes: { type: "llm" /* LLM */ }
34193
+ },
34194
+ INSTRUMENTATION_NAMES.VOYAGEAI
34195
+ )
34196
+ );
34197
+ } catch (error) {
34198
+ debugLogger.error(`Error starting span for ${name}:`, error);
34199
+ return invokeTarget();
34200
+ }
34201
+ let result;
34202
+ try {
34203
+ result = withCurrent(
34204
+ span,
34205
+ () => runWithAutoInstrumentationSuppressed(invokeTarget)
34206
+ );
34207
+ } catch (error) {
34208
+ finishVoyageAISpan(span, name, () => span.log({ error }));
34209
+ throw error;
34210
+ }
34211
+ void Promise.resolve(result).then(
34212
+ (value) => finishVoyageAISpan(span, name, () => {
34213
+ const metadata = extractResponseMetadata3(value);
34214
+ span.log({
34215
+ output: extractOutput2(value),
34216
+ ...metadata ? { metadata } : {},
34217
+ metrics: extractMetrics2(value)
34218
+ });
34219
+ }),
34220
+ (error) => finishVoyageAISpan(span, name, () => span.log({ error }))
34221
+ );
34222
+ return result;
34223
+ });
34224
+ }
34225
+ function finishVoyageAISpan(span, name, log) {
34226
+ try {
34227
+ log();
34228
+ } catch (error) {
34229
+ debugLogger.error(`Error logging span for ${name}:`, error);
34230
+ }
34231
+ try {
34232
+ span.end();
34233
+ } catch (error) {
34234
+ debugLogger.error(`Error ending span for ${name}:`, error);
34235
+ }
34236
+ }
34237
+ function getRequestArg2(args) {
34238
+ if (Array.isArray(args)) {
34239
+ return isObject(args[0]) ? args[0] : void 0;
34240
+ }
34241
+ if (!isObject(args)) {
34242
+ return void 0;
34243
+ }
34244
+ const firstArg = Reflect.get(args, "0");
34245
+ return isObject(firstArg) ? firstArg : void 0;
34246
+ }
34247
+ function pickMetadata(request, allowlist) {
34248
+ const metadata = {};
34249
+ if (request) {
34250
+ for (const key of allowlist) {
34251
+ if (!Object.hasOwn(request, key)) {
34252
+ continue;
34253
+ }
34254
+ const value = request[key];
34255
+ if (value !== void 0) {
34256
+ metadata[key] = value;
34257
+ }
34258
+ }
34259
+ }
34260
+ return {
34261
+ ...metadata,
34262
+ provider: "voyage"
34263
+ };
34264
+ }
34265
+ function buildEmbeddingInput(inputs, request) {
34266
+ const outputDimensions = request?.outputDimension;
34267
+ return {
34268
+ inputs,
34269
+ ...typeof outputDimensions === "number" && Number.isFinite(outputDimensions) ? { output_dimensions: outputDimensions } : {}
34270
+ };
34271
+ }
34272
+ function embeddingMetadata(request) {
34273
+ return {
34274
+ ...typeof request?.model === "string" ? { model: request.model } : {},
34275
+ provider: "voyage"
34276
+ };
34277
+ }
34278
+ function extractTextEmbeddingInput(args) {
34279
+ const request = getRequestArg2(args);
34280
+ const rawInput = request?.input;
34281
+ const values = Array.isArray(rawInput) ? rawInput : [rawInput];
34282
+ return {
34283
+ input: buildEmbeddingInput(
34284
+ values.flatMap(
34285
+ (value) => typeof value === "string" ? [{ content: value }] : []
34286
+ ),
34287
+ request
34288
+ ),
34289
+ metadata: embeddingMetadata(request)
34290
+ };
34291
+ }
34292
+ function extractContextualizedEmbeddingInput(args) {
34293
+ const request = getRequestArg2(args);
34294
+ const rawInputs = request?.inputs;
34295
+ const values = Array.isArray(rawInputs) ? rawInputs.flatMap((value) => Array.isArray(value) ? value : [value]) : [];
34296
+ return {
34297
+ input: buildEmbeddingInput(
34298
+ values.flatMap(
34299
+ (value) => typeof value === "string" ? [{ content: value }] : []
34300
+ ),
34301
+ request
34302
+ ),
34303
+ metadata: embeddingMetadata(request)
34304
+ };
34305
+ }
34306
+ function extractMultimodalEmbeddingInput(args) {
34307
+ const request = getRequestArg2(args);
34308
+ const rawInputs = request?.inputs;
34309
+ const inputs = Array.isArray(rawInputs) ? rawInputs.map((rawInput) => {
34310
+ const rawContent = isObject(rawInput) ? rawInput.content : void 0;
34311
+ return {
34312
+ content: Array.isArray(rawContent) ? rawContent.flatMap(normalizeMultimodalContentPart) : []
34313
+ };
34314
+ }) : [];
34315
+ const input = buildEmbeddingInput(inputs, request);
34316
+ const processedInput = processInputAttachments(input);
34317
+ return {
34318
+ input: hasInlineEmbeddingMedia(processedInput) ? input : processedInput,
34319
+ metadata: embeddingMetadata(request)
34320
+ };
34321
+ }
34322
+ function normalizeMultimodalContentPart(part) {
34323
+ if (!isObject(part) || typeof part.type !== "string") {
34324
+ return [];
34325
+ }
34326
+ if (part.type === "text") {
34327
+ return typeof part.text === "string" ? [{ type: "text", text: part.text }] : [];
34328
+ }
34329
+ const camelCaseField = {
34330
+ image_base64: "imageBase64",
34331
+ image_url: "imageUrl",
34332
+ video_base64: "videoBase64",
34333
+ video_url: "videoUrl"
34334
+ };
34335
+ const field = camelCaseField[part.type];
34336
+ if (!field) {
34337
+ return [];
34338
+ }
34339
+ const data = typeof part[field] === "string" ? part[field] : part[part.type];
34340
+ if (typeof data !== "string") {
34341
+ return [];
34342
+ }
34343
+ return part.type.startsWith("image_") ? [{ type: "image_url", image_url: { url: data } }] : [{ type: "file", file: { file_data: data } }];
34344
+ }
34345
+ function hasInlineEmbeddingMedia(input) {
34346
+ return input.inputs.some(
34347
+ ({ content }) => Array.isArray(content) ? content.some((part) => {
34348
+ const value = part.type === "image_url" ? part.image_url.url : part.type === "file" ? part.file.file_data : void 0;
34349
+ return typeof value === "string" && value.startsWith("data:");
34350
+ }) : false
34351
+ );
34352
+ }
34353
+ function extractRerankInput(args) {
34354
+ const request = getRequestArg2(args);
34355
+ const documents = request?.documents;
34356
+ return {
34357
+ input: {
34358
+ documents,
34359
+ query: request?.query
34360
+ },
34361
+ metadata: {
34362
+ ...pickMetadata(request, RERANK_METADATA_ALLOWLIST),
34363
+ ...Array.isArray(documents) ? { document_count: documents.length } : {}
34364
+ }
34365
+ };
34366
+ }
34367
+ function extractResponseMetadata3(result) {
34368
+ if (!isObject(result)) {
34369
+ return void 0;
34370
+ }
34371
+ const rawResponse = isObject(result.rawResponse) ? result.rawResponse : void 0;
34372
+ const model = typeof result.model === "string" ? result.model : typeof rawResponse?.model === "string" ? rawResponse.model : void 0;
34373
+ return model ? { model } : void 0;
34374
+ }
34375
+ function summarizeEmbeddingOutput(result) {
34376
+ return {
34377
+ count: isObject(result) && Array.isArray(result.data) ? result.data.length : 0
34378
+ };
34379
+ }
34380
+ function summarizeRerankOutput(result) {
34381
+ if (!isObject(result) || !Array.isArray(result.data)) {
34382
+ return void 0;
34383
+ }
34384
+ return result.data.slice(0, 100).map((item) => ({
34385
+ index: isObject(item) ? item.index : void 0,
34386
+ relevance_score: isObject(item) ? (typeof item.relevanceScore === "number" ? item.relevanceScore : item.relevance_score) ?? null : null
34387
+ }));
34388
+ }
34389
+ function summarizeContextualizedEmbeddingOutput(result) {
34390
+ if (!isObject(result)) {
34391
+ return { count: 0 };
34392
+ }
34393
+ if (Array.isArray(result.results)) {
34394
+ return {
34395
+ count: result.results.reduce(
34396
+ (count, item) => count + (isObject(item) && Array.isArray(item.embeddings) ? item.embeddings.length : 0),
34397
+ 0
34398
+ )
34399
+ };
34400
+ }
34401
+ if (!Array.isArray(result.data)) {
34402
+ return { count: 0 };
34403
+ }
34404
+ return {
34405
+ count: result.data.reduce(
34406
+ (count, item) => count + (isObject(item) && Array.isArray(item.data) ? item.data.length : 0),
34407
+ 0
34408
+ )
34409
+ };
34410
+ }
34411
+ function extractEmbeddingUsageMetrics(result) {
34412
+ const metrics = extractUsageMetrics3(result);
34413
+ return typeof metrics.tokens === "number" ? { prompt_tokens: metrics.tokens, tokens: metrics.tokens } : {};
34414
+ }
34415
+ function extractUsageMetrics3(result) {
34416
+ if (!isObject(result)) {
34417
+ return {};
34418
+ }
34419
+ const rawResponse = isObject(result.rawResponse) ? result.rawResponse : void 0;
34420
+ const usage = isObject(result.usage) ? result.usage : isObject(rawResponse?.usage) ? rawResponse.usage : void 0;
34421
+ const tokens = typeof result.totalTokens === "number" ? result.totalTokens : usage?.totalTokens ?? usage?.total_tokens;
34422
+ return typeof tokens === "number" && Number.isFinite(tokens) && tokens >= 0 ? { tokens } : {};
34423
+ }
34424
+
32981
34425
  // src/instrumentation/plugins/cloudflare-ai-chat-channels.ts
32982
34426
  var cloudflareAIChatChannels = defineChannels(
32983
34427
  "@cloudflare/ai-chat",
@@ -33533,6 +34977,7 @@ var BraintrustPlugin = class extends BasePlugin {
33533
34977
  langSmithPlugin = null;
33534
34978
  piCodingAgentPlugin = null;
33535
34979
  strandsAgentSDKPlugin = null;
34980
+ voyageAIPlugin = null;
33536
34981
  cloudflareAIChatPlugin = null;
33537
34982
  cloudflareAgentsPlugin = null;
33538
34983
  constructor(config = {}) {
@@ -33607,6 +35052,10 @@ var BraintrustPlugin = class extends BasePlugin {
33607
35052
  this.coherePlugin = new CoherePlugin();
33608
35053
  this.coherePlugin.enable();
33609
35054
  }
35055
+ if (integrations.voyageai !== false) {
35056
+ this.voyageAIPlugin = new VoyageAIPlugin();
35057
+ this.voyageAIPlugin.enable();
35058
+ }
33610
35059
  if (integrations.groq !== false) {
33611
35060
  this.groqPlugin = new GroqPlugin();
33612
35061
  this.groqPlugin.enable();
@@ -33723,6 +35172,10 @@ var BraintrustPlugin = class extends BasePlugin {
33723
35172
  this.coherePlugin.disable();
33724
35173
  this.coherePlugin = null;
33725
35174
  }
35175
+ if (this.voyageAIPlugin) {
35176
+ this.voyageAIPlugin.disable();
35177
+ this.voyageAIPlugin = null;
35178
+ }
33726
35179
  if (this.groqPlugin) {
33727
35180
  this.groqPlugin.disable();
33728
35181
  this.groqPlugin = null;
@@ -33788,7 +35241,7 @@ function braintrustEveHook(options) {
33788
35241
  }
33789
35242
  };
33790
35243
  }
33791
- function braintrustEveInstrumentation(options) {
35244
+ function createLegacyEveInstrumentation(options) {
33792
35245
  const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
33793
35246
  return {
33794
35247
  events: {
@@ -35176,8 +36629,10 @@ function capturedModelInput(modelInput) {
35176
36629
  const value = [];
35177
36630
  if (typeof instructions === "string") {
35178
36631
  value.push({ content: instructions, role: "system" });
35179
- } else if (instructions) {
36632
+ } else if (Array.isArray(instructions)) {
35180
36633
  value.push(...instructions.map(capturedEveModelMessage));
36634
+ } else if (instructions) {
36635
+ value.push(capturedEveModelMessage(instructions));
35181
36636
  }
35182
36637
  value.push(...messages.map(capturedEveModelMessage));
35183
36638
  try {
@@ -35421,6 +36876,464 @@ async function deterministicEveId(...parts) {
35421
36876
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
35422
36877
  }
35423
36878
 
36879
+ // src/instrumentation/plugins/eve-provider.ts
36880
+ var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
36881
+ function createEveInstrumentationProvider(options = {}) {
36882
+ const bridge = new EveProviderBridge(options.metadata);
36883
+ return {
36884
+ capture: "content",
36885
+ events: {
36886
+ "action.completed": (event, context) => bridge.handleActionTerminal(event, context),
36887
+ "action.failed": (event, context) => bridge.handleActionTerminal(event, context),
36888
+ "action.started": (event, context) => bridge.handleActionStarted(event, context),
36889
+ "model.call.completed": (event, context) => bridge.handleModelTerminal(event, context),
36890
+ "model.call.failed": (event, context) => bridge.handleModelTerminal(event, context),
36891
+ "model.call.started": (event, context) => bridge.handleModelStarted(event, context),
36892
+ "step.attempt.completed": (event) => bridge.handleStepAttemptTerminal(event),
36893
+ "step.attempt.failed": (event) => bridge.handleStepAttemptTerminal(event),
36894
+ "turn.cancelled": (event, context) => bridge.handleTurnTerminal(event, context),
36895
+ "turn.completed": (event, context) => bridge.handleTurnTerminal(event, context),
36896
+ "turn.failed": (event, context) => bridge.handleTurnTerminal(event, context),
36897
+ "turn.started": (event, context) => bridge.handleTurnStarted(event, context)
36898
+ },
36899
+ flush,
36900
+ setup: options.setup
36901
+ };
36902
+ }
36903
+ var EveProviderBridge = class {
36904
+ constructor(metadata) {
36905
+ this.metadata = metadata;
36906
+ }
36907
+ metadata;
36908
+ activeActions = /* @__PURE__ */ new Map();
36909
+ activeModels = /* @__PURE__ */ new Map();
36910
+ modelsByAttempt = /* @__PURE__ */ new Map();
36911
+ settledOperations = new LRUCache({
36912
+ max: MAX_EVE_PROVIDER_CACHE_ENTRIES
36913
+ });
36914
+ turns = new LRUCache({
36915
+ max: MAX_EVE_PROVIDER_CACHE_ENTRIES
36916
+ });
36917
+ async handleTurnStarted(event, context) {
36918
+ await this.contain("turn start", async () => {
36919
+ if (this.settledOperations.has(event.idempotencyKey)) {
36920
+ context.state.set({ skip: true });
36921
+ return;
36922
+ }
36923
+ const { rowId, spanId } = await generateEveIds(
36924
+ "turn",
36925
+ event.idempotencyKey
36926
+ );
36927
+ const key = turnKey3(event.sessionId, event.turnId);
36928
+ const stored = storedSpan(context);
36929
+ if (stored && "exported" in stored && stored.rootSpanId) {
36930
+ this.turns.set(key, { rootSpanId: stored.rootSpanId, spanId });
36931
+ return;
36932
+ }
36933
+ let rootSpanId = spanId;
36934
+ let parentSpanId;
36935
+ if (event.parentLineage) {
36936
+ const parentTurnKey = turnKey3(
36937
+ event.parentLineage.sessionId,
36938
+ event.parentLineage.turnId
36939
+ );
36940
+ const parentTurn = this.turns.get(parentTurnKey);
36941
+ rootSpanId = parentTurn?.rootSpanId ?? // Eve propagates the root session through every nested subagent. Use
36942
+ // it instead of the immediate parent session when no ancestor ran
36943
+ // in-process.
36944
+ (await generateEveIds(
36945
+ "turn",
36946
+ turnIdempotencyKey(
36947
+ event.rootSessionId,
36948
+ event.parentLineage.turnId
36949
+ )
36950
+ )).spanId;
36951
+ parentSpanId = (await generateEveIds(
36952
+ "subagent",
36953
+ actionIdempotencyKey(
36954
+ event.parentLineage.sessionId,
36955
+ event.parentLineage.turnId,
36956
+ event.parentLineage.callId
36957
+ )
36958
+ )).spanId;
36959
+ }
36960
+ const metadata = this.spanMetadata(event.sessionId);
36961
+ const span = await this.startSpan(
36962
+ context,
36963
+ {
36964
+ event: { id: rowId, metadata },
36965
+ name: "eve.turn",
36966
+ parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
36967
+ spanAttributes: { type: "task" /* TASK */ },
36968
+ spanId
36969
+ },
36970
+ rootSpanId
36971
+ );
36972
+ span?.log({ metadata });
36973
+ this.turns.set(key, {
36974
+ rootSpanId,
36975
+ spanId
36976
+ });
36977
+ });
36978
+ }
36979
+ async handleTurnTerminal(event, context) {
36980
+ await this.contain("turn terminal", async () => {
36981
+ if (this.settledOperations.has(event.idempotencyKey)) {
36982
+ context.state.set(void 0);
36983
+ return;
36984
+ }
36985
+ const error = event.type === "turn.failed" ? event.error : void 0;
36986
+ this.drainActionsForTurn(event.sessionId, event.turnId, error);
36987
+ const stored = storedSpan(context);
36988
+ if (stored && "exported" in stored) {
36989
+ updateSpan({
36990
+ exported: stored.exported,
36991
+ ...error !== void 0 ? { error } : {},
36992
+ metrics: { end: Date.now() / 1e3 }
36993
+ });
36994
+ }
36995
+ this.settledOperations.set(event.idempotencyKey, true);
36996
+ context.state.set(void 0);
36997
+ this.turns.delete(turnKey3(event.sessionId, event.turnId));
36998
+ });
36999
+ }
37000
+ async handleModelStarted(event, context) {
37001
+ await this.contain("model start", async () => {
37002
+ if (this.settledOperations.has(event.idempotencyKey)) {
37003
+ context.state.set({ skip: true });
37004
+ return;
37005
+ }
37006
+ const parent = await this.parentForScope(event.scope);
37007
+ const { rowId, spanId } = await generateEveIds(
37008
+ "step",
37009
+ event.idempotencyKey
37010
+ );
37011
+ const input = event.input ? capturedModelInput(event.input) : void 0;
37012
+ const metadata = {
37013
+ ...this.spanMetadata(event.scope.sessionId),
37014
+ model: event.model.modelId,
37015
+ provider: event.model.provider
37016
+ };
37017
+ const span = await this.startSpan(context, {
37018
+ event: {
37019
+ id: rowId,
37020
+ ...input !== void 0 ? { input } : {},
37021
+ metadata
37022
+ },
37023
+ name: "eve.step",
37024
+ parentSpanIds: parent,
37025
+ spanAttributes: { type: "llm" /* LLM */ },
37026
+ spanId
37027
+ });
37028
+ if (!span) return;
37029
+ span.log({ ...input !== void 0 ? { input } : {}, metadata });
37030
+ this.activeModels.set(event.idempotencyKey, {
37031
+ span,
37032
+ turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
37033
+ });
37034
+ const keys = this.modelsByAttempt.get(event.scope.attemptId) ?? /* @__PURE__ */ new Set();
37035
+ keys.add(event.idempotencyKey);
37036
+ this.modelsByAttempt.set(event.scope.attemptId, keys);
37037
+ });
37038
+ }
37039
+ async handleModelTerminal(event, context) {
37040
+ await this.contain("model terminal", async () => {
37041
+ if (this.settledOperations.has(event.idempotencyKey)) {
37042
+ context.state.set(void 0);
37043
+ return;
37044
+ }
37045
+ const active = this.activeModels.get(event.idempotencyKey);
37046
+ if (active) {
37047
+ const span = active.span;
37048
+ if (event.type === "model.call.failed") {
37049
+ if (event.error !== void 0) span.log({ error: event.error });
37050
+ } else {
37051
+ span.log({
37052
+ metrics: usageMetrics(event.usage),
37053
+ output: modelOutput(event)
37054
+ });
37055
+ }
37056
+ span.end();
37057
+ } else {
37058
+ const stored = storedSpan(context);
37059
+ if (stored && "exported" in stored) {
37060
+ updateSpan({
37061
+ exported: stored.exported,
37062
+ ...event.type === "model.call.failed" ? event.error !== void 0 ? { error: event.error } : {} : { output: modelOutput(event) },
37063
+ metrics: {
37064
+ ...event.type === "model.call.completed" ? usageMetrics(event.usage) : {},
37065
+ end: Date.now() / 1e3
37066
+ }
37067
+ });
37068
+ }
37069
+ }
37070
+ this.settledOperations.set(event.idempotencyKey, true);
37071
+ this.forgetModel(event.scope.attemptId, event.idempotencyKey);
37072
+ context.state.set(void 0);
37073
+ });
37074
+ }
37075
+ async handleActionStarted(event, context) {
37076
+ await this.contain("action start", async () => {
37077
+ if (event.kind === "load-skill" || this.settledOperations.has(event.idempotencyKey)) {
37078
+ context.state.set({ skip: true });
37079
+ return;
37080
+ }
37081
+ const parent = await this.parentForScope(event.scope);
37082
+ const { rowId, spanId } = await generateEveIds(
37083
+ event.kind === "subagent-call" ? "subagent" : "tool",
37084
+ event.idempotencyKey
37085
+ );
37086
+ const metadata = {
37087
+ ...this.spanMetadata(event.scope.sessionId),
37088
+ "eve.action_kind": event.kind
37089
+ };
37090
+ const span = await this.startSpan(context, {
37091
+ event: {
37092
+ id: rowId,
37093
+ ...event.input !== void 0 ? { input: event.input } : {},
37094
+ metadata
37095
+ },
37096
+ name: event.name,
37097
+ parentSpanIds: parent,
37098
+ spanAttributes: { type: "tool" /* TOOL */ },
37099
+ spanId
37100
+ });
37101
+ if (!span) return;
37102
+ span.log({
37103
+ ...event.input !== void 0 ? { input: event.input } : {},
37104
+ metadata
37105
+ });
37106
+ this.activeActions.set(event.idempotencyKey, {
37107
+ span,
37108
+ turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
37109
+ });
37110
+ });
37111
+ }
37112
+ async handleActionTerminal(event, context) {
37113
+ await this.contain("action terminal", async () => {
37114
+ if (this.settledOperations.has(event.idempotencyKey)) {
37115
+ context.state.set(void 0);
37116
+ return;
37117
+ }
37118
+ const stored = storedSpan(context);
37119
+ if (stored?.skip) {
37120
+ context.state.set(void 0);
37121
+ return;
37122
+ }
37123
+ const active = this.activeActions.get(event.idempotencyKey);
37124
+ const end = finiteTimestamp(event.acceptedAtMs) ?? Date.now();
37125
+ if (active) {
37126
+ const span = active.span;
37127
+ if (event.type === "action.failed") {
37128
+ span.log({
37129
+ error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
37130
+ });
37131
+ } else if (event.output.type === "error") {
37132
+ span.log({
37133
+ error: event.output.error ?? new Error("Eve action returned an error")
37134
+ });
37135
+ } else {
37136
+ span.log({ output: event.output.output });
37137
+ }
37138
+ span.end({ endTime: end / 1e3 });
37139
+ } else {
37140
+ const stored2 = storedSpan(context);
37141
+ if (stored2 && "exported" in stored2) {
37142
+ updateSpan({
37143
+ exported: stored2.exported,
37144
+ ...event.type === "action.failed" ? {
37145
+ error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
37146
+ } : event.output.type === "error" ? {
37147
+ error: event.output.error ?? new Error("Eve action returned an error")
37148
+ } : { output: event.output.output },
37149
+ metrics: { end: end / 1e3 }
37150
+ });
37151
+ }
37152
+ }
37153
+ this.settledOperations.set(event.idempotencyKey, true);
37154
+ this.activeActions.delete(event.idempotencyKey);
37155
+ context.state.set(void 0);
37156
+ });
37157
+ }
37158
+ handleStepAttemptTerminal(event) {
37159
+ void this.contain("step attempt terminal", () => {
37160
+ const keys = this.modelsByAttempt.get(event.scope.attemptId);
37161
+ if (!keys) return;
37162
+ for (const key of keys) {
37163
+ const active = this.activeModels.get(key);
37164
+ if (!active) continue;
37165
+ if (event.type === "step.attempt.failed" && event.error !== void 0) {
37166
+ active.span.log({ error: event.error });
37167
+ }
37168
+ active.span.end();
37169
+ this.activeModels.delete(key);
37170
+ }
37171
+ this.modelsByAttempt.delete(event.scope.attemptId);
37172
+ });
37173
+ }
37174
+ async parentForScope(scope) {
37175
+ const key = turnKey3(scope.sessionId, scope.turnId);
37176
+ const known = this.turns.get(key);
37177
+ if (known) {
37178
+ return { rootSpanId: known.rootSpanId, spanId: known.spanId };
37179
+ }
37180
+ const [{ spanId }, { spanId: rootSpanId }] = await Promise.all([
37181
+ generateEveIds("turn", turnIdempotencyKey(scope.sessionId, scope.turnId)),
37182
+ generateEveIds(
37183
+ "turn",
37184
+ turnIdempotencyKey(
37185
+ scope.rootSessionId ?? scope.sessionId,
37186
+ scope.turnId
37187
+ )
37188
+ )
37189
+ ]);
37190
+ return { rootSpanId, spanId };
37191
+ }
37192
+ async startSpan(context, args, rootSpanId) {
37193
+ const span = withCurrent(
37194
+ NOOP_SPAN,
37195
+ () => _internalStartSpanWithInitialMerge(
37196
+ withSpanInstrumentationName(args ?? {}, INSTRUMENTATION_NAMES.EVE)
37197
+ )
37198
+ );
37199
+ try {
37200
+ context.state.set({
37201
+ exported: await span.export(),
37202
+ ...rootSpanId ? { rootSpanId } : {}
37203
+ });
37204
+ } catch (error) {
37205
+ debugLogger.warn("Error exporting Eve provider span:", error);
37206
+ }
37207
+ return span;
37208
+ }
37209
+ drainActionsForTurn(sessionId, turnId, error) {
37210
+ const key = turnKey3(sessionId, turnId);
37211
+ for (const [idempotencyKey, active] of this.activeActions) {
37212
+ if (active.turnKey !== key) continue;
37213
+ if (error !== void 0) active.span.log({ error });
37214
+ active.span.end();
37215
+ this.activeActions.delete(idempotencyKey);
37216
+ }
37217
+ }
37218
+ forgetModel(attemptId, idempotencyKey) {
37219
+ this.activeModels.delete(idempotencyKey);
37220
+ const keys = this.modelsByAttempt.get(attemptId);
37221
+ keys?.delete(idempotencyKey);
37222
+ if (keys?.size === 0) this.modelsByAttempt.delete(attemptId);
37223
+ }
37224
+ spanMetadata(sessionId) {
37225
+ return {
37226
+ ...this.metadata ?? {},
37227
+ "eve.session_id": sessionId
37228
+ };
37229
+ }
37230
+ async contain(operation, fn) {
37231
+ try {
37232
+ await fn();
37233
+ } catch (error) {
37234
+ debugLogger.warn(`Error in Eve provider ${operation}:`, error);
37235
+ }
37236
+ }
37237
+ };
37238
+ function storedSpan(context) {
37239
+ const value = context.state.get();
37240
+ if (!isObject(value)) return void 0;
37241
+ if (value["skip"] === true) return { skip: true };
37242
+ return typeof value["exported"] === "string" ? {
37243
+ exported: value["exported"],
37244
+ ...typeof value["rootSpanId"] === "string" && value["rootSpanId"].length > 0 ? { rootSpanId: value["rootSpanId"] } : {}
37245
+ } : void 0;
37246
+ }
37247
+ function modelOutput(event) {
37248
+ const content = event.content ?? [];
37249
+ let text = "";
37250
+ const reasoning = [];
37251
+ const toolCalls = [];
37252
+ for (const part of content) {
37253
+ if (part.type === "text") {
37254
+ text += part.text;
37255
+ } else if (part.type === "reasoning" && part.text.trim().length > 0) {
37256
+ reasoning.push({ content: part.text });
37257
+ } else if (part.type === "tool-call") {
37258
+ toolCalls.push({
37259
+ function: {
37260
+ arguments: safeJsonStringify(part.input),
37261
+ name: part.toolName
37262
+ },
37263
+ id: part.callId,
37264
+ type: "function"
37265
+ });
37266
+ }
37267
+ }
37268
+ return [
37269
+ {
37270
+ finish_reason: normalizeFinishReason2(event.finishReason),
37271
+ index: 0,
37272
+ message: {
37273
+ content: text || null,
37274
+ ...reasoning.length > 0 ? { reasoning } : {},
37275
+ role: "assistant",
37276
+ ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
37277
+ }
37278
+ }
37279
+ ];
37280
+ }
37281
+ function usageMetrics(usage) {
37282
+ const promptTokens = nonNegativeNumber(usage.inputTokens);
37283
+ const completionTokens = nonNegativeNumber(usage.outputTokens);
37284
+ const cachedTokens = nonNegativeNumber(
37285
+ usage.inputTokenDetails?.cacheReadTokens
37286
+ );
37287
+ const cacheCreationTokens = nonNegativeNumber(
37288
+ usage.inputTokenDetails?.cacheWriteTokens
37289
+ );
37290
+ return {
37291
+ ...promptTokens !== void 0 ? { prompt_tokens: promptTokens } : {},
37292
+ ...completionTokens !== void 0 ? { completion_tokens: completionTokens } : {},
37293
+ ...promptTokens !== void 0 && completionTokens !== void 0 ? { tokens: promptTokens + completionTokens } : {},
37294
+ ...cachedTokens !== void 0 ? { prompt_cached_tokens: cachedTokens } : {},
37295
+ ...cacheCreationTokens !== void 0 ? { prompt_cache_creation_tokens: cacheCreationTokens } : {}
37296
+ };
37297
+ }
37298
+ function nonNegativeNumber(value) {
37299
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
37300
+ }
37301
+ function finiteTimestamp(value) {
37302
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
37303
+ }
37304
+ function normalizeFinishReason2(value) {
37305
+ if (value === "content-filter") return "content_filter";
37306
+ if (value === "tool-calls") return "tool_calls";
37307
+ return value;
37308
+ }
37309
+ function safeJsonStringify(value) {
37310
+ try {
37311
+ return JSON.stringify(value) ?? "null";
37312
+ } catch {
37313
+ return "null";
37314
+ }
37315
+ }
37316
+ function turnKey3(sessionId, turnId) {
37317
+ return `${sessionId}:${turnId}`;
37318
+ }
37319
+ function turnIdempotencyKey(sessionId, turnId) {
37320
+ return `turn:${sessionId}:${turnId}`;
37321
+ }
37322
+ function actionIdempotencyKey(sessionId, turnId, callId) {
37323
+ return `action:${sessionId}:${turnId}:${callId}`;
37324
+ }
37325
+
37326
+ // src/instrumentation/plugins/eve-instrumentation.ts
37327
+ var EVE_INSTRUMENTATION_PROVIDER = /* @__PURE__ */ Symbol.for("eve.instrumentation.provider");
37328
+ function braintrustEveInstrumentation(options) {
37329
+ const definition = "defineState" in options ? createLegacyEveInstrumentation(options) : createEveInstrumentationProvider(options);
37330
+ const declaration = {
37331
+ ...definition,
37332
+ [EVE_INSTRUMENTATION_PROVIDER]: true
37333
+ };
37334
+ return declaration;
37335
+ }
37336
+
35424
37337
  // src/instrumentation/config.ts
35425
37338
  var envIntegrationAliases = {
35426
37339
  openai: "openai",
@@ -35493,7 +37406,10 @@ var envIntegrationAliases = {
35493
37406
  "langchain-js": "langchain",
35494
37407
  "@langchain": "langchain",
35495
37408
  langgraph: "langgraph",
35496
- langsmith: "langsmith"
37409
+ langsmith: "langsmith",
37410
+ voyage: "voyageai",
37411
+ "voyage-ai": "voyageai",
37412
+ voyageai: "voyageai"
35497
37413
  };
35498
37414
  function getDefaultInstrumentationIntegrations() {
35499
37415
  return {
@@ -35528,6 +37444,7 @@ function getDefaultInstrumentationIntegrations() {
35528
37444
  langchain: true,
35529
37445
  langgraph: true,
35530
37446
  langsmith: true,
37447
+ voyageai: true,
35531
37448
  piCodingAgent: true,
35532
37449
  strandsAgentSDK: true,
35533
37450
  cloudflareAgents: true