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
@@ -699,8 +699,6 @@ function newGlobalTracingChannel(nameOrChannels) {
699
699
  var DefaultAsyncLocalStorage = class {
700
700
  constructor() {
701
701
  }
702
- enterWith(_) {
703
- }
704
702
  run(_, callback) {
705
703
  return callback();
706
704
  }
@@ -2621,7 +2619,10 @@ var AclObjectType = import_v36.z.union([
2621
2619
  "org_member",
2622
2620
  "project_log",
2623
2621
  "org_project",
2624
- "org_audit_logs"
2622
+ "org_audit_logs",
2623
+ "project_group",
2624
+ "ai_secret",
2625
+ "org_ai_secret"
2625
2626
  ]),
2626
2627
  import_v36.z.null()
2627
2628
  ]);
@@ -2750,7 +2751,8 @@ var AsyncScoringState = import_v36.z.union([
2750
2751
  token: import_v36.z.string(),
2751
2752
  function_ids: import_v36.z.array(import_v36.z.unknown()),
2752
2753
  skip_logging: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]).optional(),
2753
- triggered_functions: import_v36.z.union([import_v36.z.record(TriggeredFunctionState), import_v36.z.null()]).optional()
2754
+ triggered_functions: import_v36.z.union([import_v36.z.record(TriggeredFunctionState), import_v36.z.null()]).optional(),
2755
+ last_triggered_xact_id: import_v36.z.union([import_v36.z.string(), import_v36.z.number(), import_v36.z.null()]).optional()
2754
2756
  }),
2755
2757
  import_v36.z.object({ status: import_v36.z.literal("disabled") }),
2756
2758
  import_v36.z.null(),
@@ -2819,7 +2821,7 @@ var FunctionTypeEnum = import_v36.z.enum([
2819
2821
  "parameters",
2820
2822
  "sandbox"
2821
2823
  ]);
2822
- var NullableSavedFunctionId = import_v36.z.union([
2824
+ var FacetPreprocessorId = import_v36.z.union([
2823
2825
  import_v36.z.object({
2824
2826
  type: import_v36.z.literal("function"),
2825
2827
  id: import_v36.z.string(),
@@ -2830,10 +2832,23 @@ var NullableSavedFunctionId = import_v36.z.union([
2830
2832
  name: import_v36.z.string(),
2831
2833
  function_type: FunctionTypeEnum.optional().default("scorer")
2832
2834
  }),
2835
+ import_v36.z.object({ type: import_v36.z.literal("inline"), code: import_v36.z.string().min(1) }),
2833
2836
  import_v36.z.null()
2834
2837
  ]);
2838
+ var SavedFunctionId = import_v36.z.union([
2839
+ import_v36.z.object({
2840
+ type: import_v36.z.literal("function"),
2841
+ id: import_v36.z.string(),
2842
+ version: import_v36.z.string().optional()
2843
+ }),
2844
+ import_v36.z.object({
2845
+ type: import_v36.z.literal("global"),
2846
+ name: import_v36.z.string(),
2847
+ function_type: FunctionTypeEnum.optional().default("scorer")
2848
+ })
2849
+ ]);
2835
2850
  var TopicMapGenerationSettings = import_v36.z.object({
2836
- algorithm: import_v36.z.enum(["hdbscan", "kmeans"]),
2851
+ algorithm: import_v36.z.enum(["hdbscan", "kmeans", "community"]),
2837
2852
  dimension_reduction: import_v36.z.enum(["umap", "pca", "none"]),
2838
2853
  sample_size: import_v36.z.number().int().gt(0).optional(),
2839
2854
  n_clusters: import_v36.z.number().int().gt(0).optional(),
@@ -2845,6 +2860,7 @@ var TopicMapGenerationSettings = import_v36.z.object({
2845
2860
  var TopicMapData = import_v36.z.object({
2846
2861
  type: import_v36.z.literal("topic_map"),
2847
2862
  source_facet: import_v36.z.string(),
2863
+ source_facet_function: SavedFunctionId.and(import_v36.z.unknown()).optional(),
2848
2864
  embedding_model: import_v36.z.string(),
2849
2865
  bundle_key: import_v36.z.string().optional(),
2850
2866
  report_key: import_v36.z.string().optional(),
@@ -2858,7 +2874,7 @@ var TopicMapData = import_v36.z.object({
2858
2874
  });
2859
2875
  var BatchedFacetData = import_v36.z.object({
2860
2876
  type: import_v36.z.literal("batched_facet"),
2861
- preprocessor: NullableSavedFunctionId.and(import_v36.z.unknown()).optional(),
2877
+ preprocessor: FacetPreprocessorId.optional(),
2862
2878
  facets: import_v36.z.array(
2863
2879
  import_v36.z.object({
2864
2880
  name: import_v36.z.string(),
@@ -3119,18 +3135,6 @@ var ObjectReferenceNullish = import_v36.z.union([
3119
3135
  }),
3120
3136
  import_v36.z.null()
3121
3137
  ]);
3122
- var SavedFunctionId = import_v36.z.union([
3123
- import_v36.z.object({
3124
- type: import_v36.z.literal("function"),
3125
- id: import_v36.z.string(),
3126
- version: import_v36.z.string().optional()
3127
- }),
3128
- import_v36.z.object({
3129
- type: import_v36.z.literal("global"),
3130
- name: import_v36.z.string(),
3131
- function_type: FunctionTypeEnum.optional().default("scorer")
3132
- })
3133
- ]);
3134
3138
  var DatasetEvent = import_v36.z.object({
3135
3139
  id: import_v36.z.string(),
3136
3140
  _xact_id: import_v36.z.string(),
@@ -3352,7 +3356,7 @@ var ExtendedSavedFunctionId = import_v36.z.union([
3352
3356
  ]);
3353
3357
  var FacetData = import_v36.z.object({
3354
3358
  type: import_v36.z.literal("facet"),
3355
- preprocessor: NullableSavedFunctionId.and(import_v36.z.unknown()).optional(),
3359
+ preprocessor: FacetPreprocessorId.optional(),
3356
3360
  prompt: import_v36.z.string(),
3357
3361
  model: import_v36.z.string().optional(),
3358
3362
  embedding_model: import_v36.z.string().optional(),
@@ -3451,7 +3455,7 @@ var PromptParserNullish = import_v36.z.union([
3451
3455
  }),
3452
3456
  import_v36.z.null()
3453
3457
  ]);
3454
- var PreprocessorSavedFunctionId = import_v36.z.union([
3458
+ var PreprocessorId = import_v36.z.union([
3455
3459
  import_v36.z.object({
3456
3460
  type: import_v36.z.literal("function"),
3457
3461
  id: import_v36.z.string(),
@@ -3462,6 +3466,7 @@ var PreprocessorSavedFunctionId = import_v36.z.union([
3462
3466
  name: import_v36.z.string(),
3463
3467
  function_type: import_v36.z.literal("preprocessor").optional().default("preprocessor")
3464
3468
  }),
3469
+ import_v36.z.object({ type: import_v36.z.literal("inline"), code: import_v36.z.string().min(1) }),
3465
3470
  import_v36.z.null()
3466
3471
  ]);
3467
3472
  var PromptDataNullish = import_v36.z.union([
@@ -3469,7 +3474,7 @@ var PromptDataNullish = import_v36.z.union([
3469
3474
  prompt: PromptBlockDataNullish,
3470
3475
  options: PromptOptionsNullish,
3471
3476
  parser: PromptParserNullish,
3472
- preprocessor: PreprocessorSavedFunctionId,
3477
+ preprocessor: PreprocessorId,
3473
3478
  tool_functions: import_v36.z.union([import_v36.z.array(SavedFunctionId), import_v36.z.null()]),
3474
3479
  template_format: import_v36.z.union([
3475
3480
  import_v36.z.enum(["mustache", "nunjucks", "none"]),
@@ -3671,7 +3676,7 @@ var PromptData = import_v36.z.object({
3671
3676
  prompt: PromptBlockDataNullish,
3672
3677
  options: PromptOptionsNullish,
3673
3678
  parser: PromptParserNullish,
3674
- preprocessor: PreprocessorSavedFunctionId,
3679
+ preprocessor: PreprocessorId,
3675
3680
  tool_functions: import_v36.z.union([import_v36.z.array(SavedFunctionId), import_v36.z.null()]),
3676
3681
  template_format: import_v36.z.union([
3677
3682
  import_v36.z.enum(["mustache", "nunjucks", "none"]),
@@ -3857,6 +3862,19 @@ var MessageRole = import_v36.z.enum([
3857
3862
  "model",
3858
3863
  "developer"
3859
3864
  ]);
3865
+ var NullableSavedFunctionId = import_v36.z.union([
3866
+ import_v36.z.object({
3867
+ type: import_v36.z.literal("function"),
3868
+ id: import_v36.z.string(),
3869
+ version: import_v36.z.string().optional()
3870
+ }),
3871
+ import_v36.z.object({
3872
+ type: import_v36.z.literal("global"),
3873
+ name: import_v36.z.string(),
3874
+ function_type: FunctionTypeEnum.optional().default("scorer")
3875
+ }),
3876
+ import_v36.z.null()
3877
+ ]);
3860
3878
  var ObjectReference = import_v36.z.object({
3861
3879
  object_type: import_v36.z.enum([
3862
3880
  "project_logs",
@@ -3878,6 +3896,7 @@ var TraceScope = import_v36.z.object({
3878
3896
  });
3879
3897
  var OnlineScoreConfig = import_v36.z.union([
3880
3898
  import_v36.z.object({
3899
+ status: AutomationStatus.optional(),
3881
3900
  sampling_rate: import_v36.z.number().gte(0).lte(1),
3882
3901
  scorers: import_v36.z.array(SavedFunctionId),
3883
3902
  btql_filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
@@ -3958,6 +3977,72 @@ var Project = import_v36.z.object({
3958
3977
  user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3959
3978
  settings: ProjectSettings.optional()
3960
3979
  });
3980
+ var WindowedAutomationConfig = import_v36.z.object({
3981
+ event_type: import_v36.z.literal("windowed"),
3982
+ product_origin: import_v36.z.union([import_v36.z.literal("patterns"), import_v36.z.null()]).optional(),
3983
+ status: AutomationStatus.optional(),
3984
+ threshold: import_v36.z.object({
3985
+ calculation: import_v36.z.object({
3986
+ type: import_v36.z.literal("btql"),
3987
+ btql_query: import_v36.z.string().min(1),
3988
+ output: import_v36.z.object({
3989
+ type: import_v36.z.literal("scalar"),
3990
+ value_column: import_v36.z.string().min(1)
3991
+ })
3992
+ }),
3993
+ policy: import_v36.z.object({
3994
+ condition: import_v36.z.object({
3995
+ type: import_v36.z.literal("threshold"),
3996
+ operator: import_v36.z.enum(["lt", "lte", "gt", "gte", "eq", "neq"]),
3997
+ threshold: import_v36.z.number()
3998
+ }),
3999
+ pending_seconds: import_v36.z.number().int().gte(0).lte(2592e3),
4000
+ no_data_behavior: import_v36.z.enum(["keep_last", "resolve", "alert"]),
4001
+ renotify_interval_seconds: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional(),
4002
+ notify_on_recovery: import_v36.z.boolean().optional().default(true)
4003
+ })
4004
+ }).optional(),
4005
+ window: import_v36.z.object({
4006
+ window_seconds: import_v36.z.number().int().gte(1).lte(2592e3),
4007
+ schedule: import_v36.z.union([
4008
+ import_v36.z.object({
4009
+ type: import_v36.z.literal("interval"),
4010
+ evaluation_interval_seconds: import_v36.z.number().int().gte(1).lte(2592e3)
4011
+ }),
4012
+ import_v36.z.object({
4013
+ type: import_v36.z.literal("cron"),
4014
+ cron_expression: import_v36.z.string().min(1),
4015
+ timezone: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
4016
+ })
4017
+ ]),
4018
+ evaluation_delay_seconds: import_v36.z.number().int().gte(0).lte(2592e3)
4019
+ }),
4020
+ loop: import_v36.z.object({
4021
+ prompt: import_v36.z.string().min(1).max(1e4),
4022
+ include_trigger_input: import_v36.z.boolean().optional().default(false),
4023
+ agent_slug: import_v36.z.string().min(1),
4024
+ auto_approve_tools: import_v36.z.array(import_v36.z.string().min(1)).optional().default([]),
4025
+ harness: import_v36.z.enum(["native", "codex", "claude-code"]).optional(),
4026
+ model: import_v36.z.string().min(1).optional(),
4027
+ reasoning_effort: import_v36.z.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional()
4028
+ }).optional(),
4029
+ actions: import_v36.z.array(
4030
+ import_v36.z.union([
4031
+ import_v36.z.object({
4032
+ type: import_v36.z.literal("webhook"),
4033
+ url: import_v36.z.string(),
4034
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
4035
+ }),
4036
+ import_v36.z.object({
4037
+ type: import_v36.z.literal("slack"),
4038
+ workspace_id: import_v36.z.string(),
4039
+ channel: import_v36.z.string(),
4040
+ message_template: import_v36.z.string().optional(),
4041
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
4042
+ })
4043
+ ])
4044
+ ).max(20).optional().default([])
4045
+ });
3961
4046
  var TopicAutomationFacetModel = import_v36.z.union([
3962
4047
  import_v36.z.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
3963
4048
  import_v36.z.null()
@@ -3999,7 +4084,8 @@ var TopicDigestAutomationConfig = import_v36.z.object({
3999
4084
  type: import_v36.z.literal("slack"),
4000
4085
  workspace_id: import_v36.z.string(),
4001
4086
  channel: import_v36.z.string(),
4002
- message_template: import_v36.z.string().optional()
4087
+ message_template: import_v36.z.string().optional(),
4088
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
4003
4089
  }),
4004
4090
  topic_map_function_ids: import_v36.z.array(import_v36.z.string()).max(10).optional()
4005
4091
  });
@@ -4013,15 +4099,21 @@ var ProjectAutomation = import_v36.z.object({
4013
4099
  config: import_v36.z.union([
4014
4100
  import_v36.z.object({
4015
4101
  event_type: import_v36.z.literal("logs"),
4102
+ status: AutomationStatus.optional(),
4016
4103
  btql_filter: import_v36.z.string(),
4017
4104
  interval_seconds: import_v36.z.number().gte(1).lte(2592e3),
4018
4105
  action: import_v36.z.union([
4019
- import_v36.z.object({ type: import_v36.z.literal("webhook"), url: import_v36.z.string() }),
4106
+ import_v36.z.object({
4107
+ type: import_v36.z.literal("webhook"),
4108
+ url: import_v36.z.string(),
4109
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
4110
+ }),
4020
4111
  import_v36.z.object({
4021
4112
  type: import_v36.z.literal("slack"),
4022
4113
  workspace_id: import_v36.z.string(),
4023
4114
  channel: import_v36.z.string(),
4024
- message_template: import_v36.z.string().optional()
4115
+ message_template: import_v36.z.string().optional(),
4116
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
4025
4117
  })
4026
4118
  ])
4027
4119
  }),
@@ -4072,21 +4164,38 @@ var ProjectAutomation = import_v36.z.object({
4072
4164
  }),
4073
4165
  import_v36.z.object({
4074
4166
  event_type: import_v36.z.literal("environment_update"),
4167
+ status: AutomationStatus.optional(),
4075
4168
  environment_filter: import_v36.z.array(import_v36.z.string()).optional(),
4076
4169
  action: import_v36.z.union([
4077
- import_v36.z.object({ type: import_v36.z.literal("webhook"), url: import_v36.z.string() }),
4170
+ import_v36.z.object({
4171
+ type: import_v36.z.literal("webhook"),
4172
+ url: import_v36.z.string(),
4173
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
4174
+ }),
4078
4175
  import_v36.z.object({
4079
4176
  type: import_v36.z.literal("slack"),
4080
4177
  workspace_id: import_v36.z.string(),
4081
4178
  channel: import_v36.z.string(),
4082
- message_template: import_v36.z.string().optional()
4179
+ message_template: import_v36.z.string().optional(),
4180
+ formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
4083
4181
  })
4084
4182
  ])
4085
4183
  }),
4184
+ WindowedAutomationConfig,
4086
4185
  TopicAutomationConfig,
4087
4186
  TopicDigestAutomationConfig
4088
4187
  ])
4089
4188
  });
4189
+ var ProjectGroup = import_v36.z.object({
4190
+ id: import_v36.z.string().uuid(),
4191
+ org_id: import_v36.z.string().uuid(),
4192
+ user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4193
+ created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4194
+ name: import_v36.z.string(),
4195
+ description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4196
+ deleted_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4197
+ member_projects: import_v36.z.array(import_v36.z.string().uuid()).max(1e4)
4198
+ });
4090
4199
  var ProjectLogsEvent = import_v36.z.object({
4091
4200
  id: import_v36.z.string(),
4092
4201
  _xact_id: import_v36.z.string(),
@@ -4304,7 +4413,8 @@ var RunEval = import_v36.z.object({
4304
4413
  dataset_environment: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4305
4414
  _internal_btql: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional()
4306
4415
  }),
4307
- import_v36.z.object({ data: import_v36.z.array(import_v36.z.unknown()) })
4416
+ import_v36.z.object({ data: import_v36.z.array(import_v36.z.unknown()) }),
4417
+ import_v36.z.object({ experiment_name: import_v36.z.string() })
4308
4418
  ]),
4309
4419
  name: import_v36.z.string().optional(),
4310
4420
  parameters: import_v36.z.object({}).partial().passthrough().optional(),
@@ -4509,7 +4619,10 @@ var View = import_v36.z.object({
4509
4619
  "for_review_datasets"
4510
4620
  ]),
4511
4621
  name: import_v36.z.string(),
4622
+ description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4623
+ starred: import_v36.z.boolean().optional(),
4512
4624
  created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4625
+ updated_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4513
4626
  view_data: ViewData.optional(),
4514
4627
  options: ViewOptions.optional(),
4515
4628
  user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
@@ -4597,6 +4710,34 @@ var registerTemplatePlugin = templateRegistry.register.bind(templateRegistry);
4597
4710
  var getTemplateRenderer = templateRegistry.get.bind(templateRegistry);
4598
4711
  registerTemplatePlugin(mustachePlugin);
4599
4712
 
4713
+ // src/template/renderer.ts
4714
+ function isTemplateFormat(v) {
4715
+ return v === "mustache" || v === "nunjucks" || v === "none";
4716
+ }
4717
+ function parseTemplateFormat(value, defaultFormat = "mustache") {
4718
+ return isTemplateFormat(value) ? value : defaultFormat;
4719
+ }
4720
+ function renderTemplateContent(template, variables, escape, options) {
4721
+ const strict = !!options.strict;
4722
+ const templateFormat = parseTemplateFormat(options.templateFormat);
4723
+ if (templateFormat === "none") {
4724
+ return template;
4725
+ }
4726
+ const renderer = getTemplateRenderer(templateFormat);
4727
+ if (!renderer) {
4728
+ if (templateFormat === "nunjucks") {
4729
+ throw new Error(
4730
+ "Nunjucks templating requires @braintrust/template-nunjucks. Install and import it to enable templateFormat: 'nunjucks'."
4731
+ );
4732
+ }
4733
+ throw new Error(`No template renderer registered for ${templateFormat}`);
4734
+ }
4735
+ if (strict && renderer.lint) {
4736
+ renderer.lint(template, variables);
4737
+ }
4738
+ return renderer.render(template, variables, escape, strict);
4739
+ }
4740
+
4600
4741
  // src/logger.ts
4601
4742
  var import_v38 = require("zod/v3");
4602
4743
 
@@ -5181,44 +5322,72 @@ function createCacheLayers({
5181
5322
  }
5182
5323
 
5183
5324
  // src/prompt-cache/prompt-cache.ts
5184
- function createCacheKey(key) {
5325
+ function createCacheKey(key, namespace) {
5326
+ let cacheKey;
5185
5327
  if (key.id) {
5186
- return `id:${key.id}`;
5187
- }
5188
- const prefix = key.projectId ?? key.projectName;
5189
- if (!prefix) {
5190
- throw new Error("Either projectId or projectName must be provided");
5191
- }
5192
- if (!key.slug) {
5193
- throw new Error("Slug must be provided when not using ID");
5328
+ cacheKey = `id:${key.id}`;
5329
+ } else {
5330
+ const prefix = key.projectId ?? key.projectName;
5331
+ if (!prefix) {
5332
+ throw new Error("Either projectId or projectName must be provided");
5333
+ }
5334
+ if (!key.slug) {
5335
+ throw new Error("Slug must be provided when not using ID");
5336
+ }
5337
+ cacheKey = `${prefix}:${key.slug}:${key.version ?? "latest"}`;
5194
5338
  }
5195
- return `${prefix}:${key.slug}:${key.version ?? "latest"}`;
5339
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
5196
5340
  }
5197
- var PromptCache = class {
5341
+ var PromptCache = class _PromptCache {
5198
5342
  memoryCache;
5199
5343
  diskCache;
5344
+ namespace;
5345
+ expectedResolvedOrgIdentity;
5200
5346
  constructor(options) {
5201
5347
  this.memoryCache = options.memoryCache;
5202
5348
  this.diskCache = options.diskCache;
5349
+ this.namespace = options.namespace;
5350
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
5351
+ }
5352
+ /**
5353
+ * Returns a cache view that shares the same storage layers but isolates all
5354
+ * entries under the provided namespace.
5355
+ */
5356
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
5357
+ return new _PromptCache({
5358
+ memoryCache: this.memoryCache,
5359
+ diskCache: this.diskCache,
5360
+ namespace,
5361
+ expectedResolvedOrgIdentity
5362
+ });
5203
5363
  }
5204
5364
  /**
5205
5365
  * Retrieves a prompt from the cache.
5206
5366
  * First checks the in-memory LRU cache, then falls back to checking the disk cache if available.
5207
5367
  */
5208
5368
  async get(key) {
5209
- const cacheKey = createCacheKey(key);
5369
+ const cacheKey = createCacheKey(key, this.namespace);
5210
5370
  if (this.memoryCache) {
5211
- const memoryPrompt = this.memoryCache.get(cacheKey);
5212
- if (memoryPrompt !== void 0) {
5213
- return memoryPrompt;
5371
+ const memoryEntry = this.memoryCache.get(cacheKey);
5372
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
5373
+ return memoryEntry.value;
5214
5374
  }
5215
5375
  }
5216
5376
  if (this.diskCache) {
5217
- const diskPrompt = await this.diskCache.get(cacheKey);
5218
- if (!diskPrompt) {
5377
+ const diskEntry = await this.diskCache.get(cacheKey);
5378
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
5219
5379
  return void 0;
5220
5380
  }
5221
- this.memoryCache?.set(cacheKey, diskPrompt);
5381
+ const serializedPrompt = diskEntry.value;
5382
+ const diskPrompt = new Prompt2(
5383
+ serializedPrompt.metadata,
5384
+ serializedPrompt.defaults,
5385
+ serializedPrompt.noTrace
5386
+ );
5387
+ this.memoryCache?.set(cacheKey, {
5388
+ value: diskPrompt,
5389
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
5390
+ });
5222
5391
  return diskPrompt;
5223
5392
  }
5224
5393
  return void 0;
@@ -5232,58 +5401,91 @@ var PromptCache = class {
5232
5401
  * @throws If there is an error writing to the disk cache.
5233
5402
  */
5234
5403
  async set(key, value) {
5235
- const cacheKey = createCacheKey(key);
5236
- this.memoryCache?.set(cacheKey, value);
5404
+ const cacheKey = createCacheKey(key, this.namespace);
5405
+ const memoryEntry = {
5406
+ value,
5407
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5408
+ };
5409
+ this.memoryCache?.set(cacheKey, memoryEntry);
5237
5410
  if (this.diskCache) {
5238
- await this.diskCache.set(cacheKey, value);
5411
+ await this.diskCache.set(cacheKey, {
5412
+ value: value._internalSerializeForCache(),
5413
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5414
+ });
5239
5415
  }
5240
5416
  }
5241
5417
  };
5242
5418
 
5243
5419
  // src/prompt-cache/parameters-cache.ts
5244
- function createCacheKey2(key) {
5420
+ function createCacheKey2(key, namespace) {
5421
+ let cacheKey;
5245
5422
  if (key.id) {
5246
- return `parameters:id:${key.id}`;
5247
- }
5248
- const prefix = key.projectId ?? key.projectName;
5249
- if (!prefix) {
5250
- throw new Error("Either projectId or projectName must be provided");
5251
- }
5252
- if (!key.slug) {
5253
- throw new Error("Slug must be provided when not using ID");
5423
+ cacheKey = `parameters:id:${key.id}`;
5424
+ } else {
5425
+ const prefix = key.projectId ?? key.projectName;
5426
+ if (!prefix) {
5427
+ throw new Error("Either projectId or projectName must be provided");
5428
+ }
5429
+ if (!key.slug) {
5430
+ throw new Error("Slug must be provided when not using ID");
5431
+ }
5432
+ cacheKey = `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
5254
5433
  }
5255
- return `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
5434
+ return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
5256
5435
  }
5257
- var ParametersCache = class {
5436
+ var ParametersCache = class _ParametersCache {
5258
5437
  memoryCache;
5259
5438
  diskCache;
5439
+ namespace;
5440
+ expectedResolvedOrgIdentity;
5260
5441
  constructor(options) {
5261
5442
  this.memoryCache = options.memoryCache;
5262
5443
  this.diskCache = options.diskCache;
5444
+ this.namespace = options.namespace;
5445
+ this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
5446
+ }
5447
+ withNamespace(namespace, expectedResolvedOrgIdentity) {
5448
+ return new _ParametersCache({
5449
+ memoryCache: this.memoryCache,
5450
+ diskCache: this.diskCache,
5451
+ namespace,
5452
+ expectedResolvedOrgIdentity
5453
+ });
5263
5454
  }
5264
5455
  async get(key) {
5265
- const cacheKey = createCacheKey2(key);
5456
+ const cacheKey = createCacheKey2(key, this.namespace);
5266
5457
  if (this.memoryCache) {
5267
- const memoryParams = this.memoryCache.get(cacheKey);
5268
- if (memoryParams !== void 0) {
5269
- return memoryParams;
5458
+ const memoryEntry = this.memoryCache.get(cacheKey);
5459
+ if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
5460
+ return memoryEntry.value;
5270
5461
  }
5271
5462
  }
5272
5463
  if (this.diskCache) {
5273
- const diskParams = await this.diskCache.get(cacheKey);
5274
- if (!diskParams) {
5464
+ const diskEntry = await this.diskCache.get(cacheKey);
5465
+ if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
5275
5466
  return void 0;
5276
5467
  }
5277
- this.memoryCache?.set(cacheKey, diskParams);
5278
- return diskParams;
5468
+ const diskParameters = new RemoteEvalParameters(diskEntry.value.metadata);
5469
+ this.memoryCache?.set(cacheKey, {
5470
+ value: diskParameters,
5471
+ resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
5472
+ });
5473
+ return diskParameters;
5279
5474
  }
5280
5475
  return void 0;
5281
5476
  }
5282
5477
  async set(key, value) {
5283
- const cacheKey = createCacheKey2(key);
5284
- this.memoryCache?.set(cacheKey, value);
5478
+ const cacheKey = createCacheKey2(key, this.namespace);
5479
+ const memoryEntry = {
5480
+ value,
5481
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5482
+ };
5483
+ this.memoryCache?.set(cacheKey, memoryEntry);
5285
5484
  if (this.diskCache) {
5286
- await this.diskCache.set(cacheKey, value);
5485
+ await this.diskCache.set(cacheKey, {
5486
+ value: value._internalSerializeForCache(),
5487
+ resolvedOrgIdentity: this.expectedResolvedOrgIdentity
5488
+ });
5287
5489
  }
5288
5490
  }
5289
5491
  };
@@ -5587,6 +5789,7 @@ var INSTRUMENTATION_NAMES = {
5587
5789
  CLOUDFLARE_THINK: "cloudflare-think",
5588
5790
  COHERE: "cohere",
5589
5791
  CURSOR_SDK: "cursor-sdk",
5792
+ DEEPSEEK_HARNESS: "deepseek-harness",
5590
5793
  EVE: "eve",
5591
5794
  FLUE: "flue",
5592
5795
  GENKIT: "genkit",
@@ -5606,12 +5809,13 @@ var INSTRUMENTATION_NAMES = {
5606
5809
  OPENROUTER: "openrouter",
5607
5810
  OPENROUTER_AGENT: "openrouter-agent",
5608
5811
  PI_CODING_AGENT: "pi-coding-agent",
5609
- STRANDS_AGENT_SDK: "strands-agent-sdk"
5812
+ STRANDS_AGENT_SDK: "strands-agent-sdk",
5813
+ VOYAGEAI: "voyageai"
5610
5814
  };
5611
5815
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5612
5816
  "braintrust.spanInstrumentationName"
5613
5817
  );
5614
- var SDK_VERSION = true ? "3.27.0" : "0.0.0";
5818
+ var SDK_VERSION = true ? "3.29.0" : "0.0.0";
5615
5819
  function withSpanInstrumentationName(args, instrumentationName) {
5616
5820
  return {
5617
5821
  ...args,
@@ -5730,6 +5934,16 @@ var datasetSnapshotRegisterResponseSchema = import_v38.z.object({
5730
5934
  dataset_snapshot: DatasetSnapshot,
5731
5935
  found_existing: import_v38.z.boolean().optional()
5732
5936
  });
5937
+ var datasetObjectInfoSchema = import_v38.z.object({
5938
+ object_id: import_v38.z.string(),
5939
+ object_name: import_v38.z.string(),
5940
+ parent_cols: import_v38.z.object({
5941
+ project: import_v38.z.object({
5942
+ id: import_v38.z.string(),
5943
+ name: import_v38.z.string()
5944
+ })
5945
+ })
5946
+ });
5733
5947
  var datasetRestorePreviewResultSchema = import_v38.z.object({
5734
5948
  rows_to_restore: import_v38.z.number(),
5735
5949
  rows_to_delete: import_v38.z.number()
@@ -5806,6 +6020,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
5806
6020
  var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
5807
6021
  "braintrust.initial-span-write-as-merge"
5808
6022
  );
6023
+ var RESUME_SPAN_WITHOUT_INITIAL_WRITE = /* @__PURE__ */ Symbol(
6024
+ "braintrust.resume-span-without-initial-write"
6025
+ );
5809
6026
  var INTERNAL_SPAN_CONTEXT = /* @__PURE__ */ Symbol("braintrust.internal-span-context");
5810
6027
  var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
5811
6028
  "braintrust.currentSpanStore"
@@ -5940,12 +6157,53 @@ var loginSchema = import_v38.z.strictObject({
5940
6157
  });
5941
6158
  var stateNonce = 0;
5942
6159
  var V1_PROXY_SUFFIX = "/v1/proxy";
6160
+ var LOADER_LOGIN_CACHE_MAX = 16;
5943
6161
  function normalizeProxyConnUrl(proxyUrl) {
5944
6162
  return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
5945
6163
  }
5946
6164
  var BraintrustState = class _BraintrustState {
6165
+ id;
6166
+ currentExperiment;
6167
+ // Note: the value of IsAsyncFlush doesn't really matter here, since we
6168
+ // (safely) dynamically cast it whenever retrieving the logger.
6169
+ currentLogger;
6170
+ currentParent;
6171
+ currentSpan;
6172
+ // Any time we re-log in, we directly update the apiConn inside the logger.
6173
+ // This is preferable to replacing the whole logger, which would create the
6174
+ // possibility of multiple loggers floating around, which may not log in a
6175
+ // deterministic order.
6176
+ _bgLogger;
6177
+ _overrideBgLogger = null;
6178
+ appUrl = null;
6179
+ appPublicUrl = null;
6180
+ loginToken = null;
6181
+ orgId = null;
6182
+ orgName = null;
6183
+ apiUrl = null;
6184
+ proxyUrl = null;
6185
+ loggedIn = false;
6186
+ gitMetadataSettings;
6187
+ debugLogLevel;
6188
+ debugLogLevelConfigured = false;
6189
+ fetch = globalThis.fetch;
6190
+ _appConn = null;
6191
+ _apiConn = null;
6192
+ _proxyConn = null;
6193
+ promptCache;
6194
+ parametersCache;
6195
+ spanCache;
6196
+ _idGenerator = null;
6197
+ _contextManager = null;
6198
+ _otelFlushCallback = null;
6199
+ spanOriginEnvironment;
6200
+ traceContextSigningSecret;
6201
+ loaderLoginCache = /* @__PURE__ */ new WeakMap();
6202
+ loginParams;
6203
+ activeLoginOrgNameSelector;
5947
6204
  constructor(loginParams) {
5948
- this.loginParams = loginParams;
6205
+ this.loginParams = { ...loginParams };
6206
+ this.activeLoginOrgNameSelector = loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
5949
6207
  this.id = `${(/* @__PURE__ */ new Date()).toLocaleString()}-${stateNonce++}`;
5950
6208
  this.currentExperiment = void 0;
5951
6209
  this.currentLogger = void 0;
@@ -5982,12 +6240,14 @@ var BraintrustState = class _BraintrustState {
5982
6240
  const {
5983
6241
  memoryCache: parametersMemoryCache,
5984
6242
  diskCache: parametersDiskCache
5985
- } = createCacheLayers({
5986
- memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
5987
- diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
5988
- diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
5989
- getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
5990
- });
6243
+ } = createCacheLayers(
6244
+ {
6245
+ memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
6246
+ diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
6247
+ diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
6248
+ getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
6249
+ }
6250
+ );
5991
6251
  this.parametersCache = new ParametersCache({
5992
6252
  memoryCache: parametersMemoryCache,
5993
6253
  diskCache: parametersDiskCache
@@ -5996,43 +6256,6 @@ var BraintrustState = class _BraintrustState {
5996
6256
  this.spanOriginEnvironment = detectSpanOriginEnvironment();
5997
6257
  this._internalSetTraceContextSigningSecret(loginParams.apiKey);
5998
6258
  }
5999
- loginParams;
6000
- id;
6001
- currentExperiment;
6002
- // Note: the value of IsAsyncFlush doesn't really matter here, since we
6003
- // (safely) dynamically cast it whenever retrieving the logger.
6004
- currentLogger;
6005
- currentParent;
6006
- currentSpan;
6007
- // Any time we re-log in, we directly update the apiConn inside the logger.
6008
- // This is preferable to replacing the whole logger, which would create the
6009
- // possibility of multiple loggers floating around, which may not log in a
6010
- // deterministic order.
6011
- _bgLogger;
6012
- _overrideBgLogger = null;
6013
- appUrl = null;
6014
- appPublicUrl = null;
6015
- loginToken = null;
6016
- orgId = null;
6017
- orgName = null;
6018
- apiUrl = null;
6019
- proxyUrl = null;
6020
- loggedIn = false;
6021
- gitMetadataSettings;
6022
- debugLogLevel;
6023
- debugLogLevelConfigured = false;
6024
- fetch = globalThis.fetch;
6025
- _appConn = null;
6026
- _apiConn = null;
6027
- _proxyConn = null;
6028
- promptCache;
6029
- parametersCache;
6030
- spanCache;
6031
- _idGenerator = null;
6032
- _contextManager = null;
6033
- _otelFlushCallback = null;
6034
- spanOriginEnvironment;
6035
- traceContextSigningSecret;
6036
6259
  /** @internal */
6037
6260
  _internalSetTraceContextSigningSecret(secret) {
6038
6261
  const normalizedSecret = secret?.trim();
@@ -6057,6 +6280,101 @@ var BraintrustState = class _BraintrustState {
6057
6280
  this._appConn = null;
6058
6281
  this._apiConn = null;
6059
6282
  this._proxyConn = null;
6283
+ this.loaderLoginCache = /* @__PURE__ */ new WeakMap();
6284
+ }
6285
+ /** @internal */
6286
+ async _internalResolveLoaderLoginOptions({
6287
+ apiKey,
6288
+ appUrl,
6289
+ orgName,
6290
+ fetch: fetch2,
6291
+ forceLogin
6292
+ }) {
6293
+ const resolvedAppUrl = appUrl ?? (this.loggedIn ? this.appUrl ?? void 0 : void 0) ?? this.loginParams.appUrl ?? isomorph_default.getEnv("BRAINTRUST_APP_URL") ?? "https://www.braintrust.dev";
6294
+ const resolvedApiKey = apiKey ?? (this.loggedIn ? this.loginToken ?? void 0 : void 0) ?? this.loginParams.apiKey ?? await isomorph_default.getBraintrustApiKey();
6295
+ if (!resolvedApiKey) {
6296
+ throw new Error(
6297
+ "Please specify an api key (e.g. by setting BRAINTRUST_API_KEY)."
6298
+ );
6299
+ }
6300
+ const normalizedApiKey = HTTPConnection.sanitize_token(resolvedApiKey);
6301
+ const usesActiveCredential = this.loggedIn && normalizedApiKey === this.loginToken;
6302
+ const requestedOrgName = orgName ?? (usesActiveCredential ? this.activeLoginOrgNameSelector : void 0) ?? this.loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
6303
+ const resolvedOrgName = orgName ?? (usesActiveCredential ? this.orgName ?? void 0 : void 0) ?? requestedOrgName;
6304
+ const resolvedFetch = fetch2 ?? (this.loggedIn ? this.fetch : void 0) ?? this.loginParams.fetch ?? globalThis.fetch;
6305
+ const credentialCacheNamespace = JSON.stringify([
6306
+ "loader-credential",
6307
+ resolvedAppUrl,
6308
+ requestedOrgName,
6309
+ normalizedApiKey
6310
+ ]);
6311
+ return {
6312
+ apiKey: normalizedApiKey,
6313
+ appUrl: resolvedAppUrl,
6314
+ orgName: resolvedOrgName,
6315
+ fetch: resolvedFetch,
6316
+ forceLogin,
6317
+ credentialCacheNamespace,
6318
+ existingState: !forceLogin && usesActiveCredential && resolvedAppUrl === this.appUrl && resolvedOrgName === this.orgName && resolvedFetch === this.fetch ? this : void 0
6319
+ };
6320
+ }
6321
+ /** @internal */
6322
+ _internalGetLoaderCacheViews(loginOptions, requestState) {
6323
+ const expectedResolvedOrgIdentity = requestState?.orgId && requestState.appUrl ? JSON.stringify([
6324
+ "loader-org",
6325
+ requestState.appUrl,
6326
+ requestState.orgId
6327
+ ]) : void 0;
6328
+ return {
6329
+ promptCache: this.promptCache.withNamespace(
6330
+ loginOptions.credentialCacheNamespace,
6331
+ expectedResolvedOrgIdentity
6332
+ ),
6333
+ parametersCache: this.parametersCache.withNamespace(
6334
+ loginOptions.credentialCacheNamespace,
6335
+ expectedResolvedOrgIdentity
6336
+ )
6337
+ };
6338
+ }
6339
+ /** @internal */
6340
+ async _internalGetLoaderState({
6341
+ apiKey,
6342
+ appUrl,
6343
+ orgName,
6344
+ fetch: fetch2,
6345
+ forceLogin,
6346
+ existingState
6347
+ }) {
6348
+ if (existingState) {
6349
+ return existingState;
6350
+ }
6351
+ let cache = this.loaderLoginCache.get(fetch2);
6352
+ if (!cache) {
6353
+ cache = new LRUCache({ max: LOADER_LOGIN_CACHE_MAX });
6354
+ this.loaderLoginCache.set(fetch2, cache);
6355
+ }
6356
+ const cacheKey = JSON.stringify([appUrl, orgName, apiKey]);
6357
+ if (!forceLogin) {
6358
+ const cachedState = cache.get(cacheKey);
6359
+ if (cachedState) {
6360
+ return cachedState;
6361
+ }
6362
+ }
6363
+ const statePromise = loginToLoaderRequestState({
6364
+ orgName,
6365
+ apiKey,
6366
+ appUrl,
6367
+ fetch: fetch2
6368
+ });
6369
+ cache.set(cacheKey, statePromise);
6370
+ try {
6371
+ return await statePromise;
6372
+ } catch (error) {
6373
+ if (cache.get(cacheKey) === statePromise) {
6374
+ cache.delete(cacheKey);
6375
+ }
6376
+ throw error;
6377
+ }
6060
6378
  }
6061
6379
  resetIdGenState() {
6062
6380
  this._idGenerator = null;
@@ -6105,6 +6423,8 @@ var BraintrustState = class _BraintrustState {
6105
6423
  this.debugLogLevel = other.debugLogLevel;
6106
6424
  this.debugLogLevelConfigured = other.debugLogLevelConfigured;
6107
6425
  this.traceContextSigningSecret = other.traceContextSigningSecret;
6426
+ this.fetch = other.fetch;
6427
+ this.activeLoginOrgNameSelector = other.activeLoginOrgNameSelector;
6108
6428
  setGlobalDebugLogLevel(
6109
6429
  this.debugLogLevelConfigured ? this.debugLogLevel ?? false : void 0
6110
6430
  );
@@ -6299,36 +6619,76 @@ var FailedHTTPResponse = class extends Error {
6299
6619
  status;
6300
6620
  text;
6301
6621
  data;
6302
- constructor(status, text, data) {
6622
+ cause;
6623
+ constructor(status, text, data, cause) {
6303
6624
  super(`${status}: ${text} (${data})`);
6304
6625
  this.status = status;
6305
6626
  this.text = text;
6306
6627
  this.data = data;
6628
+ this.cause = cause;
6629
+ }
6630
+ };
6631
+ var HTTPTransportError = class extends Error {
6632
+ cause;
6633
+ constructor(cause) {
6634
+ super(cause instanceof Error ? cause.message : String(cause));
6635
+ this.name = "HTTPTransportError";
6636
+ this.cause = cause;
6307
6637
  }
6308
6638
  };
6639
+ var httpTransportErrorCauses = /* @__PURE__ */ new WeakSet();
6640
+ function recordHTTPTransportError(error) {
6641
+ if (typeof error === "object" && error !== null || typeof error === "function") {
6642
+ httpTransportErrorCauses.add(error);
6643
+ }
6644
+ }
6645
+ function rethrowHTTPTransportError(error, classifyTransportErrors) {
6646
+ if (classifyTransportErrors) {
6647
+ throw new HTTPTransportError(error);
6648
+ }
6649
+ recordHTTPTransportError(error);
6650
+ throw error;
6651
+ }
6652
+ async function readJSONResponse(response, classifyTransportErrors = false) {
6653
+ let data;
6654
+ try {
6655
+ data = await response.text();
6656
+ } catch (error) {
6657
+ rethrowHTTPTransportError(error, classifyTransportErrors);
6658
+ }
6659
+ return JSON.parse(data);
6660
+ }
6309
6661
  async function checkResponse(resp) {
6310
6662
  if (resp.ok) {
6311
6663
  return resp;
6312
- } else {
6664
+ }
6665
+ let data;
6666
+ try {
6667
+ data = await resp.text();
6668
+ } catch (error) {
6313
6669
  throw new FailedHTTPResponse(
6314
6670
  resp.status,
6315
6671
  resp.statusText,
6316
- await resp.text()
6672
+ "Unable to read response body",
6673
+ error
6317
6674
  );
6318
6675
  }
6676
+ throw new FailedHTTPResponse(resp.status, resp.statusText, data);
6319
6677
  }
6320
6678
  var HTTPConnection = class _HTTPConnection {
6321
- base_url;
6322
- token;
6323
- headers;
6324
- fetch;
6325
- constructor(base_url, fetch2) {
6679
+ constructor(base_url, fetch2, classifyTransportErrors = false) {
6680
+ this.classifyTransportErrors = classifyTransportErrors;
6326
6681
  this.base_url = base_url;
6327
6682
  this.token = null;
6328
6683
  this.headers = {};
6329
6684
  this._reset();
6330
6685
  this.fetch = fetch2;
6331
6686
  }
6687
+ classifyTransportErrors;
6688
+ base_url;
6689
+ token;
6690
+ headers;
6691
+ fetch;
6332
6692
  setFetch(fetch2) {
6333
6693
  this.fetch = fetch2;
6334
6694
  }
@@ -6368,9 +6728,9 @@ var HTTPConnection = class _HTTPConnection {
6368
6728
  ).toString();
6369
6729
  const this_fetch = this.fetch;
6370
6730
  const this_headers = this.headers;
6371
- return await checkResponse(
6372
- // Using toString() here makes it work with isomorphic fetch
6373
- await this_fetch(url.toString(), {
6731
+ let response;
6732
+ try {
6733
+ response = await this_fetch(url.toString(), {
6374
6734
  headers: {
6375
6735
  Accept: "application/json",
6376
6736
  ...this_headers,
@@ -6378,8 +6738,14 @@ var HTTPConnection = class _HTTPConnection {
6378
6738
  },
6379
6739
  keepalive: true,
6380
6740
  ...rest
6381
- })
6382
- );
6741
+ });
6742
+ } catch (error) {
6743
+ if (config?.signal?.aborted) {
6744
+ throw getAbortReason(config.signal);
6745
+ }
6746
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
6747
+ }
6748
+ return await checkResponse(response);
6383
6749
  }
6384
6750
  async post(path, params, config, retries = 0) {
6385
6751
  const { headers, ...rest } = config || {};
@@ -6389,8 +6755,9 @@ var HTTPConnection = class _HTTPConnection {
6389
6755
  const tries = retries + 1;
6390
6756
  for (let i = 0; i < tries; i++) {
6391
6757
  try {
6392
- return await checkResponse(
6393
- await this_fetch(_urljoin(this_base_url, path), {
6758
+ let response;
6759
+ try {
6760
+ response = await this_fetch(_urljoin(this_base_url, path), {
6394
6761
  method: "POST",
6395
6762
  headers: {
6396
6763
  Accept: "application/json",
@@ -6401,8 +6768,14 @@ var HTTPConnection = class _HTTPConnection {
6401
6768
  body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
6402
6769
  keepalive: true,
6403
6770
  ...rest
6404
- })
6405
- );
6771
+ });
6772
+ } catch (error) {
6773
+ if (config?.signal?.aborted) {
6774
+ throw getAbortReason(config.signal);
6775
+ }
6776
+ rethrowHTTPTransportError(error, this.classifyTransportErrors);
6777
+ }
6778
+ return await checkResponse(response);
6406
6779
  } catch (error) {
6407
6780
  if (config?.signal?.aborted) {
6408
6781
  throw getAbortReason(config.signal);
@@ -6427,7 +6800,7 @@ var HTTPConnection = class _HTTPConnection {
6427
6800
  for (let i = 0; i < tries; i++) {
6428
6801
  try {
6429
6802
  const resp = await this.get(`${object_type}`, args);
6430
- return await resp.json();
6803
+ return await readJSONResponse(resp, this.classifyTransportErrors);
6431
6804
  } catch (e) {
6432
6805
  if (i < tries - 1) {
6433
6806
  debugLogger.debug(
@@ -6450,7 +6823,7 @@ var HTTPConnection = class _HTTPConnection {
6450
6823
  const resp = await this.post(`${object_type}`, args, {
6451
6824
  headers: { "Content-Type": "application/json" }
6452
6825
  });
6453
- return await resp.json();
6826
+ return await readJSONResponse(resp, this.classifyTransportErrors);
6454
6827
  }
6455
6828
  // Custom inspect for Node.js console.log
6456
6829
  [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
@@ -8005,6 +8378,52 @@ function initLogger(options = {}) {
8005
8378
  }
8006
8379
  return ret;
8007
8380
  }
8381
+ async function loginToLoaderRequestState({
8382
+ appUrl,
8383
+ apiKey,
8384
+ orgName,
8385
+ fetch: fetch2
8386
+ }) {
8387
+ let orgId;
8388
+ let apiUrl;
8389
+ if (apiKey === TEST_API_KEY) {
8390
+ orgId = "test-org-id";
8391
+ apiUrl = "https://braintrust.dev/fake-api-url";
8392
+ } else {
8393
+ let loginResponse;
8394
+ try {
8395
+ loginResponse = await fetch2(_urljoin(appUrl, `/api/apikey/login`), {
8396
+ method: "POST",
8397
+ headers: {
8398
+ "Content-Type": "application/json",
8399
+ Authorization: `Bearer ${apiKey}`
8400
+ }
8401
+ });
8402
+ } catch (error) {
8403
+ throw new HTTPTransportError(error);
8404
+ }
8405
+ const info = await readJSONResponse(
8406
+ await checkResponse(loginResponse),
8407
+ true
8408
+ );
8409
+ const org = selectLoginOrg(info.org_info, orgName);
8410
+ orgId = org.id;
8411
+ apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
8412
+ if (!apiUrl) {
8413
+ throw new Error(
8414
+ 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."
8415
+ );
8416
+ }
8417
+ }
8418
+ const apiConnection = new HTTPConnection(apiUrl, fetch2, true);
8419
+ apiConnection.set_token(apiKey);
8420
+ apiConnection.make_long_lived();
8421
+ return {
8422
+ appUrl,
8423
+ orgId,
8424
+ apiConn: () => apiConnection
8425
+ };
8426
+ }
8008
8427
  async function loginToState(options = {}) {
8009
8428
  const {
8010
8429
  appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
@@ -8036,16 +8455,18 @@ async function loginToState(options = {}) {
8036
8455
  _saveOrgInfo(state, testOrgInfo, testOrgInfo[0].name);
8037
8456
  return state;
8038
8457
  } else {
8039
- const resp = await checkResponse(
8040
- await fetch2(_urljoin(state.appUrl, `/api/apikey/login`), {
8458
+ const loginResponse = await fetch2(
8459
+ _urljoin(state.appUrl, `/api/apikey/login`),
8460
+ {
8041
8461
  method: "POST",
8042
8462
  headers: {
8043
8463
  "Content-Type": "application/json",
8044
8464
  Authorization: `Bearer ${apiKey}`
8045
8465
  }
8046
- })
8466
+ }
8047
8467
  );
8048
- const info = await resp.json();
8468
+ const resp = await checkResponse(loginResponse);
8469
+ const info = await readJSONResponse(resp);
8049
8470
  _saveOrgInfo(state, info.org_info, orgName);
8050
8471
  if (!state.apiUrl) {
8051
8472
  if (orgName) {
@@ -8413,27 +8834,28 @@ function withCurrent(span, callback, state = void 0) {
8413
8834
  const currentState = state ?? _globalState;
8414
8835
  return currentState.contextManager.runInContext(span, () => callback(span));
8415
8836
  }
8416
- function _saveOrgInfo(state, org_info, org_name) {
8417
- if (org_info.length === 0) {
8837
+ function _saveOrgInfo(state, orgInfo, orgName) {
8838
+ const org = selectLoginOrg(orgInfo, orgName);
8839
+ state.orgId = org.id;
8840
+ state.orgName = org.name;
8841
+ state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
8842
+ state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
8843
+ state.gitMetadataSettings = org.git_metadata || void 0;
8844
+ }
8845
+ function selectLoginOrg(orgInfo, orgName) {
8846
+ if (orgInfo.length === 0) {
8418
8847
  throw new LoginInvalidOrgError(
8419
8848
  "This user is not part of any organizations."
8420
8849
  );
8421
8850
  }
8422
- for (const org of org_info) {
8423
- if (org_name === void 0 || org.name === org_name) {
8424
- state.orgId = org.id;
8425
- state.orgName = org.name;
8426
- state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
8427
- state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
8428
- state.gitMetadataSettings = org.git_metadata || void 0;
8429
- break;
8851
+ for (const org of orgInfo) {
8852
+ if (orgName === void 0 || org.name === orgName) {
8853
+ return org;
8430
8854
  }
8431
8855
  }
8432
- if (state.orgId === void 0) {
8433
- throw new LoginInvalidOrgError(
8434
- `Organization ${org_name} not found. Must be one of ${org_info.map((x) => x.name).join(", ")}`
8435
- );
8436
- }
8856
+ throw new LoginInvalidOrgError(
8857
+ `Organization ${orgName} not found. Must be one of ${orgInfo.map((org) => org.name).join(", ")}`
8858
+ );
8437
8859
  }
8438
8860
  function validateTags(tags) {
8439
8861
  const seen = /* @__PURE__ */ new Set();
@@ -8598,6 +9020,19 @@ function enrichAttachments(event, state) {
8598
9020
  }
8599
9021
  return event;
8600
9022
  }
9023
+ async function resolveAttachmentsToBase64(event, state) {
9024
+ for (const [key, value] of Object.entries(event)) {
9025
+ if (value instanceof ReadonlyAttachment) {
9026
+ event[key] = await value.asBase64Url();
9027
+ continue;
9028
+ }
9029
+ if (!(value instanceof Object)) {
9030
+ continue;
9031
+ }
9032
+ await resolveAttachmentsToBase64(value, state);
9033
+ }
9034
+ return event;
9035
+ }
8601
9036
  function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
8602
9037
  if ("input" in event && !isEmpty2(event.input) && "inputs" in event && !isEmpty2(event.inputs) || !("input" in event) && !("inputs" in event)) {
8603
9038
  throw new Error(
@@ -8655,7 +9090,7 @@ var ObjectFetcher = class {
8655
9090
  const objectId = await this.id;
8656
9091
  const batchLimit = batchSize ?? DEFAULT_FETCH_BATCH_SIZE;
8657
9092
  const internalLimit = getInternalBtqlLimit(this._internal_btql);
8658
- const limit = batchSize !== void 0 ? batchSize : internalLimit ?? batchLimit;
9093
+ let remainingLimit = internalLimit;
8659
9094
  const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
8660
9095
  Object.entries(this._internal_btql ?? {}).filter(
8661
9096
  ([key]) => key !== "cursor" && key !== "limit" && key !== "select" && key !== "from"
@@ -8664,6 +9099,10 @@ var ObjectFetcher = class {
8664
9099
  let cursor = void 0;
8665
9100
  let iterations = 0;
8666
9101
  while (true) {
9102
+ if (remainingLimit !== void 0 && remainingLimit <= 0) {
9103
+ return;
9104
+ }
9105
+ const limit = remainingLimit === void 0 ? batchLimit : Math.min(batchLimit, remainingLimit);
8667
9106
  const resp = await state.apiConn().post(
8668
9107
  `btql`,
8669
9108
  {
@@ -8703,7 +9142,14 @@ var ObjectFetcher = class {
8703
9142
  const respJson = await resp.json();
8704
9143
  const mutate = this.mutateRecord;
8705
9144
  for (const record of respJson.data ?? []) {
8706
- yield mutate ? mutate(record) : record;
9145
+ if (remainingLimit !== void 0 && remainingLimit <= 0) {
9146
+ return;
9147
+ }
9148
+ const mutatedRecord = mutate ? mutate(record) : record;
9149
+ if (remainingLimit !== void 0) {
9150
+ remainingLimit--;
9151
+ }
9152
+ yield mutatedRecord;
8707
9153
  }
8708
9154
  if (!respJson.cursor) {
8709
9155
  break;
@@ -9180,7 +9626,9 @@ var SpanImpl = class _SpanImpl {
9180
9626
  this._rootSpanId = resolvedIds.rootSpanId;
9181
9627
  this._spanParents = resolvedIds.spanParents;
9182
9628
  this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
9183
- this.logInternal({ event, internalData });
9629
+ if (!args[RESUME_SPAN_WITHOUT_INITIAL_WRITE]) {
9630
+ this.logInternal({ event, internalData });
9631
+ }
9184
9632
  this.isMerge = true;
9185
9633
  }
9186
9634
  getParentInfo() {
@@ -9874,6 +10322,473 @@ var Dataset2 = class extends ObjectFetcher {
9874
10322
  return typeof data === "object" && data !== null && "__braintrust_dataset_marker" in data;
9875
10323
  }
9876
10324
  };
10325
+ function isAttachmentObject(value) {
10326
+ return BraintrustAttachmentReference.safeParse(value).success || InlineAttachmentReferenceSchema.safeParse(value).success || ExternalAttachmentReference.safeParse(value).success;
10327
+ }
10328
+ function isURL(url) {
10329
+ try {
10330
+ const parsedUrl = new URL(url.trim());
10331
+ return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";
10332
+ } catch {
10333
+ return false;
10334
+ }
10335
+ }
10336
+ function expandAttachmentArrayPreTemplate(content, variables) {
10337
+ if (typeof content !== "string") return null;
10338
+ const match = content.match(/^\{\{\s*([\w.]+)\s*\}\}$/);
10339
+ if (!match) return null;
10340
+ const varPath = match[1];
10341
+ const value = varPath.includes(".") ? getObjValueByPath(variables, varPath.split(".")) : variables[varPath];
10342
+ if (!Array.isArray(value)) return null;
10343
+ const allValid = value.every(
10344
+ (v) => isAttachmentObject(v) || typeof v === "string" && isURL(v)
10345
+ );
10346
+ if (!allValid) return null;
10347
+ return value.map((item) => ({
10348
+ type: "image_url",
10349
+ image_url: { url: item }
10350
+ }));
10351
+ }
10352
+ function renderMessageImpl(render, message, variables) {
10353
+ return {
10354
+ ...message,
10355
+ ..."content" in message ? {
10356
+ content: isEmpty2(message.content) ? void 0 : typeof message.content === "string" ? render(message.content) : message.content.flatMap((c) => {
10357
+ switch (c.type) {
10358
+ case "text":
10359
+ return [{ ...c, text: render(c.text) }];
10360
+ case "image_url":
10361
+ if (isObject(c.image_url.url)) {
10362
+ throw new Error(
10363
+ "Attachments must be replaced with URLs before calling `build()`"
10364
+ );
10365
+ }
10366
+ if (variables) {
10367
+ const expanded = expandAttachmentArrayPreTemplate(
10368
+ c.image_url.url,
10369
+ variables
10370
+ );
10371
+ if (expanded) {
10372
+ return expanded;
10373
+ }
10374
+ }
10375
+ return [
10376
+ {
10377
+ ...c,
10378
+ image_url: {
10379
+ ...c.image_url,
10380
+ url: render(c.image_url.url)
10381
+ }
10382
+ }
10383
+ ];
10384
+ case "file":
10385
+ return [
10386
+ {
10387
+ ...c,
10388
+ file: {
10389
+ ...c.file.file_data && {
10390
+ file_data: render(c.file.file_data)
10391
+ },
10392
+ ...c.file.file_id && {
10393
+ file_id: render(c.file.file_id)
10394
+ },
10395
+ ...c.file.filename && {
10396
+ filename: render(c.file.filename)
10397
+ }
10398
+ }
10399
+ }
10400
+ ];
10401
+ default:
10402
+ const _exhaustiveCheck = c;
10403
+ return _exhaustiveCheck;
10404
+ }
10405
+ })
10406
+ } : {},
10407
+ ..."tool_calls" in message ? {
10408
+ tool_calls: isEmpty2(message.tool_calls) ? void 0 : message.tool_calls.map((t) => {
10409
+ return {
10410
+ type: t.type,
10411
+ id: render(t.id),
10412
+ function: {
10413
+ name: render(t.function.name),
10414
+ arguments: render(t.function.arguments)
10415
+ }
10416
+ };
10417
+ })
10418
+ } : {},
10419
+ ..."tool_call_id" in message ? {
10420
+ tool_call_id: render(message.tool_call_id)
10421
+ } : {}
10422
+ };
10423
+ }
10424
+ function deserializePlainStringAsJSON(s) {
10425
+ if (s.trim() === "") {
10426
+ return { value: null, error: void 0 };
10427
+ }
10428
+ try {
10429
+ return { value: JSON.parse(s), error: void 0 };
10430
+ } catch (e) {
10431
+ return { value: s, error: e };
10432
+ }
10433
+ }
10434
+ function renderTemplatedObject(obj, args, options) {
10435
+ if (typeof obj === "string") {
10436
+ return renderTemplateContent(
10437
+ obj,
10438
+ args,
10439
+ (value) => typeof value === "string" ? value : JSON.stringify(value),
10440
+ {
10441
+ strict: options.strict,
10442
+ templateFormat: options.templateFormat
10443
+ }
10444
+ );
10445
+ } else if (isArray(obj)) {
10446
+ return obj.map((item) => renderTemplatedObject(item, args, options));
10447
+ } else if (isObject(obj)) {
10448
+ return Object.fromEntries(
10449
+ Object.entries(obj).map(([key, value]) => [
10450
+ key,
10451
+ renderTemplatedObject(value, args, options)
10452
+ ])
10453
+ );
10454
+ }
10455
+ return obj;
10456
+ }
10457
+ function renderPromptParams(params, args, options = {}) {
10458
+ const templateFormat = parseTemplateFormat(options.templateFormat);
10459
+ const strict = !!options.strict;
10460
+ const schemaParsed = import_v38.z.object({
10461
+ response_format: import_v38.z.object({
10462
+ type: import_v38.z.literal("json_schema"),
10463
+ json_schema: ResponseFormatJsonSchema.omit({ schema: true }).extend({
10464
+ schema: import_v38.z.unknown()
10465
+ })
10466
+ })
10467
+ }).safeParse(params);
10468
+ if (schemaParsed.success) {
10469
+ const rawSchema = schemaParsed.data.response_format.json_schema.schema;
10470
+ const templatedSchema = renderTemplatedObject(rawSchema, args, {
10471
+ strict,
10472
+ templateFormat
10473
+ });
10474
+ const parsedSchema = typeof templatedSchema === "string" ? deserializePlainStringAsJSON(templatedSchema).value : templatedSchema;
10475
+ return {
10476
+ ...params,
10477
+ response_format: {
10478
+ ...schemaParsed.data.response_format,
10479
+ json_schema: {
10480
+ ...schemaParsed.data.response_format.json_schema,
10481
+ schema: parsedSchema
10482
+ }
10483
+ }
10484
+ };
10485
+ }
10486
+ return params;
10487
+ }
10488
+ var Prompt2 = class _Prompt {
10489
+ constructor(metadata, defaults, noTrace) {
10490
+ this.metadata = metadata;
10491
+ this.defaults = defaults;
10492
+ this.noTrace = noTrace;
10493
+ void this.__braintrust_prompt_marker;
10494
+ }
10495
+ metadata;
10496
+ defaults;
10497
+ noTrace;
10498
+ parsedPromptData;
10499
+ hasParsedPromptData = false;
10500
+ __braintrust_prompt_marker = true;
10501
+ get id() {
10502
+ return this.metadata.id;
10503
+ }
10504
+ get projectId() {
10505
+ return this.metadata.project_id;
10506
+ }
10507
+ get name() {
10508
+ return "name" in this.metadata ? this.metadata.name : `Playground function ${this.metadata.id}`;
10509
+ }
10510
+ get slug() {
10511
+ return "slug" in this.metadata ? this.metadata.slug : this.metadata.id;
10512
+ }
10513
+ get prompt() {
10514
+ return this.getParsedPromptData()?.prompt;
10515
+ }
10516
+ get version() {
10517
+ return this.metadata[TRANSACTION_ID_FIELD];
10518
+ }
10519
+ get options() {
10520
+ return this.getParsedPromptData()?.options || {};
10521
+ }
10522
+ get templateFormat() {
10523
+ return this.getParsedPromptData()?.template_format;
10524
+ }
10525
+ get promptData() {
10526
+ return this.getParsedPromptData();
10527
+ }
10528
+ /**
10529
+ * Build the prompt with the given formatting options. The args you pass in will
10530
+ * be forwarded to the mustache template that defines the prompt and rendered with
10531
+ * the `mustache-js` library.
10532
+ *
10533
+ * @param buildArgs Args to forward along to the prompt template.
10534
+ */
10535
+ build(buildArgs, options = {}) {
10536
+ return this.runBuild(buildArgs, {
10537
+ flavor: options.flavor ?? "chat",
10538
+ messages: options.messages,
10539
+ strict: options.strict,
10540
+ templateFormat: options.templateFormat
10541
+ });
10542
+ }
10543
+ /**
10544
+ * This is a special build method that first resolves attachment references, and then
10545
+ * calls the regular build method. You should use this if you are building prompts from
10546
+ * dataset rows that contain attachments.
10547
+ *
10548
+ * @param buildArgs Args to forward along to the prompt template.
10549
+ */
10550
+ async buildWithAttachments(buildArgs, options = {}) {
10551
+ const hydrated = buildArgs instanceof Object ? await resolveAttachmentsToBase64(buildArgs, options.state) : buildArgs;
10552
+ return this.runBuild(hydrated, {
10553
+ flavor: options.flavor ?? "chat",
10554
+ messages: options.messages,
10555
+ strict: options.strict,
10556
+ templateFormat: options.templateFormat
10557
+ });
10558
+ }
10559
+ runBuild(buildArgs, options) {
10560
+ const { flavor } = options;
10561
+ const params = Object.fromEntries(
10562
+ Object.entries({
10563
+ ...this.defaults,
10564
+ ...Object.fromEntries(
10565
+ Object.entries(this.options.params || {}).filter(
10566
+ ([k, _v]) => !BRAINTRUST_PARAMS.includes(k)
10567
+ )
10568
+ ),
10569
+ ...!isEmpty2(this.options.model) ? {
10570
+ model: this.options.model
10571
+ } : {}
10572
+ }).filter(([key, value]) => key !== "response_format" || value !== null)
10573
+ );
10574
+ if (!("model" in params) || isEmpty2(params.model)) {
10575
+ throw new Error(
10576
+ "No model specified. Either specify it in the prompt or as a default"
10577
+ );
10578
+ }
10579
+ const spanInfo = this.noTrace ? {} : {
10580
+ span_info: {
10581
+ metadata: {
10582
+ prompt: this.id ? {
10583
+ variables: buildArgs,
10584
+ id: this.id,
10585
+ project_id: this.projectId,
10586
+ version: this.version,
10587
+ ..."prompt_session_id" in this.metadata ? { prompt_session_id: this.metadata.prompt_session_id } : {}
10588
+ } : void 0
10589
+ }
10590
+ }
10591
+ };
10592
+ const prompt = this.prompt;
10593
+ if (!prompt) {
10594
+ throw new Error("Empty prompt");
10595
+ }
10596
+ const dictArgParsed = import_v38.z.record(import_v38.z.unknown()).safeParse(buildArgs);
10597
+ const variables = {
10598
+ input: buildArgs,
10599
+ ...dictArgParsed.success ? dictArgParsed.data : {}
10600
+ };
10601
+ const promptDataTemplateFormat = this.templateFormat;
10602
+ const resolvedTemplateFormat = parseTemplateFormat(
10603
+ options.templateFormat ?? promptDataTemplateFormat
10604
+ );
10605
+ const renderedPrompt = _Prompt.renderPrompt({
10606
+ prompt,
10607
+ buildArgs,
10608
+ options: { ...options, templateFormat: resolvedTemplateFormat }
10609
+ });
10610
+ if (flavor === "chat") {
10611
+ if (renderedPrompt.type !== "chat") {
10612
+ throw new Error(
10613
+ "Prompt is a completion prompt. Use buildCompletion() instead"
10614
+ );
10615
+ }
10616
+ return {
10617
+ ...renderPromptParams(params, variables, {
10618
+ strict: options.strict,
10619
+ templateFormat: resolvedTemplateFormat
10620
+ }),
10621
+ ...spanInfo,
10622
+ messages: renderedPrompt.messages,
10623
+ ...renderedPrompt.tools ? {
10624
+ tools: ChatCompletionTool.array().parse(JSON.parse(renderedPrompt.tools))
10625
+ } : void 0
10626
+ };
10627
+ } else if (flavor === "completion") {
10628
+ if (renderedPrompt.type !== "completion") {
10629
+ throw new Error(`Prompt is a chat prompt. Use flavor: 'chat' instead`);
10630
+ }
10631
+ return {
10632
+ ...renderPromptParams(params, variables, {
10633
+ strict: options.strict,
10634
+ templateFormat: resolvedTemplateFormat
10635
+ }),
10636
+ ...spanInfo,
10637
+ prompt: renderedPrompt.content
10638
+ };
10639
+ } else {
10640
+ throw new Error("never!");
10641
+ }
10642
+ }
10643
+ static renderPrompt({
10644
+ prompt,
10645
+ buildArgs,
10646
+ options
10647
+ }) {
10648
+ const escape = (v) => {
10649
+ if (v === void 0) {
10650
+ throw new Error("Missing!");
10651
+ } else if (typeof v === "string") {
10652
+ return v;
10653
+ } else if (v instanceof ReadonlyAttachment) {
10654
+ throw new Error(
10655
+ "Use buildWithAttachments() to build prompts with attachments"
10656
+ );
10657
+ } else {
10658
+ return JSON.stringify(v);
10659
+ }
10660
+ };
10661
+ const dictArgParsed = import_v38.z.record(import_v38.z.unknown()).safeParse(buildArgs);
10662
+ const variables = {
10663
+ input: buildArgs,
10664
+ ...dictArgParsed.success ? dictArgParsed.data : {}
10665
+ };
10666
+ const templateFormat = parseTemplateFormat(options.templateFormat);
10667
+ if (prompt.type === "chat") {
10668
+ const render = (template) => renderTemplateContent(template, variables, escape, {
10669
+ strict: options.strict,
10670
+ templateFormat
10671
+ });
10672
+ const baseMessages = (prompt.messages || []).map(
10673
+ (m) => renderMessageImpl(render, m, variables)
10674
+ );
10675
+ const hasSystemPrompt = baseMessages.some((m) => m.role === "system");
10676
+ const messages = [
10677
+ ...baseMessages,
10678
+ ...(options.messages ?? []).filter(
10679
+ (m) => !(hasSystemPrompt && m.role === "system")
10680
+ )
10681
+ ];
10682
+ return {
10683
+ type: "chat",
10684
+ messages,
10685
+ ...prompt.tools?.trim() ? {
10686
+ tools: render(prompt.tools)
10687
+ } : void 0
10688
+ };
10689
+ } else if (prompt.type === "completion") {
10690
+ if (options.messages) {
10691
+ throw new Error(
10692
+ "extra messages are not supported for completion prompts"
10693
+ );
10694
+ }
10695
+ const content = renderTemplateContent(prompt.content, variables, escape, {
10696
+ strict: options.strict,
10697
+ templateFormat
10698
+ });
10699
+ return {
10700
+ type: "completion",
10701
+ content
10702
+ };
10703
+ } else {
10704
+ const _ = prompt;
10705
+ throw new Error(`Invalid prompt type: ${_}`);
10706
+ }
10707
+ }
10708
+ getParsedPromptData() {
10709
+ if (!this.hasParsedPromptData) {
10710
+ this.parsedPromptData = PromptData.parse(this.metadata.prompt_data);
10711
+ this.hasParsedPromptData = true;
10712
+ }
10713
+ return this.parsedPromptData;
10714
+ }
10715
+ static isPrompt(data) {
10716
+ return typeof data === "object" && data !== null && "__braintrust_prompt_marker" in data;
10717
+ }
10718
+ /** @internal */
10719
+ _internalSerializeForCache() {
10720
+ return {
10721
+ metadata: this.metadata,
10722
+ defaults: this.defaults,
10723
+ noTrace: this.noTrace
10724
+ };
10725
+ }
10726
+ static fromPromptData(name, promptData) {
10727
+ return new _Prompt(
10728
+ {
10729
+ name,
10730
+ slug: name,
10731
+ prompt_data: promptData
10732
+ },
10733
+ {},
10734
+ false
10735
+ );
10736
+ }
10737
+ };
10738
+ var RemoteEvalParameters = class {
10739
+ constructor(metadata) {
10740
+ this.metadata = metadata;
10741
+ void this.__braintrust_parameters_marker;
10742
+ }
10743
+ metadata;
10744
+ __braintrust_parameters_marker = true;
10745
+ get id() {
10746
+ return this.metadata.id;
10747
+ }
10748
+ get projectId() {
10749
+ return this.metadata.project_id;
10750
+ }
10751
+ get name() {
10752
+ return this.metadata.name;
10753
+ }
10754
+ get slug() {
10755
+ return this.metadata.slug;
10756
+ }
10757
+ get version() {
10758
+ return this.metadata[TRANSACTION_ID_FIELD];
10759
+ }
10760
+ get schema() {
10761
+ return this.metadata.function_data.__schema;
10762
+ }
10763
+ get data() {
10764
+ return this.metadata.function_data.data ?? {};
10765
+ }
10766
+ /** @internal */
10767
+ _internalSerializeForCache() {
10768
+ return { metadata: this.metadata };
10769
+ }
10770
+ validate(data) {
10771
+ if (typeof data !== "object" || data === null) {
10772
+ return false;
10773
+ }
10774
+ const schemaProps = this.schema.properties;
10775
+ if (typeof schemaProps !== "object" || schemaProps === null) {
10776
+ return true;
10777
+ }
10778
+ for (const key of Object.keys(schemaProps)) {
10779
+ if (!(key in data)) {
10780
+ const required = Array.isArray(this.schema.required) ? this.schema.required : [];
10781
+ if (required.includes(key)) {
10782
+ return false;
10783
+ }
10784
+ }
10785
+ }
10786
+ return true;
10787
+ }
10788
+ static isParameters(x) {
10789
+ return typeof x === "object" && x !== null && "__braintrust_parameters_marker" in x && x.__braintrust_parameters_marker === true;
10790
+ }
10791
+ };
9877
10792
  var TEST_API_KEY = "___TEST_API_KEY__THIS_IS_NOT_REAL___";
9878
10793
 
9879
10794
  // src/instrumentation/core/channel-tracing-utils.ts
@@ -10319,56 +11234,14 @@ function suppressionStore() {
10319
11234
  autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
10320
11235
  return autoInstrumentationSuppressionStore;
10321
11236
  }
10322
- function currentFrames() {
10323
- return suppressionStore().getStore()?.frames ?? [];
10324
- }
10325
11237
  function isAutoInstrumentationSuppressed() {
10326
- const frames = currentFrames();
10327
- return frames[frames.length - 1]?.mode === "suppress";
11238
+ return suppressionStore().getStore() === true;
10328
11239
  }
10329
11240
  function runWithAutoInstrumentationSuppressed(callback) {
10330
- const frame = {
10331
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
10332
- mode: "suppress"
10333
- };
10334
- return suppressionStore().run(
10335
- { frames: [...currentFrames(), frame] },
10336
- callback
10337
- );
11241
+ return suppressionStore().run(true, callback);
10338
11242
  }
10339
- function bindAutoInstrumentationSuppressionToStart(tracingChannel) {
10340
- const startChannel = tracingChannel.start;
10341
- if (!startChannel) {
10342
- return void 0;
10343
- }
10344
- const store = suppressionStore();
10345
- startChannel.bindStore(store, () => ({
10346
- frames: [
10347
- ...currentFrames(),
10348
- {
10349
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
10350
- mode: "suppress"
10351
- }
10352
- ]
10353
- }));
10354
- return () => {
10355
- startChannel.unbindStore(store);
10356
- };
10357
- }
10358
- function enterAutoInstrumentationAllowed() {
10359
- const frame = {
10360
- id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
10361
- mode: "allow"
10362
- };
10363
- suppressionStore().enterWith({
10364
- frames: [...currentFrames(), frame]
10365
- });
10366
- return () => {
10367
- const frames = currentFrames().filter(
10368
- (candidate) => candidate.id !== frame.id
10369
- );
10370
- suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
10371
- };
11243
+ function runWithAutoInstrumentationAllowed(callback) {
11244
+ return suppressionStore().run(void 0, callback);
10372
11245
  }
10373
11246
 
10374
11247
  // src/instrumentation/core/channel-tracing.ts
@@ -11059,6 +11932,22 @@ function processInputAttachments(input) {
11059
11932
  };
11060
11933
  }
11061
11934
  }
11935
+ 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;
11936
+ const voyageBase64Value = voyageBase64Key ? node[voyageBase64Key] : void 0;
11937
+ if (voyageBase64Key && typeof voyageBase64Value === "string" && voyageBase64Value.startsWith("data:")) {
11938
+ const mediaType = inferMediaTypeFromDataUrl(
11939
+ voyageBase64Value,
11940
+ node.type === "video_base64" ? "video/mp4" : "image/png"
11941
+ );
11942
+ const filename = `${node.type === "video_base64" ? "video" : "image"}.${getExtensionFromMediaType(mediaType)}`;
11943
+ const attachment = toAttachment(voyageBase64Value, mediaType, filename);
11944
+ if (attachment) {
11945
+ return {
11946
+ ...node,
11947
+ [voyageBase64Key]: attachment
11948
+ };
11949
+ }
11950
+ }
11062
11951
  if (node.type === "file" && node.file && typeof node.file === "object" && typeof node.file.file_data === "string" && node.file.file_data.startsWith("data:")) {
11063
11952
  const mediaType = inferMediaTypeFromDataUrl(
11064
11953
  node.file.file_data,
@@ -11641,13 +12530,33 @@ function aggregateChatLogprobs(existing, incoming) {
11641
12530
  }
11642
12531
  return aggregated;
11643
12532
  }
12533
+ function createAggregatedChatChoice(index) {
12534
+ return {
12535
+ index,
12536
+ role: void 0,
12537
+ content: void 0,
12538
+ refusal: void 0,
12539
+ toolCallsByIndex: /* @__PURE__ */ new Map(),
12540
+ logprobs: void 0,
12541
+ finish_reason: void 0
12542
+ };
12543
+ }
12544
+ function toChatChoice(choice) {
12545
+ const toolCalls = Array.from(choice.toolCallsByIndex.entries()).sort(([left], [right]) => left - right).map(([, toolCall]) => toolCall);
12546
+ return {
12547
+ index: choice.index,
12548
+ message: {
12549
+ role: choice.role,
12550
+ content: choice.content,
12551
+ ...choice.refusal !== void 0 ? { refusal: choice.refusal } : {},
12552
+ tool_calls: toolCalls.length > 0 ? toolCalls : void 0
12553
+ },
12554
+ logprobs: choice.logprobs ?? null,
12555
+ finish_reason: choice.finish_reason
12556
+ };
12557
+ }
11644
12558
  function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
11645
- let role = void 0;
11646
- let content = void 0;
11647
- let refusal = void 0;
11648
- let tool_calls = void 0;
11649
- let logprobs = void 0;
11650
- let finish_reason = void 0;
12559
+ const choicesByIndex = /* @__PURE__ */ new Map();
11651
12560
  let metrics = {};
11652
12561
  for (const chunk of chunks) {
11653
12562
  if (chunk.usage) {
@@ -11656,62 +12565,75 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
11656
12565
  ...parseMetricsFromUsage(chunk.usage)
11657
12566
  };
11658
12567
  }
11659
- const choice = chunk.choices?.[0];
11660
- if (!choice) {
11661
- continue;
11662
- }
11663
- if (choice.finish_reason) {
11664
- finish_reason = choice.finish_reason;
11665
- }
11666
- logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
11667
- const delta = choice.delta;
11668
- if (!delta) {
12568
+ const choices = chunk.choices;
12569
+ if (!choices?.length) {
11669
12570
  continue;
11670
12571
  }
11671
- if (delta.finish_reason) {
11672
- finish_reason = delta.finish_reason;
11673
- }
11674
- if (!role && delta.role) {
11675
- role = delta.role;
11676
- }
11677
- if (delta.content) {
11678
- content = (content || "") + delta.content;
11679
- }
11680
- if (delta.refusal) {
11681
- refusal = (refusal || "") + delta.refusal;
11682
- }
11683
- if (delta.tool_calls) {
11684
- const toolDelta = delta.tool_calls[0];
11685
- if (!tool_calls || toolDelta.id && tool_calls[tool_calls.length - 1].id !== toolDelta.id) {
11686
- tool_calls = [
11687
- ...tool_calls || [],
11688
- {
11689
- id: toolDelta.id,
11690
- type: toolDelta.type,
11691
- function: toolDelta.function
12572
+ for (const choice of choices) {
12573
+ const choiceIndex = choice.index;
12574
+ let aggregatedChoice = choicesByIndex.get(choiceIndex);
12575
+ if (!aggregatedChoice) {
12576
+ aggregatedChoice = createAggregatedChatChoice(choiceIndex);
12577
+ choicesByIndex.set(choiceIndex, aggregatedChoice);
12578
+ }
12579
+ if (choice.finish_reason) {
12580
+ aggregatedChoice.finish_reason = choice.finish_reason;
12581
+ }
12582
+ aggregatedChoice.logprobs = aggregateChatLogprobs(
12583
+ aggregatedChoice.logprobs,
12584
+ choice.logprobs
12585
+ );
12586
+ const delta = choice.delta;
12587
+ if (!delta) {
12588
+ continue;
12589
+ }
12590
+ if (delta.finish_reason) {
12591
+ aggregatedChoice.finish_reason = delta.finish_reason;
12592
+ }
12593
+ if (!aggregatedChoice.role && delta.role) {
12594
+ aggregatedChoice.role = delta.role;
12595
+ }
12596
+ if (delta.content) {
12597
+ aggregatedChoice.content = (aggregatedChoice.content || "") + delta.content;
12598
+ }
12599
+ if (delta.refusal) {
12600
+ aggregatedChoice.refusal = (aggregatedChoice.refusal || "") + delta.refusal;
12601
+ }
12602
+ if (delta.tool_calls) {
12603
+ for (const toolDelta of delta.tool_calls) {
12604
+ let aggregatedToolCall = aggregatedChoice.toolCallsByIndex.get(
12605
+ toolDelta.index
12606
+ );
12607
+ if (!aggregatedToolCall) {
12608
+ aggregatedToolCall = {
12609
+ function: { arguments: "" }
12610
+ };
12611
+ aggregatedChoice.toolCallsByIndex.set(
12612
+ toolDelta.index,
12613
+ aggregatedToolCall
12614
+ );
11692
12615
  }
11693
- ];
11694
- } else {
11695
- tool_calls[tool_calls.length - 1].function.arguments += toolDelta.function.arguments;
12616
+ if (toolDelta.id !== void 0) {
12617
+ aggregatedToolCall.id = toolDelta.id;
12618
+ }
12619
+ if (toolDelta.type !== void 0) {
12620
+ aggregatedToolCall.type = toolDelta.type;
12621
+ }
12622
+ if (toolDelta.function?.name !== void 0) {
12623
+ aggregatedToolCall.function.name = toolDelta.function.name;
12624
+ }
12625
+ if (toolDelta.function?.arguments !== void 0) {
12626
+ aggregatedToolCall.function.arguments += toolDelta.function.arguments;
12627
+ }
12628
+ }
11696
12629
  }
11697
12630
  }
11698
12631
  }
11699
12632
  metrics = withCachedMetric(metrics, streamResult, endEvent);
12633
+ const output = Array.from(choicesByIndex.values()).sort((left, right) => left.index - right.index).map(toChatChoice);
11700
12634
  return {
11701
12635
  metrics,
11702
- output: [
11703
- {
11704
- index: 0,
11705
- message: {
11706
- role,
11707
- content,
11708
- ...refusal !== void 0 ? { refusal } : {},
11709
- tool_calls
11710
- },
11711
- logprobs: logprobs ?? null,
11712
- finish_reason
11713
- }
11714
- ]
12636
+ output: output.length > 0 ? output : [toChatChoice(createAggregatedChatChoice(0))]
11715
12637
  };
11716
12638
  }
11717
12639
  function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
@@ -12406,12 +13328,30 @@ function logInstrumentationError(context, error) {
12406
13328
 
12407
13329
  // src/wrappers/anthropic-tokens-util.ts
12408
13330
  function finalizeAnthropicTokens(metrics) {
12409
- const prompt_tokens = (metrics.prompt_tokens || 0) + (metrics.prompt_cached_tokens || 0) + (metrics.prompt_cache_creation_tokens || 0);
12410
- return {
13331
+ const hasSplitCacheCreationTokens = metrics.prompt_cache_creation_5m_tokens !== void 0 || metrics.prompt_cache_creation_1h_tokens !== void 0;
13332
+ const splitCacheCreationTokens = (metrics.prompt_cache_creation_5m_tokens || 0) + (metrics.prompt_cache_creation_1h_tokens || 0);
13333
+ const aggregateCacheCreationTokens = metrics.prompt_cache_creation_tokens || 0;
13334
+ const effectiveCacheCreationTokens = Math.max(
13335
+ aggregateCacheCreationTokens,
13336
+ splitCacheCreationTokens
13337
+ );
13338
+ const prompt_tokens = (metrics.prompt_tokens || 0) + (metrics.prompt_cached_tokens || 0) + effectiveCacheCreationTokens;
13339
+ const finalized = {
12411
13340
  ...metrics,
12412
13341
  prompt_tokens,
12413
13342
  tokens: prompt_tokens + (metrics.completion_tokens || 0)
12414
13343
  };
13344
+ if (hasSplitCacheCreationTokens && splitCacheCreationTokens >= aggregateCacheCreationTokens) {
13345
+ delete finalized.prompt_cache_creation_tokens;
13346
+ }
13347
+ return finalized;
13348
+ }
13349
+ function toNumericMetrics(metrics) {
13350
+ return Object.fromEntries(
13351
+ Object.entries(metrics).filter(
13352
+ (entry) => entry[1] !== void 0
13353
+ )
13354
+ );
12415
13355
  }
12416
13356
  function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens = 0) {
12417
13357
  const cacheTokens = {};
@@ -13004,6 +13944,24 @@ function parseMetricsFromUsage2(usage) {
13004
13944
  saveIfExistsTo("output_tokens", "completion_tokens");
13005
13945
  saveIfExistsTo("cache_read_input_tokens", "prompt_cached_tokens");
13006
13946
  saveIfExistsTo("cache_creation_input_tokens", "prompt_cache_creation_tokens");
13947
+ if (isObject(usage.cache_creation)) {
13948
+ const cacheCreation = usage.cache_creation;
13949
+ for (const [source, target] of [
13950
+ ["ephemeral_5m_input_tokens", "prompt_cache_creation_5m_tokens"],
13951
+ ["ephemeral_1h_input_tokens", "prompt_cache_creation_1h_tokens"]
13952
+ ]) {
13953
+ const value = cacheCreation[source];
13954
+ if (typeof value === "number") {
13955
+ metrics[target] = value;
13956
+ }
13957
+ }
13958
+ }
13959
+ if (isObject(usage.output_tokens_details)) {
13960
+ const thinkingTokens = usage.output_tokens_details.thinking_tokens;
13961
+ if (typeof thinkingTokens === "number") {
13962
+ metrics.completion_reasoning_tokens = thinkingTokens;
13963
+ }
13964
+ }
13007
13965
  if (isObject(usage.server_tool_use)) {
13008
13966
  for (const [name, value] of Object.entries(usage.server_tool_use)) {
13009
13967
  if (typeof value === "number") {
@@ -13960,7 +14918,6 @@ function endHarnessTurn(parent) {
13960
14918
  function braintrustAISDKTelemetry() {
13961
14919
  const operations = /* @__PURE__ */ new Map();
13962
14920
  const operationKeysByCallId = /* @__PURE__ */ new Map();
13963
- const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
13964
14921
  const modelSpans = /* @__PURE__ */ new Map();
13965
14922
  const objectSpans = /* @__PURE__ */ new Map();
13966
14923
  const embedSpans = /* @__PURE__ */ new Map();
@@ -14003,9 +14960,6 @@ function braintrustAISDKTelemetry() {
14003
14960
  return;
14004
14961
  }
14005
14962
  operations.delete(operationKey);
14006
- if (workflowOperationKeyStore.getStore() === operationKey) {
14007
- workflowOperationKeyStore.enterWith(void 0);
14008
- }
14009
14963
  const keys = operationKeysByCallId.get(state.callId);
14010
14964
  if (!keys) {
14011
14965
  return;
@@ -14053,14 +15007,7 @@ function braintrustAISDKTelemetry() {
14053
15007
  return key;
14054
15008
  }
14055
15009
  }
14056
- const workflowOperationKey = workflowOperationKeyStore.getStore();
14057
- if (workflowOperationKey && keys.includes(workflowOperationKey)) {
14058
- return workflowOperationKey;
14059
- }
14060
- if (callId === "workflow-agent") {
14061
- return void 0;
14062
- }
14063
- return mode === "finish" ? keys[0] : keys[keys.length - 1];
15010
+ return callId === "workflow-agent" || mode === "active" ? keys[keys.length - 1] : keys[0];
14064
15011
  };
14065
15012
  const operationKeyFromEvent = (event, mode = "active") => {
14066
15013
  const explicit = explicitOperationKey(event);
@@ -14074,17 +15021,13 @@ function braintrustAISDKTelemetry() {
14074
15021
  if (operationKey) {
14075
15022
  return operationKey;
14076
15023
  }
14077
- const workflowOperationKey2 = workflowOperationKeyStore.getStore();
14078
- if (workflowOperationKey2 && operations.has(workflowOperationKey2)) {
14079
- return workflowOperationKey2;
15024
+ const workflowAgentKeys2 = operationKeysByCallId.get("workflow-agent");
15025
+ if (workflowAgentKeys2?.length) {
15026
+ return workflowAgentKeys2[workflowAgentKeys2.length - 1];
14080
15027
  }
14081
15028
  return callId === "workflow-agent" ? void 0 : callId;
14082
15029
  }
14083
15030
  }
14084
- const workflowOperationKey = workflowOperationKeyStore.getStore();
14085
- if (workflowOperationKey && operations.has(workflowOperationKey)) {
14086
- return workflowOperationKey;
14087
- }
14088
15031
  const wrapperSpan = currentWorkflowAgentWrapperSpan();
14089
15032
  if (wrapperSpan?.spanId) {
14090
15033
  for (const [operationKey, state] of operations) {
@@ -14094,8 +15037,8 @@ function braintrustAISDKTelemetry() {
14094
15037
  }
14095
15038
  }
14096
15039
  const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
14097
- if (workflowAgentKeys?.length === 1) {
14098
- return workflowAgentKeys[0];
15040
+ if (workflowAgentKeys?.length) {
15041
+ return workflowAgentKeys[workflowAgentKeys.length - 1];
14099
15042
  }
14100
15043
  if (operations.size === 1) {
14101
15044
  return operations.keys().next().value;
@@ -14298,9 +15241,6 @@ function braintrustAISDKTelemetry() {
14298
15241
  if (!ownsSpan) {
14299
15242
  return;
14300
15243
  }
14301
- if (workflowAgent) {
14302
- workflowOperationKeyStore.enterWith(operationKey);
14303
- }
14304
15244
  let metadata = metadataFromEvent(event);
14305
15245
  const logPayload = { metadata };
14306
15246
  const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
@@ -14772,6 +15712,10 @@ var aiSDKChannels = defineChannels(
14772
15712
  channelName: "generateText",
14773
15713
  kind: "async"
14774
15714
  }),
15715
+ generateImage: channel({
15716
+ channelName: "generateImage",
15717
+ kind: "async"
15718
+ }),
14775
15719
  streamText: channel({
14776
15720
  channelName: "streamText",
14777
15721
  kind: "async"
@@ -14959,7 +15903,7 @@ var AISDKPlugin = class extends BasePlugin {
14959
15903
  }
14960
15904
  subscribeToAISDK() {
14961
15905
  const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
14962
- this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
15906
+ this.unsubscribers.push(interceptAISDKV7TelemetryDispatcher());
14963
15907
  this.unsubscribers.push(subscribeToHarnessAgentCreateSession());
14964
15908
  this.unsubscribers.push(
14965
15909
  subscribeToHarnessContinuation(
@@ -14987,6 +15931,18 @@ var AISDKPlugin = class extends BasePlugin {
14987
15931
  aggregateChunks: aggregateAISDKChunks
14988
15932
  })
14989
15933
  );
15934
+ this.unsubscribers.push(
15935
+ traceAsyncChannel(aiSDKChannels.generateImage, {
15936
+ name: "generateImage",
15937
+ type: "llm" /* LLM */,
15938
+ extractInput: ([params], event) => prepareAISDKGenerateImageInput(params, event.self),
15939
+ extractOutput: (result, endEvent) => processAISDKGenerateImageOutput(
15940
+ result,
15941
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
15942
+ ),
15943
+ extractMetrics: (result) => extractTokenMetrics(result)
15944
+ })
15945
+ );
14990
15946
  this.unsubscribers.push(
14991
15947
  traceStreamingChannel(aiSDKChannels.streamText, {
14992
15948
  name: "streamText",
@@ -15476,26 +16432,29 @@ function subscribeToHarnessContinuation(continuationChannel, defaultDenyOutputPa
15476
16432
  channel2.unsubscribe(handlers);
15477
16433
  };
15478
16434
  }
15479
- function subscribeToAISDKV7TelemetryDispatcher() {
15480
- const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
16435
+ function interceptAISDKV7TelemetryDispatcher() {
15481
16436
  const telemetry = braintrustAISDKTelemetry();
15482
- const handlers = {
15483
- end: (event) => {
15484
- const telemetryOptions = event.arguments?.[0]?.telemetry;
15485
- if (telemetryOptions?.isEnabled === false) {
15486
- return;
16437
+ return aiSDKChannels.v7CreateTelemetryDispatcher.intercept(
16438
+ (target, thisArg, args) => {
16439
+ const dispatcher = Reflect.apply(target, thisArg, args);
16440
+ const telemetryOptions = args[0]?.telemetry;
16441
+ if (telemetryOptions?.isEnabled !== false) {
16442
+ try {
16443
+ patchAISDKV7TelemetryDispatcher(
16444
+ dispatcher,
16445
+ telemetry,
16446
+ telemetryOptions
16447
+ );
16448
+ } catch (error) {
16449
+ debugLogger.error(
16450
+ "Error instrumenting AI SDK v7 telemetry dispatcher:",
16451
+ error
16452
+ );
16453
+ }
15487
16454
  }
15488
- patchAISDKV7TelemetryDispatcher(
15489
- event.result,
15490
- telemetry,
15491
- telemetryOptions
15492
- );
16455
+ return dispatcher;
15493
16456
  }
15494
- };
15495
- channel2.subscribe(handlers);
15496
- return () => {
15497
- channel2.unsubscribe(handlers);
15498
- };
16457
+ );
15499
16458
  }
15500
16459
  function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
15501
16460
  if (!isObject(dispatcher)) {
@@ -15820,16 +16779,10 @@ var convertImageToAttachment = (image, explicitMimeType) => {
15820
16779
  }
15821
16780
  }
15822
16781
  if (explicitMimeType) {
15823
- if (image instanceof Uint8Array) {
16782
+ const blob = convertDataToBlob(image, explicitMimeType);
16783
+ if (blob) {
15824
16784
  return new Attachment({
15825
- data: new Blob([image], { type: explicitMimeType }),
15826
- filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
15827
- contentType: explicitMimeType
15828
- });
15829
- }
15830
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
15831
- return new Attachment({
15832
- data: new Blob([image], { type: explicitMimeType }),
16785
+ data: blob,
15833
16786
  filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
15834
16787
  contentType: explicitMimeType
15835
16788
  });
@@ -15883,6 +16836,25 @@ var convertDataToAttachment = (data, mimeType, filename) => {
15883
16836
  function processAISDKCallInput(params) {
15884
16837
  return processInputAttachmentsSync(params);
15885
16838
  }
16839
+ function processAISDKGenerateImageInput(params) {
16840
+ const prompt = params.prompt;
16841
+ if (!isObject(prompt) || Array.isArray(prompt)) {
16842
+ return processAISDKCallInput(params);
16843
+ }
16844
+ const processedPrompt = { ...prompt };
16845
+ if (Array.isArray(prompt.images)) {
16846
+ processedPrompt.images = prompt.images.map(
16847
+ (image) => convertImageToAttachment(image, "image/png") ?? image
16848
+ );
16849
+ }
16850
+ if (prompt.mask !== void 0) {
16851
+ processedPrompt.mask = convertImageToAttachment(prompt.mask, "image/png") ?? prompt.mask;
16852
+ }
16853
+ return processAISDKCallInput({
16854
+ ...params,
16855
+ prompt: processedPrompt
16856
+ });
16857
+ }
15886
16858
  function processAISDKWorkflowAgentCallInput(params) {
15887
16859
  const processed = processAISDKCallInput(params);
15888
16860
  return {
@@ -16021,6 +16993,12 @@ function prepareAISDKEmbedInput(params, self) {
16021
16993
  metadata: extractMetadataFromEmbedParams(params, self)
16022
16994
  };
16023
16995
  }
16996
+ function prepareAISDKGenerateImageInput(params, self) {
16997
+ return {
16998
+ input: processAISDKGenerateImageInput(params).input,
16999
+ metadata: extractMetadataFromCallParams(params, self)
17000
+ };
17001
+ }
16024
17002
  function prepareAISDKRerankInput(params, self) {
16025
17003
  const { documents, query } = params;
16026
17004
  return {
@@ -17396,6 +18374,57 @@ function processAISDKOutput(output, denyOutputPaths) {
17396
18374
  }
17397
18375
  return normalizeAISDKLoggedOutput(sanitized);
17398
18376
  }
18377
+ function processAISDKGenerateImageOutput(output, denyOutputPaths) {
18378
+ if (!output || typeof output !== "object") {
18379
+ return output;
18380
+ }
18381
+ const summarized = {};
18382
+ for (const field of [
18383
+ "usage",
18384
+ "warnings",
18385
+ "providerMetadata",
18386
+ "experimental_providerMetadata",
18387
+ "responses"
18388
+ ]) {
18389
+ const value = safeSerializableFieldRead(output, field);
18390
+ if (value !== void 0 && isSerializableOutputValue(value)) {
18391
+ summarized[field] = value;
18392
+ }
18393
+ }
18394
+ const images = safeSerializableFieldRead(output, "images");
18395
+ const image = safeSerializableFieldRead(output, "image");
18396
+ const generatedFiles = Array.isArray(images) && images.length > 0 ? images : image !== void 0 ? [image] : [];
18397
+ const loggedOutput = normalizeAISDKLoggedOutput(
18398
+ omit(summarized, denyOutputPaths)
18399
+ );
18400
+ if (generatedFiles.length > 0) {
18401
+ loggedOutput.images = generatedFiles.map(
18402
+ (file, index) => convertAISDKGeneratedFileToAttachment(file, index)
18403
+ );
18404
+ }
18405
+ return loggedOutput;
18406
+ }
18407
+ function convertAISDKGeneratedFileToAttachment(file, index) {
18408
+ if (!file || typeof file !== "object") {
18409
+ return file;
18410
+ }
18411
+ const generatedFile = file;
18412
+ const generatedMediaType = safeSerializableFieldRead(
18413
+ generatedFile,
18414
+ "mediaType"
18415
+ );
18416
+ const mediaType = typeof generatedMediaType === "string" ? generatedMediaType : "application/octet-stream";
18417
+ const data = safeSerializableFieldRead(generatedFile, "base64") ?? safeSerializableFieldRead(generatedFile, "uint8Array");
18418
+ const blob = convertDataToBlob(data, mediaType);
18419
+ if (blob) {
18420
+ return new Attachment({
18421
+ data: blob,
18422
+ filename: `generated_image_${index}.${getExtensionFromMediaType(mediaType)}`,
18423
+ contentType: mediaType
18424
+ });
18425
+ }
18426
+ return file;
18427
+ }
17399
18428
  function processAISDKEmbeddingOutput(output, denyOutputPaths) {
17400
18429
  if (!output || typeof output !== "object") {
17401
18430
  return output;
@@ -17896,118 +18925,22 @@ var claudeAgentSDKChannels = defineChannels(
17896
18925
  var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
17897
18926
 
17898
18927
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
17899
- var LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED = /* @__PURE__ */ Symbol.for(
17900
- "braintrust.claude_agent_sdk.local_tool_context_async_iterator_patched"
17901
- );
17902
- function createLocalToolContextStore() {
17903
- const maybeIsoWithAsyncLocalStorage = isomorph_default;
17904
- if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
17905
- return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
17906
- }
17907
- let currentStore;
17908
- return {
17909
- enterWith(store) {
17910
- currentStore = store;
17911
- },
17912
- getStore() {
17913
- return currentStore;
17914
- },
17915
- run(store, callback) {
17916
- const previousStore = currentStore;
17917
- currentStore = store;
17918
- try {
17919
- return callback();
17920
- } finally {
17921
- currentStore = previousStore;
17922
- }
17923
- }
17924
- };
17925
- }
17926
- var localToolContextStore = createLocalToolContextStore();
17927
- var fallbackLocalToolParentResolver;
17928
- function createClaudeLocalToolContext() {
17929
- return {};
17930
- }
17931
- function runWithClaudeLocalToolContext(callback, context) {
17932
- return localToolContextStore.run(
17933
- context ?? createClaudeLocalToolContext(),
17934
- callback
17935
- );
17936
- }
17937
- function ensureClaudeLocalToolContext() {
17938
- const existing = localToolContextStore.getStore();
17939
- if (existing) {
17940
- return existing;
17941
- }
17942
- const created = {};
17943
- localToolContextStore.enterWith(created);
17944
- return created;
17945
- }
17946
- function setClaudeLocalToolParentResolver(resolver) {
17947
- fallbackLocalToolParentResolver = resolver;
17948
- const context = ensureClaudeLocalToolContext();
17949
- if (!context) {
17950
- return;
17951
- }
17952
- context.resolveLocalToolParent = resolver;
18928
+ var localToolContextStore = isomorph_default.newAsyncLocalStorage();
18929
+ var localToolParentResolversByToolUseId = /* @__PURE__ */ new Map();
18930
+ function runWithClaudeLocalToolContext(callback, resolver) {
18931
+ return localToolContextStore.run(resolver, callback);
17953
18932
  }
17954
- function getClaudeLocalToolParentResolver() {
17955
- return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
18933
+ function registerClaudeLocalToolParentResolver(toolUseId, resolver) {
18934
+ localToolParentResolversByToolUseId.set(toolUseId, resolver);
17956
18935
  }
17957
- function isAsyncIterable3(value) {
17958
- return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
17959
- }
17960
- function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
17961
- if (!isAsyncIterable3(result) || Object.isFrozen(result) || Object.isSealed(result)) {
17962
- return result;
17963
- }
17964
- const stream = result;
17965
- const originalAsyncIterator = stream[Symbol.asyncIterator];
17966
- if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
17967
- return result;
18936
+ function getClaudeLocalToolParentResolver(toolUseId) {
18937
+ const currentResolver = localToolContextStore.getStore();
18938
+ if (!toolUseId) {
18939
+ return currentResolver;
17968
18940
  }
17969
- const patchedAsyncIterator = function() {
17970
- return runWithClaudeLocalToolContext(() => {
17971
- const iterator = Reflect.apply(originalAsyncIterator, this, []);
17972
- if (!iterator || typeof iterator !== "object") {
17973
- return iterator;
17974
- }
17975
- const patchMethod = (methodName) => {
17976
- const originalMethod = Reflect.get(iterator, methodName);
17977
- if (typeof originalMethod !== "function") {
17978
- return;
17979
- }
17980
- Reflect.set(
17981
- iterator,
17982
- methodName,
17983
- (...args) => runWithClaudeLocalToolContext(
17984
- () => Reflect.apply(
17985
- originalMethod,
17986
- iterator,
17987
- args
17988
- ),
17989
- localToolContext
17990
- )
17991
- );
17992
- };
17993
- patchMethod("next");
17994
- patchMethod("return");
17995
- patchMethod("throw");
17996
- return iterator;
17997
- }, localToolContext);
17998
- };
17999
- Object.defineProperty(
18000
- patchedAsyncIterator,
18001
- LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
18002
- {
18003
- configurable: false,
18004
- enumerable: false,
18005
- value: true,
18006
- writable: false
18007
- }
18008
- );
18009
- Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
18010
- return result;
18941
+ const registeredResolver = localToolParentResolversByToolUseId.get(toolUseId);
18942
+ localToolParentResolversByToolUseId.delete(toolUseId);
18943
+ return currentResolver ?? registeredResolver;
18011
18944
  }
18012
18945
 
18013
18946
  // src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
@@ -18033,7 +18966,7 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
18033
18966
  const metadata = getMetadata();
18034
18967
  const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
18035
18968
  const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
18036
- const localToolParentResolver = getClaudeLocalToolParentResolver();
18969
+ const localToolParentResolver = getClaudeLocalToolParentResolver(toolUseId);
18037
18970
  const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
18038
18971
  const runWithResolvedParent = async () => {
18039
18972
  const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
@@ -18302,37 +19235,97 @@ function seedTaskToolUseIdMapping(taskIdToToolUseId, message) {
18302
19235
  taskIdToToolUseId.set(message.task_id, message.tool_use_id);
18303
19236
  }
18304
19237
  }
18305
- function extractUsageFromMessage(message) {
18306
- const metrics = {};
18307
- let usage;
18308
- if (message.type === "assistant") {
18309
- usage = message.message?.usage;
18310
- } else if (message.type === "result") {
18311
- usage = message.usage;
18312
- }
19238
+ function tokenCount(value) {
19239
+ return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0 ? value : void 0;
19240
+ }
19241
+ function copyUsage(usage) {
18313
19242
  if (!usage || typeof usage !== "object") {
18314
- return metrics;
19243
+ return void 0;
19244
+ }
19245
+ const copy = {};
19246
+ for (const key of [
19247
+ "input_tokens",
19248
+ "output_tokens",
19249
+ "cache_read_input_tokens",
19250
+ "cache_creation_input_tokens"
19251
+ ]) {
19252
+ const value = tokenCount(Reflect.get(usage, key));
19253
+ if (value !== void 0) {
19254
+ copy[key] = value;
19255
+ }
19256
+ }
19257
+ const cacheCreation = Reflect.get(usage, "cache_creation");
19258
+ if (cacheCreation && typeof cacheCreation === "object") {
19259
+ const cacheCreationCopy = {};
19260
+ for (const key of [
19261
+ "ephemeral_5m_input_tokens",
19262
+ "ephemeral_1h_input_tokens"
19263
+ ]) {
19264
+ const value = tokenCount(Reflect.get(cacheCreation, key));
19265
+ if (value !== void 0) {
19266
+ cacheCreationCopy[key] = value;
19267
+ }
19268
+ }
19269
+ if (Object.keys(cacheCreationCopy).length > 0) {
19270
+ copy.cache_creation = cacheCreationCopy;
19271
+ }
19272
+ }
19273
+ return Object.keys(copy).length > 0 ? copy : void 0;
19274
+ }
19275
+ function mergeUsage(base, override) {
19276
+ if (!base || !override) {
19277
+ return override ?? base;
19278
+ }
19279
+ const cacheCreation = base.cache_creation || override.cache_creation ? { ...base.cache_creation, ...override.cache_creation } : void 0;
19280
+ return {
19281
+ ...base,
19282
+ ...override,
19283
+ ...cacheCreation && { cache_creation: cacheCreation }
19284
+ };
19285
+ }
19286
+ function extractUsage(usage, includeOutput) {
19287
+ const metrics = {};
19288
+ if (!usage) {
19289
+ return {};
18315
19290
  }
18316
19291
  const inputTokens = getNumberProperty(usage, "input_tokens");
18317
19292
  if (inputTokens !== void 0) {
18318
19293
  metrics.prompt_tokens = inputTokens;
18319
19294
  }
18320
- const outputTokens = getNumberProperty(usage, "output_tokens");
18321
- if (outputTokens !== void 0) {
18322
- metrics.completion_tokens = outputTokens;
19295
+ if (includeOutput) {
19296
+ const outputTokens = getNumberProperty(usage, "output_tokens");
19297
+ if (outputTokens !== void 0) {
19298
+ metrics.completion_tokens = outputTokens;
19299
+ }
18323
19300
  }
18324
19301
  const cacheReadTokens = getNumberProperty(usage, "cache_read_input_tokens") || 0;
18325
19302
  const cacheCreationTokens = getNumberProperty(usage, "cache_creation_input_tokens") || 0;
18326
- if (cacheReadTokens > 0 || cacheCreationTokens > 0) {
18327
- Object.assign(
18328
- metrics,
18329
- extractAnthropicCacheTokens(cacheReadTokens, cacheCreationTokens)
18330
- );
19303
+ Object.assign(
19304
+ metrics,
19305
+ extractAnthropicCacheTokens(cacheReadTokens, cacheCreationTokens)
19306
+ );
19307
+ const cacheCreation5mTokens = getNumberProperty(
19308
+ usage.cache_creation,
19309
+ "ephemeral_5m_input_tokens"
19310
+ );
19311
+ const cacheCreation1hTokens = getNumberProperty(
19312
+ usage.cache_creation,
19313
+ "ephemeral_1h_input_tokens"
19314
+ );
19315
+ if (cacheCreation5mTokens !== void 0) {
19316
+ metrics.prompt_cache_creation_5m_tokens = cacheCreation5mTokens;
18331
19317
  }
18332
- if (Object.keys(metrics).length > 0) {
18333
- Object.assign(metrics, finalizeAnthropicTokens(metrics));
19318
+ if (cacheCreation1hTokens !== void 0) {
19319
+ metrics.prompt_cache_creation_1h_tokens = cacheCreation1hTokens;
18334
19320
  }
18335
- return metrics;
19321
+ if (Object.keys(metrics).length === 0) {
19322
+ return {};
19323
+ }
19324
+ const finalized = finalizeAnthropicTokens(metrics);
19325
+ if (metrics.completion_tokens === void 0) {
19326
+ delete finalized.tokens;
19327
+ }
19328
+ return toNumericMetrics(finalized);
18336
19329
  }
18337
19330
  function buildLLMInput(promptMessages, conversationHistory) {
18338
19331
  const inputParts = [...promptMessages, ...conversationHistory];
@@ -18366,16 +19359,16 @@ function buildRootPromptMessages(prompt, capturedPromptMessages) {
18366
19359
  function formatCapturedMessages(messages) {
18367
19360
  return messages.length > 0 ? messages : [];
18368
19361
  }
18369
- async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
19362
+ async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, usage, hasFinalOutputUsage, existingSpan) {
18370
19363
  if (messages.length === 0) {
18371
19364
  return void 0;
18372
19365
  }
18373
19366
  const lastMessage = messages[messages.length - 1];
18374
- if (lastMessage.type !== "assistant" || !lastMessage.message?.usage) {
19367
+ if (lastMessage.type !== "assistant") {
18375
19368
  return void 0;
18376
19369
  }
18377
- const model = lastMessage.message.model || options.model;
18378
- const usage = extractUsageFromMessage(lastMessage);
19370
+ const model = lastMessage.message?.model || options.model;
19371
+ const metrics = options.includePartialMessages ? extractUsage(usage, hasFinalOutputUsage) : {};
18379
19372
  const input = buildLLMInput(promptMessages, conversationHistory);
18380
19373
  const outputs = messages.map(
18381
19374
  (m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
@@ -18397,8 +19390,8 @@ async function createLLMSpanForMessages(messages, promptMessages, conversationHi
18397
19390
  );
18398
19391
  span.log({
18399
19392
  input,
18400
- metadata: model ? { model } : void 0,
18401
- metrics: usage,
19393
+ metadata: { ...model && { model }, provider: "anthropic" },
19394
+ ...Object.keys(metrics).length > 0 ? { metrics } : {},
18402
19395
  output: outputs
18403
19396
  });
18404
19397
  const spanExport = await span.export();
@@ -18488,12 +19481,19 @@ function prepareLocalToolHandlersInMcpServers(mcpServers) {
18488
19481
  }
18489
19482
  return { hasLocalToolHandlers, localToolHookNames };
18490
19483
  }
18491
- function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
19484
+ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToParent, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
18492
19485
  const preToolUse = async (input, toolUseID) => {
18493
19486
  if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
18494
19487
  return {};
18495
19488
  }
19489
+ if (!toolUseToParent.has(toolUseID) && input.agent_id) {
19490
+ const parentToolUseId = taskIdToToolUseId.get(input.agent_id);
19491
+ if (parentToolUseId) {
19492
+ toolUseToParent.set(toolUseID, parentToolUseId);
19493
+ }
19494
+ }
18496
19495
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
19496
+ registerClaudeLocalToolParentResolver(toolUseID, resolveParentSpan);
18497
19497
  return {};
18498
19498
  }
18499
19499
  const parsed = parseToolName(input.tool_name);
@@ -18688,9 +19688,6 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
18688
19688
  }
18689
19689
  const metadata = {
18690
19690
  ...subAgentDetailsToMetadata(details),
18691
- ...input.agent_transcript_path && {
18692
- "claude_agent_sdk.agent_transcript_path": input.agent_transcript_path
18693
- },
18694
19691
  "claude_agent_sdk.stop_hook_active": input.stop_hook_active
18695
19692
  };
18696
19693
  try {
@@ -18712,7 +19709,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
18712
19709
  subagentStop
18713
19710
  };
18714
19711
  }
18715
- function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
19712
+ function injectTracingHooks(options, resolveParentSpan, taskIdToToolUseId, toolUseToParent, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
18716
19713
  const {
18717
19714
  preToolUse,
18718
19715
  postToolUse,
@@ -18721,6 +19718,8 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
18721
19718
  subagentStop
18722
19719
  } = createToolTracingHooks(
18723
19720
  resolveParentSpan,
19721
+ taskIdToToolUseId,
19722
+ toolUseToParent,
18724
19723
  activeToolSpans,
18725
19724
  options.mcpServers,
18726
19725
  localToolHookNames,
@@ -18802,6 +19801,13 @@ async function finalizeCurrentMessageGroup(state) {
18802
19801
  }
18803
19802
  }
18804
19803
  const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
19804
+ const lastMessage = state.currentMessages[state.currentMessages.length - 1];
19805
+ const messageId = lastMessage?.message?.id;
19806
+ const usage = state.options.includePartialMessages ? mergeUsage(
19807
+ copyUsage(lastMessage?.message?.usage),
19808
+ messageId ? state.usageByMessageId.get(messageId) : void 0
19809
+ ) : void 0;
19810
+ const hasFinalOutputUsage = messageId !== void 0 && state.finalOutputUsageMessageIds.has(messageId);
18805
19811
  const llmSpanResult = await createLLMSpanForMessages(
18806
19812
  state.currentMessages,
18807
19813
  promptMessages,
@@ -18809,6 +19815,8 @@ async function finalizeCurrentMessageGroup(state) {
18809
19815
  state.options,
18810
19816
  state.currentMessageStartTime,
18811
19817
  parentSpan,
19818
+ usage,
19819
+ hasFinalOutputUsage,
18812
19820
  existingLlmSpan
18813
19821
  );
18814
19822
  if (llmSpanResult) {
@@ -18826,9 +19834,17 @@ async function finalizeCurrentMessageGroup(state) {
18826
19834
  }
18827
19835
  }
18828
19836
  state.activeLlmSpansByParentToolUse.delete(parentKey);
18829
- const lastMessage = state.currentMessages[state.currentMessages.length - 1];
18830
- if (lastMessage?.message?.usage) {
18831
- state.accumulatedOutputTokens += getNumberProperty(lastMessage.message.usage, "output_tokens") || 0;
19837
+ if (messageId) {
19838
+ state.usageByMessageId.delete(messageId);
19839
+ state.finalOutputUsageMessageIds.delete(messageId);
19840
+ for (const [
19841
+ parent,
19842
+ activeMessageId
19843
+ ] of state.activePartialMessageIdByParentKey) {
19844
+ if (activeMessageId === messageId) {
19845
+ state.activePartialMessageIdByParentKey.delete(parent);
19846
+ }
19847
+ }
18832
19848
  }
18833
19849
  state.currentMessages.length = 0;
18834
19850
  }
@@ -18919,6 +19935,10 @@ async function ensureActiveLlmSpanForParentToolUse(rootSpan, activeLlmSpansByPar
18919
19935
  );
18920
19936
  llmParentSpan = await subAgentSpan.export();
18921
19937
  }
19938
+ const racedLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
19939
+ if (racedLlmSpan) {
19940
+ return racedLlmSpan;
19941
+ }
18922
19942
  const llmSpan = startSpan(
18923
19943
  withSpanInstrumentationName(
18924
19944
  {
@@ -19038,7 +20058,49 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
19038
20058
  }
19039
20059
  return true;
19040
20060
  }
20061
+ function handlePartialUsageMessage(state, message) {
20062
+ if (message.type !== "stream_event") {
20063
+ return false;
20064
+ }
20065
+ const event = message.event;
20066
+ if (!event || typeof event !== "object") {
20067
+ return true;
20068
+ }
20069
+ const parentKey = llmParentKey(message.parent_tool_use_id ?? null);
20070
+ if (event.type === "message_start") {
20071
+ const messageId2 = event.message?.id;
20072
+ const usage = copyUsage(event.message?.usage);
20073
+ if (messageId2) {
20074
+ state.activePartialMessageIdByParentKey.set(parentKey, messageId2);
20075
+ if (usage) {
20076
+ state.usageByMessageId.set(messageId2, usage);
20077
+ }
20078
+ }
20079
+ return true;
20080
+ }
20081
+ const messageId = state.activePartialMessageIdByParentKey.get(parentKey);
20082
+ if (!messageId) {
20083
+ return true;
20084
+ }
20085
+ if (event.type === "message_delta") {
20086
+ const update = copyUsage(event.usage);
20087
+ if (update) {
20088
+ const usage = state.usageByMessageId.get(messageId) ?? {};
20089
+ Object.assign(usage, update);
20090
+ state.usageByMessageId.set(messageId, usage);
20091
+ if (update.output_tokens !== void 0) {
20092
+ state.finalOutputUsageMessageIds.add(messageId);
20093
+ }
20094
+ }
20095
+ } else if (event.type === "message_stop") {
20096
+ state.activePartialMessageIdByParentKey.delete(parentKey);
20097
+ }
20098
+ return true;
20099
+ }
19041
20100
  async function handleStreamMessage(state, message) {
20101
+ if (handlePartialUsageMessage(state, message)) {
20102
+ return;
20103
+ }
19042
20104
  maybeTrackToolUseContext(state, message);
19043
20105
  if (await maybeHandleTaskLifecycleMessage(state, message)) {
19044
20106
  return;
@@ -19085,36 +20147,9 @@ async function handleStreamMessage(state, message) {
19085
20147
  );
19086
20148
  state.currentMessages.push(message);
19087
20149
  }
19088
- if (message.type !== "result" || !message.usage) {
20150
+ if (message.type !== "result") {
19089
20151
  return;
19090
20152
  }
19091
- const finalUsageMetrics = extractUsageFromMessage(message);
19092
- if (state.currentMessages.length > 0 && finalUsageMetrics.completion_tokens !== void 0) {
19093
- const lastMessage = state.currentMessages[state.currentMessages.length - 1];
19094
- if (lastMessage?.message?.usage) {
19095
- const adjustedTokens = finalUsageMetrics.completion_tokens - state.accumulatedOutputTokens;
19096
- if (adjustedTokens >= 0) {
19097
- lastMessage.message.usage.output_tokens = adjustedTokens;
19098
- }
19099
- const resultUsage = message.usage;
19100
- if (resultUsage && typeof resultUsage === "object") {
19101
- const cacheReadTokens = getNumberProperty(
19102
- resultUsage,
19103
- "cache_read_input_tokens"
19104
- );
19105
- if (cacheReadTokens !== void 0) {
19106
- lastMessage.message.usage.cache_read_input_tokens = cacheReadTokens;
19107
- }
19108
- const cacheCreationTokens = getNumberProperty(
19109
- resultUsage,
19110
- "cache_creation_input_tokens"
19111
- );
19112
- if (cacheCreationTokens !== void 0) {
19113
- lastMessage.message.usage.cache_creation_input_tokens = cacheCreationTokens;
19114
- }
19115
- }
19116
- }
19117
- }
19118
20153
  const metadata = {};
19119
20154
  if (message.num_turns !== void 0) {
19120
20155
  metadata.num_turns = message.num_turns;
@@ -19122,8 +20157,12 @@ async function handleStreamMessage(state, message) {
19122
20157
  if (message.session_id !== void 0) {
19123
20158
  metadata.session_id = message.session_id;
19124
20159
  }
19125
- if (Object.keys(metadata).length > 0) {
19126
- state.span.log({ metadata });
20160
+ const metrics = state.options.includePartialMessages ? {} : extractUsage(copyUsage(message.usage), true);
20161
+ if (Object.keys(metadata).length > 0 || Object.keys(metrics).length > 0) {
20162
+ state.span.log({
20163
+ ...Object.keys(metadata).length > 0 ? { metadata } : {},
20164
+ ...Object.keys(metrics).length > 0 ? { metrics } : {}
20165
+ });
19127
20166
  }
19128
20167
  }
19129
20168
  async function finalizeQuerySpan(state) {
@@ -19147,6 +20186,9 @@ async function finalizeQuerySpan(state) {
19147
20186
  llmSpan.end();
19148
20187
  }
19149
20188
  state.activeLlmSpansByParentToolUse.clear();
20189
+ state.activePartialMessageIdByParentKey.clear();
20190
+ state.finalOutputUsageMessageIds.clear();
20191
+ state.usageByMessageId.clear();
19150
20192
  for (const toolSpan of state.activeToolSpans.values()) {
19151
20193
  toolSpan.end();
19152
20194
  }
@@ -19162,7 +20204,7 @@ async function finalizeQuerySpan(state) {
19162
20204
  }
19163
20205
  var ClaudeAgentSDKPlugin = class extends BasePlugin {
19164
20206
  onEnable() {
19165
- this.subscribeToQuery();
20207
+ this.interceptQuery();
19166
20208
  }
19167
20209
  onDisable() {
19168
20210
  for (const unsubscribe of this.unsubscribers) {
@@ -19170,207 +20212,218 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
19170
20212
  }
19171
20213
  this.unsubscribers = [];
19172
20214
  }
19173
- subscribeToQuery() {
19174
- const channel2 = claudeAgentSDKChannels.query.tracingChannel();
19175
- const spans = /* @__PURE__ */ new WeakMap();
19176
- const handlers = {
19177
- start: (event) => {
19178
- const params = event.arguments[0] ?? {};
19179
- const originalPrompt = params.prompt;
19180
- const options = params.options ?? {};
19181
- const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
19182
- let promptStarted = false;
19183
- let capturedPromptMessages;
19184
- let resolvePromptDone;
19185
- const promptDone = new Promise((resolve) => {
19186
- resolvePromptDone = resolve;
19187
- });
19188
- if (promptIsAsyncIterable) {
19189
- capturedPromptMessages = [];
19190
- const promptStream = originalPrompt;
19191
- params.prompt = (async function* () {
19192
- promptStarted = true;
19193
- try {
19194
- for await (const message of promptStream) {
19195
- capturedPromptMessages.push(message);
19196
- yield message;
19197
- }
19198
- } finally {
19199
- resolvePromptDone?.();
20215
+ interceptQuery() {
20216
+ const startQuery = (params) => {
20217
+ const originalPrompt = params.prompt;
20218
+ const options = params.options ?? {};
20219
+ const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
20220
+ let promptStarted = false;
20221
+ let capturedPromptMessages;
20222
+ let resolvePromptDone;
20223
+ const promptDone = new Promise((resolve) => {
20224
+ resolvePromptDone = resolve;
20225
+ });
20226
+ if (promptIsAsyncIterable) {
20227
+ capturedPromptMessages = [];
20228
+ const promptStream = originalPrompt;
20229
+ params.prompt = (async function* () {
20230
+ promptStarted = true;
20231
+ try {
20232
+ for await (const message of promptStream) {
20233
+ capturedPromptMessages.push(message);
20234
+ yield message;
19200
20235
  }
19201
- })();
19202
- }
19203
- const span = startSpan(
19204
- withSpanInstrumentationName(
19205
- {
19206
- name: "Claude Agent",
19207
- spanAttributes: {
19208
- type: "task" /* TASK */
19209
- }
19210
- },
19211
- INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
19212
- )
19213
- );
19214
- const startTime = getCurrentUnixTimestamp();
19215
- try {
19216
- span.log({
19217
- input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
19218
- metadata: filterSerializableOptions(options)
19219
- });
19220
- } catch (error) {
19221
- console.error("Error extracting input for Claude Agent SDK:", error);
19222
- }
19223
- const activeToolSpans = /* @__PURE__ */ new Map();
19224
- const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
19225
- const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
19226
- const subAgentSpans = /* @__PURE__ */ new Map();
19227
- const endedSubAgentSpans = /* @__PURE__ */ new Set();
19228
- const toolUseToParent = /* @__PURE__ */ new Map();
19229
- const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
19230
- const latestRootLlmParentRef = {
19231
- value: void 0
19232
- };
19233
- const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
19234
- const taskIdToToolUseId = /* @__PURE__ */ new Map();
19235
- const promptMessagesByParentKey = /* @__PURE__ */ new Map();
19236
- const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
19237
- const localToolContext = createClaudeLocalToolContext();
19238
- const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
19239
- const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
19240
- const resolveToolUseParentSpan = async (toolUseID, context) => {
19241
- const trackedParentToolUseId = toolUseToParent.get(toolUseID);
19242
- const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
19243
- const parentKey = llmParentKey(parentToolUseId);
19244
- const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
19245
- const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
19246
- if (!activeLlmSpan && !latestLlmParent) {
19247
- await ensureActiveLlmSpanForParentToolUse(
19248
- span,
19249
- activeLlmSpansByParentToolUse,
19250
- subAgentDetailsByToolUseId,
19251
- activeToolSpans,
19252
- subAgentSpans,
19253
- parentToolUseId,
19254
- getCurrentUnixTimestamp()
19255
- );
19256
- }
19257
- if (parentToolUseId) {
19258
- const subAgentSpan = await ensureSubAgentSpan(
19259
- subAgentDetailsByToolUseId,
19260
- span,
19261
- activeToolSpans,
19262
- subAgentSpans,
19263
- parentToolUseId
19264
- );
19265
- return subAgentSpan.export();
20236
+ } finally {
20237
+ resolvePromptDone?.();
19266
20238
  }
19267
- return span.export();
19268
- };
19269
- localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
19270
- setClaudeLocalToolParentResolver(resolveToolUseParentSpan);
19271
- const optionsWithHooks = injectTracingHooks(
19272
- options,
19273
- resolveToolUseParentSpan,
19274
- activeToolSpans,
19275
- localToolHookNames,
19276
- skipLocalToolHooks,
19277
- subAgentDetailsByToolUseId,
19278
- subAgentSpans,
19279
- endedSubAgentSpans
19280
- );
19281
- params.options = optionsWithHooks;
19282
- event.arguments[0] = params;
19283
- spans.set(event, {
19284
- accumulatedOutputTokens: 0,
19285
- activeLlmSpansByParentToolUse,
19286
- activeToolSpans,
19287
- conversationHistoryByParentKey,
19288
- capturedPromptMessages,
19289
- currentMessageId: void 0,
19290
- currentMessageStartTime: startTime,
19291
- currentMessages: [],
19292
- endedSubAgentSpans,
19293
- finalResults: [],
19294
- options: optionsWithHooks,
19295
- originalPrompt,
19296
- processing: Promise.resolve(),
19297
- promptDone,
19298
- promptMessagesByParentKey,
19299
- promptStarted: () => promptStarted,
19300
- promptSourcePriorityByParentKey,
19301
- span,
19302
- subAgentDetailsByToolUseId,
19303
- subAgentSpans,
19304
- taskIdToToolUseId,
19305
- latestLlmParentBySubAgentToolUse,
19306
- latestRootLlmParentRef,
19307
- toolUseToParent,
19308
- localToolContext
20239
+ })();
20240
+ }
20241
+ const span = startSpan(
20242
+ withSpanInstrumentationName(
20243
+ {
20244
+ name: "Claude Agent",
20245
+ spanAttributes: {
20246
+ type: "task" /* TASK */
20247
+ }
20248
+ },
20249
+ INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
20250
+ )
20251
+ );
20252
+ const startTime = getCurrentUnixTimestamp();
20253
+ try {
20254
+ span.log({
20255
+ input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
20256
+ metadata: filterSerializableOptions(options)
19309
20257
  });
19310
- },
19311
- end: (event) => {
19312
- const state = spans.get(event);
19313
- if (!state) {
19314
- return;
19315
- }
19316
- const eventResult = bindClaudeLocalToolContextToAsyncIterable(
19317
- event.result,
19318
- state.localToolContext
19319
- );
19320
- if (eventResult === void 0) {
19321
- state.span.end();
19322
- spans.delete(event);
19323
- return;
19324
- }
19325
- if (isAsyncIterable(eventResult)) {
19326
- patchStreamIfNeeded(eventResult, {
19327
- onChunk: (message) => {
19328
- maybeTrackToolUseContext(state, message);
19329
- state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
19330
- console.error(
19331
- "Error processing Claude Agent SDK stream chunk:",
19332
- error
19333
- );
19334
- });
19335
- },
19336
- onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
19337
- spans.delete(event);
19338
- }),
19339
- onError: (error) => state.processing.then(() => {
19340
- state.span.log({
19341
- error: error.message
19342
- });
19343
- }).then(() => finalizeQuerySpan(state)).finally(() => {
19344
- spans.delete(event);
19345
- })
19346
- });
19347
- return;
19348
- }
19349
- try {
19350
- state.span.log({ output: eventResult });
19351
- } catch (error) {
19352
- console.error("Error extracting output for Claude Agent SDK:", error);
19353
- } finally {
19354
- state.span.end();
19355
- spans.delete(event);
20258
+ } catch (error) {
20259
+ console.error("Error extracting input for Claude Agent SDK:", error);
20260
+ }
20261
+ const activeToolSpans = /* @__PURE__ */ new Map();
20262
+ const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
20263
+ const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
20264
+ const subAgentSpans = /* @__PURE__ */ new Map();
20265
+ const endedSubAgentSpans = /* @__PURE__ */ new Set();
20266
+ const toolUseToParent = /* @__PURE__ */ new Map();
20267
+ const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
20268
+ const latestRootLlmParentRef = {
20269
+ value: void 0
20270
+ };
20271
+ const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
20272
+ const taskIdToToolUseId = /* @__PURE__ */ new Map();
20273
+ const promptMessagesByParentKey = /* @__PURE__ */ new Map();
20274
+ const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
20275
+ const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
20276
+ const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
20277
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
20278
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
20279
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
20280
+ const parentKey = llmParentKey(parentToolUseId);
20281
+ const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
20282
+ const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
20283
+ if (!activeLlmSpan && !latestLlmParent) {
20284
+ await ensureActiveLlmSpanForParentToolUse(
20285
+ span,
20286
+ activeLlmSpansByParentToolUse,
20287
+ subAgentDetailsByToolUseId,
20288
+ activeToolSpans,
20289
+ subAgentSpans,
20290
+ parentToolUseId,
20291
+ getCurrentUnixTimestamp()
20292
+ );
19356
20293
  }
19357
- },
19358
- error: (event) => {
19359
- const state = spans.get(event);
19360
- if (!state || !event.error) {
19361
- return;
20294
+ if (parentToolUseId) {
20295
+ const subAgentSpan = await ensureSubAgentSpan(
20296
+ subAgentDetailsByToolUseId,
20297
+ span,
20298
+ activeToolSpans,
20299
+ subAgentSpans,
20300
+ parentToolUseId
20301
+ );
20302
+ return subAgentSpan.export();
19362
20303
  }
19363
- state.span.log({
19364
- error: event.error.message
20304
+ return span.export();
20305
+ };
20306
+ const optionsWithHooks = injectTracingHooks(
20307
+ options,
20308
+ resolveToolUseParentSpan,
20309
+ taskIdToToolUseId,
20310
+ toolUseToParent,
20311
+ activeToolSpans,
20312
+ localToolHookNames,
20313
+ skipLocalToolHooks,
20314
+ subAgentDetailsByToolUseId,
20315
+ subAgentSpans,
20316
+ endedSubAgentSpans
20317
+ );
20318
+ params.options = optionsWithHooks;
20319
+ return {
20320
+ activeLlmSpansByParentToolUse,
20321
+ activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
20322
+ activeToolSpans,
20323
+ conversationHistoryByParentKey,
20324
+ capturedPromptMessages,
20325
+ currentMessageId: void 0,
20326
+ currentMessageStartTime: startTime,
20327
+ currentMessages: [],
20328
+ endedSubAgentSpans,
20329
+ finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
20330
+ finalResults: [],
20331
+ options: optionsWithHooks,
20332
+ originalPrompt,
20333
+ processing: Promise.resolve(),
20334
+ promptDone,
20335
+ promptMessagesByParentKey,
20336
+ promptStarted: () => promptStarted,
20337
+ promptSourcePriorityByParentKey,
20338
+ span,
20339
+ subAgentDetailsByToolUseId,
20340
+ subAgentSpans,
20341
+ taskIdToToolUseId,
20342
+ latestLlmParentBySubAgentToolUse,
20343
+ latestRootLlmParentRef,
20344
+ toolUseToParent,
20345
+ usageByMessageId: /* @__PURE__ */ new Map(),
20346
+ localToolParentResolver: resolveToolUseParentSpan
20347
+ };
20348
+ };
20349
+ const finishQuery = (state, result) => {
20350
+ if (isAsyncIterable(result)) {
20351
+ patchStreamIfNeeded(result, {
20352
+ aroundNext: (callback) => runWithClaudeLocalToolContext(
20353
+ callback,
20354
+ state.localToolParentResolver
20355
+ ),
20356
+ onChunk: (message) => {
20357
+ maybeTrackToolUseContext(state, message);
20358
+ state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
20359
+ console.error(
20360
+ "Error processing Claude Agent SDK stream chunk:",
20361
+ error
20362
+ );
20363
+ });
20364
+ },
20365
+ onComplete: () => state.processing.then(() => finalizeQuerySpan(state)),
20366
+ onError: (error) => state.processing.then(() => {
20367
+ state.span.log({ error: error.message });
20368
+ }).then(() => finalizeQuerySpan(state))
19365
20369
  });
20370
+ return;
20371
+ }
20372
+ try {
20373
+ state.span.log({ output: result });
20374
+ } catch (error) {
20375
+ console.error("Error extracting output for Claude Agent SDK:", error);
20376
+ } finally {
19366
20377
  state.span.end();
19367
- spans.delete(event);
19368
20378
  }
19369
20379
  };
19370
- channel2.subscribe(handlers);
19371
- this.unsubscribers.push(() => {
19372
- channel2.unsubscribe(handlers);
19373
- });
20380
+ this.unsubscribers.push(
20381
+ claudeAgentSDKChannels.query.intercept((target, thisArg, args) => {
20382
+ let state;
20383
+ try {
20384
+ args[0] ??= {};
20385
+ state = startQuery(args[0]);
20386
+ } catch (error) {
20387
+ debugLogger.error(
20388
+ "Error starting Claude Agent SDK instrumentation:",
20389
+ error
20390
+ );
20391
+ }
20392
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
20393
+ try {
20394
+ const result = state ? runWithClaudeLocalToolContext(
20395
+ invokeTarget,
20396
+ state.localToolParentResolver
20397
+ ) : invokeTarget();
20398
+ if (state) {
20399
+ try {
20400
+ finishQuery(state, result);
20401
+ } catch (error) {
20402
+ debugLogger.error(
20403
+ "Error finalizing Claude Agent SDK instrumentation:",
20404
+ error
20405
+ );
20406
+ }
20407
+ }
20408
+ return result;
20409
+ } catch (error) {
20410
+ if (state) {
20411
+ try {
20412
+ state.span.log({
20413
+ error: error instanceof Error ? error.message : String(error)
20414
+ });
20415
+ state.span.end();
20416
+ } catch (instrumentationError) {
20417
+ debugLogger.error(
20418
+ "Error handling Claude Agent SDK instrumentation failure:",
20419
+ instrumentationError
20420
+ );
20421
+ }
20422
+ }
20423
+ throw error;
20424
+ }
20425
+ })
20426
+ );
19374
20427
  }
19375
20428
  };
19376
20429
 
@@ -21779,9 +22832,9 @@ function extractEmbedPromptTokenCount(response) {
21779
22832
  let sawAny = false;
21780
22833
  for (const embedding of embeddings) {
21781
22834
  const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
21782
- const tokenCount = embeddingStats?.tokenCount;
21783
- if (typeof tokenCount === "number" && Number.isFinite(tokenCount)) {
21784
- total += tokenCount;
22835
+ const tokenCount2 = embeddingStats?.tokenCount;
22836
+ if (typeof tokenCount2 === "number" && Number.isFinite(tokenCount2)) {
22837
+ total += tokenCount2;
21785
22838
  sawAny = true;
21786
22839
  }
21787
22840
  }
@@ -23484,7 +24537,7 @@ function patchOpenRouterCallModelResult(args) {
23484
24537
  span,
23485
24538
  () => originalMethod.apply(resultLike, args2)
23486
24539
  );
23487
- if (!isAsyncIterable4(stream)) {
24540
+ if (!isAsyncIterable3(stream)) {
23488
24541
  return stream;
23489
24542
  }
23490
24543
  return wrapAsyncIterableWithSpan({
@@ -23679,7 +24732,7 @@ function wrapAsyncIterableWithSpan(args) {
23679
24732
  }
23680
24733
  };
23681
24734
  }
23682
- function isAsyncIterable4(value) {
24735
+ function isAsyncIterable3(value) {
23683
24736
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
23684
24737
  }
23685
24738
  function normalizeError(error) {
@@ -24557,7 +25610,7 @@ function patchOpenRouterCallModelResult2(args) {
24557
25610
  span,
24558
25611
  () => originalMethod.apply(resultLike, args2)
24559
25612
  );
24560
- if (!isAsyncIterable5(stream)) {
25613
+ if (!isAsyncIterable4(stream)) {
24561
25614
  return stream;
24562
25615
  }
24563
25616
  return wrapAsyncIterableWithSpan2({
@@ -24752,7 +25805,7 @@ function wrapAsyncIterableWithSpan2(args) {
24752
25805
  }
24753
25806
  };
24754
25807
  }
24755
- function isAsyncIterable5(value) {
25808
+ function isAsyncIterable4(value) {
24756
25809
  return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
24757
25810
  }
24758
25811
  function normalizeError2(error) {
@@ -28676,7 +29729,7 @@ function getStringProperty2(obj, key) {
28676
29729
  return typeof value === "string" ? value : void 0;
28677
29730
  }
28678
29731
  function extractMetricsFromUsage(usage) {
28679
- const metrics = {
29732
+ const rawMetrics = {
28680
29733
  prompt_tokens: usage.inputTokens,
28681
29734
  completion_tokens: usage.outputTokens,
28682
29735
  ...extractAnthropicCacheTokens(
@@ -28685,10 +29738,10 @@ function extractMetricsFromUsage(usage) {
28685
29738
  )
28686
29739
  };
28687
29740
  if (usage.reasoningTokens !== void 0) {
28688
- metrics.completion_reasoning_tokens = usage.reasoningTokens;
28689
- metrics.reasoning_tokens = usage.reasoningTokens;
29741
+ rawMetrics.completion_reasoning_tokens = usage.reasoningTokens;
29742
+ rawMetrics.reasoning_tokens = usage.reasoningTokens;
28690
29743
  }
28691
- Object.assign(metrics, finalizeAnthropicTokens(metrics));
29744
+ const metrics = finalizeAnthropicTokens(rawMetrics);
28692
29745
  const metadata = {
28693
29746
  model: usage.model
28694
29747
  };
@@ -29627,17 +30680,20 @@ var FlueObserveBridge = class {
29627
30680
  return;
29628
30681
  }
29629
30682
  const metadata = {
30683
+ ...event.runId ? this.runsById.get(event.runId)?.metadata : {},
29630
30684
  ...extractEventMetadata(event),
29631
30685
  "flue.operation": event.operationKind,
29632
30686
  provider: "flue"
29633
30687
  };
29634
30688
  const parent = this.parentSpanForEvent(event);
29635
- const span = startFlueSpan(parent, {
30689
+ const args = {
29636
30690
  name: `flue.${event.operationKind}`,
29637
30691
  spanAttributes: { type: "task" /* TASK */ },
29638
30692
  startTime: eventTime(event.timestamp),
29639
30693
  event: { metadata }
29640
- });
30694
+ };
30695
+ const runSpan = event.runId ? this.runsById.get(event.runId)?.span : void 0;
30696
+ const span = event.operationKind === "prompt" && (!parent || parent === runSpan) ? startFlueRootSpan(args) : startFlueSpan(parent, args);
29641
30697
  this.operationsById.set(event.operationId, { metadata, span });
29642
30698
  }
29643
30699
  handleOperation(event) {
@@ -29652,6 +30708,11 @@ var FlueObserveBridge = class {
29652
30708
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
29653
30709
  ...event.usage ? { "flue.usage": event.usage } : {}
29654
30710
  };
30711
+ const input = flueOperationInput(event);
30712
+ if (!state.loggedInput && input !== void 0) {
30713
+ safeLog3(state.span, { input });
30714
+ state.loggedInput = true;
30715
+ }
29655
30716
  this.finishPendingChildrenForOperation(event, output);
29656
30717
  safeLog3(state.span, {
29657
30718
  ...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
@@ -29668,6 +30729,8 @@ var FlueObserveBridge = class {
29668
30729
  return;
29669
30730
  }
29670
30731
  const input = flueTurnRequestInput(event);
30732
+ const operation = event.operationId ? this.operationsById.get(event.operationId) : void 0;
30733
+ const turnInput = prepareFlueTurnInput(event, input, operation);
29671
30734
  const model = flueTurnRequestModel(event);
29672
30735
  const provider = flueTurnRequestProvider(event);
29673
30736
  const api = flueTurnRequestApi(event);
@@ -29680,8 +30743,7 @@ var FlueObserveBridge = class {
29680
30743
  ...provider ? { "flue.provider": provider } : {},
29681
30744
  ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
29682
30745
  ...reasoning ? { reasoning } : {},
29683
- ...input?.systemPrompt ? { "flue.system_prompt": input.systemPrompt } : {},
29684
- ...input?.tools ? { tools: input.tools } : {}
30746
+ ...turnInput.metadata
29685
30747
  };
29686
30748
  const parent = this.parentSpanForTurn(event);
29687
30749
  const span = startFlueSpan(parent, {
@@ -29689,11 +30751,14 @@ var FlueObserveBridge = class {
29689
30751
  spanAttributes: { type: "llm" /* LLM */ },
29690
30752
  startTime: eventTime(event.timestamp),
29691
30753
  event: {
29692
- input: input?.messages,
30754
+ input: turnInput.messages,
29693
30755
  metadata
29694
30756
  }
29695
30757
  });
29696
- this.logOperationInput(event.operationId, input?.messages ?? input);
30758
+ this.logOperationInput(
30759
+ event.operationId,
30760
+ latestUserMessageInput(input?.messages)
30761
+ );
29697
30762
  this.turnsByKey.set(key, { metadata, span });
29698
30763
  }
29699
30764
  handleTurn(event) {
@@ -29940,16 +31005,20 @@ var FlueObserveBridge = class {
29940
31005
  }
29941
31006
  startSyntheticOperation(event) {
29942
31007
  const metadata = {
31008
+ ...event.runId ? this.runsById.get(event.runId)?.metadata : {},
29943
31009
  ...extractEventMetadata(event),
29944
31010
  "flue.operation": event.operationKind,
29945
31011
  provider: "flue"
29946
31012
  };
29947
- const span = startFlueSpan(this.parentSpanForEvent(event), {
31013
+ const args = {
29948
31014
  name: `flue.${event.operationKind}`,
29949
31015
  spanAttributes: { type: "task" /* TASK */ },
29950
31016
  startTime: eventTime(event.timestamp),
29951
31017
  event: { metadata }
29952
- });
31018
+ };
31019
+ const parent = this.parentSpanForEvent(event);
31020
+ const runSpan = event.runId ? this.runsById.get(event.runId)?.span : void 0;
31021
+ const span = event.operationKind === "prompt" && (!parent || parent === runSpan) ? startFlueRootSpan(args) : startFlueSpan(parent, args);
29953
31022
  return { metadata, span };
29954
31023
  }
29955
31024
  startSyntheticTurn(event) {
@@ -30128,6 +31197,71 @@ function flueRunInput(event) {
30128
31197
  function flueTurnRequestInput(event) {
30129
31198
  return event.request?.input ?? event.input;
30130
31199
  }
31200
+ function prepareFlueTurnInput(event, input, operation) {
31201
+ const messages = input?.messages;
31202
+ const tracksUserTurn = event.purpose === "agent" && operation?.metadata["flue.operation"] === "prompt" && Array.isArray(messages);
31203
+ if (!tracksUserTurn) {
31204
+ return {
31205
+ messages,
31206
+ metadata: {
31207
+ ...input?.systemPrompt ? { "flue.system_prompt": input.systemPrompt } : {},
31208
+ ...input?.tools ? { tools: input.tools } : {}
31209
+ }
31210
+ };
31211
+ }
31212
+ const previous = operation.turnInputState;
31213
+ const previousMessageCount = previous?.messageCount ?? 0;
31214
+ const boundaryFingerprint = messages.length > 0 ? fingerprintJsonValue(messages[messages.length - 1]) : void 0;
31215
+ const continuesPreviousInput = previous !== void 0 && messages.length >= previousMessageCount && (previousMessageCount === 0 || previous.boundaryFingerprint !== void 0 && previous.boundaryFingerprint === fingerprintJsonValue(messages[previousMessageCount - 1]));
31216
+ const inputMode = previous === void 0 ? "full" : continuesPreviousInput ? "delta" : "reset";
31217
+ const systemPromptFingerprint = fingerprintJsonValue(input?.systemPrompt);
31218
+ const toolsFingerprint = fingerprintJsonValue(input?.tools);
31219
+ operation.turnInputState = {
31220
+ ...boundaryFingerprint !== void 0 ? { boundaryFingerprint } : {},
31221
+ messageCount: messages.length,
31222
+ ...systemPromptFingerprint !== void 0 ? { systemPromptFingerprint } : {},
31223
+ ...toolsFingerprint !== void 0 ? { toolsFingerprint } : {}
31224
+ };
31225
+ return {
31226
+ messages: continuesPreviousInput ? messages.slice(previousMessageCount) : messages,
31227
+ metadata: {
31228
+ "flue.input_mode": inputMode,
31229
+ ...continuesPreviousInput ? { "flue.input_message_offset": previousMessageCount } : {},
31230
+ ...input?.systemPrompt && (!continuesPreviousInput || systemPromptFingerprint !== previous?.systemPromptFingerprint) ? { "flue.system_prompt": input.systemPrompt } : {},
31231
+ ...input?.tools && (!continuesPreviousInput || toolsFingerprint !== previous?.toolsFingerprint) ? { tools: input.tools } : {}
31232
+ }
31233
+ };
31234
+ }
31235
+ function fingerprintJsonValue(value) {
31236
+ try {
31237
+ const serialized = JSON.stringify(value);
31238
+ if (serialized === void 0) {
31239
+ return void 0;
31240
+ }
31241
+ let hash = 2166136261;
31242
+ for (let i = 0; i < serialized.length; i++) {
31243
+ hash = Math.imul(hash ^ serialized.charCodeAt(i), 16777619);
31244
+ }
31245
+ return `${serialized.length}:${hash >>> 0}`;
31246
+ } catch {
31247
+ return void 0;
31248
+ }
31249
+ }
31250
+ function latestUserMessageInput(messages) {
31251
+ if (!messages) {
31252
+ return void 0;
31253
+ }
31254
+ for (let i = messages.length - 1; i >= 0; i--) {
31255
+ const message = messages[i];
31256
+ if (isObjectLike(message) && Reflect.get(message, "role") === "user") {
31257
+ return [message];
31258
+ }
31259
+ }
31260
+ return void 0;
31261
+ }
31262
+ function flueOperationInput(event) {
31263
+ return typeof event.agentInput?.text === "string" ? [{ content: event.agentInput.text, role: "user" }] : void 0;
31264
+ }
30131
31265
  function flueTurnRequestModel(event) {
30132
31266
  return event.request?.requestedModel ?? event.request?.model ?? event.model;
30133
31267
  }
@@ -30285,6 +31419,21 @@ function startFlueSpan(parent, args) {
30285
31419
  withSpanInstrumentationName(args, INSTRUMENTATION_NAMES.FLUE)
30286
31420
  );
30287
31421
  }
31422
+ function startFlueRootSpan(args) {
31423
+ const state = _internalGetGlobalState();
31424
+ const spanId = state.idGenerator.getSpanId();
31425
+ const rootSpanId = state.idGenerator.shareRootSpanId() ? spanId : state.idGenerator.getTraceId();
31426
+ return withCurrent(
31427
+ NOOP_SPAN,
31428
+ () => startSpan({
31429
+ ...withSpanInstrumentationName(args, INSTRUMENTATION_NAMES.FLUE),
31430
+ parentSpanIds: { parentSpanIds: [], rootSpanId },
31431
+ spanId,
31432
+ state
31433
+ }),
31434
+ state
31435
+ );
31436
+ }
30288
31437
  function runWithCurrentSpanStore(span, next) {
30289
31438
  const state = _internalGetGlobalState();
30290
31439
  const contextManager = state?.contextManager;
@@ -30648,12 +31797,14 @@ function getMetricsFromResponse(response) {
30648
31797
  continue;
30649
31798
  }
30650
31799
  const inputTokenDetails = usageMetadata.input_token_details;
31800
+ const outputTokenDetails = usageMetadata.output_token_details;
30651
31801
  return normalizeTokenMetrics({
30652
31802
  total_tokens: usageMetadata.total_tokens,
30653
31803
  prompt_tokens: usageMetadata.input_tokens,
30654
31804
  completion_tokens: usageMetadata.output_tokens,
30655
31805
  prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
30656
- prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
31806
+ prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
31807
+ completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
30657
31808
  });
30658
31809
  }
30659
31810
  const llmOutput = response.llmOutput || {};
@@ -31240,6 +32391,9 @@ var piCodingAgentChannels = defineChannels(
31240
32391
  // src/instrumentation/plugins/pi-coding-agent-plugin.ts
31241
32392
  var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
31242
32393
  var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
32394
+ var PI_TOOL_EXECUTE_WRAPPED = /* @__PURE__ */ Symbol.for(
32395
+ "braintrust.pi_coding_agent.tool_execute_wrapped"
32396
+ );
31243
32397
  var piPromptContextStore;
31244
32398
  var PiCodingAgentPlugin = class extends BasePlugin {
31245
32399
  activePromptStates = /* @__PURE__ */ new Set();
@@ -31320,6 +32474,7 @@ function startPiPromptRun(event, onFinalize) {
31320
32474
  return void 0;
31321
32475
  }
31322
32476
  installPiAgentInstrumentation(agent);
32477
+ wrapPiToolExecutors(agent.state?.tools);
31323
32478
  const metadata = {
31324
32479
  ...extractSessionMetadata(session),
31325
32480
  ...extractPromptOptionsMetadata(event.arguments[1]),
@@ -31416,6 +32571,7 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
31416
32571
  if (!state || state.agent !== agent || state.finalized) {
31417
32572
  return invokeOriginal();
31418
32573
  }
32574
+ wrapPiToolExecutors(context.tools);
31419
32575
  const llmState = await startPiLlmSpan(state, model, context, options);
31420
32576
  try {
31421
32577
  const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
@@ -31426,6 +32582,33 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
31426
32582
  }
31427
32583
  };
31428
32584
  }
32585
+ function wrapPiToolExecutors(tools) {
32586
+ if (!tools) {
32587
+ return;
32588
+ }
32589
+ for (const tool of tools) {
32590
+ try {
32591
+ const execute = tool.execute;
32592
+ if (typeof execute !== "function" || execute[PI_TOOL_EXECUTE_WRAPPED]) {
32593
+ continue;
32594
+ }
32595
+ const wrappedExecute = function(...args) {
32596
+ return runWithAutoInstrumentationAllowed(
32597
+ () => Reflect.apply(execute, this, args)
32598
+ );
32599
+ };
32600
+ Object.defineProperty(wrappedExecute, PI_TOOL_EXECUTE_WRAPPED, {
32601
+ configurable: false,
32602
+ enumerable: false,
32603
+ value: true,
32604
+ writable: false
32605
+ });
32606
+ tool.execute = wrappedExecute;
32607
+ } catch (error) {
32608
+ logInstrumentationError4("Pi Coding Agent tool wrapping", error);
32609
+ }
32610
+ }
32611
+ }
31429
32612
  async function startPiLlmSpan(state, model, context, options) {
31430
32613
  const metadata = {
31431
32614
  ...extractModelMetadata2(model),
@@ -31597,35 +32780,26 @@ async function startPiToolSpan(state, event) {
31597
32780
  if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
31598
32781
  return;
31599
32782
  }
31600
- const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
31601
32783
  const metadata = {
31602
32784
  "gen_ai.tool.call.id": event.toolCallId,
31603
32785
  "gen_ai.tool.name": event.toolName,
31604
32786
  "pi_coding_agent.tool.name": event.toolName
31605
32787
  };
31606
- try {
31607
- const span = startSpan(
31608
- withSpanInstrumentationName(
31609
- {
31610
- event: {
31611
- input: event.args,
31612
- metadata
31613
- },
31614
- name: event.toolName || "tool",
31615
- parent: await state.span.export(),
31616
- spanAttributes: { type: "tool" /* TOOL */ }
32788
+ const span = startSpan(
32789
+ withSpanInstrumentationName(
32790
+ {
32791
+ event: {
32792
+ input: event.args,
32793
+ metadata
31617
32794
  },
31618
- INSTRUMENTATION_NAMES.PI_CODING_AGENT
31619
- )
31620
- );
31621
- state.activeToolSpans.set(event.toolCallId, {
31622
- restoreAutoInstrumentation,
31623
- span
31624
- });
31625
- } catch (error) {
31626
- restoreAutoInstrumentation();
31627
- throw error;
31628
- }
32795
+ name: event.toolName || "tool",
32796
+ parent: await state.span.export(),
32797
+ spanAttributes: { type: "tool" /* TOOL */ }
32798
+ },
32799
+ INSTRUMENTATION_NAMES.PI_CODING_AGENT
32800
+ )
32801
+ );
32802
+ state.activeToolSpans.set(event.toolCallId, { span });
31629
32803
  }
31630
32804
  function finishPiToolSpan(state, event) {
31631
32805
  const toolState = state.activeToolSpans.get(event.toolCallId);
@@ -31646,11 +32820,7 @@ function finishPiToolSpan(state, event) {
31646
32820
  output: event.result
31647
32821
  });
31648
32822
  } finally {
31649
- try {
31650
- toolState.span.end();
31651
- } finally {
31652
- toolState.restoreAutoInstrumentation?.();
31653
- }
32823
+ toolState.span.end();
31654
32824
  }
31655
32825
  }
31656
32826
  function finishPiPromptRun(state, error) {
@@ -31700,10 +32870,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
31700
32870
  ...cleanMetrics5(llmState.metrics),
31701
32871
  ...buildDurationMetrics3(llmState.startTime)
31702
32872
  };
31703
- const usageMetrics = extractUsageMetrics2(message?.usage);
31704
- if (Object.keys(usageMetrics).length > 0) {
32873
+ const usageMetrics2 = extractUsageMetrics2(message?.usage);
32874
+ if (Object.keys(usageMetrics2).length > 0) {
31705
32875
  promptState.collectedLlmUsageMetrics = true;
31706
- addMetrics(promptState.metrics, usageMetrics);
32876
+ addMetrics(promptState.metrics, usageMetrics2);
31707
32877
  }
31708
32878
  try {
31709
32879
  safeLog4(llmState.span, {
@@ -31721,14 +32891,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
31721
32891
  }
31722
32892
  function finishOpenToolSpans(state, error) {
31723
32893
  for (const [, toolState] of state.activeToolSpans) {
31724
- try {
31725
- safeLog4(toolState.span, {
31726
- error: error ? toLoggedError(error) : "Pi tool did not complete"
31727
- });
31728
- toolState.span.end();
31729
- } finally {
31730
- toolState.restoreAutoInstrumentation?.();
31731
- }
32894
+ safeLog4(toolState.span, {
32895
+ error: error ? toLoggedError(error) : "Pi tool did not complete"
32896
+ });
32897
+ toolState.span.end();
31732
32898
  }
31733
32899
  state.activeToolSpans.clear();
31734
32900
  }
@@ -32047,12 +33213,12 @@ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
32047
33213
  var StrandsAgentSDKPlugin = class extends BasePlugin {
32048
33214
  activeChildParents = /* @__PURE__ */ new WeakMap();
32049
33215
  onEnable() {
32050
- this.subscribeToAgentStream();
32051
- this.subscribeToMultiAgentStream(
33216
+ this.interceptAgentStream();
33217
+ this.interceptMultiAgentStream(
32052
33218
  strandsAgentSDKChannels.graphStream,
32053
33219
  "Graph.stream"
32054
33220
  );
32055
- this.subscribeToMultiAgentStream(
33221
+ this.interceptMultiAgentStream(
32056
33222
  strandsAgentSDKChannels.swarmStream,
32057
33223
  "Swarm.stream"
32058
33224
  );
@@ -32063,143 +33229,109 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
32063
33229
  }
32064
33230
  this.unsubscribers = [];
32065
33231
  }
32066
- subscribeToAgentStream() {
32067
- const channel2 = strandsAgentSDKChannels.agentStream.tracingChannel();
32068
- const states = /* @__PURE__ */ new WeakMap();
32069
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
32070
- const handlers = {
32071
- start: (event) => {
32072
- const state = startAgentStream(event, this.activeChildParents);
32073
- if (state) {
32074
- states.set(event, state);
32075
- }
32076
- },
32077
- end: (event) => {
32078
- const state = states.get(event);
32079
- if (!state) {
32080
- return;
32081
- }
32082
- const result = event.result;
32083
- if (isAsyncIterable(result)) {
32084
- patchStreamIfNeeded(result, {
32085
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
32086
- onChunk: (chunk) => handleAgentStreamEvent(state, chunk),
32087
- onComplete: () => {
32088
- finalizeAgentStream(state);
32089
- states.delete(event);
32090
- },
32091
- onError: (error) => {
32092
- finalizeAgentStream(state, error);
32093
- states.delete(event);
32094
- }
32095
- });
32096
- return;
32097
- }
32098
- finalizeAgentStream(state, void 0, result);
32099
- states.delete(event);
32100
- },
32101
- error: (event) => {
32102
- const state = states.get(event);
32103
- if (!state || !event.error) {
32104
- return;
32105
- }
32106
- finalizeAgentStream(state, event.error);
32107
- states.delete(event);
32108
- }
32109
- };
32110
- channel2.subscribe(handlers);
32111
- this.unsubscribers.push(() => {
32112
- unbindAutoInstrumentationSuppression?.();
32113
- channel2.unsubscribe(handlers);
32114
- });
33232
+ interceptAgentStream() {
33233
+ this.unsubscribers.push(
33234
+ strandsAgentSDKChannels.agentStream.intercept(
33235
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
33236
+ finalize: finalizeAgentStream,
33237
+ handleChunk: handleAgentStreamEvent,
33238
+ invoke: () => Reflect.apply(target, thisArg, args),
33239
+ name: "Strands Agent SDK",
33240
+ start: () => startAgentStream(
33241
+ args[0],
33242
+ extractAgent(additional.agent, thisArg),
33243
+ this.activeChildParents
33244
+ )
33245
+ })
33246
+ )
33247
+ );
32115
33248
  }
32116
- subscribeToMultiAgentStream(channel2, operation) {
32117
- const tracingChannel = channel2.tracingChannel();
32118
- const states = /* @__PURE__ */ new WeakMap();
32119
- const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(tracingChannel);
32120
- const handlers = {
32121
- start: (event) => {
32122
- const state = startMultiAgentStream(
32123
- event,
32124
- operation,
32125
- this.activeChildParents
32126
- );
32127
- if (state) {
32128
- states.set(event, state);
32129
- }
32130
- },
32131
- end: (event) => {
32132
- const state = states.get(event);
32133
- if (!state) {
32134
- return;
32135
- }
32136
- const result = event.result;
32137
- if (isAsyncIterable(result)) {
32138
- patchStreamIfNeeded(result, {
32139
- aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
32140
- onChunk: (chunk) => handleMultiAgentStreamEvent(
32141
- state,
32142
- chunk,
32143
- this.activeChildParents
32144
- ),
32145
- onComplete: () => {
32146
- finalizeMultiAgentStream(state, this.activeChildParents);
32147
- states.delete(event);
32148
- },
32149
- onError: (error) => {
32150
- finalizeMultiAgentStream(state, this.activeChildParents, error);
32151
- states.delete(event);
32152
- }
32153
- });
32154
- return;
32155
- }
32156
- finalizeMultiAgentStream(
32157
- state,
32158
- this.activeChildParents,
32159
- void 0,
32160
- result
33249
+ interceptMultiAgentStream(channel2, operation) {
33250
+ this.unsubscribers.push(
33251
+ channel2.intercept(
33252
+ (target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
33253
+ finalize: (state, error, output) => finalizeMultiAgentStream(
33254
+ state,
33255
+ this.activeChildParents,
33256
+ error,
33257
+ output
33258
+ ),
33259
+ handleChunk: (state, chunk) => handleMultiAgentStreamEvent(state, chunk, this.activeChildParents),
33260
+ invoke: () => Reflect.apply(target, thisArg, args),
33261
+ name: "Strands multi-agent",
33262
+ start: () => startMultiAgentStream(
33263
+ args[0],
33264
+ extractOrchestrator(additional.orchestrator, thisArg),
33265
+ operation,
33266
+ this.activeChildParents
33267
+ )
33268
+ })
33269
+ )
33270
+ );
33271
+ }
33272
+ };
33273
+ function instrumentStrandsStreamInvocation(options) {
33274
+ let state;
33275
+ try {
33276
+ state = options.start();
33277
+ } catch (error) {
33278
+ debugLogger.error(`Error starting ${options.name} instrumentation:`, error);
33279
+ }
33280
+ let result;
33281
+ try {
33282
+ result = runWithAutoInstrumentationSuppressed(options.invoke);
33283
+ } catch (error) {
33284
+ if (state) {
33285
+ try {
33286
+ options.finalize(state, error);
33287
+ } catch (instrumentationError) {
33288
+ debugLogger.error(
33289
+ `Error handling ${options.name} instrumentation failure:`,
33290
+ instrumentationError
32161
33291
  );
32162
- states.delete(event);
32163
- },
32164
- error: (event) => {
32165
- const state = states.get(event);
32166
- if (!state || !event.error) {
32167
- return;
32168
- }
32169
- finalizeMultiAgentStream(state, this.activeChildParents, event.error);
32170
- states.delete(event);
32171
33292
  }
32172
- };
32173
- tracingChannel.subscribe(handlers);
32174
- this.unsubscribers.push(() => {
32175
- unbindAutoInstrumentationSuppression?.();
32176
- tracingChannel.unsubscribe(handlers);
32177
- });
33293
+ }
33294
+ throw error;
32178
33295
  }
32179
- };
32180
- function startAgentStream(event, activeChildParents) {
32181
- const agent = extractAgent(event);
33296
+ if (state) {
33297
+ try {
33298
+ if (isAsyncIterable(result)) {
33299
+ patchStreamIfNeeded(result, {
33300
+ aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
33301
+ onChunk: (chunk) => options.handleChunk(state, chunk),
33302
+ onComplete: () => options.finalize(state),
33303
+ onError: (error) => options.finalize(state, error)
33304
+ });
33305
+ } else {
33306
+ options.finalize(state, void 0, result);
33307
+ }
33308
+ } catch (error) {
33309
+ debugLogger.error(
33310
+ `Error finalizing ${options.name} instrumentation:`,
33311
+ error
33312
+ );
33313
+ }
33314
+ }
33315
+ return result;
33316
+ }
33317
+ function startAgentStream(input, agent, activeChildParents) {
32182
33318
  const model = agent?.model;
32183
33319
  const metadata = {
32184
33320
  ...extractAgentMetadata2(agent),
32185
33321
  ...extractModelMetadata3(model),
32186
33322
  "strands.operation": "Agent.stream",
32187
- provider: extractProvider(model),
32188
- ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
33323
+ provider: extractProvider(model)
32189
33324
  };
32190
33325
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
32191
33326
  const attachmentCache = createStrandsAttachmentCache();
32192
- const input = processStrandsInputAttachments(
32193
- event.arguments[0],
32194
- attachmentCache
32195
- );
33327
+ const processedInput = processStrandsInputAttachments(input, attachmentCache);
32196
33328
  const span = parentSpan ? withCurrent(
32197
33329
  parentSpan,
32198
33330
  () => startSpan(
32199
33331
  withSpanInstrumentationName(
32200
33332
  {
32201
33333
  event: {
32202
- input,
33334
+ input: processedInput,
32203
33335
  metadata
32204
33336
  },
32205
33337
  name: formatAgentSpanName(agent),
@@ -32212,7 +33344,7 @@ function startAgentStream(event, activeChildParents) {
32212
33344
  withSpanInstrumentationName(
32213
33345
  {
32214
33346
  event: {
32215
- input,
33347
+ input: processedInput,
32216
33348
  metadata
32217
33349
  },
32218
33350
  name: formatAgentSpanName(agent),
@@ -32230,23 +33362,21 @@ function startAgentStream(event, activeChildParents) {
32230
33362
  startTime: getCurrentUnixTimestamp()
32231
33363
  };
32232
33364
  }
32233
- function startMultiAgentStream(event, operation, activeChildParents) {
32234
- const orchestrator = extractOrchestrator(event);
33365
+ function startMultiAgentStream(input, orchestrator, operation, activeChildParents) {
32235
33366
  const metadata = {
32236
33367
  "strands.operation": operation,
32237
33368
  provider: "strands",
32238
- ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {},
32239
- ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
33369
+ ...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
32240
33370
  };
32241
33371
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
32242
- const input = processStrandsInputAttachments(event.arguments[0]);
33372
+ const processedInput = processStrandsInputAttachments(input);
32243
33373
  const span = parentSpan ? withCurrent(
32244
33374
  parentSpan,
32245
33375
  () => startSpan(
32246
33376
  withSpanInstrumentationName(
32247
33377
  {
32248
33378
  event: {
32249
- input,
33379
+ input: processedInput,
32250
33380
  metadata
32251
33381
  },
32252
33382
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -32259,7 +33389,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
32259
33389
  withSpanInstrumentationName(
32260
33390
  {
32261
33391
  event: {
32262
- input,
33392
+ input: processedInput,
32263
33393
  metadata
32264
33394
  },
32265
33395
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -32630,12 +33760,12 @@ function finalizeMultiAgentStream(state, activeChildParents, error, output) {
32630
33760
  });
32631
33761
  state.span.end();
32632
33762
  }
32633
- function extractAgent(event) {
32634
- const candidate = event.agent ?? event.self;
33763
+ function extractAgent(agent, self) {
33764
+ const candidate = agent ?? self;
32635
33765
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
32636
33766
  }
32637
- function extractOrchestrator(event) {
32638
- const candidate = event.orchestrator ?? event.self;
33767
+ function extractOrchestrator(orchestrator, self) {
33768
+ const candidate = orchestrator ?? self;
32639
33769
  return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
32640
33770
  }
32641
33771
  function extractAgentMetadata2(agent) {
@@ -33022,6 +34152,320 @@ function logInstrumentationError5(context, error) {
33022
34152
  debugLogger.debug(`${context}:`, error);
33023
34153
  }
33024
34154
 
34155
+ // src/instrumentation/plugins/voyageai-channels.ts
34156
+ var voyageAIChannels = defineChannels(
34157
+ "voyageai",
34158
+ {
34159
+ embed: channel({
34160
+ channelName: "embed",
34161
+ kind: "async"
34162
+ }),
34163
+ multimodalEmbed: channel({
34164
+ channelName: "multimodalEmbed",
34165
+ kind: "async"
34166
+ }),
34167
+ rerank: channel({
34168
+ channelName: "rerank",
34169
+ kind: "async"
34170
+ }),
34171
+ contextualizedEmbed: channel({
34172
+ channelName: "contextualizedEmbed",
34173
+ kind: "async"
34174
+ })
34175
+ },
34176
+ { instrumentationName: INSTRUMENTATION_NAMES.VOYAGEAI }
34177
+ );
34178
+
34179
+ // src/instrumentation/plugins/voyageai-plugin.ts
34180
+ var RERANK_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
34181
+ "model",
34182
+ "returnDocuments",
34183
+ "topK",
34184
+ "truncation"
34185
+ ]);
34186
+ var VoyageAIPlugin = class extends BasePlugin {
34187
+ onEnable() {
34188
+ this.unsubscribers.push(
34189
+ interceptVoyageAICall(
34190
+ voyageAIChannels.embed,
34191
+ "voyageai.embed",
34192
+ extractTextEmbeddingInput,
34193
+ summarizeEmbeddingOutput,
34194
+ extractEmbeddingUsageMetrics
34195
+ ),
34196
+ interceptVoyageAICall(
34197
+ voyageAIChannels.multimodalEmbed,
34198
+ "voyageai.multimodalEmbed",
34199
+ extractMultimodalEmbeddingInput,
34200
+ summarizeEmbeddingOutput,
34201
+ extractEmbeddingUsageMetrics
34202
+ ),
34203
+ interceptVoyageAICall(
34204
+ voyageAIChannels.rerank,
34205
+ "voyageai.rerank",
34206
+ extractRerankInput,
34207
+ summarizeRerankOutput
34208
+ ),
34209
+ interceptVoyageAICall(
34210
+ voyageAIChannels.contextualizedEmbed,
34211
+ "voyageai.contextualizedEmbed",
34212
+ extractContextualizedEmbeddingInput,
34213
+ summarizeContextualizedEmbeddingOutput,
34214
+ extractEmbeddingUsageMetrics
34215
+ )
34216
+ );
34217
+ }
34218
+ onDisable() {
34219
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
34220
+ }
34221
+ };
34222
+ function interceptVoyageAICall(channel2, name, extractInput2, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
34223
+ return channel2.intercept((target, thisArg, args) => {
34224
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
34225
+ if (isAutoInstrumentationSuppressed()) {
34226
+ return invokeTarget();
34227
+ }
34228
+ let span;
34229
+ try {
34230
+ const { input, metadata } = extractInput2(args);
34231
+ span = startSpan(
34232
+ withSpanInstrumentationName(
34233
+ {
34234
+ event: { input, metadata },
34235
+ name,
34236
+ spanAttributes: { type: "llm" /* LLM */ }
34237
+ },
34238
+ INSTRUMENTATION_NAMES.VOYAGEAI
34239
+ )
34240
+ );
34241
+ } catch (error) {
34242
+ debugLogger.error(`Error starting span for ${name}:`, error);
34243
+ return invokeTarget();
34244
+ }
34245
+ let result;
34246
+ try {
34247
+ result = withCurrent(
34248
+ span,
34249
+ () => runWithAutoInstrumentationSuppressed(invokeTarget)
34250
+ );
34251
+ } catch (error) {
34252
+ finishVoyageAISpan(span, name, () => span.log({ error }));
34253
+ throw error;
34254
+ }
34255
+ void Promise.resolve(result).then(
34256
+ (value) => finishVoyageAISpan(span, name, () => {
34257
+ const metadata = extractResponseMetadata3(value);
34258
+ span.log({
34259
+ output: extractOutput2(value),
34260
+ ...metadata ? { metadata } : {},
34261
+ metrics: extractMetrics2(value)
34262
+ });
34263
+ }),
34264
+ (error) => finishVoyageAISpan(span, name, () => span.log({ error }))
34265
+ );
34266
+ return result;
34267
+ });
34268
+ }
34269
+ function finishVoyageAISpan(span, name, log) {
34270
+ try {
34271
+ log();
34272
+ } catch (error) {
34273
+ debugLogger.error(`Error logging span for ${name}:`, error);
34274
+ }
34275
+ try {
34276
+ span.end();
34277
+ } catch (error) {
34278
+ debugLogger.error(`Error ending span for ${name}:`, error);
34279
+ }
34280
+ }
34281
+ function getRequestArg2(args) {
34282
+ if (Array.isArray(args)) {
34283
+ return isObject(args[0]) ? args[0] : void 0;
34284
+ }
34285
+ if (!isObject(args)) {
34286
+ return void 0;
34287
+ }
34288
+ const firstArg = Reflect.get(args, "0");
34289
+ return isObject(firstArg) ? firstArg : void 0;
34290
+ }
34291
+ function pickMetadata(request, allowlist) {
34292
+ const metadata = {};
34293
+ if (request) {
34294
+ for (const key of allowlist) {
34295
+ if (!Object.hasOwn(request, key)) {
34296
+ continue;
34297
+ }
34298
+ const value = request[key];
34299
+ if (value !== void 0) {
34300
+ metadata[key] = value;
34301
+ }
34302
+ }
34303
+ }
34304
+ return {
34305
+ ...metadata,
34306
+ provider: "voyage"
34307
+ };
34308
+ }
34309
+ function buildEmbeddingInput(inputs, request) {
34310
+ const outputDimensions = request?.outputDimension;
34311
+ return {
34312
+ inputs,
34313
+ ...typeof outputDimensions === "number" && Number.isFinite(outputDimensions) ? { output_dimensions: outputDimensions } : {}
34314
+ };
34315
+ }
34316
+ function embeddingMetadata(request) {
34317
+ return {
34318
+ ...typeof request?.model === "string" ? { model: request.model } : {},
34319
+ provider: "voyage"
34320
+ };
34321
+ }
34322
+ function extractTextEmbeddingInput(args) {
34323
+ const request = getRequestArg2(args);
34324
+ const rawInput = request?.input;
34325
+ const values = Array.isArray(rawInput) ? rawInput : [rawInput];
34326
+ return {
34327
+ input: buildEmbeddingInput(
34328
+ values.flatMap(
34329
+ (value) => typeof value === "string" ? [{ content: value }] : []
34330
+ ),
34331
+ request
34332
+ ),
34333
+ metadata: embeddingMetadata(request)
34334
+ };
34335
+ }
34336
+ function extractContextualizedEmbeddingInput(args) {
34337
+ const request = getRequestArg2(args);
34338
+ const rawInputs = request?.inputs;
34339
+ const values = Array.isArray(rawInputs) ? rawInputs.flatMap((value) => Array.isArray(value) ? value : [value]) : [];
34340
+ return {
34341
+ input: buildEmbeddingInput(
34342
+ values.flatMap(
34343
+ (value) => typeof value === "string" ? [{ content: value }] : []
34344
+ ),
34345
+ request
34346
+ ),
34347
+ metadata: embeddingMetadata(request)
34348
+ };
34349
+ }
34350
+ function extractMultimodalEmbeddingInput(args) {
34351
+ const request = getRequestArg2(args);
34352
+ const rawInputs = request?.inputs;
34353
+ const inputs = Array.isArray(rawInputs) ? rawInputs.map((rawInput) => {
34354
+ const rawContent = isObject(rawInput) ? rawInput.content : void 0;
34355
+ return {
34356
+ content: Array.isArray(rawContent) ? rawContent.flatMap(normalizeMultimodalContentPart) : []
34357
+ };
34358
+ }) : [];
34359
+ const input = buildEmbeddingInput(inputs, request);
34360
+ const processedInput = processInputAttachments(input);
34361
+ return {
34362
+ input: hasInlineEmbeddingMedia(processedInput) ? input : processedInput,
34363
+ metadata: embeddingMetadata(request)
34364
+ };
34365
+ }
34366
+ function normalizeMultimodalContentPart(part) {
34367
+ if (!isObject(part) || typeof part.type !== "string") {
34368
+ return [];
34369
+ }
34370
+ if (part.type === "text") {
34371
+ return typeof part.text === "string" ? [{ type: "text", text: part.text }] : [];
34372
+ }
34373
+ const camelCaseField = {
34374
+ image_base64: "imageBase64",
34375
+ image_url: "imageUrl",
34376
+ video_base64: "videoBase64",
34377
+ video_url: "videoUrl"
34378
+ };
34379
+ const field = camelCaseField[part.type];
34380
+ if (!field) {
34381
+ return [];
34382
+ }
34383
+ const data = typeof part[field] === "string" ? part[field] : part[part.type];
34384
+ if (typeof data !== "string") {
34385
+ return [];
34386
+ }
34387
+ return part.type.startsWith("image_") ? [{ type: "image_url", image_url: { url: data } }] : [{ type: "file", file: { file_data: data } }];
34388
+ }
34389
+ function hasInlineEmbeddingMedia(input) {
34390
+ return input.inputs.some(
34391
+ ({ content }) => Array.isArray(content) ? content.some((part) => {
34392
+ const value = part.type === "image_url" ? part.image_url.url : part.type === "file" ? part.file.file_data : void 0;
34393
+ return typeof value === "string" && value.startsWith("data:");
34394
+ }) : false
34395
+ );
34396
+ }
34397
+ function extractRerankInput(args) {
34398
+ const request = getRequestArg2(args);
34399
+ const documents = request?.documents;
34400
+ return {
34401
+ input: {
34402
+ documents,
34403
+ query: request?.query
34404
+ },
34405
+ metadata: {
34406
+ ...pickMetadata(request, RERANK_METADATA_ALLOWLIST),
34407
+ ...Array.isArray(documents) ? { document_count: documents.length } : {}
34408
+ }
34409
+ };
34410
+ }
34411
+ function extractResponseMetadata3(result) {
34412
+ if (!isObject(result)) {
34413
+ return void 0;
34414
+ }
34415
+ const rawResponse = isObject(result.rawResponse) ? result.rawResponse : void 0;
34416
+ const model = typeof result.model === "string" ? result.model : typeof rawResponse?.model === "string" ? rawResponse.model : void 0;
34417
+ return model ? { model } : void 0;
34418
+ }
34419
+ function summarizeEmbeddingOutput(result) {
34420
+ return {
34421
+ count: isObject(result) && Array.isArray(result.data) ? result.data.length : 0
34422
+ };
34423
+ }
34424
+ function summarizeRerankOutput(result) {
34425
+ if (!isObject(result) || !Array.isArray(result.data)) {
34426
+ return void 0;
34427
+ }
34428
+ return result.data.slice(0, 100).map((item) => ({
34429
+ index: isObject(item) ? item.index : void 0,
34430
+ relevance_score: isObject(item) ? (typeof item.relevanceScore === "number" ? item.relevanceScore : item.relevance_score) ?? null : null
34431
+ }));
34432
+ }
34433
+ function summarizeContextualizedEmbeddingOutput(result) {
34434
+ if (!isObject(result)) {
34435
+ return { count: 0 };
34436
+ }
34437
+ if (Array.isArray(result.results)) {
34438
+ return {
34439
+ count: result.results.reduce(
34440
+ (count, item) => count + (isObject(item) && Array.isArray(item.embeddings) ? item.embeddings.length : 0),
34441
+ 0
34442
+ )
34443
+ };
34444
+ }
34445
+ if (!Array.isArray(result.data)) {
34446
+ return { count: 0 };
34447
+ }
34448
+ return {
34449
+ count: result.data.reduce(
34450
+ (count, item) => count + (isObject(item) && Array.isArray(item.data) ? item.data.length : 0),
34451
+ 0
34452
+ )
34453
+ };
34454
+ }
34455
+ function extractEmbeddingUsageMetrics(result) {
34456
+ const metrics = extractUsageMetrics3(result);
34457
+ return typeof metrics.tokens === "number" ? { prompt_tokens: metrics.tokens, tokens: metrics.tokens } : {};
34458
+ }
34459
+ function extractUsageMetrics3(result) {
34460
+ if (!isObject(result)) {
34461
+ return {};
34462
+ }
34463
+ const rawResponse = isObject(result.rawResponse) ? result.rawResponse : void 0;
34464
+ const usage = isObject(result.usage) ? result.usage : isObject(rawResponse?.usage) ? rawResponse.usage : void 0;
34465
+ const tokens = typeof result.totalTokens === "number" ? result.totalTokens : usage?.totalTokens ?? usage?.total_tokens;
34466
+ return typeof tokens === "number" && Number.isFinite(tokens) && tokens >= 0 ? { tokens } : {};
34467
+ }
34468
+
33025
34469
  // src/instrumentation/plugins/cloudflare-ai-chat-channels.ts
33026
34470
  var cloudflareAIChatChannels = defineChannels(
33027
34471
  "@cloudflare/ai-chat",
@@ -33577,6 +35021,7 @@ var BraintrustPlugin = class extends BasePlugin {
33577
35021
  langSmithPlugin = null;
33578
35022
  piCodingAgentPlugin = null;
33579
35023
  strandsAgentSDKPlugin = null;
35024
+ voyageAIPlugin = null;
33580
35025
  cloudflareAIChatPlugin = null;
33581
35026
  cloudflareAgentsPlugin = null;
33582
35027
  constructor(config = {}) {
@@ -33651,6 +35096,10 @@ var BraintrustPlugin = class extends BasePlugin {
33651
35096
  this.coherePlugin = new CoherePlugin();
33652
35097
  this.coherePlugin.enable();
33653
35098
  }
35099
+ if (integrations.voyageai !== false) {
35100
+ this.voyageAIPlugin = new VoyageAIPlugin();
35101
+ this.voyageAIPlugin.enable();
35102
+ }
33654
35103
  if (integrations.groq !== false) {
33655
35104
  this.groqPlugin = new GroqPlugin();
33656
35105
  this.groqPlugin.enable();
@@ -33767,6 +35216,10 @@ var BraintrustPlugin = class extends BasePlugin {
33767
35216
  this.coherePlugin.disable();
33768
35217
  this.coherePlugin = null;
33769
35218
  }
35219
+ if (this.voyageAIPlugin) {
35220
+ this.voyageAIPlugin.disable();
35221
+ this.voyageAIPlugin = null;
35222
+ }
33770
35223
  if (this.groqPlugin) {
33771
35224
  this.groqPlugin.disable();
33772
35225
  this.groqPlugin = null;
@@ -33832,7 +35285,7 @@ function braintrustEveHook(options) {
33832
35285
  }
33833
35286
  };
33834
35287
  }
33835
- function braintrustEveInstrumentation(options) {
35288
+ function createLegacyEveInstrumentation(options) {
33836
35289
  const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
33837
35290
  return {
33838
35291
  events: {
@@ -35220,8 +36673,10 @@ function capturedModelInput(modelInput) {
35220
36673
  const value = [];
35221
36674
  if (typeof instructions === "string") {
35222
36675
  value.push({ content: instructions, role: "system" });
35223
- } else if (instructions) {
36676
+ } else if (Array.isArray(instructions)) {
35224
36677
  value.push(...instructions.map(capturedEveModelMessage));
36678
+ } else if (instructions) {
36679
+ value.push(capturedEveModelMessage(instructions));
35225
36680
  }
35226
36681
  value.push(...messages.map(capturedEveModelMessage));
35227
36682
  try {
@@ -35465,6 +36920,464 @@ async function deterministicEveId(...parts) {
35465
36920
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
35466
36921
  }
35467
36922
 
36923
+ // src/instrumentation/plugins/eve-provider.ts
36924
+ var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
36925
+ function createEveInstrumentationProvider(options = {}) {
36926
+ const bridge = new EveProviderBridge(options.metadata);
36927
+ return {
36928
+ capture: "content",
36929
+ events: {
36930
+ "action.completed": (event, context) => bridge.handleActionTerminal(event, context),
36931
+ "action.failed": (event, context) => bridge.handleActionTerminal(event, context),
36932
+ "action.started": (event, context) => bridge.handleActionStarted(event, context),
36933
+ "model.call.completed": (event, context) => bridge.handleModelTerminal(event, context),
36934
+ "model.call.failed": (event, context) => bridge.handleModelTerminal(event, context),
36935
+ "model.call.started": (event, context) => bridge.handleModelStarted(event, context),
36936
+ "step.attempt.completed": (event) => bridge.handleStepAttemptTerminal(event),
36937
+ "step.attempt.failed": (event) => bridge.handleStepAttemptTerminal(event),
36938
+ "turn.cancelled": (event, context) => bridge.handleTurnTerminal(event, context),
36939
+ "turn.completed": (event, context) => bridge.handleTurnTerminal(event, context),
36940
+ "turn.failed": (event, context) => bridge.handleTurnTerminal(event, context),
36941
+ "turn.started": (event, context) => bridge.handleTurnStarted(event, context)
36942
+ },
36943
+ flush,
36944
+ setup: options.setup
36945
+ };
36946
+ }
36947
+ var EveProviderBridge = class {
36948
+ constructor(metadata) {
36949
+ this.metadata = metadata;
36950
+ }
36951
+ metadata;
36952
+ activeActions = /* @__PURE__ */ new Map();
36953
+ activeModels = /* @__PURE__ */ new Map();
36954
+ modelsByAttempt = /* @__PURE__ */ new Map();
36955
+ settledOperations = new LRUCache({
36956
+ max: MAX_EVE_PROVIDER_CACHE_ENTRIES
36957
+ });
36958
+ turns = new LRUCache({
36959
+ max: MAX_EVE_PROVIDER_CACHE_ENTRIES
36960
+ });
36961
+ async handleTurnStarted(event, context) {
36962
+ await this.contain("turn start", async () => {
36963
+ if (this.settledOperations.has(event.idempotencyKey)) {
36964
+ context.state.set({ skip: true });
36965
+ return;
36966
+ }
36967
+ const { rowId, spanId } = await generateEveIds(
36968
+ "turn",
36969
+ event.idempotencyKey
36970
+ );
36971
+ const key = turnKey3(event.sessionId, event.turnId);
36972
+ const stored = storedSpan(context);
36973
+ if (stored && "exported" in stored && stored.rootSpanId) {
36974
+ this.turns.set(key, { rootSpanId: stored.rootSpanId, spanId });
36975
+ return;
36976
+ }
36977
+ let rootSpanId = spanId;
36978
+ let parentSpanId;
36979
+ if (event.parentLineage) {
36980
+ const parentTurnKey = turnKey3(
36981
+ event.parentLineage.sessionId,
36982
+ event.parentLineage.turnId
36983
+ );
36984
+ const parentTurn = this.turns.get(parentTurnKey);
36985
+ rootSpanId = parentTurn?.rootSpanId ?? // Eve propagates the root session through every nested subagent. Use
36986
+ // it instead of the immediate parent session when no ancestor ran
36987
+ // in-process.
36988
+ (await generateEveIds(
36989
+ "turn",
36990
+ turnIdempotencyKey(
36991
+ event.rootSessionId,
36992
+ event.parentLineage.turnId
36993
+ )
36994
+ )).spanId;
36995
+ parentSpanId = (await generateEveIds(
36996
+ "subagent",
36997
+ actionIdempotencyKey(
36998
+ event.parentLineage.sessionId,
36999
+ event.parentLineage.turnId,
37000
+ event.parentLineage.callId
37001
+ )
37002
+ )).spanId;
37003
+ }
37004
+ const metadata = this.spanMetadata(event.sessionId);
37005
+ const span = await this.startSpan(
37006
+ context,
37007
+ {
37008
+ event: { id: rowId, metadata },
37009
+ name: "eve.turn",
37010
+ parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
37011
+ spanAttributes: { type: "task" /* TASK */ },
37012
+ spanId
37013
+ },
37014
+ rootSpanId
37015
+ );
37016
+ span?.log({ metadata });
37017
+ this.turns.set(key, {
37018
+ rootSpanId,
37019
+ spanId
37020
+ });
37021
+ });
37022
+ }
37023
+ async handleTurnTerminal(event, context) {
37024
+ await this.contain("turn terminal", async () => {
37025
+ if (this.settledOperations.has(event.idempotencyKey)) {
37026
+ context.state.set(void 0);
37027
+ return;
37028
+ }
37029
+ const error = event.type === "turn.failed" ? event.error : void 0;
37030
+ this.drainActionsForTurn(event.sessionId, event.turnId, error);
37031
+ const stored = storedSpan(context);
37032
+ if (stored && "exported" in stored) {
37033
+ updateSpan({
37034
+ exported: stored.exported,
37035
+ ...error !== void 0 ? { error } : {},
37036
+ metrics: { end: Date.now() / 1e3 }
37037
+ });
37038
+ }
37039
+ this.settledOperations.set(event.idempotencyKey, true);
37040
+ context.state.set(void 0);
37041
+ this.turns.delete(turnKey3(event.sessionId, event.turnId));
37042
+ });
37043
+ }
37044
+ async handleModelStarted(event, context) {
37045
+ await this.contain("model start", async () => {
37046
+ if (this.settledOperations.has(event.idempotencyKey)) {
37047
+ context.state.set({ skip: true });
37048
+ return;
37049
+ }
37050
+ const parent = await this.parentForScope(event.scope);
37051
+ const { rowId, spanId } = await generateEveIds(
37052
+ "step",
37053
+ event.idempotencyKey
37054
+ );
37055
+ const input = event.input ? capturedModelInput(event.input) : void 0;
37056
+ const metadata = {
37057
+ ...this.spanMetadata(event.scope.sessionId),
37058
+ model: event.model.modelId,
37059
+ provider: event.model.provider
37060
+ };
37061
+ const span = await this.startSpan(context, {
37062
+ event: {
37063
+ id: rowId,
37064
+ ...input !== void 0 ? { input } : {},
37065
+ metadata
37066
+ },
37067
+ name: "eve.step",
37068
+ parentSpanIds: parent,
37069
+ spanAttributes: { type: "llm" /* LLM */ },
37070
+ spanId
37071
+ });
37072
+ if (!span) return;
37073
+ span.log({ ...input !== void 0 ? { input } : {}, metadata });
37074
+ this.activeModels.set(event.idempotencyKey, {
37075
+ span,
37076
+ turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
37077
+ });
37078
+ const keys = this.modelsByAttempt.get(event.scope.attemptId) ?? /* @__PURE__ */ new Set();
37079
+ keys.add(event.idempotencyKey);
37080
+ this.modelsByAttempt.set(event.scope.attemptId, keys);
37081
+ });
37082
+ }
37083
+ async handleModelTerminal(event, context) {
37084
+ await this.contain("model terminal", async () => {
37085
+ if (this.settledOperations.has(event.idempotencyKey)) {
37086
+ context.state.set(void 0);
37087
+ return;
37088
+ }
37089
+ const active = this.activeModels.get(event.idempotencyKey);
37090
+ if (active) {
37091
+ const span = active.span;
37092
+ if (event.type === "model.call.failed") {
37093
+ if (event.error !== void 0) span.log({ error: event.error });
37094
+ } else {
37095
+ span.log({
37096
+ metrics: usageMetrics(event.usage),
37097
+ output: modelOutput(event)
37098
+ });
37099
+ }
37100
+ span.end();
37101
+ } else {
37102
+ const stored = storedSpan(context);
37103
+ if (stored && "exported" in stored) {
37104
+ updateSpan({
37105
+ exported: stored.exported,
37106
+ ...event.type === "model.call.failed" ? event.error !== void 0 ? { error: event.error } : {} : { output: modelOutput(event) },
37107
+ metrics: {
37108
+ ...event.type === "model.call.completed" ? usageMetrics(event.usage) : {},
37109
+ end: Date.now() / 1e3
37110
+ }
37111
+ });
37112
+ }
37113
+ }
37114
+ this.settledOperations.set(event.idempotencyKey, true);
37115
+ this.forgetModel(event.scope.attemptId, event.idempotencyKey);
37116
+ context.state.set(void 0);
37117
+ });
37118
+ }
37119
+ async handleActionStarted(event, context) {
37120
+ await this.contain("action start", async () => {
37121
+ if (event.kind === "load-skill" || this.settledOperations.has(event.idempotencyKey)) {
37122
+ context.state.set({ skip: true });
37123
+ return;
37124
+ }
37125
+ const parent = await this.parentForScope(event.scope);
37126
+ const { rowId, spanId } = await generateEveIds(
37127
+ event.kind === "subagent-call" ? "subagent" : "tool",
37128
+ event.idempotencyKey
37129
+ );
37130
+ const metadata = {
37131
+ ...this.spanMetadata(event.scope.sessionId),
37132
+ "eve.action_kind": event.kind
37133
+ };
37134
+ const span = await this.startSpan(context, {
37135
+ event: {
37136
+ id: rowId,
37137
+ ...event.input !== void 0 ? { input: event.input } : {},
37138
+ metadata
37139
+ },
37140
+ name: event.name,
37141
+ parentSpanIds: parent,
37142
+ spanAttributes: { type: "tool" /* TOOL */ },
37143
+ spanId
37144
+ });
37145
+ if (!span) return;
37146
+ span.log({
37147
+ ...event.input !== void 0 ? { input: event.input } : {},
37148
+ metadata
37149
+ });
37150
+ this.activeActions.set(event.idempotencyKey, {
37151
+ span,
37152
+ turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
37153
+ });
37154
+ });
37155
+ }
37156
+ async handleActionTerminal(event, context) {
37157
+ await this.contain("action terminal", async () => {
37158
+ if (this.settledOperations.has(event.idempotencyKey)) {
37159
+ context.state.set(void 0);
37160
+ return;
37161
+ }
37162
+ const stored = storedSpan(context);
37163
+ if (stored?.skip) {
37164
+ context.state.set(void 0);
37165
+ return;
37166
+ }
37167
+ const active = this.activeActions.get(event.idempotencyKey);
37168
+ const end = finiteTimestamp(event.acceptedAtMs) ?? Date.now();
37169
+ if (active) {
37170
+ const span = active.span;
37171
+ if (event.type === "action.failed") {
37172
+ span.log({
37173
+ error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
37174
+ });
37175
+ } else if (event.output.type === "error") {
37176
+ span.log({
37177
+ error: event.output.error ?? new Error("Eve action returned an error")
37178
+ });
37179
+ } else {
37180
+ span.log({ output: event.output.output });
37181
+ }
37182
+ span.end({ endTime: end / 1e3 });
37183
+ } else {
37184
+ const stored2 = storedSpan(context);
37185
+ if (stored2 && "exported" in stored2) {
37186
+ updateSpan({
37187
+ exported: stored2.exported,
37188
+ ...event.type === "action.failed" ? {
37189
+ error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
37190
+ } : event.output.type === "error" ? {
37191
+ error: event.output.error ?? new Error("Eve action returned an error")
37192
+ } : { output: event.output.output },
37193
+ metrics: { end: end / 1e3 }
37194
+ });
37195
+ }
37196
+ }
37197
+ this.settledOperations.set(event.idempotencyKey, true);
37198
+ this.activeActions.delete(event.idempotencyKey);
37199
+ context.state.set(void 0);
37200
+ });
37201
+ }
37202
+ handleStepAttemptTerminal(event) {
37203
+ void this.contain("step attempt terminal", () => {
37204
+ const keys = this.modelsByAttempt.get(event.scope.attemptId);
37205
+ if (!keys) return;
37206
+ for (const key of keys) {
37207
+ const active = this.activeModels.get(key);
37208
+ if (!active) continue;
37209
+ if (event.type === "step.attempt.failed" && event.error !== void 0) {
37210
+ active.span.log({ error: event.error });
37211
+ }
37212
+ active.span.end();
37213
+ this.activeModels.delete(key);
37214
+ }
37215
+ this.modelsByAttempt.delete(event.scope.attemptId);
37216
+ });
37217
+ }
37218
+ async parentForScope(scope) {
37219
+ const key = turnKey3(scope.sessionId, scope.turnId);
37220
+ const known = this.turns.get(key);
37221
+ if (known) {
37222
+ return { rootSpanId: known.rootSpanId, spanId: known.spanId };
37223
+ }
37224
+ const [{ spanId }, { spanId: rootSpanId }] = await Promise.all([
37225
+ generateEveIds("turn", turnIdempotencyKey(scope.sessionId, scope.turnId)),
37226
+ generateEveIds(
37227
+ "turn",
37228
+ turnIdempotencyKey(
37229
+ scope.rootSessionId ?? scope.sessionId,
37230
+ scope.turnId
37231
+ )
37232
+ )
37233
+ ]);
37234
+ return { rootSpanId, spanId };
37235
+ }
37236
+ async startSpan(context, args, rootSpanId) {
37237
+ const span = withCurrent(
37238
+ NOOP_SPAN,
37239
+ () => _internalStartSpanWithInitialMerge(
37240
+ withSpanInstrumentationName(args ?? {}, INSTRUMENTATION_NAMES.EVE)
37241
+ )
37242
+ );
37243
+ try {
37244
+ context.state.set({
37245
+ exported: await span.export(),
37246
+ ...rootSpanId ? { rootSpanId } : {}
37247
+ });
37248
+ } catch (error) {
37249
+ debugLogger.warn("Error exporting Eve provider span:", error);
37250
+ }
37251
+ return span;
37252
+ }
37253
+ drainActionsForTurn(sessionId, turnId, error) {
37254
+ const key = turnKey3(sessionId, turnId);
37255
+ for (const [idempotencyKey, active] of this.activeActions) {
37256
+ if (active.turnKey !== key) continue;
37257
+ if (error !== void 0) active.span.log({ error });
37258
+ active.span.end();
37259
+ this.activeActions.delete(idempotencyKey);
37260
+ }
37261
+ }
37262
+ forgetModel(attemptId, idempotencyKey) {
37263
+ this.activeModels.delete(idempotencyKey);
37264
+ const keys = this.modelsByAttempt.get(attemptId);
37265
+ keys?.delete(idempotencyKey);
37266
+ if (keys?.size === 0) this.modelsByAttempt.delete(attemptId);
37267
+ }
37268
+ spanMetadata(sessionId) {
37269
+ return {
37270
+ ...this.metadata ?? {},
37271
+ "eve.session_id": sessionId
37272
+ };
37273
+ }
37274
+ async contain(operation, fn) {
37275
+ try {
37276
+ await fn();
37277
+ } catch (error) {
37278
+ debugLogger.warn(`Error in Eve provider ${operation}:`, error);
37279
+ }
37280
+ }
37281
+ };
37282
+ function storedSpan(context) {
37283
+ const value = context.state.get();
37284
+ if (!isObject(value)) return void 0;
37285
+ if (value["skip"] === true) return { skip: true };
37286
+ return typeof value["exported"] === "string" ? {
37287
+ exported: value["exported"],
37288
+ ...typeof value["rootSpanId"] === "string" && value["rootSpanId"].length > 0 ? { rootSpanId: value["rootSpanId"] } : {}
37289
+ } : void 0;
37290
+ }
37291
+ function modelOutput(event) {
37292
+ const content = event.content ?? [];
37293
+ let text = "";
37294
+ const reasoning = [];
37295
+ const toolCalls = [];
37296
+ for (const part of content) {
37297
+ if (part.type === "text") {
37298
+ text += part.text;
37299
+ } else if (part.type === "reasoning" && part.text.trim().length > 0) {
37300
+ reasoning.push({ content: part.text });
37301
+ } else if (part.type === "tool-call") {
37302
+ toolCalls.push({
37303
+ function: {
37304
+ arguments: safeJsonStringify(part.input),
37305
+ name: part.toolName
37306
+ },
37307
+ id: part.callId,
37308
+ type: "function"
37309
+ });
37310
+ }
37311
+ }
37312
+ return [
37313
+ {
37314
+ finish_reason: normalizeFinishReason2(event.finishReason),
37315
+ index: 0,
37316
+ message: {
37317
+ content: text || null,
37318
+ ...reasoning.length > 0 ? { reasoning } : {},
37319
+ role: "assistant",
37320
+ ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
37321
+ }
37322
+ }
37323
+ ];
37324
+ }
37325
+ function usageMetrics(usage) {
37326
+ const promptTokens = nonNegativeNumber(usage.inputTokens);
37327
+ const completionTokens = nonNegativeNumber(usage.outputTokens);
37328
+ const cachedTokens = nonNegativeNumber(
37329
+ usage.inputTokenDetails?.cacheReadTokens
37330
+ );
37331
+ const cacheCreationTokens = nonNegativeNumber(
37332
+ usage.inputTokenDetails?.cacheWriteTokens
37333
+ );
37334
+ return {
37335
+ ...promptTokens !== void 0 ? { prompt_tokens: promptTokens } : {},
37336
+ ...completionTokens !== void 0 ? { completion_tokens: completionTokens } : {},
37337
+ ...promptTokens !== void 0 && completionTokens !== void 0 ? { tokens: promptTokens + completionTokens } : {},
37338
+ ...cachedTokens !== void 0 ? { prompt_cached_tokens: cachedTokens } : {},
37339
+ ...cacheCreationTokens !== void 0 ? { prompt_cache_creation_tokens: cacheCreationTokens } : {}
37340
+ };
37341
+ }
37342
+ function nonNegativeNumber(value) {
37343
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
37344
+ }
37345
+ function finiteTimestamp(value) {
37346
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
37347
+ }
37348
+ function normalizeFinishReason2(value) {
37349
+ if (value === "content-filter") return "content_filter";
37350
+ if (value === "tool-calls") return "tool_calls";
37351
+ return value;
37352
+ }
37353
+ function safeJsonStringify(value) {
37354
+ try {
37355
+ return JSON.stringify(value) ?? "null";
37356
+ } catch {
37357
+ return "null";
37358
+ }
37359
+ }
37360
+ function turnKey3(sessionId, turnId) {
37361
+ return `${sessionId}:${turnId}`;
37362
+ }
37363
+ function turnIdempotencyKey(sessionId, turnId) {
37364
+ return `turn:${sessionId}:${turnId}`;
37365
+ }
37366
+ function actionIdempotencyKey(sessionId, turnId, callId) {
37367
+ return `action:${sessionId}:${turnId}:${callId}`;
37368
+ }
37369
+
37370
+ // src/instrumentation/plugins/eve-instrumentation.ts
37371
+ var EVE_INSTRUMENTATION_PROVIDER = /* @__PURE__ */ Symbol.for("eve.instrumentation.provider");
37372
+ function braintrustEveInstrumentation(options) {
37373
+ const definition = "defineState" in options ? createLegacyEveInstrumentation(options) : createEveInstrumentationProvider(options);
37374
+ const declaration = {
37375
+ ...definition,
37376
+ [EVE_INSTRUMENTATION_PROVIDER]: true
37377
+ };
37378
+ return declaration;
37379
+ }
37380
+
35468
37381
  // src/instrumentation/config.ts
35469
37382
  var envIntegrationAliases = {
35470
37383
  openai: "openai",
@@ -35537,7 +37450,10 @@ var envIntegrationAliases = {
35537
37450
  "langchain-js": "langchain",
35538
37451
  "@langchain": "langchain",
35539
37452
  langgraph: "langgraph",
35540
- langsmith: "langsmith"
37453
+ langsmith: "langsmith",
37454
+ voyage: "voyageai",
37455
+ "voyage-ai": "voyageai",
37456
+ voyageai: "voyageai"
35541
37457
  };
35542
37458
  function getDefaultInstrumentationIntegrations() {
35543
37459
  return {
@@ -35572,6 +37488,7 @@ function getDefaultInstrumentationIntegrations() {
35572
37488
  langchain: true,
35573
37489
  langgraph: true,
35574
37490
  langsmith: true,
37491
+ voyageai: true,
35575
37492
  piCodingAgent: true,
35576
37493
  strandsAgentSDK: true,
35577
37494
  cloudflareAgents: true