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
@@ -140,6 +140,16 @@ var isomorph_default = iso;
140
140
  function isAsyncIterable(value) {
141
141
  return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
142
142
  }
143
+ function hasAsyncIteratorMethods(value) {
144
+ return value !== null && typeof value === "object" && "next" in value && typeof value.next === "function";
145
+ }
146
+ function isSelfAsyncIterator(value) {
147
+ try {
148
+ return value[Symbol.asyncIterator]() === value;
149
+ } catch {
150
+ return false;
151
+ }
152
+ }
143
153
  function patchStreamIfNeeded(stream, options) {
144
154
  if (!isAsyncIterable(stream)) {
145
155
  return stream;
@@ -150,6 +160,98 @@ function patchStreamIfNeeded(stream, options) {
150
160
  );
151
161
  return stream;
152
162
  }
163
+ if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
164
+ if ("__braintrust_patched_iterator_methods" in stream) {
165
+ return stream;
166
+ }
167
+ try {
168
+ const originalNext = stream.next.bind(stream);
169
+ const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
170
+ const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
171
+ const chunks = [];
172
+ let completed = false;
173
+ stream.next = async (...args) => {
174
+ try {
175
+ const result = await originalNext(...args);
176
+ if (result.done) {
177
+ if (!completed) {
178
+ completed = true;
179
+ try {
180
+ await options.onComplete(chunks);
181
+ } catch (error) {
182
+ console.error("Error in stream onComplete handler:", error);
183
+ }
184
+ }
185
+ } else {
186
+ const chunk = result.value;
187
+ const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
188
+ if (shouldCollect) {
189
+ chunks.push(chunk);
190
+ if (options.onChunk) {
191
+ try {
192
+ await options.onChunk(chunk);
193
+ } catch (error) {
194
+ console.error("Error in stream onChunk handler:", error);
195
+ }
196
+ }
197
+ }
198
+ }
199
+ return result;
200
+ } catch (error) {
201
+ if (!completed) {
202
+ completed = true;
203
+ if (options.onError) {
204
+ try {
205
+ await options.onError(
206
+ error instanceof Error ? error : new Error(String(error)),
207
+ chunks
208
+ );
209
+ } catch (handlerError) {
210
+ console.error("Error in stream onError handler:", handlerError);
211
+ }
212
+ }
213
+ }
214
+ throw error;
215
+ }
216
+ };
217
+ if (originalReturn) {
218
+ stream.return = async (...args) => {
219
+ if (!completed) {
220
+ completed = true;
221
+ try {
222
+ await options.onComplete(chunks);
223
+ } catch (error) {
224
+ console.error("Error in stream onComplete handler:", error);
225
+ }
226
+ }
227
+ return originalReturn(...args);
228
+ };
229
+ }
230
+ if (originalThrow) {
231
+ stream.throw = async (...args) => {
232
+ if (!completed) {
233
+ completed = true;
234
+ const rawError = args[0];
235
+ const error = rawError instanceof Error ? rawError : new Error(String(rawError));
236
+ if (options.onError) {
237
+ try {
238
+ await options.onError(error, chunks);
239
+ } catch (handlerError) {
240
+ console.error("Error in stream onError handler:", handlerError);
241
+ }
242
+ }
243
+ }
244
+ return originalThrow(...args);
245
+ };
246
+ }
247
+ Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
248
+ value: true
249
+ });
250
+ return stream;
251
+ } catch (error) {
252
+ console.warn("Failed to patch stream iterator methods:", error);
253
+ }
254
+ }
153
255
  const originalIteratorFn = stream[Symbol.asyncIterator];
154
256
  if ("__braintrust_patched" in originalIteratorFn && originalIteratorFn["__braintrust_patched"]) {
155
257
  return stream;
@@ -1059,6 +1161,9 @@ function isArray(value) {
1059
1161
  function isObjectOrArray(value) {
1060
1162
  return value instanceof Object;
1061
1163
  }
1164
+ function isPromiseLike(value) {
1165
+ return value != null && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
1166
+ }
1062
1167
 
1063
1168
  // util/object_util.ts
1064
1169
  var SET_UNION_FIELDS = /* @__PURE__ */ new Set(["tags"]);
@@ -2014,7 +2119,11 @@ var CodeBundle = import_v36.z.object({
2014
2119
  eval_name: import_v36.z.string(),
2015
2120
  position: import_v36.z.union([
2016
2121
  import_v36.z.object({ type: import_v36.z.literal("task") }),
2017
- import_v36.z.object({ type: import_v36.z.literal("scorer"), index: import_v36.z.number().int().gte(0) })
2122
+ import_v36.z.object({ type: import_v36.z.literal("scorer"), index: import_v36.z.number().int().gte(0) }),
2123
+ import_v36.z.object({
2124
+ type: import_v36.z.literal("classifier"),
2125
+ index: import_v36.z.number().int().gte(0)
2126
+ })
2018
2127
  ])
2019
2128
  }),
2020
2129
  import_v36.z.object({ type: import_v36.z.literal("function"), index: import_v36.z.number().int().gte(0) }),
@@ -3136,11 +3245,15 @@ var RunEval = import_v36.z.object({
3136
3245
  data: import_v36.z.union([
3137
3246
  import_v36.z.object({
3138
3247
  dataset_id: import_v36.z.string(),
3248
+ dataset_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3249
+ dataset_environment: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3139
3250
  _internal_btql: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional()
3140
3251
  }),
3141
3252
  import_v36.z.object({
3142
3253
  project_name: import_v36.z.string(),
3143
3254
  dataset_name: import_v36.z.string(),
3255
+ dataset_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3256
+ dataset_environment: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3144
3257
  _internal_btql: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional()
3145
3258
  }),
3146
3259
  import_v36.z.object({ data: import_v36.z.array(import_v36.z.unknown()) })
@@ -3268,6 +3381,7 @@ var ViewOptions = import_v36.z.union([
3268
3381
  rowHeight: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3269
3382
  tallGroupRows: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]),
3270
3383
  layout: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3384
+ topicMapReportKey: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3271
3385
  chartHeight: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]),
3272
3386
  excludedMeasures: import_v36.z.union([
3273
3387
  import_v36.z.array(
@@ -3310,6 +3424,7 @@ var ViewOptions = import_v36.z.union([
3310
3424
  import_v36.z.null()
3311
3425
  ]),
3312
3426
  queryShape: import_v36.z.union([import_v36.z.enum(["traces", "spans"]), import_v36.z.null()]),
3427
+ cluster: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3313
3428
  freezeColumns: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()])
3314
3429
  }).partial(),
3315
3430
  import_v36.z.null()
@@ -6577,8 +6692,9 @@ function validateAndSanitizeExperimentLogPartialArgs(event) {
6577
6692
  }
6578
6693
  function deepCopyEvent(event) {
6579
6694
  const attachments = [];
6580
- const IDENTIFIER = "_bt_internal_saved_attachment";
6581
- const savedAttachmentSchema = import_v38.z.strictObject({ [IDENTIFIER]: import_v38.z.number() });
6695
+ const ATTACHMENT_INDEX_KEY = "_bt_internal_saved_attachment_idx";
6696
+ const ATTACHMENT_MARKER_KEY = "_bt_internal_saved_attachment_marker";
6697
+ const attachmentMarker = ++deepCopyEventMarkerCounter;
6582
6698
  const serialized = JSON.stringify(event, (_k, v) => {
6583
6699
  if (v instanceof SpanImpl || v instanceof NoopSpan) {
6584
6700
  return `<span>`;
@@ -6590,21 +6706,39 @@ function deepCopyEvent(event) {
6590
6706
  return `<logger>`;
6591
6707
  } else if (v instanceof BaseAttachment) {
6592
6708
  const idx = attachments.push(v);
6593
- return { [IDENTIFIER]: idx - 1 };
6709
+ return {
6710
+ [ATTACHMENT_INDEX_KEY]: idx - 1,
6711
+ [ATTACHMENT_MARKER_KEY]: attachmentMarker
6712
+ };
6594
6713
  } else if (v instanceof ReadonlyAttachment) {
6595
6714
  return v.reference;
6596
6715
  }
6597
6716
  return v;
6598
6717
  });
6599
6718
  const x = JSON.parse(serialized, (_k, v) => {
6600
- const parsedAttachment = savedAttachmentSchema.safeParse(v);
6601
- if (parsedAttachment.success) {
6602
- return attachments[parsedAttachment.data[IDENTIFIER]];
6719
+ if (isDeepCopyAttachmentPlaceholder(v, attachmentMarker)) {
6720
+ return attachments[v[ATTACHMENT_INDEX_KEY]];
6603
6721
  }
6604
6722
  return v;
6605
6723
  });
6606
6724
  return x;
6607
6725
  }
6726
+ var deepCopyEventMarkerCounter = 0;
6727
+ function isDeepCopyAttachmentPlaceholder(value, attachmentMarker) {
6728
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
6729
+ return false;
6730
+ }
6731
+ const record = value;
6732
+ if (!Object.hasOwn(record, "_bt_internal_saved_attachment_idx") || !Object.hasOwn(record, "_bt_internal_saved_attachment_marker")) {
6733
+ return false;
6734
+ }
6735
+ if (Object.keys(record).length !== 2) {
6736
+ return false;
6737
+ }
6738
+ const attachmentIndex = record._bt_internal_saved_attachment_idx;
6739
+ const marker = record._bt_internal_saved_attachment_marker;
6740
+ return Number.isInteger(attachmentIndex) && attachmentIndex >= 0 && marker === attachmentMarker;
6741
+ }
6608
6742
  function extractAttachments(event, attachments) {
6609
6743
  for (const [key, value] of Object.entries(event)) {
6610
6744
  if (!value) {
@@ -9183,10 +9317,42 @@ function processImagesInOutput(output) {
9183
9317
  }
9184
9318
  return output;
9185
9319
  }
9320
+ function mergeLogprobTokens(existing, incoming) {
9321
+ if (incoming === void 0) {
9322
+ return existing;
9323
+ }
9324
+ if (incoming === null) {
9325
+ return existing ?? null;
9326
+ }
9327
+ if (Array.isArray(existing)) {
9328
+ return [...existing, ...incoming];
9329
+ }
9330
+ return [...incoming];
9331
+ }
9332
+ function aggregateChatLogprobs(existing, incoming) {
9333
+ if (incoming === void 0) {
9334
+ return existing;
9335
+ }
9336
+ if (incoming === null) {
9337
+ return existing ?? null;
9338
+ }
9339
+ const aggregated = existing && existing !== null ? { ...existing, ...incoming } : { ...incoming };
9340
+ const content = mergeLogprobTokens(existing?.content, incoming.content);
9341
+ if (content !== void 0) {
9342
+ aggregated.content = content;
9343
+ }
9344
+ const refusal = mergeLogprobTokens(existing?.refusal, incoming.refusal);
9345
+ if (refusal !== void 0) {
9346
+ aggregated.refusal = refusal;
9347
+ }
9348
+ return aggregated;
9349
+ }
9186
9350
  function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
9187
9351
  let role = void 0;
9188
9352
  let content = void 0;
9353
+ let refusal = void 0;
9189
9354
  let tool_calls = void 0;
9355
+ let logprobs = void 0;
9190
9356
  let finish_reason = void 0;
9191
9357
  let metrics = {};
9192
9358
  for (const chunk of chunks) {
@@ -9196,19 +9362,30 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
9196
9362
  ...parseMetricsFromUsage(chunk.usage)
9197
9363
  };
9198
9364
  }
9199
- const delta = chunk.choices?.[0]?.delta;
9200
- if (!delta) {
9365
+ const choice = chunk.choices?.[0];
9366
+ if (!choice) {
9201
9367
  continue;
9202
9368
  }
9203
- if (!role && delta.role) {
9204
- role = delta.role;
9369
+ if (choice.finish_reason) {
9370
+ finish_reason = choice.finish_reason;
9371
+ }
9372
+ logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
9373
+ const delta = choice.delta;
9374
+ if (!delta) {
9375
+ continue;
9205
9376
  }
9206
9377
  if (delta.finish_reason) {
9207
9378
  finish_reason = delta.finish_reason;
9208
9379
  }
9380
+ if (!role && delta.role) {
9381
+ role = delta.role;
9382
+ }
9209
9383
  if (delta.content) {
9210
9384
  content = (content || "") + delta.content;
9211
9385
  }
9386
+ if (delta.refusal) {
9387
+ refusal = (refusal || "") + delta.refusal;
9388
+ }
9212
9389
  if (delta.tool_calls) {
9213
9390
  const toolDelta = delta.tool_calls[0];
9214
9391
  if (!tool_calls || toolDelta.id && tool_calls[tool_calls.length - 1].id !== toolDelta.id) {
@@ -9234,9 +9411,10 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
9234
9411
  message: {
9235
9412
  role,
9236
9413
  content,
9414
+ ...refusal !== void 0 ? { refusal } : {},
9237
9415
  tool_calls
9238
9416
  },
9239
- logprobs: null,
9417
+ logprobs: logprobs ?? null,
9240
9418
  finish_reason
9241
9419
  }
9242
9420
  ]
@@ -9299,13 +9477,21 @@ var anthropicChannels = defineChannels("@anthropic-ai/sdk", {
9299
9477
  betaMessagesCreate: channel({
9300
9478
  channelName: "beta.messages.create",
9301
9479
  kind: "async"
9480
+ }),
9481
+ betaMessagesToolRunner: channel({
9482
+ channelName: "beta.messages.toolRunner",
9483
+ kind: "sync-stream"
9302
9484
  })
9303
9485
  });
9304
9486
 
9305
9487
  // src/instrumentation/plugins/anthropic-plugin.ts
9488
+ var ANTHROPIC_TOOL_RUNNER_TOOL_WRAPPED = Symbol.for(
9489
+ "braintrust.anthropic_tool_runner_tool_wrapped"
9490
+ );
9306
9491
  var AnthropicPlugin = class extends BasePlugin {
9307
9492
  onEnable() {
9308
9493
  this.subscribeToAnthropicChannels();
9494
+ this.subscribeToAnthropicToolRunner();
9309
9495
  }
9310
9496
  onDisable() {
9311
9497
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -9360,6 +9546,61 @@ var AnthropicPlugin = class extends BasePlugin {
9360
9546
  })
9361
9547
  );
9362
9548
  }
9549
+ subscribeToAnthropicToolRunner() {
9550
+ const tracingChannel = anthropicChannels.betaMessagesToolRunner.tracingChannel();
9551
+ const states = /* @__PURE__ */ new WeakMap();
9552
+ const handlers = {
9553
+ start: (event) => {
9554
+ const params = event.arguments[0] ?? {};
9555
+ const span = startSpan({
9556
+ name: "anthropic.beta.messages.toolRunner",
9557
+ spanAttributes: {
9558
+ type: "task" /* TASK */
9559
+ }
9560
+ });
9561
+ span.log({
9562
+ input: processAttachmentsInInput(
9563
+ coalesceInput(params.messages ?? [], params.system)
9564
+ ),
9565
+ metadata: {
9566
+ ...extractAnthropicToolRunnerMetadata(params),
9567
+ provider: "anthropic"
9568
+ }
9569
+ });
9570
+ const state = {
9571
+ aggregatedMetrics: {},
9572
+ finalized: false,
9573
+ iterationCount: 0,
9574
+ seenMessages: /* @__PURE__ */ new WeakSet(),
9575
+ span,
9576
+ startTime: getCurrentUnixTimestamp()
9577
+ };
9578
+ states.set(event, state);
9579
+ },
9580
+ end: (event) => {
9581
+ const state = states.get(event);
9582
+ if (!state) {
9583
+ return;
9584
+ }
9585
+ patchAnthropicToolRunner({
9586
+ runner: event.result,
9587
+ state
9588
+ });
9589
+ },
9590
+ error: (event) => {
9591
+ const state = states.get(event);
9592
+ if (!state || !event.error) {
9593
+ return;
9594
+ }
9595
+ finalizeAnthropicToolRunnerError(state, event.error);
9596
+ states.delete(event);
9597
+ }
9598
+ };
9599
+ tracingChannel.subscribe(handlers);
9600
+ this.unsubscribers.push(() => {
9601
+ tracingChannel.unsubscribe(handlers);
9602
+ });
9603
+ }
9363
9604
  };
9364
9605
  function parseMetricsFromUsage2(usage) {
9365
9606
  if (!usage) {
@@ -9376,72 +9617,411 @@ function parseMetricsFromUsage2(usage) {
9376
9617
  saveIfExistsTo("output_tokens", "completion_tokens");
9377
9618
  saveIfExistsTo("cache_read_input_tokens", "prompt_cached_tokens");
9378
9619
  saveIfExistsTo("cache_creation_input_tokens", "prompt_cache_creation_tokens");
9620
+ if (isObject(usage.server_tool_use)) {
9621
+ for (const [name, value] of Object.entries(usage.server_tool_use)) {
9622
+ if (typeof value === "number") {
9623
+ metrics[`server_tool_use_${name}`] = value;
9624
+ }
9625
+ }
9626
+ }
9379
9627
  return metrics;
9380
9628
  }
9381
- function aggregateAnthropicStreamChunks(chunks) {
9382
- const fallbackTextDeltas = [];
9383
- const contentBlocks = {};
9384
- const contentBlockDeltas = {};
9385
- let metrics = {};
9386
- let metadata = {};
9387
- let role;
9388
- for (const event of chunks) {
9389
- switch (event?.type) {
9390
- case "message_start":
9391
- if (event.message?.usage) {
9392
- const initialMetrics = parseMetricsFromUsage2(event.message.usage);
9393
- metrics = { ...metrics, ...initialMetrics };
9394
- }
9395
- if (typeof event.message?.role === "string") {
9396
- role = event.message.role;
9397
- }
9398
- break;
9399
- case "content_block_start":
9400
- if (event.content_block) {
9401
- contentBlocks[event.index] = event.content_block;
9402
- contentBlockDeltas[event.index] = { textDeltas: [], citations: [] };
9403
- }
9404
- break;
9405
- case "content_block_delta": {
9406
- const acc = contentBlockDeltas[event.index];
9407
- const delta = event.delta;
9408
- if (!delta) break;
9409
- if (delta.type === "text_delta" && "text" in delta) {
9410
- const text = delta.text;
9411
- if (text) {
9412
- if (acc !== void 0) {
9413
- acc.textDeltas.push(text);
9414
- } else {
9415
- fallbackTextDeltas.push(text);
9629
+ function extractAnthropicToolRunnerMetadata(params) {
9630
+ const metadata = filterFrom(params, ["messages", "system", "tools"]);
9631
+ const toolNames = extractAnthropicToolNames(params.tools);
9632
+ return {
9633
+ ...metadata,
9634
+ operation: "toolRunner",
9635
+ ...toolNames.length > 0 ? { tool_names: toolNames } : {}
9636
+ };
9637
+ }
9638
+ function extractAnthropicToolNames(tools) {
9639
+ const toolNames = [];
9640
+ for (const tool of tools) {
9641
+ if (!tool || typeof tool !== "object") {
9642
+ continue;
9643
+ }
9644
+ const toolRecord = tool;
9645
+ if (typeof toolRecord.name === "string") {
9646
+ toolNames.push(toolRecord.name);
9647
+ continue;
9648
+ }
9649
+ if (typeof toolRecord.mcp_server_name === "string") {
9650
+ toolNames.push(toolRecord.mcp_server_name);
9651
+ }
9652
+ }
9653
+ return toolNames;
9654
+ }
9655
+ function toErrorMessage(error) {
9656
+ return error instanceof Error ? error.message : String(error);
9657
+ }
9658
+ function getAnthropicToolRunnerInput(args) {
9659
+ return args.length > 0 ? args[0] : void 0;
9660
+ }
9661
+ function wrapAnthropicToolRunnerTools(params, state) {
9662
+ if (!Array.isArray(params.tools)) {
9663
+ return;
9664
+ }
9665
+ params.tools = params.tools.map(
9666
+ (tool, index) => wrapAnthropicToolRunnerTool(tool, index, state)
9667
+ );
9668
+ }
9669
+ function wrapAnthropicToolRunnerTool(tool, index, state) {
9670
+ if (!tool || typeof tool !== "object" || typeof tool.run !== "function" || tool[ANTHROPIC_TOOL_RUNNER_TOOL_WRAPPED]) {
9671
+ return tool;
9672
+ }
9673
+ const toolName = typeof tool.name === "string" ? tool.name : `tool[${index}]`;
9674
+ const originalRun = tool.run;
9675
+ const runDescriptor = Object.getOwnPropertyDescriptor(tool, "run");
9676
+ const wrappedTool = Object.create(
9677
+ Object.getPrototypeOf(tool),
9678
+ Object.getOwnPropertyDescriptors(tool)
9679
+ );
9680
+ Object.defineProperty(wrappedTool, "run", {
9681
+ configurable: runDescriptor?.configurable ?? true,
9682
+ enumerable: runDescriptor?.enumerable ?? true,
9683
+ value: function braintrustAnthropicToolRunnerRun(...args) {
9684
+ return state.span.traced(
9685
+ (span) => {
9686
+ const finalizeSuccess = (result) => {
9687
+ span.log({ output: result });
9688
+ return result;
9689
+ };
9690
+ const finalizeError = (error) => {
9691
+ span.log({ error: toErrorMessage(error) });
9692
+ throw error;
9693
+ };
9694
+ try {
9695
+ const result = Reflect.apply(originalRun, this, args);
9696
+ if (isPromiseLike(result)) {
9697
+ return result.then(finalizeSuccess, finalizeError);
9416
9698
  }
9699
+ return finalizeSuccess(result);
9700
+ } catch (error) {
9701
+ return finalizeError(error);
9417
9702
  }
9418
- } else if (delta.type === "input_json_delta" && "partial_json" in delta) {
9419
- const partialJson = delta.partial_json;
9420
- if (partialJson && acc !== void 0) {
9421
- acc.textDeltas.push(partialJson);
9422
- }
9423
- } else if (delta.type === "thinking_delta" && "thinking" in delta) {
9424
- const thinking = delta.thinking;
9425
- if (thinking && acc !== void 0) {
9426
- acc.textDeltas.push(thinking);
9427
- }
9428
- } else if (delta.type === "citations_delta" && "citation" in delta) {
9429
- const citation = delta.citation;
9430
- if (citation && acc !== void 0) {
9431
- acc.citations.push(citation);
9703
+ },
9704
+ {
9705
+ event: {
9706
+ input: getAnthropicToolRunnerInput(args),
9707
+ metadata: {
9708
+ "gen_ai.tool.name": toolName,
9709
+ provider: "anthropic"
9710
+ }
9711
+ },
9712
+ name: `tool: ${toolName}`,
9713
+ spanAttributes: {
9714
+ type: "tool" /* TOOL */
9432
9715
  }
9433
9716
  }
9434
- break;
9435
- }
9436
- case "content_block_stop":
9437
- finalizeContentBlock(
9438
- event.index,
9439
- contentBlocks,
9440
- contentBlockDeltas,
9441
- fallbackTextDeltas
9442
- );
9443
- break;
9444
- case "message_delta":
9717
+ );
9718
+ },
9719
+ writable: runDescriptor?.writable ?? true
9720
+ });
9721
+ Object.defineProperty(wrappedTool, ANTHROPIC_TOOL_RUNNER_TOOL_WRAPPED, {
9722
+ configurable: false,
9723
+ enumerable: false,
9724
+ value: true,
9725
+ writable: false
9726
+ });
9727
+ return wrappedTool;
9728
+ }
9729
+ function getAnthropicToolRunnerParams(runnerRecord) {
9730
+ const params = Reflect.get(runnerRecord, "params");
9731
+ return params && typeof params === "object" ? params : void 0;
9732
+ }
9733
+ function ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state) {
9734
+ const params = getAnthropicToolRunnerParams(runnerRecord);
9735
+ if (params) {
9736
+ wrapAnthropicToolRunnerTools(params, state);
9737
+ }
9738
+ }
9739
+ function wrapAnthropicToolRunnerSetMessagesParams(runnerRecord, state) {
9740
+ const setMessagesParams = Reflect.get(runnerRecord, "setMessagesParams");
9741
+ if (typeof setMessagesParams !== "function") {
9742
+ return;
9743
+ }
9744
+ Reflect.set(
9745
+ runnerRecord,
9746
+ "setMessagesParams",
9747
+ function patchedSetMessagesParams(...args) {
9748
+ const result = Reflect.apply(setMessagesParams, this, args);
9749
+ const nextParams = getAnthropicToolRunnerParams(runnerRecord);
9750
+ if (nextParams) {
9751
+ wrapAnthropicToolRunnerTools(nextParams, state);
9752
+ }
9753
+ return result;
9754
+ }
9755
+ );
9756
+ }
9757
+ function isAnthropicMessage(value) {
9758
+ return !!value && typeof value === "object" && typeof value.role === "string" && Array.isArray(value.content);
9759
+ }
9760
+ function isAnthropicMessageStream(value) {
9761
+ return !!value && typeof value === "object" && isAsyncIterable(value) && "finalMessage" in value && typeof value.finalMessage === "function";
9762
+ }
9763
+ function recordAnthropicToolRunnerMessage(state, message) {
9764
+ if (typeof message !== "object" || message === null) {
9765
+ return;
9766
+ }
9767
+ if (state.seenMessages.has(message)) {
9768
+ state.lastMessage = message;
9769
+ return;
9770
+ }
9771
+ state.seenMessages.add(message);
9772
+ state.lastMessage = message;
9773
+ const parsedMetrics = parseMetricsFromUsage2(message.usage);
9774
+ for (const [key, value] of Object.entries(parsedMetrics)) {
9775
+ if (typeof value === "number") {
9776
+ state.aggregatedMetrics[key] = (state.aggregatedMetrics[key] ?? 0) + value;
9777
+ }
9778
+ }
9779
+ }
9780
+ function instrumentAnthropicMessageStream(stream, state) {
9781
+ if ("__braintrust_tool_runner_stream_patched" in stream) {
9782
+ return;
9783
+ }
9784
+ if (!Object.isFrozen(stream) && !Object.isSealed(stream)) {
9785
+ patchStreamIfNeeded(stream, {
9786
+ onChunk: () => {
9787
+ if (state.firstTokenTime === void 0) {
9788
+ state.firstTokenTime = getCurrentUnixTimestamp();
9789
+ }
9790
+ },
9791
+ onComplete: () => void 0
9792
+ });
9793
+ }
9794
+ if (typeof stream.finalMessage === "function") {
9795
+ const originalFinalMessage = stream.finalMessage.bind(stream);
9796
+ stream.finalMessage = async () => {
9797
+ const message = await originalFinalMessage();
9798
+ recordAnthropicToolRunnerMessage(state, message);
9799
+ return message;
9800
+ };
9801
+ }
9802
+ Object.defineProperty(stream, "__braintrust_tool_runner_stream_patched", {
9803
+ value: true
9804
+ });
9805
+ }
9806
+ async function finalizeAnthropicToolRunner(state, finalMessage) {
9807
+ if (state.finalized) {
9808
+ return;
9809
+ }
9810
+ state.finalized = true;
9811
+ const message = finalMessage ?? state.lastMessage;
9812
+ if (message) {
9813
+ recordAnthropicToolRunnerMessage(state, message);
9814
+ }
9815
+ const metrics = finalizeAnthropicTokens({
9816
+ ...state.aggregatedMetrics
9817
+ });
9818
+ if (state.firstTokenTime !== void 0) {
9819
+ metrics.time_to_first_token = state.firstTokenTime - state.startTime;
9820
+ }
9821
+ const metadata = {
9822
+ anthropic_tool_runner_iterations: state.iterationCount
9823
+ };
9824
+ if (message?.stop_reason !== void 0) {
9825
+ metadata.stop_reason = message.stop_reason;
9826
+ }
9827
+ if (message?.stop_sequence !== void 0) {
9828
+ metadata.stop_sequence = message.stop_sequence;
9829
+ }
9830
+ state.span.log({
9831
+ ...message ? { output: { role: message.role, content: message.content } } : {},
9832
+ metadata,
9833
+ metrics: Object.fromEntries(
9834
+ Object.entries(metrics).filter(
9835
+ (entry) => entry[1] !== void 0
9836
+ )
9837
+ )
9838
+ });
9839
+ state.span.end();
9840
+ }
9841
+ function finalizeAnthropicToolRunnerError(state, error) {
9842
+ if (state.finalized) {
9843
+ return;
9844
+ }
9845
+ state.finalized = true;
9846
+ state.span.log({
9847
+ error: error instanceof Error ? error.message : String(error)
9848
+ });
9849
+ state.span.end();
9850
+ }
9851
+ async function resolveAnthropicToolRunnerFinalMessage(runner) {
9852
+ if (typeof runner.done === "function") {
9853
+ return await runner.done();
9854
+ }
9855
+ if (typeof runner.runUntilDone === "function") {
9856
+ return await runner.runUntilDone();
9857
+ }
9858
+ return void 0;
9859
+ }
9860
+ function wrapAnthropicToolRunnerPromiseMethod(runnerRecord, methodName, state) {
9861
+ const method = runnerRecord[methodName];
9862
+ if (typeof method !== "function") {
9863
+ return;
9864
+ }
9865
+ runnerRecord[methodName] = async (...args) => {
9866
+ ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state);
9867
+ return await withCurrent(state.span, async () => {
9868
+ try {
9869
+ const message = await method.apply(runnerRecord, args);
9870
+ recordAnthropicToolRunnerMessage(state, message);
9871
+ await finalizeAnthropicToolRunner(state, message);
9872
+ return message;
9873
+ } catch (error) {
9874
+ finalizeAnthropicToolRunnerError(state, error);
9875
+ throw error;
9876
+ }
9877
+ });
9878
+ };
9879
+ }
9880
+ function patchAnthropicToolRunner(args) {
9881
+ const { runner, state } = args;
9882
+ if (!runner || typeof runner !== "object") {
9883
+ void finalizeAnthropicToolRunner(state);
9884
+ return;
9885
+ }
9886
+ const runnerRecord = runner;
9887
+ if ("__braintrust_tool_runner_patched" in runnerRecord) {
9888
+ return;
9889
+ }
9890
+ ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state);
9891
+ wrapAnthropicToolRunnerSetMessagesParams(runnerRecord, state);
9892
+ wrapAnthropicToolRunnerPromiseMethod(runnerRecord, "done", state);
9893
+ wrapAnthropicToolRunnerPromiseMethod(runnerRecord, "runUntilDone", state);
9894
+ if (!isAsyncIterable(runnerRecord)) {
9895
+ Object.defineProperty(runnerRecord, "__braintrust_tool_runner_patched", {
9896
+ value: true
9897
+ });
9898
+ return;
9899
+ }
9900
+ const originalIterator = runnerRecord[Symbol.asyncIterator].bind(runnerRecord);
9901
+ runnerRecord[Symbol.asyncIterator] = function() {
9902
+ const iterator = originalIterator();
9903
+ return {
9904
+ async next(value) {
9905
+ try {
9906
+ ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state);
9907
+ const result = await withCurrent(
9908
+ state.span,
9909
+ () => value === void 0 ? iterator.next() : iterator.next(value)
9910
+ );
9911
+ if (result.done) {
9912
+ const finalMessage = await resolveAnthropicToolRunnerFinalMessage(runner);
9913
+ await finalizeAnthropicToolRunner(state, finalMessage);
9914
+ return result;
9915
+ }
9916
+ state.iterationCount += 1;
9917
+ if (isAnthropicMessage(result.value)) {
9918
+ if (state.firstTokenTime === void 0) {
9919
+ state.firstTokenTime = getCurrentUnixTimestamp();
9920
+ }
9921
+ recordAnthropicToolRunnerMessage(state, result.value);
9922
+ } else if (isAnthropicMessageStream(result.value)) {
9923
+ instrumentAnthropicMessageStream(result.value, state);
9924
+ }
9925
+ return result;
9926
+ } catch (error) {
9927
+ finalizeAnthropicToolRunnerError(state, error);
9928
+ throw error;
9929
+ }
9930
+ },
9931
+ async return(value) {
9932
+ try {
9933
+ ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state);
9934
+ const result = typeof iterator.return === "function" ? await withCurrent(state.span, () => iterator.return(value)) : { done: true, value };
9935
+ const finalMessage = await resolveAnthropicToolRunnerFinalMessage(
9936
+ runner
9937
+ ).catch(() => void 0);
9938
+ await finalizeAnthropicToolRunner(state, finalMessage);
9939
+ return result;
9940
+ } catch (error) {
9941
+ finalizeAnthropicToolRunnerError(state, error);
9942
+ throw error;
9943
+ }
9944
+ },
9945
+ async throw(error) {
9946
+ finalizeAnthropicToolRunnerError(state, error);
9947
+ if (typeof iterator.throw === "function") {
9948
+ return await withCurrent(state.span, () => iterator.throw(error));
9949
+ }
9950
+ throw error;
9951
+ },
9952
+ [Symbol.asyncIterator]() {
9953
+ return this;
9954
+ }
9955
+ };
9956
+ };
9957
+ Object.defineProperty(runnerRecord, "__braintrust_tool_runner_patched", {
9958
+ value: true
9959
+ });
9960
+ }
9961
+ function aggregateAnthropicStreamChunks(chunks) {
9962
+ const fallbackTextDeltas = [];
9963
+ const contentBlocks = {};
9964
+ const contentBlockDeltas = {};
9965
+ let metrics = {};
9966
+ let metadata = {};
9967
+ let role;
9968
+ for (const event of chunks) {
9969
+ switch (event?.type) {
9970
+ case "message_start":
9971
+ if (event.message?.usage) {
9972
+ const initialMetrics = parseMetricsFromUsage2(event.message.usage);
9973
+ metrics = { ...metrics, ...initialMetrics };
9974
+ }
9975
+ if (typeof event.message?.role === "string") {
9976
+ role = event.message.role;
9977
+ }
9978
+ break;
9979
+ case "content_block_start":
9980
+ if (event.content_block) {
9981
+ contentBlocks[event.index] = event.content_block;
9982
+ contentBlockDeltas[event.index] = { textDeltas: [], citations: [] };
9983
+ }
9984
+ break;
9985
+ case "content_block_delta": {
9986
+ const acc = contentBlockDeltas[event.index];
9987
+ const delta = event.delta;
9988
+ if (!delta) break;
9989
+ if (delta.type === "text_delta" && "text" in delta) {
9990
+ const text = delta.text;
9991
+ if (text) {
9992
+ if (acc !== void 0) {
9993
+ acc.textDeltas.push(text);
9994
+ } else {
9995
+ fallbackTextDeltas.push(text);
9996
+ }
9997
+ }
9998
+ } else if (delta.type === "input_json_delta" && "partial_json" in delta) {
9999
+ const partialJson = delta.partial_json;
10000
+ if (partialJson && acc !== void 0) {
10001
+ acc.textDeltas.push(partialJson);
10002
+ }
10003
+ } else if (delta.type === "thinking_delta" && "thinking" in delta) {
10004
+ const thinking = delta.thinking;
10005
+ if (thinking && acc !== void 0) {
10006
+ acc.textDeltas.push(thinking);
10007
+ }
10008
+ } else if (delta.type === "citations_delta" && "citation" in delta) {
10009
+ const citation = delta.citation;
10010
+ if (citation && acc !== void 0) {
10011
+ acc.citations.push(citation);
10012
+ }
10013
+ }
10014
+ break;
10015
+ }
10016
+ case "content_block_stop":
10017
+ finalizeContentBlock(
10018
+ event.index,
10019
+ contentBlocks,
10020
+ contentBlockDeltas,
10021
+ fallbackTextDeltas
10022
+ );
10023
+ break;
10024
+ case "message_delta":
9445
10025
  if (event.usage) {
9446
10026
  const finalMetrics = parseMetricsFromUsage2(event.usage);
9447
10027
  metrics = { ...metrics, ...finalMetrics };
@@ -9486,15 +10066,24 @@ function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallback
9486
10066
  }
9487
10067
  const acc = contentBlockDeltas[index];
9488
10068
  const text = acc?.textDeltas.join("") ?? "";
9489
- if (isToolUseContentBlock(contentBlock)) {
10069
+ if (isToolUseLikeContentBlock(contentBlock)) {
9490
10070
  if (!text) {
9491
10071
  return;
9492
10072
  }
9493
10073
  try {
9494
- contentBlocks[index] = {
9495
- ...contentBlock,
9496
- input: JSON.parse(text)
10074
+ const parsedInput = JSON.parse(text);
10075
+ if (!isObject(parsedInput)) {
10076
+ fallbackTextDeltas.push(text);
10077
+ delete contentBlocks[index];
10078
+ return;
10079
+ }
10080
+ const parsedToolUseBlock = {
10081
+ type: contentBlock.type,
10082
+ id: contentBlock.id,
10083
+ name: contentBlock.name,
10084
+ input: parsedInput
9497
10085
  };
10086
+ contentBlocks[index] = parsedToolUseBlock;
9498
10087
  } catch {
9499
10088
  fallbackTextDeltas.push(text);
9500
10089
  delete contentBlocks[index];
@@ -9528,8 +10117,8 @@ function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallback
9528
10117
  function isTextContentBlock(contentBlock) {
9529
10118
  return contentBlock.type === "text";
9530
10119
  }
9531
- function isToolUseContentBlock(contentBlock) {
9532
- return contentBlock.type === "tool_use";
10120
+ function isToolUseLikeContentBlock(contentBlock) {
10121
+ return (contentBlock.type === "tool_use" || contentBlock.type === "server_tool_use") && typeof contentBlock.id === "string" && typeof contentBlock.name === "string" && isObject(contentBlock.input);
9533
10122
  }
9534
10123
  function isThinkingContentBlock(contentBlock) {
9535
10124
  return contentBlock.type === "thinking";
@@ -9727,6 +10316,10 @@ var aiSDKChannels = defineChannels("ai", {
9727
10316
  channelName: "embedMany",
9728
10317
  kind: "async"
9729
10318
  }),
10319
+ rerank: channel({
10320
+ channelName: "rerank",
10321
+ kind: "async"
10322
+ }),
9730
10323
  agentGenerate: channel({
9731
10324
  channelName: "Agent.generate",
9732
10325
  kind: "async"
@@ -9786,7 +10379,7 @@ var AISDKPlugin = class extends BasePlugin {
9786
10379
  this.unsubscribers.push(
9787
10380
  traceStreamingChannel(aiSDKChannels.generateText, {
9788
10381
  name: "generateText",
9789
- type: "llm" /* LLM */,
10382
+ type: "function" /* FUNCTION */,
9790
10383
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9791
10384
  extractOutput: (result, endEvent) => {
9792
10385
  finalizeAISDKChildTracing(endEvent);
@@ -9802,7 +10395,7 @@ var AISDKPlugin = class extends BasePlugin {
9802
10395
  this.unsubscribers.push(
9803
10396
  traceStreamingChannel(aiSDKChannels.streamText, {
9804
10397
  name: "streamText",
9805
- type: "llm" /* LLM */,
10398
+ type: "function" /* FUNCTION */,
9806
10399
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9807
10400
  extractOutput: (result, endEvent) => processAISDKOutput(
9808
10401
  result,
@@ -9822,7 +10415,7 @@ var AISDKPlugin = class extends BasePlugin {
9822
10415
  this.unsubscribers.push(
9823
10416
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
9824
10417
  name: "streamText",
9825
- type: "llm" /* LLM */,
10418
+ type: "function" /* FUNCTION */,
9826
10419
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9827
10420
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
9828
10421
  defaultDenyOutputPaths: denyOutputPaths,
@@ -9836,7 +10429,7 @@ var AISDKPlugin = class extends BasePlugin {
9836
10429
  this.unsubscribers.push(
9837
10430
  traceStreamingChannel(aiSDKChannels.generateObject, {
9838
10431
  name: "generateObject",
9839
- type: "llm" /* LLM */,
10432
+ type: "function" /* FUNCTION */,
9840
10433
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9841
10434
  extractOutput: (result, endEvent) => {
9842
10435
  finalizeAISDKChildTracing(endEvent);
@@ -9852,7 +10445,7 @@ var AISDKPlugin = class extends BasePlugin {
9852
10445
  this.unsubscribers.push(
9853
10446
  traceStreamingChannel(aiSDKChannels.streamObject, {
9854
10447
  name: "streamObject",
9855
- type: "llm" /* LLM */,
10448
+ type: "function" /* FUNCTION */,
9856
10449
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9857
10450
  extractOutput: (result, endEvent) => processAISDKOutput(
9858
10451
  result,
@@ -9872,7 +10465,7 @@ var AISDKPlugin = class extends BasePlugin {
9872
10465
  this.unsubscribers.push(
9873
10466
  traceSyncStreamChannel(aiSDKChannels.streamObjectSync, {
9874
10467
  name: "streamObject",
9875
- type: "llm" /* LLM */,
10468
+ type: "function" /* FUNCTION */,
9876
10469
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9877
10470
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
9878
10471
  defaultDenyOutputPaths: denyOutputPaths,
@@ -9886,7 +10479,7 @@ var AISDKPlugin = class extends BasePlugin {
9886
10479
  this.unsubscribers.push(
9887
10480
  traceAsyncChannel(aiSDKChannels.embed, {
9888
10481
  name: "embed",
9889
- type: "llm" /* LLM */,
10482
+ type: "function" /* FUNCTION */,
9890
10483
  extractInput: ([params], event) => prepareAISDKEmbedInput(params, event.self),
9891
10484
  extractOutput: (result, endEvent) => processAISDKEmbeddingOutput(
9892
10485
  result,
@@ -9898,7 +10491,7 @@ var AISDKPlugin = class extends BasePlugin {
9898
10491
  this.unsubscribers.push(
9899
10492
  traceAsyncChannel(aiSDKChannels.embedMany, {
9900
10493
  name: "embedMany",
9901
- type: "llm" /* LLM */,
10494
+ type: "function" /* FUNCTION */,
9902
10495
  extractInput: ([params], event) => prepareAISDKEmbedInput(params, event.self),
9903
10496
  extractOutput: (result, endEvent) => processAISDKEmbeddingOutput(
9904
10497
  result,
@@ -9907,10 +10500,22 @@ var AISDKPlugin = class extends BasePlugin {
9907
10500
  extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent)
9908
10501
  })
9909
10502
  );
10503
+ this.unsubscribers.push(
10504
+ traceAsyncChannel(aiSDKChannels.rerank, {
10505
+ name: "rerank",
10506
+ type: "function" /* FUNCTION */,
10507
+ extractInput: ([params], event) => prepareAISDKRerankInput(params, event.self),
10508
+ extractOutput: (result, endEvent) => processAISDKRerankOutput(
10509
+ result,
10510
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
10511
+ ),
10512
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent)
10513
+ })
10514
+ );
9910
10515
  this.unsubscribers.push(
9911
10516
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
9912
10517
  name: "Agent.generate",
9913
- type: "llm" /* LLM */,
10518
+ type: "function" /* FUNCTION */,
9914
10519
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9915
10520
  extractOutput: (result, endEvent) => {
9916
10521
  finalizeAISDKChildTracing(endEvent);
@@ -9926,7 +10531,7 @@ var AISDKPlugin = class extends BasePlugin {
9926
10531
  this.unsubscribers.push(
9927
10532
  traceStreamingChannel(aiSDKChannels.agentStream, {
9928
10533
  name: "Agent.stream",
9929
- type: "llm" /* LLM */,
10534
+ type: "function" /* FUNCTION */,
9930
10535
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9931
10536
  extractOutput: (result, endEvent) => processAISDKOutput(
9932
10537
  result,
@@ -9946,7 +10551,7 @@ var AISDKPlugin = class extends BasePlugin {
9946
10551
  this.unsubscribers.push(
9947
10552
  traceSyncStreamChannel(aiSDKChannels.agentStreamSync, {
9948
10553
  name: "Agent.stream",
9949
- type: "llm" /* LLM */,
10554
+ type: "function" /* FUNCTION */,
9950
10555
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9951
10556
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
9952
10557
  defaultDenyOutputPaths: denyOutputPaths,
@@ -9960,7 +10565,7 @@ var AISDKPlugin = class extends BasePlugin {
9960
10565
  this.unsubscribers.push(
9961
10566
  traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
9962
10567
  name: "ToolLoopAgent.generate",
9963
- type: "llm" /* LLM */,
10568
+ type: "function" /* FUNCTION */,
9964
10569
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9965
10570
  extractOutput: (result, endEvent) => {
9966
10571
  finalizeAISDKChildTracing(endEvent);
@@ -9976,7 +10581,7 @@ var AISDKPlugin = class extends BasePlugin {
9976
10581
  this.unsubscribers.push(
9977
10582
  traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
9978
10583
  name: "ToolLoopAgent.stream",
9979
- type: "llm" /* LLM */,
10584
+ type: "function" /* FUNCTION */,
9980
10585
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
9981
10586
  extractOutput: (result, endEvent) => processAISDKOutput(
9982
10587
  result,
@@ -10326,6 +10931,16 @@ function prepareAISDKEmbedInput(params, self) {
10326
10931
  metadata: extractMetadataFromEmbedParams(params, self)
10327
10932
  };
10328
10933
  }
10934
+ function prepareAISDKRerankInput(params, self) {
10935
+ const { documents, query } = params;
10936
+ return {
10937
+ input: {
10938
+ documents,
10939
+ query
10940
+ },
10941
+ metadata: extractMetadataFromRerankParams(params, self)
10942
+ };
10943
+ }
10329
10944
  function extractTopLevelAISDKMetrics(result, event, startTime) {
10330
10945
  const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
10331
10946
  if (startTime) {
@@ -10371,6 +10986,16 @@ function extractMetadataFromCallParams(params, self) {
10371
10986
  function extractMetadataFromEmbedParams(params, self) {
10372
10987
  return extractBaseMetadata(params.model, self);
10373
10988
  }
10989
+ function extractMetadataFromRerankParams(params, self) {
10990
+ const metadata = extractBaseMetadata(params.model, self);
10991
+ if (typeof params.topN === "number") {
10992
+ metadata.topN = params.topN;
10993
+ }
10994
+ if (Array.isArray(params.documents)) {
10995
+ metadata.document_count = params.documents.length;
10996
+ }
10997
+ return metadata;
10998
+ }
10374
10999
  function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
10375
11000
  const cleanup = [];
10376
11001
  const patchedModels = /* @__PURE__ */ new WeakSet();
@@ -10918,6 +11543,22 @@ function processAISDKEmbeddingOutput(output, denyOutputPaths) {
10918
11543
  }
10919
11544
  return normalizeAISDKLoggedOutput(omit(summarized, denyOutputPaths));
10920
11545
  }
11546
+ function processAISDKRerankOutput(output, _denyOutputPaths) {
11547
+ if (!output || typeof output !== "object") {
11548
+ return output;
11549
+ }
11550
+ const ranking = safeSerializableFieldRead(output, "ranking");
11551
+ if (Array.isArray(ranking)) {
11552
+ return ranking.slice(0, 100).map((item) => {
11553
+ const entry = item && typeof item === "object" ? item : void 0;
11554
+ return {
11555
+ index: typeof entry?.originalIndex === "number" ? entry.originalIndex : void 0,
11556
+ relevance_score: typeof entry?.score === "number" ? entry.score : void 0
11557
+ };
11558
+ });
11559
+ }
11560
+ return void 0;
11561
+ }
10921
11562
  function extractTokenMetrics(result) {
10922
11563
  const metrics = {};
10923
11564
  let usage;
@@ -10960,12 +11601,80 @@ function extractTokenMetrics(result) {
10960
11601
  if (totalTokens !== void 0) {
10961
11602
  metrics.tokens = totalTokens;
10962
11603
  }
11604
+ const promptCachedTokens = firstNumber(
11605
+ usage.inputTokens?.cacheRead,
11606
+ usage.inputTokenDetails?.cacheReadTokens,
11607
+ usage.cachedInputTokens,
11608
+ usage.promptCachedTokens,
11609
+ usage.prompt_cached_tokens
11610
+ );
11611
+ if (promptCachedTokens !== void 0) {
11612
+ metrics.prompt_cached_tokens = promptCachedTokens;
11613
+ }
11614
+ const promptCacheCreationTokens = firstNumber(
11615
+ usage.inputTokens?.cacheWrite,
11616
+ usage.inputTokenDetails?.cacheWriteTokens,
11617
+ usage.promptCacheCreationTokens,
11618
+ usage.prompt_cache_creation_tokens,
11619
+ extractAnthropicCacheCreationTokens(result)
11620
+ );
11621
+ if (promptCacheCreationTokens !== void 0) {
11622
+ metrics.prompt_cache_creation_tokens = promptCacheCreationTokens;
11623
+ }
11624
+ const promptReasoningTokens = firstNumber(
11625
+ usage.promptReasoningTokens,
11626
+ usage.prompt_reasoning_tokens
11627
+ );
11628
+ if (promptReasoningTokens !== void 0) {
11629
+ metrics.prompt_reasoning_tokens = promptReasoningTokens;
11630
+ }
11631
+ const completionCachedTokens = firstNumber(
11632
+ usage.completionCachedTokens,
11633
+ usage.completion_cached_tokens
11634
+ );
11635
+ if (completionCachedTokens !== void 0) {
11636
+ metrics.completion_cached_tokens = completionCachedTokens;
11637
+ }
11638
+ const reasoningTokenCount = firstNumber(
11639
+ usage.outputTokens?.reasoning,
11640
+ usage.reasoningTokens,
11641
+ usage.completionReasoningTokens,
11642
+ usage.completion_reasoning_tokens,
11643
+ usage.reasoning_tokens,
11644
+ usage.thinkingTokens,
11645
+ usage.thinking_tokens
11646
+ );
11647
+ if (reasoningTokenCount !== void 0) {
11648
+ metrics.completion_reasoning_tokens = reasoningTokenCount;
11649
+ metrics.reasoning_tokens = reasoningTokenCount;
11650
+ }
11651
+ const completionAudioTokens = firstNumber(
11652
+ usage.completionAudioTokens,
11653
+ usage.completion_audio_tokens
11654
+ );
11655
+ if (completionAudioTokens !== void 0) {
11656
+ metrics.completion_audio_tokens = completionAudioTokens;
11657
+ }
10963
11658
  const cost = extractCostFromResult(result);
10964
11659
  if (cost !== void 0) {
10965
11660
  metrics.estimated_cost = cost;
10966
11661
  }
10967
11662
  return metrics;
10968
11663
  }
11664
+ function extractAnthropicCacheCreationTokens(result) {
11665
+ const providerMetadata = safeSerializableFieldRead(
11666
+ result,
11667
+ "providerMetadata"
11668
+ );
11669
+ const anthropicMetadata = providerMetadata?.anthropic;
11670
+ if (!anthropicMetadata) {
11671
+ return void 0;
11672
+ }
11673
+ return firstNumber(
11674
+ anthropicMetadata.cacheCreationInputTokens,
11675
+ anthropicMetadata.usage?.cache_creation_input_tokens
11676
+ );
11677
+ }
10969
11678
  function safeResultFieldRead(result, field) {
10970
11679
  return safeSerializableFieldRead(result, field);
10971
11680
  }
@@ -11082,14 +11791,11 @@ function extractSerializableOutputFields(output) {
11082
11791
  ...extractGetterValues(output)
11083
11792
  };
11084
11793
  }
11085
- function isPromiseLike(value) {
11086
- return value != null && typeof value === "object" && typeof value.then === "function";
11087
- }
11088
11794
  function isSerializableOutputValue(value) {
11089
11795
  if (typeof value === "function") {
11090
11796
  return false;
11091
11797
  }
11092
- if (value && typeof value === "object" && typeof value.then === "function") {
11798
+ if (isPromiseLike(value)) {
11093
11799
  return false;
11094
11800
  }
11095
11801
  if (value && typeof value === "object" && typeof value.getReader === "function") {
@@ -11409,12 +12115,9 @@ function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
11409
12115
  var LOCAL_TOOL_HANDLER_WRAPPED = Symbol.for(
11410
12116
  "braintrust.claude_agent_sdk.local_tool_handler_wrapped"
11411
12117
  );
11412
- function toErrorMessage(error) {
12118
+ function toErrorMessage2(error) {
11413
12119
  return error instanceof Error ? error.message : String(error);
11414
12120
  }
11415
- function isPromiseLike2(value) {
11416
- return value !== null && typeof value === "object" && "then" in value && typeof value.then === "function";
11417
- }
11418
12121
  function getToolUseIdFromExtra(extra) {
11419
12122
  if (!extra || typeof extra !== "object" || !("_meta" in extra)) {
11420
12123
  return void 0;
@@ -11461,14 +12164,14 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
11461
12164
  return result;
11462
12165
  };
11463
12166
  const finalizeError = (error) => {
11464
- span.log({ error: toErrorMessage(error) });
12167
+ span.log({ error: toErrorMessage2(error) });
11465
12168
  span.end();
11466
12169
  throw error;
11467
12170
  };
11468
12171
  return withCurrent(span, () => {
11469
12172
  try {
11470
12173
  const result = runHandler();
11471
- if (isPromiseLike2(result)) {
12174
+ if (isPromiseLike(result)) {
11472
12175
  return result.then(finalizeSuccess, finalizeError);
11473
12176
  }
11474
12177
  return finalizeSuccess(result);
@@ -11588,7 +12291,7 @@ var ROOT_LLM_PARENT_KEY = "__root__";
11588
12291
  function llmParentKey(parentToolUseId) {
11589
12292
  return parentToolUseId ?? ROOT_LLM_PARENT_KEY;
11590
12293
  }
11591
- function isSubAgentToolName(toolName) {
12294
+ function isSubAgentDelegationToolName(toolName) {
11592
12295
  return toolName === "Agent" || toolName === "Task";
11593
12296
  }
11594
12297
  function filterSerializableOptions(options) {
@@ -11622,24 +12325,92 @@ function getNumberProperty(obj, key) {
11622
12325
  const value = Reflect.get(obj, key);
11623
12326
  return typeof value === "number" ? value : void 0;
11624
12327
  }
11625
- function extractUsageFromMessage(message) {
11626
- const metrics = {};
11627
- let usage;
11628
- if (message.type === "assistant") {
11629
- usage = message.message?.usage;
11630
- } else if (message.type === "result") {
11631
- usage = message.usage;
12328
+ function getStringProperty(obj, key) {
12329
+ if (!obj || typeof obj !== "object" || !(key in obj)) {
12330
+ return void 0;
11632
12331
  }
11633
- if (!usage || typeof usage !== "object") {
11634
- return metrics;
12332
+ const value = Reflect.get(obj, key);
12333
+ return typeof value === "string" ? value : void 0;
12334
+ }
12335
+ function upsertSubAgentDetails(detailsByToolUseId, toolUseId, update) {
12336
+ const existing = detailsByToolUseId.get(toolUseId) ?? {};
12337
+ const merged = {
12338
+ ...existing,
12339
+ ...Object.fromEntries(
12340
+ Object.entries(update).filter(([, value]) => value !== void 0)
12341
+ )
12342
+ };
12343
+ detailsByToolUseId.set(toolUseId, merged);
12344
+ return merged;
12345
+ }
12346
+ function formatSubAgentSpanName(details) {
12347
+ if (details?.description) {
12348
+ return `Agent: ${details.description}`;
11635
12349
  }
11636
- const inputTokens = getNumberProperty(usage, "input_tokens");
11637
- if (inputTokens !== void 0) {
11638
- metrics.prompt_tokens = inputTokens;
12350
+ if (details?.agentType) {
12351
+ return `Agent: ${details.agentType}`;
11639
12352
  }
11640
- const outputTokens = getNumberProperty(usage, "output_tokens");
11641
- if (outputTokens !== void 0) {
11642
- metrics.completion_tokens = outputTokens;
12353
+ return "Agent: sub-agent";
12354
+ }
12355
+ function subAgentDetailsToMetadata(details) {
12356
+ if (!details) {
12357
+ return {};
12358
+ }
12359
+ const metadata = {};
12360
+ if (details.agentId) {
12361
+ metadata["claude_agent_sdk.agent_id"] = details.agentId;
12362
+ }
12363
+ if (details.agentType) {
12364
+ metadata["claude_agent_sdk.agent_type"] = details.agentType;
12365
+ }
12366
+ if (details.description) {
12367
+ metadata["claude_agent_sdk.description"] = details.description;
12368
+ }
12369
+ if (details.taskId) {
12370
+ metadata["claude_agent_sdk.task_id"] = details.taskId;
12371
+ }
12372
+ if (details.taskType) {
12373
+ metadata["claude_agent_sdk.task_type"] = details.taskType;
12374
+ }
12375
+ if (details.toolUseId) {
12376
+ metadata["claude_agent_sdk.tool_use_id"] = details.toolUseId;
12377
+ }
12378
+ if (details.workflowName) {
12379
+ metadata["claude_agent_sdk.workflow_name"] = details.workflowName;
12380
+ }
12381
+ return metadata;
12382
+ }
12383
+ function resolveTaskToolUseId(taskIdToToolUseId, message) {
12384
+ const messageToolUseId = typeof message.tool_use_id === "string" ? message.tool_use_id : void 0;
12385
+ if (messageToolUseId && typeof message.task_id === "string") {
12386
+ taskIdToToolUseId.set(message.task_id, messageToolUseId);
12387
+ }
12388
+ if (messageToolUseId) {
12389
+ return messageToolUseId;
12390
+ }
12391
+ if (typeof message.task_id === "string") {
12392
+ return taskIdToToolUseId.get(message.task_id);
12393
+ }
12394
+ return void 0;
12395
+ }
12396
+ function extractUsageFromMessage(message) {
12397
+ const metrics = {};
12398
+ let usage;
12399
+ if (message.type === "assistant") {
12400
+ usage = message.message?.usage;
12401
+ } else if (message.type === "result") {
12402
+ usage = message.usage;
12403
+ }
12404
+ if (!usage || typeof usage !== "object") {
12405
+ return metrics;
12406
+ }
12407
+ const inputTokens = getNumberProperty(usage, "input_tokens");
12408
+ if (inputTokens !== void 0) {
12409
+ metrics.prompt_tokens = inputTokens;
12410
+ }
12411
+ const outputTokens = getNumberProperty(usage, "output_tokens");
12412
+ if (outputTokens !== void 0) {
12413
+ metrics.completion_tokens = outputTokens;
11643
12414
  }
11644
12415
  const cacheReadTokens = getNumberProperty(usage, "cache_read_input_tokens") || 0;
11645
12416
  const cacheCreationTokens = getNumberProperty(usage, "cache_creation_input_tokens") || 0;
@@ -11794,7 +12565,7 @@ function prepareLocalToolHandlersInMcpServers(mcpServers) {
11794
12565
  }
11795
12566
  return { hasLocalToolHandlers, localToolHookNames };
11796
12567
  }
11797
- function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentSpans, endedSubAgentSpans) {
12568
+ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
11798
12569
  const preToolUse = async (input, toolUseID) => {
11799
12570
  if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
11800
12571
  return {};
@@ -11802,9 +12573,6 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
11802
12573
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
11803
12574
  return {};
11804
12575
  }
11805
- if (isSubAgentToolName(input.tool_name)) {
11806
- return {};
11807
- }
11808
12576
  const parsed = parseToolName(input.tool_name);
11809
12577
  const toolSpan = startSpan({
11810
12578
  event: {
@@ -11834,10 +12602,18 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
11834
12602
  return {};
11835
12603
  }
11836
12604
  const subAgentSpan = subAgentSpans.get(toolUseID);
12605
+ const toolSpan = activeToolSpans.get(toolUseID);
11837
12606
  if (subAgentSpan) {
12607
+ if (endedSubAgentSpans.has(toolUseID)) {
12608
+ return {};
12609
+ }
11838
12610
  try {
11839
12611
  const response = input.tool_response;
11840
- const metadata = {};
12612
+ const metadata = {
12613
+ ...subAgentDetailsToMetadata(
12614
+ subAgentDetailsByToolUseId.get(toolUseID)
12615
+ )
12616
+ };
11841
12617
  if (response?.status) {
11842
12618
  metadata["claude_agent_sdk.status"] = response.status;
11843
12619
  }
@@ -11855,9 +12631,16 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
11855
12631
  subAgentSpan.end();
11856
12632
  endedSubAgentSpans.add(toolUseID);
11857
12633
  }
12634
+ if (toolSpan) {
12635
+ try {
12636
+ toolSpan.log({ output: input.tool_response });
12637
+ } finally {
12638
+ toolSpan.end();
12639
+ activeToolSpans.delete(toolUseID);
12640
+ }
12641
+ }
11858
12642
  return {};
11859
12643
  }
11860
- const toolSpan = activeToolSpans.get(toolUseID);
11861
12644
  if (!toolSpan) {
11862
12645
  return {};
11863
12646
  }
@@ -11877,16 +12660,43 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
11877
12660
  return {};
11878
12661
  }
11879
12662
  const subAgentSpan = subAgentSpans.get(toolUseID);
12663
+ const toolSpan = activeToolSpans.get(toolUseID);
11880
12664
  if (subAgentSpan) {
12665
+ if (endedSubAgentSpans.has(toolUseID)) {
12666
+ return {};
12667
+ }
11881
12668
  try {
11882
- subAgentSpan.log({ error: input.error });
12669
+ subAgentSpan.log({
12670
+ error: input.error,
12671
+ metadata: subAgentDetailsToMetadata(
12672
+ subAgentDetailsByToolUseId.get(toolUseID)
12673
+ )
12674
+ });
11883
12675
  } finally {
11884
12676
  subAgentSpan.end();
11885
12677
  endedSubAgentSpans.add(toolUseID);
11886
12678
  }
12679
+ if (toolSpan) {
12680
+ const parsed2 = parseToolName(input.tool_name);
12681
+ try {
12682
+ toolSpan.log({
12683
+ error: input.error,
12684
+ metadata: {
12685
+ "claude_agent_sdk.is_interrupt": input.is_interrupt,
12686
+ "claude_agent_sdk.session_id": input.session_id,
12687
+ "claude_agent_sdk.raw_tool_name": parsed2.rawToolName,
12688
+ "gen_ai.tool.call.id": toolUseID,
12689
+ "gen_ai.tool.name": parsed2.toolName,
12690
+ ...parsed2.mcpServer && { "mcp.server": parsed2.mcpServer }
12691
+ }
12692
+ });
12693
+ } finally {
12694
+ toolSpan.end();
12695
+ activeToolSpans.delete(toolUseID);
12696
+ }
12697
+ }
11887
12698
  return {};
11888
12699
  }
11889
- const toolSpan = activeToolSpans.get(toolUseID);
11890
12700
  if (!toolSpan) {
11891
12701
  return {};
11892
12702
  }
@@ -11908,15 +12718,84 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
11908
12718
  }
11909
12719
  return {};
11910
12720
  };
11911
- return { postToolUse, postToolUseFailure, preToolUse };
12721
+ const subagentStart = async (input, toolUseID) => {
12722
+ if (input.hook_event_name !== "SubagentStart" || !toolUseID) {
12723
+ return {};
12724
+ }
12725
+ const details = upsertSubAgentDetails(
12726
+ subAgentDetailsByToolUseId,
12727
+ toolUseID,
12728
+ {
12729
+ agentId: input.agent_id,
12730
+ agentType: input.agent_type,
12731
+ toolUseId: toolUseID
12732
+ }
12733
+ );
12734
+ const subAgentSpan = subAgentSpans.get(toolUseID);
12735
+ if (subAgentSpan && !endedSubAgentSpans.has(toolUseID)) {
12736
+ subAgentSpan.log({
12737
+ metadata: subAgentDetailsToMetadata(details)
12738
+ });
12739
+ }
12740
+ return {};
12741
+ };
12742
+ const subagentStop = async (input, toolUseID) => {
12743
+ if (input.hook_event_name !== "SubagentStop" || !toolUseID) {
12744
+ return {};
12745
+ }
12746
+ const details = upsertSubAgentDetails(
12747
+ subAgentDetailsByToolUseId,
12748
+ toolUseID,
12749
+ {
12750
+ agentId: input.agent_id,
12751
+ agentType: input.agent_type,
12752
+ toolUseId: toolUseID
12753
+ }
12754
+ );
12755
+ const subAgentSpan = subAgentSpans.get(toolUseID);
12756
+ if (!subAgentSpan || endedSubAgentSpans.has(toolUseID)) {
12757
+ return {};
12758
+ }
12759
+ const metadata = {
12760
+ ...subAgentDetailsToMetadata(details),
12761
+ ...input.agent_transcript_path && {
12762
+ "claude_agent_sdk.agent_transcript_path": input.agent_transcript_path
12763
+ },
12764
+ "claude_agent_sdk.stop_hook_active": input.stop_hook_active
12765
+ };
12766
+ try {
12767
+ subAgentSpan.log({
12768
+ metadata,
12769
+ output: input.last_assistant_message
12770
+ });
12771
+ } finally {
12772
+ subAgentSpan.end();
12773
+ endedSubAgentSpans.add(toolUseID);
12774
+ }
12775
+ return {};
12776
+ };
12777
+ return {
12778
+ postToolUse,
12779
+ postToolUseFailure,
12780
+ preToolUse,
12781
+ subagentStart,
12782
+ subagentStop
12783
+ };
11912
12784
  }
11913
- function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentSpans, endedSubAgentSpans) {
11914
- const { preToolUse, postToolUse, postToolUseFailure } = createToolTracingHooks(
12785
+ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
12786
+ const {
12787
+ preToolUse,
12788
+ postToolUse,
12789
+ postToolUseFailure,
12790
+ subagentStart,
12791
+ subagentStop
12792
+ } = createToolTracingHooks(
11915
12793
  resolveParentSpan,
11916
12794
  activeToolSpans,
11917
12795
  options.mcpServers,
11918
12796
  localToolHookNames,
11919
12797
  skipLocalToolHooks,
12798
+ subAgentDetailsByToolUseId,
11920
12799
  subAgentSpans,
11921
12800
  endedSubAgentSpans
11922
12801
  );
@@ -11938,6 +12817,18 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
11938
12817
  PreToolUse: [
11939
12818
  ...existingHooks.PreToolUse ?? [],
11940
12819
  { hooks: [preToolUse] }
12820
+ ],
12821
+ SubagentStart: [
12822
+ ...existingHooks.SubagentStart ?? [],
12823
+ {
12824
+ hooks: [subagentStart]
12825
+ }
12826
+ ],
12827
+ SubagentStop: [
12828
+ ...existingHooks.SubagentStop ?? [],
12829
+ {
12830
+ hooks: [subagentStop]
12831
+ }
11941
12832
  ]
11942
12833
  }
11943
12834
  };
@@ -11966,7 +12857,6 @@ async function finalizeCurrentMessageGroup(state) {
11966
12857
  parentSpan,
11967
12858
  existingLlmSpan
11968
12859
  );
11969
- state.activeLlmSpansByParentToolUse.delete(parentKey);
11970
12860
  if (llmSpanResult) {
11971
12861
  if (parentToolUseId) {
11972
12862
  state.latestLlmParentBySubAgentToolUse.set(
@@ -11980,6 +12870,7 @@ async function finalizeCurrentMessageGroup(state) {
11980
12870
  state.finalResults.push(llmSpanResult.finalMessage);
11981
12871
  }
11982
12872
  }
12873
+ state.activeLlmSpansByParentToolUse.delete(parentKey);
11983
12874
  const lastMessage = state.currentMessages[state.currentMessages.length - 1];
11984
12875
  if (lastMessage?.message?.usage) {
11985
12876
  state.accumulatedOutputTokens += getNumberProperty(lastMessage.message.usage, "output_tokens") || 0;
@@ -11996,8 +12887,12 @@ function maybeTrackToolUseContext(state, message) {
11996
12887
  continue;
11997
12888
  }
11998
12889
  state.toolUseToParent.set(block.id, parentToolUseId);
11999
- if (block.name === "Task" && typeof block.input === "object" && block.input !== null && "subagent_type" in block.input && typeof block.input.subagent_type === "string") {
12000
- state.pendingSubAgentNames.set(block.id, block.input.subagent_type);
12890
+ if (typeof block.name === "string" && isSubAgentDelegationToolName(block.name) && typeof block.input === "object" && block.input !== null) {
12891
+ upsertSubAgentDetails(state.subAgentDetailsByToolUseId, block.id, {
12892
+ agentType: getStringProperty(block.input, "subagent_type"),
12893
+ description: getStringProperty(block.input, "description"),
12894
+ toolUseId: block.id
12895
+ });
12001
12896
  }
12002
12897
  }
12003
12898
  }
@@ -12010,34 +12905,133 @@ async function maybeStartSubAgentSpan(state, message) {
12010
12905
  return;
12011
12906
  }
12012
12907
  await ensureSubAgentSpan(
12013
- state.pendingSubAgentNames,
12908
+ state.subAgentDetailsByToolUseId,
12014
12909
  state.span,
12910
+ state.activeToolSpans,
12015
12911
  state.subAgentSpans,
12016
12912
  parentToolUseId
12017
12913
  );
12018
12914
  }
12019
- async function ensureSubAgentSpan(pendingSubAgentNames, rootSpan, subAgentSpans, parentToolUseId) {
12915
+ async function ensureSubAgentSpan(subAgentDetailsByToolUseId, rootSpan, activeToolSpans, subAgentSpans, parentToolUseId) {
12020
12916
  const existingSpan = subAgentSpans.get(parentToolUseId);
12021
12917
  if (existingSpan) {
12022
12918
  return existingSpan;
12023
12919
  }
12024
- const agentName = pendingSubAgentNames.get(parentToolUseId);
12025
- const spanName = agentName ? `Agent: ${agentName}` : "Agent: sub-agent";
12920
+ const details = subAgentDetailsByToolUseId.get(parentToolUseId);
12921
+ const spanName = formatSubAgentSpanName(details);
12922
+ const parentToolSpan = activeToolSpans.get(parentToolUseId);
12923
+ const parentSpan = parentToolSpan ? await parentToolSpan.export() : await rootSpan.export();
12026
12924
  const subAgentSpan = startSpan({
12027
12925
  event: {
12028
- metadata: {
12029
- ...agentName && { "claude_agent_sdk.agent_type": agentName }
12030
- }
12926
+ metadata: subAgentDetailsToMetadata(details)
12031
12927
  },
12032
12928
  name: spanName,
12033
- parent: await rootSpan.export(),
12929
+ parent: parentSpan,
12034
12930
  spanAttributes: { type: "task" /* TASK */ }
12035
12931
  });
12036
12932
  subAgentSpans.set(parentToolUseId, subAgentSpan);
12037
12933
  return subAgentSpan;
12038
12934
  }
12935
+ async function maybeHandleTaskLifecycleMessage(state, message) {
12936
+ if (message.type !== "system") {
12937
+ return false;
12938
+ }
12939
+ if (message.subtype !== "task_started" && message.subtype !== "task_progress" && message.subtype !== "task_notification") {
12940
+ return false;
12941
+ }
12942
+ const toolUseId = resolveTaskToolUseId(state.taskIdToToolUseId, message);
12943
+ if (!toolUseId) {
12944
+ return true;
12945
+ }
12946
+ const details = upsertSubAgentDetails(
12947
+ state.subAgentDetailsByToolUseId,
12948
+ toolUseId,
12949
+ {
12950
+ description: getStringProperty(message, "description"),
12951
+ taskId: getStringProperty(message, "task_id"),
12952
+ taskType: getStringProperty(message, "task_type"),
12953
+ toolUseId,
12954
+ workflowName: getStringProperty(message, "workflow_name")
12955
+ }
12956
+ );
12957
+ const subAgentSpan = await ensureSubAgentSpan(
12958
+ state.subAgentDetailsByToolUseId,
12959
+ state.span,
12960
+ state.activeToolSpans,
12961
+ state.subAgentSpans,
12962
+ toolUseId
12963
+ );
12964
+ if (state.endedSubAgentSpans.has(toolUseId)) {
12965
+ return true;
12966
+ }
12967
+ const usage = message.usage;
12968
+ const usageTotalTokens = getNumberProperty(usage, "total_tokens");
12969
+ const usageToolUses = getNumberProperty(usage, "tool_uses");
12970
+ const usageDurationMs = getNumberProperty(usage, "duration_ms");
12971
+ const metadata = {
12972
+ ...subAgentDetailsToMetadata(details),
12973
+ "claude_agent_sdk.tool_use_id": toolUseId,
12974
+ ...usageTotalTokens !== void 0 && {
12975
+ "claude_agent_sdk.total_tokens": usageTotalTokens
12976
+ },
12977
+ ...usageToolUses !== void 0 && {
12978
+ "claude_agent_sdk.tool_use_count": usageToolUses
12979
+ },
12980
+ ...usageDurationMs !== void 0 && {
12981
+ "claude_agent_sdk.duration_ms": usageDurationMs
12982
+ }
12983
+ };
12984
+ if (message.subtype === "task_started") {
12985
+ const prompt = getStringProperty(message, "prompt");
12986
+ subAgentSpan.log({
12987
+ input: prompt,
12988
+ metadata
12989
+ });
12990
+ return true;
12991
+ }
12992
+ const summary = getStringProperty(message, "summary");
12993
+ if (summary) {
12994
+ metadata["claude_agent_sdk.summary"] = summary;
12995
+ }
12996
+ if (message.subtype === "task_progress") {
12997
+ const lastToolName = getStringProperty(message, "last_tool_name");
12998
+ if (lastToolName) {
12999
+ metadata["claude_agent_sdk.last_tool_name"] = lastToolName;
13000
+ }
13001
+ subAgentSpan.log({
13002
+ metadata,
13003
+ output: summary
13004
+ });
13005
+ return true;
13006
+ }
13007
+ const status = getStringProperty(message, "status");
13008
+ const outputFile = getStringProperty(message, "output_file");
13009
+ if (status) {
13010
+ metadata["claude_agent_sdk.task_status"] = status;
13011
+ }
13012
+ if (outputFile) {
13013
+ metadata["claude_agent_sdk.output_file"] = outputFile;
13014
+ }
13015
+ const output = summary || outputFile ? {
13016
+ ...summary && { summary },
13017
+ ...outputFile && { output_file: outputFile }
13018
+ } : void 0;
13019
+ try {
13020
+ subAgentSpan.log({
13021
+ metadata,
13022
+ output
13023
+ });
13024
+ } finally {
13025
+ subAgentSpan.end();
13026
+ state.endedSubAgentSpans.add(toolUseId);
13027
+ }
13028
+ return true;
13029
+ }
12039
13030
  async function handleStreamMessage(state, message) {
12040
13031
  maybeTrackToolUseContext(state, message);
13032
+ if (await maybeHandleTaskLifecycleMessage(state, message)) {
13033
+ return;
13034
+ }
12041
13035
  await maybeStartSubAgentSpan(state, message);
12042
13036
  const messageId = message.message?.id;
12043
13037
  if (messageId && messageId !== state.currentMessageId) {
@@ -12052,8 +13046,9 @@ async function handleStreamMessage(state, message) {
12052
13046
  let llmParentSpan = await state.span.export();
12053
13047
  if (parentToolUseId) {
12054
13048
  const subAgentSpan = await ensureSubAgentSpan(
12055
- state.pendingSubAgentNames,
13049
+ state.subAgentDetailsByToolUseId,
12056
13050
  state.span,
13051
+ state.activeToolSpans,
12057
13052
  state.subAgentSpans,
12058
13053
  parentToolUseId
12059
13054
  );
@@ -12133,6 +13128,10 @@ async function finalizeQuerySpan(state) {
12133
13128
  llmSpan.end();
12134
13129
  }
12135
13130
  state.activeLlmSpansByParentToolUse.clear();
13131
+ for (const toolSpan of state.activeToolSpans.values()) {
13132
+ toolSpan.end();
13133
+ }
13134
+ state.activeToolSpans.clear();
12136
13135
  for (const [id, subAgentSpan] of state.subAgentSpans) {
12137
13136
  if (!state.endedSubAgentSpans.has(id)) {
12138
13137
  subAgentSpan.end();
@@ -12206,7 +13205,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
12206
13205
  const latestRootLlmParentRef = {
12207
13206
  value: void 0
12208
13207
  };
12209
- const pendingSubAgentNames = /* @__PURE__ */ new Map();
13208
+ const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
13209
+ const taskIdToToolUseId = /* @__PURE__ */ new Map();
12210
13210
  const localToolContext = createClaudeLocalToolContext();
12211
13211
  const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
12212
13212
  const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
@@ -12223,8 +13223,9 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
12223
13223
  return parentLlm;
12224
13224
  }
12225
13225
  const subAgentSpan = await ensureSubAgentSpan(
12226
- pendingSubAgentNames,
13226
+ subAgentDetailsByToolUseId,
12227
13227
  span,
13228
+ activeToolSpans,
12228
13229
  subAgentSpans,
12229
13230
  parentToolUseId
12230
13231
  );
@@ -12243,6 +13244,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
12243
13244
  activeToolSpans,
12244
13245
  localToolHookNames,
12245
13246
  skipLocalToolHooks,
13247
+ subAgentDetailsByToolUseId,
12246
13248
  subAgentSpans,
12247
13249
  endedSubAgentSpans
12248
13250
  );
@@ -12260,12 +13262,13 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
12260
13262
  finalResults: [],
12261
13263
  options: optionsWithHooks,
12262
13264
  originalPrompt,
12263
- pendingSubAgentNames,
12264
13265
  processing: Promise.resolve(),
12265
13266
  promptDone,
12266
13267
  promptStarted: () => promptStarted,
12267
13268
  span,
13269
+ subAgentDetailsByToolUseId,
12268
13270
  subAgentSpans,
13271
+ taskIdToToolUseId,
12269
13272
  latestLlmParentBySubAgentToolUse,
12270
13273
  latestRootLlmParentRef,
12271
13274
  toolUseToParent,
@@ -12347,6 +13350,10 @@ var googleGenAIChannels = defineChannels("@google/genai", {
12347
13350
  generateContentStream: channel({
12348
13351
  channelName: "models.generateContentStream",
12349
13352
  kind: "async"
13353
+ }),
13354
+ embedContent: channel({
13355
+ channelName: "models.embedContent",
13356
+ kind: "async"
12350
13357
  })
12351
13358
  });
12352
13359
 
@@ -12373,6 +13380,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
12373
13380
  subscribeToGoogleGenAIChannels() {
12374
13381
  this.subscribeToGenerateContentChannel();
12375
13382
  this.subscribeToGenerateContentStreamChannel();
13383
+ this.subscribeToEmbedContentChannel();
12376
13384
  }
12377
13385
  subscribeToGenerateContentChannel() {
12378
13386
  const tracingChannel = googleGenAIChannels.generateContent.tracingChannel();
@@ -12382,8 +13390,8 @@ var GoogleGenAIPlugin = class extends BasePlugin {
12382
13390
  states,
12383
13391
  (event) => {
12384
13392
  const params = event.arguments[0];
12385
- const input = serializeInput(params);
12386
- const metadata = extractMetadata(params);
13393
+ const input = serializeGenerateContentInput(params);
13394
+ const metadata = extractGenerateContentMetadata(params);
12387
13395
  const span = startSpan({
12388
13396
  name: "generate_content",
12389
13397
  spanAttributes: {
@@ -12401,8 +13409,8 @@ var GoogleGenAIPlugin = class extends BasePlugin {
12401
13409
  start: (event) => {
12402
13410
  ensureSpanState(states, event, () => {
12403
13411
  const params = event.arguments[0];
12404
- const input = serializeInput(params);
12405
- const metadata = extractMetadata(params);
13412
+ const input = serializeGenerateContentInput(params);
13413
+ const metadata = extractGenerateContentMetadata(params);
12406
13414
  const span = startSpan({
12407
13415
  name: "generate_content",
12408
13416
  spanAttributes: {
@@ -12422,7 +13430,9 @@ var GoogleGenAIPlugin = class extends BasePlugin {
12422
13430
  return;
12423
13431
  }
12424
13432
  try {
13433
+ const responseMetadata = extractResponseMetadata(event.result);
12425
13434
  spanState.span.log({
13435
+ ...responseMetadata ? { metadata: responseMetadata } : {},
12426
13436
  metrics: cleanMetrics(
12427
13437
  extractGenerateContentMetrics(
12428
13438
  event.result,
@@ -12452,8 +13462,8 @@ var GoogleGenAIPlugin = class extends BasePlugin {
12452
13462
  start: (event) => {
12453
13463
  const streamEvent = event;
12454
13464
  const params = event.arguments[0];
12455
- streamEvent.googleGenAIInput = serializeInput(params);
12456
- streamEvent.googleGenAIMetadata = extractMetadata(params);
13465
+ streamEvent.googleGenAIInput = serializeGenerateContentInput(params);
13466
+ streamEvent.googleGenAIMetadata = extractGenerateContentMetadata(params);
12457
13467
  streamEvent.googleGenAIStartTime = getCurrentUnixTimestamp();
12458
13468
  },
12459
13469
  asyncEnd: (event) => {
@@ -12473,6 +13483,76 @@ var GoogleGenAIPlugin = class extends BasePlugin {
12473
13483
  tracingChannel.unsubscribe(handlers);
12474
13484
  });
12475
13485
  }
13486
+ subscribeToEmbedContentChannel() {
13487
+ const tracingChannel = googleGenAIChannels.embedContent.tracingChannel();
13488
+ const states = /* @__PURE__ */ new WeakMap();
13489
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
13490
+ tracingChannel,
13491
+ states,
13492
+ (event) => {
13493
+ const params = event.arguments[0];
13494
+ const input = serializeEmbedContentInput(params);
13495
+ const metadata = extractEmbedContentMetadata(params);
13496
+ const span = startSpan({
13497
+ name: "embed_content",
13498
+ spanAttributes: {
13499
+ type: "llm" /* LLM */
13500
+ },
13501
+ event: createWrapperParityEvent({ input, metadata })
13502
+ });
13503
+ return {
13504
+ span,
13505
+ startTime: getCurrentUnixTimestamp()
13506
+ };
13507
+ }
13508
+ );
13509
+ const handlers = {
13510
+ start: (event) => {
13511
+ ensureSpanState(states, event, () => {
13512
+ const params = event.arguments[0];
13513
+ const input = serializeEmbedContentInput(params);
13514
+ const metadata = extractEmbedContentMetadata(params);
13515
+ const span = startSpan({
13516
+ name: "embed_content",
13517
+ spanAttributes: {
13518
+ type: "llm" /* LLM */
13519
+ },
13520
+ event: createWrapperParityEvent({ input, metadata })
13521
+ });
13522
+ return {
13523
+ span,
13524
+ startTime: getCurrentUnixTimestamp()
13525
+ };
13526
+ });
13527
+ },
13528
+ asyncEnd: (event) => {
13529
+ const spanState = states.get(event);
13530
+ if (!spanState) {
13531
+ return;
13532
+ }
13533
+ try {
13534
+ const output = summarizeEmbedContentOutput(event.result);
13535
+ spanState.span.log({
13536
+ ...output ? { output } : {},
13537
+ metrics: cleanMetrics(
13538
+ extractEmbedContentMetrics(event.result, spanState.startTime)
13539
+ )
13540
+ });
13541
+ } finally {
13542
+ spanState.span.end();
13543
+ states.delete(event);
13544
+ }
13545
+ },
13546
+ error: (event) => {
13547
+ logErrorAndEndSpan(states, event);
13548
+ }
13549
+ };
13550
+ tracingChannel.subscribe(handlers);
13551
+ this.unsubscribers.push(() => {
13552
+ unbindCurrentSpanStore?.();
13553
+ tracingChannel.unsubscribe(handlers);
13554
+ });
13555
+ }
12476
13556
  };
12477
13557
  function ensureSpanState(states, event, create) {
12478
13558
  const existing = states.get(event);
@@ -12546,7 +13626,11 @@ function patchGoogleGenAIStreamingResult(args) {
12546
13626
  finalized = true;
12547
13627
  if (options.result) {
12548
13628
  const { end, ...metricsWithoutEnd } = options.result.metrics;
13629
+ const responseMetadata = extractResponseMetadata(
13630
+ options.result.aggregated
13631
+ );
12549
13632
  span.log({
13633
+ ...responseMetadata ? { metadata: responseMetadata } : {},
12550
13634
  metrics: cleanMetrics(metricsWithoutEnd),
12551
13635
  output: options.result.aggregated
12552
13636
  });
@@ -12649,26 +13733,35 @@ function patchGoogleGenAIStreamingResult(args) {
12649
13733
  patchIterator(result);
12650
13734
  return true;
12651
13735
  }
12652
- function serializeInput(params) {
13736
+ function serializeGenerateContentInput(params) {
12653
13737
  const input = {
12654
13738
  model: params.model,
12655
- contents: serializeContents(params.contents)
13739
+ contents: serializeContentCollection(params.contents)
12656
13740
  };
12657
- if (params.config) {
12658
- const config = tryToDict(params.config);
12659
- if (config) {
12660
- const filteredConfig = {};
12661
- Object.keys(config).forEach((key) => {
12662
- if (key !== "tools") {
12663
- filteredConfig[key] = config[key];
12664
- }
12665
- });
12666
- input.config = filteredConfig;
12667
- }
13741
+ const config = params.config ? tryToDict(params.config) : null;
13742
+ if (config) {
13743
+ const filteredConfig = {};
13744
+ Object.keys(config).forEach((key) => {
13745
+ if (key !== "tools") {
13746
+ filteredConfig[key] = config[key];
13747
+ }
13748
+ });
13749
+ input.config = filteredConfig;
13750
+ }
13751
+ return input;
13752
+ }
13753
+ function serializeEmbedContentInput(params) {
13754
+ const input = {
13755
+ model: params.model,
13756
+ contents: serializeContentCollection(params.contents)
13757
+ };
13758
+ const config = params.config ? tryToDict(params.config) : null;
13759
+ if (config) {
13760
+ input.config = config;
12668
13761
  }
12669
13762
  return input;
12670
13763
  }
12671
- function serializeContents(contents) {
13764
+ function serializeContentCollection(contents) {
12672
13765
  if (contents === null || contents === void 0) {
12673
13766
  return null;
12674
13767
  }
@@ -12720,22 +13813,26 @@ function serializePart(part) {
12720
13813
  }
12721
13814
  return part;
12722
13815
  }
12723
- function serializeTools(params) {
12724
- if (!params.config?.tools) {
13816
+ function serializeGenerateContentTools(params) {
13817
+ const config = params.config ? tryToDict(params.config) : null;
13818
+ const tools = config?.tools;
13819
+ if (!Array.isArray(tools)) {
12725
13820
  return null;
12726
13821
  }
12727
13822
  try {
12728
- return params.config.tools.map((tool) => {
12729
- if (typeof tool === "object" && tool.functionDeclarations) {
12730
- return tool;
13823
+ const serializedTools = [];
13824
+ for (const tool of tools) {
13825
+ const toolDict = tryToDict(tool);
13826
+ if (toolDict) {
13827
+ serializedTools.push(toolDict);
12731
13828
  }
12732
- return tool;
12733
- });
13829
+ }
13830
+ return serializedTools.length > 0 ? serializedTools : null;
12734
13831
  } catch {
12735
13832
  return null;
12736
13833
  }
12737
13834
  }
12738
- function extractMetadata(params) {
13835
+ function extractGenerateContentMetadata(params) {
12739
13836
  const metadata = {};
12740
13837
  if (params.model) {
12741
13838
  metadata.model = params.model;
@@ -12750,12 +13847,25 @@ function extractMetadata(params) {
12750
13847
  });
12751
13848
  }
12752
13849
  }
12753
- const tools = serializeTools(params);
13850
+ const tools = serializeGenerateContentTools(params);
12754
13851
  if (tools) {
12755
13852
  metadata.tools = tools;
12756
13853
  }
12757
13854
  return metadata;
12758
13855
  }
13856
+ function extractEmbedContentMetadata(params) {
13857
+ const metadata = {};
13858
+ if (params.model) {
13859
+ metadata.model = params.model;
13860
+ }
13861
+ const config = params.config ? tryToDict(params.config) : null;
13862
+ if (config) {
13863
+ Object.keys(config).forEach((key) => {
13864
+ metadata[key] = config[key];
13865
+ });
13866
+ }
13867
+ return metadata;
13868
+ }
12759
13869
  function extractGenerateContentMetrics(response, startTime) {
12760
13870
  const metrics = {};
12761
13871
  if (startTime !== void 0) {
@@ -12769,24 +13879,87 @@ function extractGenerateContentMetrics(response, startTime) {
12769
13879
  }
12770
13880
  return metrics;
12771
13881
  }
12772
- function populateUsageMetrics(metrics, usage) {
12773
- if (usage.promptTokenCount !== void 0) {
12774
- metrics.prompt_tokens = usage.promptTokenCount;
13882
+ function extractEmbedContentMetrics(response, startTime) {
13883
+ const metrics = {};
13884
+ if (startTime !== void 0) {
13885
+ const end = getCurrentUnixTimestamp();
13886
+ metrics.start = startTime;
13887
+ metrics.end = end;
13888
+ metrics.duration = end - startTime;
12775
13889
  }
12776
- if (usage.candidatesTokenCount !== void 0) {
12777
- metrics.completion_tokens = usage.candidatesTokenCount;
13890
+ if (response?.usageMetadata) {
13891
+ populateUsageMetrics(metrics, response.usageMetadata);
12778
13892
  }
12779
- if (usage.totalTokenCount !== void 0) {
12780
- metrics.tokens = usage.totalTokenCount;
13893
+ const embeddingTokenCount = extractEmbedPromptTokenCount(response);
13894
+ if (embeddingTokenCount !== void 0) {
13895
+ metrics.prompt_tokens = embeddingTokenCount;
13896
+ metrics.tokens = embeddingTokenCount;
12781
13897
  }
12782
- if (usage.cachedContentTokenCount !== void 0) {
12783
- metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
13898
+ return metrics;
13899
+ }
13900
+ function extractEmbedPromptTokenCount(response) {
13901
+ if (!response) {
13902
+ return void 0;
12784
13903
  }
12785
- if (usage.thoughtsTokenCount !== void 0) {
12786
- metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
13904
+ const usagePromptTokens = response.usageMetadata?.promptTokenCount;
13905
+ if (typeof usagePromptTokens === "number" && Number.isFinite(usagePromptTokens)) {
13906
+ return usagePromptTokens;
13907
+ }
13908
+ const usageTotalTokens = response.usageMetadata?.totalTokenCount;
13909
+ if (typeof usageTotalTokens === "number" && Number.isFinite(usageTotalTokens)) {
13910
+ return usageTotalTokens;
13911
+ }
13912
+ const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
13913
+ if (embeddings.length === 0) {
13914
+ return void 0;
13915
+ }
13916
+ let total = 0;
13917
+ let sawAny = false;
13918
+ for (const embedding of embeddings) {
13919
+ const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
13920
+ const tokenCount = embeddingStats?.tokenCount;
13921
+ if (typeof tokenCount === "number" && Number.isFinite(tokenCount)) {
13922
+ total += tokenCount;
13923
+ sawAny = true;
13924
+ }
12787
13925
  }
13926
+ return sawAny ? total : void 0;
12788
13927
  }
12789
- function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
13928
+ function summarizeEmbedContentOutput(response) {
13929
+ if (!response) {
13930
+ return void 0;
13931
+ }
13932
+ const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
13933
+ if (embeddings.length === 0) {
13934
+ return void 0;
13935
+ }
13936
+ const firstValues = embeddings[0]?.values;
13937
+ if (!Array.isArray(firstValues)) {
13938
+ return void 0;
13939
+ }
13940
+ return {
13941
+ embedding_count: embeddings.length,
13942
+ embedding_length: firstValues.length
13943
+ };
13944
+ }
13945
+ function populateUsageMetrics(metrics, usage) {
13946
+ if (usage.promptTokenCount !== void 0) {
13947
+ metrics.prompt_tokens = usage.promptTokenCount;
13948
+ }
13949
+ if (usage.candidatesTokenCount !== void 0) {
13950
+ metrics.completion_tokens = usage.candidatesTokenCount;
13951
+ }
13952
+ if (usage.totalTokenCount !== void 0) {
13953
+ metrics.tokens = usage.totalTokenCount;
13954
+ }
13955
+ if (usage.cachedContentTokenCount !== void 0) {
13956
+ metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
13957
+ }
13958
+ if (usage.thoughtsTokenCount !== void 0) {
13959
+ metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
13960
+ }
13961
+ }
13962
+ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
12790
13963
  const end = getCurrentUnixTimestamp();
12791
13964
  const metrics = {
12792
13965
  start: startTime,
@@ -12802,6 +13975,7 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
12802
13975
  let text = "";
12803
13976
  let thoughtText = "";
12804
13977
  const otherParts = [];
13978
+ let groundingMetadata = void 0;
12805
13979
  let usageMetadata = null;
12806
13980
  let lastResponse = null;
12807
13981
  for (const chunk of chunks) {
@@ -12809,6 +13983,9 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
12809
13983
  if (chunk.usageMetadata) {
12810
13984
  usageMetadata = chunk.usageMetadata;
12811
13985
  }
13986
+ if (chunk.groundingMetadata !== void 0) {
13987
+ groundingMetadata = chunk.groundingMetadata;
13988
+ }
12812
13989
  if (chunk.candidates && Array.isArray(chunk.candidates)) {
12813
13990
  for (const candidate of chunk.candidates) {
12814
13991
  if (candidate.content?.parts) {
@@ -12854,6 +14031,12 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
12854
14031
  if (candidate.finishReason !== void 0) {
12855
14032
  candidateDict.finishReason = candidate.finishReason;
12856
14033
  }
14034
+ if (candidate.groundingMetadata !== void 0) {
14035
+ candidateDict.groundingMetadata = candidate.groundingMetadata;
14036
+ if (groundingMetadata === void 0) {
14037
+ groundingMetadata = candidate.groundingMetadata;
14038
+ }
14039
+ }
12857
14040
  if (candidate.safetyRatings) {
12858
14041
  candidateDict.safetyRatings = candidate.safetyRatings;
12859
14042
  }
@@ -12865,6 +14048,9 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
12865
14048
  aggregated.usageMetadata = usageMetadata;
12866
14049
  populateUsageMetrics(metrics, usageMetadata);
12867
14050
  }
14051
+ if (groundingMetadata !== void 0) {
14052
+ aggregated.groundingMetadata = groundingMetadata;
14053
+ }
12868
14054
  if (text) {
12869
14055
  aggregated.text = text;
12870
14056
  }
@@ -12879,6 +14065,31 @@ function cleanMetrics(metrics) {
12879
14065
  }
12880
14066
  return cleaned;
12881
14067
  }
14068
+ function extractResponseMetadata(response) {
14069
+ const responseDict = tryToDict(response);
14070
+ if (!responseDict) {
14071
+ return void 0;
14072
+ }
14073
+ const metadata = {};
14074
+ const responseGroundingMetadata = responseDict.groundingMetadata;
14075
+ const candidateGroundingMetadata = [];
14076
+ if (Array.isArray(responseDict.candidates)) {
14077
+ for (const candidate of responseDict.candidates) {
14078
+ const candidateDict = tryToDict(candidate);
14079
+ if (candidateDict?.groundingMetadata !== void 0) {
14080
+ candidateGroundingMetadata.push(candidateDict.groundingMetadata);
14081
+ }
14082
+ }
14083
+ }
14084
+ if (responseGroundingMetadata !== void 0) {
14085
+ metadata.groundingMetadata = responseGroundingMetadata;
14086
+ } else if (candidateGroundingMetadata.length === 1) {
14087
+ [metadata.groundingMetadata] = candidateGroundingMetadata;
14088
+ } else if (candidateGroundingMetadata.length > 1) {
14089
+ metadata.groundingMetadata = candidateGroundingMetadata;
14090
+ }
14091
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
14092
+ }
12882
14093
  function tryToDict(obj) {
12883
14094
  if (obj === null || obj === void 0) {
12884
14095
  return null;
@@ -12893,6 +14104,385 @@ function tryToDict(obj) {
12893
14104
  return null;
12894
14105
  }
12895
14106
 
14107
+ // src/instrumentation/plugins/huggingface-channels.ts
14108
+ var huggingFaceChannels = defineChannels("@huggingface/inference", {
14109
+ chatCompletion: channel({
14110
+ channelName: "chatCompletion",
14111
+ kind: "async"
14112
+ }),
14113
+ chatCompletionStream: channel({
14114
+ channelName: "chatCompletionStream",
14115
+ kind: "sync-stream"
14116
+ }),
14117
+ textGeneration: channel({
14118
+ channelName: "textGeneration",
14119
+ kind: "async"
14120
+ }),
14121
+ textGenerationStream: channel({
14122
+ channelName: "textGenerationStream",
14123
+ kind: "sync-stream"
14124
+ }),
14125
+ featureExtraction: channel({
14126
+ channelName: "featureExtraction",
14127
+ kind: "async"
14128
+ })
14129
+ });
14130
+
14131
+ // src/instrumentation/plugins/huggingface-plugin.ts
14132
+ var REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
14133
+ "dimensions",
14134
+ "encoding_format",
14135
+ "endpointUrl",
14136
+ "max_tokens",
14137
+ "model",
14138
+ "provider",
14139
+ "seed",
14140
+ "stop",
14141
+ "stream",
14142
+ "temperature",
14143
+ "top_p"
14144
+ ]);
14145
+ var RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
14146
+ "created",
14147
+ "id",
14148
+ "model",
14149
+ "object"
14150
+ ]);
14151
+ var HuggingFacePlugin = class extends BasePlugin {
14152
+ onEnable() {
14153
+ this.unsubscribers.push(
14154
+ traceAsyncChannel(huggingFaceChannels.chatCompletion, {
14155
+ name: "huggingface.chat_completion",
14156
+ type: "llm" /* LLM */,
14157
+ extractInput: extractChatInputWithMetadata,
14158
+ extractOutput: (result) => result?.choices,
14159
+ extractMetadata: (result) => extractResponseMetadata2(result),
14160
+ extractMetrics: (result) => parseMetricsFromUsage(result?.usage)
14161
+ }),
14162
+ traceSyncStreamChannel(huggingFaceChannels.chatCompletionStream, {
14163
+ name: "huggingface.chat_completion_stream",
14164
+ type: "llm" /* LLM */,
14165
+ extractInput: extractChatInputWithMetadata,
14166
+ patchResult: ({ result, span, startTime }) => patchChatCompletionStream({
14167
+ result,
14168
+ span,
14169
+ startTime
14170
+ })
14171
+ }),
14172
+ traceAsyncChannel(huggingFaceChannels.textGeneration, {
14173
+ name: "huggingface.text_generation",
14174
+ type: "llm" /* LLM */,
14175
+ extractInput: extractTextGenerationInputWithMetadata,
14176
+ extractOutput: (result) => isObject(result) ? { generated_text: result.generated_text } : result,
14177
+ extractMetadata: extractTextGenerationMetadata,
14178
+ extractMetrics: (result) => extractTextGenerationMetrics(result?.details ?? null)
14179
+ }),
14180
+ traceSyncStreamChannel(huggingFaceChannels.textGenerationStream, {
14181
+ name: "huggingface.text_generation_stream",
14182
+ type: "llm" /* LLM */,
14183
+ extractInput: extractTextGenerationInputWithMetadata,
14184
+ patchResult: ({ result, span, startTime }) => patchTextGenerationStream({
14185
+ result,
14186
+ span,
14187
+ startTime
14188
+ })
14189
+ }),
14190
+ traceAsyncChannel(huggingFaceChannels.featureExtraction, {
14191
+ name: "huggingface.feature_extraction",
14192
+ type: "llm" /* LLM */,
14193
+ extractInput: extractFeatureExtractionInputWithMetadata,
14194
+ extractOutput: summarizeFeatureExtractionOutput,
14195
+ extractMetrics: () => ({})
14196
+ })
14197
+ );
14198
+ }
14199
+ onDisable() {
14200
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
14201
+ }
14202
+ };
14203
+ function addProviderMetadata(metadata) {
14204
+ return {
14205
+ ...metadata,
14206
+ provider: metadata.provider ?? "huggingface"
14207
+ };
14208
+ }
14209
+ function normalizeArgs(args) {
14210
+ if (Array.isArray(args)) {
14211
+ return args;
14212
+ }
14213
+ if (isArrayLike(args)) {
14214
+ return Array.from(args);
14215
+ }
14216
+ return [args];
14217
+ }
14218
+ function isArrayLike(value) {
14219
+ return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
14220
+ }
14221
+ function getFirstObjectArg(args) {
14222
+ const firstObjectArg = normalizeArgs(args).find((arg) => isObject(arg));
14223
+ return isObject(firstObjectArg) ? firstObjectArg : void 0;
14224
+ }
14225
+ function pickRequestMetadata(params) {
14226
+ if (!params) {
14227
+ return addProviderMetadata({});
14228
+ }
14229
+ const metadata = {};
14230
+ for (const key of REQUEST_METADATA_ALLOWLIST) {
14231
+ const value = params[key];
14232
+ if (value !== void 0) {
14233
+ metadata[key] = value;
14234
+ }
14235
+ }
14236
+ if (isObject(params.parameters)) {
14237
+ metadata.parameters = params.parameters;
14238
+ }
14239
+ return addProviderMetadata(metadata);
14240
+ }
14241
+ function extractChatInputWithMetadata(args) {
14242
+ const params = getFirstObjectArg(args);
14243
+ const { messages, ...rawMetadata } = params ?? {};
14244
+ return {
14245
+ input: messages,
14246
+ metadata: pickRequestMetadata(rawMetadata)
14247
+ };
14248
+ }
14249
+ function extractTextGenerationInputWithMetadata(args) {
14250
+ const params = getFirstObjectArg(args);
14251
+ const { inputs, ...rawMetadata } = params ?? {};
14252
+ return {
14253
+ input: inputs,
14254
+ metadata: pickRequestMetadata(rawMetadata)
14255
+ };
14256
+ }
14257
+ function extractFeatureExtractionInputWithMetadata(args) {
14258
+ const params = getFirstObjectArg(args);
14259
+ const { inputs, ...rawMetadata } = params ?? {};
14260
+ return {
14261
+ input: inputs,
14262
+ metadata: pickRequestMetadata(rawMetadata)
14263
+ };
14264
+ }
14265
+ function extractResponseMetadata2(result) {
14266
+ if (!isObject(result)) {
14267
+ return void 0;
14268
+ }
14269
+ const metadata = {};
14270
+ for (const key of RESPONSE_METADATA_ALLOWLIST) {
14271
+ const value = result[key];
14272
+ if (value !== void 0) {
14273
+ metadata[key] = value;
14274
+ }
14275
+ }
14276
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
14277
+ }
14278
+ function extractTextGenerationMetrics(details) {
14279
+ if (!isObject(details)) {
14280
+ return {};
14281
+ }
14282
+ const promptTokens = Array.isArray(details.prefill) ? details.prefill.length : void 0;
14283
+ const completionTokens = typeof details.generated_tokens === "number" ? details.generated_tokens : Array.isArray(details.tokens) ? details.tokens.length : void 0;
14284
+ const metrics = {};
14285
+ if (promptTokens !== void 0) {
14286
+ metrics.prompt_tokens = promptTokens;
14287
+ }
14288
+ if (completionTokens !== void 0) {
14289
+ metrics.completion_tokens = completionTokens;
14290
+ }
14291
+ if (promptTokens !== void 0 || completionTokens !== void 0) {
14292
+ metrics.tokens = (promptTokens ?? 0) + (completionTokens ?? 0);
14293
+ }
14294
+ return metrics;
14295
+ }
14296
+ function extractTextGenerationMetadata(result) {
14297
+ if (!isObject(result?.details)) {
14298
+ return void 0;
14299
+ }
14300
+ return typeof result.details.finish_reason === "string" ? {
14301
+ finish_reason: result.details.finish_reason
14302
+ } : void 0;
14303
+ }
14304
+ function summarizeFeatureExtractionOutput(result) {
14305
+ if (!Array.isArray(result)) {
14306
+ return void 0;
14307
+ }
14308
+ const first = result[0];
14309
+ if (typeof first === "number") {
14310
+ return { embedding_length: result.length };
14311
+ }
14312
+ if (Array.isArray(first) && first.every((value) => typeof value === "number")) {
14313
+ return {
14314
+ embedding_count: result.length,
14315
+ embedding_length: first.length
14316
+ };
14317
+ }
14318
+ if (Array.isArray(first) && first.length > 0 && Array.isArray(first[0]) && first[0].every((value) => typeof value === "number")) {
14319
+ return {
14320
+ embedding_batch_count: result.length,
14321
+ embedding_count: first.length,
14322
+ embedding_length: first[0].length
14323
+ };
14324
+ }
14325
+ return void 0;
14326
+ }
14327
+ function patchChatCompletionStream(args) {
14328
+ const { result, span, startTime } = args;
14329
+ if (!result || !isAsyncIterable(result)) {
14330
+ return false;
14331
+ }
14332
+ let firstChunkTime;
14333
+ patchStreamIfNeeded(result, {
14334
+ onChunk: () => {
14335
+ if (firstChunkTime === void 0) {
14336
+ firstChunkTime = getCurrentUnixTimestamp();
14337
+ }
14338
+ },
14339
+ onComplete: (chunks) => {
14340
+ const lastChunk = chunks.at(-1);
14341
+ const responseMetadata = extractResponseMetadata2(lastChunk);
14342
+ const metrics = {
14343
+ ...parseMetricsFromUsage(lastChunk?.usage),
14344
+ ...firstChunkTime !== void 0 ? { time_to_first_token: firstChunkTime - startTime } : {}
14345
+ };
14346
+ span.log({
14347
+ output: aggregateChatCompletionChunks2(chunks),
14348
+ ...responseMetadata ? { metadata: responseMetadata } : {},
14349
+ metrics
14350
+ });
14351
+ span.end();
14352
+ },
14353
+ onError: (error) => {
14354
+ span.log({
14355
+ error: error.message
14356
+ });
14357
+ span.end();
14358
+ }
14359
+ });
14360
+ return true;
14361
+ }
14362
+ function patchTextGenerationStream(args) {
14363
+ const { result, span, startTime } = args;
14364
+ if (!result || !isAsyncIterable(result)) {
14365
+ return false;
14366
+ }
14367
+ let firstChunkTime;
14368
+ patchStreamIfNeeded(result, {
14369
+ onChunk: () => {
14370
+ if (firstChunkTime === void 0) {
14371
+ firstChunkTime = getCurrentUnixTimestamp();
14372
+ }
14373
+ },
14374
+ onComplete: (chunks) => {
14375
+ const lastChunk = chunks.at(-1);
14376
+ const streamMetadata = extractTextGenerationStreamMetadata(chunks);
14377
+ span.log({
14378
+ output: aggregateTextGenerationStreamChunks(chunks),
14379
+ ...streamMetadata ? { metadata: streamMetadata } : {},
14380
+ metrics: {
14381
+ ...extractTextGenerationMetrics(lastChunk?.details ?? null),
14382
+ ...parseMetricsFromUsage(lastChunk?.usage),
14383
+ ...firstChunkTime !== void 0 ? { time_to_first_token: firstChunkTime - startTime } : {}
14384
+ }
14385
+ });
14386
+ span.end();
14387
+ },
14388
+ onError: (error) => {
14389
+ span.log({
14390
+ error: error.message
14391
+ });
14392
+ span.end();
14393
+ }
14394
+ });
14395
+ return true;
14396
+ }
14397
+ function aggregateChatCompletionChunks2(chunks) {
14398
+ if (chunks.length === 0) {
14399
+ return void 0;
14400
+ }
14401
+ const aggregatedChoices = /* @__PURE__ */ new Map();
14402
+ for (const chunk of chunks) {
14403
+ for (const choice of chunk.choices ?? []) {
14404
+ const index = typeof choice.index === "number" ? choice.index : 0;
14405
+ const existing = aggregatedChoices.get(index) ?? { content: "" };
14406
+ const delta = isObject(choice.delta) ? choice.delta : void 0;
14407
+ const message = isObject(choice.message) ? choice.message : void 0;
14408
+ if (typeof delta?.content === "string") {
14409
+ existing.content += delta.content;
14410
+ } else if (typeof message?.content === "string") {
14411
+ existing.content = message.content;
14412
+ }
14413
+ if (typeof delta?.role === "string") {
14414
+ existing.role = delta.role;
14415
+ } else if (typeof message?.role === "string") {
14416
+ existing.role = message.role;
14417
+ }
14418
+ if (choice.finish_reason !== void 0) {
14419
+ existing.finish_reason = choice.finish_reason;
14420
+ }
14421
+ aggregatedChoices.set(index, existing);
14422
+ }
14423
+ }
14424
+ return {
14425
+ choices: [...aggregatedChoices.entries()].map(([index, choice]) => ({
14426
+ index,
14427
+ message: {
14428
+ content: choice.content,
14429
+ role: choice.role ?? "assistant"
14430
+ },
14431
+ ...choice.finish_reason !== void 0 ? { finish_reason: choice.finish_reason } : {}
14432
+ }))
14433
+ };
14434
+ }
14435
+ function aggregateTextGenerationStreamChunks(chunks) {
14436
+ if (chunks.length === 0) {
14437
+ return void 0;
14438
+ }
14439
+ let generatedText = "";
14440
+ let finishReason;
14441
+ for (const chunk of chunks) {
14442
+ if (typeof chunk.generated_text === "string") {
14443
+ generatedText = chunk.generated_text;
14444
+ } else if (typeof chunk.token?.text === "string" && !chunk.token.special) {
14445
+ generatedText += chunk.token.text;
14446
+ } else if (Array.isArray(chunk.choices)) {
14447
+ for (const choice of chunk.choices) {
14448
+ if (typeof choice.text === "string") {
14449
+ generatedText += choice.text;
14450
+ }
14451
+ if (choice.finish_reason !== void 0) {
14452
+ finishReason = choice.finish_reason;
14453
+ }
14454
+ }
14455
+ }
14456
+ if (isObject(chunk.details) && typeof chunk.details.finish_reason === "string") {
14457
+ finishReason = chunk.details.finish_reason;
14458
+ }
14459
+ }
14460
+ return {
14461
+ generated_text: generatedText,
14462
+ ...finishReason !== void 0 ? { finish_reason: finishReason } : {}
14463
+ };
14464
+ }
14465
+ function extractTextGenerationStreamMetadata(chunks) {
14466
+ for (let index = chunks.length - 1; index >= 0; index--) {
14467
+ const chunk = chunks[index];
14468
+ if (isObject(chunk?.details) && typeof chunk.details.finish_reason === "string") {
14469
+ return {
14470
+ finish_reason: chunk.details.finish_reason
14471
+ };
14472
+ }
14473
+ if (!Array.isArray(chunk?.choices)) {
14474
+ continue;
14475
+ }
14476
+ for (let choiceIndex = chunk.choices.length - 1; choiceIndex >= 0; choiceIndex--) {
14477
+ const choice = chunk.choices[choiceIndex];
14478
+ if (choice?.finish_reason !== void 0) {
14479
+ return { finish_reason: choice.finish_reason };
14480
+ }
14481
+ }
14482
+ }
14483
+ return void 0;
14484
+ }
14485
+
12896
14486
  // src/instrumentation/plugins/openrouter-agent-channels.ts
12897
14487
  var openRouterAgentChannels = defineChannels("@openrouter/agent", {
12898
14488
  callModel: channel({
@@ -13010,20 +14600,20 @@ var OpenRouterAgentPlugin = class extends BasePlugin {
13010
14600
  });
13011
14601
  }
13012
14602
  };
13013
- function normalizeArgs(args) {
14603
+ function normalizeArgs2(args) {
13014
14604
  if (Array.isArray(args)) {
13015
14605
  return args;
13016
14606
  }
13017
- if (isArrayLike(args)) {
14607
+ if (isArrayLike2(args)) {
13018
14608
  return Array.from(args);
13019
14609
  }
13020
14610
  return [args];
13021
14611
  }
13022
- function isArrayLike(value) {
14612
+ function isArrayLike2(value) {
13023
14613
  return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
13024
14614
  }
13025
14615
  function getOpenRouterCallModelRequestArg(args) {
13026
- const normalizedArgs = normalizeArgs(args);
14616
+ const normalizedArgs = normalizeArgs2(args);
13027
14617
  const keyedRequestArg = normalizedArgs.find(
13028
14618
  (arg) => isObject(arg) && ("input" in arg || "model" in arg || "tools" in arg)
13029
14619
  );
@@ -13309,7 +14899,7 @@ function traceToolExecution(args) {
13309
14899
  }
13310
14900
  }
13311
14901
  function publishToolResult(tracingChannel, event, result) {
13312
- if (isPromiseLike3(result)) {
14902
+ if (isPromiseLike(result)) {
13313
14903
  return result.then(
13314
14904
  (resolved) => {
13315
14905
  event.result = resolved;
@@ -13331,9 +14921,6 @@ function getToolCallId(context) {
13331
14921
  const toolContext = context;
13332
14922
  return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
13333
14923
  }
13334
- function isPromiseLike3(value) {
13335
- return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
13336
- }
13337
14924
  var OPENROUTER_WRAPPED_CALL_MODEL_RESULT = Symbol(
13338
14925
  "braintrust.openrouter.wrappedCallModelResult"
13339
14926
  );
@@ -13688,7 +15275,13 @@ var openRouterChannels = defineChannels("@openrouter/sdk", {
13688
15275
  channelName: "embeddings.generate",
13689
15276
  kind: "async"
13690
15277
  }),
13691
- betaResponsesSend: channel({
15278
+ rerankRerank: channel(
15279
+ {
15280
+ channelName: "rerank.rerank",
15281
+ kind: "async"
15282
+ }
15283
+ ),
15284
+ betaResponsesSend: channel({
13692
15285
  channelName: "beta.responses.send",
13693
15286
  kind: "async"
13694
15287
  }),
@@ -13780,6 +15373,34 @@ var OpenRouterPlugin = class extends BasePlugin {
13780
15373
  }
13781
15374
  })
13782
15375
  );
15376
+ this.unsubscribers.push(
15377
+ traceAsyncChannel(openRouterChannels.rerankRerank, {
15378
+ name: "openrouter.rerank.rerank",
15379
+ type: "llm" /* LLM */,
15380
+ extractInput: (args) => {
15381
+ const request = getOpenRouterRequestArg(args);
15382
+ const requestBody = isObject(request?.requestBody) ? request.requestBody : {};
15383
+ const httpReferer = request?.httpReferer;
15384
+ const xTitle = request?.xTitle ?? request?.appTitle;
15385
+ const { documents, query, ...metadata } = requestBody;
15386
+ return {
15387
+ input: {
15388
+ documents,
15389
+ query
15390
+ },
15391
+ metadata: buildOpenRouterRerankMetadata(
15392
+ metadata,
15393
+ documents,
15394
+ httpReferer,
15395
+ xTitle
15396
+ )
15397
+ };
15398
+ },
15399
+ extractOutput: (result) => extractOpenRouterRerankOutput(result),
15400
+ extractMetadata: (result) => extractOpenRouterResponseMetadata2(result),
15401
+ extractMetrics: (result) => isObject(result) ? parseOpenRouterMetricsFromUsage2(result.usage) : {}
15402
+ })
15403
+ );
13783
15404
  this.unsubscribers.push(
13784
15405
  traceStreamingChannel(openRouterChannels.betaResponsesSend, {
13785
15406
  name: "openrouter.beta.responses.send",
@@ -13899,20 +15520,20 @@ var OpenRouterPlugin = class extends BasePlugin {
13899
15520
  });
13900
15521
  }
13901
15522
  };
13902
- function normalizeArgs2(args) {
15523
+ function normalizeArgs3(args) {
13903
15524
  if (Array.isArray(args)) {
13904
15525
  return args;
13905
15526
  }
13906
- if (isArrayLike2(args)) {
15527
+ if (isArrayLike3(args)) {
13907
15528
  return Array.from(args);
13908
15529
  }
13909
15530
  return [args];
13910
15531
  }
13911
- function isArrayLike2(value) {
15532
+ function isArrayLike3(value) {
13912
15533
  return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
13913
15534
  }
13914
15535
  function getOpenRouterRequestArg(args) {
13915
- const normalizedArgs = normalizeArgs2(args);
15536
+ const normalizedArgs = normalizeArgs3(args);
13916
15537
  const keyedCandidate = normalizedArgs.find(
13917
15538
  (arg) => isObject(arg) && ("chatGenerationParams" in arg || "requestBody" in arg || "openResponsesRequest" in arg)
13918
15539
  );
@@ -13923,7 +15544,7 @@ function getOpenRouterRequestArg(args) {
13923
15544
  return isObject(firstObjectArg) ? firstObjectArg : void 0;
13924
15545
  }
13925
15546
  function getOpenRouterCallModelRequestArg2(args) {
13926
- const firstObjectArg = normalizeArgs2(args).find((arg) => isObject(arg));
15547
+ const firstObjectArg = normalizeArgs3(args).find((arg) => isObject(arg));
13927
15548
  return isObject(firstObjectArg) ? firstObjectArg : void 0;
13928
15549
  }
13929
15550
  var TOKEN_NAME_MAP3 = {
@@ -14093,6 +15714,13 @@ function buildOpenRouterEmbeddingMetadata(metadata, httpReferer, xTitle) {
14093
15714
  embedding_model: normalized.model
14094
15715
  } : normalized;
14095
15716
  }
15717
+ function buildOpenRouterRerankMetadata(metadata, documents, httpReferer, xTitle) {
15718
+ const normalized = buildOpenRouterMetadata2(metadata, httpReferer, xTitle);
15719
+ return {
15720
+ ...normalized,
15721
+ ...Array.isArray(documents) ? { document_count: documents.length } : {}
15722
+ };
15723
+ }
14096
15724
  function extractOpenRouterCallModelInput2(request) {
14097
15725
  return isObject(request) && "input" in request ? sanitizeOpenRouterLoggedValue2(request.input) : void 0;
14098
15726
  }
@@ -14112,7 +15740,7 @@ function extractOpenRouterResponseMetadata2(result) {
14112
15740
  const metadataRecord = isObject(sanitized) ? sanitized : {};
14113
15741
  const { model, provider, ...rest } = metadataRecord;
14114
15742
  const normalizedModel = parseOpenRouterModelString2(model);
14115
- const normalizedProvider = (typeof provider === "string" ? provider : void 0) || normalizedModel.provider;
15743
+ const normalizedProvider = (typeof provider === "string" ? provider.toLowerCase() : void 0) || normalizedModel.provider;
14116
15744
  const usageMetadata = extractOpenRouterUsageMetadata2(usage);
14117
15745
  const combined = {
14118
15746
  ...rest,
@@ -14131,6 +15759,15 @@ function extractOpenRouterResponseOutput2(response, fallbackOutput) {
14131
15759
  }
14132
15760
  return void 0;
14133
15761
  }
15762
+ function extractOpenRouterRerankOutput(result) {
15763
+ if (!isObject(result) || !Array.isArray(result.results)) {
15764
+ return void 0;
15765
+ }
15766
+ return result.results.slice(0, 100).map((item) => ({
15767
+ index: isObject(item) && typeof item.index === "number" ? item.index : void 0,
15768
+ relevance_score: isObject(item) && typeof item.relevanceScore === "number" ? item.relevanceScore : isObject(item) && typeof item.relevance_score === "number" ? item.relevance_score : void 0
15769
+ }));
15770
+ }
14134
15771
  var OPENROUTER_WRAPPED_TOOL2 = Symbol("braintrust.openrouter.wrappedTool");
14135
15772
  function patchOpenRouterCallModelRequestTools2(request) {
14136
15773
  if (!Array.isArray(request.tools) || request.tools.length === 0) {
@@ -14201,7 +15838,7 @@ function traceToolExecution2(args) {
14201
15838
  }
14202
15839
  }
14203
15840
  function publishToolResult2(tracingChannel, event, result) {
14204
- if (isPromiseLike4(result)) {
15841
+ if (isPromiseLike(result)) {
14205
15842
  return result.then(
14206
15843
  (resolved) => {
14207
15844
  event.result = resolved;
@@ -14223,9 +15860,6 @@ function getToolCallId2(context) {
14223
15860
  const toolContext = context;
14224
15861
  return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
14225
15862
  }
14226
- function isPromiseLike4(value) {
14227
- return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
14228
- }
14229
15863
  function aggregateOpenRouterChatChunks(chunks) {
14230
15864
  let role;
14231
15865
  let content = "";
@@ -14865,20 +16499,20 @@ var MISTRAL_RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
14865
16499
  function camelToSnake3(value) {
14866
16500
  return value.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
14867
16501
  }
14868
- function normalizeArgs3(args) {
16502
+ function normalizeArgs4(args) {
14869
16503
  if (Array.isArray(args)) {
14870
16504
  return args;
14871
16505
  }
14872
- if (isArrayLike3(args)) {
16506
+ if (isArrayLike4(args)) {
14873
16507
  return Array.from(args);
14874
16508
  }
14875
16509
  return [args];
14876
16510
  }
14877
- function isArrayLike3(value) {
16511
+ function isArrayLike4(value) {
14878
16512
  return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
14879
16513
  }
14880
16514
  function getMistralRequestArg(args) {
14881
- const firstObjectArg = normalizeArgs3(args).find((arg) => isObject(arg));
16515
+ const firstObjectArg = normalizeArgs4(args).find((arg) => isObject(arg));
14882
16516
  return isObject(firstObjectArg) ? firstObjectArg : void 0;
14883
16517
  }
14884
16518
  function addMistralProviderMetadata(metadata) {
@@ -15183,88 +16817,1326 @@ function aggregateMistralStreamChunks(chunks) {
15183
16817
  };
15184
16818
  }
15185
16819
 
15186
- // src/instrumentation/braintrust-plugin.ts
15187
- var BraintrustPlugin = class extends BasePlugin {
15188
- config;
15189
- openaiPlugin = null;
15190
- anthropicPlugin = null;
15191
- aiSDKPlugin = null;
15192
- claudeAgentSDKPlugin = null;
15193
- googleGenAIPlugin = null;
15194
- openRouterPlugin = null;
15195
- openRouterAgentPlugin = null;
15196
- mistralPlugin = null;
15197
- constructor(config = {}) {
15198
- super();
15199
- this.config = config;
15200
- }
16820
+ // src/instrumentation/plugins/google-adk-channels.ts
16821
+ var googleADKChannels = defineChannels("@google/adk", {
16822
+ runnerRunAsync: channel({
16823
+ channelName: "runner.runAsync",
16824
+ kind: "sync-stream"
16825
+ }),
16826
+ agentRunAsync: channel({
16827
+ channelName: "agent.runAsync",
16828
+ kind: "sync-stream"
16829
+ }),
16830
+ toolRunAsync: channel({
16831
+ channelName: "tool.runAsync",
16832
+ kind: "async"
16833
+ })
16834
+ });
16835
+
16836
+ // src/instrumentation/plugins/google-adk-plugin.ts
16837
+ var GoogleADKPlugin = class extends BasePlugin {
16838
+ activeRunnerSpans = /* @__PURE__ */ new Map();
16839
+ activeAgentSpans = /* @__PURE__ */ new Map();
15201
16840
  onEnable() {
15202
- const integrations = this.config.integrations || {};
15203
- if (integrations.openai !== false) {
15204
- this.openaiPlugin = new OpenAIPlugin();
15205
- this.openaiPlugin.enable();
15206
- }
15207
- if (integrations.anthropic !== false) {
15208
- this.anthropicPlugin = new AnthropicPlugin();
15209
- this.anthropicPlugin.enable();
15210
- }
15211
- if (integrations.aisdk !== false && integrations.vercel !== false) {
15212
- this.aiSDKPlugin = new AISDKPlugin();
15213
- this.aiSDKPlugin.enable();
15214
- }
15215
- if (integrations.claudeAgentSDK !== false) {
15216
- this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
15217
- this.claudeAgentSDKPlugin.enable();
15218
- }
15219
- if (integrations.googleGenAI !== false && integrations.google !== false) {
15220
- this.googleGenAIPlugin = new GoogleGenAIPlugin();
15221
- this.googleGenAIPlugin.enable();
15222
- }
15223
- if (integrations.openrouter !== false) {
15224
- this.openRouterPlugin = new OpenRouterPlugin();
15225
- this.openRouterPlugin.enable();
15226
- }
15227
- if (integrations.openrouterAgent !== false) {
15228
- this.openRouterAgentPlugin = new OpenRouterAgentPlugin();
15229
- this.openRouterAgentPlugin.enable();
15230
- }
15231
- if (integrations.mistral !== false) {
15232
- this.mistralPlugin = new MistralPlugin();
15233
- this.mistralPlugin.enable();
15234
- }
16841
+ this.subscribeToRunnerRunAsync();
16842
+ this.subscribeToAgentRunAsync();
16843
+ this.subscribeToToolRunAsync();
15235
16844
  }
15236
16845
  onDisable() {
15237
- if (this.openaiPlugin) {
15238
- this.openaiPlugin.disable();
15239
- this.openaiPlugin = null;
15240
- }
15241
- if (this.anthropicPlugin) {
15242
- this.anthropicPlugin.disable();
15243
- this.anthropicPlugin = null;
15244
- }
15245
- if (this.aiSDKPlugin) {
15246
- this.aiSDKPlugin.disable();
15247
- this.aiSDKPlugin = null;
15248
- }
15249
- if (this.claudeAgentSDKPlugin) {
15250
- this.claudeAgentSDKPlugin.disable();
15251
- this.claudeAgentSDKPlugin = null;
15252
- }
15253
- if (this.googleGenAIPlugin) {
15254
- this.googleGenAIPlugin.disable();
15255
- this.googleGenAIPlugin = null;
15256
- }
15257
- if (this.openRouterPlugin) {
15258
- this.openRouterPlugin.disable();
15259
- this.openRouterPlugin = null;
15260
- }
15261
- if (this.openRouterAgentPlugin) {
15262
- this.openRouterAgentPlugin.disable();
15263
- this.openRouterAgentPlugin = null;
16846
+ for (const unsubscribe of this.unsubscribers) {
16847
+ unsubscribe();
15264
16848
  }
15265
- if (this.mistralPlugin) {
15266
- this.mistralPlugin.disable();
15267
- this.mistralPlugin = null;
16849
+ this.unsubscribers = [];
16850
+ this.activeRunnerSpans.clear();
16851
+ this.activeAgentSpans.clear();
16852
+ }
16853
+ subscribeToRunnerRunAsync() {
16854
+ const tracingChannel = googleADKChannels.runnerRunAsync.tracingChannel();
16855
+ const states = /* @__PURE__ */ new WeakMap();
16856
+ const createState = (event) => {
16857
+ const params = event.arguments[0] ?? {};
16858
+ const contextKey = extractRunnerContextKey(params);
16859
+ const span = startSpan({
16860
+ name: "Google ADK Runner",
16861
+ spanAttributes: {
16862
+ type: "task" /* TASK */
16863
+ }
16864
+ });
16865
+ const startTime = getCurrentUnixTimestamp();
16866
+ try {
16867
+ const metadata = extractRunnerMetadata(params);
16868
+ span.log({
16869
+ input: extractRunnerInput(params),
16870
+ metadata
16871
+ });
16872
+ } catch {
16873
+ }
16874
+ if (contextKey) {
16875
+ this.activeRunnerSpans.set(contextKey, span);
16876
+ }
16877
+ return { span, startTime, events: [], contextKey };
16878
+ };
16879
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart3(
16880
+ tracingChannel,
16881
+ states,
16882
+ createState
16883
+ );
16884
+ const handlers = {
16885
+ start: (event) => {
16886
+ ensureState(states, event, () => createState(event));
16887
+ },
16888
+ end: (event) => {
16889
+ const state = states.get(event);
16890
+ if (!state) {
16891
+ return;
16892
+ }
16893
+ const result = event.result;
16894
+ if (isAsyncIterable(result)) {
16895
+ bindAsyncIterableToCurrentSpan(result, state.span);
16896
+ patchStreamIfNeeded(result, {
16897
+ onChunk: (adkEvent) => {
16898
+ state.events.push(adkEvent);
16899
+ },
16900
+ onComplete: () => {
16901
+ finalizeRunnerSpan(state, this.activeRunnerSpans);
16902
+ states.delete(event);
16903
+ },
16904
+ onError: (error) => {
16905
+ cleanupActiveRunnerSpan(state, this.activeRunnerSpans);
16906
+ state.span.log({ error: error.message });
16907
+ state.span.end();
16908
+ states.delete(event);
16909
+ }
16910
+ });
16911
+ return;
16912
+ }
16913
+ try {
16914
+ state.span.log({ output: result });
16915
+ } finally {
16916
+ cleanupActiveRunnerSpan(state, this.activeRunnerSpans);
16917
+ state.span.end();
16918
+ states.delete(event);
16919
+ }
16920
+ },
16921
+ error: (event) => {
16922
+ const state = states.get(event);
16923
+ if (!state || !event.error) {
16924
+ return;
16925
+ }
16926
+ cleanupActiveRunnerSpan(state, this.activeRunnerSpans);
16927
+ state.span.log({ error: event.error.message });
16928
+ state.span.end();
16929
+ states.delete(event);
16930
+ }
16931
+ };
16932
+ tracingChannel.subscribe(handlers);
16933
+ this.unsubscribers.push(() => {
16934
+ unbindCurrentSpanStore?.();
16935
+ tracingChannel.unsubscribe(handlers);
16936
+ });
16937
+ }
16938
+ subscribeToAgentRunAsync() {
16939
+ const tracingChannel = googleADKChannels.agentRunAsync.tracingChannel();
16940
+ const states = /* @__PURE__ */ new WeakMap();
16941
+ const createState = (event) => {
16942
+ const parentContext = event.arguments[0];
16943
+ const agentName = extractAgentName(parentContext);
16944
+ const runnerParentSpan = findRunnerParentSpan(
16945
+ parentContext,
16946
+ this.activeRunnerSpans
16947
+ );
16948
+ const contextKey = extractInvocationContextKey(parentContext);
16949
+ const span = startSpan({
16950
+ name: agentName ? `Agent: ${agentName}` : "Google ADK Agent",
16951
+ spanAttributes: {
16952
+ type: "task" /* TASK */
16953
+ },
16954
+ ...runnerParentSpan ? {
16955
+ parentSpanIds: {
16956
+ spanId: runnerParentSpan.spanId,
16957
+ rootSpanId: runnerParentSpan.rootSpanId
16958
+ }
16959
+ } : {}
16960
+ });
16961
+ const startTime = getCurrentUnixTimestamp();
16962
+ try {
16963
+ const metadata = {
16964
+ provider: "google-adk"
16965
+ };
16966
+ if (agentName) {
16967
+ metadata["google_adk.agent_name"] = agentName;
16968
+ }
16969
+ const modelName = extractModelName(parentContext);
16970
+ if (modelName) {
16971
+ metadata.model = modelName;
16972
+ }
16973
+ span.log({ metadata });
16974
+ } catch {
16975
+ }
16976
+ if (contextKey && agentName) {
16977
+ this.activeAgentSpans.set(agentContextKey(contextKey, agentName), span);
16978
+ }
16979
+ return { span, startTime, events: [], contextKey, name: agentName };
16980
+ };
16981
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart3(
16982
+ tracingChannel,
16983
+ states,
16984
+ createState
16985
+ );
16986
+ const handlers = {
16987
+ start: (event) => {
16988
+ ensureState(states, event, () => createState(event));
16989
+ },
16990
+ end: (event) => {
16991
+ const state = states.get(event);
16992
+ if (!state) {
16993
+ return;
16994
+ }
16995
+ const result = event.result;
16996
+ if (isAsyncIterable(result)) {
16997
+ bindAsyncIterableToCurrentSpan(result, state.span);
16998
+ patchStreamIfNeeded(result, {
16999
+ onChunk: (adkEvent) => {
17000
+ state.events.push(adkEvent);
17001
+ },
17002
+ onComplete: () => {
17003
+ finalizeAgentSpan(state, this.activeAgentSpans);
17004
+ states.delete(event);
17005
+ },
17006
+ onError: (error) => {
17007
+ cleanupActiveAgentSpan(state, this.activeAgentSpans);
17008
+ state.span.log({ error: error.message });
17009
+ state.span.end();
17010
+ states.delete(event);
17011
+ }
17012
+ });
17013
+ return;
17014
+ }
17015
+ try {
17016
+ state.span.log({ output: result });
17017
+ } finally {
17018
+ cleanupActiveAgentSpan(state, this.activeAgentSpans);
17019
+ state.span.end();
17020
+ states.delete(event);
17021
+ }
17022
+ },
17023
+ error: (event) => {
17024
+ const state = states.get(event);
17025
+ if (!state || !event.error) {
17026
+ return;
17027
+ }
17028
+ cleanupActiveAgentSpan(state, this.activeAgentSpans);
17029
+ state.span.log({ error: event.error.message });
17030
+ state.span.end();
17031
+ states.delete(event);
17032
+ }
17033
+ };
17034
+ tracingChannel.subscribe(handlers);
17035
+ this.unsubscribers.push(() => {
17036
+ unbindCurrentSpanStore?.();
17037
+ tracingChannel.unsubscribe(handlers);
17038
+ });
17039
+ }
17040
+ subscribeToToolRunAsync() {
17041
+ const tracingChannel = googleADKChannels.toolRunAsync.tracingChannel();
17042
+ const states = /* @__PURE__ */ new WeakMap();
17043
+ const handlers = {
17044
+ start: (event) => {
17045
+ const req = event.arguments[0] ?? {};
17046
+ const tool = event.self;
17047
+ const toolName = extractToolName(req, tool);
17048
+ const parentSpan = findToolParentSpan(
17049
+ req,
17050
+ this.activeAgentSpans,
17051
+ this.activeRunnerSpans
17052
+ );
17053
+ const createSpan = () => startSpan({
17054
+ name: toolName ? `tool: ${toolName}` : "Google ADK Tool",
17055
+ spanAttributes: {
17056
+ type: "tool" /* TOOL */
17057
+ },
17058
+ event: {
17059
+ input: req.args,
17060
+ metadata: {
17061
+ provider: "google-adk",
17062
+ ...toolName && { "google_adk.tool_name": toolName },
17063
+ ...extractToolCallId(req) && {
17064
+ "google_adk.tool_call_id": extractToolCallId(req)
17065
+ }
17066
+ }
17067
+ }
17068
+ });
17069
+ const span = parentSpan ? withCurrent(parentSpan, () => createSpan()) : createSpan();
17070
+ const startTime = getCurrentUnixTimestamp();
17071
+ states.set(event, { span, startTime });
17072
+ },
17073
+ asyncEnd: (event) => {
17074
+ const state = states.get(event);
17075
+ if (!state) {
17076
+ return;
17077
+ }
17078
+ try {
17079
+ const metrics = {};
17080
+ const end = getCurrentUnixTimestamp();
17081
+ metrics.start = state.startTime;
17082
+ metrics.end = end;
17083
+ metrics.duration = end - state.startTime;
17084
+ state.span.log({
17085
+ output: event.result,
17086
+ metrics: cleanMetrics2(metrics)
17087
+ });
17088
+ } finally {
17089
+ state.span.end();
17090
+ states.delete(event);
17091
+ }
17092
+ },
17093
+ error: (event) => {
17094
+ const state = states.get(event);
17095
+ if (!state || !event.error) {
17096
+ return;
17097
+ }
17098
+ state.span.log({ error: event.error.message });
17099
+ state.span.end();
17100
+ states.delete(event);
17101
+ }
17102
+ };
17103
+ tracingChannel.subscribe(handlers);
17104
+ this.unsubscribers.push(() => {
17105
+ tracingChannel.unsubscribe(handlers);
17106
+ });
17107
+ }
17108
+ };
17109
+ function ensureState(states, event, create) {
17110
+ const existing = states.get(event);
17111
+ if (existing) {
17112
+ return existing;
17113
+ }
17114
+ const created = create();
17115
+ states.set(event, created);
17116
+ return created;
17117
+ }
17118
+ function bindAsyncIterableToCurrentSpan(stream, span) {
17119
+ if (!isAsyncIterable(stream)) {
17120
+ return stream;
17121
+ }
17122
+ if (Object.isFrozen(stream) || Object.isSealed(stream)) {
17123
+ return stream;
17124
+ }
17125
+ if ("next" in stream && typeof stream.next === "function") {
17126
+ if ("__braintrust_current_span_bound" in stream) {
17127
+ return stream;
17128
+ }
17129
+ try {
17130
+ const iterator = stream;
17131
+ const originalNext = iterator.next.bind(iterator);
17132
+ iterator.next = (...args) => withCurrent(span, () => originalNext(...args));
17133
+ if (typeof iterator.return === "function") {
17134
+ const originalReturn = iterator.return.bind(iterator);
17135
+ iterator.return = (...args) => withCurrent(span, () => originalReturn(...args));
17136
+ }
17137
+ if (typeof iterator.throw === "function") {
17138
+ const originalThrow = iterator.throw.bind(iterator);
17139
+ iterator.throw = (...args) => withCurrent(span, () => originalThrow(...args));
17140
+ }
17141
+ Object.defineProperty(stream, "__braintrust_current_span_bound", {
17142
+ value: true
17143
+ });
17144
+ return stream;
17145
+ } catch {
17146
+ return stream;
17147
+ }
17148
+ }
17149
+ const originalIteratorFn = stream[Symbol.asyncIterator];
17150
+ if ("__braintrust_current_span_bound" in originalIteratorFn && originalIteratorFn.__braintrust_current_span_bound) {
17151
+ return stream;
17152
+ }
17153
+ try {
17154
+ const patchedIteratorFn = function() {
17155
+ const iterator = originalIteratorFn.call(this);
17156
+ const originalNext = iterator.next.bind(iterator);
17157
+ iterator.next = (...args) => withCurrent(span, () => originalNext(...args));
17158
+ if (typeof iterator.return === "function") {
17159
+ const originalReturn = iterator.return.bind(iterator);
17160
+ iterator.return = (...args) => withCurrent(span, () => originalReturn(...args));
17161
+ }
17162
+ if (typeof iterator.throw === "function") {
17163
+ const originalThrow = iterator.throw.bind(iterator);
17164
+ iterator.throw = (...args) => withCurrent(span, () => originalThrow(...args));
17165
+ }
17166
+ return iterator;
17167
+ };
17168
+ Object.defineProperty(
17169
+ patchedIteratorFn,
17170
+ "__braintrust_current_span_bound",
17171
+ {
17172
+ value: true
17173
+ }
17174
+ );
17175
+ stream[Symbol.asyncIterator] = patchedIteratorFn;
17176
+ } catch {
17177
+ return stream;
17178
+ }
17179
+ return stream;
17180
+ }
17181
+ function bindCurrentSpanStoreToStart3(tracingChannel, states, create) {
17182
+ const state = _internalGetGlobalState();
17183
+ const contextManager = state?.contextManager;
17184
+ const startChannel = tracingChannel.start;
17185
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
17186
+ if (!startChannel?.bindStore || !currentSpanStore) {
17187
+ return void 0;
17188
+ }
17189
+ startChannel.bindStore(currentSpanStore, (event) => {
17190
+ const span = ensureState(
17191
+ states,
17192
+ event,
17193
+ () => create(event)
17194
+ ).span;
17195
+ return contextManager.wrapSpanForStore(span);
17196
+ });
17197
+ return () => {
17198
+ startChannel.unbindStore?.(currentSpanStore);
17199
+ };
17200
+ }
17201
+ function extractRunnerContextKey(paramsOrContext) {
17202
+ const directUserId = "userId" in paramsOrContext ? paramsOrContext.userId : void 0;
17203
+ const directSessionId = "sessionId" in paramsOrContext ? paramsOrContext.sessionId : void 0;
17204
+ if (typeof directUserId === "string" && typeof directSessionId === "string") {
17205
+ return `${directUserId}:${directSessionId}`;
17206
+ }
17207
+ const invocationContext = paramsOrContext;
17208
+ return extractInvocationContextKey(invocationContext);
17209
+ }
17210
+ function extractInvocationContextKey(parentContext) {
17211
+ const session = parentContext?.session;
17212
+ const userId = session?.userId;
17213
+ const sessionId = session?.id;
17214
+ if (typeof userId !== "string" || typeof sessionId !== "string") {
17215
+ return void 0;
17216
+ }
17217
+ return `${userId}:${sessionId}`;
17218
+ }
17219
+ function findRunnerParentSpan(parentContext, activeRunnerSpans) {
17220
+ const contextKey = extractInvocationContextKey(parentContext);
17221
+ return contextKey ? activeRunnerSpans.get(contextKey) : void 0;
17222
+ }
17223
+ function cleanupActiveRunnerSpan(state, activeRunnerSpans) {
17224
+ if (state.contextKey) {
17225
+ activeRunnerSpans.delete(state.contextKey);
17226
+ }
17227
+ }
17228
+ function agentContextKey(contextKey, agentName) {
17229
+ return `${contextKey}:${agentName}`;
17230
+ }
17231
+ function cleanupActiveAgentSpan(state, activeAgentSpans) {
17232
+ if (state.contextKey && state.name) {
17233
+ activeAgentSpans.delete(agentContextKey(state.contextKey, state.name));
17234
+ }
17235
+ }
17236
+ function extractRunnerInput(paramsOrContext) {
17237
+ const content = "newMessage" in paramsOrContext ? paramsOrContext.newMessage : paramsOrContext.userContent;
17238
+ if (!content || typeof content !== "object") {
17239
+ return void 0;
17240
+ }
17241
+ const normalizedContent = content;
17242
+ if (normalizedContent.parts && Array.isArray(normalizedContent.parts)) {
17243
+ const textParts = normalizedContent.parts.filter((p) => p.text !== void 0).map((p) => p.text);
17244
+ if (textParts.length > 0) {
17245
+ return {
17246
+ messages: [
17247
+ {
17248
+ role: normalizedContent.role ?? "user",
17249
+ content: textParts.join("")
17250
+ }
17251
+ ]
17252
+ };
17253
+ }
17254
+ }
17255
+ return { messages: [normalizedContent] };
17256
+ }
17257
+ function extractRunnerMetadata(paramsOrContext) {
17258
+ const metadata = {
17259
+ provider: "google-adk"
17260
+ };
17261
+ const directUserId = "userId" in paramsOrContext ? paramsOrContext.userId : void 0;
17262
+ const directSessionId = "sessionId" in paramsOrContext ? paramsOrContext.sessionId : void 0;
17263
+ if (typeof directUserId === "string") {
17264
+ metadata["google_adk.user_id"] = directUserId;
17265
+ }
17266
+ if (typeof directSessionId === "string") {
17267
+ metadata["google_adk.session_id"] = directSessionId;
17268
+ }
17269
+ const session = "session" in paramsOrContext ? paramsOrContext.session : void 0;
17270
+ if (metadata["google_adk.user_id"] === void 0 && typeof session?.userId === "string") {
17271
+ metadata["google_adk.user_id"] = session.userId;
17272
+ }
17273
+ if (metadata["google_adk.session_id"] === void 0 && typeof session?.id === "string") {
17274
+ metadata["google_adk.session_id"] = session.id;
17275
+ }
17276
+ return metadata;
17277
+ }
17278
+ function extractAgentName(parentContext) {
17279
+ if (!parentContext) {
17280
+ return void 0;
17281
+ }
17282
+ const agent = parentContext.agent;
17283
+ return agent?.name;
17284
+ }
17285
+ function extractModelName(parentContext) {
17286
+ if (!parentContext) {
17287
+ return void 0;
17288
+ }
17289
+ const agent = parentContext.agent;
17290
+ if (!agent?.model) {
17291
+ return void 0;
17292
+ }
17293
+ if (typeof agent.model === "string") {
17294
+ return agent.model;
17295
+ }
17296
+ if (typeof agent.model === "object" && "model" in agent.model) {
17297
+ return agent.model.model;
17298
+ }
17299
+ return void 0;
17300
+ }
17301
+ function extractToolCallId(req) {
17302
+ const toolContext = req.toolContext;
17303
+ return toolContext?.functionCallId;
17304
+ }
17305
+ function extractToolName(req, tool) {
17306
+ if (typeof tool?.name === "string" && tool.name.length > 0) {
17307
+ return tool.name;
17308
+ }
17309
+ const toolContext = req.toolContext;
17310
+ const invocationContext = toolContext?.invocationContext;
17311
+ const invocationTool = invocationContext?.tool;
17312
+ const toolName = invocationTool?.name;
17313
+ return typeof toolName === "string" && toolName.length > 0 ? toolName : void 0;
17314
+ }
17315
+ function extractToolAgentName(req) {
17316
+ const toolContext = req.toolContext;
17317
+ const directName = toolContext?.agentName;
17318
+ if (typeof directName === "string" && directName.length > 0) {
17319
+ return directName;
17320
+ }
17321
+ const invocationContext = toolContext?.invocationContext;
17322
+ return extractAgentName(invocationContext);
17323
+ }
17324
+ function findToolParentSpan(req, activeAgentSpans, activeRunnerSpans) {
17325
+ const toolContext = req.toolContext;
17326
+ const invocationContext = toolContext?.invocationContext;
17327
+ const contextKey = extractInvocationContextKey(invocationContext);
17328
+ const agentName = extractToolAgentName(req);
17329
+ if (contextKey && agentName) {
17330
+ const agentSpan = activeAgentSpans.get(
17331
+ agentContextKey(contextKey, agentName)
17332
+ );
17333
+ if (agentSpan) {
17334
+ return agentSpan;
17335
+ }
17336
+ }
17337
+ return contextKey ? activeRunnerSpans.get(contextKey) : void 0;
17338
+ }
17339
+ function finalizeRunnerSpan(state, activeRunnerSpans) {
17340
+ try {
17341
+ const lastEvent = getLastNonPartialEvent(state.events);
17342
+ const metrics = {};
17343
+ const end = getCurrentUnixTimestamp();
17344
+ metrics.start = state.startTime;
17345
+ metrics.end = end;
17346
+ metrics.duration = end - state.startTime;
17347
+ const usage = aggregateUsageFromEvents(state.events);
17348
+ if (usage) {
17349
+ populateUsageMetrics2(metrics, usage);
17350
+ }
17351
+ state.span.log({
17352
+ output: lastEvent ? extractEventOutput(lastEvent) : void 0,
17353
+ metrics: cleanMetrics2(metrics)
17354
+ });
17355
+ } finally {
17356
+ cleanupActiveRunnerSpan(state, activeRunnerSpans);
17357
+ state.span.end();
17358
+ }
17359
+ }
17360
+ function finalizeAgentSpan(state, activeAgentSpans) {
17361
+ try {
17362
+ const lastEvent = getLastNonPartialEvent(state.events);
17363
+ const metrics = {};
17364
+ const end = getCurrentUnixTimestamp();
17365
+ metrics.start = state.startTime;
17366
+ metrics.end = end;
17367
+ metrics.duration = end - state.startTime;
17368
+ state.span.log({
17369
+ output: lastEvent ? extractEventOutput(lastEvent) : void 0,
17370
+ metrics: cleanMetrics2(metrics)
17371
+ });
17372
+ } finally {
17373
+ cleanupActiveAgentSpan(state, activeAgentSpans);
17374
+ state.span.end();
17375
+ }
17376
+ }
17377
+ function getLastNonPartialEvent(events) {
17378
+ for (let i = events.length - 1; i >= 0; i--) {
17379
+ if (!events[i].partial) {
17380
+ return events[i];
17381
+ }
17382
+ }
17383
+ return events.length > 0 ? events[events.length - 1] : void 0;
17384
+ }
17385
+ function extractEventOutput(event) {
17386
+ if (!event.content) {
17387
+ return void 0;
17388
+ }
17389
+ const output = {};
17390
+ if (event.content.role) {
17391
+ output.role = event.content.role;
17392
+ }
17393
+ if (event.content.parts && Array.isArray(event.content.parts)) {
17394
+ const textParts = event.content.parts.filter((p) => p.text !== void 0 && !p.thought).map((p) => p.text);
17395
+ const thoughtParts = event.content.parts.filter((p) => p.text !== void 0 && p.thought).map((p) => p.text);
17396
+ const functionCalls = event.content.parts.filter((p) => p.functionCall).map((p) => p.functionCall);
17397
+ if (textParts.length > 0) {
17398
+ output.content = textParts.join("");
17399
+ }
17400
+ if (thoughtParts.length > 0) {
17401
+ output.thought = thoughtParts.join("");
17402
+ }
17403
+ if (functionCalls.length > 0) {
17404
+ output.functionCalls = functionCalls;
17405
+ }
17406
+ }
17407
+ if (event.author) {
17408
+ output.author = event.author;
17409
+ }
17410
+ return Object.keys(output).length > 0 ? output : void 0;
17411
+ }
17412
+ function aggregateUsageFromEvents(events) {
17413
+ let hasUsage = false;
17414
+ const aggregated = {};
17415
+ for (const event of events) {
17416
+ if (!event.usageMetadata) {
17417
+ continue;
17418
+ }
17419
+ hasUsage = true;
17420
+ const usage = event.usageMetadata;
17421
+ if (usage.promptTokenCount !== void 0) {
17422
+ aggregated.promptTokenCount = (aggregated.promptTokenCount ?? 0) + usage.promptTokenCount;
17423
+ }
17424
+ if (usage.candidatesTokenCount !== void 0) {
17425
+ aggregated.candidatesTokenCount = (aggregated.candidatesTokenCount ?? 0) + usage.candidatesTokenCount;
17426
+ }
17427
+ if (usage.totalTokenCount !== void 0) {
17428
+ aggregated.totalTokenCount = (aggregated.totalTokenCount ?? 0) + usage.totalTokenCount;
17429
+ }
17430
+ if (usage.cachedContentTokenCount !== void 0) {
17431
+ aggregated.cachedContentTokenCount = (aggregated.cachedContentTokenCount ?? 0) + usage.cachedContentTokenCount;
17432
+ }
17433
+ if (usage.thoughtsTokenCount !== void 0) {
17434
+ aggregated.thoughtsTokenCount = (aggregated.thoughtsTokenCount ?? 0) + usage.thoughtsTokenCount;
17435
+ }
17436
+ }
17437
+ return hasUsage ? aggregated : void 0;
17438
+ }
17439
+ function populateUsageMetrics2(metrics, usage) {
17440
+ if (usage.promptTokenCount !== void 0) {
17441
+ metrics.prompt_tokens = usage.promptTokenCount;
17442
+ }
17443
+ if (usage.candidatesTokenCount !== void 0) {
17444
+ metrics.completion_tokens = usage.candidatesTokenCount;
17445
+ }
17446
+ if (usage.totalTokenCount !== void 0) {
17447
+ metrics.tokens = usage.totalTokenCount;
17448
+ }
17449
+ if (usage.cachedContentTokenCount !== void 0) {
17450
+ metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
17451
+ }
17452
+ if (usage.thoughtsTokenCount !== void 0) {
17453
+ metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
17454
+ }
17455
+ }
17456
+ function cleanMetrics2(metrics) {
17457
+ const cleaned = {};
17458
+ for (const [key, value] of Object.entries(metrics)) {
17459
+ if (value !== null && value !== void 0) {
17460
+ cleaned[key] = value;
17461
+ }
17462
+ }
17463
+ return cleaned;
17464
+ }
17465
+
17466
+ // src/instrumentation/plugins/cohere-channels.ts
17467
+ var cohereChannels = defineChannels("cohere-ai", {
17468
+ chat: channel({
17469
+ channelName: "chat",
17470
+ kind: "async"
17471
+ }),
17472
+ chatStream: channel({
17473
+ channelName: "chatStream",
17474
+ kind: "async"
17475
+ }),
17476
+ embed: channel({
17477
+ channelName: "embed",
17478
+ kind: "async"
17479
+ }),
17480
+ rerank: channel({
17481
+ channelName: "rerank",
17482
+ kind: "async"
17483
+ })
17484
+ });
17485
+
17486
+ // src/instrumentation/plugins/cohere-plugin.ts
17487
+ var CoherePlugin = class extends BasePlugin {
17488
+ onEnable() {
17489
+ this.subscribeToCohereChannels();
17490
+ }
17491
+ onDisable() {
17492
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
17493
+ }
17494
+ subscribeToCohereChannels() {
17495
+ this.unsubscribers.push(
17496
+ traceStreamingChannel(cohereChannels.chat, {
17497
+ name: "cohere.chat",
17498
+ type: "llm" /* LLM */,
17499
+ extractInput: extractChatInputWithMetadata2,
17500
+ extractOutput: (result) => extractCohereChatOutput(result),
17501
+ extractMetadata: (result) => extractCohereResponseMetadata(result),
17502
+ extractMetrics: (result, startTime) => {
17503
+ const metrics = parseCohereMetricsFromUsage(result);
17504
+ if (startTime) {
17505
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
17506
+ }
17507
+ return metrics;
17508
+ }
17509
+ })
17510
+ );
17511
+ this.unsubscribers.push(
17512
+ traceStreamingChannel(cohereChannels.chatStream, {
17513
+ name: "cohere.chatStream",
17514
+ type: "llm" /* LLM */,
17515
+ extractInput: extractChatInputWithMetadata2,
17516
+ extractOutput: () => void 0,
17517
+ extractMetadata: () => void 0,
17518
+ extractMetrics: () => ({}),
17519
+ aggregateChunks: aggregateCohereChatStreamChunks
17520
+ })
17521
+ );
17522
+ this.unsubscribers.push(
17523
+ traceAsyncChannel(cohereChannels.embed, {
17524
+ name: "cohere.embed",
17525
+ type: "llm" /* LLM */,
17526
+ extractInput: extractEmbedInputWithMetadata,
17527
+ extractOutput: extractCohereEmbeddingOutput,
17528
+ extractMetadata: (result) => extractCohereResponseMetadata(result),
17529
+ extractMetrics: (result) => parseCohereMetricsFromUsage(result)
17530
+ })
17531
+ );
17532
+ this.unsubscribers.push(
17533
+ traceAsyncChannel(cohereChannels.rerank, {
17534
+ name: "cohere.rerank",
17535
+ type: "llm" /* LLM */,
17536
+ extractInput: extractRerankInputWithMetadata,
17537
+ extractOutput: (result) => {
17538
+ if (!isObject(result) || !Array.isArray(result.results)) {
17539
+ return void 0;
17540
+ }
17541
+ return result.results.slice(0, 100).map((item) => ({
17542
+ index: isObject(item) ? item.index : void 0,
17543
+ relevance_score: isObject(item) ? (typeof item.relevanceScore === "number" ? item.relevanceScore : item.relevance_score) ?? null : null
17544
+ }));
17545
+ },
17546
+ extractMetadata: (result) => extractCohereResponseMetadata(result),
17547
+ extractMetrics: (result) => parseCohereMetricsFromUsage(result)
17548
+ })
17549
+ );
17550
+ }
17551
+ };
17552
+ var CHAT_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
17553
+ "conversationId",
17554
+ "conversation_id",
17555
+ "frequencyPenalty",
17556
+ "frequency_penalty",
17557
+ "k",
17558
+ "maxInputTokens",
17559
+ "max_input_tokens",
17560
+ "maxTokens",
17561
+ "max_tokens",
17562
+ "model",
17563
+ "p",
17564
+ "preamble",
17565
+ "presencePenalty",
17566
+ "presence_penalty",
17567
+ "priority",
17568
+ "promptTruncation",
17569
+ "prompt_truncation",
17570
+ "rawPrompting",
17571
+ "raw_prompting",
17572
+ "responseFormat",
17573
+ "response_format",
17574
+ "safetyMode",
17575
+ "safety_mode",
17576
+ "searchQueriesOnly",
17577
+ "search_queries_only",
17578
+ "seed",
17579
+ "stopSequences",
17580
+ "stop_sequences",
17581
+ "strictTools",
17582
+ "strict_tools",
17583
+ "temperature",
17584
+ "toolChoice",
17585
+ "tool_choice"
17586
+ ]);
17587
+ var EMBED_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
17588
+ "embeddingTypes",
17589
+ "embedding_types",
17590
+ "inputType",
17591
+ "input_type",
17592
+ "maxTokens",
17593
+ "max_tokens",
17594
+ "model",
17595
+ "outputDimension",
17596
+ "output_dimension",
17597
+ "priority",
17598
+ "truncate"
17599
+ ]);
17600
+ var RERANK_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
17601
+ "maxChunksPerDoc",
17602
+ "max_chunks_per_doc",
17603
+ "maxTokensPerDoc",
17604
+ "max_tokens_per_doc",
17605
+ "model",
17606
+ "priority",
17607
+ "rankFields",
17608
+ "rank_fields",
17609
+ "returnDocuments",
17610
+ "return_documents",
17611
+ "topN",
17612
+ "top_n"
17613
+ ]);
17614
+ var RESPONSE_METADATA_ALLOWLIST2 = /* @__PURE__ */ new Set([
17615
+ "finishReason",
17616
+ "finish_reason",
17617
+ "generationId",
17618
+ "generation_id",
17619
+ "id",
17620
+ "responseId",
17621
+ "responseType",
17622
+ "response_id",
17623
+ "response_type"
17624
+ ]);
17625
+ function normalizeArgs5(args) {
17626
+ if (Array.isArray(args)) {
17627
+ return args;
17628
+ }
17629
+ if (isArrayLike5(args)) {
17630
+ return Array.from(args);
17631
+ }
17632
+ return [args];
17633
+ }
17634
+ function isArrayLike5(value) {
17635
+ return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
17636
+ }
17637
+ function getRequestArg(args) {
17638
+ const firstObjectArg = normalizeArgs5(args).find((arg) => isObject(arg));
17639
+ return isObject(firstObjectArg) ? firstObjectArg : void 0;
17640
+ }
17641
+ function addCohereProviderMetadata(metadata) {
17642
+ return {
17643
+ ...metadata,
17644
+ provider: "cohere"
17645
+ };
17646
+ }
17647
+ function pickAllowedMetadata2(metadata, allowlist) {
17648
+ if (!metadata) {
17649
+ return {};
17650
+ }
17651
+ const picked = {};
17652
+ for (const key of allowlist) {
17653
+ const value = metadata[key];
17654
+ if (value !== void 0) {
17655
+ picked[key] = value;
17656
+ }
17657
+ }
17658
+ return picked;
17659
+ }
17660
+ function extractChatInputWithMetadata2(args) {
17661
+ const request = getRequestArg(args);
17662
+ const { message, messages, ...rawMetadata } = request || {};
17663
+ return {
17664
+ input: processInputAttachments(messages ?? message),
17665
+ metadata: addCohereProviderMetadata(
17666
+ pickAllowedMetadata2(rawMetadata, CHAT_REQUEST_METADATA_ALLOWLIST)
17667
+ )
17668
+ };
17669
+ }
17670
+ function extractEmbedInputWithMetadata(args) {
17671
+ const request = getRequestArg(args);
17672
+ const { inputs, texts, images, ...rawMetadata } = request || {};
17673
+ return {
17674
+ input: inputs ?? texts ?? images,
17675
+ metadata: addCohereProviderMetadata(
17676
+ pickAllowedMetadata2(rawMetadata, EMBED_REQUEST_METADATA_ALLOWLIST)
17677
+ )
17678
+ };
17679
+ }
17680
+ function extractRerankInputWithMetadata(args) {
17681
+ const request = getRequestArg(args);
17682
+ const { query, documents, ...rawMetadata } = request || {};
17683
+ return {
17684
+ input: {
17685
+ documents,
17686
+ query
17687
+ },
17688
+ metadata: addCohereProviderMetadata({
17689
+ ...pickAllowedMetadata2(rawMetadata, RERANK_REQUEST_METADATA_ALLOWLIST),
17690
+ ...Array.isArray(documents) ? { document_count: documents.length } : {}
17691
+ })
17692
+ };
17693
+ }
17694
+ function extractCohereResponseMetadata(result) {
17695
+ if (!isObject(result)) {
17696
+ return void 0;
17697
+ }
17698
+ const responseMetadata = pickAllowedMetadata2(
17699
+ result,
17700
+ RESPONSE_METADATA_ALLOWLIST2
17701
+ );
17702
+ const meta = isObject(result.meta) ? result.meta : void 0;
17703
+ 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;
17704
+ const metadata = {
17705
+ ...responseMetadata,
17706
+ ...apiVersion ? { api_version: apiVersion } : {}
17707
+ };
17708
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
17709
+ }
17710
+ function extractCohereChatOutput(result) {
17711
+ if (!isObject(result)) {
17712
+ return void 0;
17713
+ }
17714
+ if (isObject(result.message)) {
17715
+ return result.message;
17716
+ }
17717
+ if (typeof result.text !== "string") {
17718
+ return void 0;
17719
+ }
17720
+ const toolCalls = Array.isArray(result.toolCalls) ? result.toolCalls : Array.isArray(result.tool_calls) ? result.tool_calls : void 0;
17721
+ if (toolCalls && toolCalls.length > 0) {
17722
+ return {
17723
+ content: result.text,
17724
+ role: "assistant",
17725
+ toolCalls
17726
+ };
17727
+ }
17728
+ return result.text;
17729
+ }
17730
+ function extractCohereEmbeddingOutput(result) {
17731
+ if (!isObject(result)) {
17732
+ return void 0;
17733
+ }
17734
+ const embeddingLength = getFirstEmbeddingLength(result.embeddings);
17735
+ if (embeddingLength === void 0) {
17736
+ return void 0;
17737
+ }
17738
+ return {
17739
+ embedding_length: embeddingLength
17740
+ };
17741
+ }
17742
+ function getFirstEmbeddingLength(value) {
17743
+ if (Array.isArray(value) && Array.isArray(value[0])) {
17744
+ return value[0].length;
17745
+ }
17746
+ if (!isObject(value)) {
17747
+ return void 0;
17748
+ }
17749
+ for (const key of Object.keys(value)) {
17750
+ const entry = value[key];
17751
+ if (Array.isArray(entry) && Array.isArray(entry[0])) {
17752
+ return entry[0].length;
17753
+ }
17754
+ }
17755
+ return void 0;
17756
+ }
17757
+ function setMetricIfNumber(metrics, key, value) {
17758
+ if (typeof value === "number" && Number.isFinite(value)) {
17759
+ metrics[key] = value;
17760
+ }
17761
+ }
17762
+ function mergeUsageMetrics(metrics, usage) {
17763
+ if (!isObject(usage)) {
17764
+ return metrics;
17765
+ }
17766
+ const source = usage;
17767
+ setMetricIfNumber(
17768
+ metrics,
17769
+ "prompt_tokens",
17770
+ source.inputTokens ?? source.input_tokens
17771
+ );
17772
+ setMetricIfNumber(
17773
+ metrics,
17774
+ "completion_tokens",
17775
+ source.outputTokens ?? source.output_tokens
17776
+ );
17777
+ setMetricIfNumber(
17778
+ metrics,
17779
+ "tokens",
17780
+ source.totalTokens ?? source.total_tokens
17781
+ );
17782
+ setMetricIfNumber(
17783
+ metrics,
17784
+ "prompt_cached_tokens",
17785
+ source.cachedTokens ?? source.cached_tokens
17786
+ );
17787
+ const tokenContainer = isObject(source.tokens) ? source.tokens : void 0;
17788
+ if (tokenContainer) {
17789
+ setMetricIfNumber(
17790
+ metrics,
17791
+ "prompt_tokens",
17792
+ tokenContainer.inputTokens ?? tokenContainer.input_tokens
17793
+ );
17794
+ setMetricIfNumber(
17795
+ metrics,
17796
+ "completion_tokens",
17797
+ tokenContainer.outputTokens ?? tokenContainer.output_tokens
17798
+ );
17799
+ setMetricIfNumber(
17800
+ metrics,
17801
+ "tokens",
17802
+ tokenContainer.totalTokens ?? tokenContainer.total_tokens
17803
+ );
17804
+ }
17805
+ const billedUnits = (isObject(source.billedUnits) ? source.billedUnits : void 0) || (isObject(source.billed_units) ? source.billed_units : void 0);
17806
+ if (billedUnits) {
17807
+ setMetricIfNumber(
17808
+ metrics,
17809
+ "prompt_tokens",
17810
+ billedUnits.inputTokens ?? billedUnits.input_tokens
17811
+ );
17812
+ setMetricIfNumber(
17813
+ metrics,
17814
+ "completion_tokens",
17815
+ billedUnits.outputTokens ?? billedUnits.output_tokens
17816
+ );
17817
+ setMetricIfNumber(
17818
+ metrics,
17819
+ "search_units",
17820
+ billedUnits.searchUnits ?? billedUnits.search_units
17821
+ );
17822
+ setMetricIfNumber(metrics, "classifications", billedUnits.classifications);
17823
+ setMetricIfNumber(metrics, "images", billedUnits.images);
17824
+ setMetricIfNumber(
17825
+ metrics,
17826
+ "image_tokens",
17827
+ billedUnits.imageTokens ?? billedUnits.image_tokens
17828
+ );
17829
+ }
17830
+ return metrics;
17831
+ }
17832
+ function parseCohereMetricsFromUsage(source) {
17833
+ if (!isObject(source)) {
17834
+ return {};
17835
+ }
17836
+ const metrics = {};
17837
+ mergeUsageMetrics(metrics, source);
17838
+ if ("usage" in source) {
17839
+ mergeUsageMetrics(metrics, source.usage);
17840
+ }
17841
+ if ("meta" in source) {
17842
+ mergeUsageMetrics(metrics, source.meta);
17843
+ }
17844
+ if (metrics.tokens === void 0 && typeof metrics.prompt_tokens === "number" && typeof metrics.completion_tokens === "number") {
17845
+ metrics.tokens = metrics.prompt_tokens + metrics.completion_tokens;
17846
+ }
17847
+ return metrics;
17848
+ }
17849
+ function toToolCallArray(value) {
17850
+ if (Array.isArray(value)) {
17851
+ return value.filter((item) => isObject(item));
17852
+ }
17853
+ return isObject(value) ? [value] : [];
17854
+ }
17855
+ function getToolCallIndex2(toolCall, fallbackIndex) {
17856
+ return typeof toolCall.index === "number" && Number.isInteger(toolCall.index) ? toolCall.index : fallbackIndex;
17857
+ }
17858
+ function appendToolCallDelta(existing, incoming) {
17859
+ const currentArguments = isObject(existing?.function) && typeof existing.function.arguments === "string" ? existing.function.arguments : "";
17860
+ const incomingArguments = isObject(incoming.function) && typeof incoming.function.arguments === "string" ? incoming.function.arguments : "";
17861
+ return {
17862
+ ...existing,
17863
+ ...incoming,
17864
+ function: {
17865
+ ...isObject(existing?.function) ? existing.function : {},
17866
+ ...isObject(incoming.function) ? incoming.function : {},
17867
+ ...incomingArguments ? { arguments: `${currentArguments}${incomingArguments}` } : {}
17868
+ }
17869
+ };
17870
+ }
17871
+ function extractV8DeltaText(chunk) {
17872
+ if (!isObject(chunk.delta) || !isObject(chunk.delta.message)) {
17873
+ return void 0;
17874
+ }
17875
+ const content = chunk.delta.message.content;
17876
+ if (typeof content === "string") {
17877
+ return content;
17878
+ }
17879
+ if (isObject(content) && typeof content.text === "string") {
17880
+ return content.text;
17881
+ }
17882
+ return void 0;
17883
+ }
17884
+ function aggregateCohereChatStreamChunks(chunks) {
17885
+ const textDeltas = [];
17886
+ const toolCallsByIndex = {};
17887
+ const toolCallOrder = [];
17888
+ let terminalResponse;
17889
+ let role;
17890
+ let finishReason;
17891
+ let metadata = {};
17892
+ let metrics = {};
17893
+ for (const chunk of chunks) {
17894
+ if (!isObject(chunk)) {
17895
+ continue;
17896
+ }
17897
+ const eventType = typeof chunk.eventType === "string" ? chunk.eventType : typeof chunk.event_type === "string" ? chunk.event_type : typeof chunk.type === "string" ? chunk.type : void 0;
17898
+ if (eventType === "text-generation" && typeof chunk.text === "string") {
17899
+ textDeltas.push(chunk.text);
17900
+ continue;
17901
+ }
17902
+ if (eventType === "tool-calls-generation") {
17903
+ const generatedToolCalls = toToolCallArray(
17904
+ Array.isArray(chunk.toolCalls) ? chunk.toolCalls : chunk.tool_calls
17905
+ );
17906
+ for (const [index, toolCall] of generatedToolCalls.entries()) {
17907
+ const normalizedIndex = getToolCallIndex2(toolCall, index);
17908
+ if (!toolCallOrder.includes(normalizedIndex)) {
17909
+ toolCallOrder.push(normalizedIndex);
17910
+ }
17911
+ toolCallsByIndex[normalizedIndex] = {
17912
+ ...toolCallsByIndex[normalizedIndex],
17913
+ ...toolCall
17914
+ };
17915
+ }
17916
+ if (typeof chunk.text === "string") {
17917
+ textDeltas.push(chunk.text);
17918
+ }
17919
+ continue;
17920
+ }
17921
+ if (eventType === "stream-end" && isObject(chunk.response)) {
17922
+ terminalResponse = chunk.response;
17923
+ metrics = {
17924
+ ...metrics,
17925
+ ...parseCohereMetricsFromUsage(chunk.response)
17926
+ };
17927
+ metadata = {
17928
+ ...metadata,
17929
+ ...extractCohereResponseMetadata(chunk.response) || {}
17930
+ };
17931
+ const responseFinishReason = typeof chunk.response.finishReason === "string" ? chunk.response.finishReason : typeof chunk.response.finish_reason === "string" ? chunk.response.finish_reason : void 0;
17932
+ finishReason = responseFinishReason ?? finishReason;
17933
+ continue;
17934
+ }
17935
+ if (eventType === "message-start") {
17936
+ if (typeof chunk.id === "string") {
17937
+ metadata.id = chunk.id;
17938
+ }
17939
+ if (isObject(chunk.delta) && isObject(chunk.delta.message)) {
17940
+ const messageRole = chunk.delta.message.role;
17941
+ if (typeof messageRole === "string") {
17942
+ role = messageRole;
17943
+ }
17944
+ }
17945
+ continue;
17946
+ }
17947
+ if (eventType === "content-delta") {
17948
+ const text = extractV8DeltaText(chunk);
17949
+ if (text) {
17950
+ textDeltas.push(text);
17951
+ }
17952
+ continue;
17953
+ }
17954
+ if (eventType === "tool-call-start") {
17955
+ const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
17956
+ Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
17957
+ ) : [];
17958
+ for (const [index, toolCall] of toolCalls.entries()) {
17959
+ const normalizedIndex = getToolCallIndex2(
17960
+ toolCall,
17961
+ typeof chunk.index === "number" ? chunk.index : index
17962
+ );
17963
+ if (!toolCallOrder.includes(normalizedIndex)) {
17964
+ toolCallOrder.push(normalizedIndex);
17965
+ }
17966
+ toolCallsByIndex[normalizedIndex] = {
17967
+ ...toolCallsByIndex[normalizedIndex],
17968
+ ...toolCall
17969
+ };
17970
+ }
17971
+ continue;
17972
+ }
17973
+ if (eventType === "tool-call-delta") {
17974
+ const toolCallDelta = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
17975
+ chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
17976
+ ) : [];
17977
+ if (toolCallDelta.length > 0) {
17978
+ const delta = toolCallDelta[0];
17979
+ const normalizedIndex = getToolCallIndex2(delta, chunk.index ?? 0);
17980
+ if (!toolCallOrder.includes(normalizedIndex)) {
17981
+ toolCallOrder.push(normalizedIndex);
17982
+ }
17983
+ toolCallsByIndex[normalizedIndex] = appendToolCallDelta(
17984
+ toolCallsByIndex[normalizedIndex],
17985
+ delta
17986
+ );
17987
+ }
17988
+ continue;
17989
+ }
17990
+ if (eventType === "message-end" && isObject(chunk.delta)) {
17991
+ const delta = chunk.delta;
17992
+ if (typeof delta.finishReason === "string") {
17993
+ finishReason = delta.finishReason;
17994
+ } else if (typeof delta.finish_reason === "string") {
17995
+ finishReason = delta.finish_reason;
17996
+ }
17997
+ if (delta.error !== void 0) {
17998
+ metadata.error = delta.error;
17999
+ }
18000
+ metrics = {
18001
+ ...metrics,
18002
+ ...parseCohereMetricsFromUsage(delta.usage)
18003
+ };
18004
+ }
18005
+ }
18006
+ const mergedToolCalls = toolCallOrder.sort((left, right) => left - right).map((index) => toolCallsByIndex[index]).filter((toolCall) => isObject(toolCall));
18007
+ let output = extractCohereChatOutput(terminalResponse);
18008
+ if (output === void 0) {
18009
+ const mergedText = textDeltas.join("");
18010
+ if (mergedToolCalls.length > 0 || role || mergedText.length > 0) {
18011
+ output = {
18012
+ ...role ? { role } : {},
18013
+ ...mergedText.length > 0 ? { content: mergedText } : {},
18014
+ ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
18015
+ };
18016
+ }
18017
+ }
18018
+ if (finishReason) {
18019
+ metadata = {
18020
+ ...metadata,
18021
+ finish_reason: finishReason
18022
+ };
18023
+ }
18024
+ return {
18025
+ metadata,
18026
+ metrics,
18027
+ output
18028
+ };
18029
+ }
18030
+
18031
+ // src/instrumentation/braintrust-plugin.ts
18032
+ var BraintrustPlugin = class extends BasePlugin {
18033
+ config;
18034
+ openaiPlugin = null;
18035
+ anthropicPlugin = null;
18036
+ aiSDKPlugin = null;
18037
+ claudeAgentSDKPlugin = null;
18038
+ googleGenAIPlugin = null;
18039
+ huggingFacePlugin = null;
18040
+ openRouterPlugin = null;
18041
+ openRouterAgentPlugin = null;
18042
+ mistralPlugin = null;
18043
+ googleADKPlugin = null;
18044
+ coherePlugin = null;
18045
+ constructor(config = {}) {
18046
+ super();
18047
+ this.config = config;
18048
+ }
18049
+ onEnable() {
18050
+ const integrations = this.config.integrations || {};
18051
+ if (integrations.openai !== false) {
18052
+ this.openaiPlugin = new OpenAIPlugin();
18053
+ this.openaiPlugin.enable();
18054
+ }
18055
+ if (integrations.anthropic !== false) {
18056
+ this.anthropicPlugin = new AnthropicPlugin();
18057
+ this.anthropicPlugin.enable();
18058
+ }
18059
+ if (integrations.aisdk !== false && integrations.vercel !== false) {
18060
+ this.aiSDKPlugin = new AISDKPlugin();
18061
+ this.aiSDKPlugin.enable();
18062
+ }
18063
+ if (integrations.claudeAgentSDK !== false) {
18064
+ this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
18065
+ this.claudeAgentSDKPlugin.enable();
18066
+ }
18067
+ if (integrations.googleGenAI !== false && integrations.google !== false) {
18068
+ this.googleGenAIPlugin = new GoogleGenAIPlugin();
18069
+ this.googleGenAIPlugin.enable();
18070
+ }
18071
+ if (integrations.huggingface !== false) {
18072
+ this.huggingFacePlugin = new HuggingFacePlugin();
18073
+ this.huggingFacePlugin.enable();
18074
+ }
18075
+ if (integrations.openrouter !== false) {
18076
+ this.openRouterPlugin = new OpenRouterPlugin();
18077
+ this.openRouterPlugin.enable();
18078
+ }
18079
+ if (integrations.openrouterAgent !== false) {
18080
+ this.openRouterAgentPlugin = new OpenRouterAgentPlugin();
18081
+ this.openRouterAgentPlugin.enable();
18082
+ }
18083
+ if (integrations.mistral !== false) {
18084
+ this.mistralPlugin = new MistralPlugin();
18085
+ this.mistralPlugin.enable();
18086
+ }
18087
+ if (integrations.googleADK !== false) {
18088
+ this.googleADKPlugin = new GoogleADKPlugin();
18089
+ this.googleADKPlugin.enable();
18090
+ }
18091
+ if (integrations.cohere !== false) {
18092
+ this.coherePlugin = new CoherePlugin();
18093
+ this.coherePlugin.enable();
18094
+ }
18095
+ }
18096
+ onDisable() {
18097
+ if (this.openaiPlugin) {
18098
+ this.openaiPlugin.disable();
18099
+ this.openaiPlugin = null;
18100
+ }
18101
+ if (this.anthropicPlugin) {
18102
+ this.anthropicPlugin.disable();
18103
+ this.anthropicPlugin = null;
18104
+ }
18105
+ if (this.aiSDKPlugin) {
18106
+ this.aiSDKPlugin.disable();
18107
+ this.aiSDKPlugin = null;
18108
+ }
18109
+ if (this.claudeAgentSDKPlugin) {
18110
+ this.claudeAgentSDKPlugin.disable();
18111
+ this.claudeAgentSDKPlugin = null;
18112
+ }
18113
+ if (this.googleGenAIPlugin) {
18114
+ this.googleGenAIPlugin.disable();
18115
+ this.googleGenAIPlugin = null;
18116
+ }
18117
+ if (this.huggingFacePlugin) {
18118
+ this.huggingFacePlugin.disable();
18119
+ this.huggingFacePlugin = null;
18120
+ }
18121
+ if (this.openRouterPlugin) {
18122
+ this.openRouterPlugin.disable();
18123
+ this.openRouterPlugin = null;
18124
+ }
18125
+ if (this.openRouterAgentPlugin) {
18126
+ this.openRouterAgentPlugin.disable();
18127
+ this.openRouterAgentPlugin = null;
18128
+ }
18129
+ if (this.mistralPlugin) {
18130
+ this.mistralPlugin.disable();
18131
+ this.mistralPlugin = null;
18132
+ }
18133
+ if (this.googleADKPlugin) {
18134
+ this.googleADKPlugin.disable();
18135
+ this.googleADKPlugin = null;
18136
+ }
18137
+ if (this.coherePlugin) {
18138
+ this.coherePlugin.disable();
18139
+ this.coherePlugin = null;
15268
18140
  }
15269
18141
  }
15270
18142
  };
@@ -15337,10 +18209,12 @@ var PluginRegistry = class {
15337
18209
  vercel: true,
15338
18210
  aisdk: true,
15339
18211
  google: true,
18212
+ huggingface: true,
15340
18213
  claudeAgentSDK: true,
15341
18214
  openrouter: true,
15342
18215
  openrouterAgent: true,
15343
- mistral: true
18216
+ mistral: true,
18217
+ cohere: true
15344
18218
  };
15345
18219
  }
15346
18220
  /**