braintrust 3.8.0 → 3.9.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 (48) hide show
  1. package/dev/dist/index.d.mts +84 -3
  2. package/dev/dist/index.d.ts +84 -3
  3. package/dev/dist/index.js +3687 -691
  4. package/dev/dist/index.mjs +3399 -403
  5. package/dist/auto-instrumentations/bundler/esbuild.cjs +575 -2
  6. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  7. package/dist/auto-instrumentations/bundler/rollup.cjs +575 -2
  8. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  9. package/dist/auto-instrumentations/bundler/vite.cjs +575 -2
  10. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  11. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +575 -2
  12. package/dist/auto-instrumentations/bundler/webpack.cjs +575 -2
  13. package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
  14. package/dist/auto-instrumentations/{chunk-MD7W27YH.mjs → chunk-G7F6HZGE.mjs} +5 -1
  15. package/dist/auto-instrumentations/{chunk-OLBMPZXE.mjs → chunk-KIMMUFAK.mjs} +578 -3
  16. package/dist/auto-instrumentations/hook.mjs +757 -10
  17. package/dist/auto-instrumentations/index.cjs +739 -2
  18. package/dist/auto-instrumentations/index.d.mts +18 -1
  19. package/dist/auto-instrumentations/index.d.ts +18 -1
  20. package/dist/auto-instrumentations/index.mjs +168 -1
  21. package/dist/auto-instrumentations/loader/esm-hook.mjs +2 -1
  22. package/dist/browser.d.mts +312 -6
  23. package/dist/browser.d.ts +312 -6
  24. package/dist/browser.js +5335 -1892
  25. package/dist/browser.mjs +5335 -1892
  26. package/dist/cli.js +3514 -489
  27. package/dist/edge-light.d.mts +1 -1
  28. package/dist/edge-light.d.ts +1 -1
  29. package/dist/edge-light.js +5335 -1892
  30. package/dist/edge-light.mjs +5335 -1892
  31. package/dist/index.d.mts +312 -6
  32. package/dist/index.d.ts +312 -6
  33. package/dist/index.js +4244 -801
  34. package/dist/index.mjs +5335 -1892
  35. package/dist/instrumentation/index.d.mts +10 -0
  36. package/dist/instrumentation/index.d.ts +10 -0
  37. package/dist/instrumentation/index.js +3160 -286
  38. package/dist/instrumentation/index.mjs +3160 -286
  39. package/dist/workerd.d.mts +1 -1
  40. package/dist/workerd.d.ts +1 -1
  41. package/dist/workerd.js +5335 -1892
  42. package/dist/workerd.mjs +5335 -1892
  43. package/package.json +52 -47
  44. package/util/dist/index.d.mts +42 -1
  45. package/util/dist/index.d.ts +42 -1
  46. package/util/dist/index.js +5 -1
  47. package/util/dist/index.mjs +4 -0
  48. package/LICENSE +0 -201
@@ -99,6 +99,16 @@ var isomorph_default = iso;
99
99
  function isAsyncIterable(value) {
100
100
  return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
101
101
  }
102
+ function hasAsyncIteratorMethods(value) {
103
+ return value !== null && typeof value === "object" && "next" in value && typeof value.next === "function";
104
+ }
105
+ function isSelfAsyncIterator(value) {
106
+ try {
107
+ return value[Symbol.asyncIterator]() === value;
108
+ } catch {
109
+ return false;
110
+ }
111
+ }
102
112
  function patchStreamIfNeeded(stream, options) {
103
113
  if (!isAsyncIterable(stream)) {
104
114
  return stream;
@@ -109,6 +119,98 @@ function patchStreamIfNeeded(stream, options) {
109
119
  );
110
120
  return stream;
111
121
  }
122
+ if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
123
+ if ("__braintrust_patched_iterator_methods" in stream) {
124
+ return stream;
125
+ }
126
+ try {
127
+ const originalNext = stream.next.bind(stream);
128
+ const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
129
+ const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
130
+ const chunks = [];
131
+ let completed = false;
132
+ stream.next = async (...args) => {
133
+ try {
134
+ const result = await originalNext(...args);
135
+ if (result.done) {
136
+ if (!completed) {
137
+ completed = true;
138
+ try {
139
+ await options.onComplete(chunks);
140
+ } catch (error) {
141
+ console.error("Error in stream onComplete handler:", error);
142
+ }
143
+ }
144
+ } else {
145
+ const chunk = result.value;
146
+ const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
147
+ if (shouldCollect) {
148
+ chunks.push(chunk);
149
+ if (options.onChunk) {
150
+ try {
151
+ await options.onChunk(chunk);
152
+ } catch (error) {
153
+ console.error("Error in stream onChunk handler:", error);
154
+ }
155
+ }
156
+ }
157
+ }
158
+ return result;
159
+ } catch (error) {
160
+ if (!completed) {
161
+ completed = true;
162
+ if (options.onError) {
163
+ try {
164
+ await options.onError(
165
+ error instanceof Error ? error : new Error(String(error)),
166
+ chunks
167
+ );
168
+ } catch (handlerError) {
169
+ console.error("Error in stream onError handler:", handlerError);
170
+ }
171
+ }
172
+ }
173
+ throw error;
174
+ }
175
+ };
176
+ if (originalReturn) {
177
+ stream.return = async (...args) => {
178
+ if (!completed) {
179
+ completed = true;
180
+ try {
181
+ await options.onComplete(chunks);
182
+ } catch (error) {
183
+ console.error("Error in stream onComplete handler:", error);
184
+ }
185
+ }
186
+ return originalReturn(...args);
187
+ };
188
+ }
189
+ if (originalThrow) {
190
+ stream.throw = async (...args) => {
191
+ if (!completed) {
192
+ completed = true;
193
+ const rawError = args[0];
194
+ const error = rawError instanceof Error ? rawError : new Error(String(rawError));
195
+ if (options.onError) {
196
+ try {
197
+ await options.onError(error, chunks);
198
+ } catch (handlerError) {
199
+ console.error("Error in stream onError handler:", handlerError);
200
+ }
201
+ }
202
+ }
203
+ return originalThrow(...args);
204
+ };
205
+ }
206
+ Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
207
+ value: true
208
+ });
209
+ return stream;
210
+ } catch (error) {
211
+ console.warn("Failed to patch stream iterator methods:", error);
212
+ }
213
+ }
112
214
  const originalIteratorFn = stream[Symbol.asyncIterator];
113
215
  if ("__braintrust_patched" in originalIteratorFn && originalIteratorFn["__braintrust_patched"]) {
114
216
  return stream;
@@ -1018,6 +1120,9 @@ function isArray(value) {
1018
1120
  function isObjectOrArray(value) {
1019
1121
  return value instanceof Object;
1020
1122
  }
1123
+ function isPromiseLike(value) {
1124
+ return value != null && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
1125
+ }
1021
1126
 
1022
1127
  // util/object_util.ts
1023
1128
  var SET_UNION_FIELDS = /* @__PURE__ */ new Set(["tags"]);
@@ -1973,7 +2078,11 @@ var CodeBundle = z6.object({
1973
2078
  eval_name: z6.string(),
1974
2079
  position: z6.union([
1975
2080
  z6.object({ type: z6.literal("task") }),
1976
- z6.object({ type: z6.literal("scorer"), index: z6.number().int().gte(0) })
2081
+ z6.object({ type: z6.literal("scorer"), index: z6.number().int().gte(0) }),
2082
+ z6.object({
2083
+ type: z6.literal("classifier"),
2084
+ index: z6.number().int().gte(0)
2085
+ })
1977
2086
  ])
1978
2087
  }),
1979
2088
  z6.object({ type: z6.literal("function"), index: z6.number().int().gte(0) }),
@@ -3095,11 +3204,15 @@ var RunEval = z6.object({
3095
3204
  data: z6.union([
3096
3205
  z6.object({
3097
3206
  dataset_id: z6.string(),
3207
+ dataset_version: z6.union([z6.string(), z6.null()]).optional(),
3208
+ dataset_environment: z6.union([z6.string(), z6.null()]).optional(),
3098
3209
  _internal_btql: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional()
3099
3210
  }),
3100
3211
  z6.object({
3101
3212
  project_name: z6.string(),
3102
3213
  dataset_name: z6.string(),
3214
+ dataset_version: z6.union([z6.string(), z6.null()]).optional(),
3215
+ dataset_environment: z6.union([z6.string(), z6.null()]).optional(),
3103
3216
  _internal_btql: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional()
3104
3217
  }),
3105
3218
  z6.object({ data: z6.array(z6.unknown()) })
@@ -3227,6 +3340,7 @@ var ViewOptions = z6.union([
3227
3340
  rowHeight: z6.union([z6.string(), z6.null()]),
3228
3341
  tallGroupRows: z6.union([z6.boolean(), z6.null()]),
3229
3342
  layout: z6.union([z6.string(), z6.null()]),
3343
+ topicMapReportKey: z6.union([z6.string(), z6.null()]),
3230
3344
  chartHeight: z6.union([z6.number(), z6.null()]),
3231
3345
  excludedMeasures: z6.union([
3232
3346
  z6.array(
@@ -3269,6 +3383,7 @@ var ViewOptions = z6.union([
3269
3383
  z6.null()
3270
3384
  ]),
3271
3385
  queryShape: z6.union([z6.enum(["traces", "spans"]), z6.null()]),
3386
+ cluster: z6.union([z6.string(), z6.null()]),
3272
3387
  freezeColumns: z6.union([z6.boolean(), z6.null()])
3273
3388
  }).partial(),
3274
3389
  z6.null()
@@ -6538,8 +6653,9 @@ function validateAndSanitizeExperimentLogPartialArgs(event) {
6538
6653
  }
6539
6654
  function deepCopyEvent(event) {
6540
6655
  const attachments = [];
6541
- const IDENTIFIER = "_bt_internal_saved_attachment";
6542
- const savedAttachmentSchema = z8.strictObject({ [IDENTIFIER]: z8.number() });
6656
+ const ATTACHMENT_INDEX_KEY = "_bt_internal_saved_attachment_idx";
6657
+ const ATTACHMENT_MARKER_KEY = "_bt_internal_saved_attachment_marker";
6658
+ const attachmentMarker = ++deepCopyEventMarkerCounter;
6543
6659
  const serialized = JSON.stringify(event, (_k, v) => {
6544
6660
  if (v instanceof SpanImpl || v instanceof NoopSpan) {
6545
6661
  return `<span>`;
@@ -6551,21 +6667,39 @@ function deepCopyEvent(event) {
6551
6667
  return `<logger>`;
6552
6668
  } else if (v instanceof BaseAttachment) {
6553
6669
  const idx = attachments.push(v);
6554
- return { [IDENTIFIER]: idx - 1 };
6670
+ return {
6671
+ [ATTACHMENT_INDEX_KEY]: idx - 1,
6672
+ [ATTACHMENT_MARKER_KEY]: attachmentMarker
6673
+ };
6555
6674
  } else if (v instanceof ReadonlyAttachment) {
6556
6675
  return v.reference;
6557
6676
  }
6558
6677
  return v;
6559
6678
  });
6560
6679
  const x = JSON.parse(serialized, (_k, v) => {
6561
- const parsedAttachment = savedAttachmentSchema.safeParse(v);
6562
- if (parsedAttachment.success) {
6563
- return attachments[parsedAttachment.data[IDENTIFIER]];
6680
+ if (isDeepCopyAttachmentPlaceholder(v, attachmentMarker)) {
6681
+ return attachments[v[ATTACHMENT_INDEX_KEY]];
6564
6682
  }
6565
6683
  return v;
6566
6684
  });
6567
6685
  return x;
6568
6686
  }
6687
+ var deepCopyEventMarkerCounter = 0;
6688
+ function isDeepCopyAttachmentPlaceholder(value, attachmentMarker) {
6689
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6690
+ return false;
6691
+ }
6692
+ const record = value;
6693
+ if (!Object.hasOwn(record, "_bt_internal_saved_attachment_idx") || !Object.hasOwn(record, "_bt_internal_saved_attachment_marker")) {
6694
+ return false;
6695
+ }
6696
+ if (Object.keys(record).length !== 2) {
6697
+ return false;
6698
+ }
6699
+ const attachmentIndex = record._bt_internal_saved_attachment_idx;
6700
+ const marker = record._bt_internal_saved_attachment_marker;
6701
+ return Number.isInteger(attachmentIndex) && attachmentIndex >= 0 && marker === attachmentMarker;
6702
+ }
6569
6703
  function extractAttachments(event, attachments) {
6570
6704
  for (const [key, value] of Object.entries(event)) {
6571
6705
  if (!value) {
@@ -9144,10 +9278,42 @@ function processImagesInOutput(output) {
9144
9278
  }
9145
9279
  return output;
9146
9280
  }
9281
+ function mergeLogprobTokens(existing, incoming) {
9282
+ if (incoming === void 0) {
9283
+ return existing;
9284
+ }
9285
+ if (incoming === null) {
9286
+ return existing ?? null;
9287
+ }
9288
+ if (Array.isArray(existing)) {
9289
+ return [...existing, ...incoming];
9290
+ }
9291
+ return [...incoming];
9292
+ }
9293
+ function aggregateChatLogprobs(existing, incoming) {
9294
+ if (incoming === void 0) {
9295
+ return existing;
9296
+ }
9297
+ if (incoming === null) {
9298
+ return existing ?? null;
9299
+ }
9300
+ const aggregated = existing && existing !== null ? { ...existing, ...incoming } : { ...incoming };
9301
+ const content = mergeLogprobTokens(existing?.content, incoming.content);
9302
+ if (content !== void 0) {
9303
+ aggregated.content = content;
9304
+ }
9305
+ const refusal = mergeLogprobTokens(existing?.refusal, incoming.refusal);
9306
+ if (refusal !== void 0) {
9307
+ aggregated.refusal = refusal;
9308
+ }
9309
+ return aggregated;
9310
+ }
9147
9311
  function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
9148
9312
  let role = void 0;
9149
9313
  let content = void 0;
9314
+ let refusal = void 0;
9150
9315
  let tool_calls = void 0;
9316
+ let logprobs = void 0;
9151
9317
  let finish_reason = void 0;
9152
9318
  let metrics = {};
9153
9319
  for (const chunk of chunks) {
@@ -9157,19 +9323,30 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
9157
9323
  ...parseMetricsFromUsage(chunk.usage)
9158
9324
  };
9159
9325
  }
9160
- const delta = chunk.choices?.[0]?.delta;
9161
- if (!delta) {
9326
+ const choice = chunk.choices?.[0];
9327
+ if (!choice) {
9162
9328
  continue;
9163
9329
  }
9164
- if (!role && delta.role) {
9165
- role = delta.role;
9330
+ if (choice.finish_reason) {
9331
+ finish_reason = choice.finish_reason;
9332
+ }
9333
+ logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
9334
+ const delta = choice.delta;
9335
+ if (!delta) {
9336
+ continue;
9166
9337
  }
9167
9338
  if (delta.finish_reason) {
9168
9339
  finish_reason = delta.finish_reason;
9169
9340
  }
9341
+ if (!role && delta.role) {
9342
+ role = delta.role;
9343
+ }
9170
9344
  if (delta.content) {
9171
9345
  content = (content || "") + delta.content;
9172
9346
  }
9347
+ if (delta.refusal) {
9348
+ refusal = (refusal || "") + delta.refusal;
9349
+ }
9173
9350
  if (delta.tool_calls) {
9174
9351
  const toolDelta = delta.tool_calls[0];
9175
9352
  if (!tool_calls || toolDelta.id && tool_calls[tool_calls.length - 1].id !== toolDelta.id) {
@@ -9195,9 +9372,10 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
9195
9372
  message: {
9196
9373
  role,
9197
9374
  content,
9375
+ ...refusal !== void 0 ? { refusal } : {},
9198
9376
  tool_calls
9199
9377
  },
9200
- logprobs: null,
9378
+ logprobs: logprobs ?? null,
9201
9379
  finish_reason
9202
9380
  }
9203
9381
  ]
@@ -9260,13 +9438,21 @@ var anthropicChannels = defineChannels("@anthropic-ai/sdk", {
9260
9438
  betaMessagesCreate: channel({
9261
9439
  channelName: "beta.messages.create",
9262
9440
  kind: "async"
9441
+ }),
9442
+ betaMessagesToolRunner: channel({
9443
+ channelName: "beta.messages.toolRunner",
9444
+ kind: "sync-stream"
9263
9445
  })
9264
9446
  });
9265
9447
 
9266
9448
  // src/instrumentation/plugins/anthropic-plugin.ts
9449
+ var ANTHROPIC_TOOL_RUNNER_TOOL_WRAPPED = Symbol.for(
9450
+ "braintrust.anthropic_tool_runner_tool_wrapped"
9451
+ );
9267
9452
  var AnthropicPlugin = class extends BasePlugin {
9268
9453
  onEnable() {
9269
9454
  this.subscribeToAnthropicChannels();
9455
+ this.subscribeToAnthropicToolRunner();
9270
9456
  }
9271
9457
  onDisable() {
9272
9458
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -9321,6 +9507,61 @@ var AnthropicPlugin = class extends BasePlugin {
9321
9507
  })
9322
9508
  );
9323
9509
  }
9510
+ subscribeToAnthropicToolRunner() {
9511
+ const tracingChannel = anthropicChannels.betaMessagesToolRunner.tracingChannel();
9512
+ const states = /* @__PURE__ */ new WeakMap();
9513
+ const handlers = {
9514
+ start: (event) => {
9515
+ const params = event.arguments[0] ?? {};
9516
+ const span = startSpan({
9517
+ name: "anthropic.beta.messages.toolRunner",
9518
+ spanAttributes: {
9519
+ type: "task" /* TASK */
9520
+ }
9521
+ });
9522
+ span.log({
9523
+ input: processAttachmentsInInput(
9524
+ coalesceInput(params.messages ?? [], params.system)
9525
+ ),
9526
+ metadata: {
9527
+ ...extractAnthropicToolRunnerMetadata(params),
9528
+ provider: "anthropic"
9529
+ }
9530
+ });
9531
+ const state = {
9532
+ aggregatedMetrics: {},
9533
+ finalized: false,
9534
+ iterationCount: 0,
9535
+ seenMessages: /* @__PURE__ */ new WeakSet(),
9536
+ span,
9537
+ startTime: getCurrentUnixTimestamp()
9538
+ };
9539
+ states.set(event, state);
9540
+ },
9541
+ end: (event) => {
9542
+ const state = states.get(event);
9543
+ if (!state) {
9544
+ return;
9545
+ }
9546
+ patchAnthropicToolRunner({
9547
+ runner: event.result,
9548
+ state
9549
+ });
9550
+ },
9551
+ error: (event) => {
9552
+ const state = states.get(event);
9553
+ if (!state || !event.error) {
9554
+ return;
9555
+ }
9556
+ finalizeAnthropicToolRunnerError(state, event.error);
9557
+ states.delete(event);
9558
+ }
9559
+ };
9560
+ tracingChannel.subscribe(handlers);
9561
+ this.unsubscribers.push(() => {
9562
+ tracingChannel.unsubscribe(handlers);
9563
+ });
9564
+ }
9324
9565
  };
9325
9566
  function parseMetricsFromUsage2(usage) {
9326
9567
  if (!usage) {
@@ -9337,72 +9578,411 @@ function parseMetricsFromUsage2(usage) {
9337
9578
  saveIfExistsTo("output_tokens", "completion_tokens");
9338
9579
  saveIfExistsTo("cache_read_input_tokens", "prompt_cached_tokens");
9339
9580
  saveIfExistsTo("cache_creation_input_tokens", "prompt_cache_creation_tokens");
9581
+ if (isObject(usage.server_tool_use)) {
9582
+ for (const [name, value] of Object.entries(usage.server_tool_use)) {
9583
+ if (typeof value === "number") {
9584
+ metrics[`server_tool_use_${name}`] = value;
9585
+ }
9586
+ }
9587
+ }
9340
9588
  return metrics;
9341
9589
  }
9342
- function aggregateAnthropicStreamChunks(chunks) {
9343
- const fallbackTextDeltas = [];
9344
- const contentBlocks = {};
9345
- const contentBlockDeltas = {};
9346
- let metrics = {};
9347
- let metadata = {};
9348
- let role;
9349
- for (const event of chunks) {
9350
- switch (event?.type) {
9351
- case "message_start":
9352
- if (event.message?.usage) {
9353
- const initialMetrics = parseMetricsFromUsage2(event.message.usage);
9354
- metrics = { ...metrics, ...initialMetrics };
9355
- }
9356
- if (typeof event.message?.role === "string") {
9357
- role = event.message.role;
9358
- }
9359
- break;
9360
- case "content_block_start":
9361
- if (event.content_block) {
9362
- contentBlocks[event.index] = event.content_block;
9363
- contentBlockDeltas[event.index] = { textDeltas: [], citations: [] };
9364
- }
9365
- break;
9366
- case "content_block_delta": {
9367
- const acc = contentBlockDeltas[event.index];
9368
- const delta = event.delta;
9369
- if (!delta) break;
9370
- if (delta.type === "text_delta" && "text" in delta) {
9371
- const text = delta.text;
9372
- if (text) {
9373
- if (acc !== void 0) {
9374
- acc.textDeltas.push(text);
9375
- } else {
9376
- fallbackTextDeltas.push(text);
9590
+ function extractAnthropicToolRunnerMetadata(params) {
9591
+ const metadata = filterFrom(params, ["messages", "system", "tools"]);
9592
+ const toolNames = extractAnthropicToolNames(params.tools);
9593
+ return {
9594
+ ...metadata,
9595
+ operation: "toolRunner",
9596
+ ...toolNames.length > 0 ? { tool_names: toolNames } : {}
9597
+ };
9598
+ }
9599
+ function extractAnthropicToolNames(tools) {
9600
+ const toolNames = [];
9601
+ for (const tool of tools) {
9602
+ if (!tool || typeof tool !== "object") {
9603
+ continue;
9604
+ }
9605
+ const toolRecord = tool;
9606
+ if (typeof toolRecord.name === "string") {
9607
+ toolNames.push(toolRecord.name);
9608
+ continue;
9609
+ }
9610
+ if (typeof toolRecord.mcp_server_name === "string") {
9611
+ toolNames.push(toolRecord.mcp_server_name);
9612
+ }
9613
+ }
9614
+ return toolNames;
9615
+ }
9616
+ function toErrorMessage(error) {
9617
+ return error instanceof Error ? error.message : String(error);
9618
+ }
9619
+ function getAnthropicToolRunnerInput(args) {
9620
+ return args.length > 0 ? args[0] : void 0;
9621
+ }
9622
+ function wrapAnthropicToolRunnerTools(params, state) {
9623
+ if (!Array.isArray(params.tools)) {
9624
+ return;
9625
+ }
9626
+ params.tools = params.tools.map(
9627
+ (tool, index) => wrapAnthropicToolRunnerTool(tool, index, state)
9628
+ );
9629
+ }
9630
+ function wrapAnthropicToolRunnerTool(tool, index, state) {
9631
+ if (!tool || typeof tool !== "object" || typeof tool.run !== "function" || tool[ANTHROPIC_TOOL_RUNNER_TOOL_WRAPPED]) {
9632
+ return tool;
9633
+ }
9634
+ const toolName = typeof tool.name === "string" ? tool.name : `tool[${index}]`;
9635
+ const originalRun = tool.run;
9636
+ const runDescriptor = Object.getOwnPropertyDescriptor(tool, "run");
9637
+ const wrappedTool = Object.create(
9638
+ Object.getPrototypeOf(tool),
9639
+ Object.getOwnPropertyDescriptors(tool)
9640
+ );
9641
+ Object.defineProperty(wrappedTool, "run", {
9642
+ configurable: runDescriptor?.configurable ?? true,
9643
+ enumerable: runDescriptor?.enumerable ?? true,
9644
+ value: function braintrustAnthropicToolRunnerRun(...args) {
9645
+ return state.span.traced(
9646
+ (span) => {
9647
+ const finalizeSuccess = (result) => {
9648
+ span.log({ output: result });
9649
+ return result;
9650
+ };
9651
+ const finalizeError = (error) => {
9652
+ span.log({ error: toErrorMessage(error) });
9653
+ throw error;
9654
+ };
9655
+ try {
9656
+ const result = Reflect.apply(originalRun, this, args);
9657
+ if (isPromiseLike(result)) {
9658
+ return result.then(finalizeSuccess, finalizeError);
9377
9659
  }
9660
+ return finalizeSuccess(result);
9661
+ } catch (error) {
9662
+ return finalizeError(error);
9378
9663
  }
9379
- } else if (delta.type === "input_json_delta" && "partial_json" in delta) {
9380
- const partialJson = delta.partial_json;
9381
- if (partialJson && acc !== void 0) {
9382
- acc.textDeltas.push(partialJson);
9383
- }
9384
- } else if (delta.type === "thinking_delta" && "thinking" in delta) {
9385
- const thinking = delta.thinking;
9386
- if (thinking && acc !== void 0) {
9387
- acc.textDeltas.push(thinking);
9388
- }
9389
- } else if (delta.type === "citations_delta" && "citation" in delta) {
9390
- const citation = delta.citation;
9391
- if (citation && acc !== void 0) {
9392
- acc.citations.push(citation);
9664
+ },
9665
+ {
9666
+ event: {
9667
+ input: getAnthropicToolRunnerInput(args),
9668
+ metadata: {
9669
+ "gen_ai.tool.name": toolName,
9670
+ provider: "anthropic"
9671
+ }
9672
+ },
9673
+ name: `tool: ${toolName}`,
9674
+ spanAttributes: {
9675
+ type: "tool" /* TOOL */
9393
9676
  }
9394
9677
  }
9395
- break;
9396
- }
9397
- case "content_block_stop":
9398
- finalizeContentBlock(
9399
- event.index,
9400
- contentBlocks,
9401
- contentBlockDeltas,
9402
- fallbackTextDeltas
9403
- );
9404
- break;
9405
- case "message_delta":
9678
+ );
9679
+ },
9680
+ writable: runDescriptor?.writable ?? true
9681
+ });
9682
+ Object.defineProperty(wrappedTool, ANTHROPIC_TOOL_RUNNER_TOOL_WRAPPED, {
9683
+ configurable: false,
9684
+ enumerable: false,
9685
+ value: true,
9686
+ writable: false
9687
+ });
9688
+ return wrappedTool;
9689
+ }
9690
+ function getAnthropicToolRunnerParams(runnerRecord) {
9691
+ const params = Reflect.get(runnerRecord, "params");
9692
+ return params && typeof params === "object" ? params : void 0;
9693
+ }
9694
+ function ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state) {
9695
+ const params = getAnthropicToolRunnerParams(runnerRecord);
9696
+ if (params) {
9697
+ wrapAnthropicToolRunnerTools(params, state);
9698
+ }
9699
+ }
9700
+ function wrapAnthropicToolRunnerSetMessagesParams(runnerRecord, state) {
9701
+ const setMessagesParams = Reflect.get(runnerRecord, "setMessagesParams");
9702
+ if (typeof setMessagesParams !== "function") {
9703
+ return;
9704
+ }
9705
+ Reflect.set(
9706
+ runnerRecord,
9707
+ "setMessagesParams",
9708
+ function patchedSetMessagesParams(...args) {
9709
+ const result = Reflect.apply(setMessagesParams, this, args);
9710
+ const nextParams = getAnthropicToolRunnerParams(runnerRecord);
9711
+ if (nextParams) {
9712
+ wrapAnthropicToolRunnerTools(nextParams, state);
9713
+ }
9714
+ return result;
9715
+ }
9716
+ );
9717
+ }
9718
+ function isAnthropicMessage(value) {
9719
+ return !!value && typeof value === "object" && typeof value.role === "string" && Array.isArray(value.content);
9720
+ }
9721
+ function isAnthropicMessageStream(value) {
9722
+ return !!value && typeof value === "object" && isAsyncIterable(value) && "finalMessage" in value && typeof value.finalMessage === "function";
9723
+ }
9724
+ function recordAnthropicToolRunnerMessage(state, message) {
9725
+ if (typeof message !== "object" || message === null) {
9726
+ return;
9727
+ }
9728
+ if (state.seenMessages.has(message)) {
9729
+ state.lastMessage = message;
9730
+ return;
9731
+ }
9732
+ state.seenMessages.add(message);
9733
+ state.lastMessage = message;
9734
+ const parsedMetrics = parseMetricsFromUsage2(message.usage);
9735
+ for (const [key, value] of Object.entries(parsedMetrics)) {
9736
+ if (typeof value === "number") {
9737
+ state.aggregatedMetrics[key] = (state.aggregatedMetrics[key] ?? 0) + value;
9738
+ }
9739
+ }
9740
+ }
9741
+ function instrumentAnthropicMessageStream(stream, state) {
9742
+ if ("__braintrust_tool_runner_stream_patched" in stream) {
9743
+ return;
9744
+ }
9745
+ if (!Object.isFrozen(stream) && !Object.isSealed(stream)) {
9746
+ patchStreamIfNeeded(stream, {
9747
+ onChunk: () => {
9748
+ if (state.firstTokenTime === void 0) {
9749
+ state.firstTokenTime = getCurrentUnixTimestamp();
9750
+ }
9751
+ },
9752
+ onComplete: () => void 0
9753
+ });
9754
+ }
9755
+ if (typeof stream.finalMessage === "function") {
9756
+ const originalFinalMessage = stream.finalMessage.bind(stream);
9757
+ stream.finalMessage = async () => {
9758
+ const message = await originalFinalMessage();
9759
+ recordAnthropicToolRunnerMessage(state, message);
9760
+ return message;
9761
+ };
9762
+ }
9763
+ Object.defineProperty(stream, "__braintrust_tool_runner_stream_patched", {
9764
+ value: true
9765
+ });
9766
+ }
9767
+ async function finalizeAnthropicToolRunner(state, finalMessage) {
9768
+ if (state.finalized) {
9769
+ return;
9770
+ }
9771
+ state.finalized = true;
9772
+ const message = finalMessage ?? state.lastMessage;
9773
+ if (message) {
9774
+ recordAnthropicToolRunnerMessage(state, message);
9775
+ }
9776
+ const metrics = finalizeAnthropicTokens({
9777
+ ...state.aggregatedMetrics
9778
+ });
9779
+ if (state.firstTokenTime !== void 0) {
9780
+ metrics.time_to_first_token = state.firstTokenTime - state.startTime;
9781
+ }
9782
+ const metadata = {
9783
+ anthropic_tool_runner_iterations: state.iterationCount
9784
+ };
9785
+ if (message?.stop_reason !== void 0) {
9786
+ metadata.stop_reason = message.stop_reason;
9787
+ }
9788
+ if (message?.stop_sequence !== void 0) {
9789
+ metadata.stop_sequence = message.stop_sequence;
9790
+ }
9791
+ state.span.log({
9792
+ ...message ? { output: { role: message.role, content: message.content } } : {},
9793
+ metadata,
9794
+ metrics: Object.fromEntries(
9795
+ Object.entries(metrics).filter(
9796
+ (entry) => entry[1] !== void 0
9797
+ )
9798
+ )
9799
+ });
9800
+ state.span.end();
9801
+ }
9802
+ function finalizeAnthropicToolRunnerError(state, error) {
9803
+ if (state.finalized) {
9804
+ return;
9805
+ }
9806
+ state.finalized = true;
9807
+ state.span.log({
9808
+ error: error instanceof Error ? error.message : String(error)
9809
+ });
9810
+ state.span.end();
9811
+ }
9812
+ async function resolveAnthropicToolRunnerFinalMessage(runner) {
9813
+ if (typeof runner.done === "function") {
9814
+ return await runner.done();
9815
+ }
9816
+ if (typeof runner.runUntilDone === "function") {
9817
+ return await runner.runUntilDone();
9818
+ }
9819
+ return void 0;
9820
+ }
9821
+ function wrapAnthropicToolRunnerPromiseMethod(runnerRecord, methodName, state) {
9822
+ const method = runnerRecord[methodName];
9823
+ if (typeof method !== "function") {
9824
+ return;
9825
+ }
9826
+ runnerRecord[methodName] = async (...args) => {
9827
+ ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state);
9828
+ return await withCurrent(state.span, async () => {
9829
+ try {
9830
+ const message = await method.apply(runnerRecord, args);
9831
+ recordAnthropicToolRunnerMessage(state, message);
9832
+ await finalizeAnthropicToolRunner(state, message);
9833
+ return message;
9834
+ } catch (error) {
9835
+ finalizeAnthropicToolRunnerError(state, error);
9836
+ throw error;
9837
+ }
9838
+ });
9839
+ };
9840
+ }
9841
+ function patchAnthropicToolRunner(args) {
9842
+ const { runner, state } = args;
9843
+ if (!runner || typeof runner !== "object") {
9844
+ void finalizeAnthropicToolRunner(state);
9845
+ return;
9846
+ }
9847
+ const runnerRecord = runner;
9848
+ if ("__braintrust_tool_runner_patched" in runnerRecord) {
9849
+ return;
9850
+ }
9851
+ ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state);
9852
+ wrapAnthropicToolRunnerSetMessagesParams(runnerRecord, state);
9853
+ wrapAnthropicToolRunnerPromiseMethod(runnerRecord, "done", state);
9854
+ wrapAnthropicToolRunnerPromiseMethod(runnerRecord, "runUntilDone", state);
9855
+ if (!isAsyncIterable(runnerRecord)) {
9856
+ Object.defineProperty(runnerRecord, "__braintrust_tool_runner_patched", {
9857
+ value: true
9858
+ });
9859
+ return;
9860
+ }
9861
+ const originalIterator = runnerRecord[Symbol.asyncIterator].bind(runnerRecord);
9862
+ runnerRecord[Symbol.asyncIterator] = function() {
9863
+ const iterator = originalIterator();
9864
+ return {
9865
+ async next(value) {
9866
+ try {
9867
+ ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state);
9868
+ const result = await withCurrent(
9869
+ state.span,
9870
+ () => value === void 0 ? iterator.next() : iterator.next(value)
9871
+ );
9872
+ if (result.done) {
9873
+ const finalMessage = await resolveAnthropicToolRunnerFinalMessage(runner);
9874
+ await finalizeAnthropicToolRunner(state, finalMessage);
9875
+ return result;
9876
+ }
9877
+ state.iterationCount += 1;
9878
+ if (isAnthropicMessage(result.value)) {
9879
+ if (state.firstTokenTime === void 0) {
9880
+ state.firstTokenTime = getCurrentUnixTimestamp();
9881
+ }
9882
+ recordAnthropicToolRunnerMessage(state, result.value);
9883
+ } else if (isAnthropicMessageStream(result.value)) {
9884
+ instrumentAnthropicMessageStream(result.value, state);
9885
+ }
9886
+ return result;
9887
+ } catch (error) {
9888
+ finalizeAnthropicToolRunnerError(state, error);
9889
+ throw error;
9890
+ }
9891
+ },
9892
+ async return(value) {
9893
+ try {
9894
+ ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state);
9895
+ const result = typeof iterator.return === "function" ? await withCurrent(state.span, () => iterator.return(value)) : { done: true, value };
9896
+ const finalMessage = await resolveAnthropicToolRunnerFinalMessage(
9897
+ runner
9898
+ ).catch(() => void 0);
9899
+ await finalizeAnthropicToolRunner(state, finalMessage);
9900
+ return result;
9901
+ } catch (error) {
9902
+ finalizeAnthropicToolRunnerError(state, error);
9903
+ throw error;
9904
+ }
9905
+ },
9906
+ async throw(error) {
9907
+ finalizeAnthropicToolRunnerError(state, error);
9908
+ if (typeof iterator.throw === "function") {
9909
+ return await withCurrent(state.span, () => iterator.throw(error));
9910
+ }
9911
+ throw error;
9912
+ },
9913
+ [Symbol.asyncIterator]() {
9914
+ return this;
9915
+ }
9916
+ };
9917
+ };
9918
+ Object.defineProperty(runnerRecord, "__braintrust_tool_runner_patched", {
9919
+ value: true
9920
+ });
9921
+ }
9922
+ function aggregateAnthropicStreamChunks(chunks) {
9923
+ const fallbackTextDeltas = [];
9924
+ const contentBlocks = {};
9925
+ const contentBlockDeltas = {};
9926
+ let metrics = {};
9927
+ let metadata = {};
9928
+ let role;
9929
+ for (const event of chunks) {
9930
+ switch (event?.type) {
9931
+ case "message_start":
9932
+ if (event.message?.usage) {
9933
+ const initialMetrics = parseMetricsFromUsage2(event.message.usage);
9934
+ metrics = { ...metrics, ...initialMetrics };
9935
+ }
9936
+ if (typeof event.message?.role === "string") {
9937
+ role = event.message.role;
9938
+ }
9939
+ break;
9940
+ case "content_block_start":
9941
+ if (event.content_block) {
9942
+ contentBlocks[event.index] = event.content_block;
9943
+ contentBlockDeltas[event.index] = { textDeltas: [], citations: [] };
9944
+ }
9945
+ break;
9946
+ case "content_block_delta": {
9947
+ const acc = contentBlockDeltas[event.index];
9948
+ const delta = event.delta;
9949
+ if (!delta) break;
9950
+ if (delta.type === "text_delta" && "text" in delta) {
9951
+ const text = delta.text;
9952
+ if (text) {
9953
+ if (acc !== void 0) {
9954
+ acc.textDeltas.push(text);
9955
+ } else {
9956
+ fallbackTextDeltas.push(text);
9957
+ }
9958
+ }
9959
+ } else if (delta.type === "input_json_delta" && "partial_json" in delta) {
9960
+ const partialJson = delta.partial_json;
9961
+ if (partialJson && acc !== void 0) {
9962
+ acc.textDeltas.push(partialJson);
9963
+ }
9964
+ } else if (delta.type === "thinking_delta" && "thinking" in delta) {
9965
+ const thinking = delta.thinking;
9966
+ if (thinking && acc !== void 0) {
9967
+ acc.textDeltas.push(thinking);
9968
+ }
9969
+ } else if (delta.type === "citations_delta" && "citation" in delta) {
9970
+ const citation = delta.citation;
9971
+ if (citation && acc !== void 0) {
9972
+ acc.citations.push(citation);
9973
+ }
9974
+ }
9975
+ break;
9976
+ }
9977
+ case "content_block_stop":
9978
+ finalizeContentBlock(
9979
+ event.index,
9980
+ contentBlocks,
9981
+ contentBlockDeltas,
9982
+ fallbackTextDeltas
9983
+ );
9984
+ break;
9985
+ case "message_delta":
9406
9986
  if (event.usage) {
9407
9987
  const finalMetrics = parseMetricsFromUsage2(event.usage);
9408
9988
  metrics = { ...metrics, ...finalMetrics };
@@ -9447,15 +10027,24 @@ function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallback
9447
10027
  }
9448
10028
  const acc = contentBlockDeltas[index];
9449
10029
  const text = acc?.textDeltas.join("") ?? "";
9450
- if (isToolUseContentBlock(contentBlock)) {
10030
+ if (isToolUseLikeContentBlock(contentBlock)) {
9451
10031
  if (!text) {
9452
10032
  return;
9453
10033
  }
9454
10034
  try {
9455
- contentBlocks[index] = {
9456
- ...contentBlock,
9457
- input: JSON.parse(text)
10035
+ const parsedInput = JSON.parse(text);
10036
+ if (!isObject(parsedInput)) {
10037
+ fallbackTextDeltas.push(text);
10038
+ delete contentBlocks[index];
10039
+ return;
10040
+ }
10041
+ const parsedToolUseBlock = {
10042
+ type: contentBlock.type,
10043
+ id: contentBlock.id,
10044
+ name: contentBlock.name,
10045
+ input: parsedInput
9458
10046
  };
10047
+ contentBlocks[index] = parsedToolUseBlock;
9459
10048
  } catch {
9460
10049
  fallbackTextDeltas.push(text);
9461
10050
  delete contentBlocks[index];
@@ -9489,8 +10078,8 @@ function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallback
9489
10078
  function isTextContentBlock(contentBlock) {
9490
10079
  return contentBlock.type === "text";
9491
10080
  }
9492
- function isToolUseContentBlock(contentBlock) {
9493
- return contentBlock.type === "tool_use";
10081
+ function isToolUseLikeContentBlock(contentBlock) {
10082
+ return (contentBlock.type === "tool_use" || contentBlock.type === "server_tool_use") && typeof contentBlock.id === "string" && typeof contentBlock.name === "string" && isObject(contentBlock.input);
9494
10083
  }
9495
10084
  function isThinkingContentBlock(contentBlock) {
9496
10085
  return contentBlock.type === "thinking";
@@ -9688,6 +10277,10 @@ var aiSDKChannels = defineChannels("ai", {
9688
10277
  channelName: "embedMany",
9689
10278
  kind: "async"
9690
10279
  }),
10280
+ rerank: channel({
10281
+ channelName: "rerank",
10282
+ kind: "async"
10283
+ }),
9691
10284
  agentGenerate: channel({
9692
10285
  channelName: "Agent.generate",
9693
10286
  kind: "async"
@@ -9747,7 +10340,7 @@ var AISDKPlugin = class extends BasePlugin {
9747
10340
  this.unsubscribers.push(
9748
10341
  traceStreamingChannel(aiSDKChannels.generateText, {
9749
10342
  name: "generateText",
9750
- type: "llm" /* LLM */,
10343
+ type: "function" /* FUNCTION */,
9751
10344
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9752
10345
  extractOutput: (result, endEvent) => {
9753
10346
  finalizeAISDKChildTracing(endEvent);
@@ -9763,7 +10356,7 @@ var AISDKPlugin = class extends BasePlugin {
9763
10356
  this.unsubscribers.push(
9764
10357
  traceStreamingChannel(aiSDKChannels.streamText, {
9765
10358
  name: "streamText",
9766
- type: "llm" /* LLM */,
10359
+ type: "function" /* FUNCTION */,
9767
10360
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9768
10361
  extractOutput: (result, endEvent) => processAISDKOutput(
9769
10362
  result,
@@ -9783,7 +10376,7 @@ var AISDKPlugin = class extends BasePlugin {
9783
10376
  this.unsubscribers.push(
9784
10377
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
9785
10378
  name: "streamText",
9786
- type: "llm" /* LLM */,
10379
+ type: "function" /* FUNCTION */,
9787
10380
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9788
10381
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
9789
10382
  defaultDenyOutputPaths: denyOutputPaths,
@@ -9797,7 +10390,7 @@ var AISDKPlugin = class extends BasePlugin {
9797
10390
  this.unsubscribers.push(
9798
10391
  traceStreamingChannel(aiSDKChannels.generateObject, {
9799
10392
  name: "generateObject",
9800
- type: "llm" /* LLM */,
10393
+ type: "function" /* FUNCTION */,
9801
10394
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9802
10395
  extractOutput: (result, endEvent) => {
9803
10396
  finalizeAISDKChildTracing(endEvent);
@@ -9813,7 +10406,7 @@ var AISDKPlugin = class extends BasePlugin {
9813
10406
  this.unsubscribers.push(
9814
10407
  traceStreamingChannel(aiSDKChannels.streamObject, {
9815
10408
  name: "streamObject",
9816
- type: "llm" /* LLM */,
10409
+ type: "function" /* FUNCTION */,
9817
10410
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9818
10411
  extractOutput: (result, endEvent) => processAISDKOutput(
9819
10412
  result,
@@ -9833,7 +10426,7 @@ var AISDKPlugin = class extends BasePlugin {
9833
10426
  this.unsubscribers.push(
9834
10427
  traceSyncStreamChannel(aiSDKChannels.streamObjectSync, {
9835
10428
  name: "streamObject",
9836
- type: "llm" /* LLM */,
10429
+ type: "function" /* FUNCTION */,
9837
10430
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9838
10431
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
9839
10432
  defaultDenyOutputPaths: denyOutputPaths,
@@ -9847,7 +10440,7 @@ var AISDKPlugin = class extends BasePlugin {
9847
10440
  this.unsubscribers.push(
9848
10441
  traceAsyncChannel(aiSDKChannels.embed, {
9849
10442
  name: "embed",
9850
- type: "llm" /* LLM */,
10443
+ type: "function" /* FUNCTION */,
9851
10444
  extractInput: ([params], event) => prepareAISDKEmbedInput(params, event.self),
9852
10445
  extractOutput: (result, endEvent) => processAISDKEmbeddingOutput(
9853
10446
  result,
@@ -9859,7 +10452,7 @@ var AISDKPlugin = class extends BasePlugin {
9859
10452
  this.unsubscribers.push(
9860
10453
  traceAsyncChannel(aiSDKChannels.embedMany, {
9861
10454
  name: "embedMany",
9862
- type: "llm" /* LLM */,
10455
+ type: "function" /* FUNCTION */,
9863
10456
  extractInput: ([params], event) => prepareAISDKEmbedInput(params, event.self),
9864
10457
  extractOutput: (result, endEvent) => processAISDKEmbeddingOutput(
9865
10458
  result,
@@ -9868,10 +10461,22 @@ var AISDKPlugin = class extends BasePlugin {
9868
10461
  extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent)
9869
10462
  })
9870
10463
  );
10464
+ this.unsubscribers.push(
10465
+ traceAsyncChannel(aiSDKChannels.rerank, {
10466
+ name: "rerank",
10467
+ type: "function" /* FUNCTION */,
10468
+ extractInput: ([params], event) => prepareAISDKRerankInput(params, event.self),
10469
+ extractOutput: (result, endEvent) => processAISDKRerankOutput(
10470
+ result,
10471
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
10472
+ ),
10473
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent)
10474
+ })
10475
+ );
9871
10476
  this.unsubscribers.push(
9872
10477
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
9873
10478
  name: "Agent.generate",
9874
- type: "llm" /* LLM */,
10479
+ type: "function" /* FUNCTION */,
9875
10480
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9876
10481
  extractOutput: (result, endEvent) => {
9877
10482
  finalizeAISDKChildTracing(endEvent);
@@ -9887,7 +10492,7 @@ var AISDKPlugin = class extends BasePlugin {
9887
10492
  this.unsubscribers.push(
9888
10493
  traceStreamingChannel(aiSDKChannels.agentStream, {
9889
10494
  name: "Agent.stream",
9890
- type: "llm" /* LLM */,
10495
+ type: "function" /* FUNCTION */,
9891
10496
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9892
10497
  extractOutput: (result, endEvent) => processAISDKOutput(
9893
10498
  result,
@@ -9907,7 +10512,7 @@ var AISDKPlugin = class extends BasePlugin {
9907
10512
  this.unsubscribers.push(
9908
10513
  traceSyncStreamChannel(aiSDKChannels.agentStreamSync, {
9909
10514
  name: "Agent.stream",
9910
- type: "llm" /* LLM */,
10515
+ type: "function" /* FUNCTION */,
9911
10516
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9912
10517
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
9913
10518
  defaultDenyOutputPaths: denyOutputPaths,
@@ -9921,7 +10526,7 @@ var AISDKPlugin = class extends BasePlugin {
9921
10526
  this.unsubscribers.push(
9922
10527
  traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
9923
10528
  name: "ToolLoopAgent.generate",
9924
- type: "llm" /* LLM */,
10529
+ type: "function" /* FUNCTION */,
9925
10530
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9926
10531
  extractOutput: (result, endEvent) => {
9927
10532
  finalizeAISDKChildTracing(endEvent);
@@ -9937,7 +10542,7 @@ var AISDKPlugin = class extends BasePlugin {
9937
10542
  this.unsubscribers.push(
9938
10543
  traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
9939
10544
  name: "ToolLoopAgent.stream",
9940
- type: "llm" /* LLM */,
10545
+ type: "function" /* FUNCTION */,
9941
10546
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9942
10547
  extractOutput: (result, endEvent) => processAISDKOutput(
9943
10548
  result,
@@ -10287,6 +10892,16 @@ function prepareAISDKEmbedInput(params, self) {
10287
10892
  metadata: extractMetadataFromEmbedParams(params, self)
10288
10893
  };
10289
10894
  }
10895
+ function prepareAISDKRerankInput(params, self) {
10896
+ const { documents, query } = params;
10897
+ return {
10898
+ input: {
10899
+ documents,
10900
+ query
10901
+ },
10902
+ metadata: extractMetadataFromRerankParams(params, self)
10903
+ };
10904
+ }
10290
10905
  function extractTopLevelAISDKMetrics(result, event, startTime) {
10291
10906
  const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
10292
10907
  if (startTime) {
@@ -10332,6 +10947,16 @@ function extractMetadataFromCallParams(params, self) {
10332
10947
  function extractMetadataFromEmbedParams(params, self) {
10333
10948
  return extractBaseMetadata(params.model, self);
10334
10949
  }
10950
+ function extractMetadataFromRerankParams(params, self) {
10951
+ const metadata = extractBaseMetadata(params.model, self);
10952
+ if (typeof params.topN === "number") {
10953
+ metadata.topN = params.topN;
10954
+ }
10955
+ if (Array.isArray(params.documents)) {
10956
+ metadata.document_count = params.documents.length;
10957
+ }
10958
+ return metadata;
10959
+ }
10335
10960
  function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
10336
10961
  const cleanup = [];
10337
10962
  const patchedModels = /* @__PURE__ */ new WeakSet();
@@ -10879,6 +11504,22 @@ function processAISDKEmbeddingOutput(output, denyOutputPaths) {
10879
11504
  }
10880
11505
  return normalizeAISDKLoggedOutput(omit(summarized, denyOutputPaths));
10881
11506
  }
11507
+ function processAISDKRerankOutput(output, _denyOutputPaths) {
11508
+ if (!output || typeof output !== "object") {
11509
+ return output;
11510
+ }
11511
+ const ranking = safeSerializableFieldRead(output, "ranking");
11512
+ if (Array.isArray(ranking)) {
11513
+ return ranking.slice(0, 100).map((item) => {
11514
+ const entry = item && typeof item === "object" ? item : void 0;
11515
+ return {
11516
+ index: typeof entry?.originalIndex === "number" ? entry.originalIndex : void 0,
11517
+ relevance_score: typeof entry?.score === "number" ? entry.score : void 0
11518
+ };
11519
+ });
11520
+ }
11521
+ return void 0;
11522
+ }
10882
11523
  function extractTokenMetrics(result) {
10883
11524
  const metrics = {};
10884
11525
  let usage;
@@ -10921,12 +11562,80 @@ function extractTokenMetrics(result) {
10921
11562
  if (totalTokens !== void 0) {
10922
11563
  metrics.tokens = totalTokens;
10923
11564
  }
11565
+ const promptCachedTokens = firstNumber(
11566
+ usage.inputTokens?.cacheRead,
11567
+ usage.inputTokenDetails?.cacheReadTokens,
11568
+ usage.cachedInputTokens,
11569
+ usage.promptCachedTokens,
11570
+ usage.prompt_cached_tokens
11571
+ );
11572
+ if (promptCachedTokens !== void 0) {
11573
+ metrics.prompt_cached_tokens = promptCachedTokens;
11574
+ }
11575
+ const promptCacheCreationTokens = firstNumber(
11576
+ usage.inputTokens?.cacheWrite,
11577
+ usage.inputTokenDetails?.cacheWriteTokens,
11578
+ usage.promptCacheCreationTokens,
11579
+ usage.prompt_cache_creation_tokens,
11580
+ extractAnthropicCacheCreationTokens(result)
11581
+ );
11582
+ if (promptCacheCreationTokens !== void 0) {
11583
+ metrics.prompt_cache_creation_tokens = promptCacheCreationTokens;
11584
+ }
11585
+ const promptReasoningTokens = firstNumber(
11586
+ usage.promptReasoningTokens,
11587
+ usage.prompt_reasoning_tokens
11588
+ );
11589
+ if (promptReasoningTokens !== void 0) {
11590
+ metrics.prompt_reasoning_tokens = promptReasoningTokens;
11591
+ }
11592
+ const completionCachedTokens = firstNumber(
11593
+ usage.completionCachedTokens,
11594
+ usage.completion_cached_tokens
11595
+ );
11596
+ if (completionCachedTokens !== void 0) {
11597
+ metrics.completion_cached_tokens = completionCachedTokens;
11598
+ }
11599
+ const reasoningTokenCount = firstNumber(
11600
+ usage.outputTokens?.reasoning,
11601
+ usage.reasoningTokens,
11602
+ usage.completionReasoningTokens,
11603
+ usage.completion_reasoning_tokens,
11604
+ usage.reasoning_tokens,
11605
+ usage.thinkingTokens,
11606
+ usage.thinking_tokens
11607
+ );
11608
+ if (reasoningTokenCount !== void 0) {
11609
+ metrics.completion_reasoning_tokens = reasoningTokenCount;
11610
+ metrics.reasoning_tokens = reasoningTokenCount;
11611
+ }
11612
+ const completionAudioTokens = firstNumber(
11613
+ usage.completionAudioTokens,
11614
+ usage.completion_audio_tokens
11615
+ );
11616
+ if (completionAudioTokens !== void 0) {
11617
+ metrics.completion_audio_tokens = completionAudioTokens;
11618
+ }
10924
11619
  const cost = extractCostFromResult(result);
10925
11620
  if (cost !== void 0) {
10926
11621
  metrics.estimated_cost = cost;
10927
11622
  }
10928
11623
  return metrics;
10929
11624
  }
11625
+ function extractAnthropicCacheCreationTokens(result) {
11626
+ const providerMetadata = safeSerializableFieldRead(
11627
+ result,
11628
+ "providerMetadata"
11629
+ );
11630
+ const anthropicMetadata = providerMetadata?.anthropic;
11631
+ if (!anthropicMetadata) {
11632
+ return void 0;
11633
+ }
11634
+ return firstNumber(
11635
+ anthropicMetadata.cacheCreationInputTokens,
11636
+ anthropicMetadata.usage?.cache_creation_input_tokens
11637
+ );
11638
+ }
10930
11639
  function safeResultFieldRead(result, field) {
10931
11640
  return safeSerializableFieldRead(result, field);
10932
11641
  }
@@ -11043,14 +11752,11 @@ function extractSerializableOutputFields(output) {
11043
11752
  ...extractGetterValues(output)
11044
11753
  };
11045
11754
  }
11046
- function isPromiseLike(value) {
11047
- return value != null && typeof value === "object" && typeof value.then === "function";
11048
- }
11049
11755
  function isSerializableOutputValue(value) {
11050
11756
  if (typeof value === "function") {
11051
11757
  return false;
11052
11758
  }
11053
- if (value && typeof value === "object" && typeof value.then === "function") {
11759
+ if (isPromiseLike(value)) {
11054
11760
  return false;
11055
11761
  }
11056
11762
  if (value && typeof value === "object" && typeof value.getReader === "function") {
@@ -11370,12 +12076,9 @@ function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
11370
12076
  var LOCAL_TOOL_HANDLER_WRAPPED = Symbol.for(
11371
12077
  "braintrust.claude_agent_sdk.local_tool_handler_wrapped"
11372
12078
  );
11373
- function toErrorMessage(error) {
12079
+ function toErrorMessage2(error) {
11374
12080
  return error instanceof Error ? error.message : String(error);
11375
12081
  }
11376
- function isPromiseLike2(value) {
11377
- return value !== null && typeof value === "object" && "then" in value && typeof value.then === "function";
11378
- }
11379
12082
  function getToolUseIdFromExtra(extra) {
11380
12083
  if (!extra || typeof extra !== "object" || !("_meta" in extra)) {
11381
12084
  return void 0;
@@ -11422,14 +12125,14 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
11422
12125
  return result;
11423
12126
  };
11424
12127
  const finalizeError = (error) => {
11425
- span.log({ error: toErrorMessage(error) });
12128
+ span.log({ error: toErrorMessage2(error) });
11426
12129
  span.end();
11427
12130
  throw error;
11428
12131
  };
11429
12132
  return withCurrent(span, () => {
11430
12133
  try {
11431
12134
  const result = runHandler();
11432
- if (isPromiseLike2(result)) {
12135
+ if (isPromiseLike(result)) {
11433
12136
  return result.then(finalizeSuccess, finalizeError);
11434
12137
  }
11435
12138
  return finalizeSuccess(result);
@@ -11549,7 +12252,7 @@ var ROOT_LLM_PARENT_KEY = "__root__";
11549
12252
  function llmParentKey(parentToolUseId) {
11550
12253
  return parentToolUseId ?? ROOT_LLM_PARENT_KEY;
11551
12254
  }
11552
- function isSubAgentToolName(toolName) {
12255
+ function isSubAgentDelegationToolName(toolName) {
11553
12256
  return toolName === "Agent" || toolName === "Task";
11554
12257
  }
11555
12258
  function filterSerializableOptions(options) {
@@ -11583,24 +12286,92 @@ function getNumberProperty(obj, key) {
11583
12286
  const value = Reflect.get(obj, key);
11584
12287
  return typeof value === "number" ? value : void 0;
11585
12288
  }
11586
- function extractUsageFromMessage(message) {
11587
- const metrics = {};
11588
- let usage;
11589
- if (message.type === "assistant") {
11590
- usage = message.message?.usage;
11591
- } else if (message.type === "result") {
11592
- usage = message.usage;
12289
+ function getStringProperty(obj, key) {
12290
+ if (!obj || typeof obj !== "object" || !(key in obj)) {
12291
+ return void 0;
11593
12292
  }
11594
- if (!usage || typeof usage !== "object") {
11595
- return metrics;
12293
+ const value = Reflect.get(obj, key);
12294
+ return typeof value === "string" ? value : void 0;
12295
+ }
12296
+ function upsertSubAgentDetails(detailsByToolUseId, toolUseId, update) {
12297
+ const existing = detailsByToolUseId.get(toolUseId) ?? {};
12298
+ const merged = {
12299
+ ...existing,
12300
+ ...Object.fromEntries(
12301
+ Object.entries(update).filter(([, value]) => value !== void 0)
12302
+ )
12303
+ };
12304
+ detailsByToolUseId.set(toolUseId, merged);
12305
+ return merged;
12306
+ }
12307
+ function formatSubAgentSpanName(details) {
12308
+ if (details?.description) {
12309
+ return `Agent: ${details.description}`;
11596
12310
  }
11597
- const inputTokens = getNumberProperty(usage, "input_tokens");
11598
- if (inputTokens !== void 0) {
11599
- metrics.prompt_tokens = inputTokens;
12311
+ if (details?.agentType) {
12312
+ return `Agent: ${details.agentType}`;
11600
12313
  }
11601
- const outputTokens = getNumberProperty(usage, "output_tokens");
11602
- if (outputTokens !== void 0) {
11603
- metrics.completion_tokens = outputTokens;
12314
+ return "Agent: sub-agent";
12315
+ }
12316
+ function subAgentDetailsToMetadata(details) {
12317
+ if (!details) {
12318
+ return {};
12319
+ }
12320
+ const metadata = {};
12321
+ if (details.agentId) {
12322
+ metadata["claude_agent_sdk.agent_id"] = details.agentId;
12323
+ }
12324
+ if (details.agentType) {
12325
+ metadata["claude_agent_sdk.agent_type"] = details.agentType;
12326
+ }
12327
+ if (details.description) {
12328
+ metadata["claude_agent_sdk.description"] = details.description;
12329
+ }
12330
+ if (details.taskId) {
12331
+ metadata["claude_agent_sdk.task_id"] = details.taskId;
12332
+ }
12333
+ if (details.taskType) {
12334
+ metadata["claude_agent_sdk.task_type"] = details.taskType;
12335
+ }
12336
+ if (details.toolUseId) {
12337
+ metadata["claude_agent_sdk.tool_use_id"] = details.toolUseId;
12338
+ }
12339
+ if (details.workflowName) {
12340
+ metadata["claude_agent_sdk.workflow_name"] = details.workflowName;
12341
+ }
12342
+ return metadata;
12343
+ }
12344
+ function resolveTaskToolUseId(taskIdToToolUseId, message) {
12345
+ const messageToolUseId = typeof message.tool_use_id === "string" ? message.tool_use_id : void 0;
12346
+ if (messageToolUseId && typeof message.task_id === "string") {
12347
+ taskIdToToolUseId.set(message.task_id, messageToolUseId);
12348
+ }
12349
+ if (messageToolUseId) {
12350
+ return messageToolUseId;
12351
+ }
12352
+ if (typeof message.task_id === "string") {
12353
+ return taskIdToToolUseId.get(message.task_id);
12354
+ }
12355
+ return void 0;
12356
+ }
12357
+ function extractUsageFromMessage(message) {
12358
+ const metrics = {};
12359
+ let usage;
12360
+ if (message.type === "assistant") {
12361
+ usage = message.message?.usage;
12362
+ } else if (message.type === "result") {
12363
+ usage = message.usage;
12364
+ }
12365
+ if (!usage || typeof usage !== "object") {
12366
+ return metrics;
12367
+ }
12368
+ const inputTokens = getNumberProperty(usage, "input_tokens");
12369
+ if (inputTokens !== void 0) {
12370
+ metrics.prompt_tokens = inputTokens;
12371
+ }
12372
+ const outputTokens = getNumberProperty(usage, "output_tokens");
12373
+ if (outputTokens !== void 0) {
12374
+ metrics.completion_tokens = outputTokens;
11604
12375
  }
11605
12376
  const cacheReadTokens = getNumberProperty(usage, "cache_read_input_tokens") || 0;
11606
12377
  const cacheCreationTokens = getNumberProperty(usage, "cache_creation_input_tokens") || 0;
@@ -11755,7 +12526,7 @@ function prepareLocalToolHandlersInMcpServers(mcpServers) {
11755
12526
  }
11756
12527
  return { hasLocalToolHandlers, localToolHookNames };
11757
12528
  }
11758
- function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentSpans, endedSubAgentSpans) {
12529
+ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
11759
12530
  const preToolUse = async (input, toolUseID) => {
11760
12531
  if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
11761
12532
  return {};
@@ -11763,9 +12534,6 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
11763
12534
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
11764
12535
  return {};
11765
12536
  }
11766
- if (isSubAgentToolName(input.tool_name)) {
11767
- return {};
11768
- }
11769
12537
  const parsed = parseToolName(input.tool_name);
11770
12538
  const toolSpan = startSpan({
11771
12539
  event: {
@@ -11795,10 +12563,18 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
11795
12563
  return {};
11796
12564
  }
11797
12565
  const subAgentSpan = subAgentSpans.get(toolUseID);
12566
+ const toolSpan = activeToolSpans.get(toolUseID);
11798
12567
  if (subAgentSpan) {
12568
+ if (endedSubAgentSpans.has(toolUseID)) {
12569
+ return {};
12570
+ }
11799
12571
  try {
11800
12572
  const response = input.tool_response;
11801
- const metadata = {};
12573
+ const metadata = {
12574
+ ...subAgentDetailsToMetadata(
12575
+ subAgentDetailsByToolUseId.get(toolUseID)
12576
+ )
12577
+ };
11802
12578
  if (response?.status) {
11803
12579
  metadata["claude_agent_sdk.status"] = response.status;
11804
12580
  }
@@ -11816,9 +12592,16 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
11816
12592
  subAgentSpan.end();
11817
12593
  endedSubAgentSpans.add(toolUseID);
11818
12594
  }
12595
+ if (toolSpan) {
12596
+ try {
12597
+ toolSpan.log({ output: input.tool_response });
12598
+ } finally {
12599
+ toolSpan.end();
12600
+ activeToolSpans.delete(toolUseID);
12601
+ }
12602
+ }
11819
12603
  return {};
11820
12604
  }
11821
- const toolSpan = activeToolSpans.get(toolUseID);
11822
12605
  if (!toolSpan) {
11823
12606
  return {};
11824
12607
  }
@@ -11838,16 +12621,43 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
11838
12621
  return {};
11839
12622
  }
11840
12623
  const subAgentSpan = subAgentSpans.get(toolUseID);
12624
+ const toolSpan = activeToolSpans.get(toolUseID);
11841
12625
  if (subAgentSpan) {
12626
+ if (endedSubAgentSpans.has(toolUseID)) {
12627
+ return {};
12628
+ }
11842
12629
  try {
11843
- subAgentSpan.log({ error: input.error });
12630
+ subAgentSpan.log({
12631
+ error: input.error,
12632
+ metadata: subAgentDetailsToMetadata(
12633
+ subAgentDetailsByToolUseId.get(toolUseID)
12634
+ )
12635
+ });
11844
12636
  } finally {
11845
12637
  subAgentSpan.end();
11846
12638
  endedSubAgentSpans.add(toolUseID);
11847
12639
  }
12640
+ if (toolSpan) {
12641
+ const parsed2 = parseToolName(input.tool_name);
12642
+ try {
12643
+ toolSpan.log({
12644
+ error: input.error,
12645
+ metadata: {
12646
+ "claude_agent_sdk.is_interrupt": input.is_interrupt,
12647
+ "claude_agent_sdk.session_id": input.session_id,
12648
+ "claude_agent_sdk.raw_tool_name": parsed2.rawToolName,
12649
+ "gen_ai.tool.call.id": toolUseID,
12650
+ "gen_ai.tool.name": parsed2.toolName,
12651
+ ...parsed2.mcpServer && { "mcp.server": parsed2.mcpServer }
12652
+ }
12653
+ });
12654
+ } finally {
12655
+ toolSpan.end();
12656
+ activeToolSpans.delete(toolUseID);
12657
+ }
12658
+ }
11848
12659
  return {};
11849
12660
  }
11850
- const toolSpan = activeToolSpans.get(toolUseID);
11851
12661
  if (!toolSpan) {
11852
12662
  return {};
11853
12663
  }
@@ -11869,15 +12679,84 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
11869
12679
  }
11870
12680
  return {};
11871
12681
  };
11872
- return { postToolUse, postToolUseFailure, preToolUse };
12682
+ const subagentStart = async (input, toolUseID) => {
12683
+ if (input.hook_event_name !== "SubagentStart" || !toolUseID) {
12684
+ return {};
12685
+ }
12686
+ const details = upsertSubAgentDetails(
12687
+ subAgentDetailsByToolUseId,
12688
+ toolUseID,
12689
+ {
12690
+ agentId: input.agent_id,
12691
+ agentType: input.agent_type,
12692
+ toolUseId: toolUseID
12693
+ }
12694
+ );
12695
+ const subAgentSpan = subAgentSpans.get(toolUseID);
12696
+ if (subAgentSpan && !endedSubAgentSpans.has(toolUseID)) {
12697
+ subAgentSpan.log({
12698
+ metadata: subAgentDetailsToMetadata(details)
12699
+ });
12700
+ }
12701
+ return {};
12702
+ };
12703
+ const subagentStop = async (input, toolUseID) => {
12704
+ if (input.hook_event_name !== "SubagentStop" || !toolUseID) {
12705
+ return {};
12706
+ }
12707
+ const details = upsertSubAgentDetails(
12708
+ subAgentDetailsByToolUseId,
12709
+ toolUseID,
12710
+ {
12711
+ agentId: input.agent_id,
12712
+ agentType: input.agent_type,
12713
+ toolUseId: toolUseID
12714
+ }
12715
+ );
12716
+ const subAgentSpan = subAgentSpans.get(toolUseID);
12717
+ if (!subAgentSpan || endedSubAgentSpans.has(toolUseID)) {
12718
+ return {};
12719
+ }
12720
+ const metadata = {
12721
+ ...subAgentDetailsToMetadata(details),
12722
+ ...input.agent_transcript_path && {
12723
+ "claude_agent_sdk.agent_transcript_path": input.agent_transcript_path
12724
+ },
12725
+ "claude_agent_sdk.stop_hook_active": input.stop_hook_active
12726
+ };
12727
+ try {
12728
+ subAgentSpan.log({
12729
+ metadata,
12730
+ output: input.last_assistant_message
12731
+ });
12732
+ } finally {
12733
+ subAgentSpan.end();
12734
+ endedSubAgentSpans.add(toolUseID);
12735
+ }
12736
+ return {};
12737
+ };
12738
+ return {
12739
+ postToolUse,
12740
+ postToolUseFailure,
12741
+ preToolUse,
12742
+ subagentStart,
12743
+ subagentStop
12744
+ };
11873
12745
  }
11874
- function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentSpans, endedSubAgentSpans) {
11875
- const { preToolUse, postToolUse, postToolUseFailure } = createToolTracingHooks(
12746
+ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
12747
+ const {
12748
+ preToolUse,
12749
+ postToolUse,
12750
+ postToolUseFailure,
12751
+ subagentStart,
12752
+ subagentStop
12753
+ } = createToolTracingHooks(
11876
12754
  resolveParentSpan,
11877
12755
  activeToolSpans,
11878
12756
  options.mcpServers,
11879
12757
  localToolHookNames,
11880
12758
  skipLocalToolHooks,
12759
+ subAgentDetailsByToolUseId,
11881
12760
  subAgentSpans,
11882
12761
  endedSubAgentSpans
11883
12762
  );
@@ -11899,6 +12778,18 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
11899
12778
  PreToolUse: [
11900
12779
  ...existingHooks.PreToolUse ?? [],
11901
12780
  { hooks: [preToolUse] }
12781
+ ],
12782
+ SubagentStart: [
12783
+ ...existingHooks.SubagentStart ?? [],
12784
+ {
12785
+ hooks: [subagentStart]
12786
+ }
12787
+ ],
12788
+ SubagentStop: [
12789
+ ...existingHooks.SubagentStop ?? [],
12790
+ {
12791
+ hooks: [subagentStop]
12792
+ }
11902
12793
  ]
11903
12794
  }
11904
12795
  };
@@ -11927,7 +12818,6 @@ async function finalizeCurrentMessageGroup(state) {
11927
12818
  parentSpan,
11928
12819
  existingLlmSpan
11929
12820
  );
11930
- state.activeLlmSpansByParentToolUse.delete(parentKey);
11931
12821
  if (llmSpanResult) {
11932
12822
  if (parentToolUseId) {
11933
12823
  state.latestLlmParentBySubAgentToolUse.set(
@@ -11941,6 +12831,7 @@ async function finalizeCurrentMessageGroup(state) {
11941
12831
  state.finalResults.push(llmSpanResult.finalMessage);
11942
12832
  }
11943
12833
  }
12834
+ state.activeLlmSpansByParentToolUse.delete(parentKey);
11944
12835
  const lastMessage = state.currentMessages[state.currentMessages.length - 1];
11945
12836
  if (lastMessage?.message?.usage) {
11946
12837
  state.accumulatedOutputTokens += getNumberProperty(lastMessage.message.usage, "output_tokens") || 0;
@@ -11957,8 +12848,12 @@ function maybeTrackToolUseContext(state, message) {
11957
12848
  continue;
11958
12849
  }
11959
12850
  state.toolUseToParent.set(block.id, parentToolUseId);
11960
- if (block.name === "Task" && typeof block.input === "object" && block.input !== null && "subagent_type" in block.input && typeof block.input.subagent_type === "string") {
11961
- state.pendingSubAgentNames.set(block.id, block.input.subagent_type);
12851
+ if (typeof block.name === "string" && isSubAgentDelegationToolName(block.name) && typeof block.input === "object" && block.input !== null) {
12852
+ upsertSubAgentDetails(state.subAgentDetailsByToolUseId, block.id, {
12853
+ agentType: getStringProperty(block.input, "subagent_type"),
12854
+ description: getStringProperty(block.input, "description"),
12855
+ toolUseId: block.id
12856
+ });
11962
12857
  }
11963
12858
  }
11964
12859
  }
@@ -11971,34 +12866,133 @@ async function maybeStartSubAgentSpan(state, message) {
11971
12866
  return;
11972
12867
  }
11973
12868
  await ensureSubAgentSpan(
11974
- state.pendingSubAgentNames,
12869
+ state.subAgentDetailsByToolUseId,
11975
12870
  state.span,
12871
+ state.activeToolSpans,
11976
12872
  state.subAgentSpans,
11977
12873
  parentToolUseId
11978
12874
  );
11979
12875
  }
11980
- async function ensureSubAgentSpan(pendingSubAgentNames, rootSpan, subAgentSpans, parentToolUseId) {
12876
+ async function ensureSubAgentSpan(subAgentDetailsByToolUseId, rootSpan, activeToolSpans, subAgentSpans, parentToolUseId) {
11981
12877
  const existingSpan = subAgentSpans.get(parentToolUseId);
11982
12878
  if (existingSpan) {
11983
12879
  return existingSpan;
11984
12880
  }
11985
- const agentName = pendingSubAgentNames.get(parentToolUseId);
11986
- const spanName = agentName ? `Agent: ${agentName}` : "Agent: sub-agent";
12881
+ const details = subAgentDetailsByToolUseId.get(parentToolUseId);
12882
+ const spanName = formatSubAgentSpanName(details);
12883
+ const parentToolSpan = activeToolSpans.get(parentToolUseId);
12884
+ const parentSpan = parentToolSpan ? await parentToolSpan.export() : await rootSpan.export();
11987
12885
  const subAgentSpan = startSpan({
11988
12886
  event: {
11989
- metadata: {
11990
- ...agentName && { "claude_agent_sdk.agent_type": agentName }
11991
- }
12887
+ metadata: subAgentDetailsToMetadata(details)
11992
12888
  },
11993
12889
  name: spanName,
11994
- parent: await rootSpan.export(),
12890
+ parent: parentSpan,
11995
12891
  spanAttributes: { type: "task" /* TASK */ }
11996
12892
  });
11997
12893
  subAgentSpans.set(parentToolUseId, subAgentSpan);
11998
12894
  return subAgentSpan;
11999
12895
  }
12896
+ async function maybeHandleTaskLifecycleMessage(state, message) {
12897
+ if (message.type !== "system") {
12898
+ return false;
12899
+ }
12900
+ if (message.subtype !== "task_started" && message.subtype !== "task_progress" && message.subtype !== "task_notification") {
12901
+ return false;
12902
+ }
12903
+ const toolUseId = resolveTaskToolUseId(state.taskIdToToolUseId, message);
12904
+ if (!toolUseId) {
12905
+ return true;
12906
+ }
12907
+ const details = upsertSubAgentDetails(
12908
+ state.subAgentDetailsByToolUseId,
12909
+ toolUseId,
12910
+ {
12911
+ description: getStringProperty(message, "description"),
12912
+ taskId: getStringProperty(message, "task_id"),
12913
+ taskType: getStringProperty(message, "task_type"),
12914
+ toolUseId,
12915
+ workflowName: getStringProperty(message, "workflow_name")
12916
+ }
12917
+ );
12918
+ const subAgentSpan = await ensureSubAgentSpan(
12919
+ state.subAgentDetailsByToolUseId,
12920
+ state.span,
12921
+ state.activeToolSpans,
12922
+ state.subAgentSpans,
12923
+ toolUseId
12924
+ );
12925
+ if (state.endedSubAgentSpans.has(toolUseId)) {
12926
+ return true;
12927
+ }
12928
+ const usage = message.usage;
12929
+ const usageTotalTokens = getNumberProperty(usage, "total_tokens");
12930
+ const usageToolUses = getNumberProperty(usage, "tool_uses");
12931
+ const usageDurationMs = getNumberProperty(usage, "duration_ms");
12932
+ const metadata = {
12933
+ ...subAgentDetailsToMetadata(details),
12934
+ "claude_agent_sdk.tool_use_id": toolUseId,
12935
+ ...usageTotalTokens !== void 0 && {
12936
+ "claude_agent_sdk.total_tokens": usageTotalTokens
12937
+ },
12938
+ ...usageToolUses !== void 0 && {
12939
+ "claude_agent_sdk.tool_use_count": usageToolUses
12940
+ },
12941
+ ...usageDurationMs !== void 0 && {
12942
+ "claude_agent_sdk.duration_ms": usageDurationMs
12943
+ }
12944
+ };
12945
+ if (message.subtype === "task_started") {
12946
+ const prompt = getStringProperty(message, "prompt");
12947
+ subAgentSpan.log({
12948
+ input: prompt,
12949
+ metadata
12950
+ });
12951
+ return true;
12952
+ }
12953
+ const summary = getStringProperty(message, "summary");
12954
+ if (summary) {
12955
+ metadata["claude_agent_sdk.summary"] = summary;
12956
+ }
12957
+ if (message.subtype === "task_progress") {
12958
+ const lastToolName = getStringProperty(message, "last_tool_name");
12959
+ if (lastToolName) {
12960
+ metadata["claude_agent_sdk.last_tool_name"] = lastToolName;
12961
+ }
12962
+ subAgentSpan.log({
12963
+ metadata,
12964
+ output: summary
12965
+ });
12966
+ return true;
12967
+ }
12968
+ const status = getStringProperty(message, "status");
12969
+ const outputFile = getStringProperty(message, "output_file");
12970
+ if (status) {
12971
+ metadata["claude_agent_sdk.task_status"] = status;
12972
+ }
12973
+ if (outputFile) {
12974
+ metadata["claude_agent_sdk.output_file"] = outputFile;
12975
+ }
12976
+ const output = summary || outputFile ? {
12977
+ ...summary && { summary },
12978
+ ...outputFile && { output_file: outputFile }
12979
+ } : void 0;
12980
+ try {
12981
+ subAgentSpan.log({
12982
+ metadata,
12983
+ output
12984
+ });
12985
+ } finally {
12986
+ subAgentSpan.end();
12987
+ state.endedSubAgentSpans.add(toolUseId);
12988
+ }
12989
+ return true;
12990
+ }
12000
12991
  async function handleStreamMessage(state, message) {
12001
12992
  maybeTrackToolUseContext(state, message);
12993
+ if (await maybeHandleTaskLifecycleMessage(state, message)) {
12994
+ return;
12995
+ }
12002
12996
  await maybeStartSubAgentSpan(state, message);
12003
12997
  const messageId = message.message?.id;
12004
12998
  if (messageId && messageId !== state.currentMessageId) {
@@ -12013,8 +13007,9 @@ async function handleStreamMessage(state, message) {
12013
13007
  let llmParentSpan = await state.span.export();
12014
13008
  if (parentToolUseId) {
12015
13009
  const subAgentSpan = await ensureSubAgentSpan(
12016
- state.pendingSubAgentNames,
13010
+ state.subAgentDetailsByToolUseId,
12017
13011
  state.span,
13012
+ state.activeToolSpans,
12018
13013
  state.subAgentSpans,
12019
13014
  parentToolUseId
12020
13015
  );
@@ -12094,6 +13089,10 @@ async function finalizeQuerySpan(state) {
12094
13089
  llmSpan.end();
12095
13090
  }
12096
13091
  state.activeLlmSpansByParentToolUse.clear();
13092
+ for (const toolSpan of state.activeToolSpans.values()) {
13093
+ toolSpan.end();
13094
+ }
13095
+ state.activeToolSpans.clear();
12097
13096
  for (const [id, subAgentSpan] of state.subAgentSpans) {
12098
13097
  if (!state.endedSubAgentSpans.has(id)) {
12099
13098
  subAgentSpan.end();
@@ -12167,7 +13166,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
12167
13166
  const latestRootLlmParentRef = {
12168
13167
  value: void 0
12169
13168
  };
12170
- const pendingSubAgentNames = /* @__PURE__ */ new Map();
13169
+ const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
13170
+ const taskIdToToolUseId = /* @__PURE__ */ new Map();
12171
13171
  const localToolContext = createClaudeLocalToolContext();
12172
13172
  const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
12173
13173
  const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
@@ -12184,8 +13184,9 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
12184
13184
  return parentLlm;
12185
13185
  }
12186
13186
  const subAgentSpan = await ensureSubAgentSpan(
12187
- pendingSubAgentNames,
13187
+ subAgentDetailsByToolUseId,
12188
13188
  span,
13189
+ activeToolSpans,
12189
13190
  subAgentSpans,
12190
13191
  parentToolUseId
12191
13192
  );
@@ -12204,6 +13205,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
12204
13205
  activeToolSpans,
12205
13206
  localToolHookNames,
12206
13207
  skipLocalToolHooks,
13208
+ subAgentDetailsByToolUseId,
12207
13209
  subAgentSpans,
12208
13210
  endedSubAgentSpans
12209
13211
  );
@@ -12221,12 +13223,13 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
12221
13223
  finalResults: [],
12222
13224
  options: optionsWithHooks,
12223
13225
  originalPrompt,
12224
- pendingSubAgentNames,
12225
13226
  processing: Promise.resolve(),
12226
13227
  promptDone,
12227
13228
  promptStarted: () => promptStarted,
12228
13229
  span,
13230
+ subAgentDetailsByToolUseId,
12229
13231
  subAgentSpans,
13232
+ taskIdToToolUseId,
12230
13233
  latestLlmParentBySubAgentToolUse,
12231
13234
  latestRootLlmParentRef,
12232
13235
  toolUseToParent,
@@ -12308,6 +13311,10 @@ var googleGenAIChannels = defineChannels("@google/genai", {
12308
13311
  generateContentStream: channel({
12309
13312
  channelName: "models.generateContentStream",
12310
13313
  kind: "async"
13314
+ }),
13315
+ embedContent: channel({
13316
+ channelName: "models.embedContent",
13317
+ kind: "async"
12311
13318
  })
12312
13319
  });
12313
13320
 
@@ -12334,6 +13341,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
12334
13341
  subscribeToGoogleGenAIChannels() {
12335
13342
  this.subscribeToGenerateContentChannel();
12336
13343
  this.subscribeToGenerateContentStreamChannel();
13344
+ this.subscribeToEmbedContentChannel();
12337
13345
  }
12338
13346
  subscribeToGenerateContentChannel() {
12339
13347
  const tracingChannel = googleGenAIChannels.generateContent.tracingChannel();
@@ -12343,8 +13351,8 @@ var GoogleGenAIPlugin = class extends BasePlugin {
12343
13351
  states,
12344
13352
  (event) => {
12345
13353
  const params = event.arguments[0];
12346
- const input = serializeInput(params);
12347
- const metadata = extractMetadata(params);
13354
+ const input = serializeGenerateContentInput(params);
13355
+ const metadata = extractGenerateContentMetadata(params);
12348
13356
  const span = startSpan({
12349
13357
  name: "generate_content",
12350
13358
  spanAttributes: {
@@ -12362,8 +13370,8 @@ var GoogleGenAIPlugin = class extends BasePlugin {
12362
13370
  start: (event) => {
12363
13371
  ensureSpanState(states, event, () => {
12364
13372
  const params = event.arguments[0];
12365
- const input = serializeInput(params);
12366
- const metadata = extractMetadata(params);
13373
+ const input = serializeGenerateContentInput(params);
13374
+ const metadata = extractGenerateContentMetadata(params);
12367
13375
  const span = startSpan({
12368
13376
  name: "generate_content",
12369
13377
  spanAttributes: {
@@ -12383,7 +13391,9 @@ var GoogleGenAIPlugin = class extends BasePlugin {
12383
13391
  return;
12384
13392
  }
12385
13393
  try {
13394
+ const responseMetadata = extractResponseMetadata(event.result);
12386
13395
  spanState.span.log({
13396
+ ...responseMetadata ? { metadata: responseMetadata } : {},
12387
13397
  metrics: cleanMetrics(
12388
13398
  extractGenerateContentMetrics(
12389
13399
  event.result,
@@ -12413,8 +13423,8 @@ var GoogleGenAIPlugin = class extends BasePlugin {
12413
13423
  start: (event) => {
12414
13424
  const streamEvent = event;
12415
13425
  const params = event.arguments[0];
12416
- streamEvent.googleGenAIInput = serializeInput(params);
12417
- streamEvent.googleGenAIMetadata = extractMetadata(params);
13426
+ streamEvent.googleGenAIInput = serializeGenerateContentInput(params);
13427
+ streamEvent.googleGenAIMetadata = extractGenerateContentMetadata(params);
12418
13428
  streamEvent.googleGenAIStartTime = getCurrentUnixTimestamp();
12419
13429
  },
12420
13430
  asyncEnd: (event) => {
@@ -12434,6 +13444,76 @@ var GoogleGenAIPlugin = class extends BasePlugin {
12434
13444
  tracingChannel.unsubscribe(handlers);
12435
13445
  });
12436
13446
  }
13447
+ subscribeToEmbedContentChannel() {
13448
+ const tracingChannel = googleGenAIChannels.embedContent.tracingChannel();
13449
+ const states = /* @__PURE__ */ new WeakMap();
13450
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
13451
+ tracingChannel,
13452
+ states,
13453
+ (event) => {
13454
+ const params = event.arguments[0];
13455
+ const input = serializeEmbedContentInput(params);
13456
+ const metadata = extractEmbedContentMetadata(params);
13457
+ const span = startSpan({
13458
+ name: "embed_content",
13459
+ spanAttributes: {
13460
+ type: "llm" /* LLM */
13461
+ },
13462
+ event: createWrapperParityEvent({ input, metadata })
13463
+ });
13464
+ return {
13465
+ span,
13466
+ startTime: getCurrentUnixTimestamp()
13467
+ };
13468
+ }
13469
+ );
13470
+ const handlers = {
13471
+ start: (event) => {
13472
+ ensureSpanState(states, event, () => {
13473
+ const params = event.arguments[0];
13474
+ const input = serializeEmbedContentInput(params);
13475
+ const metadata = extractEmbedContentMetadata(params);
13476
+ const span = startSpan({
13477
+ name: "embed_content",
13478
+ spanAttributes: {
13479
+ type: "llm" /* LLM */
13480
+ },
13481
+ event: createWrapperParityEvent({ input, metadata })
13482
+ });
13483
+ return {
13484
+ span,
13485
+ startTime: getCurrentUnixTimestamp()
13486
+ };
13487
+ });
13488
+ },
13489
+ asyncEnd: (event) => {
13490
+ const spanState = states.get(event);
13491
+ if (!spanState) {
13492
+ return;
13493
+ }
13494
+ try {
13495
+ const output = summarizeEmbedContentOutput(event.result);
13496
+ spanState.span.log({
13497
+ ...output ? { output } : {},
13498
+ metrics: cleanMetrics(
13499
+ extractEmbedContentMetrics(event.result, spanState.startTime)
13500
+ )
13501
+ });
13502
+ } finally {
13503
+ spanState.span.end();
13504
+ states.delete(event);
13505
+ }
13506
+ },
13507
+ error: (event) => {
13508
+ logErrorAndEndSpan(states, event);
13509
+ }
13510
+ };
13511
+ tracingChannel.subscribe(handlers);
13512
+ this.unsubscribers.push(() => {
13513
+ unbindCurrentSpanStore?.();
13514
+ tracingChannel.unsubscribe(handlers);
13515
+ });
13516
+ }
12437
13517
  };
12438
13518
  function ensureSpanState(states, event, create) {
12439
13519
  const existing = states.get(event);
@@ -12507,7 +13587,11 @@ function patchGoogleGenAIStreamingResult(args) {
12507
13587
  finalized = true;
12508
13588
  if (options.result) {
12509
13589
  const { end, ...metricsWithoutEnd } = options.result.metrics;
13590
+ const responseMetadata = extractResponseMetadata(
13591
+ options.result.aggregated
13592
+ );
12510
13593
  span.log({
13594
+ ...responseMetadata ? { metadata: responseMetadata } : {},
12511
13595
  metrics: cleanMetrics(metricsWithoutEnd),
12512
13596
  output: options.result.aggregated
12513
13597
  });
@@ -12610,26 +13694,35 @@ function patchGoogleGenAIStreamingResult(args) {
12610
13694
  patchIterator(result);
12611
13695
  return true;
12612
13696
  }
12613
- function serializeInput(params) {
13697
+ function serializeGenerateContentInput(params) {
12614
13698
  const input = {
12615
13699
  model: params.model,
12616
- contents: serializeContents(params.contents)
13700
+ contents: serializeContentCollection(params.contents)
12617
13701
  };
12618
- if (params.config) {
12619
- const config = tryToDict(params.config);
12620
- if (config) {
12621
- const filteredConfig = {};
12622
- Object.keys(config).forEach((key) => {
12623
- if (key !== "tools") {
12624
- filteredConfig[key] = config[key];
12625
- }
12626
- });
12627
- input.config = filteredConfig;
12628
- }
13702
+ const config = params.config ? tryToDict(params.config) : null;
13703
+ if (config) {
13704
+ const filteredConfig = {};
13705
+ Object.keys(config).forEach((key) => {
13706
+ if (key !== "tools") {
13707
+ filteredConfig[key] = config[key];
13708
+ }
13709
+ });
13710
+ input.config = filteredConfig;
13711
+ }
13712
+ return input;
13713
+ }
13714
+ function serializeEmbedContentInput(params) {
13715
+ const input = {
13716
+ model: params.model,
13717
+ contents: serializeContentCollection(params.contents)
13718
+ };
13719
+ const config = params.config ? tryToDict(params.config) : null;
13720
+ if (config) {
13721
+ input.config = config;
12629
13722
  }
12630
13723
  return input;
12631
13724
  }
12632
- function serializeContents(contents) {
13725
+ function serializeContentCollection(contents) {
12633
13726
  if (contents === null || contents === void 0) {
12634
13727
  return null;
12635
13728
  }
@@ -12681,22 +13774,26 @@ function serializePart(part) {
12681
13774
  }
12682
13775
  return part;
12683
13776
  }
12684
- function serializeTools(params) {
12685
- if (!params.config?.tools) {
13777
+ function serializeGenerateContentTools(params) {
13778
+ const config = params.config ? tryToDict(params.config) : null;
13779
+ const tools = config?.tools;
13780
+ if (!Array.isArray(tools)) {
12686
13781
  return null;
12687
13782
  }
12688
13783
  try {
12689
- return params.config.tools.map((tool) => {
12690
- if (typeof tool === "object" && tool.functionDeclarations) {
12691
- return tool;
13784
+ const serializedTools = [];
13785
+ for (const tool of tools) {
13786
+ const toolDict = tryToDict(tool);
13787
+ if (toolDict) {
13788
+ serializedTools.push(toolDict);
12692
13789
  }
12693
- return tool;
12694
- });
13790
+ }
13791
+ return serializedTools.length > 0 ? serializedTools : null;
12695
13792
  } catch {
12696
13793
  return null;
12697
13794
  }
12698
13795
  }
12699
- function extractMetadata(params) {
13796
+ function extractGenerateContentMetadata(params) {
12700
13797
  const metadata = {};
12701
13798
  if (params.model) {
12702
13799
  metadata.model = params.model;
@@ -12711,12 +13808,25 @@ function extractMetadata(params) {
12711
13808
  });
12712
13809
  }
12713
13810
  }
12714
- const tools = serializeTools(params);
13811
+ const tools = serializeGenerateContentTools(params);
12715
13812
  if (tools) {
12716
13813
  metadata.tools = tools;
12717
13814
  }
12718
13815
  return metadata;
12719
13816
  }
13817
+ function extractEmbedContentMetadata(params) {
13818
+ const metadata = {};
13819
+ if (params.model) {
13820
+ metadata.model = params.model;
13821
+ }
13822
+ const config = params.config ? tryToDict(params.config) : null;
13823
+ if (config) {
13824
+ Object.keys(config).forEach((key) => {
13825
+ metadata[key] = config[key];
13826
+ });
13827
+ }
13828
+ return metadata;
13829
+ }
12720
13830
  function extractGenerateContentMetrics(response, startTime) {
12721
13831
  const metrics = {};
12722
13832
  if (startTime !== void 0) {
@@ -12730,24 +13840,87 @@ function extractGenerateContentMetrics(response, startTime) {
12730
13840
  }
12731
13841
  return metrics;
12732
13842
  }
12733
- function populateUsageMetrics(metrics, usage) {
12734
- if (usage.promptTokenCount !== void 0) {
12735
- metrics.prompt_tokens = usage.promptTokenCount;
13843
+ function extractEmbedContentMetrics(response, startTime) {
13844
+ const metrics = {};
13845
+ if (startTime !== void 0) {
13846
+ const end = getCurrentUnixTimestamp();
13847
+ metrics.start = startTime;
13848
+ metrics.end = end;
13849
+ metrics.duration = end - startTime;
12736
13850
  }
12737
- if (usage.candidatesTokenCount !== void 0) {
12738
- metrics.completion_tokens = usage.candidatesTokenCount;
13851
+ if (response?.usageMetadata) {
13852
+ populateUsageMetrics(metrics, response.usageMetadata);
12739
13853
  }
12740
- if (usage.totalTokenCount !== void 0) {
12741
- metrics.tokens = usage.totalTokenCount;
13854
+ const embeddingTokenCount = extractEmbedPromptTokenCount(response);
13855
+ if (embeddingTokenCount !== void 0) {
13856
+ metrics.prompt_tokens = embeddingTokenCount;
13857
+ metrics.tokens = embeddingTokenCount;
12742
13858
  }
12743
- if (usage.cachedContentTokenCount !== void 0) {
12744
- metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
13859
+ return metrics;
13860
+ }
13861
+ function extractEmbedPromptTokenCount(response) {
13862
+ if (!response) {
13863
+ return void 0;
12745
13864
  }
12746
- if (usage.thoughtsTokenCount !== void 0) {
12747
- metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
13865
+ const usagePromptTokens = response.usageMetadata?.promptTokenCount;
13866
+ if (typeof usagePromptTokens === "number" && Number.isFinite(usagePromptTokens)) {
13867
+ return usagePromptTokens;
13868
+ }
13869
+ const usageTotalTokens = response.usageMetadata?.totalTokenCount;
13870
+ if (typeof usageTotalTokens === "number" && Number.isFinite(usageTotalTokens)) {
13871
+ return usageTotalTokens;
13872
+ }
13873
+ const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
13874
+ if (embeddings.length === 0) {
13875
+ return void 0;
13876
+ }
13877
+ let total = 0;
13878
+ let sawAny = false;
13879
+ for (const embedding of embeddings) {
13880
+ const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
13881
+ const tokenCount = embeddingStats?.tokenCount;
13882
+ if (typeof tokenCount === "number" && Number.isFinite(tokenCount)) {
13883
+ total += tokenCount;
13884
+ sawAny = true;
13885
+ }
12748
13886
  }
13887
+ return sawAny ? total : void 0;
12749
13888
  }
12750
- function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
13889
+ function summarizeEmbedContentOutput(response) {
13890
+ if (!response) {
13891
+ return void 0;
13892
+ }
13893
+ const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
13894
+ if (embeddings.length === 0) {
13895
+ return void 0;
13896
+ }
13897
+ const firstValues = embeddings[0]?.values;
13898
+ if (!Array.isArray(firstValues)) {
13899
+ return void 0;
13900
+ }
13901
+ return {
13902
+ embedding_count: embeddings.length,
13903
+ embedding_length: firstValues.length
13904
+ };
13905
+ }
13906
+ function populateUsageMetrics(metrics, usage) {
13907
+ if (usage.promptTokenCount !== void 0) {
13908
+ metrics.prompt_tokens = usage.promptTokenCount;
13909
+ }
13910
+ if (usage.candidatesTokenCount !== void 0) {
13911
+ metrics.completion_tokens = usage.candidatesTokenCount;
13912
+ }
13913
+ if (usage.totalTokenCount !== void 0) {
13914
+ metrics.tokens = usage.totalTokenCount;
13915
+ }
13916
+ if (usage.cachedContentTokenCount !== void 0) {
13917
+ metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
13918
+ }
13919
+ if (usage.thoughtsTokenCount !== void 0) {
13920
+ metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
13921
+ }
13922
+ }
13923
+ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
12751
13924
  const end = getCurrentUnixTimestamp();
12752
13925
  const metrics = {
12753
13926
  start: startTime,
@@ -12763,6 +13936,7 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
12763
13936
  let text = "";
12764
13937
  let thoughtText = "";
12765
13938
  const otherParts = [];
13939
+ let groundingMetadata = void 0;
12766
13940
  let usageMetadata = null;
12767
13941
  let lastResponse = null;
12768
13942
  for (const chunk of chunks) {
@@ -12770,6 +13944,9 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
12770
13944
  if (chunk.usageMetadata) {
12771
13945
  usageMetadata = chunk.usageMetadata;
12772
13946
  }
13947
+ if (chunk.groundingMetadata !== void 0) {
13948
+ groundingMetadata = chunk.groundingMetadata;
13949
+ }
12773
13950
  if (chunk.candidates && Array.isArray(chunk.candidates)) {
12774
13951
  for (const candidate of chunk.candidates) {
12775
13952
  if (candidate.content?.parts) {
@@ -12815,6 +13992,12 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
12815
13992
  if (candidate.finishReason !== void 0) {
12816
13993
  candidateDict.finishReason = candidate.finishReason;
12817
13994
  }
13995
+ if (candidate.groundingMetadata !== void 0) {
13996
+ candidateDict.groundingMetadata = candidate.groundingMetadata;
13997
+ if (groundingMetadata === void 0) {
13998
+ groundingMetadata = candidate.groundingMetadata;
13999
+ }
14000
+ }
12818
14001
  if (candidate.safetyRatings) {
12819
14002
  candidateDict.safetyRatings = candidate.safetyRatings;
12820
14003
  }
@@ -12826,6 +14009,9 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
12826
14009
  aggregated.usageMetadata = usageMetadata;
12827
14010
  populateUsageMetrics(metrics, usageMetadata);
12828
14011
  }
14012
+ if (groundingMetadata !== void 0) {
14013
+ aggregated.groundingMetadata = groundingMetadata;
14014
+ }
12829
14015
  if (text) {
12830
14016
  aggregated.text = text;
12831
14017
  }
@@ -12840,6 +14026,31 @@ function cleanMetrics(metrics) {
12840
14026
  }
12841
14027
  return cleaned;
12842
14028
  }
14029
+ function extractResponseMetadata(response) {
14030
+ const responseDict = tryToDict(response);
14031
+ if (!responseDict) {
14032
+ return void 0;
14033
+ }
14034
+ const metadata = {};
14035
+ const responseGroundingMetadata = responseDict.groundingMetadata;
14036
+ const candidateGroundingMetadata = [];
14037
+ if (Array.isArray(responseDict.candidates)) {
14038
+ for (const candidate of responseDict.candidates) {
14039
+ const candidateDict = tryToDict(candidate);
14040
+ if (candidateDict?.groundingMetadata !== void 0) {
14041
+ candidateGroundingMetadata.push(candidateDict.groundingMetadata);
14042
+ }
14043
+ }
14044
+ }
14045
+ if (responseGroundingMetadata !== void 0) {
14046
+ metadata.groundingMetadata = responseGroundingMetadata;
14047
+ } else if (candidateGroundingMetadata.length === 1) {
14048
+ [metadata.groundingMetadata] = candidateGroundingMetadata;
14049
+ } else if (candidateGroundingMetadata.length > 1) {
14050
+ metadata.groundingMetadata = candidateGroundingMetadata;
14051
+ }
14052
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
14053
+ }
12843
14054
  function tryToDict(obj) {
12844
14055
  if (obj === null || obj === void 0) {
12845
14056
  return null;
@@ -12854,6 +14065,385 @@ function tryToDict(obj) {
12854
14065
  return null;
12855
14066
  }
12856
14067
 
14068
+ // src/instrumentation/plugins/huggingface-channels.ts
14069
+ var huggingFaceChannels = defineChannels("@huggingface/inference", {
14070
+ chatCompletion: channel({
14071
+ channelName: "chatCompletion",
14072
+ kind: "async"
14073
+ }),
14074
+ chatCompletionStream: channel({
14075
+ channelName: "chatCompletionStream",
14076
+ kind: "sync-stream"
14077
+ }),
14078
+ textGeneration: channel({
14079
+ channelName: "textGeneration",
14080
+ kind: "async"
14081
+ }),
14082
+ textGenerationStream: channel({
14083
+ channelName: "textGenerationStream",
14084
+ kind: "sync-stream"
14085
+ }),
14086
+ featureExtraction: channel({
14087
+ channelName: "featureExtraction",
14088
+ kind: "async"
14089
+ })
14090
+ });
14091
+
14092
+ // src/instrumentation/plugins/huggingface-plugin.ts
14093
+ var REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
14094
+ "dimensions",
14095
+ "encoding_format",
14096
+ "endpointUrl",
14097
+ "max_tokens",
14098
+ "model",
14099
+ "provider",
14100
+ "seed",
14101
+ "stop",
14102
+ "stream",
14103
+ "temperature",
14104
+ "top_p"
14105
+ ]);
14106
+ var RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
14107
+ "created",
14108
+ "id",
14109
+ "model",
14110
+ "object"
14111
+ ]);
14112
+ var HuggingFacePlugin = class extends BasePlugin {
14113
+ onEnable() {
14114
+ this.unsubscribers.push(
14115
+ traceAsyncChannel(huggingFaceChannels.chatCompletion, {
14116
+ name: "huggingface.chat_completion",
14117
+ type: "llm" /* LLM */,
14118
+ extractInput: extractChatInputWithMetadata,
14119
+ extractOutput: (result) => result?.choices,
14120
+ extractMetadata: (result) => extractResponseMetadata2(result),
14121
+ extractMetrics: (result) => parseMetricsFromUsage(result?.usage)
14122
+ }),
14123
+ traceSyncStreamChannel(huggingFaceChannels.chatCompletionStream, {
14124
+ name: "huggingface.chat_completion_stream",
14125
+ type: "llm" /* LLM */,
14126
+ extractInput: extractChatInputWithMetadata,
14127
+ patchResult: ({ result, span, startTime }) => patchChatCompletionStream({
14128
+ result,
14129
+ span,
14130
+ startTime
14131
+ })
14132
+ }),
14133
+ traceAsyncChannel(huggingFaceChannels.textGeneration, {
14134
+ name: "huggingface.text_generation",
14135
+ type: "llm" /* LLM */,
14136
+ extractInput: extractTextGenerationInputWithMetadata,
14137
+ extractOutput: (result) => isObject(result) ? { generated_text: result.generated_text } : result,
14138
+ extractMetadata: extractTextGenerationMetadata,
14139
+ extractMetrics: (result) => extractTextGenerationMetrics(result?.details ?? null)
14140
+ }),
14141
+ traceSyncStreamChannel(huggingFaceChannels.textGenerationStream, {
14142
+ name: "huggingface.text_generation_stream",
14143
+ type: "llm" /* LLM */,
14144
+ extractInput: extractTextGenerationInputWithMetadata,
14145
+ patchResult: ({ result, span, startTime }) => patchTextGenerationStream({
14146
+ result,
14147
+ span,
14148
+ startTime
14149
+ })
14150
+ }),
14151
+ traceAsyncChannel(huggingFaceChannels.featureExtraction, {
14152
+ name: "huggingface.feature_extraction",
14153
+ type: "llm" /* LLM */,
14154
+ extractInput: extractFeatureExtractionInputWithMetadata,
14155
+ extractOutput: summarizeFeatureExtractionOutput,
14156
+ extractMetrics: () => ({})
14157
+ })
14158
+ );
14159
+ }
14160
+ onDisable() {
14161
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
14162
+ }
14163
+ };
14164
+ function addProviderMetadata(metadata) {
14165
+ return {
14166
+ ...metadata,
14167
+ provider: metadata.provider ?? "huggingface"
14168
+ };
14169
+ }
14170
+ function normalizeArgs(args) {
14171
+ if (Array.isArray(args)) {
14172
+ return args;
14173
+ }
14174
+ if (isArrayLike(args)) {
14175
+ return Array.from(args);
14176
+ }
14177
+ return [args];
14178
+ }
14179
+ function isArrayLike(value) {
14180
+ return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
14181
+ }
14182
+ function getFirstObjectArg(args) {
14183
+ const firstObjectArg = normalizeArgs(args).find((arg) => isObject(arg));
14184
+ return isObject(firstObjectArg) ? firstObjectArg : void 0;
14185
+ }
14186
+ function pickRequestMetadata(params) {
14187
+ if (!params) {
14188
+ return addProviderMetadata({});
14189
+ }
14190
+ const metadata = {};
14191
+ for (const key of REQUEST_METADATA_ALLOWLIST) {
14192
+ const value = params[key];
14193
+ if (value !== void 0) {
14194
+ metadata[key] = value;
14195
+ }
14196
+ }
14197
+ if (isObject(params.parameters)) {
14198
+ metadata.parameters = params.parameters;
14199
+ }
14200
+ return addProviderMetadata(metadata);
14201
+ }
14202
+ function extractChatInputWithMetadata(args) {
14203
+ const params = getFirstObjectArg(args);
14204
+ const { messages, ...rawMetadata } = params ?? {};
14205
+ return {
14206
+ input: messages,
14207
+ metadata: pickRequestMetadata(rawMetadata)
14208
+ };
14209
+ }
14210
+ function extractTextGenerationInputWithMetadata(args) {
14211
+ const params = getFirstObjectArg(args);
14212
+ const { inputs, ...rawMetadata } = params ?? {};
14213
+ return {
14214
+ input: inputs,
14215
+ metadata: pickRequestMetadata(rawMetadata)
14216
+ };
14217
+ }
14218
+ function extractFeatureExtractionInputWithMetadata(args) {
14219
+ const params = getFirstObjectArg(args);
14220
+ const { inputs, ...rawMetadata } = params ?? {};
14221
+ return {
14222
+ input: inputs,
14223
+ metadata: pickRequestMetadata(rawMetadata)
14224
+ };
14225
+ }
14226
+ function extractResponseMetadata2(result) {
14227
+ if (!isObject(result)) {
14228
+ return void 0;
14229
+ }
14230
+ const metadata = {};
14231
+ for (const key of RESPONSE_METADATA_ALLOWLIST) {
14232
+ const value = result[key];
14233
+ if (value !== void 0) {
14234
+ metadata[key] = value;
14235
+ }
14236
+ }
14237
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
14238
+ }
14239
+ function extractTextGenerationMetrics(details) {
14240
+ if (!isObject(details)) {
14241
+ return {};
14242
+ }
14243
+ const promptTokens = Array.isArray(details.prefill) ? details.prefill.length : void 0;
14244
+ const completionTokens = typeof details.generated_tokens === "number" ? details.generated_tokens : Array.isArray(details.tokens) ? details.tokens.length : void 0;
14245
+ const metrics = {};
14246
+ if (promptTokens !== void 0) {
14247
+ metrics.prompt_tokens = promptTokens;
14248
+ }
14249
+ if (completionTokens !== void 0) {
14250
+ metrics.completion_tokens = completionTokens;
14251
+ }
14252
+ if (promptTokens !== void 0 || completionTokens !== void 0) {
14253
+ metrics.tokens = (promptTokens ?? 0) + (completionTokens ?? 0);
14254
+ }
14255
+ return metrics;
14256
+ }
14257
+ function extractTextGenerationMetadata(result) {
14258
+ if (!isObject(result?.details)) {
14259
+ return void 0;
14260
+ }
14261
+ return typeof result.details.finish_reason === "string" ? {
14262
+ finish_reason: result.details.finish_reason
14263
+ } : void 0;
14264
+ }
14265
+ function summarizeFeatureExtractionOutput(result) {
14266
+ if (!Array.isArray(result)) {
14267
+ return void 0;
14268
+ }
14269
+ const first = result[0];
14270
+ if (typeof first === "number") {
14271
+ return { embedding_length: result.length };
14272
+ }
14273
+ if (Array.isArray(first) && first.every((value) => typeof value === "number")) {
14274
+ return {
14275
+ embedding_count: result.length,
14276
+ embedding_length: first.length
14277
+ };
14278
+ }
14279
+ if (Array.isArray(first) && first.length > 0 && Array.isArray(first[0]) && first[0].every((value) => typeof value === "number")) {
14280
+ return {
14281
+ embedding_batch_count: result.length,
14282
+ embedding_count: first.length,
14283
+ embedding_length: first[0].length
14284
+ };
14285
+ }
14286
+ return void 0;
14287
+ }
14288
+ function patchChatCompletionStream(args) {
14289
+ const { result, span, startTime } = args;
14290
+ if (!result || !isAsyncIterable(result)) {
14291
+ return false;
14292
+ }
14293
+ let firstChunkTime;
14294
+ patchStreamIfNeeded(result, {
14295
+ onChunk: () => {
14296
+ if (firstChunkTime === void 0) {
14297
+ firstChunkTime = getCurrentUnixTimestamp();
14298
+ }
14299
+ },
14300
+ onComplete: (chunks) => {
14301
+ const lastChunk = chunks.at(-1);
14302
+ const responseMetadata = extractResponseMetadata2(lastChunk);
14303
+ const metrics = {
14304
+ ...parseMetricsFromUsage(lastChunk?.usage),
14305
+ ...firstChunkTime !== void 0 ? { time_to_first_token: firstChunkTime - startTime } : {}
14306
+ };
14307
+ span.log({
14308
+ output: aggregateChatCompletionChunks2(chunks),
14309
+ ...responseMetadata ? { metadata: responseMetadata } : {},
14310
+ metrics
14311
+ });
14312
+ span.end();
14313
+ },
14314
+ onError: (error) => {
14315
+ span.log({
14316
+ error: error.message
14317
+ });
14318
+ span.end();
14319
+ }
14320
+ });
14321
+ return true;
14322
+ }
14323
+ function patchTextGenerationStream(args) {
14324
+ const { result, span, startTime } = args;
14325
+ if (!result || !isAsyncIterable(result)) {
14326
+ return false;
14327
+ }
14328
+ let firstChunkTime;
14329
+ patchStreamIfNeeded(result, {
14330
+ onChunk: () => {
14331
+ if (firstChunkTime === void 0) {
14332
+ firstChunkTime = getCurrentUnixTimestamp();
14333
+ }
14334
+ },
14335
+ onComplete: (chunks) => {
14336
+ const lastChunk = chunks.at(-1);
14337
+ const streamMetadata = extractTextGenerationStreamMetadata(chunks);
14338
+ span.log({
14339
+ output: aggregateTextGenerationStreamChunks(chunks),
14340
+ ...streamMetadata ? { metadata: streamMetadata } : {},
14341
+ metrics: {
14342
+ ...extractTextGenerationMetrics(lastChunk?.details ?? null),
14343
+ ...parseMetricsFromUsage(lastChunk?.usage),
14344
+ ...firstChunkTime !== void 0 ? { time_to_first_token: firstChunkTime - startTime } : {}
14345
+ }
14346
+ });
14347
+ span.end();
14348
+ },
14349
+ onError: (error) => {
14350
+ span.log({
14351
+ error: error.message
14352
+ });
14353
+ span.end();
14354
+ }
14355
+ });
14356
+ return true;
14357
+ }
14358
+ function aggregateChatCompletionChunks2(chunks) {
14359
+ if (chunks.length === 0) {
14360
+ return void 0;
14361
+ }
14362
+ const aggregatedChoices = /* @__PURE__ */ new Map();
14363
+ for (const chunk of chunks) {
14364
+ for (const choice of chunk.choices ?? []) {
14365
+ const index = typeof choice.index === "number" ? choice.index : 0;
14366
+ const existing = aggregatedChoices.get(index) ?? { content: "" };
14367
+ const delta = isObject(choice.delta) ? choice.delta : void 0;
14368
+ const message = isObject(choice.message) ? choice.message : void 0;
14369
+ if (typeof delta?.content === "string") {
14370
+ existing.content += delta.content;
14371
+ } else if (typeof message?.content === "string") {
14372
+ existing.content = message.content;
14373
+ }
14374
+ if (typeof delta?.role === "string") {
14375
+ existing.role = delta.role;
14376
+ } else if (typeof message?.role === "string") {
14377
+ existing.role = message.role;
14378
+ }
14379
+ if (choice.finish_reason !== void 0) {
14380
+ existing.finish_reason = choice.finish_reason;
14381
+ }
14382
+ aggregatedChoices.set(index, existing);
14383
+ }
14384
+ }
14385
+ return {
14386
+ choices: [...aggregatedChoices.entries()].map(([index, choice]) => ({
14387
+ index,
14388
+ message: {
14389
+ content: choice.content,
14390
+ role: choice.role ?? "assistant"
14391
+ },
14392
+ ...choice.finish_reason !== void 0 ? { finish_reason: choice.finish_reason } : {}
14393
+ }))
14394
+ };
14395
+ }
14396
+ function aggregateTextGenerationStreamChunks(chunks) {
14397
+ if (chunks.length === 0) {
14398
+ return void 0;
14399
+ }
14400
+ let generatedText = "";
14401
+ let finishReason;
14402
+ for (const chunk of chunks) {
14403
+ if (typeof chunk.generated_text === "string") {
14404
+ generatedText = chunk.generated_text;
14405
+ } else if (typeof chunk.token?.text === "string" && !chunk.token.special) {
14406
+ generatedText += chunk.token.text;
14407
+ } else if (Array.isArray(chunk.choices)) {
14408
+ for (const choice of chunk.choices) {
14409
+ if (typeof choice.text === "string") {
14410
+ generatedText += choice.text;
14411
+ }
14412
+ if (choice.finish_reason !== void 0) {
14413
+ finishReason = choice.finish_reason;
14414
+ }
14415
+ }
14416
+ }
14417
+ if (isObject(chunk.details) && typeof chunk.details.finish_reason === "string") {
14418
+ finishReason = chunk.details.finish_reason;
14419
+ }
14420
+ }
14421
+ return {
14422
+ generated_text: generatedText,
14423
+ ...finishReason !== void 0 ? { finish_reason: finishReason } : {}
14424
+ };
14425
+ }
14426
+ function extractTextGenerationStreamMetadata(chunks) {
14427
+ for (let index = chunks.length - 1; index >= 0; index--) {
14428
+ const chunk = chunks[index];
14429
+ if (isObject(chunk?.details) && typeof chunk.details.finish_reason === "string") {
14430
+ return {
14431
+ finish_reason: chunk.details.finish_reason
14432
+ };
14433
+ }
14434
+ if (!Array.isArray(chunk?.choices)) {
14435
+ continue;
14436
+ }
14437
+ for (let choiceIndex = chunk.choices.length - 1; choiceIndex >= 0; choiceIndex--) {
14438
+ const choice = chunk.choices[choiceIndex];
14439
+ if (choice?.finish_reason !== void 0) {
14440
+ return { finish_reason: choice.finish_reason };
14441
+ }
14442
+ }
14443
+ }
14444
+ return void 0;
14445
+ }
14446
+
12857
14447
  // src/instrumentation/plugins/openrouter-agent-channels.ts
12858
14448
  var openRouterAgentChannels = defineChannels("@openrouter/agent", {
12859
14449
  callModel: channel({
@@ -12971,20 +14561,20 @@ var OpenRouterAgentPlugin = class extends BasePlugin {
12971
14561
  });
12972
14562
  }
12973
14563
  };
12974
- function normalizeArgs(args) {
14564
+ function normalizeArgs2(args) {
12975
14565
  if (Array.isArray(args)) {
12976
14566
  return args;
12977
14567
  }
12978
- if (isArrayLike(args)) {
14568
+ if (isArrayLike2(args)) {
12979
14569
  return Array.from(args);
12980
14570
  }
12981
14571
  return [args];
12982
14572
  }
12983
- function isArrayLike(value) {
14573
+ function isArrayLike2(value) {
12984
14574
  return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
12985
14575
  }
12986
14576
  function getOpenRouterCallModelRequestArg(args) {
12987
- const normalizedArgs = normalizeArgs(args);
14577
+ const normalizedArgs = normalizeArgs2(args);
12988
14578
  const keyedRequestArg = normalizedArgs.find(
12989
14579
  (arg) => isObject(arg) && ("input" in arg || "model" in arg || "tools" in arg)
12990
14580
  );
@@ -13270,7 +14860,7 @@ function traceToolExecution(args) {
13270
14860
  }
13271
14861
  }
13272
14862
  function publishToolResult(tracingChannel, event, result) {
13273
- if (isPromiseLike3(result)) {
14863
+ if (isPromiseLike(result)) {
13274
14864
  return result.then(
13275
14865
  (resolved) => {
13276
14866
  event.result = resolved;
@@ -13292,9 +14882,6 @@ function getToolCallId(context) {
13292
14882
  const toolContext = context;
13293
14883
  return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
13294
14884
  }
13295
- function isPromiseLike3(value) {
13296
- return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
13297
- }
13298
14885
  var OPENROUTER_WRAPPED_CALL_MODEL_RESULT = Symbol(
13299
14886
  "braintrust.openrouter.wrappedCallModelResult"
13300
14887
  );
@@ -13649,7 +15236,13 @@ var openRouterChannels = defineChannels("@openrouter/sdk", {
13649
15236
  channelName: "embeddings.generate",
13650
15237
  kind: "async"
13651
15238
  }),
13652
- betaResponsesSend: channel({
15239
+ rerankRerank: channel(
15240
+ {
15241
+ channelName: "rerank.rerank",
15242
+ kind: "async"
15243
+ }
15244
+ ),
15245
+ betaResponsesSend: channel({
13653
15246
  channelName: "beta.responses.send",
13654
15247
  kind: "async"
13655
15248
  }),
@@ -13741,6 +15334,34 @@ var OpenRouterPlugin = class extends BasePlugin {
13741
15334
  }
13742
15335
  })
13743
15336
  );
15337
+ this.unsubscribers.push(
15338
+ traceAsyncChannel(openRouterChannels.rerankRerank, {
15339
+ name: "openrouter.rerank.rerank",
15340
+ type: "llm" /* LLM */,
15341
+ extractInput: (args) => {
15342
+ const request = getOpenRouterRequestArg(args);
15343
+ const requestBody = isObject(request?.requestBody) ? request.requestBody : {};
15344
+ const httpReferer = request?.httpReferer;
15345
+ const xTitle = request?.xTitle ?? request?.appTitle;
15346
+ const { documents, query, ...metadata } = requestBody;
15347
+ return {
15348
+ input: {
15349
+ documents,
15350
+ query
15351
+ },
15352
+ metadata: buildOpenRouterRerankMetadata(
15353
+ metadata,
15354
+ documents,
15355
+ httpReferer,
15356
+ xTitle
15357
+ )
15358
+ };
15359
+ },
15360
+ extractOutput: (result) => extractOpenRouterRerankOutput(result),
15361
+ extractMetadata: (result) => extractOpenRouterResponseMetadata2(result),
15362
+ extractMetrics: (result) => isObject(result) ? parseOpenRouterMetricsFromUsage2(result.usage) : {}
15363
+ })
15364
+ );
13744
15365
  this.unsubscribers.push(
13745
15366
  traceStreamingChannel(openRouterChannels.betaResponsesSend, {
13746
15367
  name: "openrouter.beta.responses.send",
@@ -13860,20 +15481,20 @@ var OpenRouterPlugin = class extends BasePlugin {
13860
15481
  });
13861
15482
  }
13862
15483
  };
13863
- function normalizeArgs2(args) {
15484
+ function normalizeArgs3(args) {
13864
15485
  if (Array.isArray(args)) {
13865
15486
  return args;
13866
15487
  }
13867
- if (isArrayLike2(args)) {
15488
+ if (isArrayLike3(args)) {
13868
15489
  return Array.from(args);
13869
15490
  }
13870
15491
  return [args];
13871
15492
  }
13872
- function isArrayLike2(value) {
15493
+ function isArrayLike3(value) {
13873
15494
  return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
13874
15495
  }
13875
15496
  function getOpenRouterRequestArg(args) {
13876
- const normalizedArgs = normalizeArgs2(args);
15497
+ const normalizedArgs = normalizeArgs3(args);
13877
15498
  const keyedCandidate = normalizedArgs.find(
13878
15499
  (arg) => isObject(arg) && ("chatGenerationParams" in arg || "requestBody" in arg || "openResponsesRequest" in arg)
13879
15500
  );
@@ -13884,7 +15505,7 @@ function getOpenRouterRequestArg(args) {
13884
15505
  return isObject(firstObjectArg) ? firstObjectArg : void 0;
13885
15506
  }
13886
15507
  function getOpenRouterCallModelRequestArg2(args) {
13887
- const firstObjectArg = normalizeArgs2(args).find((arg) => isObject(arg));
15508
+ const firstObjectArg = normalizeArgs3(args).find((arg) => isObject(arg));
13888
15509
  return isObject(firstObjectArg) ? firstObjectArg : void 0;
13889
15510
  }
13890
15511
  var TOKEN_NAME_MAP3 = {
@@ -14054,6 +15675,13 @@ function buildOpenRouterEmbeddingMetadata(metadata, httpReferer, xTitle) {
14054
15675
  embedding_model: normalized.model
14055
15676
  } : normalized;
14056
15677
  }
15678
+ function buildOpenRouterRerankMetadata(metadata, documents, httpReferer, xTitle) {
15679
+ const normalized = buildOpenRouterMetadata2(metadata, httpReferer, xTitle);
15680
+ return {
15681
+ ...normalized,
15682
+ ...Array.isArray(documents) ? { document_count: documents.length } : {}
15683
+ };
15684
+ }
14057
15685
  function extractOpenRouterCallModelInput2(request) {
14058
15686
  return isObject(request) && "input" in request ? sanitizeOpenRouterLoggedValue2(request.input) : void 0;
14059
15687
  }
@@ -14073,7 +15701,7 @@ function extractOpenRouterResponseMetadata2(result) {
14073
15701
  const metadataRecord = isObject(sanitized) ? sanitized : {};
14074
15702
  const { model, provider, ...rest } = metadataRecord;
14075
15703
  const normalizedModel = parseOpenRouterModelString2(model);
14076
- const normalizedProvider = (typeof provider === "string" ? provider : void 0) || normalizedModel.provider;
15704
+ const normalizedProvider = (typeof provider === "string" ? provider.toLowerCase() : void 0) || normalizedModel.provider;
14077
15705
  const usageMetadata = extractOpenRouterUsageMetadata2(usage);
14078
15706
  const combined = {
14079
15707
  ...rest,
@@ -14092,6 +15720,15 @@ function extractOpenRouterResponseOutput2(response, fallbackOutput) {
14092
15720
  }
14093
15721
  return void 0;
14094
15722
  }
15723
+ function extractOpenRouterRerankOutput(result) {
15724
+ if (!isObject(result) || !Array.isArray(result.results)) {
15725
+ return void 0;
15726
+ }
15727
+ return result.results.slice(0, 100).map((item) => ({
15728
+ index: isObject(item) && typeof item.index === "number" ? item.index : void 0,
15729
+ relevance_score: isObject(item) && typeof item.relevanceScore === "number" ? item.relevanceScore : isObject(item) && typeof item.relevance_score === "number" ? item.relevance_score : void 0
15730
+ }));
15731
+ }
14095
15732
  var OPENROUTER_WRAPPED_TOOL2 = Symbol("braintrust.openrouter.wrappedTool");
14096
15733
  function patchOpenRouterCallModelRequestTools2(request) {
14097
15734
  if (!Array.isArray(request.tools) || request.tools.length === 0) {
@@ -14162,7 +15799,7 @@ function traceToolExecution2(args) {
14162
15799
  }
14163
15800
  }
14164
15801
  function publishToolResult2(tracingChannel, event, result) {
14165
- if (isPromiseLike4(result)) {
15802
+ if (isPromiseLike(result)) {
14166
15803
  return result.then(
14167
15804
  (resolved) => {
14168
15805
  event.result = resolved;
@@ -14184,9 +15821,6 @@ function getToolCallId2(context) {
14184
15821
  const toolContext = context;
14185
15822
  return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
14186
15823
  }
14187
- function isPromiseLike4(value) {
14188
- return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
14189
- }
14190
15824
  function aggregateOpenRouterChatChunks(chunks) {
14191
15825
  let role;
14192
15826
  let content = "";
@@ -14826,20 +16460,20 @@ var MISTRAL_RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
14826
16460
  function camelToSnake3(value) {
14827
16461
  return value.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
14828
16462
  }
14829
- function normalizeArgs3(args) {
16463
+ function normalizeArgs4(args) {
14830
16464
  if (Array.isArray(args)) {
14831
16465
  return args;
14832
16466
  }
14833
- if (isArrayLike3(args)) {
16467
+ if (isArrayLike4(args)) {
14834
16468
  return Array.from(args);
14835
16469
  }
14836
16470
  return [args];
14837
16471
  }
14838
- function isArrayLike3(value) {
16472
+ function isArrayLike4(value) {
14839
16473
  return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
14840
16474
  }
14841
16475
  function getMistralRequestArg(args) {
14842
- const firstObjectArg = normalizeArgs3(args).find((arg) => isObject(arg));
16476
+ const firstObjectArg = normalizeArgs4(args).find((arg) => isObject(arg));
14843
16477
  return isObject(firstObjectArg) ? firstObjectArg : void 0;
14844
16478
  }
14845
16479
  function addMistralProviderMetadata(metadata) {
@@ -15144,88 +16778,1326 @@ function aggregateMistralStreamChunks(chunks) {
15144
16778
  };
15145
16779
  }
15146
16780
 
15147
- // src/instrumentation/braintrust-plugin.ts
15148
- var BraintrustPlugin = class extends BasePlugin {
15149
- config;
15150
- openaiPlugin = null;
15151
- anthropicPlugin = null;
15152
- aiSDKPlugin = null;
15153
- claudeAgentSDKPlugin = null;
15154
- googleGenAIPlugin = null;
15155
- openRouterPlugin = null;
15156
- openRouterAgentPlugin = null;
15157
- mistralPlugin = null;
15158
- constructor(config = {}) {
15159
- super();
15160
- this.config = config;
15161
- }
16781
+ // src/instrumentation/plugins/google-adk-channels.ts
16782
+ var googleADKChannels = defineChannels("@google/adk", {
16783
+ runnerRunAsync: channel({
16784
+ channelName: "runner.runAsync",
16785
+ kind: "sync-stream"
16786
+ }),
16787
+ agentRunAsync: channel({
16788
+ channelName: "agent.runAsync",
16789
+ kind: "sync-stream"
16790
+ }),
16791
+ toolRunAsync: channel({
16792
+ channelName: "tool.runAsync",
16793
+ kind: "async"
16794
+ })
16795
+ });
16796
+
16797
+ // src/instrumentation/plugins/google-adk-plugin.ts
16798
+ var GoogleADKPlugin = class extends BasePlugin {
16799
+ activeRunnerSpans = /* @__PURE__ */ new Map();
16800
+ activeAgentSpans = /* @__PURE__ */ new Map();
15162
16801
  onEnable() {
15163
- const integrations = this.config.integrations || {};
15164
- if (integrations.openai !== false) {
15165
- this.openaiPlugin = new OpenAIPlugin();
15166
- this.openaiPlugin.enable();
15167
- }
15168
- if (integrations.anthropic !== false) {
15169
- this.anthropicPlugin = new AnthropicPlugin();
15170
- this.anthropicPlugin.enable();
15171
- }
15172
- if (integrations.aisdk !== false && integrations.vercel !== false) {
15173
- this.aiSDKPlugin = new AISDKPlugin();
15174
- this.aiSDKPlugin.enable();
15175
- }
15176
- if (integrations.claudeAgentSDK !== false) {
15177
- this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
15178
- this.claudeAgentSDKPlugin.enable();
15179
- }
15180
- if (integrations.googleGenAI !== false && integrations.google !== false) {
15181
- this.googleGenAIPlugin = new GoogleGenAIPlugin();
15182
- this.googleGenAIPlugin.enable();
15183
- }
15184
- if (integrations.openrouter !== false) {
15185
- this.openRouterPlugin = new OpenRouterPlugin();
15186
- this.openRouterPlugin.enable();
15187
- }
15188
- if (integrations.openrouterAgent !== false) {
15189
- this.openRouterAgentPlugin = new OpenRouterAgentPlugin();
15190
- this.openRouterAgentPlugin.enable();
15191
- }
15192
- if (integrations.mistral !== false) {
15193
- this.mistralPlugin = new MistralPlugin();
15194
- this.mistralPlugin.enable();
15195
- }
16802
+ this.subscribeToRunnerRunAsync();
16803
+ this.subscribeToAgentRunAsync();
16804
+ this.subscribeToToolRunAsync();
15196
16805
  }
15197
16806
  onDisable() {
15198
- if (this.openaiPlugin) {
15199
- this.openaiPlugin.disable();
15200
- this.openaiPlugin = null;
15201
- }
15202
- if (this.anthropicPlugin) {
15203
- this.anthropicPlugin.disable();
15204
- this.anthropicPlugin = null;
15205
- }
15206
- if (this.aiSDKPlugin) {
15207
- this.aiSDKPlugin.disable();
15208
- this.aiSDKPlugin = null;
15209
- }
15210
- if (this.claudeAgentSDKPlugin) {
15211
- this.claudeAgentSDKPlugin.disable();
15212
- this.claudeAgentSDKPlugin = null;
15213
- }
15214
- if (this.googleGenAIPlugin) {
15215
- this.googleGenAIPlugin.disable();
15216
- this.googleGenAIPlugin = null;
15217
- }
15218
- if (this.openRouterPlugin) {
15219
- this.openRouterPlugin.disable();
15220
- this.openRouterPlugin = null;
15221
- }
15222
- if (this.openRouterAgentPlugin) {
15223
- this.openRouterAgentPlugin.disable();
15224
- this.openRouterAgentPlugin = null;
16807
+ for (const unsubscribe of this.unsubscribers) {
16808
+ unsubscribe();
15225
16809
  }
15226
- if (this.mistralPlugin) {
15227
- this.mistralPlugin.disable();
15228
- this.mistralPlugin = null;
16810
+ this.unsubscribers = [];
16811
+ this.activeRunnerSpans.clear();
16812
+ this.activeAgentSpans.clear();
16813
+ }
16814
+ subscribeToRunnerRunAsync() {
16815
+ const tracingChannel = googleADKChannels.runnerRunAsync.tracingChannel();
16816
+ const states = /* @__PURE__ */ new WeakMap();
16817
+ const createState = (event) => {
16818
+ const params = event.arguments[0] ?? {};
16819
+ const contextKey = extractRunnerContextKey(params);
16820
+ const span = startSpan({
16821
+ name: "Google ADK Runner",
16822
+ spanAttributes: {
16823
+ type: "task" /* TASK */
16824
+ }
16825
+ });
16826
+ const startTime = getCurrentUnixTimestamp();
16827
+ try {
16828
+ const metadata = extractRunnerMetadata(params);
16829
+ span.log({
16830
+ input: extractRunnerInput(params),
16831
+ metadata
16832
+ });
16833
+ } catch {
16834
+ }
16835
+ if (contextKey) {
16836
+ this.activeRunnerSpans.set(contextKey, span);
16837
+ }
16838
+ return { span, startTime, events: [], contextKey };
16839
+ };
16840
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart3(
16841
+ tracingChannel,
16842
+ states,
16843
+ createState
16844
+ );
16845
+ const handlers = {
16846
+ start: (event) => {
16847
+ ensureState(states, event, () => createState(event));
16848
+ },
16849
+ end: (event) => {
16850
+ const state = states.get(event);
16851
+ if (!state) {
16852
+ return;
16853
+ }
16854
+ const result = event.result;
16855
+ if (isAsyncIterable(result)) {
16856
+ bindAsyncIterableToCurrentSpan(result, state.span);
16857
+ patchStreamIfNeeded(result, {
16858
+ onChunk: (adkEvent) => {
16859
+ state.events.push(adkEvent);
16860
+ },
16861
+ onComplete: () => {
16862
+ finalizeRunnerSpan(state, this.activeRunnerSpans);
16863
+ states.delete(event);
16864
+ },
16865
+ onError: (error) => {
16866
+ cleanupActiveRunnerSpan(state, this.activeRunnerSpans);
16867
+ state.span.log({ error: error.message });
16868
+ state.span.end();
16869
+ states.delete(event);
16870
+ }
16871
+ });
16872
+ return;
16873
+ }
16874
+ try {
16875
+ state.span.log({ output: result });
16876
+ } finally {
16877
+ cleanupActiveRunnerSpan(state, this.activeRunnerSpans);
16878
+ state.span.end();
16879
+ states.delete(event);
16880
+ }
16881
+ },
16882
+ error: (event) => {
16883
+ const state = states.get(event);
16884
+ if (!state || !event.error) {
16885
+ return;
16886
+ }
16887
+ cleanupActiveRunnerSpan(state, this.activeRunnerSpans);
16888
+ state.span.log({ error: event.error.message });
16889
+ state.span.end();
16890
+ states.delete(event);
16891
+ }
16892
+ };
16893
+ tracingChannel.subscribe(handlers);
16894
+ this.unsubscribers.push(() => {
16895
+ unbindCurrentSpanStore?.();
16896
+ tracingChannel.unsubscribe(handlers);
16897
+ });
16898
+ }
16899
+ subscribeToAgentRunAsync() {
16900
+ const tracingChannel = googleADKChannels.agentRunAsync.tracingChannel();
16901
+ const states = /* @__PURE__ */ new WeakMap();
16902
+ const createState = (event) => {
16903
+ const parentContext = event.arguments[0];
16904
+ const agentName = extractAgentName(parentContext);
16905
+ const runnerParentSpan = findRunnerParentSpan(
16906
+ parentContext,
16907
+ this.activeRunnerSpans
16908
+ );
16909
+ const contextKey = extractInvocationContextKey(parentContext);
16910
+ const span = startSpan({
16911
+ name: agentName ? `Agent: ${agentName}` : "Google ADK Agent",
16912
+ spanAttributes: {
16913
+ type: "task" /* TASK */
16914
+ },
16915
+ ...runnerParentSpan ? {
16916
+ parentSpanIds: {
16917
+ spanId: runnerParentSpan.spanId,
16918
+ rootSpanId: runnerParentSpan.rootSpanId
16919
+ }
16920
+ } : {}
16921
+ });
16922
+ const startTime = getCurrentUnixTimestamp();
16923
+ try {
16924
+ const metadata = {
16925
+ provider: "google-adk"
16926
+ };
16927
+ if (agentName) {
16928
+ metadata["google_adk.agent_name"] = agentName;
16929
+ }
16930
+ const modelName = extractModelName(parentContext);
16931
+ if (modelName) {
16932
+ metadata.model = modelName;
16933
+ }
16934
+ span.log({ metadata });
16935
+ } catch {
16936
+ }
16937
+ if (contextKey && agentName) {
16938
+ this.activeAgentSpans.set(agentContextKey(contextKey, agentName), span);
16939
+ }
16940
+ return { span, startTime, events: [], contextKey, name: agentName };
16941
+ };
16942
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart3(
16943
+ tracingChannel,
16944
+ states,
16945
+ createState
16946
+ );
16947
+ const handlers = {
16948
+ start: (event) => {
16949
+ ensureState(states, event, () => createState(event));
16950
+ },
16951
+ end: (event) => {
16952
+ const state = states.get(event);
16953
+ if (!state) {
16954
+ return;
16955
+ }
16956
+ const result = event.result;
16957
+ if (isAsyncIterable(result)) {
16958
+ bindAsyncIterableToCurrentSpan(result, state.span);
16959
+ patchStreamIfNeeded(result, {
16960
+ onChunk: (adkEvent) => {
16961
+ state.events.push(adkEvent);
16962
+ },
16963
+ onComplete: () => {
16964
+ finalizeAgentSpan(state, this.activeAgentSpans);
16965
+ states.delete(event);
16966
+ },
16967
+ onError: (error) => {
16968
+ cleanupActiveAgentSpan(state, this.activeAgentSpans);
16969
+ state.span.log({ error: error.message });
16970
+ state.span.end();
16971
+ states.delete(event);
16972
+ }
16973
+ });
16974
+ return;
16975
+ }
16976
+ try {
16977
+ state.span.log({ output: result });
16978
+ } finally {
16979
+ cleanupActiveAgentSpan(state, this.activeAgentSpans);
16980
+ state.span.end();
16981
+ states.delete(event);
16982
+ }
16983
+ },
16984
+ error: (event) => {
16985
+ const state = states.get(event);
16986
+ if (!state || !event.error) {
16987
+ return;
16988
+ }
16989
+ cleanupActiveAgentSpan(state, this.activeAgentSpans);
16990
+ state.span.log({ error: event.error.message });
16991
+ state.span.end();
16992
+ states.delete(event);
16993
+ }
16994
+ };
16995
+ tracingChannel.subscribe(handlers);
16996
+ this.unsubscribers.push(() => {
16997
+ unbindCurrentSpanStore?.();
16998
+ tracingChannel.unsubscribe(handlers);
16999
+ });
17000
+ }
17001
+ subscribeToToolRunAsync() {
17002
+ const tracingChannel = googleADKChannels.toolRunAsync.tracingChannel();
17003
+ const states = /* @__PURE__ */ new WeakMap();
17004
+ const handlers = {
17005
+ start: (event) => {
17006
+ const req = event.arguments[0] ?? {};
17007
+ const tool = event.self;
17008
+ const toolName = extractToolName(req, tool);
17009
+ const parentSpan = findToolParentSpan(
17010
+ req,
17011
+ this.activeAgentSpans,
17012
+ this.activeRunnerSpans
17013
+ );
17014
+ const createSpan = () => startSpan({
17015
+ name: toolName ? `tool: ${toolName}` : "Google ADK Tool",
17016
+ spanAttributes: {
17017
+ type: "tool" /* TOOL */
17018
+ },
17019
+ event: {
17020
+ input: req.args,
17021
+ metadata: {
17022
+ provider: "google-adk",
17023
+ ...toolName && { "google_adk.tool_name": toolName },
17024
+ ...extractToolCallId(req) && {
17025
+ "google_adk.tool_call_id": extractToolCallId(req)
17026
+ }
17027
+ }
17028
+ }
17029
+ });
17030
+ const span = parentSpan ? withCurrent(parentSpan, () => createSpan()) : createSpan();
17031
+ const startTime = getCurrentUnixTimestamp();
17032
+ states.set(event, { span, startTime });
17033
+ },
17034
+ asyncEnd: (event) => {
17035
+ const state = states.get(event);
17036
+ if (!state) {
17037
+ return;
17038
+ }
17039
+ try {
17040
+ const metrics = {};
17041
+ const end = getCurrentUnixTimestamp();
17042
+ metrics.start = state.startTime;
17043
+ metrics.end = end;
17044
+ metrics.duration = end - state.startTime;
17045
+ state.span.log({
17046
+ output: event.result,
17047
+ metrics: cleanMetrics2(metrics)
17048
+ });
17049
+ } finally {
17050
+ state.span.end();
17051
+ states.delete(event);
17052
+ }
17053
+ },
17054
+ error: (event) => {
17055
+ const state = states.get(event);
17056
+ if (!state || !event.error) {
17057
+ return;
17058
+ }
17059
+ state.span.log({ error: event.error.message });
17060
+ state.span.end();
17061
+ states.delete(event);
17062
+ }
17063
+ };
17064
+ tracingChannel.subscribe(handlers);
17065
+ this.unsubscribers.push(() => {
17066
+ tracingChannel.unsubscribe(handlers);
17067
+ });
17068
+ }
17069
+ };
17070
+ function ensureState(states, event, create) {
17071
+ const existing = states.get(event);
17072
+ if (existing) {
17073
+ return existing;
17074
+ }
17075
+ const created = create();
17076
+ states.set(event, created);
17077
+ return created;
17078
+ }
17079
+ function bindAsyncIterableToCurrentSpan(stream, span) {
17080
+ if (!isAsyncIterable(stream)) {
17081
+ return stream;
17082
+ }
17083
+ if (Object.isFrozen(stream) || Object.isSealed(stream)) {
17084
+ return stream;
17085
+ }
17086
+ if ("next" in stream && typeof stream.next === "function") {
17087
+ if ("__braintrust_current_span_bound" in stream) {
17088
+ return stream;
17089
+ }
17090
+ try {
17091
+ const iterator = stream;
17092
+ const originalNext = iterator.next.bind(iterator);
17093
+ iterator.next = (...args) => withCurrent(span, () => originalNext(...args));
17094
+ if (typeof iterator.return === "function") {
17095
+ const originalReturn = iterator.return.bind(iterator);
17096
+ iterator.return = (...args) => withCurrent(span, () => originalReturn(...args));
17097
+ }
17098
+ if (typeof iterator.throw === "function") {
17099
+ const originalThrow = iterator.throw.bind(iterator);
17100
+ iterator.throw = (...args) => withCurrent(span, () => originalThrow(...args));
17101
+ }
17102
+ Object.defineProperty(stream, "__braintrust_current_span_bound", {
17103
+ value: true
17104
+ });
17105
+ return stream;
17106
+ } catch {
17107
+ return stream;
17108
+ }
17109
+ }
17110
+ const originalIteratorFn = stream[Symbol.asyncIterator];
17111
+ if ("__braintrust_current_span_bound" in originalIteratorFn && originalIteratorFn.__braintrust_current_span_bound) {
17112
+ return stream;
17113
+ }
17114
+ try {
17115
+ const patchedIteratorFn = function() {
17116
+ const iterator = originalIteratorFn.call(this);
17117
+ const originalNext = iterator.next.bind(iterator);
17118
+ iterator.next = (...args) => withCurrent(span, () => originalNext(...args));
17119
+ if (typeof iterator.return === "function") {
17120
+ const originalReturn = iterator.return.bind(iterator);
17121
+ iterator.return = (...args) => withCurrent(span, () => originalReturn(...args));
17122
+ }
17123
+ if (typeof iterator.throw === "function") {
17124
+ const originalThrow = iterator.throw.bind(iterator);
17125
+ iterator.throw = (...args) => withCurrent(span, () => originalThrow(...args));
17126
+ }
17127
+ return iterator;
17128
+ };
17129
+ Object.defineProperty(
17130
+ patchedIteratorFn,
17131
+ "__braintrust_current_span_bound",
17132
+ {
17133
+ value: true
17134
+ }
17135
+ );
17136
+ stream[Symbol.asyncIterator] = patchedIteratorFn;
17137
+ } catch {
17138
+ return stream;
17139
+ }
17140
+ return stream;
17141
+ }
17142
+ function bindCurrentSpanStoreToStart3(tracingChannel, states, create) {
17143
+ const state = _internalGetGlobalState();
17144
+ const contextManager = state?.contextManager;
17145
+ const startChannel = tracingChannel.start;
17146
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
17147
+ if (!startChannel?.bindStore || !currentSpanStore) {
17148
+ return void 0;
17149
+ }
17150
+ startChannel.bindStore(currentSpanStore, (event) => {
17151
+ const span = ensureState(
17152
+ states,
17153
+ event,
17154
+ () => create(event)
17155
+ ).span;
17156
+ return contextManager.wrapSpanForStore(span);
17157
+ });
17158
+ return () => {
17159
+ startChannel.unbindStore?.(currentSpanStore);
17160
+ };
17161
+ }
17162
+ function extractRunnerContextKey(paramsOrContext) {
17163
+ const directUserId = "userId" in paramsOrContext ? paramsOrContext.userId : void 0;
17164
+ const directSessionId = "sessionId" in paramsOrContext ? paramsOrContext.sessionId : void 0;
17165
+ if (typeof directUserId === "string" && typeof directSessionId === "string") {
17166
+ return `${directUserId}:${directSessionId}`;
17167
+ }
17168
+ const invocationContext = paramsOrContext;
17169
+ return extractInvocationContextKey(invocationContext);
17170
+ }
17171
+ function extractInvocationContextKey(parentContext) {
17172
+ const session = parentContext?.session;
17173
+ const userId = session?.userId;
17174
+ const sessionId = session?.id;
17175
+ if (typeof userId !== "string" || typeof sessionId !== "string") {
17176
+ return void 0;
17177
+ }
17178
+ return `${userId}:${sessionId}`;
17179
+ }
17180
+ function findRunnerParentSpan(parentContext, activeRunnerSpans) {
17181
+ const contextKey = extractInvocationContextKey(parentContext);
17182
+ return contextKey ? activeRunnerSpans.get(contextKey) : void 0;
17183
+ }
17184
+ function cleanupActiveRunnerSpan(state, activeRunnerSpans) {
17185
+ if (state.contextKey) {
17186
+ activeRunnerSpans.delete(state.contextKey);
17187
+ }
17188
+ }
17189
+ function agentContextKey(contextKey, agentName) {
17190
+ return `${contextKey}:${agentName}`;
17191
+ }
17192
+ function cleanupActiveAgentSpan(state, activeAgentSpans) {
17193
+ if (state.contextKey && state.name) {
17194
+ activeAgentSpans.delete(agentContextKey(state.contextKey, state.name));
17195
+ }
17196
+ }
17197
+ function extractRunnerInput(paramsOrContext) {
17198
+ const content = "newMessage" in paramsOrContext ? paramsOrContext.newMessage : paramsOrContext.userContent;
17199
+ if (!content || typeof content !== "object") {
17200
+ return void 0;
17201
+ }
17202
+ const normalizedContent = content;
17203
+ if (normalizedContent.parts && Array.isArray(normalizedContent.parts)) {
17204
+ const textParts = normalizedContent.parts.filter((p) => p.text !== void 0).map((p) => p.text);
17205
+ if (textParts.length > 0) {
17206
+ return {
17207
+ messages: [
17208
+ {
17209
+ role: normalizedContent.role ?? "user",
17210
+ content: textParts.join("")
17211
+ }
17212
+ ]
17213
+ };
17214
+ }
17215
+ }
17216
+ return { messages: [normalizedContent] };
17217
+ }
17218
+ function extractRunnerMetadata(paramsOrContext) {
17219
+ const metadata = {
17220
+ provider: "google-adk"
17221
+ };
17222
+ const directUserId = "userId" in paramsOrContext ? paramsOrContext.userId : void 0;
17223
+ const directSessionId = "sessionId" in paramsOrContext ? paramsOrContext.sessionId : void 0;
17224
+ if (typeof directUserId === "string") {
17225
+ metadata["google_adk.user_id"] = directUserId;
17226
+ }
17227
+ if (typeof directSessionId === "string") {
17228
+ metadata["google_adk.session_id"] = directSessionId;
17229
+ }
17230
+ const session = "session" in paramsOrContext ? paramsOrContext.session : void 0;
17231
+ if (metadata["google_adk.user_id"] === void 0 && typeof session?.userId === "string") {
17232
+ metadata["google_adk.user_id"] = session.userId;
17233
+ }
17234
+ if (metadata["google_adk.session_id"] === void 0 && typeof session?.id === "string") {
17235
+ metadata["google_adk.session_id"] = session.id;
17236
+ }
17237
+ return metadata;
17238
+ }
17239
+ function extractAgentName(parentContext) {
17240
+ if (!parentContext) {
17241
+ return void 0;
17242
+ }
17243
+ const agent = parentContext.agent;
17244
+ return agent?.name;
17245
+ }
17246
+ function extractModelName(parentContext) {
17247
+ if (!parentContext) {
17248
+ return void 0;
17249
+ }
17250
+ const agent = parentContext.agent;
17251
+ if (!agent?.model) {
17252
+ return void 0;
17253
+ }
17254
+ if (typeof agent.model === "string") {
17255
+ return agent.model;
17256
+ }
17257
+ if (typeof agent.model === "object" && "model" in agent.model) {
17258
+ return agent.model.model;
17259
+ }
17260
+ return void 0;
17261
+ }
17262
+ function extractToolCallId(req) {
17263
+ const toolContext = req.toolContext;
17264
+ return toolContext?.functionCallId;
17265
+ }
17266
+ function extractToolName(req, tool) {
17267
+ if (typeof tool?.name === "string" && tool.name.length > 0) {
17268
+ return tool.name;
17269
+ }
17270
+ const toolContext = req.toolContext;
17271
+ const invocationContext = toolContext?.invocationContext;
17272
+ const invocationTool = invocationContext?.tool;
17273
+ const toolName = invocationTool?.name;
17274
+ return typeof toolName === "string" && toolName.length > 0 ? toolName : void 0;
17275
+ }
17276
+ function extractToolAgentName(req) {
17277
+ const toolContext = req.toolContext;
17278
+ const directName = toolContext?.agentName;
17279
+ if (typeof directName === "string" && directName.length > 0) {
17280
+ return directName;
17281
+ }
17282
+ const invocationContext = toolContext?.invocationContext;
17283
+ return extractAgentName(invocationContext);
17284
+ }
17285
+ function findToolParentSpan(req, activeAgentSpans, activeRunnerSpans) {
17286
+ const toolContext = req.toolContext;
17287
+ const invocationContext = toolContext?.invocationContext;
17288
+ const contextKey = extractInvocationContextKey(invocationContext);
17289
+ const agentName = extractToolAgentName(req);
17290
+ if (contextKey && agentName) {
17291
+ const agentSpan = activeAgentSpans.get(
17292
+ agentContextKey(contextKey, agentName)
17293
+ );
17294
+ if (agentSpan) {
17295
+ return agentSpan;
17296
+ }
17297
+ }
17298
+ return contextKey ? activeRunnerSpans.get(contextKey) : void 0;
17299
+ }
17300
+ function finalizeRunnerSpan(state, activeRunnerSpans) {
17301
+ try {
17302
+ const lastEvent = getLastNonPartialEvent(state.events);
17303
+ const metrics = {};
17304
+ const end = getCurrentUnixTimestamp();
17305
+ metrics.start = state.startTime;
17306
+ metrics.end = end;
17307
+ metrics.duration = end - state.startTime;
17308
+ const usage = aggregateUsageFromEvents(state.events);
17309
+ if (usage) {
17310
+ populateUsageMetrics2(metrics, usage);
17311
+ }
17312
+ state.span.log({
17313
+ output: lastEvent ? extractEventOutput(lastEvent) : void 0,
17314
+ metrics: cleanMetrics2(metrics)
17315
+ });
17316
+ } finally {
17317
+ cleanupActiveRunnerSpan(state, activeRunnerSpans);
17318
+ state.span.end();
17319
+ }
17320
+ }
17321
+ function finalizeAgentSpan(state, activeAgentSpans) {
17322
+ try {
17323
+ const lastEvent = getLastNonPartialEvent(state.events);
17324
+ const metrics = {};
17325
+ const end = getCurrentUnixTimestamp();
17326
+ metrics.start = state.startTime;
17327
+ metrics.end = end;
17328
+ metrics.duration = end - state.startTime;
17329
+ state.span.log({
17330
+ output: lastEvent ? extractEventOutput(lastEvent) : void 0,
17331
+ metrics: cleanMetrics2(metrics)
17332
+ });
17333
+ } finally {
17334
+ cleanupActiveAgentSpan(state, activeAgentSpans);
17335
+ state.span.end();
17336
+ }
17337
+ }
17338
+ function getLastNonPartialEvent(events) {
17339
+ for (let i = events.length - 1; i >= 0; i--) {
17340
+ if (!events[i].partial) {
17341
+ return events[i];
17342
+ }
17343
+ }
17344
+ return events.length > 0 ? events[events.length - 1] : void 0;
17345
+ }
17346
+ function extractEventOutput(event) {
17347
+ if (!event.content) {
17348
+ return void 0;
17349
+ }
17350
+ const output = {};
17351
+ if (event.content.role) {
17352
+ output.role = event.content.role;
17353
+ }
17354
+ if (event.content.parts && Array.isArray(event.content.parts)) {
17355
+ const textParts = event.content.parts.filter((p) => p.text !== void 0 && !p.thought).map((p) => p.text);
17356
+ const thoughtParts = event.content.parts.filter((p) => p.text !== void 0 && p.thought).map((p) => p.text);
17357
+ const functionCalls = event.content.parts.filter((p) => p.functionCall).map((p) => p.functionCall);
17358
+ if (textParts.length > 0) {
17359
+ output.content = textParts.join("");
17360
+ }
17361
+ if (thoughtParts.length > 0) {
17362
+ output.thought = thoughtParts.join("");
17363
+ }
17364
+ if (functionCalls.length > 0) {
17365
+ output.functionCalls = functionCalls;
17366
+ }
17367
+ }
17368
+ if (event.author) {
17369
+ output.author = event.author;
17370
+ }
17371
+ return Object.keys(output).length > 0 ? output : void 0;
17372
+ }
17373
+ function aggregateUsageFromEvents(events) {
17374
+ let hasUsage = false;
17375
+ const aggregated = {};
17376
+ for (const event of events) {
17377
+ if (!event.usageMetadata) {
17378
+ continue;
17379
+ }
17380
+ hasUsage = true;
17381
+ const usage = event.usageMetadata;
17382
+ if (usage.promptTokenCount !== void 0) {
17383
+ aggregated.promptTokenCount = (aggregated.promptTokenCount ?? 0) + usage.promptTokenCount;
17384
+ }
17385
+ if (usage.candidatesTokenCount !== void 0) {
17386
+ aggregated.candidatesTokenCount = (aggregated.candidatesTokenCount ?? 0) + usage.candidatesTokenCount;
17387
+ }
17388
+ if (usage.totalTokenCount !== void 0) {
17389
+ aggregated.totalTokenCount = (aggregated.totalTokenCount ?? 0) + usage.totalTokenCount;
17390
+ }
17391
+ if (usage.cachedContentTokenCount !== void 0) {
17392
+ aggregated.cachedContentTokenCount = (aggregated.cachedContentTokenCount ?? 0) + usage.cachedContentTokenCount;
17393
+ }
17394
+ if (usage.thoughtsTokenCount !== void 0) {
17395
+ aggregated.thoughtsTokenCount = (aggregated.thoughtsTokenCount ?? 0) + usage.thoughtsTokenCount;
17396
+ }
17397
+ }
17398
+ return hasUsage ? aggregated : void 0;
17399
+ }
17400
+ function populateUsageMetrics2(metrics, usage) {
17401
+ if (usage.promptTokenCount !== void 0) {
17402
+ metrics.prompt_tokens = usage.promptTokenCount;
17403
+ }
17404
+ if (usage.candidatesTokenCount !== void 0) {
17405
+ metrics.completion_tokens = usage.candidatesTokenCount;
17406
+ }
17407
+ if (usage.totalTokenCount !== void 0) {
17408
+ metrics.tokens = usage.totalTokenCount;
17409
+ }
17410
+ if (usage.cachedContentTokenCount !== void 0) {
17411
+ metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
17412
+ }
17413
+ if (usage.thoughtsTokenCount !== void 0) {
17414
+ metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
17415
+ }
17416
+ }
17417
+ function cleanMetrics2(metrics) {
17418
+ const cleaned = {};
17419
+ for (const [key, value] of Object.entries(metrics)) {
17420
+ if (value !== null && value !== void 0) {
17421
+ cleaned[key] = value;
17422
+ }
17423
+ }
17424
+ return cleaned;
17425
+ }
17426
+
17427
+ // src/instrumentation/plugins/cohere-channels.ts
17428
+ var cohereChannels = defineChannels("cohere-ai", {
17429
+ chat: channel({
17430
+ channelName: "chat",
17431
+ kind: "async"
17432
+ }),
17433
+ chatStream: channel({
17434
+ channelName: "chatStream",
17435
+ kind: "async"
17436
+ }),
17437
+ embed: channel({
17438
+ channelName: "embed",
17439
+ kind: "async"
17440
+ }),
17441
+ rerank: channel({
17442
+ channelName: "rerank",
17443
+ kind: "async"
17444
+ })
17445
+ });
17446
+
17447
+ // src/instrumentation/plugins/cohere-plugin.ts
17448
+ var CoherePlugin = class extends BasePlugin {
17449
+ onEnable() {
17450
+ this.subscribeToCohereChannels();
17451
+ }
17452
+ onDisable() {
17453
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
17454
+ }
17455
+ subscribeToCohereChannels() {
17456
+ this.unsubscribers.push(
17457
+ traceStreamingChannel(cohereChannels.chat, {
17458
+ name: "cohere.chat",
17459
+ type: "llm" /* LLM */,
17460
+ extractInput: extractChatInputWithMetadata2,
17461
+ extractOutput: (result) => extractCohereChatOutput(result),
17462
+ extractMetadata: (result) => extractCohereResponseMetadata(result),
17463
+ extractMetrics: (result, startTime) => {
17464
+ const metrics = parseCohereMetricsFromUsage(result);
17465
+ if (startTime) {
17466
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
17467
+ }
17468
+ return metrics;
17469
+ }
17470
+ })
17471
+ );
17472
+ this.unsubscribers.push(
17473
+ traceStreamingChannel(cohereChannels.chatStream, {
17474
+ name: "cohere.chatStream",
17475
+ type: "llm" /* LLM */,
17476
+ extractInput: extractChatInputWithMetadata2,
17477
+ extractOutput: () => void 0,
17478
+ extractMetadata: () => void 0,
17479
+ extractMetrics: () => ({}),
17480
+ aggregateChunks: aggregateCohereChatStreamChunks
17481
+ })
17482
+ );
17483
+ this.unsubscribers.push(
17484
+ traceAsyncChannel(cohereChannels.embed, {
17485
+ name: "cohere.embed",
17486
+ type: "llm" /* LLM */,
17487
+ extractInput: extractEmbedInputWithMetadata,
17488
+ extractOutput: extractCohereEmbeddingOutput,
17489
+ extractMetadata: (result) => extractCohereResponseMetadata(result),
17490
+ extractMetrics: (result) => parseCohereMetricsFromUsage(result)
17491
+ })
17492
+ );
17493
+ this.unsubscribers.push(
17494
+ traceAsyncChannel(cohereChannels.rerank, {
17495
+ name: "cohere.rerank",
17496
+ type: "llm" /* LLM */,
17497
+ extractInput: extractRerankInputWithMetadata,
17498
+ extractOutput: (result) => {
17499
+ if (!isObject(result) || !Array.isArray(result.results)) {
17500
+ return void 0;
17501
+ }
17502
+ return result.results.slice(0, 100).map((item) => ({
17503
+ index: isObject(item) ? item.index : void 0,
17504
+ relevance_score: isObject(item) ? (typeof item.relevanceScore === "number" ? item.relevanceScore : item.relevance_score) ?? null : null
17505
+ }));
17506
+ },
17507
+ extractMetadata: (result) => extractCohereResponseMetadata(result),
17508
+ extractMetrics: (result) => parseCohereMetricsFromUsage(result)
17509
+ })
17510
+ );
17511
+ }
17512
+ };
17513
+ var CHAT_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
17514
+ "conversationId",
17515
+ "conversation_id",
17516
+ "frequencyPenalty",
17517
+ "frequency_penalty",
17518
+ "k",
17519
+ "maxInputTokens",
17520
+ "max_input_tokens",
17521
+ "maxTokens",
17522
+ "max_tokens",
17523
+ "model",
17524
+ "p",
17525
+ "preamble",
17526
+ "presencePenalty",
17527
+ "presence_penalty",
17528
+ "priority",
17529
+ "promptTruncation",
17530
+ "prompt_truncation",
17531
+ "rawPrompting",
17532
+ "raw_prompting",
17533
+ "responseFormat",
17534
+ "response_format",
17535
+ "safetyMode",
17536
+ "safety_mode",
17537
+ "searchQueriesOnly",
17538
+ "search_queries_only",
17539
+ "seed",
17540
+ "stopSequences",
17541
+ "stop_sequences",
17542
+ "strictTools",
17543
+ "strict_tools",
17544
+ "temperature",
17545
+ "toolChoice",
17546
+ "tool_choice"
17547
+ ]);
17548
+ var EMBED_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
17549
+ "embeddingTypes",
17550
+ "embedding_types",
17551
+ "inputType",
17552
+ "input_type",
17553
+ "maxTokens",
17554
+ "max_tokens",
17555
+ "model",
17556
+ "outputDimension",
17557
+ "output_dimension",
17558
+ "priority",
17559
+ "truncate"
17560
+ ]);
17561
+ var RERANK_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
17562
+ "maxChunksPerDoc",
17563
+ "max_chunks_per_doc",
17564
+ "maxTokensPerDoc",
17565
+ "max_tokens_per_doc",
17566
+ "model",
17567
+ "priority",
17568
+ "rankFields",
17569
+ "rank_fields",
17570
+ "returnDocuments",
17571
+ "return_documents",
17572
+ "topN",
17573
+ "top_n"
17574
+ ]);
17575
+ var RESPONSE_METADATA_ALLOWLIST2 = /* @__PURE__ */ new Set([
17576
+ "finishReason",
17577
+ "finish_reason",
17578
+ "generationId",
17579
+ "generation_id",
17580
+ "id",
17581
+ "responseId",
17582
+ "responseType",
17583
+ "response_id",
17584
+ "response_type"
17585
+ ]);
17586
+ function normalizeArgs5(args) {
17587
+ if (Array.isArray(args)) {
17588
+ return args;
17589
+ }
17590
+ if (isArrayLike5(args)) {
17591
+ return Array.from(args);
17592
+ }
17593
+ return [args];
17594
+ }
17595
+ function isArrayLike5(value) {
17596
+ return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
17597
+ }
17598
+ function getRequestArg(args) {
17599
+ const firstObjectArg = normalizeArgs5(args).find((arg) => isObject(arg));
17600
+ return isObject(firstObjectArg) ? firstObjectArg : void 0;
17601
+ }
17602
+ function addCohereProviderMetadata(metadata) {
17603
+ return {
17604
+ ...metadata,
17605
+ provider: "cohere"
17606
+ };
17607
+ }
17608
+ function pickAllowedMetadata2(metadata, allowlist) {
17609
+ if (!metadata) {
17610
+ return {};
17611
+ }
17612
+ const picked = {};
17613
+ for (const key of allowlist) {
17614
+ const value = metadata[key];
17615
+ if (value !== void 0) {
17616
+ picked[key] = value;
17617
+ }
17618
+ }
17619
+ return picked;
17620
+ }
17621
+ function extractChatInputWithMetadata2(args) {
17622
+ const request = getRequestArg(args);
17623
+ const { message, messages, ...rawMetadata } = request || {};
17624
+ return {
17625
+ input: processInputAttachments(messages ?? message),
17626
+ metadata: addCohereProviderMetadata(
17627
+ pickAllowedMetadata2(rawMetadata, CHAT_REQUEST_METADATA_ALLOWLIST)
17628
+ )
17629
+ };
17630
+ }
17631
+ function extractEmbedInputWithMetadata(args) {
17632
+ const request = getRequestArg(args);
17633
+ const { inputs, texts, images, ...rawMetadata } = request || {};
17634
+ return {
17635
+ input: inputs ?? texts ?? images,
17636
+ metadata: addCohereProviderMetadata(
17637
+ pickAllowedMetadata2(rawMetadata, EMBED_REQUEST_METADATA_ALLOWLIST)
17638
+ )
17639
+ };
17640
+ }
17641
+ function extractRerankInputWithMetadata(args) {
17642
+ const request = getRequestArg(args);
17643
+ const { query, documents, ...rawMetadata } = request || {};
17644
+ return {
17645
+ input: {
17646
+ documents,
17647
+ query
17648
+ },
17649
+ metadata: addCohereProviderMetadata({
17650
+ ...pickAllowedMetadata2(rawMetadata, RERANK_REQUEST_METADATA_ALLOWLIST),
17651
+ ...Array.isArray(documents) ? { document_count: documents.length } : {}
17652
+ })
17653
+ };
17654
+ }
17655
+ function extractCohereResponseMetadata(result) {
17656
+ if (!isObject(result)) {
17657
+ return void 0;
17658
+ }
17659
+ const responseMetadata = pickAllowedMetadata2(
17660
+ result,
17661
+ RESPONSE_METADATA_ALLOWLIST2
17662
+ );
17663
+ const meta = isObject(result.meta) ? result.meta : void 0;
17664
+ const apiVersion = isObject(meta?.apiVersion) && typeof meta.apiVersion.version === "string" && meta.apiVersion.version || isObject(meta?.api_version) && typeof meta.api_version.version === "string" && meta.api_version.version;
17665
+ const metadata = {
17666
+ ...responseMetadata,
17667
+ ...apiVersion ? { api_version: apiVersion } : {}
17668
+ };
17669
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
17670
+ }
17671
+ function extractCohereChatOutput(result) {
17672
+ if (!isObject(result)) {
17673
+ return void 0;
17674
+ }
17675
+ if (isObject(result.message)) {
17676
+ return result.message;
17677
+ }
17678
+ if (typeof result.text !== "string") {
17679
+ return void 0;
17680
+ }
17681
+ const toolCalls = Array.isArray(result.toolCalls) ? result.toolCalls : Array.isArray(result.tool_calls) ? result.tool_calls : void 0;
17682
+ if (toolCalls && toolCalls.length > 0) {
17683
+ return {
17684
+ content: result.text,
17685
+ role: "assistant",
17686
+ toolCalls
17687
+ };
17688
+ }
17689
+ return result.text;
17690
+ }
17691
+ function extractCohereEmbeddingOutput(result) {
17692
+ if (!isObject(result)) {
17693
+ return void 0;
17694
+ }
17695
+ const embeddingLength = getFirstEmbeddingLength(result.embeddings);
17696
+ if (embeddingLength === void 0) {
17697
+ return void 0;
17698
+ }
17699
+ return {
17700
+ embedding_length: embeddingLength
17701
+ };
17702
+ }
17703
+ function getFirstEmbeddingLength(value) {
17704
+ if (Array.isArray(value) && Array.isArray(value[0])) {
17705
+ return value[0].length;
17706
+ }
17707
+ if (!isObject(value)) {
17708
+ return void 0;
17709
+ }
17710
+ for (const key of Object.keys(value)) {
17711
+ const entry = value[key];
17712
+ if (Array.isArray(entry) && Array.isArray(entry[0])) {
17713
+ return entry[0].length;
17714
+ }
17715
+ }
17716
+ return void 0;
17717
+ }
17718
+ function setMetricIfNumber(metrics, key, value) {
17719
+ if (typeof value === "number" && Number.isFinite(value)) {
17720
+ metrics[key] = value;
17721
+ }
17722
+ }
17723
+ function mergeUsageMetrics(metrics, usage) {
17724
+ if (!isObject(usage)) {
17725
+ return metrics;
17726
+ }
17727
+ const source = usage;
17728
+ setMetricIfNumber(
17729
+ metrics,
17730
+ "prompt_tokens",
17731
+ source.inputTokens ?? source.input_tokens
17732
+ );
17733
+ setMetricIfNumber(
17734
+ metrics,
17735
+ "completion_tokens",
17736
+ source.outputTokens ?? source.output_tokens
17737
+ );
17738
+ setMetricIfNumber(
17739
+ metrics,
17740
+ "tokens",
17741
+ source.totalTokens ?? source.total_tokens
17742
+ );
17743
+ setMetricIfNumber(
17744
+ metrics,
17745
+ "prompt_cached_tokens",
17746
+ source.cachedTokens ?? source.cached_tokens
17747
+ );
17748
+ const tokenContainer = isObject(source.tokens) ? source.tokens : void 0;
17749
+ if (tokenContainer) {
17750
+ setMetricIfNumber(
17751
+ metrics,
17752
+ "prompt_tokens",
17753
+ tokenContainer.inputTokens ?? tokenContainer.input_tokens
17754
+ );
17755
+ setMetricIfNumber(
17756
+ metrics,
17757
+ "completion_tokens",
17758
+ tokenContainer.outputTokens ?? tokenContainer.output_tokens
17759
+ );
17760
+ setMetricIfNumber(
17761
+ metrics,
17762
+ "tokens",
17763
+ tokenContainer.totalTokens ?? tokenContainer.total_tokens
17764
+ );
17765
+ }
17766
+ const billedUnits = (isObject(source.billedUnits) ? source.billedUnits : void 0) || (isObject(source.billed_units) ? source.billed_units : void 0);
17767
+ if (billedUnits) {
17768
+ setMetricIfNumber(
17769
+ metrics,
17770
+ "prompt_tokens",
17771
+ billedUnits.inputTokens ?? billedUnits.input_tokens
17772
+ );
17773
+ setMetricIfNumber(
17774
+ metrics,
17775
+ "completion_tokens",
17776
+ billedUnits.outputTokens ?? billedUnits.output_tokens
17777
+ );
17778
+ setMetricIfNumber(
17779
+ metrics,
17780
+ "search_units",
17781
+ billedUnits.searchUnits ?? billedUnits.search_units
17782
+ );
17783
+ setMetricIfNumber(metrics, "classifications", billedUnits.classifications);
17784
+ setMetricIfNumber(metrics, "images", billedUnits.images);
17785
+ setMetricIfNumber(
17786
+ metrics,
17787
+ "image_tokens",
17788
+ billedUnits.imageTokens ?? billedUnits.image_tokens
17789
+ );
17790
+ }
17791
+ return metrics;
17792
+ }
17793
+ function parseCohereMetricsFromUsage(source) {
17794
+ if (!isObject(source)) {
17795
+ return {};
17796
+ }
17797
+ const metrics = {};
17798
+ mergeUsageMetrics(metrics, source);
17799
+ if ("usage" in source) {
17800
+ mergeUsageMetrics(metrics, source.usage);
17801
+ }
17802
+ if ("meta" in source) {
17803
+ mergeUsageMetrics(metrics, source.meta);
17804
+ }
17805
+ if (metrics.tokens === void 0 && typeof metrics.prompt_tokens === "number" && typeof metrics.completion_tokens === "number") {
17806
+ metrics.tokens = metrics.prompt_tokens + metrics.completion_tokens;
17807
+ }
17808
+ return metrics;
17809
+ }
17810
+ function toToolCallArray(value) {
17811
+ if (Array.isArray(value)) {
17812
+ return value.filter((item) => isObject(item));
17813
+ }
17814
+ return isObject(value) ? [value] : [];
17815
+ }
17816
+ function getToolCallIndex2(toolCall, fallbackIndex) {
17817
+ return typeof toolCall.index === "number" && Number.isInteger(toolCall.index) ? toolCall.index : fallbackIndex;
17818
+ }
17819
+ function appendToolCallDelta(existing, incoming) {
17820
+ const currentArguments = isObject(existing?.function) && typeof existing.function.arguments === "string" ? existing.function.arguments : "";
17821
+ const incomingArguments = isObject(incoming.function) && typeof incoming.function.arguments === "string" ? incoming.function.arguments : "";
17822
+ return {
17823
+ ...existing,
17824
+ ...incoming,
17825
+ function: {
17826
+ ...isObject(existing?.function) ? existing.function : {},
17827
+ ...isObject(incoming.function) ? incoming.function : {},
17828
+ ...incomingArguments ? { arguments: `${currentArguments}${incomingArguments}` } : {}
17829
+ }
17830
+ };
17831
+ }
17832
+ function extractV8DeltaText(chunk) {
17833
+ if (!isObject(chunk.delta) || !isObject(chunk.delta.message)) {
17834
+ return void 0;
17835
+ }
17836
+ const content = chunk.delta.message.content;
17837
+ if (typeof content === "string") {
17838
+ return content;
17839
+ }
17840
+ if (isObject(content) && typeof content.text === "string") {
17841
+ return content.text;
17842
+ }
17843
+ return void 0;
17844
+ }
17845
+ function aggregateCohereChatStreamChunks(chunks) {
17846
+ const textDeltas = [];
17847
+ const toolCallsByIndex = {};
17848
+ const toolCallOrder = [];
17849
+ let terminalResponse;
17850
+ let role;
17851
+ let finishReason;
17852
+ let metadata = {};
17853
+ let metrics = {};
17854
+ for (const chunk of chunks) {
17855
+ if (!isObject(chunk)) {
17856
+ continue;
17857
+ }
17858
+ const eventType = typeof chunk.eventType === "string" ? chunk.eventType : typeof chunk.event_type === "string" ? chunk.event_type : typeof chunk.type === "string" ? chunk.type : void 0;
17859
+ if (eventType === "text-generation" && typeof chunk.text === "string") {
17860
+ textDeltas.push(chunk.text);
17861
+ continue;
17862
+ }
17863
+ if (eventType === "tool-calls-generation") {
17864
+ const generatedToolCalls = toToolCallArray(
17865
+ Array.isArray(chunk.toolCalls) ? chunk.toolCalls : chunk.tool_calls
17866
+ );
17867
+ for (const [index, toolCall] of generatedToolCalls.entries()) {
17868
+ const normalizedIndex = getToolCallIndex2(toolCall, index);
17869
+ if (!toolCallOrder.includes(normalizedIndex)) {
17870
+ toolCallOrder.push(normalizedIndex);
17871
+ }
17872
+ toolCallsByIndex[normalizedIndex] = {
17873
+ ...toolCallsByIndex[normalizedIndex],
17874
+ ...toolCall
17875
+ };
17876
+ }
17877
+ if (typeof chunk.text === "string") {
17878
+ textDeltas.push(chunk.text);
17879
+ }
17880
+ continue;
17881
+ }
17882
+ if (eventType === "stream-end" && isObject(chunk.response)) {
17883
+ terminalResponse = chunk.response;
17884
+ metrics = {
17885
+ ...metrics,
17886
+ ...parseCohereMetricsFromUsage(chunk.response)
17887
+ };
17888
+ metadata = {
17889
+ ...metadata,
17890
+ ...extractCohereResponseMetadata(chunk.response) || {}
17891
+ };
17892
+ const responseFinishReason = typeof chunk.response.finishReason === "string" ? chunk.response.finishReason : typeof chunk.response.finish_reason === "string" ? chunk.response.finish_reason : void 0;
17893
+ finishReason = responseFinishReason ?? finishReason;
17894
+ continue;
17895
+ }
17896
+ if (eventType === "message-start") {
17897
+ if (typeof chunk.id === "string") {
17898
+ metadata.id = chunk.id;
17899
+ }
17900
+ if (isObject(chunk.delta) && isObject(chunk.delta.message)) {
17901
+ const messageRole = chunk.delta.message.role;
17902
+ if (typeof messageRole === "string") {
17903
+ role = messageRole;
17904
+ }
17905
+ }
17906
+ continue;
17907
+ }
17908
+ if (eventType === "content-delta") {
17909
+ const text = extractV8DeltaText(chunk);
17910
+ if (text) {
17911
+ textDeltas.push(text);
17912
+ }
17913
+ continue;
17914
+ }
17915
+ if (eventType === "tool-call-start") {
17916
+ const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
17917
+ Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
17918
+ ) : [];
17919
+ for (const [index, toolCall] of toolCalls.entries()) {
17920
+ const normalizedIndex = getToolCallIndex2(
17921
+ toolCall,
17922
+ typeof chunk.index === "number" ? chunk.index : index
17923
+ );
17924
+ if (!toolCallOrder.includes(normalizedIndex)) {
17925
+ toolCallOrder.push(normalizedIndex);
17926
+ }
17927
+ toolCallsByIndex[normalizedIndex] = {
17928
+ ...toolCallsByIndex[normalizedIndex],
17929
+ ...toolCall
17930
+ };
17931
+ }
17932
+ continue;
17933
+ }
17934
+ if (eventType === "tool-call-delta") {
17935
+ const toolCallDelta = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
17936
+ chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
17937
+ ) : [];
17938
+ if (toolCallDelta.length > 0) {
17939
+ const delta = toolCallDelta[0];
17940
+ const normalizedIndex = getToolCallIndex2(delta, chunk.index ?? 0);
17941
+ if (!toolCallOrder.includes(normalizedIndex)) {
17942
+ toolCallOrder.push(normalizedIndex);
17943
+ }
17944
+ toolCallsByIndex[normalizedIndex] = appendToolCallDelta(
17945
+ toolCallsByIndex[normalizedIndex],
17946
+ delta
17947
+ );
17948
+ }
17949
+ continue;
17950
+ }
17951
+ if (eventType === "message-end" && isObject(chunk.delta)) {
17952
+ const delta = chunk.delta;
17953
+ if (typeof delta.finishReason === "string") {
17954
+ finishReason = delta.finishReason;
17955
+ } else if (typeof delta.finish_reason === "string") {
17956
+ finishReason = delta.finish_reason;
17957
+ }
17958
+ if (delta.error !== void 0) {
17959
+ metadata.error = delta.error;
17960
+ }
17961
+ metrics = {
17962
+ ...metrics,
17963
+ ...parseCohereMetricsFromUsage(delta.usage)
17964
+ };
17965
+ }
17966
+ }
17967
+ const mergedToolCalls = toolCallOrder.sort((left, right) => left - right).map((index) => toolCallsByIndex[index]).filter((toolCall) => isObject(toolCall));
17968
+ let output = extractCohereChatOutput(terminalResponse);
17969
+ if (output === void 0) {
17970
+ const mergedText = textDeltas.join("");
17971
+ if (mergedToolCalls.length > 0 || role || mergedText.length > 0) {
17972
+ output = {
17973
+ ...role ? { role } : {},
17974
+ ...mergedText.length > 0 ? { content: mergedText } : {},
17975
+ ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
17976
+ };
17977
+ }
17978
+ }
17979
+ if (finishReason) {
17980
+ metadata = {
17981
+ ...metadata,
17982
+ finish_reason: finishReason
17983
+ };
17984
+ }
17985
+ return {
17986
+ metadata,
17987
+ metrics,
17988
+ output
17989
+ };
17990
+ }
17991
+
17992
+ // src/instrumentation/braintrust-plugin.ts
17993
+ var BraintrustPlugin = class extends BasePlugin {
17994
+ config;
17995
+ openaiPlugin = null;
17996
+ anthropicPlugin = null;
17997
+ aiSDKPlugin = null;
17998
+ claudeAgentSDKPlugin = null;
17999
+ googleGenAIPlugin = null;
18000
+ huggingFacePlugin = null;
18001
+ openRouterPlugin = null;
18002
+ openRouterAgentPlugin = null;
18003
+ mistralPlugin = null;
18004
+ googleADKPlugin = null;
18005
+ coherePlugin = null;
18006
+ constructor(config = {}) {
18007
+ super();
18008
+ this.config = config;
18009
+ }
18010
+ onEnable() {
18011
+ const integrations = this.config.integrations || {};
18012
+ if (integrations.openai !== false) {
18013
+ this.openaiPlugin = new OpenAIPlugin();
18014
+ this.openaiPlugin.enable();
18015
+ }
18016
+ if (integrations.anthropic !== false) {
18017
+ this.anthropicPlugin = new AnthropicPlugin();
18018
+ this.anthropicPlugin.enable();
18019
+ }
18020
+ if (integrations.aisdk !== false && integrations.vercel !== false) {
18021
+ this.aiSDKPlugin = new AISDKPlugin();
18022
+ this.aiSDKPlugin.enable();
18023
+ }
18024
+ if (integrations.claudeAgentSDK !== false) {
18025
+ this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
18026
+ this.claudeAgentSDKPlugin.enable();
18027
+ }
18028
+ if (integrations.googleGenAI !== false && integrations.google !== false) {
18029
+ this.googleGenAIPlugin = new GoogleGenAIPlugin();
18030
+ this.googleGenAIPlugin.enable();
18031
+ }
18032
+ if (integrations.huggingface !== false) {
18033
+ this.huggingFacePlugin = new HuggingFacePlugin();
18034
+ this.huggingFacePlugin.enable();
18035
+ }
18036
+ if (integrations.openrouter !== false) {
18037
+ this.openRouterPlugin = new OpenRouterPlugin();
18038
+ this.openRouterPlugin.enable();
18039
+ }
18040
+ if (integrations.openrouterAgent !== false) {
18041
+ this.openRouterAgentPlugin = new OpenRouterAgentPlugin();
18042
+ this.openRouterAgentPlugin.enable();
18043
+ }
18044
+ if (integrations.mistral !== false) {
18045
+ this.mistralPlugin = new MistralPlugin();
18046
+ this.mistralPlugin.enable();
18047
+ }
18048
+ if (integrations.googleADK !== false) {
18049
+ this.googleADKPlugin = new GoogleADKPlugin();
18050
+ this.googleADKPlugin.enable();
18051
+ }
18052
+ if (integrations.cohere !== false) {
18053
+ this.coherePlugin = new CoherePlugin();
18054
+ this.coherePlugin.enable();
18055
+ }
18056
+ }
18057
+ onDisable() {
18058
+ if (this.openaiPlugin) {
18059
+ this.openaiPlugin.disable();
18060
+ this.openaiPlugin = null;
18061
+ }
18062
+ if (this.anthropicPlugin) {
18063
+ this.anthropicPlugin.disable();
18064
+ this.anthropicPlugin = null;
18065
+ }
18066
+ if (this.aiSDKPlugin) {
18067
+ this.aiSDKPlugin.disable();
18068
+ this.aiSDKPlugin = null;
18069
+ }
18070
+ if (this.claudeAgentSDKPlugin) {
18071
+ this.claudeAgentSDKPlugin.disable();
18072
+ this.claudeAgentSDKPlugin = null;
18073
+ }
18074
+ if (this.googleGenAIPlugin) {
18075
+ this.googleGenAIPlugin.disable();
18076
+ this.googleGenAIPlugin = null;
18077
+ }
18078
+ if (this.huggingFacePlugin) {
18079
+ this.huggingFacePlugin.disable();
18080
+ this.huggingFacePlugin = null;
18081
+ }
18082
+ if (this.openRouterPlugin) {
18083
+ this.openRouterPlugin.disable();
18084
+ this.openRouterPlugin = null;
18085
+ }
18086
+ if (this.openRouterAgentPlugin) {
18087
+ this.openRouterAgentPlugin.disable();
18088
+ this.openRouterAgentPlugin = null;
18089
+ }
18090
+ if (this.mistralPlugin) {
18091
+ this.mistralPlugin.disable();
18092
+ this.mistralPlugin = null;
18093
+ }
18094
+ if (this.googleADKPlugin) {
18095
+ this.googleADKPlugin.disable();
18096
+ this.googleADKPlugin = null;
18097
+ }
18098
+ if (this.coherePlugin) {
18099
+ this.coherePlugin.disable();
18100
+ this.coherePlugin = null;
15229
18101
  }
15230
18102
  }
15231
18103
  };
@@ -15298,10 +18170,12 @@ var PluginRegistry = class {
15298
18170
  vercel: true,
15299
18171
  aisdk: true,
15300
18172
  google: true,
18173
+ huggingface: true,
15301
18174
  claudeAgentSDK: true,
15302
18175
  openrouter: true,
15303
18176
  openrouterAgent: true,
15304
- mistral: true
18177
+ mistral: true,
18178
+ cohere: true
15305
18179
  };
15306
18180
  }
15307
18181
  /**