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
package/dist/cli.js CHANGED
@@ -1232,12 +1232,12 @@ var require_package = __commonJS({
1232
1232
  "package.json"(exports2, module2) {
1233
1233
  module2.exports = {
1234
1234
  name: "braintrust",
1235
- version: "3.8.0",
1235
+ version: "3.9.0",
1236
1236
  description: "SDK for integrating Braintrust",
1237
1237
  repository: {
1238
1238
  type: "git",
1239
1239
  url: "git+https://github.com/braintrustdata/braintrust-sdk-javascript.git",
1240
- directory: "blob/main/js"
1240
+ directory: "js"
1241
1241
  },
1242
1242
  homepage: "https://www.braintrust.dev/docs",
1243
1243
  main: "./dist/index.js",
@@ -1375,7 +1375,6 @@ var require_package = __commonJS({
1375
1375
  "test:vitest": "pnpm --filter @braintrust/vitest-wrapper-tests test",
1376
1376
  "test:output": "tsx scripts/test-output.ts --with-comparison --with-metrics --with-progress",
1377
1377
  bench: "tsx src/queue.bench.ts",
1378
- "publish:validate": "./scripts/validate-release.sh && pnpm install --frozen-lockfile && pnpm run build && pnpm publish",
1379
1378
  lint: "eslint .",
1380
1379
  "fix:lint": "eslint --fix .",
1381
1380
  playground: "tsx playground.ts",
@@ -1388,6 +1387,7 @@ var require_package = __commonJS({
1388
1387
  devDependencies: {
1389
1388
  "@ai-sdk/anthropic": "2.0.37",
1390
1389
  "@anthropic-ai/sdk": "^0.60.0",
1390
+ "@google/adk": "^0.6.1",
1391
1391
  "@google/genai": "^1.25.0",
1392
1392
  "@jest/globals": "^29.7.0",
1393
1393
  "@nodelib/fs.walk": "^1.2.8",
@@ -1423,7 +1423,7 @@ var require_package = __commonJS({
1423
1423
  typedoc: "^0.25.13",
1424
1424
  "typedoc-plugin-markdown": "^3.17.1",
1425
1425
  typescript: "5.4.4",
1426
- vite: "^6.4.1",
1426
+ vite: "^6.4.2",
1427
1427
  "vite-tsconfig-paths": "^4.3.2",
1428
1428
  vitest: "^4.1.2",
1429
1429
  webpack: "^5.97.1",
@@ -1431,7 +1431,7 @@ var require_package = __commonJS({
1431
1431
  },
1432
1432
  dependencies: {
1433
1433
  "@ai-sdk/provider": "^1.1.3",
1434
- "@apm-js-collab/code-transformer": "^0.9.0",
1434
+ "@apm-js-collab/code-transformer": "^0.12.0",
1435
1435
  "@next/env": "^14.2.3",
1436
1436
  "@vercel/functions": "^1.0.2",
1437
1437
  ajv: "^8.17.1",
@@ -1441,7 +1441,7 @@ var require_package = __commonJS({
1441
1441
  "cli-progress": "^3.12.0",
1442
1442
  "cli-table3": "^0.6.5",
1443
1443
  cors: "^2.8.5",
1444
- "dc-browser": "^1.0.3",
1444
+ "dc-browser": "^1.0.4",
1445
1445
  dotenv: "^16.4.5",
1446
1446
  esbuild: "^0.27.0",
1447
1447
  "eventsource-parser": "^1.1.2",
@@ -1461,6 +1461,11 @@ var require_package = __commonJS({
1461
1461
  },
1462
1462
  peerDependencies: {
1463
1463
  zod: "^3.25.34 || ^4.0"
1464
+ },
1465
+ publishConfig: {
1466
+ access: "public",
1467
+ registry: "https://registry.npmjs.org/",
1468
+ provenance: true
1464
1469
  }
1465
1470
  };
1466
1471
  }
@@ -2400,6 +2405,9 @@ function isObjectOrArray(value) {
2400
2405
  function isEmpty(a) {
2401
2406
  return a === void 0 || a === null;
2402
2407
  }
2408
+ function isPromiseLike(value) {
2409
+ return value != null && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
2410
+ }
2403
2411
 
2404
2412
  // util/object_util.ts
2405
2413
  var SET_UNION_FIELDS = /* @__PURE__ */ new Set(["tags"]);
@@ -3508,7 +3516,11 @@ var CodeBundle = import_v36.z.object({
3508
3516
  eval_name: import_v36.z.string(),
3509
3517
  position: import_v36.z.union([
3510
3518
  import_v36.z.object({ type: import_v36.z.literal("task") }),
3511
- import_v36.z.object({ type: import_v36.z.literal("scorer"), index: import_v36.z.number().int().gte(0) })
3519
+ import_v36.z.object({ type: import_v36.z.literal("scorer"), index: import_v36.z.number().int().gte(0) }),
3520
+ import_v36.z.object({
3521
+ type: import_v36.z.literal("classifier"),
3522
+ index: import_v36.z.number().int().gte(0)
3523
+ })
3512
3524
  ])
3513
3525
  }),
3514
3526
  import_v36.z.object({ type: import_v36.z.literal("function"), index: import_v36.z.number().int().gte(0) }),
@@ -4630,11 +4642,15 @@ var RunEval = import_v36.z.object({
4630
4642
  data: import_v36.z.union([
4631
4643
  import_v36.z.object({
4632
4644
  dataset_id: import_v36.z.string(),
4645
+ dataset_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4646
+ dataset_environment: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4633
4647
  _internal_btql: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional()
4634
4648
  }),
4635
4649
  import_v36.z.object({
4636
4650
  project_name: import_v36.z.string(),
4637
4651
  dataset_name: import_v36.z.string(),
4652
+ dataset_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4653
+ dataset_environment: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
4638
4654
  _internal_btql: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional()
4639
4655
  }),
4640
4656
  import_v36.z.object({ data: import_v36.z.array(import_v36.z.unknown()) })
@@ -4762,6 +4778,7 @@ var ViewOptions = import_v36.z.union([
4762
4778
  rowHeight: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
4763
4779
  tallGroupRows: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]),
4764
4780
  layout: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
4781
+ topicMapReportKey: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
4765
4782
  chartHeight: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]),
4766
4783
  excludedMeasures: import_v36.z.union([
4767
4784
  import_v36.z.array(
@@ -4804,6 +4821,7 @@ var ViewOptions = import_v36.z.union([
4804
4821
  import_v36.z.null()
4805
4822
  ]),
4806
4823
  queryShape: import_v36.z.union([import_v36.z.enum(["traces", "spans"]), import_v36.z.null()]),
4824
+ cluster: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
4807
4825
  freezeColumns: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()])
4808
4826
  }).partial(),
4809
4827
  import_v36.z.null()
@@ -8441,8 +8459,9 @@ function validateAndSanitizeExperimentLogPartialArgs(event) {
8441
8459
  }
8442
8460
  function deepCopyEvent(event) {
8443
8461
  const attachments = [];
8444
- const IDENTIFIER = "_bt_internal_saved_attachment";
8445
- const savedAttachmentSchema = import_v38.z.strictObject({ [IDENTIFIER]: import_v38.z.number() });
8462
+ const ATTACHMENT_INDEX_KEY = "_bt_internal_saved_attachment_idx";
8463
+ const ATTACHMENT_MARKER_KEY = "_bt_internal_saved_attachment_marker";
8464
+ const attachmentMarker = ++deepCopyEventMarkerCounter;
8446
8465
  const serialized = JSON.stringify(event, (_k, v) => {
8447
8466
  if (v instanceof SpanImpl || v instanceof NoopSpan) {
8448
8467
  return `<span>`;
@@ -8454,21 +8473,39 @@ function deepCopyEvent(event) {
8454
8473
  return `<logger>`;
8455
8474
  } else if (v instanceof BaseAttachment) {
8456
8475
  const idx = attachments.push(v);
8457
- return { [IDENTIFIER]: idx - 1 };
8476
+ return {
8477
+ [ATTACHMENT_INDEX_KEY]: idx - 1,
8478
+ [ATTACHMENT_MARKER_KEY]: attachmentMarker
8479
+ };
8458
8480
  } else if (v instanceof ReadonlyAttachment) {
8459
8481
  return v.reference;
8460
8482
  }
8461
8483
  return v;
8462
8484
  });
8463
8485
  const x = JSON.parse(serialized, (_k, v) => {
8464
- const parsedAttachment = savedAttachmentSchema.safeParse(v);
8465
- if (parsedAttachment.success) {
8466
- return attachments[parsedAttachment.data[IDENTIFIER]];
8486
+ if (isDeepCopyAttachmentPlaceholder(v, attachmentMarker)) {
8487
+ return attachments[v[ATTACHMENT_INDEX_KEY]];
8467
8488
  }
8468
8489
  return v;
8469
8490
  });
8470
8491
  return x;
8471
8492
  }
8493
+ var deepCopyEventMarkerCounter = 0;
8494
+ function isDeepCopyAttachmentPlaceholder(value, attachmentMarker) {
8495
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
8496
+ return false;
8497
+ }
8498
+ const record = value;
8499
+ if (!Object.hasOwn(record, "_bt_internal_saved_attachment_idx") || !Object.hasOwn(record, "_bt_internal_saved_attachment_marker")) {
8500
+ return false;
8501
+ }
8502
+ if (Object.keys(record).length !== 2) {
8503
+ return false;
8504
+ }
8505
+ const attachmentIndex = record._bt_internal_saved_attachment_idx;
8506
+ const marker = record._bt_internal_saved_attachment_marker;
8507
+ return Number.isInteger(attachmentIndex) && attachmentIndex >= 0 && marker === attachmentMarker;
8508
+ }
8472
8509
  function extractAttachments(event, attachments) {
8473
8510
  for (const [key, value] of Object.entries(event)) {
8474
8511
  if (!value) {
@@ -11909,7 +11946,88 @@ function evaluateFilter(object, filter2) {
11909
11946
  function scorerName(scorer, scorer_idx) {
11910
11947
  return scorer.name || `scorer_${scorer_idx}`;
11911
11948
  }
11949
+ function classifierName(classifier, classifier_idx) {
11950
+ return classifier.name || `classifier_${classifier_idx}`;
11951
+ }
11952
+ function buildSpanMetadata(results) {
11953
+ return results.length === 1 ? results[0].metadata : results.reduce(
11954
+ (prev, s) => mergeDicts(prev, { [s.name]: s.metadata }),
11955
+ {}
11956
+ );
11957
+ }
11958
+ function buildSpanScores(results) {
11959
+ const scoresRecord = results.reduce(
11960
+ (prev, s) => mergeDicts(prev, { [s.name]: s.score }),
11961
+ {}
11962
+ );
11963
+ return { resultMetadata: buildSpanMetadata(results), scoresRecord };
11964
+ }
11965
+ async function runInScorerSpan(rootSpan, spanName, spanType, propagatedEvent, eventInput, fn) {
11966
+ try {
11967
+ const value = await rootSpan.traced(fn, {
11968
+ name: spanName,
11969
+ spanAttributes: { type: spanType, purpose: "scorer" },
11970
+ propagatedEvent,
11971
+ event: { input: eventInput }
11972
+ });
11973
+ return { kind: "score", value };
11974
+ } catch (e) {
11975
+ return { kind: "error", value: e };
11976
+ }
11977
+ }
11978
+ function collectScoringResults(runResults, names, onResult) {
11979
+ const failing = [];
11980
+ runResults.forEach((r, i) => {
11981
+ if (r.kind === "score") {
11982
+ (r.value ?? []).forEach(onResult);
11983
+ } else {
11984
+ failing.push({ name: names[i], error: r.value });
11985
+ }
11986
+ });
11987
+ return failing;
11988
+ }
11989
+ function validateClassificationResult(value, scorerName2) {
11990
+ if (!(typeof value === "object" && value !== null && !isEmpty2(value))) {
11991
+ throw new Error(
11992
+ `When returning structured classifier results, each classification must be a non-empty object. Got: ${JSON.stringify(value)}`
11993
+ );
11994
+ }
11995
+ if (!("name" in value) || typeof value.name !== "string" || !value.name) {
11996
+ const classification = value;
11997
+ classification.name = scorerName2;
11998
+ return classification;
11999
+ }
12000
+ return value;
12001
+ }
12002
+ function toClassificationItem(c) {
12003
+ return {
12004
+ id: c.id,
12005
+ label: c.label ?? c.id,
12006
+ ...c.metadata !== void 0 ? { metadata: c.metadata } : {}
12007
+ };
12008
+ }
12009
+ function logScoringFailures(kind, failures, metadata, rootSpan, state) {
12010
+ if (!failures.length) return [];
12011
+ const errorMap = Object.fromEntries(
12012
+ failures.map(({ name, error: error2 }) => [
12013
+ name,
12014
+ error2 instanceof Error ? error2.stack : `${error2}`
12015
+ ])
12016
+ );
12017
+ metadata[`${kind}_errors`] = errorMap;
12018
+ rootSpan.log({ metadata: { [`${kind}_errors`]: errorMap } });
12019
+ debugLogger.forState(state).warn(
12020
+ `Found exceptions for the following ${kind}s: ${Object.keys(errorMap).join(", ")}`,
12021
+ failures.map((f) => f.error)
12022
+ );
12023
+ return Object.keys(errorMap);
12024
+ }
11912
12025
  async function runEvaluator(experiment, evaluator, progressReporter, filters, stream, parameters, collectResults = true, enableCache = true) {
12026
+ if (!evaluator.scores && !evaluator.classifiers) {
12027
+ throw new Error(
12028
+ "Evaluator must include at least one of `scores` or `classifiers`"
12029
+ );
12030
+ }
11913
12031
  return await runEvaluatorInternal(
11914
12032
  experiment,
11915
12033
  evaluator,
@@ -12047,7 +12165,11 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
12047
12165
  let error2 = void 0;
12048
12166
  let tags = [...datum.tags ?? []];
12049
12167
  const scores = {};
12050
- const scorerNames = evaluator.scores.map(scorerName);
12168
+ const classifications = {};
12169
+ const scorerNames = (evaluator.scores ?? []).map(scorerName);
12170
+ const classifierNames = (evaluator.classifiers ?? []).map(
12171
+ classifierName
12172
+ );
12051
12173
  let unhandledScores = scorerNames;
12052
12174
  try {
12053
12175
  const meta = (o) => metadata = { ...metadata, ...o };
@@ -12101,106 +12223,131 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
12101
12223
  output,
12102
12224
  trace
12103
12225
  };
12104
- const scoreResults = await Promise.all(
12105
- evaluator.scores.map(async (score, score_idx) => {
12106
- try {
12107
- const runScorer = async (span) => {
12108
- const scoreResult = score(scoringArgs);
12109
- const scoreValue = scoreResult instanceof Promise ? await scoreResult : scoreResult;
12110
- if (scoreValue === null) {
12111
- return null;
12112
- }
12113
- if (Array.isArray(scoreValue)) {
12114
- for (const s of scoreValue) {
12115
- if (!(typeof s === "object" && !isEmpty2(s))) {
12116
- throw new Error(
12117
- `When returning an array of scores, each score must be a non-empty object. Got: ${JSON.stringify(
12118
- s
12119
- )}`
12120
- );
12226
+ const { trace: _trace, ...scoringArgsForLogging } = scoringArgs;
12227
+ const propagatedEvent = makeScorerPropagatedEvent(
12228
+ await rootSpan.export()
12229
+ );
12230
+ const getOtherFields = (s) => {
12231
+ const { metadata: _metadata, name: _name, ...rest } = s;
12232
+ return rest;
12233
+ };
12234
+ const [scoreResults, classificationResults] = await Promise.all([
12235
+ Promise.all(
12236
+ (evaluator.scores ?? []).map(
12237
+ (score, score_idx) => runInScorerSpan(
12238
+ rootSpan,
12239
+ scorerNames[score_idx],
12240
+ "score" /* SCORE */,
12241
+ propagatedEvent,
12242
+ scoringArgsForLogging,
12243
+ async (span) => {
12244
+ const scoreValue = await Promise.resolve(
12245
+ score(scoringArgs)
12246
+ );
12247
+ if (scoreValue === null) return null;
12248
+ if (Array.isArray(scoreValue)) {
12249
+ for (const s of scoreValue) {
12250
+ if (!(typeof s === "object" && !isEmpty2(s))) {
12251
+ throw new Error(
12252
+ `When returning an array of scores, each score must be a non-empty object. Got: ${JSON.stringify(s)}`
12253
+ );
12254
+ }
12121
12255
  }
12122
12256
  }
12257
+ const results = Array.isArray(scoreValue) ? scoreValue : typeof scoreValue === "object" && !isEmpty2(scoreValue) ? [scoreValue] : [
12258
+ {
12259
+ name: scorerNames[score_idx],
12260
+ score: scoreValue
12261
+ }
12262
+ ];
12263
+ const { resultMetadata, scoresRecord } = buildSpanScores(results);
12264
+ const resultOutput = results.length === 1 ? getOtherFields(results[0]) : results.reduce(
12265
+ (prev, s) => mergeDicts(prev, {
12266
+ [s.name]: getOtherFields(s)
12267
+ }),
12268
+ {}
12269
+ );
12270
+ span.log({
12271
+ output: resultOutput,
12272
+ metadata: resultMetadata,
12273
+ scores: scoresRecord
12274
+ });
12275
+ return results;
12123
12276
  }
12124
- const results2 = Array.isArray(scoreValue) ? scoreValue : typeof scoreValue === "object" && !isEmpty2(scoreValue) ? [scoreValue] : [
12125
- {
12126
- name: scorerNames[score_idx],
12127
- score: scoreValue
12128
- }
12129
- ];
12130
- const getOtherFields = (s) => {
12131
- const { metadata: _metadata, name: _name, ...rest } = s;
12132
- return rest;
12133
- };
12134
- const resultMetadata = results2.length === 1 ? results2[0].metadata : results2.reduce(
12135
- (prev, s) => mergeDicts(prev, {
12136
- [s.name]: s.metadata
12137
- }),
12138
- {}
12139
- );
12140
- const resultOutput = results2.length === 1 ? getOtherFields(results2[0]) : results2.reduce(
12141
- (prev, s) => mergeDicts(prev, { [s.name]: getOtherFields(s) }),
12142
- {}
12143
- );
12144
- const scores2 = results2.reduce(
12145
- (prev, s) => mergeDicts(prev, { [s.name]: s.score }),
12146
- {}
12147
- );
12148
- span.log({
12149
- output: resultOutput,
12150
- metadata: resultMetadata,
12151
- scores: scores2
12152
- });
12153
- return results2;
12154
- };
12155
- const { trace: _trace, ...scoringArgsForLogging } = scoringArgs;
12156
- const results = await rootSpan.traced(runScorer, {
12157
- name: scorerNames[score_idx],
12158
- spanAttributes: {
12159
- type: "score" /* SCORE */,
12160
- purpose: "scorer"
12161
- },
12162
- propagatedEvent: makeScorerPropagatedEvent(
12163
- await rootSpan.export()
12164
- ),
12165
- event: { input: scoringArgsForLogging }
12166
- });
12167
- return { kind: "score", value: results };
12168
- } catch (e) {
12169
- return { kind: "error", value: e };
12170
- }
12171
- })
12277
+ )
12278
+ )
12279
+ ),
12280
+ Promise.all(
12281
+ (evaluator.classifiers ?? []).map(
12282
+ (classifier, idx) => runInScorerSpan(
12283
+ rootSpan,
12284
+ classifierNames[idx],
12285
+ "classifier" /* CLASSIFIER */,
12286
+ propagatedEvent,
12287
+ scoringArgsForLogging,
12288
+ async (span) => {
12289
+ const classifierValue = await Promise.resolve(
12290
+ classifier(scoringArgs)
12291
+ );
12292
+ if (classifierValue === null) return null;
12293
+ const rawResults = (Array.isArray(classifierValue) ? classifierValue : [classifierValue]).map(
12294
+ (result) => validateClassificationResult(
12295
+ result,
12296
+ classifierNames[idx]
12297
+ )
12298
+ );
12299
+ const resultOutput = rawResults.length === 1 ? toClassificationItem(rawResults[0]) : rawResults.reduce(
12300
+ (prev, r) => mergeDicts(prev, {
12301
+ [r.name]: toClassificationItem(r)
12302
+ }),
12303
+ {}
12304
+ );
12305
+ span.log({
12306
+ output: resultOutput,
12307
+ metadata: buildSpanMetadata(rawResults)
12308
+ });
12309
+ return rawResults;
12310
+ }
12311
+ )
12312
+ )
12313
+ )
12314
+ ]);
12315
+ const failingScorers = collectScoringResults(
12316
+ scoreResults,
12317
+ scorerNames,
12318
+ (result) => {
12319
+ scores[result.name] = result.score;
12320
+ }
12172
12321
  );
12173
- const failingScorersAndResults = [];
12174
- scoreResults.forEach((results, i) => {
12175
- const name = scorerNames[i];
12176
- if (results.kind === "score") {
12177
- (results.value || []).forEach((result) => {
12178
- scores[result.name] = result.score;
12179
- });
12180
- } else {
12181
- failingScorersAndResults.push({ name, error: results.value });
12322
+ const failingClassifiers = collectScoringResults(
12323
+ classificationResults,
12324
+ classifierNames,
12325
+ (result) => {
12326
+ const item = toClassificationItem(result);
12327
+ if (!classifications[result.name]) {
12328
+ classifications[result.name] = [];
12329
+ }
12330
+ classifications[result.name].push(item);
12182
12331
  }
12183
- });
12184
- unhandledScores = null;
12185
- if (failingScorersAndResults.length) {
12186
- const scorerErrors = Object.fromEntries(
12187
- failingScorersAndResults.map(({ name, error: error3 }) => [
12188
- name,
12189
- error3 instanceof Error ? error3.stack : `${error3}`
12190
- ])
12191
- );
12192
- metadata["scorer_errors"] = scorerErrors;
12193
- rootSpan.log({
12194
- metadata: { scorer_errors: scorerErrors }
12195
- });
12196
- const names = Object.keys(scorerErrors).join(", ");
12197
- const errors = failingScorersAndResults.map((item) => item.error);
12198
- unhandledScores = Object.keys(scorerErrors);
12199
- debugLogger.forState(evaluator.state).warn(
12200
- `Found exceptions for the following scorers: ${names}`,
12201
- errors
12202
- );
12332
+ );
12333
+ if (Object.keys(classifications).length > 0) {
12334
+ rootSpan.log({ classifications });
12203
12335
  }
12336
+ const failedScorerNames = logScoringFailures(
12337
+ "scorer",
12338
+ failingScorers,
12339
+ metadata,
12340
+ rootSpan,
12341
+ evaluator.state
12342
+ );
12343
+ unhandledScores = failedScorerNames.length ? failedScorerNames : null;
12344
+ logScoringFailures(
12345
+ "classifier",
12346
+ failingClassifiers,
12347
+ metadata,
12348
+ rootSpan,
12349
+ evaluator.state
12350
+ );
12204
12351
  } catch (e) {
12205
12352
  logError(rootSpan, e);
12206
12353
  error2 = e;
@@ -12219,15 +12366,19 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
12219
12366
  accumulateScores(localScoreAccumulator, mergedScores);
12220
12367
  }
12221
12368
  if (collectResults) {
12222
- collectedResults.push({
12369
+ const baseResult = {
12223
12370
  input: datum.input,
12224
12371
  ..."expected" in datum ? { expected: datum.expected } : {},
12225
12372
  output,
12226
12373
  tags: tags.length ? tags : void 0,
12227
12374
  metadata,
12228
- scores: mergedScores,
12229
12375
  error: error2,
12230
12376
  origin: baseEvent.event?.origin
12377
+ };
12378
+ collectedResults.push({
12379
+ ...baseResult,
12380
+ scores: mergedScores,
12381
+ ...Object.keys(classifications).length > 0 ? { classifications } : {}
12231
12382
  });
12232
12383
  }
12233
12384
  };
@@ -12256,7 +12407,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
12256
12407
  if (!filters.every((f) => evaluateFilter(datum, f))) {
12257
12408
  continue;
12258
12409
  }
12259
- const trialCount = evaluator.trialCount ?? 1;
12410
+ const trialCount = datum.trialCount ?? evaluator.trialCount ?? 1;
12260
12411
  for (let trialIndex = 0; trialIndex < trialCount; trialIndex++) {
12261
12412
  if (cancelled) {
12262
12413
  break;
@@ -12363,6 +12514,9 @@ function logError2(e, verbose) {
12363
12514
  }
12364
12515
  }
12365
12516
  function accumulateScores(accumulator, scores) {
12517
+ if (!scores) {
12518
+ return;
12519
+ }
12366
12520
  for (const [name, score] of Object.entries(scores)) {
12367
12521
  if (score === null || score === void 0) {
12368
12522
  continue;
@@ -12983,6 +13137,16 @@ function getCallerLocation() {
12983
13137
  function isAsyncIterable3(value) {
12984
13138
  return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
12985
13139
  }
13140
+ function hasAsyncIteratorMethods(value) {
13141
+ return value !== null && typeof value === "object" && "next" in value && typeof value.next === "function";
13142
+ }
13143
+ function isSelfAsyncIterator(value) {
13144
+ try {
13145
+ return value[Symbol.asyncIterator]() === value;
13146
+ } catch {
13147
+ return false;
13148
+ }
13149
+ }
12986
13150
  function patchStreamIfNeeded(stream, options) {
12987
13151
  if (!isAsyncIterable3(stream)) {
12988
13152
  return stream;
@@ -12993,6 +13157,98 @@ function patchStreamIfNeeded(stream, options) {
12993
13157
  );
12994
13158
  return stream;
12995
13159
  }
13160
+ if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
13161
+ if ("__braintrust_patched_iterator_methods" in stream) {
13162
+ return stream;
13163
+ }
13164
+ try {
13165
+ const originalNext = stream.next.bind(stream);
13166
+ const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
13167
+ const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
13168
+ const chunks = [];
13169
+ let completed = false;
13170
+ stream.next = async (...args) => {
13171
+ try {
13172
+ const result = await originalNext(...args);
13173
+ if (result.done) {
13174
+ if (!completed) {
13175
+ completed = true;
13176
+ try {
13177
+ await options.onComplete(chunks);
13178
+ } catch (error2) {
13179
+ console.error("Error in stream onComplete handler:", error2);
13180
+ }
13181
+ }
13182
+ } else {
13183
+ const chunk = result.value;
13184
+ const shouldCollect = options.shouldCollect ? options.shouldCollect(chunk) : true;
13185
+ if (shouldCollect) {
13186
+ chunks.push(chunk);
13187
+ if (options.onChunk) {
13188
+ try {
13189
+ await options.onChunk(chunk);
13190
+ } catch (error2) {
13191
+ console.error("Error in stream onChunk handler:", error2);
13192
+ }
13193
+ }
13194
+ }
13195
+ }
13196
+ return result;
13197
+ } catch (error2) {
13198
+ if (!completed) {
13199
+ completed = true;
13200
+ if (options.onError) {
13201
+ try {
13202
+ await options.onError(
13203
+ error2 instanceof Error ? error2 : new Error(String(error2)),
13204
+ chunks
13205
+ );
13206
+ } catch (handlerError) {
13207
+ console.error("Error in stream onError handler:", handlerError);
13208
+ }
13209
+ }
13210
+ }
13211
+ throw error2;
13212
+ }
13213
+ };
13214
+ if (originalReturn) {
13215
+ stream.return = async (...args) => {
13216
+ if (!completed) {
13217
+ completed = true;
13218
+ try {
13219
+ await options.onComplete(chunks);
13220
+ } catch (error2) {
13221
+ console.error("Error in stream onComplete handler:", error2);
13222
+ }
13223
+ }
13224
+ return originalReturn(...args);
13225
+ };
13226
+ }
13227
+ if (originalThrow) {
13228
+ stream.throw = async (...args) => {
13229
+ if (!completed) {
13230
+ completed = true;
13231
+ const rawError = args[0];
13232
+ const error2 = rawError instanceof Error ? rawError : new Error(String(rawError));
13233
+ if (options.onError) {
13234
+ try {
13235
+ await options.onError(error2, chunks);
13236
+ } catch (handlerError) {
13237
+ console.error("Error in stream onError handler:", handlerError);
13238
+ }
13239
+ }
13240
+ }
13241
+ return originalThrow(...args);
13242
+ };
13243
+ }
13244
+ Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
13245
+ value: true
13246
+ });
13247
+ return stream;
13248
+ } catch (error2) {
13249
+ console.warn("Failed to patch stream iterator methods:", error2);
13250
+ }
13251
+ }
12996
13252
  const originalIteratorFn = stream[Symbol.asyncIterator];
12997
13253
  if ("__braintrust_patched" in originalIteratorFn && originalIteratorFn["__braintrust_patched"]) {
12998
13254
  return stream;
@@ -14549,10 +14805,42 @@ function processImagesInOutput(output) {
14549
14805
  }
14550
14806
  return output;
14551
14807
  }
14808
+ function mergeLogprobTokens(existing, incoming) {
14809
+ if (incoming === void 0) {
14810
+ return existing;
14811
+ }
14812
+ if (incoming === null) {
14813
+ return existing ?? null;
14814
+ }
14815
+ if (Array.isArray(existing)) {
14816
+ return [...existing, ...incoming];
14817
+ }
14818
+ return [...incoming];
14819
+ }
14820
+ function aggregateChatLogprobs(existing, incoming) {
14821
+ if (incoming === void 0) {
14822
+ return existing;
14823
+ }
14824
+ if (incoming === null) {
14825
+ return existing ?? null;
14826
+ }
14827
+ const aggregated = existing && existing !== null ? { ...existing, ...incoming } : { ...incoming };
14828
+ const content = mergeLogprobTokens(existing?.content, incoming.content);
14829
+ if (content !== void 0) {
14830
+ aggregated.content = content;
14831
+ }
14832
+ const refusal = mergeLogprobTokens(existing?.refusal, incoming.refusal);
14833
+ if (refusal !== void 0) {
14834
+ aggregated.refusal = refusal;
14835
+ }
14836
+ return aggregated;
14837
+ }
14552
14838
  function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
14553
14839
  let role = void 0;
14554
14840
  let content = void 0;
14841
+ let refusal = void 0;
14555
14842
  let tool_calls = void 0;
14843
+ let logprobs = void 0;
14556
14844
  let finish_reason = void 0;
14557
14845
  let metrics = {};
14558
14846
  for (const chunk of chunks) {
@@ -14562,19 +14850,30 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
14562
14850
  ...parseMetricsFromUsage(chunk.usage)
14563
14851
  };
14564
14852
  }
14565
- const delta = chunk.choices?.[0]?.delta;
14566
- if (!delta) {
14853
+ const choice = chunk.choices?.[0];
14854
+ if (!choice) {
14567
14855
  continue;
14568
14856
  }
14569
- if (!role && delta.role) {
14570
- role = delta.role;
14857
+ if (choice.finish_reason) {
14858
+ finish_reason = choice.finish_reason;
14859
+ }
14860
+ logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
14861
+ const delta = choice.delta;
14862
+ if (!delta) {
14863
+ continue;
14571
14864
  }
14572
14865
  if (delta.finish_reason) {
14573
14866
  finish_reason = delta.finish_reason;
14574
14867
  }
14868
+ if (!role && delta.role) {
14869
+ role = delta.role;
14870
+ }
14575
14871
  if (delta.content) {
14576
14872
  content = (content || "") + delta.content;
14577
14873
  }
14874
+ if (delta.refusal) {
14875
+ refusal = (refusal || "") + delta.refusal;
14876
+ }
14578
14877
  if (delta.tool_calls) {
14579
14878
  const toolDelta = delta.tool_calls[0];
14580
14879
  if (!tool_calls || toolDelta.id && tool_calls[tool_calls.length - 1].id !== toolDelta.id) {
@@ -14600,9 +14899,10 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
14600
14899
  message: {
14601
14900
  role,
14602
14901
  content,
14902
+ ...refusal !== void 0 ? { refusal } : {},
14603
14903
  tool_calls
14604
14904
  },
14605
- logprobs: null,
14905
+ logprobs: logprobs ?? null,
14606
14906
  finish_reason
14607
14907
  }
14608
14908
  ]
@@ -14665,13 +14965,21 @@ var anthropicChannels = defineChannels("@anthropic-ai/sdk", {
14665
14965
  betaMessagesCreate: channel({
14666
14966
  channelName: "beta.messages.create",
14667
14967
  kind: "async"
14968
+ }),
14969
+ betaMessagesToolRunner: channel({
14970
+ channelName: "beta.messages.toolRunner",
14971
+ kind: "sync-stream"
14668
14972
  })
14669
14973
  });
14670
14974
 
14671
14975
  // src/instrumentation/plugins/anthropic-plugin.ts
14976
+ var ANTHROPIC_TOOL_RUNNER_TOOL_WRAPPED = Symbol.for(
14977
+ "braintrust.anthropic_tool_runner_tool_wrapped"
14978
+ );
14672
14979
  var AnthropicPlugin = class extends BasePlugin {
14673
14980
  onEnable() {
14674
14981
  this.subscribeToAnthropicChannels();
14982
+ this.subscribeToAnthropicToolRunner();
14675
14983
  }
14676
14984
  onDisable() {
14677
14985
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
@@ -14726,6 +15034,61 @@ var AnthropicPlugin = class extends BasePlugin {
14726
15034
  })
14727
15035
  );
14728
15036
  }
15037
+ subscribeToAnthropicToolRunner() {
15038
+ const tracingChannel2 = anthropicChannels.betaMessagesToolRunner.tracingChannel();
15039
+ const states = /* @__PURE__ */ new WeakMap();
15040
+ const handlers = {
15041
+ start: (event) => {
15042
+ const params = event.arguments[0] ?? {};
15043
+ const span = startSpan({
15044
+ name: "anthropic.beta.messages.toolRunner",
15045
+ spanAttributes: {
15046
+ type: "task" /* TASK */
15047
+ }
15048
+ });
15049
+ span.log({
15050
+ input: processAttachmentsInInput(
15051
+ coalesceInput(params.messages ?? [], params.system)
15052
+ ),
15053
+ metadata: {
15054
+ ...extractAnthropicToolRunnerMetadata(params),
15055
+ provider: "anthropic"
15056
+ }
15057
+ });
15058
+ const state = {
15059
+ aggregatedMetrics: {},
15060
+ finalized: false,
15061
+ iterationCount: 0,
15062
+ seenMessages: /* @__PURE__ */ new WeakSet(),
15063
+ span,
15064
+ startTime: getCurrentUnixTimestamp()
15065
+ };
15066
+ states.set(event, state);
15067
+ },
15068
+ end: (event) => {
15069
+ const state = states.get(event);
15070
+ if (!state) {
15071
+ return;
15072
+ }
15073
+ patchAnthropicToolRunner({
15074
+ runner: event.result,
15075
+ state
15076
+ });
15077
+ },
15078
+ error: (event) => {
15079
+ const state = states.get(event);
15080
+ if (!state || !event.error) {
15081
+ return;
15082
+ }
15083
+ finalizeAnthropicToolRunnerError(state, event.error);
15084
+ states.delete(event);
15085
+ }
15086
+ };
15087
+ tracingChannel2.subscribe(handlers);
15088
+ this.unsubscribers.push(() => {
15089
+ tracingChannel2.unsubscribe(handlers);
15090
+ });
15091
+ }
14729
15092
  };
14730
15093
  function parseMetricsFromUsage2(usage) {
14731
15094
  if (!usage) {
@@ -14742,39 +15105,378 @@ function parseMetricsFromUsage2(usage) {
14742
15105
  saveIfExistsTo("output_tokens", "completion_tokens");
14743
15106
  saveIfExistsTo("cache_read_input_tokens", "prompt_cached_tokens");
14744
15107
  saveIfExistsTo("cache_creation_input_tokens", "prompt_cache_creation_tokens");
15108
+ if (isObject(usage.server_tool_use)) {
15109
+ for (const [name, value] of Object.entries(usage.server_tool_use)) {
15110
+ if (typeof value === "number") {
15111
+ metrics[`server_tool_use_${name}`] = value;
15112
+ }
15113
+ }
15114
+ }
14745
15115
  return metrics;
14746
15116
  }
14747
- function aggregateAnthropicStreamChunks(chunks) {
14748
- const fallbackTextDeltas = [];
14749
- const contentBlocks = {};
14750
- const contentBlockDeltas = {};
14751
- let metrics = {};
14752
- let metadata = {};
14753
- let role;
14754
- for (const event of chunks) {
14755
- switch (event?.type) {
14756
- case "message_start":
14757
- if (event.message?.usage) {
14758
- const initialMetrics = parseMetricsFromUsage2(event.message.usage);
14759
- metrics = { ...metrics, ...initialMetrics };
14760
- }
14761
- if (typeof event.message?.role === "string") {
14762
- role = event.message.role;
14763
- }
14764
- break;
14765
- case "content_block_start":
14766
- if (event.content_block) {
14767
- contentBlocks[event.index] = event.content_block;
14768
- contentBlockDeltas[event.index] = { textDeltas: [], citations: [] };
14769
- }
14770
- break;
14771
- case "content_block_delta": {
14772
- const acc = contentBlockDeltas[event.index];
14773
- const delta = event.delta;
14774
- if (!delta) break;
14775
- if (delta.type === "text_delta" && "text" in delta) {
14776
- const text = delta.text;
14777
- if (text) {
15117
+ function extractAnthropicToolRunnerMetadata(params) {
15118
+ const metadata = filterFrom(params, ["messages", "system", "tools"]);
15119
+ const toolNames = extractAnthropicToolNames(params.tools);
15120
+ return {
15121
+ ...metadata,
15122
+ operation: "toolRunner",
15123
+ ...toolNames.length > 0 ? { tool_names: toolNames } : {}
15124
+ };
15125
+ }
15126
+ function extractAnthropicToolNames(tools) {
15127
+ const toolNames = [];
15128
+ for (const tool of tools) {
15129
+ if (!tool || typeof tool !== "object") {
15130
+ continue;
15131
+ }
15132
+ const toolRecord = tool;
15133
+ if (typeof toolRecord.name === "string") {
15134
+ toolNames.push(toolRecord.name);
15135
+ continue;
15136
+ }
15137
+ if (typeof toolRecord.mcp_server_name === "string") {
15138
+ toolNames.push(toolRecord.mcp_server_name);
15139
+ }
15140
+ }
15141
+ return toolNames;
15142
+ }
15143
+ function toErrorMessage(error2) {
15144
+ return error2 instanceof Error ? error2.message : String(error2);
15145
+ }
15146
+ function getAnthropicToolRunnerInput(args) {
15147
+ return args.length > 0 ? args[0] : void 0;
15148
+ }
15149
+ function wrapAnthropicToolRunnerTools(params, state) {
15150
+ if (!Array.isArray(params.tools)) {
15151
+ return;
15152
+ }
15153
+ params.tools = params.tools.map(
15154
+ (tool, index) => wrapAnthropicToolRunnerTool(tool, index, state)
15155
+ );
15156
+ }
15157
+ function wrapAnthropicToolRunnerTool(tool, index, state) {
15158
+ if (!tool || typeof tool !== "object" || typeof tool.run !== "function" || tool[ANTHROPIC_TOOL_RUNNER_TOOL_WRAPPED]) {
15159
+ return tool;
15160
+ }
15161
+ const toolName = typeof tool.name === "string" ? tool.name : `tool[${index}]`;
15162
+ const originalRun = tool.run;
15163
+ const runDescriptor = Object.getOwnPropertyDescriptor(tool, "run");
15164
+ const wrappedTool = Object.create(
15165
+ Object.getPrototypeOf(tool),
15166
+ Object.getOwnPropertyDescriptors(tool)
15167
+ );
15168
+ Object.defineProperty(wrappedTool, "run", {
15169
+ configurable: runDescriptor?.configurable ?? true,
15170
+ enumerable: runDescriptor?.enumerable ?? true,
15171
+ value: function braintrustAnthropicToolRunnerRun(...args) {
15172
+ return state.span.traced(
15173
+ (span) => {
15174
+ const finalizeSuccess = (result) => {
15175
+ span.log({ output: result });
15176
+ return result;
15177
+ };
15178
+ const finalizeError = (error2) => {
15179
+ span.log({ error: toErrorMessage(error2) });
15180
+ throw error2;
15181
+ };
15182
+ try {
15183
+ const result = Reflect.apply(originalRun, this, args);
15184
+ if (isPromiseLike(result)) {
15185
+ return result.then(finalizeSuccess, finalizeError);
15186
+ }
15187
+ return finalizeSuccess(result);
15188
+ } catch (error2) {
15189
+ return finalizeError(error2);
15190
+ }
15191
+ },
15192
+ {
15193
+ event: {
15194
+ input: getAnthropicToolRunnerInput(args),
15195
+ metadata: {
15196
+ "gen_ai.tool.name": toolName,
15197
+ provider: "anthropic"
15198
+ }
15199
+ },
15200
+ name: `tool: ${toolName}`,
15201
+ spanAttributes: {
15202
+ type: "tool" /* TOOL */
15203
+ }
15204
+ }
15205
+ );
15206
+ },
15207
+ writable: runDescriptor?.writable ?? true
15208
+ });
15209
+ Object.defineProperty(wrappedTool, ANTHROPIC_TOOL_RUNNER_TOOL_WRAPPED, {
15210
+ configurable: false,
15211
+ enumerable: false,
15212
+ value: true,
15213
+ writable: false
15214
+ });
15215
+ return wrappedTool;
15216
+ }
15217
+ function getAnthropicToolRunnerParams(runnerRecord) {
15218
+ const params = Reflect.get(runnerRecord, "params");
15219
+ return params && typeof params === "object" ? params : void 0;
15220
+ }
15221
+ function ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state) {
15222
+ const params = getAnthropicToolRunnerParams(runnerRecord);
15223
+ if (params) {
15224
+ wrapAnthropicToolRunnerTools(params, state);
15225
+ }
15226
+ }
15227
+ function wrapAnthropicToolRunnerSetMessagesParams(runnerRecord, state) {
15228
+ const setMessagesParams = Reflect.get(runnerRecord, "setMessagesParams");
15229
+ if (typeof setMessagesParams !== "function") {
15230
+ return;
15231
+ }
15232
+ Reflect.set(
15233
+ runnerRecord,
15234
+ "setMessagesParams",
15235
+ function patchedSetMessagesParams(...args) {
15236
+ const result = Reflect.apply(setMessagesParams, this, args);
15237
+ const nextParams = getAnthropicToolRunnerParams(runnerRecord);
15238
+ if (nextParams) {
15239
+ wrapAnthropicToolRunnerTools(nextParams, state);
15240
+ }
15241
+ return result;
15242
+ }
15243
+ );
15244
+ }
15245
+ function isAnthropicMessage(value) {
15246
+ return !!value && typeof value === "object" && typeof value.role === "string" && Array.isArray(value.content);
15247
+ }
15248
+ function isAnthropicMessageStream(value) {
15249
+ return !!value && typeof value === "object" && isAsyncIterable3(value) && "finalMessage" in value && typeof value.finalMessage === "function";
15250
+ }
15251
+ function recordAnthropicToolRunnerMessage(state, message) {
15252
+ if (typeof message !== "object" || message === null) {
15253
+ return;
15254
+ }
15255
+ if (state.seenMessages.has(message)) {
15256
+ state.lastMessage = message;
15257
+ return;
15258
+ }
15259
+ state.seenMessages.add(message);
15260
+ state.lastMessage = message;
15261
+ const parsedMetrics = parseMetricsFromUsage2(message.usage);
15262
+ for (const [key, value] of Object.entries(parsedMetrics)) {
15263
+ if (typeof value === "number") {
15264
+ state.aggregatedMetrics[key] = (state.aggregatedMetrics[key] ?? 0) + value;
15265
+ }
15266
+ }
15267
+ }
15268
+ function instrumentAnthropicMessageStream(stream, state) {
15269
+ if ("__braintrust_tool_runner_stream_patched" in stream) {
15270
+ return;
15271
+ }
15272
+ if (!Object.isFrozen(stream) && !Object.isSealed(stream)) {
15273
+ patchStreamIfNeeded(stream, {
15274
+ onChunk: () => {
15275
+ if (state.firstTokenTime === void 0) {
15276
+ state.firstTokenTime = getCurrentUnixTimestamp();
15277
+ }
15278
+ },
15279
+ onComplete: () => void 0
15280
+ });
15281
+ }
15282
+ if (typeof stream.finalMessage === "function") {
15283
+ const originalFinalMessage = stream.finalMessage.bind(stream);
15284
+ stream.finalMessage = async () => {
15285
+ const message = await originalFinalMessage();
15286
+ recordAnthropicToolRunnerMessage(state, message);
15287
+ return message;
15288
+ };
15289
+ }
15290
+ Object.defineProperty(stream, "__braintrust_tool_runner_stream_patched", {
15291
+ value: true
15292
+ });
15293
+ }
15294
+ async function finalizeAnthropicToolRunner(state, finalMessage) {
15295
+ if (state.finalized) {
15296
+ return;
15297
+ }
15298
+ state.finalized = true;
15299
+ const message = finalMessage ?? state.lastMessage;
15300
+ if (message) {
15301
+ recordAnthropicToolRunnerMessage(state, message);
15302
+ }
15303
+ const metrics = finalizeAnthropicTokens({
15304
+ ...state.aggregatedMetrics
15305
+ });
15306
+ if (state.firstTokenTime !== void 0) {
15307
+ metrics.time_to_first_token = state.firstTokenTime - state.startTime;
15308
+ }
15309
+ const metadata = {
15310
+ anthropic_tool_runner_iterations: state.iterationCount
15311
+ };
15312
+ if (message?.stop_reason !== void 0) {
15313
+ metadata.stop_reason = message.stop_reason;
15314
+ }
15315
+ if (message?.stop_sequence !== void 0) {
15316
+ metadata.stop_sequence = message.stop_sequence;
15317
+ }
15318
+ state.span.log({
15319
+ ...message ? { output: { role: message.role, content: message.content } } : {},
15320
+ metadata,
15321
+ metrics: Object.fromEntries(
15322
+ Object.entries(metrics).filter(
15323
+ (entry) => entry[1] !== void 0
15324
+ )
15325
+ )
15326
+ });
15327
+ state.span.end();
15328
+ }
15329
+ function finalizeAnthropicToolRunnerError(state, error2) {
15330
+ if (state.finalized) {
15331
+ return;
15332
+ }
15333
+ state.finalized = true;
15334
+ state.span.log({
15335
+ error: error2 instanceof Error ? error2.message : String(error2)
15336
+ });
15337
+ state.span.end();
15338
+ }
15339
+ async function resolveAnthropicToolRunnerFinalMessage(runner) {
15340
+ if (typeof runner.done === "function") {
15341
+ return await runner.done();
15342
+ }
15343
+ if (typeof runner.runUntilDone === "function") {
15344
+ return await runner.runUntilDone();
15345
+ }
15346
+ return void 0;
15347
+ }
15348
+ function wrapAnthropicToolRunnerPromiseMethod(runnerRecord, methodName, state) {
15349
+ const method = runnerRecord[methodName];
15350
+ if (typeof method !== "function") {
15351
+ return;
15352
+ }
15353
+ runnerRecord[methodName] = async (...args) => {
15354
+ ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state);
15355
+ return await withCurrent(state.span, async () => {
15356
+ try {
15357
+ const message = await method.apply(runnerRecord, args);
15358
+ recordAnthropicToolRunnerMessage(state, message);
15359
+ await finalizeAnthropicToolRunner(state, message);
15360
+ return message;
15361
+ } catch (error2) {
15362
+ finalizeAnthropicToolRunnerError(state, error2);
15363
+ throw error2;
15364
+ }
15365
+ });
15366
+ };
15367
+ }
15368
+ function patchAnthropicToolRunner(args) {
15369
+ const { runner, state } = args;
15370
+ if (!runner || typeof runner !== "object") {
15371
+ void finalizeAnthropicToolRunner(state);
15372
+ return;
15373
+ }
15374
+ const runnerRecord = runner;
15375
+ if ("__braintrust_tool_runner_patched" in runnerRecord) {
15376
+ return;
15377
+ }
15378
+ ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state);
15379
+ wrapAnthropicToolRunnerSetMessagesParams(runnerRecord, state);
15380
+ wrapAnthropicToolRunnerPromiseMethod(runnerRecord, "done", state);
15381
+ wrapAnthropicToolRunnerPromiseMethod(runnerRecord, "runUntilDone", state);
15382
+ if (!isAsyncIterable3(runnerRecord)) {
15383
+ Object.defineProperty(runnerRecord, "__braintrust_tool_runner_patched", {
15384
+ value: true
15385
+ });
15386
+ return;
15387
+ }
15388
+ const originalIterator = runnerRecord[Symbol.asyncIterator].bind(runnerRecord);
15389
+ runnerRecord[Symbol.asyncIterator] = function() {
15390
+ const iterator = originalIterator();
15391
+ return {
15392
+ async next(value) {
15393
+ try {
15394
+ ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state);
15395
+ const result = await withCurrent(
15396
+ state.span,
15397
+ () => value === void 0 ? iterator.next() : iterator.next(value)
15398
+ );
15399
+ if (result.done) {
15400
+ const finalMessage = await resolveAnthropicToolRunnerFinalMessage(runner);
15401
+ await finalizeAnthropicToolRunner(state, finalMessage);
15402
+ return result;
15403
+ }
15404
+ state.iterationCount += 1;
15405
+ if (isAnthropicMessage(result.value)) {
15406
+ if (state.firstTokenTime === void 0) {
15407
+ state.firstTokenTime = getCurrentUnixTimestamp();
15408
+ }
15409
+ recordAnthropicToolRunnerMessage(state, result.value);
15410
+ } else if (isAnthropicMessageStream(result.value)) {
15411
+ instrumentAnthropicMessageStream(result.value, state);
15412
+ }
15413
+ return result;
15414
+ } catch (error2) {
15415
+ finalizeAnthropicToolRunnerError(state, error2);
15416
+ throw error2;
15417
+ }
15418
+ },
15419
+ async return(value) {
15420
+ try {
15421
+ ensureAnthropicToolRunnerToolsWrapped(runnerRecord, state);
15422
+ const result = typeof iterator.return === "function" ? await withCurrent(state.span, () => iterator.return(value)) : { done: true, value };
15423
+ const finalMessage = await resolveAnthropicToolRunnerFinalMessage(
15424
+ runner
15425
+ ).catch(() => void 0);
15426
+ await finalizeAnthropicToolRunner(state, finalMessage);
15427
+ return result;
15428
+ } catch (error2) {
15429
+ finalizeAnthropicToolRunnerError(state, error2);
15430
+ throw error2;
15431
+ }
15432
+ },
15433
+ async throw(error2) {
15434
+ finalizeAnthropicToolRunnerError(state, error2);
15435
+ if (typeof iterator.throw === "function") {
15436
+ return await withCurrent(state.span, () => iterator.throw(error2));
15437
+ }
15438
+ throw error2;
15439
+ },
15440
+ [Symbol.asyncIterator]() {
15441
+ return this;
15442
+ }
15443
+ };
15444
+ };
15445
+ Object.defineProperty(runnerRecord, "__braintrust_tool_runner_patched", {
15446
+ value: true
15447
+ });
15448
+ }
15449
+ function aggregateAnthropicStreamChunks(chunks) {
15450
+ const fallbackTextDeltas = [];
15451
+ const contentBlocks = {};
15452
+ const contentBlockDeltas = {};
15453
+ let metrics = {};
15454
+ let metadata = {};
15455
+ let role;
15456
+ for (const event of chunks) {
15457
+ switch (event?.type) {
15458
+ case "message_start":
15459
+ if (event.message?.usage) {
15460
+ const initialMetrics = parseMetricsFromUsage2(event.message.usage);
15461
+ metrics = { ...metrics, ...initialMetrics };
15462
+ }
15463
+ if (typeof event.message?.role === "string") {
15464
+ role = event.message.role;
15465
+ }
15466
+ break;
15467
+ case "content_block_start":
15468
+ if (event.content_block) {
15469
+ contentBlocks[event.index] = event.content_block;
15470
+ contentBlockDeltas[event.index] = { textDeltas: [], citations: [] };
15471
+ }
15472
+ break;
15473
+ case "content_block_delta": {
15474
+ const acc = contentBlockDeltas[event.index];
15475
+ const delta = event.delta;
15476
+ if (!delta) break;
15477
+ if (delta.type === "text_delta" && "text" in delta) {
15478
+ const text = delta.text;
15479
+ if (text) {
14778
15480
  if (acc !== void 0) {
14779
15481
  acc.textDeltas.push(text);
14780
15482
  } else {
@@ -14852,15 +15554,24 @@ function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallback
14852
15554
  }
14853
15555
  const acc = contentBlockDeltas[index];
14854
15556
  const text = acc?.textDeltas.join("") ?? "";
14855
- if (isToolUseContentBlock(contentBlock)) {
15557
+ if (isToolUseLikeContentBlock(contentBlock)) {
14856
15558
  if (!text) {
14857
15559
  return;
14858
15560
  }
14859
15561
  try {
14860
- contentBlocks[index] = {
14861
- ...contentBlock,
14862
- input: JSON.parse(text)
15562
+ const parsedInput = JSON.parse(text);
15563
+ if (!isObject(parsedInput)) {
15564
+ fallbackTextDeltas.push(text);
15565
+ delete contentBlocks[index];
15566
+ return;
15567
+ }
15568
+ const parsedToolUseBlock = {
15569
+ type: contentBlock.type,
15570
+ id: contentBlock.id,
15571
+ name: contentBlock.name,
15572
+ input: parsedInput
14863
15573
  };
15574
+ contentBlocks[index] = parsedToolUseBlock;
14864
15575
  } catch {
14865
15576
  fallbackTextDeltas.push(text);
14866
15577
  delete contentBlocks[index];
@@ -14894,8 +15605,8 @@ function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallback
14894
15605
  function isTextContentBlock(contentBlock) {
14895
15606
  return contentBlock.type === "text";
14896
15607
  }
14897
- function isToolUseContentBlock(contentBlock) {
14898
- return contentBlock.type === "tool_use";
15608
+ function isToolUseLikeContentBlock(contentBlock) {
15609
+ return (contentBlock.type === "tool_use" || contentBlock.type === "server_tool_use") && typeof contentBlock.id === "string" && typeof contentBlock.name === "string" && isObject(contentBlock.input);
14899
15610
  }
14900
15611
  function isThinkingContentBlock(contentBlock) {
14901
15612
  return contentBlock.type === "thinking";
@@ -15093,6 +15804,10 @@ var aiSDKChannels = defineChannels("ai", {
15093
15804
  channelName: "embedMany",
15094
15805
  kind: "async"
15095
15806
  }),
15807
+ rerank: channel({
15808
+ channelName: "rerank",
15809
+ kind: "async"
15810
+ }),
15096
15811
  agentGenerate: channel({
15097
15812
  channelName: "Agent.generate",
15098
15813
  kind: "async"
@@ -15152,7 +15867,7 @@ var AISDKPlugin = class extends BasePlugin {
15152
15867
  this.unsubscribers.push(
15153
15868
  traceStreamingChannel(aiSDKChannels.generateText, {
15154
15869
  name: "generateText",
15155
- type: "llm" /* LLM */,
15870
+ type: "function" /* FUNCTION */,
15156
15871
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15157
15872
  extractOutput: (result, endEvent) => {
15158
15873
  finalizeAISDKChildTracing(endEvent);
@@ -15168,7 +15883,7 @@ var AISDKPlugin = class extends BasePlugin {
15168
15883
  this.unsubscribers.push(
15169
15884
  traceStreamingChannel(aiSDKChannels.streamText, {
15170
15885
  name: "streamText",
15171
- type: "llm" /* LLM */,
15886
+ type: "function" /* FUNCTION */,
15172
15887
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15173
15888
  extractOutput: (result, endEvent) => processAISDKOutput(
15174
15889
  result,
@@ -15188,7 +15903,7 @@ var AISDKPlugin = class extends BasePlugin {
15188
15903
  this.unsubscribers.push(
15189
15904
  traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
15190
15905
  name: "streamText",
15191
- type: "llm" /* LLM */,
15906
+ type: "function" /* FUNCTION */,
15192
15907
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15193
15908
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
15194
15909
  defaultDenyOutputPaths: denyOutputPaths,
@@ -15202,7 +15917,7 @@ var AISDKPlugin = class extends BasePlugin {
15202
15917
  this.unsubscribers.push(
15203
15918
  traceStreamingChannel(aiSDKChannels.generateObject, {
15204
15919
  name: "generateObject",
15205
- type: "llm" /* LLM */,
15920
+ type: "function" /* FUNCTION */,
15206
15921
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15207
15922
  extractOutput: (result, endEvent) => {
15208
15923
  finalizeAISDKChildTracing(endEvent);
@@ -15218,7 +15933,7 @@ var AISDKPlugin = class extends BasePlugin {
15218
15933
  this.unsubscribers.push(
15219
15934
  traceStreamingChannel(aiSDKChannels.streamObject, {
15220
15935
  name: "streamObject",
15221
- type: "llm" /* LLM */,
15936
+ type: "function" /* FUNCTION */,
15222
15937
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15223
15938
  extractOutput: (result, endEvent) => processAISDKOutput(
15224
15939
  result,
@@ -15238,7 +15953,7 @@ var AISDKPlugin = class extends BasePlugin {
15238
15953
  this.unsubscribers.push(
15239
15954
  traceSyncStreamChannel(aiSDKChannels.streamObjectSync, {
15240
15955
  name: "streamObject",
15241
- type: "llm" /* LLM */,
15956
+ type: "function" /* FUNCTION */,
15242
15957
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15243
15958
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
15244
15959
  defaultDenyOutputPaths: denyOutputPaths,
@@ -15252,7 +15967,7 @@ var AISDKPlugin = class extends BasePlugin {
15252
15967
  this.unsubscribers.push(
15253
15968
  traceAsyncChannel(aiSDKChannels.embed, {
15254
15969
  name: "embed",
15255
- type: "llm" /* LLM */,
15970
+ type: "function" /* FUNCTION */,
15256
15971
  extractInput: ([params], event) => prepareAISDKEmbedInput(params, event.self),
15257
15972
  extractOutput: (result, endEvent) => processAISDKEmbeddingOutput(
15258
15973
  result,
@@ -15264,7 +15979,7 @@ var AISDKPlugin = class extends BasePlugin {
15264
15979
  this.unsubscribers.push(
15265
15980
  traceAsyncChannel(aiSDKChannels.embedMany, {
15266
15981
  name: "embedMany",
15267
- type: "llm" /* LLM */,
15982
+ type: "function" /* FUNCTION */,
15268
15983
  extractInput: ([params], event) => prepareAISDKEmbedInput(params, event.self),
15269
15984
  extractOutput: (result, endEvent) => processAISDKEmbeddingOutput(
15270
15985
  result,
@@ -15273,10 +15988,22 @@ var AISDKPlugin = class extends BasePlugin {
15273
15988
  extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent)
15274
15989
  })
15275
15990
  );
15991
+ this.unsubscribers.push(
15992
+ traceAsyncChannel(aiSDKChannels.rerank, {
15993
+ name: "rerank",
15994
+ type: "function" /* FUNCTION */,
15995
+ extractInput: ([params], event) => prepareAISDKRerankInput(params, event.self),
15996
+ extractOutput: (result, endEvent) => processAISDKRerankOutput(
15997
+ result,
15998
+ resolveDenyOutputPaths(endEvent, denyOutputPaths)
15999
+ ),
16000
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent)
16001
+ })
16002
+ );
15276
16003
  this.unsubscribers.push(
15277
16004
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
15278
16005
  name: "Agent.generate",
15279
- type: "llm" /* LLM */,
16006
+ type: "function" /* FUNCTION */,
15280
16007
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15281
16008
  extractOutput: (result, endEvent) => {
15282
16009
  finalizeAISDKChildTracing(endEvent);
@@ -15292,7 +16019,7 @@ var AISDKPlugin = class extends BasePlugin {
15292
16019
  this.unsubscribers.push(
15293
16020
  traceStreamingChannel(aiSDKChannels.agentStream, {
15294
16021
  name: "Agent.stream",
15295
- type: "llm" /* LLM */,
16022
+ type: "function" /* FUNCTION */,
15296
16023
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15297
16024
  extractOutput: (result, endEvent) => processAISDKOutput(
15298
16025
  result,
@@ -15312,7 +16039,7 @@ var AISDKPlugin = class extends BasePlugin {
15312
16039
  this.unsubscribers.push(
15313
16040
  traceSyncStreamChannel(aiSDKChannels.agentStreamSync, {
15314
16041
  name: "Agent.stream",
15315
- type: "llm" /* LLM */,
16042
+ type: "function" /* FUNCTION */,
15316
16043
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15317
16044
  patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
15318
16045
  defaultDenyOutputPaths: denyOutputPaths,
@@ -15326,7 +16053,7 @@ var AISDKPlugin = class extends BasePlugin {
15326
16053
  this.unsubscribers.push(
15327
16054
  traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
15328
16055
  name: "ToolLoopAgent.generate",
15329
- type: "llm" /* LLM */,
16056
+ type: "function" /* FUNCTION */,
15330
16057
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15331
16058
  extractOutput: (result, endEvent) => {
15332
16059
  finalizeAISDKChildTracing(endEvent);
@@ -15342,7 +16069,7 @@ var AISDKPlugin = class extends BasePlugin {
15342
16069
  this.unsubscribers.push(
15343
16070
  traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
15344
16071
  name: "ToolLoopAgent.stream",
15345
- type: "llm" /* LLM */,
16072
+ type: "function" /* FUNCTION */,
15346
16073
  extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
15347
16074
  extractOutput: (result, endEvent) => processAISDKOutput(
15348
16075
  result,
@@ -15692,6 +16419,16 @@ function prepareAISDKEmbedInput(params, self) {
15692
16419
  metadata: extractMetadataFromEmbedParams(params, self)
15693
16420
  };
15694
16421
  }
16422
+ function prepareAISDKRerankInput(params, self) {
16423
+ const { documents, query } = params;
16424
+ return {
16425
+ input: {
16426
+ documents,
16427
+ query
16428
+ },
16429
+ metadata: extractMetadataFromRerankParams(params, self)
16430
+ };
16431
+ }
15695
16432
  function extractTopLevelAISDKMetrics(result, event, startTime) {
15696
16433
  const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
15697
16434
  if (startTime) {
@@ -15737,6 +16474,16 @@ function extractMetadataFromCallParams(params, self) {
15737
16474
  function extractMetadataFromEmbedParams(params, self) {
15738
16475
  return extractBaseMetadata(params.model, self);
15739
16476
  }
16477
+ function extractMetadataFromRerankParams(params, self) {
16478
+ const metadata = extractBaseMetadata(params.model, self);
16479
+ if (typeof params.topN === "number") {
16480
+ metadata.topN = params.topN;
16481
+ }
16482
+ if (Array.isArray(params.documents)) {
16483
+ metadata.document_count = params.documents.length;
16484
+ }
16485
+ return metadata;
16486
+ }
15740
16487
  function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
15741
16488
  const cleanup = [];
15742
16489
  const patchedModels = /* @__PURE__ */ new WeakSet();
@@ -16284,6 +17031,22 @@ function processAISDKEmbeddingOutput(output, denyOutputPaths) {
16284
17031
  }
16285
17032
  return normalizeAISDKLoggedOutput(omit(summarized, denyOutputPaths));
16286
17033
  }
17034
+ function processAISDKRerankOutput(output, _denyOutputPaths) {
17035
+ if (!output || typeof output !== "object") {
17036
+ return output;
17037
+ }
17038
+ const ranking = safeSerializableFieldRead(output, "ranking");
17039
+ if (Array.isArray(ranking)) {
17040
+ return ranking.slice(0, 100).map((item) => {
17041
+ const entry = item && typeof item === "object" ? item : void 0;
17042
+ return {
17043
+ index: typeof entry?.originalIndex === "number" ? entry.originalIndex : void 0,
17044
+ relevance_score: typeof entry?.score === "number" ? entry.score : void 0
17045
+ };
17046
+ });
17047
+ }
17048
+ return void 0;
17049
+ }
16287
17050
  function extractTokenMetrics(result) {
16288
17051
  const metrics = {};
16289
17052
  let usage;
@@ -16326,12 +17089,80 @@ function extractTokenMetrics(result) {
16326
17089
  if (totalTokens !== void 0) {
16327
17090
  metrics.tokens = totalTokens;
16328
17091
  }
17092
+ const promptCachedTokens = firstNumber(
17093
+ usage.inputTokens?.cacheRead,
17094
+ usage.inputTokenDetails?.cacheReadTokens,
17095
+ usage.cachedInputTokens,
17096
+ usage.promptCachedTokens,
17097
+ usage.prompt_cached_tokens
17098
+ );
17099
+ if (promptCachedTokens !== void 0) {
17100
+ metrics.prompt_cached_tokens = promptCachedTokens;
17101
+ }
17102
+ const promptCacheCreationTokens = firstNumber(
17103
+ usage.inputTokens?.cacheWrite,
17104
+ usage.inputTokenDetails?.cacheWriteTokens,
17105
+ usage.promptCacheCreationTokens,
17106
+ usage.prompt_cache_creation_tokens,
17107
+ extractAnthropicCacheCreationTokens(result)
17108
+ );
17109
+ if (promptCacheCreationTokens !== void 0) {
17110
+ metrics.prompt_cache_creation_tokens = promptCacheCreationTokens;
17111
+ }
17112
+ const promptReasoningTokens = firstNumber(
17113
+ usage.promptReasoningTokens,
17114
+ usage.prompt_reasoning_tokens
17115
+ );
17116
+ if (promptReasoningTokens !== void 0) {
17117
+ metrics.prompt_reasoning_tokens = promptReasoningTokens;
17118
+ }
17119
+ const completionCachedTokens = firstNumber(
17120
+ usage.completionCachedTokens,
17121
+ usage.completion_cached_tokens
17122
+ );
17123
+ if (completionCachedTokens !== void 0) {
17124
+ metrics.completion_cached_tokens = completionCachedTokens;
17125
+ }
17126
+ const reasoningTokenCount = firstNumber(
17127
+ usage.outputTokens?.reasoning,
17128
+ usage.reasoningTokens,
17129
+ usage.completionReasoningTokens,
17130
+ usage.completion_reasoning_tokens,
17131
+ usage.reasoning_tokens,
17132
+ usage.thinkingTokens,
17133
+ usage.thinking_tokens
17134
+ );
17135
+ if (reasoningTokenCount !== void 0) {
17136
+ metrics.completion_reasoning_tokens = reasoningTokenCount;
17137
+ metrics.reasoning_tokens = reasoningTokenCount;
17138
+ }
17139
+ const completionAudioTokens = firstNumber(
17140
+ usage.completionAudioTokens,
17141
+ usage.completion_audio_tokens
17142
+ );
17143
+ if (completionAudioTokens !== void 0) {
17144
+ metrics.completion_audio_tokens = completionAudioTokens;
17145
+ }
16329
17146
  const cost = extractCostFromResult(result);
16330
17147
  if (cost !== void 0) {
16331
17148
  metrics.estimated_cost = cost;
16332
17149
  }
16333
17150
  return metrics;
16334
17151
  }
17152
+ function extractAnthropicCacheCreationTokens(result) {
17153
+ const providerMetadata = safeSerializableFieldRead(
17154
+ result,
17155
+ "providerMetadata"
17156
+ );
17157
+ const anthropicMetadata = providerMetadata?.anthropic;
17158
+ if (!anthropicMetadata) {
17159
+ return void 0;
17160
+ }
17161
+ return firstNumber(
17162
+ anthropicMetadata.cacheCreationInputTokens,
17163
+ anthropicMetadata.usage?.cache_creation_input_tokens
17164
+ );
17165
+ }
16335
17166
  function safeResultFieldRead(result, field) {
16336
17167
  return safeSerializableFieldRead(result, field);
16337
17168
  }
@@ -16448,14 +17279,11 @@ function extractSerializableOutputFields(output) {
16448
17279
  ...extractGetterValues(output)
16449
17280
  };
16450
17281
  }
16451
- function isPromiseLike(value) {
16452
- return value != null && typeof value === "object" && typeof value.then === "function";
16453
- }
16454
17282
  function isSerializableOutputValue(value) {
16455
17283
  if (typeof value === "function") {
16456
17284
  return false;
16457
17285
  }
16458
- if (value && typeof value === "object" && typeof value.then === "function") {
17286
+ if (isPromiseLike(value)) {
16459
17287
  return false;
16460
17288
  }
16461
17289
  if (value && typeof value === "object" && typeof value.getReader === "function") {
@@ -16775,12 +17603,9 @@ function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
16775
17603
  var LOCAL_TOOL_HANDLER_WRAPPED = Symbol.for(
16776
17604
  "braintrust.claude_agent_sdk.local_tool_handler_wrapped"
16777
17605
  );
16778
- function toErrorMessage(error2) {
17606
+ function toErrorMessage2(error2) {
16779
17607
  return error2 instanceof Error ? error2.message : String(error2);
16780
17608
  }
16781
- function isPromiseLike2(value) {
16782
- return value !== null && typeof value === "object" && "then" in value && typeof value.then === "function";
16783
- }
16784
17609
  function getToolUseIdFromExtra(extra) {
16785
17610
  if (!extra || typeof extra !== "object" || !("_meta" in extra)) {
16786
17611
  return void 0;
@@ -16827,14 +17652,14 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
16827
17652
  return result;
16828
17653
  };
16829
17654
  const finalizeError = (error2) => {
16830
- span.log({ error: toErrorMessage(error2) });
17655
+ span.log({ error: toErrorMessage2(error2) });
16831
17656
  span.end();
16832
17657
  throw error2;
16833
17658
  };
16834
17659
  return withCurrent(span, () => {
16835
17660
  try {
16836
17661
  const result = runHandler();
16837
- if (isPromiseLike2(result)) {
17662
+ if (isPromiseLike(result)) {
16838
17663
  return result.then(finalizeSuccess, finalizeError);
16839
17664
  }
16840
17665
  return finalizeSuccess(result);
@@ -16954,7 +17779,7 @@ var ROOT_LLM_PARENT_KEY = "__root__";
16954
17779
  function llmParentKey(parentToolUseId) {
16955
17780
  return parentToolUseId ?? ROOT_LLM_PARENT_KEY;
16956
17781
  }
16957
- function isSubAgentToolName(toolName) {
17782
+ function isSubAgentDelegationToolName(toolName) {
16958
17783
  return toolName === "Agent" || toolName === "Task";
16959
17784
  }
16960
17785
  function filterSerializableOptions(options) {
@@ -16988,19 +17813,87 @@ function getNumberProperty(obj, key) {
16988
17813
  const value = Reflect.get(obj, key);
16989
17814
  return typeof value === "number" ? value : void 0;
16990
17815
  }
16991
- function extractUsageFromMessage(message) {
16992
- const metrics = {};
16993
- let usage;
16994
- if (message.type === "assistant") {
16995
- usage = message.message?.usage;
16996
- } else if (message.type === "result") {
16997
- usage = message.usage;
16998
- }
16999
- if (!usage || typeof usage !== "object") {
17000
- return metrics;
17816
+ function getStringProperty(obj, key) {
17817
+ if (!obj || typeof obj !== "object" || !(key in obj)) {
17818
+ return void 0;
17001
17819
  }
17002
- const inputTokens = getNumberProperty(usage, "input_tokens");
17003
- if (inputTokens !== void 0) {
17820
+ const value = Reflect.get(obj, key);
17821
+ return typeof value === "string" ? value : void 0;
17822
+ }
17823
+ function upsertSubAgentDetails(detailsByToolUseId, toolUseId, update) {
17824
+ const existing = detailsByToolUseId.get(toolUseId) ?? {};
17825
+ const merged = {
17826
+ ...existing,
17827
+ ...Object.fromEntries(
17828
+ Object.entries(update).filter(([, value]) => value !== void 0)
17829
+ )
17830
+ };
17831
+ detailsByToolUseId.set(toolUseId, merged);
17832
+ return merged;
17833
+ }
17834
+ function formatSubAgentSpanName(details) {
17835
+ if (details?.description) {
17836
+ return `Agent: ${details.description}`;
17837
+ }
17838
+ if (details?.agentType) {
17839
+ return `Agent: ${details.agentType}`;
17840
+ }
17841
+ return "Agent: sub-agent";
17842
+ }
17843
+ function subAgentDetailsToMetadata(details) {
17844
+ if (!details) {
17845
+ return {};
17846
+ }
17847
+ const metadata = {};
17848
+ if (details.agentId) {
17849
+ metadata["claude_agent_sdk.agent_id"] = details.agentId;
17850
+ }
17851
+ if (details.agentType) {
17852
+ metadata["claude_agent_sdk.agent_type"] = details.agentType;
17853
+ }
17854
+ if (details.description) {
17855
+ metadata["claude_agent_sdk.description"] = details.description;
17856
+ }
17857
+ if (details.taskId) {
17858
+ metadata["claude_agent_sdk.task_id"] = details.taskId;
17859
+ }
17860
+ if (details.taskType) {
17861
+ metadata["claude_agent_sdk.task_type"] = details.taskType;
17862
+ }
17863
+ if (details.toolUseId) {
17864
+ metadata["claude_agent_sdk.tool_use_id"] = details.toolUseId;
17865
+ }
17866
+ if (details.workflowName) {
17867
+ metadata["claude_agent_sdk.workflow_name"] = details.workflowName;
17868
+ }
17869
+ return metadata;
17870
+ }
17871
+ function resolveTaskToolUseId(taskIdToToolUseId, message) {
17872
+ const messageToolUseId = typeof message.tool_use_id === "string" ? message.tool_use_id : void 0;
17873
+ if (messageToolUseId && typeof message.task_id === "string") {
17874
+ taskIdToToolUseId.set(message.task_id, messageToolUseId);
17875
+ }
17876
+ if (messageToolUseId) {
17877
+ return messageToolUseId;
17878
+ }
17879
+ if (typeof message.task_id === "string") {
17880
+ return taskIdToToolUseId.get(message.task_id);
17881
+ }
17882
+ return void 0;
17883
+ }
17884
+ function extractUsageFromMessage(message) {
17885
+ const metrics = {};
17886
+ let usage;
17887
+ if (message.type === "assistant") {
17888
+ usage = message.message?.usage;
17889
+ } else if (message.type === "result") {
17890
+ usage = message.usage;
17891
+ }
17892
+ if (!usage || typeof usage !== "object") {
17893
+ return metrics;
17894
+ }
17895
+ const inputTokens = getNumberProperty(usage, "input_tokens");
17896
+ if (inputTokens !== void 0) {
17004
17897
  metrics.prompt_tokens = inputTokens;
17005
17898
  }
17006
17899
  const outputTokens = getNumberProperty(usage, "output_tokens");
@@ -17160,7 +18053,7 @@ function prepareLocalToolHandlersInMcpServers(mcpServers) {
17160
18053
  }
17161
18054
  return { hasLocalToolHandlers, localToolHookNames };
17162
18055
  }
17163
- function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentSpans, endedSubAgentSpans) {
18056
+ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
17164
18057
  const preToolUse = async (input, toolUseID) => {
17165
18058
  if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
17166
18059
  return {};
@@ -17168,9 +18061,6 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
17168
18061
  if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
17169
18062
  return {};
17170
18063
  }
17171
- if (isSubAgentToolName(input.tool_name)) {
17172
- return {};
17173
- }
17174
18064
  const parsed = parseToolName(input.tool_name);
17175
18065
  const toolSpan = startSpan({
17176
18066
  event: {
@@ -17200,10 +18090,18 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
17200
18090
  return {};
17201
18091
  }
17202
18092
  const subAgentSpan = subAgentSpans.get(toolUseID);
18093
+ const toolSpan = activeToolSpans.get(toolUseID);
17203
18094
  if (subAgentSpan) {
18095
+ if (endedSubAgentSpans.has(toolUseID)) {
18096
+ return {};
18097
+ }
17204
18098
  try {
17205
18099
  const response = input.tool_response;
17206
- const metadata = {};
18100
+ const metadata = {
18101
+ ...subAgentDetailsToMetadata(
18102
+ subAgentDetailsByToolUseId.get(toolUseID)
18103
+ )
18104
+ };
17207
18105
  if (response?.status) {
17208
18106
  metadata["claude_agent_sdk.status"] = response.status;
17209
18107
  }
@@ -17221,9 +18119,16 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
17221
18119
  subAgentSpan.end();
17222
18120
  endedSubAgentSpans.add(toolUseID);
17223
18121
  }
18122
+ if (toolSpan) {
18123
+ try {
18124
+ toolSpan.log({ output: input.tool_response });
18125
+ } finally {
18126
+ toolSpan.end();
18127
+ activeToolSpans.delete(toolUseID);
18128
+ }
18129
+ }
17224
18130
  return {};
17225
18131
  }
17226
- const toolSpan = activeToolSpans.get(toolUseID);
17227
18132
  if (!toolSpan) {
17228
18133
  return {};
17229
18134
  }
@@ -17243,16 +18148,43 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
17243
18148
  return {};
17244
18149
  }
17245
18150
  const subAgentSpan = subAgentSpans.get(toolUseID);
18151
+ const toolSpan = activeToolSpans.get(toolUseID);
17246
18152
  if (subAgentSpan) {
18153
+ if (endedSubAgentSpans.has(toolUseID)) {
18154
+ return {};
18155
+ }
17247
18156
  try {
17248
- subAgentSpan.log({ error: input.error });
18157
+ subAgentSpan.log({
18158
+ error: input.error,
18159
+ metadata: subAgentDetailsToMetadata(
18160
+ subAgentDetailsByToolUseId.get(toolUseID)
18161
+ )
18162
+ });
17249
18163
  } finally {
17250
18164
  subAgentSpan.end();
17251
18165
  endedSubAgentSpans.add(toolUseID);
17252
18166
  }
18167
+ if (toolSpan) {
18168
+ const parsed2 = parseToolName(input.tool_name);
18169
+ try {
18170
+ toolSpan.log({
18171
+ error: input.error,
18172
+ metadata: {
18173
+ "claude_agent_sdk.is_interrupt": input.is_interrupt,
18174
+ "claude_agent_sdk.session_id": input.session_id,
18175
+ "claude_agent_sdk.raw_tool_name": parsed2.rawToolName,
18176
+ "gen_ai.tool.call.id": toolUseID,
18177
+ "gen_ai.tool.name": parsed2.toolName,
18178
+ ...parsed2.mcpServer && { "mcp.server": parsed2.mcpServer }
18179
+ }
18180
+ });
18181
+ } finally {
18182
+ toolSpan.end();
18183
+ activeToolSpans.delete(toolUseID);
18184
+ }
18185
+ }
17253
18186
  return {};
17254
18187
  }
17255
- const toolSpan = activeToolSpans.get(toolUseID);
17256
18188
  if (!toolSpan) {
17257
18189
  return {};
17258
18190
  }
@@ -17274,15 +18206,84 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
17274
18206
  }
17275
18207
  return {};
17276
18208
  };
17277
- return { postToolUse, postToolUseFailure, preToolUse };
18209
+ const subagentStart = async (input, toolUseID) => {
18210
+ if (input.hook_event_name !== "SubagentStart" || !toolUseID) {
18211
+ return {};
18212
+ }
18213
+ const details = upsertSubAgentDetails(
18214
+ subAgentDetailsByToolUseId,
18215
+ toolUseID,
18216
+ {
18217
+ agentId: input.agent_id,
18218
+ agentType: input.agent_type,
18219
+ toolUseId: toolUseID
18220
+ }
18221
+ );
18222
+ const subAgentSpan = subAgentSpans.get(toolUseID);
18223
+ if (subAgentSpan && !endedSubAgentSpans.has(toolUseID)) {
18224
+ subAgentSpan.log({
18225
+ metadata: subAgentDetailsToMetadata(details)
18226
+ });
18227
+ }
18228
+ return {};
18229
+ };
18230
+ const subagentStop = async (input, toolUseID) => {
18231
+ if (input.hook_event_name !== "SubagentStop" || !toolUseID) {
18232
+ return {};
18233
+ }
18234
+ const details = upsertSubAgentDetails(
18235
+ subAgentDetailsByToolUseId,
18236
+ toolUseID,
18237
+ {
18238
+ agentId: input.agent_id,
18239
+ agentType: input.agent_type,
18240
+ toolUseId: toolUseID
18241
+ }
18242
+ );
18243
+ const subAgentSpan = subAgentSpans.get(toolUseID);
18244
+ if (!subAgentSpan || endedSubAgentSpans.has(toolUseID)) {
18245
+ return {};
18246
+ }
18247
+ const metadata = {
18248
+ ...subAgentDetailsToMetadata(details),
18249
+ ...input.agent_transcript_path && {
18250
+ "claude_agent_sdk.agent_transcript_path": input.agent_transcript_path
18251
+ },
18252
+ "claude_agent_sdk.stop_hook_active": input.stop_hook_active
18253
+ };
18254
+ try {
18255
+ subAgentSpan.log({
18256
+ metadata,
18257
+ output: input.last_assistant_message
18258
+ });
18259
+ } finally {
18260
+ subAgentSpan.end();
18261
+ endedSubAgentSpans.add(toolUseID);
18262
+ }
18263
+ return {};
18264
+ };
18265
+ return {
18266
+ postToolUse,
18267
+ postToolUseFailure,
18268
+ preToolUse,
18269
+ subagentStart,
18270
+ subagentStop
18271
+ };
17278
18272
  }
17279
- function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentSpans, endedSubAgentSpans) {
17280
- const { preToolUse, postToolUse, postToolUseFailure } = createToolTracingHooks(
18273
+ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
18274
+ const {
18275
+ preToolUse,
18276
+ postToolUse,
18277
+ postToolUseFailure,
18278
+ subagentStart,
18279
+ subagentStop
18280
+ } = createToolTracingHooks(
17281
18281
  resolveParentSpan,
17282
18282
  activeToolSpans,
17283
18283
  options.mcpServers,
17284
18284
  localToolHookNames,
17285
18285
  skipLocalToolHooks,
18286
+ subAgentDetailsByToolUseId,
17286
18287
  subAgentSpans,
17287
18288
  endedSubAgentSpans
17288
18289
  );
@@ -17304,6 +18305,18 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
17304
18305
  PreToolUse: [
17305
18306
  ...existingHooks.PreToolUse ?? [],
17306
18307
  { hooks: [preToolUse] }
18308
+ ],
18309
+ SubagentStart: [
18310
+ ...existingHooks.SubagentStart ?? [],
18311
+ {
18312
+ hooks: [subagentStart]
18313
+ }
18314
+ ],
18315
+ SubagentStop: [
18316
+ ...existingHooks.SubagentStop ?? [],
18317
+ {
18318
+ hooks: [subagentStop]
18319
+ }
17307
18320
  ]
17308
18321
  }
17309
18322
  };
@@ -17332,7 +18345,6 @@ async function finalizeCurrentMessageGroup(state) {
17332
18345
  parentSpan,
17333
18346
  existingLlmSpan
17334
18347
  );
17335
- state.activeLlmSpansByParentToolUse.delete(parentKey);
17336
18348
  if (llmSpanResult) {
17337
18349
  if (parentToolUseId) {
17338
18350
  state.latestLlmParentBySubAgentToolUse.set(
@@ -17346,6 +18358,7 @@ async function finalizeCurrentMessageGroup(state) {
17346
18358
  state.finalResults.push(llmSpanResult.finalMessage);
17347
18359
  }
17348
18360
  }
18361
+ state.activeLlmSpansByParentToolUse.delete(parentKey);
17349
18362
  const lastMessage = state.currentMessages[state.currentMessages.length - 1];
17350
18363
  if (lastMessage?.message?.usage) {
17351
18364
  state.accumulatedOutputTokens += getNumberProperty(lastMessage.message.usage, "output_tokens") || 0;
@@ -17362,8 +18375,12 @@ function maybeTrackToolUseContext(state, message) {
17362
18375
  continue;
17363
18376
  }
17364
18377
  state.toolUseToParent.set(block.id, parentToolUseId);
17365
- if (block.name === "Task" && typeof block.input === "object" && block.input !== null && "subagent_type" in block.input && typeof block.input.subagent_type === "string") {
17366
- state.pendingSubAgentNames.set(block.id, block.input.subagent_type);
18378
+ if (typeof block.name === "string" && isSubAgentDelegationToolName(block.name) && typeof block.input === "object" && block.input !== null) {
18379
+ upsertSubAgentDetails(state.subAgentDetailsByToolUseId, block.id, {
18380
+ agentType: getStringProperty(block.input, "subagent_type"),
18381
+ description: getStringProperty(block.input, "description"),
18382
+ toolUseId: block.id
18383
+ });
17367
18384
  }
17368
18385
  }
17369
18386
  }
@@ -17376,34 +18393,133 @@ async function maybeStartSubAgentSpan(state, message) {
17376
18393
  return;
17377
18394
  }
17378
18395
  await ensureSubAgentSpan(
17379
- state.pendingSubAgentNames,
18396
+ state.subAgentDetailsByToolUseId,
17380
18397
  state.span,
18398
+ state.activeToolSpans,
17381
18399
  state.subAgentSpans,
17382
18400
  parentToolUseId
17383
18401
  );
17384
18402
  }
17385
- async function ensureSubAgentSpan(pendingSubAgentNames, rootSpan, subAgentSpans, parentToolUseId) {
18403
+ async function ensureSubAgentSpan(subAgentDetailsByToolUseId, rootSpan, activeToolSpans, subAgentSpans, parentToolUseId) {
17386
18404
  const existingSpan = subAgentSpans.get(parentToolUseId);
17387
18405
  if (existingSpan) {
17388
18406
  return existingSpan;
17389
18407
  }
17390
- const agentName = pendingSubAgentNames.get(parentToolUseId);
17391
- const spanName = agentName ? `Agent: ${agentName}` : "Agent: sub-agent";
18408
+ const details = subAgentDetailsByToolUseId.get(parentToolUseId);
18409
+ const spanName = formatSubAgentSpanName(details);
18410
+ const parentToolSpan = activeToolSpans.get(parentToolUseId);
18411
+ const parentSpan = parentToolSpan ? await parentToolSpan.export() : await rootSpan.export();
17392
18412
  const subAgentSpan = startSpan({
17393
18413
  event: {
17394
- metadata: {
17395
- ...agentName && { "claude_agent_sdk.agent_type": agentName }
17396
- }
18414
+ metadata: subAgentDetailsToMetadata(details)
17397
18415
  },
17398
18416
  name: spanName,
17399
- parent: await rootSpan.export(),
18417
+ parent: parentSpan,
17400
18418
  spanAttributes: { type: "task" /* TASK */ }
17401
18419
  });
17402
18420
  subAgentSpans.set(parentToolUseId, subAgentSpan);
17403
18421
  return subAgentSpan;
17404
18422
  }
18423
+ async function maybeHandleTaskLifecycleMessage(state, message) {
18424
+ if (message.type !== "system") {
18425
+ return false;
18426
+ }
18427
+ if (message.subtype !== "task_started" && message.subtype !== "task_progress" && message.subtype !== "task_notification") {
18428
+ return false;
18429
+ }
18430
+ const toolUseId = resolveTaskToolUseId(state.taskIdToToolUseId, message);
18431
+ if (!toolUseId) {
18432
+ return true;
18433
+ }
18434
+ const details = upsertSubAgentDetails(
18435
+ state.subAgentDetailsByToolUseId,
18436
+ toolUseId,
18437
+ {
18438
+ description: getStringProperty(message, "description"),
18439
+ taskId: getStringProperty(message, "task_id"),
18440
+ taskType: getStringProperty(message, "task_type"),
18441
+ toolUseId,
18442
+ workflowName: getStringProperty(message, "workflow_name")
18443
+ }
18444
+ );
18445
+ const subAgentSpan = await ensureSubAgentSpan(
18446
+ state.subAgentDetailsByToolUseId,
18447
+ state.span,
18448
+ state.activeToolSpans,
18449
+ state.subAgentSpans,
18450
+ toolUseId
18451
+ );
18452
+ if (state.endedSubAgentSpans.has(toolUseId)) {
18453
+ return true;
18454
+ }
18455
+ const usage = message.usage;
18456
+ const usageTotalTokens = getNumberProperty(usage, "total_tokens");
18457
+ const usageToolUses = getNumberProperty(usage, "tool_uses");
18458
+ const usageDurationMs = getNumberProperty(usage, "duration_ms");
18459
+ const metadata = {
18460
+ ...subAgentDetailsToMetadata(details),
18461
+ "claude_agent_sdk.tool_use_id": toolUseId,
18462
+ ...usageTotalTokens !== void 0 && {
18463
+ "claude_agent_sdk.total_tokens": usageTotalTokens
18464
+ },
18465
+ ...usageToolUses !== void 0 && {
18466
+ "claude_agent_sdk.tool_use_count": usageToolUses
18467
+ },
18468
+ ...usageDurationMs !== void 0 && {
18469
+ "claude_agent_sdk.duration_ms": usageDurationMs
18470
+ }
18471
+ };
18472
+ if (message.subtype === "task_started") {
18473
+ const prompt = getStringProperty(message, "prompt");
18474
+ subAgentSpan.log({
18475
+ input: prompt,
18476
+ metadata
18477
+ });
18478
+ return true;
18479
+ }
18480
+ const summary = getStringProperty(message, "summary");
18481
+ if (summary) {
18482
+ metadata["claude_agent_sdk.summary"] = summary;
18483
+ }
18484
+ if (message.subtype === "task_progress") {
18485
+ const lastToolName = getStringProperty(message, "last_tool_name");
18486
+ if (lastToolName) {
18487
+ metadata["claude_agent_sdk.last_tool_name"] = lastToolName;
18488
+ }
18489
+ subAgentSpan.log({
18490
+ metadata,
18491
+ output: summary
18492
+ });
18493
+ return true;
18494
+ }
18495
+ const status = getStringProperty(message, "status");
18496
+ const outputFile = getStringProperty(message, "output_file");
18497
+ if (status) {
18498
+ metadata["claude_agent_sdk.task_status"] = status;
18499
+ }
18500
+ if (outputFile) {
18501
+ metadata["claude_agent_sdk.output_file"] = outputFile;
18502
+ }
18503
+ const output = summary || outputFile ? {
18504
+ ...summary && { summary },
18505
+ ...outputFile && { output_file: outputFile }
18506
+ } : void 0;
18507
+ try {
18508
+ subAgentSpan.log({
18509
+ metadata,
18510
+ output
18511
+ });
18512
+ } finally {
18513
+ subAgentSpan.end();
18514
+ state.endedSubAgentSpans.add(toolUseId);
18515
+ }
18516
+ return true;
18517
+ }
17405
18518
  async function handleStreamMessage(state, message) {
17406
18519
  maybeTrackToolUseContext(state, message);
18520
+ if (await maybeHandleTaskLifecycleMessage(state, message)) {
18521
+ return;
18522
+ }
17407
18523
  await maybeStartSubAgentSpan(state, message);
17408
18524
  const messageId = message.message?.id;
17409
18525
  if (messageId && messageId !== state.currentMessageId) {
@@ -17418,8 +18534,9 @@ async function handleStreamMessage(state, message) {
17418
18534
  let llmParentSpan = await state.span.export();
17419
18535
  if (parentToolUseId) {
17420
18536
  const subAgentSpan = await ensureSubAgentSpan(
17421
- state.pendingSubAgentNames,
18537
+ state.subAgentDetailsByToolUseId,
17422
18538
  state.span,
18539
+ state.activeToolSpans,
17423
18540
  state.subAgentSpans,
17424
18541
  parentToolUseId
17425
18542
  );
@@ -17499,6 +18616,10 @@ async function finalizeQuerySpan(state) {
17499
18616
  llmSpan.end();
17500
18617
  }
17501
18618
  state.activeLlmSpansByParentToolUse.clear();
18619
+ for (const toolSpan of state.activeToolSpans.values()) {
18620
+ toolSpan.end();
18621
+ }
18622
+ state.activeToolSpans.clear();
17502
18623
  for (const [id, subAgentSpan] of state.subAgentSpans) {
17503
18624
  if (!state.endedSubAgentSpans.has(id)) {
17504
18625
  subAgentSpan.end();
@@ -17572,7 +18693,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
17572
18693
  const latestRootLlmParentRef = {
17573
18694
  value: void 0
17574
18695
  };
17575
- const pendingSubAgentNames = /* @__PURE__ */ new Map();
18696
+ const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
18697
+ const taskIdToToolUseId = /* @__PURE__ */ new Map();
17576
18698
  const localToolContext = createClaudeLocalToolContext();
17577
18699
  const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
17578
18700
  const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
@@ -17589,8 +18711,9 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
17589
18711
  return parentLlm;
17590
18712
  }
17591
18713
  const subAgentSpan = await ensureSubAgentSpan(
17592
- pendingSubAgentNames,
18714
+ subAgentDetailsByToolUseId,
17593
18715
  span,
18716
+ activeToolSpans,
17594
18717
  subAgentSpans,
17595
18718
  parentToolUseId
17596
18719
  );
@@ -17609,6 +18732,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
17609
18732
  activeToolSpans,
17610
18733
  localToolHookNames,
17611
18734
  skipLocalToolHooks,
18735
+ subAgentDetailsByToolUseId,
17612
18736
  subAgentSpans,
17613
18737
  endedSubAgentSpans
17614
18738
  );
@@ -17626,12 +18750,13 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
17626
18750
  finalResults: [],
17627
18751
  options: optionsWithHooks,
17628
18752
  originalPrompt,
17629
- pendingSubAgentNames,
17630
18753
  processing: Promise.resolve(),
17631
18754
  promptDone,
17632
18755
  promptStarted: () => promptStarted,
17633
18756
  span,
18757
+ subAgentDetailsByToolUseId,
17634
18758
  subAgentSpans,
18759
+ taskIdToToolUseId,
17635
18760
  latestLlmParentBySubAgentToolUse,
17636
18761
  latestRootLlmParentRef,
17637
18762
  toolUseToParent,
@@ -17713,6 +18838,10 @@ var googleGenAIChannels = defineChannels("@google/genai", {
17713
18838
  generateContentStream: channel({
17714
18839
  channelName: "models.generateContentStream",
17715
18840
  kind: "async"
18841
+ }),
18842
+ embedContent: channel({
18843
+ channelName: "models.embedContent",
18844
+ kind: "async"
17716
18845
  })
17717
18846
  });
17718
18847
 
@@ -17739,6 +18868,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
17739
18868
  subscribeToGoogleGenAIChannels() {
17740
18869
  this.subscribeToGenerateContentChannel();
17741
18870
  this.subscribeToGenerateContentStreamChannel();
18871
+ this.subscribeToEmbedContentChannel();
17742
18872
  }
17743
18873
  subscribeToGenerateContentChannel() {
17744
18874
  const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
@@ -17748,8 +18878,8 @@ var GoogleGenAIPlugin = class extends BasePlugin {
17748
18878
  states,
17749
18879
  (event) => {
17750
18880
  const params = event.arguments[0];
17751
- const input = serializeInput(params);
17752
- const metadata = extractMetadata(params);
18881
+ const input = serializeGenerateContentInput(params);
18882
+ const metadata = extractGenerateContentMetadata(params);
17753
18883
  const span = startSpan({
17754
18884
  name: "generate_content",
17755
18885
  spanAttributes: {
@@ -17767,8 +18897,8 @@ var GoogleGenAIPlugin = class extends BasePlugin {
17767
18897
  start: (event) => {
17768
18898
  ensureSpanState(states, event, () => {
17769
18899
  const params = event.arguments[0];
17770
- const input = serializeInput(params);
17771
- const metadata = extractMetadata(params);
18900
+ const input = serializeGenerateContentInput(params);
18901
+ const metadata = extractGenerateContentMetadata(params);
17772
18902
  const span = startSpan({
17773
18903
  name: "generate_content",
17774
18904
  spanAttributes: {
@@ -17788,7 +18918,9 @@ var GoogleGenAIPlugin = class extends BasePlugin {
17788
18918
  return;
17789
18919
  }
17790
18920
  try {
18921
+ const responseMetadata = extractResponseMetadata(event.result);
17791
18922
  spanState.span.log({
18923
+ ...responseMetadata ? { metadata: responseMetadata } : {},
17792
18924
  metrics: cleanMetrics(
17793
18925
  extractGenerateContentMetrics(
17794
18926
  event.result,
@@ -17818,8 +18950,8 @@ var GoogleGenAIPlugin = class extends BasePlugin {
17818
18950
  start: (event) => {
17819
18951
  const streamEvent = event;
17820
18952
  const params = event.arguments[0];
17821
- streamEvent.googleGenAIInput = serializeInput(params);
17822
- streamEvent.googleGenAIMetadata = extractMetadata(params);
18953
+ streamEvent.googleGenAIInput = serializeGenerateContentInput(params);
18954
+ streamEvent.googleGenAIMetadata = extractGenerateContentMetadata(params);
17823
18955
  streamEvent.googleGenAIStartTime = getCurrentUnixTimestamp();
17824
18956
  },
17825
18957
  asyncEnd: (event) => {
@@ -17839,6 +18971,76 @@ var GoogleGenAIPlugin = class extends BasePlugin {
17839
18971
  tracingChannel2.unsubscribe(handlers);
17840
18972
  });
17841
18973
  }
18974
+ subscribeToEmbedContentChannel() {
18975
+ const tracingChannel2 = googleGenAIChannels.embedContent.tracingChannel();
18976
+ const states = /* @__PURE__ */ new WeakMap();
18977
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
18978
+ tracingChannel2,
18979
+ states,
18980
+ (event) => {
18981
+ const params = event.arguments[0];
18982
+ const input = serializeEmbedContentInput(params);
18983
+ const metadata = extractEmbedContentMetadata(params);
18984
+ const span = startSpan({
18985
+ name: "embed_content",
18986
+ spanAttributes: {
18987
+ type: "llm" /* LLM */
18988
+ },
18989
+ event: createWrapperParityEvent({ input, metadata })
18990
+ });
18991
+ return {
18992
+ span,
18993
+ startTime: getCurrentUnixTimestamp()
18994
+ };
18995
+ }
18996
+ );
18997
+ const handlers = {
18998
+ start: (event) => {
18999
+ ensureSpanState(states, event, () => {
19000
+ const params = event.arguments[0];
19001
+ const input = serializeEmbedContentInput(params);
19002
+ const metadata = extractEmbedContentMetadata(params);
19003
+ const span = startSpan({
19004
+ name: "embed_content",
19005
+ spanAttributes: {
19006
+ type: "llm" /* LLM */
19007
+ },
19008
+ event: createWrapperParityEvent({ input, metadata })
19009
+ });
19010
+ return {
19011
+ span,
19012
+ startTime: getCurrentUnixTimestamp()
19013
+ };
19014
+ });
19015
+ },
19016
+ asyncEnd: (event) => {
19017
+ const spanState = states.get(event);
19018
+ if (!spanState) {
19019
+ return;
19020
+ }
19021
+ try {
19022
+ const output = summarizeEmbedContentOutput(event.result);
19023
+ spanState.span.log({
19024
+ ...output ? { output } : {},
19025
+ metrics: cleanMetrics(
19026
+ extractEmbedContentMetrics(event.result, spanState.startTime)
19027
+ )
19028
+ });
19029
+ } finally {
19030
+ spanState.span.end();
19031
+ states.delete(event);
19032
+ }
19033
+ },
19034
+ error: (event) => {
19035
+ logErrorAndEndSpan(states, event);
19036
+ }
19037
+ };
19038
+ tracingChannel2.subscribe(handlers);
19039
+ this.unsubscribers.push(() => {
19040
+ unbindCurrentSpanStore?.();
19041
+ tracingChannel2.unsubscribe(handlers);
19042
+ });
19043
+ }
17842
19044
  };
17843
19045
  function ensureSpanState(states, event, create) {
17844
19046
  const existing = states.get(event);
@@ -17912,7 +19114,11 @@ function patchGoogleGenAIStreamingResult(args) {
17912
19114
  finalized = true;
17913
19115
  if (options.result) {
17914
19116
  const { end, ...metricsWithoutEnd } = options.result.metrics;
19117
+ const responseMetadata = extractResponseMetadata(
19118
+ options.result.aggregated
19119
+ );
17915
19120
  span.log({
19121
+ ...responseMetadata ? { metadata: responseMetadata } : {},
17916
19122
  metrics: cleanMetrics(metricsWithoutEnd),
17917
19123
  output: options.result.aggregated
17918
19124
  });
@@ -18015,26 +19221,35 @@ function patchGoogleGenAIStreamingResult(args) {
18015
19221
  patchIterator(result);
18016
19222
  return true;
18017
19223
  }
18018
- function serializeInput(params) {
19224
+ function serializeGenerateContentInput(params) {
18019
19225
  const input = {
18020
19226
  model: params.model,
18021
- contents: serializeContents(params.contents)
19227
+ contents: serializeContentCollection(params.contents)
18022
19228
  };
18023
- if (params.config) {
18024
- const config3 = tryToDict(params.config);
18025
- if (config3) {
18026
- const filteredConfig = {};
18027
- Object.keys(config3).forEach((key) => {
18028
- if (key !== "tools") {
18029
- filteredConfig[key] = config3[key];
18030
- }
18031
- });
18032
- input.config = filteredConfig;
18033
- }
19229
+ const config3 = params.config ? tryToDict(params.config) : null;
19230
+ if (config3) {
19231
+ const filteredConfig = {};
19232
+ Object.keys(config3).forEach((key) => {
19233
+ if (key !== "tools") {
19234
+ filteredConfig[key] = config3[key];
19235
+ }
19236
+ });
19237
+ input.config = filteredConfig;
19238
+ }
19239
+ return input;
19240
+ }
19241
+ function serializeEmbedContentInput(params) {
19242
+ const input = {
19243
+ model: params.model,
19244
+ contents: serializeContentCollection(params.contents)
19245
+ };
19246
+ const config3 = params.config ? tryToDict(params.config) : null;
19247
+ if (config3) {
19248
+ input.config = config3;
18034
19249
  }
18035
19250
  return input;
18036
19251
  }
18037
- function serializeContents(contents) {
19252
+ function serializeContentCollection(contents) {
18038
19253
  if (contents === null || contents === void 0) {
18039
19254
  return null;
18040
19255
  }
@@ -18086,22 +19301,26 @@ function serializePart(part) {
18086
19301
  }
18087
19302
  return part;
18088
19303
  }
18089
- function serializeTools(params) {
18090
- if (!params.config?.tools) {
19304
+ function serializeGenerateContentTools(params) {
19305
+ const config3 = params.config ? tryToDict(params.config) : null;
19306
+ const tools = config3?.tools;
19307
+ if (!Array.isArray(tools)) {
18091
19308
  return null;
18092
19309
  }
18093
19310
  try {
18094
- return params.config.tools.map((tool) => {
18095
- if (typeof tool === "object" && tool.functionDeclarations) {
18096
- return tool;
19311
+ const serializedTools = [];
19312
+ for (const tool of tools) {
19313
+ const toolDict = tryToDict(tool);
19314
+ if (toolDict) {
19315
+ serializedTools.push(toolDict);
18097
19316
  }
18098
- return tool;
18099
- });
19317
+ }
19318
+ return serializedTools.length > 0 ? serializedTools : null;
18100
19319
  } catch {
18101
19320
  return null;
18102
19321
  }
18103
19322
  }
18104
- function extractMetadata(params) {
19323
+ function extractGenerateContentMetadata(params) {
18105
19324
  const metadata = {};
18106
19325
  if (params.model) {
18107
19326
  metadata.model = params.model;
@@ -18116,12 +19335,25 @@ function extractMetadata(params) {
18116
19335
  });
18117
19336
  }
18118
19337
  }
18119
- const tools = serializeTools(params);
19338
+ const tools = serializeGenerateContentTools(params);
18120
19339
  if (tools) {
18121
19340
  metadata.tools = tools;
18122
19341
  }
18123
19342
  return metadata;
18124
19343
  }
19344
+ function extractEmbedContentMetadata(params) {
19345
+ const metadata = {};
19346
+ if (params.model) {
19347
+ metadata.model = params.model;
19348
+ }
19349
+ const config3 = params.config ? tryToDict(params.config) : null;
19350
+ if (config3) {
19351
+ Object.keys(config3).forEach((key) => {
19352
+ metadata[key] = config3[key];
19353
+ });
19354
+ }
19355
+ return metadata;
19356
+ }
18125
19357
  function extractGenerateContentMetrics(response, startTime) {
18126
19358
  const metrics = {};
18127
19359
  if (startTime !== void 0) {
@@ -18135,25 +19367,88 @@ function extractGenerateContentMetrics(response, startTime) {
18135
19367
  }
18136
19368
  return metrics;
18137
19369
  }
18138
- function populateUsageMetrics(metrics, usage) {
18139
- if (usage.promptTokenCount !== void 0) {
18140
- metrics.prompt_tokens = usage.promptTokenCount;
19370
+ function extractEmbedContentMetrics(response, startTime) {
19371
+ const metrics = {};
19372
+ if (startTime !== void 0) {
19373
+ const end = getCurrentUnixTimestamp();
19374
+ metrics.start = startTime;
19375
+ metrics.end = end;
19376
+ metrics.duration = end - startTime;
18141
19377
  }
18142
- if (usage.candidatesTokenCount !== void 0) {
18143
- metrics.completion_tokens = usage.candidatesTokenCount;
19378
+ if (response?.usageMetadata) {
19379
+ populateUsageMetrics(metrics, response.usageMetadata);
18144
19380
  }
18145
- if (usage.totalTokenCount !== void 0) {
18146
- metrics.tokens = usage.totalTokenCount;
19381
+ const embeddingTokenCount = extractEmbedPromptTokenCount(response);
19382
+ if (embeddingTokenCount !== void 0) {
19383
+ metrics.prompt_tokens = embeddingTokenCount;
19384
+ metrics.tokens = embeddingTokenCount;
18147
19385
  }
18148
- if (usage.cachedContentTokenCount !== void 0) {
18149
- metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
19386
+ return metrics;
19387
+ }
19388
+ function extractEmbedPromptTokenCount(response) {
19389
+ if (!response) {
19390
+ return void 0;
18150
19391
  }
18151
- if (usage.thoughtsTokenCount !== void 0) {
18152
- metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
19392
+ const usagePromptTokens = response.usageMetadata?.promptTokenCount;
19393
+ if (typeof usagePromptTokens === "number" && Number.isFinite(usagePromptTokens)) {
19394
+ return usagePromptTokens;
18153
19395
  }
18154
- }
18155
- function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
18156
- const end = getCurrentUnixTimestamp();
19396
+ const usageTotalTokens = response.usageMetadata?.totalTokenCount;
19397
+ if (typeof usageTotalTokens === "number" && Number.isFinite(usageTotalTokens)) {
19398
+ return usageTotalTokens;
19399
+ }
19400
+ const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
19401
+ if (embeddings.length === 0) {
19402
+ return void 0;
19403
+ }
19404
+ let total = 0;
19405
+ let sawAny = false;
19406
+ for (const embedding of embeddings) {
19407
+ const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
19408
+ const tokenCount = embeddingStats?.tokenCount;
19409
+ if (typeof tokenCount === "number" && Number.isFinite(tokenCount)) {
19410
+ total += tokenCount;
19411
+ sawAny = true;
19412
+ }
19413
+ }
19414
+ return sawAny ? total : void 0;
19415
+ }
19416
+ function summarizeEmbedContentOutput(response) {
19417
+ if (!response) {
19418
+ return void 0;
19419
+ }
19420
+ const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
19421
+ if (embeddings.length === 0) {
19422
+ return void 0;
19423
+ }
19424
+ const firstValues = embeddings[0]?.values;
19425
+ if (!Array.isArray(firstValues)) {
19426
+ return void 0;
19427
+ }
19428
+ return {
19429
+ embedding_count: embeddings.length,
19430
+ embedding_length: firstValues.length
19431
+ };
19432
+ }
19433
+ function populateUsageMetrics(metrics, usage) {
19434
+ if (usage.promptTokenCount !== void 0) {
19435
+ metrics.prompt_tokens = usage.promptTokenCount;
19436
+ }
19437
+ if (usage.candidatesTokenCount !== void 0) {
19438
+ metrics.completion_tokens = usage.candidatesTokenCount;
19439
+ }
19440
+ if (usage.totalTokenCount !== void 0) {
19441
+ metrics.tokens = usage.totalTokenCount;
19442
+ }
19443
+ if (usage.cachedContentTokenCount !== void 0) {
19444
+ metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
19445
+ }
19446
+ if (usage.thoughtsTokenCount !== void 0) {
19447
+ metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
19448
+ }
19449
+ }
19450
+ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
19451
+ const end = getCurrentUnixTimestamp();
18157
19452
  const metrics = {
18158
19453
  start: startTime,
18159
19454
  end,
@@ -18168,6 +19463,7 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
18168
19463
  let text = "";
18169
19464
  let thoughtText = "";
18170
19465
  const otherParts = [];
19466
+ let groundingMetadata = void 0;
18171
19467
  let usageMetadata = null;
18172
19468
  let lastResponse = null;
18173
19469
  for (const chunk of chunks) {
@@ -18175,6 +19471,9 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
18175
19471
  if (chunk.usageMetadata) {
18176
19472
  usageMetadata = chunk.usageMetadata;
18177
19473
  }
19474
+ if (chunk.groundingMetadata !== void 0) {
19475
+ groundingMetadata = chunk.groundingMetadata;
19476
+ }
18178
19477
  if (chunk.candidates && Array.isArray(chunk.candidates)) {
18179
19478
  for (const candidate of chunk.candidates) {
18180
19479
  if (candidate.content?.parts) {
@@ -18220,6 +19519,12 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
18220
19519
  if (candidate.finishReason !== void 0) {
18221
19520
  candidateDict.finishReason = candidate.finishReason;
18222
19521
  }
19522
+ if (candidate.groundingMetadata !== void 0) {
19523
+ candidateDict.groundingMetadata = candidate.groundingMetadata;
19524
+ if (groundingMetadata === void 0) {
19525
+ groundingMetadata = candidate.groundingMetadata;
19526
+ }
19527
+ }
18223
19528
  if (candidate.safetyRatings) {
18224
19529
  candidateDict.safetyRatings = candidate.safetyRatings;
18225
19530
  }
@@ -18231,6 +19536,9 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
18231
19536
  aggregated.usageMetadata = usageMetadata;
18232
19537
  populateUsageMetrics(metrics, usageMetadata);
18233
19538
  }
19539
+ if (groundingMetadata !== void 0) {
19540
+ aggregated.groundingMetadata = groundingMetadata;
19541
+ }
18234
19542
  if (text) {
18235
19543
  aggregated.text = text;
18236
19544
  }
@@ -18245,6 +19553,31 @@ function cleanMetrics(metrics) {
18245
19553
  }
18246
19554
  return cleaned;
18247
19555
  }
19556
+ function extractResponseMetadata(response) {
19557
+ const responseDict = tryToDict(response);
19558
+ if (!responseDict) {
19559
+ return void 0;
19560
+ }
19561
+ const metadata = {};
19562
+ const responseGroundingMetadata = responseDict.groundingMetadata;
19563
+ const candidateGroundingMetadata = [];
19564
+ if (Array.isArray(responseDict.candidates)) {
19565
+ for (const candidate of responseDict.candidates) {
19566
+ const candidateDict = tryToDict(candidate);
19567
+ if (candidateDict?.groundingMetadata !== void 0) {
19568
+ candidateGroundingMetadata.push(candidateDict.groundingMetadata);
19569
+ }
19570
+ }
19571
+ }
19572
+ if (responseGroundingMetadata !== void 0) {
19573
+ metadata.groundingMetadata = responseGroundingMetadata;
19574
+ } else if (candidateGroundingMetadata.length === 1) {
19575
+ [metadata.groundingMetadata] = candidateGroundingMetadata;
19576
+ } else if (candidateGroundingMetadata.length > 1) {
19577
+ metadata.groundingMetadata = candidateGroundingMetadata;
19578
+ }
19579
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
19580
+ }
18248
19581
  function tryToDict(obj) {
18249
19582
  if (obj === null || obj === void 0) {
18250
19583
  return null;
@@ -18259,6 +19592,385 @@ function tryToDict(obj) {
18259
19592
  return null;
18260
19593
  }
18261
19594
 
19595
+ // src/instrumentation/plugins/huggingface-channels.ts
19596
+ var huggingFaceChannels = defineChannels("@huggingface/inference", {
19597
+ chatCompletion: channel({
19598
+ channelName: "chatCompletion",
19599
+ kind: "async"
19600
+ }),
19601
+ chatCompletionStream: channel({
19602
+ channelName: "chatCompletionStream",
19603
+ kind: "sync-stream"
19604
+ }),
19605
+ textGeneration: channel({
19606
+ channelName: "textGeneration",
19607
+ kind: "async"
19608
+ }),
19609
+ textGenerationStream: channel({
19610
+ channelName: "textGenerationStream",
19611
+ kind: "sync-stream"
19612
+ }),
19613
+ featureExtraction: channel({
19614
+ channelName: "featureExtraction",
19615
+ kind: "async"
19616
+ })
19617
+ });
19618
+
19619
+ // src/instrumentation/plugins/huggingface-plugin.ts
19620
+ var REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
19621
+ "dimensions",
19622
+ "encoding_format",
19623
+ "endpointUrl",
19624
+ "max_tokens",
19625
+ "model",
19626
+ "provider",
19627
+ "seed",
19628
+ "stop",
19629
+ "stream",
19630
+ "temperature",
19631
+ "top_p"
19632
+ ]);
19633
+ var RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
19634
+ "created",
19635
+ "id",
19636
+ "model",
19637
+ "object"
19638
+ ]);
19639
+ var HuggingFacePlugin = class extends BasePlugin {
19640
+ onEnable() {
19641
+ this.unsubscribers.push(
19642
+ traceAsyncChannel(huggingFaceChannels.chatCompletion, {
19643
+ name: "huggingface.chat_completion",
19644
+ type: "llm" /* LLM */,
19645
+ extractInput: extractChatInputWithMetadata,
19646
+ extractOutput: (result) => result?.choices,
19647
+ extractMetadata: (result) => extractResponseMetadata2(result),
19648
+ extractMetrics: (result) => parseMetricsFromUsage(result?.usage)
19649
+ }),
19650
+ traceSyncStreamChannel(huggingFaceChannels.chatCompletionStream, {
19651
+ name: "huggingface.chat_completion_stream",
19652
+ type: "llm" /* LLM */,
19653
+ extractInput: extractChatInputWithMetadata,
19654
+ patchResult: ({ result, span, startTime }) => patchChatCompletionStream({
19655
+ result,
19656
+ span,
19657
+ startTime
19658
+ })
19659
+ }),
19660
+ traceAsyncChannel(huggingFaceChannels.textGeneration, {
19661
+ name: "huggingface.text_generation",
19662
+ type: "llm" /* LLM */,
19663
+ extractInput: extractTextGenerationInputWithMetadata,
19664
+ extractOutput: (result) => isObject(result) ? { generated_text: result.generated_text } : result,
19665
+ extractMetadata: extractTextGenerationMetadata,
19666
+ extractMetrics: (result) => extractTextGenerationMetrics(result?.details ?? null)
19667
+ }),
19668
+ traceSyncStreamChannel(huggingFaceChannels.textGenerationStream, {
19669
+ name: "huggingface.text_generation_stream",
19670
+ type: "llm" /* LLM */,
19671
+ extractInput: extractTextGenerationInputWithMetadata,
19672
+ patchResult: ({ result, span, startTime }) => patchTextGenerationStream({
19673
+ result,
19674
+ span,
19675
+ startTime
19676
+ })
19677
+ }),
19678
+ traceAsyncChannel(huggingFaceChannels.featureExtraction, {
19679
+ name: "huggingface.feature_extraction",
19680
+ type: "llm" /* LLM */,
19681
+ extractInput: extractFeatureExtractionInputWithMetadata,
19682
+ extractOutput: summarizeFeatureExtractionOutput,
19683
+ extractMetrics: () => ({})
19684
+ })
19685
+ );
19686
+ }
19687
+ onDisable() {
19688
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
19689
+ }
19690
+ };
19691
+ function addProviderMetadata(metadata) {
19692
+ return {
19693
+ ...metadata,
19694
+ provider: metadata.provider ?? "huggingface"
19695
+ };
19696
+ }
19697
+ function normalizeArgs(args) {
19698
+ if (Array.isArray(args)) {
19699
+ return args;
19700
+ }
19701
+ if (isArrayLike2(args)) {
19702
+ return Array.from(args);
19703
+ }
19704
+ return [args];
19705
+ }
19706
+ function isArrayLike2(value) {
19707
+ return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
19708
+ }
19709
+ function getFirstObjectArg(args) {
19710
+ const firstObjectArg = normalizeArgs(args).find((arg) => isObject(arg));
19711
+ return isObject(firstObjectArg) ? firstObjectArg : void 0;
19712
+ }
19713
+ function pickRequestMetadata(params) {
19714
+ if (!params) {
19715
+ return addProviderMetadata({});
19716
+ }
19717
+ const metadata = {};
19718
+ for (const key of REQUEST_METADATA_ALLOWLIST) {
19719
+ const value = params[key];
19720
+ if (value !== void 0) {
19721
+ metadata[key] = value;
19722
+ }
19723
+ }
19724
+ if (isObject(params.parameters)) {
19725
+ metadata.parameters = params.parameters;
19726
+ }
19727
+ return addProviderMetadata(metadata);
19728
+ }
19729
+ function extractChatInputWithMetadata(args) {
19730
+ const params = getFirstObjectArg(args);
19731
+ const { messages, ...rawMetadata } = params ?? {};
19732
+ return {
19733
+ input: messages,
19734
+ metadata: pickRequestMetadata(rawMetadata)
19735
+ };
19736
+ }
19737
+ function extractTextGenerationInputWithMetadata(args) {
19738
+ const params = getFirstObjectArg(args);
19739
+ const { inputs, ...rawMetadata } = params ?? {};
19740
+ return {
19741
+ input: inputs,
19742
+ metadata: pickRequestMetadata(rawMetadata)
19743
+ };
19744
+ }
19745
+ function extractFeatureExtractionInputWithMetadata(args) {
19746
+ const params = getFirstObjectArg(args);
19747
+ const { inputs, ...rawMetadata } = params ?? {};
19748
+ return {
19749
+ input: inputs,
19750
+ metadata: pickRequestMetadata(rawMetadata)
19751
+ };
19752
+ }
19753
+ function extractResponseMetadata2(result) {
19754
+ if (!isObject(result)) {
19755
+ return void 0;
19756
+ }
19757
+ const metadata = {};
19758
+ for (const key of RESPONSE_METADATA_ALLOWLIST) {
19759
+ const value = result[key];
19760
+ if (value !== void 0) {
19761
+ metadata[key] = value;
19762
+ }
19763
+ }
19764
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
19765
+ }
19766
+ function extractTextGenerationMetrics(details) {
19767
+ if (!isObject(details)) {
19768
+ return {};
19769
+ }
19770
+ const promptTokens = Array.isArray(details.prefill) ? details.prefill.length : void 0;
19771
+ const completionTokens = typeof details.generated_tokens === "number" ? details.generated_tokens : Array.isArray(details.tokens) ? details.tokens.length : void 0;
19772
+ const metrics = {};
19773
+ if (promptTokens !== void 0) {
19774
+ metrics.prompt_tokens = promptTokens;
19775
+ }
19776
+ if (completionTokens !== void 0) {
19777
+ metrics.completion_tokens = completionTokens;
19778
+ }
19779
+ if (promptTokens !== void 0 || completionTokens !== void 0) {
19780
+ metrics.tokens = (promptTokens ?? 0) + (completionTokens ?? 0);
19781
+ }
19782
+ return metrics;
19783
+ }
19784
+ function extractTextGenerationMetadata(result) {
19785
+ if (!isObject(result?.details)) {
19786
+ return void 0;
19787
+ }
19788
+ return typeof result.details.finish_reason === "string" ? {
19789
+ finish_reason: result.details.finish_reason
19790
+ } : void 0;
19791
+ }
19792
+ function summarizeFeatureExtractionOutput(result) {
19793
+ if (!Array.isArray(result)) {
19794
+ return void 0;
19795
+ }
19796
+ const first = result[0];
19797
+ if (typeof first === "number") {
19798
+ return { embedding_length: result.length };
19799
+ }
19800
+ if (Array.isArray(first) && first.every((value) => typeof value === "number")) {
19801
+ return {
19802
+ embedding_count: result.length,
19803
+ embedding_length: first.length
19804
+ };
19805
+ }
19806
+ if (Array.isArray(first) && first.length > 0 && Array.isArray(first[0]) && first[0].every((value) => typeof value === "number")) {
19807
+ return {
19808
+ embedding_batch_count: result.length,
19809
+ embedding_count: first.length,
19810
+ embedding_length: first[0].length
19811
+ };
19812
+ }
19813
+ return void 0;
19814
+ }
19815
+ function patchChatCompletionStream(args) {
19816
+ const { result, span, startTime } = args;
19817
+ if (!result || !isAsyncIterable3(result)) {
19818
+ return false;
19819
+ }
19820
+ let firstChunkTime;
19821
+ patchStreamIfNeeded(result, {
19822
+ onChunk: () => {
19823
+ if (firstChunkTime === void 0) {
19824
+ firstChunkTime = getCurrentUnixTimestamp();
19825
+ }
19826
+ },
19827
+ onComplete: (chunks) => {
19828
+ const lastChunk = chunks.at(-1);
19829
+ const responseMetadata = extractResponseMetadata2(lastChunk);
19830
+ const metrics = {
19831
+ ...parseMetricsFromUsage(lastChunk?.usage),
19832
+ ...firstChunkTime !== void 0 ? { time_to_first_token: firstChunkTime - startTime } : {}
19833
+ };
19834
+ span.log({
19835
+ output: aggregateChatCompletionChunks2(chunks),
19836
+ ...responseMetadata ? { metadata: responseMetadata } : {},
19837
+ metrics
19838
+ });
19839
+ span.end();
19840
+ },
19841
+ onError: (error2) => {
19842
+ span.log({
19843
+ error: error2.message
19844
+ });
19845
+ span.end();
19846
+ }
19847
+ });
19848
+ return true;
19849
+ }
19850
+ function patchTextGenerationStream(args) {
19851
+ const { result, span, startTime } = args;
19852
+ if (!result || !isAsyncIterable3(result)) {
19853
+ return false;
19854
+ }
19855
+ let firstChunkTime;
19856
+ patchStreamIfNeeded(result, {
19857
+ onChunk: () => {
19858
+ if (firstChunkTime === void 0) {
19859
+ firstChunkTime = getCurrentUnixTimestamp();
19860
+ }
19861
+ },
19862
+ onComplete: (chunks) => {
19863
+ const lastChunk = chunks.at(-1);
19864
+ const streamMetadata = extractTextGenerationStreamMetadata(chunks);
19865
+ span.log({
19866
+ output: aggregateTextGenerationStreamChunks(chunks),
19867
+ ...streamMetadata ? { metadata: streamMetadata } : {},
19868
+ metrics: {
19869
+ ...extractTextGenerationMetrics(lastChunk?.details ?? null),
19870
+ ...parseMetricsFromUsage(lastChunk?.usage),
19871
+ ...firstChunkTime !== void 0 ? { time_to_first_token: firstChunkTime - startTime } : {}
19872
+ }
19873
+ });
19874
+ span.end();
19875
+ },
19876
+ onError: (error2) => {
19877
+ span.log({
19878
+ error: error2.message
19879
+ });
19880
+ span.end();
19881
+ }
19882
+ });
19883
+ return true;
19884
+ }
19885
+ function aggregateChatCompletionChunks2(chunks) {
19886
+ if (chunks.length === 0) {
19887
+ return void 0;
19888
+ }
19889
+ const aggregatedChoices = /* @__PURE__ */ new Map();
19890
+ for (const chunk of chunks) {
19891
+ for (const choice of chunk.choices ?? []) {
19892
+ const index = typeof choice.index === "number" ? choice.index : 0;
19893
+ const existing = aggregatedChoices.get(index) ?? { content: "" };
19894
+ const delta = isObject(choice.delta) ? choice.delta : void 0;
19895
+ const message = isObject(choice.message) ? choice.message : void 0;
19896
+ if (typeof delta?.content === "string") {
19897
+ existing.content += delta.content;
19898
+ } else if (typeof message?.content === "string") {
19899
+ existing.content = message.content;
19900
+ }
19901
+ if (typeof delta?.role === "string") {
19902
+ existing.role = delta.role;
19903
+ } else if (typeof message?.role === "string") {
19904
+ existing.role = message.role;
19905
+ }
19906
+ if (choice.finish_reason !== void 0) {
19907
+ existing.finish_reason = choice.finish_reason;
19908
+ }
19909
+ aggregatedChoices.set(index, existing);
19910
+ }
19911
+ }
19912
+ return {
19913
+ choices: [...aggregatedChoices.entries()].map(([index, choice]) => ({
19914
+ index,
19915
+ message: {
19916
+ content: choice.content,
19917
+ role: choice.role ?? "assistant"
19918
+ },
19919
+ ...choice.finish_reason !== void 0 ? { finish_reason: choice.finish_reason } : {}
19920
+ }))
19921
+ };
19922
+ }
19923
+ function aggregateTextGenerationStreamChunks(chunks) {
19924
+ if (chunks.length === 0) {
19925
+ return void 0;
19926
+ }
19927
+ let generatedText = "";
19928
+ let finishReason;
19929
+ for (const chunk of chunks) {
19930
+ if (typeof chunk.generated_text === "string") {
19931
+ generatedText = chunk.generated_text;
19932
+ } else if (typeof chunk.token?.text === "string" && !chunk.token.special) {
19933
+ generatedText += chunk.token.text;
19934
+ } else if (Array.isArray(chunk.choices)) {
19935
+ for (const choice of chunk.choices) {
19936
+ if (typeof choice.text === "string") {
19937
+ generatedText += choice.text;
19938
+ }
19939
+ if (choice.finish_reason !== void 0) {
19940
+ finishReason = choice.finish_reason;
19941
+ }
19942
+ }
19943
+ }
19944
+ if (isObject(chunk.details) && typeof chunk.details.finish_reason === "string") {
19945
+ finishReason = chunk.details.finish_reason;
19946
+ }
19947
+ }
19948
+ return {
19949
+ generated_text: generatedText,
19950
+ ...finishReason !== void 0 ? { finish_reason: finishReason } : {}
19951
+ };
19952
+ }
19953
+ function extractTextGenerationStreamMetadata(chunks) {
19954
+ for (let index = chunks.length - 1; index >= 0; index--) {
19955
+ const chunk = chunks[index];
19956
+ if (isObject(chunk?.details) && typeof chunk.details.finish_reason === "string") {
19957
+ return {
19958
+ finish_reason: chunk.details.finish_reason
19959
+ };
19960
+ }
19961
+ if (!Array.isArray(chunk?.choices)) {
19962
+ continue;
19963
+ }
19964
+ for (let choiceIndex = chunk.choices.length - 1; choiceIndex >= 0; choiceIndex--) {
19965
+ const choice = chunk.choices[choiceIndex];
19966
+ if (choice?.finish_reason !== void 0) {
19967
+ return { finish_reason: choice.finish_reason };
19968
+ }
19969
+ }
19970
+ }
19971
+ return void 0;
19972
+ }
19973
+
18262
19974
  // src/instrumentation/plugins/openrouter-agent-channels.ts
18263
19975
  var openRouterAgentChannels = defineChannels("@openrouter/agent", {
18264
19976
  callModel: channel({
@@ -18376,20 +20088,20 @@ var OpenRouterAgentPlugin = class extends BasePlugin {
18376
20088
  });
18377
20089
  }
18378
20090
  };
18379
- function normalizeArgs(args) {
20091
+ function normalizeArgs2(args) {
18380
20092
  if (Array.isArray(args)) {
18381
20093
  return args;
18382
20094
  }
18383
- if (isArrayLike2(args)) {
20095
+ if (isArrayLike3(args)) {
18384
20096
  return Array.from(args);
18385
20097
  }
18386
20098
  return [args];
18387
20099
  }
18388
- function isArrayLike2(value) {
20100
+ function isArrayLike3(value) {
18389
20101
  return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
18390
20102
  }
18391
20103
  function getOpenRouterCallModelRequestArg(args) {
18392
- const normalizedArgs = normalizeArgs(args);
20104
+ const normalizedArgs = normalizeArgs2(args);
18393
20105
  const keyedRequestArg = normalizedArgs.find(
18394
20106
  (arg) => isObject(arg) && ("input" in arg || "model" in arg || "tools" in arg)
18395
20107
  );
@@ -18675,7 +20387,7 @@ function traceToolExecution(args) {
18675
20387
  }
18676
20388
  }
18677
20389
  function publishToolResult(tracingChannel2, event, result) {
18678
- if (isPromiseLike3(result)) {
20390
+ if (isPromiseLike(result)) {
18679
20391
  return result.then(
18680
20392
  (resolved) => {
18681
20393
  event.result = resolved;
@@ -18697,9 +20409,6 @@ function getToolCallId(context2) {
18697
20409
  const toolContext = context2;
18698
20410
  return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
18699
20411
  }
18700
- function isPromiseLike3(value) {
18701
- return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
18702
- }
18703
20412
  var OPENROUTER_WRAPPED_CALL_MODEL_RESULT = Symbol(
18704
20413
  "braintrust.openrouter.wrappedCallModelResult"
18705
20414
  );
@@ -19054,6 +20763,12 @@ var openRouterChannels = defineChannels("@openrouter/sdk", {
19054
20763
  channelName: "embeddings.generate",
19055
20764
  kind: "async"
19056
20765
  }),
20766
+ rerankRerank: channel(
20767
+ {
20768
+ channelName: "rerank.rerank",
20769
+ kind: "async"
20770
+ }
20771
+ ),
19057
20772
  betaResponsesSend: channel({
19058
20773
  channelName: "beta.responses.send",
19059
20774
  kind: "async"
@@ -19146,6 +20861,34 @@ var OpenRouterPlugin = class extends BasePlugin {
19146
20861
  }
19147
20862
  })
19148
20863
  );
20864
+ this.unsubscribers.push(
20865
+ traceAsyncChannel(openRouterChannels.rerankRerank, {
20866
+ name: "openrouter.rerank.rerank",
20867
+ type: "llm" /* LLM */,
20868
+ extractInput: (args) => {
20869
+ const request = getOpenRouterRequestArg(args);
20870
+ const requestBody = isObject(request?.requestBody) ? request.requestBody : {};
20871
+ const httpReferer = request?.httpReferer;
20872
+ const xTitle = request?.xTitle ?? request?.appTitle;
20873
+ const { documents, query, ...metadata } = requestBody;
20874
+ return {
20875
+ input: {
20876
+ documents,
20877
+ query
20878
+ },
20879
+ metadata: buildOpenRouterRerankMetadata(
20880
+ metadata,
20881
+ documents,
20882
+ httpReferer,
20883
+ xTitle
20884
+ )
20885
+ };
20886
+ },
20887
+ extractOutput: (result) => extractOpenRouterRerankOutput(result),
20888
+ extractMetadata: (result) => extractOpenRouterResponseMetadata2(result),
20889
+ extractMetrics: (result) => isObject(result) ? parseOpenRouterMetricsFromUsage2(result.usage) : {}
20890
+ })
20891
+ );
19149
20892
  this.unsubscribers.push(
19150
20893
  traceStreamingChannel(openRouterChannels.betaResponsesSend, {
19151
20894
  name: "openrouter.beta.responses.send",
@@ -19265,20 +21008,20 @@ var OpenRouterPlugin = class extends BasePlugin {
19265
21008
  });
19266
21009
  }
19267
21010
  };
19268
- function normalizeArgs2(args) {
21011
+ function normalizeArgs3(args) {
19269
21012
  if (Array.isArray(args)) {
19270
21013
  return args;
19271
21014
  }
19272
- if (isArrayLike3(args)) {
21015
+ if (isArrayLike4(args)) {
19273
21016
  return Array.from(args);
19274
21017
  }
19275
21018
  return [args];
19276
21019
  }
19277
- function isArrayLike3(value) {
21020
+ function isArrayLike4(value) {
19278
21021
  return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
19279
21022
  }
19280
21023
  function getOpenRouterRequestArg(args) {
19281
- const normalizedArgs = normalizeArgs2(args);
21024
+ const normalizedArgs = normalizeArgs3(args);
19282
21025
  const keyedCandidate = normalizedArgs.find(
19283
21026
  (arg) => isObject(arg) && ("chatGenerationParams" in arg || "requestBody" in arg || "openResponsesRequest" in arg)
19284
21027
  );
@@ -19289,7 +21032,7 @@ function getOpenRouterRequestArg(args) {
19289
21032
  return isObject(firstObjectArg) ? firstObjectArg : void 0;
19290
21033
  }
19291
21034
  function getOpenRouterCallModelRequestArg2(args) {
19292
- const firstObjectArg = normalizeArgs2(args).find((arg) => isObject(arg));
21035
+ const firstObjectArg = normalizeArgs3(args).find((arg) => isObject(arg));
19293
21036
  return isObject(firstObjectArg) ? firstObjectArg : void 0;
19294
21037
  }
19295
21038
  var TOKEN_NAME_MAP3 = {
@@ -19459,6 +21202,13 @@ function buildOpenRouterEmbeddingMetadata(metadata, httpReferer, xTitle) {
19459
21202
  embedding_model: normalized.model
19460
21203
  } : normalized;
19461
21204
  }
21205
+ function buildOpenRouterRerankMetadata(metadata, documents, httpReferer, xTitle) {
21206
+ const normalized = buildOpenRouterMetadata2(metadata, httpReferer, xTitle);
21207
+ return {
21208
+ ...normalized,
21209
+ ...Array.isArray(documents) ? { document_count: documents.length } : {}
21210
+ };
21211
+ }
19462
21212
  function extractOpenRouterCallModelInput2(request) {
19463
21213
  return isObject(request) && "input" in request ? sanitizeOpenRouterLoggedValue2(request.input) : void 0;
19464
21214
  }
@@ -19478,7 +21228,7 @@ function extractOpenRouterResponseMetadata2(result) {
19478
21228
  const metadataRecord = isObject(sanitized) ? sanitized : {};
19479
21229
  const { model, provider, ...rest } = metadataRecord;
19480
21230
  const normalizedModel = parseOpenRouterModelString2(model);
19481
- const normalizedProvider = (typeof provider === "string" ? provider : void 0) || normalizedModel.provider;
21231
+ const normalizedProvider = (typeof provider === "string" ? provider.toLowerCase() : void 0) || normalizedModel.provider;
19482
21232
  const usageMetadata = extractOpenRouterUsageMetadata2(usage);
19483
21233
  const combined = {
19484
21234
  ...rest,
@@ -19497,6 +21247,15 @@ function extractOpenRouterResponseOutput2(response, fallbackOutput) {
19497
21247
  }
19498
21248
  return void 0;
19499
21249
  }
21250
+ function extractOpenRouterRerankOutput(result) {
21251
+ if (!isObject(result) || !Array.isArray(result.results)) {
21252
+ return void 0;
21253
+ }
21254
+ return result.results.slice(0, 100).map((item) => ({
21255
+ index: isObject(item) && typeof item.index === "number" ? item.index : void 0,
21256
+ relevance_score: isObject(item) && typeof item.relevanceScore === "number" ? item.relevanceScore : isObject(item) && typeof item.relevance_score === "number" ? item.relevance_score : void 0
21257
+ }));
21258
+ }
19500
21259
  var OPENROUTER_WRAPPED_TOOL2 = Symbol("braintrust.openrouter.wrappedTool");
19501
21260
  function patchOpenRouterCallModelRequestTools2(request) {
19502
21261
  if (!Array.isArray(request.tools) || request.tools.length === 0) {
@@ -19567,7 +21326,7 @@ function traceToolExecution2(args) {
19567
21326
  }
19568
21327
  }
19569
21328
  function publishToolResult2(tracingChannel2, event, result) {
19570
- if (isPromiseLike4(result)) {
21329
+ if (isPromiseLike(result)) {
19571
21330
  return result.then(
19572
21331
  (resolved) => {
19573
21332
  event.result = resolved;
@@ -19589,9 +21348,6 @@ function getToolCallId2(context2) {
19589
21348
  const toolContext = context2;
19590
21349
  return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
19591
21350
  }
19592
- function isPromiseLike4(value) {
19593
- return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
19594
- }
19595
21351
  function aggregateOpenRouterChatChunks(chunks) {
19596
21352
  let role;
19597
21353
  let content = "";
@@ -20231,20 +21987,20 @@ var MISTRAL_RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
20231
21987
  function camelToSnake3(value) {
20232
21988
  return value.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
20233
21989
  }
20234
- function normalizeArgs3(args) {
21990
+ function normalizeArgs4(args) {
20235
21991
  if (Array.isArray(args)) {
20236
21992
  return args;
20237
21993
  }
20238
- if (isArrayLike4(args)) {
21994
+ if (isArrayLike5(args)) {
20239
21995
  return Array.from(args);
20240
21996
  }
20241
21997
  return [args];
20242
21998
  }
20243
- function isArrayLike4(value) {
21999
+ function isArrayLike5(value) {
20244
22000
  return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
20245
22001
  }
20246
22002
  function getMistralRequestArg(args) {
20247
- const firstObjectArg = normalizeArgs3(args).find((arg) => isObject(arg));
22003
+ const firstObjectArg = normalizeArgs4(args).find((arg) => isObject(arg));
20248
22004
  return isObject(firstObjectArg) ? firstObjectArg : void 0;
20249
22005
  }
20250
22006
  function addMistralProviderMetadata(metadata) {
@@ -20323,229 +22079,1440 @@ function extractMistralMetrics(usage, startTime) {
20323
22079
  }
20324
22080
  return metrics;
20325
22081
  }
20326
- function extractMistralStreamOutput(result) {
20327
- return isObject(result) ? result.choices : void 0;
20328
- }
20329
- function extractMistralStreamingMetrics(result, startTime) {
20330
- const metrics = isObject(result) ? parseMistralMetricsFromUsage(result.usage) : {};
20331
- if (startTime) {
20332
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
22082
+ function extractMistralStreamOutput(result) {
22083
+ return isObject(result) ? result.choices : void 0;
22084
+ }
22085
+ function extractMistralStreamingMetrics(result, startTime) {
22086
+ const metrics = isObject(result) ? parseMistralMetricsFromUsage(result.usage) : {};
22087
+ if (startTime) {
22088
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
22089
+ }
22090
+ return metrics;
22091
+ }
22092
+ function extractDeltaText(content) {
22093
+ if (typeof content === "string") {
22094
+ return content;
22095
+ }
22096
+ if (!Array.isArray(content)) {
22097
+ return void 0;
22098
+ }
22099
+ const textParts = content.map((part) => {
22100
+ if (!isObject(part) || part.type !== "text") {
22101
+ return "";
22102
+ }
22103
+ return typeof part.text === "string" ? part.text : "";
22104
+ }).filter((part) => part.length > 0);
22105
+ return textParts.length > 0 ? textParts.join("") : void 0;
22106
+ }
22107
+ function getDeltaToolCalls(delta) {
22108
+ const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
22109
+ return toolCalls.filter((toolCall) => isObject(toolCall));
22110
+ }
22111
+ function getToolCallIndex(toolCall) {
22112
+ return typeof toolCall.index === "number" && toolCall.index >= 0 ? toolCall.index : void 0;
22113
+ }
22114
+ function createMergedToolCallDelta(delta) {
22115
+ return {
22116
+ ...delta,
22117
+ function: {
22118
+ ...delta.function,
22119
+ arguments: typeof delta.function?.arguments === "string" ? delta.function.arguments : ""
22120
+ }
22121
+ };
22122
+ }
22123
+ function mergeToolCallDeltaPair(current, delta) {
22124
+ const currentArguments = typeof current.function?.arguments === "string" ? current.function.arguments : "";
22125
+ const deltaArguments = typeof delta.function?.arguments === "string" ? delta.function.arguments : "";
22126
+ return {
22127
+ ...current,
22128
+ ...delta,
22129
+ function: {
22130
+ ...current.function || {},
22131
+ ...delta.function || {},
22132
+ arguments: `${currentArguments}${deltaArguments}`
22133
+ }
22134
+ };
22135
+ }
22136
+ function mergeToolCallDeltas(toolCalls, deltas) {
22137
+ if (deltas.length === 0) {
22138
+ return toolCalls;
22139
+ }
22140
+ const merged = toolCalls ? [...toolCalls] : [];
22141
+ const indexToPosition = /* @__PURE__ */ new Map();
22142
+ const idToPosition = /* @__PURE__ */ new Map();
22143
+ for (const [position, toolCall] of merged.entries()) {
22144
+ const index = getToolCallIndex(toolCall);
22145
+ if (index !== void 0 && !indexToPosition.has(index)) {
22146
+ indexToPosition.set(index, position);
22147
+ }
22148
+ if (typeof toolCall.id === "string" && !idToPosition.has(toolCall.id)) {
22149
+ idToPosition.set(toolCall.id, position);
22150
+ }
22151
+ }
22152
+ for (const delta of deltas) {
22153
+ const deltaIndex = getToolCallIndex(delta);
22154
+ const existingByIndex = deltaIndex !== void 0 ? indexToPosition.get(deltaIndex) : void 0;
22155
+ const existingById = typeof delta.id === "string" ? idToPosition.get(delta.id) : void 0;
22156
+ const existingPosition = existingByIndex ?? existingById;
22157
+ if (existingPosition === void 0) {
22158
+ const newToolCall = createMergedToolCallDelta(delta);
22159
+ merged.push(newToolCall);
22160
+ const newPosition = merged.length - 1;
22161
+ const newIndex = getToolCallIndex(newToolCall);
22162
+ if (newIndex !== void 0 && !indexToPosition.has(newIndex)) {
22163
+ indexToPosition.set(newIndex, newPosition);
22164
+ }
22165
+ if (typeof newToolCall.id === "string" && !idToPosition.has(newToolCall.id)) {
22166
+ idToPosition.set(newToolCall.id, newPosition);
22167
+ }
22168
+ continue;
22169
+ }
22170
+ const mergedToolCall = mergeToolCallDeltaPair(
22171
+ merged[existingPosition],
22172
+ delta
22173
+ );
22174
+ merged[existingPosition] = mergedToolCall;
22175
+ const mergedIndex = getToolCallIndex(mergedToolCall);
22176
+ if (mergedIndex !== void 0 && !indexToPosition.has(mergedIndex)) {
22177
+ indexToPosition.set(mergedIndex, existingPosition);
22178
+ }
22179
+ if (typeof mergedToolCall.id === "string" && !idToPosition.has(mergedToolCall.id)) {
22180
+ idToPosition.set(mergedToolCall.id, existingPosition);
22181
+ }
22182
+ }
22183
+ return merged.length > 0 ? merged : void 0;
22184
+ }
22185
+ function getChoiceFinishReason(choice) {
22186
+ if (typeof choice.finishReason === "string" || choice.finishReason === null) {
22187
+ return choice.finishReason;
22188
+ }
22189
+ if (typeof choice.finish_reason === "string" || choice.finish_reason === null) {
22190
+ return choice.finish_reason;
22191
+ }
22192
+ return void 0;
22193
+ }
22194
+ function parseMistralMetricsFromUsage(usage) {
22195
+ if (!isObject(usage)) {
22196
+ return {};
22197
+ }
22198
+ const metrics = {};
22199
+ for (const [name, value] of Object.entries(usage)) {
22200
+ if (typeof value === "number") {
22201
+ metrics[TOKEN_NAME_MAP4[name] || camelToSnake3(name)] = value;
22202
+ continue;
22203
+ }
22204
+ if (!isObject(value)) {
22205
+ continue;
22206
+ }
22207
+ const prefix = TOKEN_DETAIL_PREFIX_MAP3[name];
22208
+ if (!prefix) {
22209
+ continue;
22210
+ }
22211
+ for (const [nestedName, nestedValue] of Object.entries(value)) {
22212
+ if (typeof nestedValue !== "number") {
22213
+ continue;
22214
+ }
22215
+ metrics[`${prefix}_${camelToSnake3(nestedName)}`] = nestedValue;
22216
+ }
22217
+ }
22218
+ return metrics;
22219
+ }
22220
+ function aggregateMistralStreamChunks(chunks) {
22221
+ const choiceAccumulators = /* @__PURE__ */ new Map();
22222
+ const indexToAccumulatorKey = /* @__PURE__ */ new Map();
22223
+ const positionToAccumulatorKey = /* @__PURE__ */ new Map();
22224
+ let nextAccumulatorOrder = 0;
22225
+ let metrics = {};
22226
+ let metadata;
22227
+ for (const event of chunks) {
22228
+ const chunk = isMistralChatCompletionChunk(event?.data) ? event.data : void 0;
22229
+ if (!chunk) {
22230
+ continue;
22231
+ }
22232
+ if (isObject(chunk.usage)) {
22233
+ metrics = {
22234
+ ...metrics,
22235
+ ...parseMistralMetricsFromUsage(chunk.usage)
22236
+ };
22237
+ }
22238
+ const chunkMetadata = extractMistralResponseMetadata(chunk);
22239
+ if (chunkMetadata) {
22240
+ metadata = { ...metadata || {}, ...chunkMetadata };
22241
+ }
22242
+ for (const [choicePosition, rawChoice] of (chunk.choices || []).entries()) {
22243
+ if (!isMistralChunkChoice(rawChoice)) {
22244
+ continue;
22245
+ }
22246
+ const choice = rawChoice;
22247
+ const choiceIndex = typeof choice.index === "number" && choice.index >= 0 ? choice.index : void 0;
22248
+ let accumulatorKey = choiceIndex !== void 0 ? indexToAccumulatorKey.get(choiceIndex) : void 0;
22249
+ if (!accumulatorKey) {
22250
+ accumulatorKey = positionToAccumulatorKey.get(choicePosition);
22251
+ }
22252
+ if (!accumulatorKey) {
22253
+ const initialIndex = choiceIndex ?? choicePosition;
22254
+ const keyPrefix = choiceIndex !== void 0 ? "index" : "position";
22255
+ accumulatorKey = `${keyPrefix}:${initialIndex}`;
22256
+ choiceAccumulators.set(accumulatorKey, {
22257
+ index: initialIndex,
22258
+ order: nextAccumulatorOrder++
22259
+ });
22260
+ }
22261
+ const accumulator = choiceAccumulators.get(accumulatorKey);
22262
+ if (!accumulator) {
22263
+ continue;
22264
+ }
22265
+ if (choiceIndex !== void 0) {
22266
+ accumulator.index = choiceIndex;
22267
+ indexToAccumulatorKey.set(choiceIndex, accumulatorKey);
22268
+ }
22269
+ positionToAccumulatorKey.set(choicePosition, accumulatorKey);
22270
+ const delta = isObject(choice.delta) ? choice.delta : void 0;
22271
+ if (delta) {
22272
+ if (!accumulator.role && typeof delta.role === "string") {
22273
+ accumulator.role = delta.role;
22274
+ }
22275
+ const deltaText = extractDeltaText(delta.content);
22276
+ if (deltaText) {
22277
+ accumulator.content = `${accumulator.content || ""}${deltaText}`;
22278
+ }
22279
+ accumulator.toolCalls = mergeToolCallDeltas(
22280
+ accumulator.toolCalls,
22281
+ getDeltaToolCalls(delta)
22282
+ );
22283
+ }
22284
+ const choiceFinishReason = getChoiceFinishReason(choice);
22285
+ if (choiceFinishReason !== void 0) {
22286
+ accumulator.finishReason = choiceFinishReason;
22287
+ }
22288
+ }
22289
+ }
22290
+ const output = Array.from(choiceAccumulators.values()).sort(
22291
+ (left, right) => left.index === right.index ? left.order - right.order : left.index - right.index
22292
+ ).map((choice) => ({
22293
+ index: choice.index,
22294
+ message: {
22295
+ ...choice.role ? { role: choice.role } : {},
22296
+ content: choice.content ?? null,
22297
+ ...choice.toolCalls ? { toolCalls: choice.toolCalls } : {}
22298
+ },
22299
+ ...choice.finishReason !== void 0 ? { finishReason: choice.finishReason } : {}
22300
+ }));
22301
+ return {
22302
+ output,
22303
+ metrics,
22304
+ ...metadata ? { metadata } : {}
22305
+ };
22306
+ }
22307
+
22308
+ // src/instrumentation/plugins/google-adk-channels.ts
22309
+ var googleADKChannels = defineChannels("@google/adk", {
22310
+ runnerRunAsync: channel({
22311
+ channelName: "runner.runAsync",
22312
+ kind: "sync-stream"
22313
+ }),
22314
+ agentRunAsync: channel({
22315
+ channelName: "agent.runAsync",
22316
+ kind: "sync-stream"
22317
+ }),
22318
+ toolRunAsync: channel({
22319
+ channelName: "tool.runAsync",
22320
+ kind: "async"
22321
+ })
22322
+ });
22323
+
22324
+ // src/instrumentation/plugins/google-adk-plugin.ts
22325
+ var GoogleADKPlugin = class extends BasePlugin {
22326
+ activeRunnerSpans = /* @__PURE__ */ new Map();
22327
+ activeAgentSpans = /* @__PURE__ */ new Map();
22328
+ onEnable() {
22329
+ this.subscribeToRunnerRunAsync();
22330
+ this.subscribeToAgentRunAsync();
22331
+ this.subscribeToToolRunAsync();
22332
+ }
22333
+ onDisable() {
22334
+ for (const unsubscribe of this.unsubscribers) {
22335
+ unsubscribe();
22336
+ }
22337
+ this.unsubscribers = [];
22338
+ this.activeRunnerSpans.clear();
22339
+ this.activeAgentSpans.clear();
22340
+ }
22341
+ subscribeToRunnerRunAsync() {
22342
+ const tracingChannel2 = googleADKChannels.runnerRunAsync.tracingChannel();
22343
+ const states = /* @__PURE__ */ new WeakMap();
22344
+ const createState = (event) => {
22345
+ const params = event.arguments[0] ?? {};
22346
+ const contextKey = extractRunnerContextKey(params);
22347
+ const span = startSpan({
22348
+ name: "Google ADK Runner",
22349
+ spanAttributes: {
22350
+ type: "task" /* TASK */
22351
+ }
22352
+ });
22353
+ const startTime = getCurrentUnixTimestamp();
22354
+ try {
22355
+ const metadata = extractRunnerMetadata(params);
22356
+ span.log({
22357
+ input: extractRunnerInput(params),
22358
+ metadata
22359
+ });
22360
+ } catch {
22361
+ }
22362
+ if (contextKey) {
22363
+ this.activeRunnerSpans.set(contextKey, span);
22364
+ }
22365
+ return { span, startTime, events: [], contextKey };
22366
+ };
22367
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart3(
22368
+ tracingChannel2,
22369
+ states,
22370
+ createState
22371
+ );
22372
+ const handlers = {
22373
+ start: (event) => {
22374
+ ensureState(states, event, () => createState(event));
22375
+ },
22376
+ end: (event) => {
22377
+ const state = states.get(event);
22378
+ if (!state) {
22379
+ return;
22380
+ }
22381
+ const result = event.result;
22382
+ if (isAsyncIterable3(result)) {
22383
+ bindAsyncIterableToCurrentSpan(result, state.span);
22384
+ patchStreamIfNeeded(result, {
22385
+ onChunk: (adkEvent) => {
22386
+ state.events.push(adkEvent);
22387
+ },
22388
+ onComplete: () => {
22389
+ finalizeRunnerSpan(state, this.activeRunnerSpans);
22390
+ states.delete(event);
22391
+ },
22392
+ onError: (error2) => {
22393
+ cleanupActiveRunnerSpan(state, this.activeRunnerSpans);
22394
+ state.span.log({ error: error2.message });
22395
+ state.span.end();
22396
+ states.delete(event);
22397
+ }
22398
+ });
22399
+ return;
22400
+ }
22401
+ try {
22402
+ state.span.log({ output: result });
22403
+ } finally {
22404
+ cleanupActiveRunnerSpan(state, this.activeRunnerSpans);
22405
+ state.span.end();
22406
+ states.delete(event);
22407
+ }
22408
+ },
22409
+ error: (event) => {
22410
+ const state = states.get(event);
22411
+ if (!state || !event.error) {
22412
+ return;
22413
+ }
22414
+ cleanupActiveRunnerSpan(state, this.activeRunnerSpans);
22415
+ state.span.log({ error: event.error.message });
22416
+ state.span.end();
22417
+ states.delete(event);
22418
+ }
22419
+ };
22420
+ tracingChannel2.subscribe(handlers);
22421
+ this.unsubscribers.push(() => {
22422
+ unbindCurrentSpanStore?.();
22423
+ tracingChannel2.unsubscribe(handlers);
22424
+ });
22425
+ }
22426
+ subscribeToAgentRunAsync() {
22427
+ const tracingChannel2 = googleADKChannels.agentRunAsync.tracingChannel();
22428
+ const states = /* @__PURE__ */ new WeakMap();
22429
+ const createState = (event) => {
22430
+ const parentContext = event.arguments[0];
22431
+ const agentName = extractAgentName(parentContext);
22432
+ const runnerParentSpan = findRunnerParentSpan(
22433
+ parentContext,
22434
+ this.activeRunnerSpans
22435
+ );
22436
+ const contextKey = extractInvocationContextKey(parentContext);
22437
+ const span = startSpan({
22438
+ name: agentName ? `Agent: ${agentName}` : "Google ADK Agent",
22439
+ spanAttributes: {
22440
+ type: "task" /* TASK */
22441
+ },
22442
+ ...runnerParentSpan ? {
22443
+ parentSpanIds: {
22444
+ spanId: runnerParentSpan.spanId,
22445
+ rootSpanId: runnerParentSpan.rootSpanId
22446
+ }
22447
+ } : {}
22448
+ });
22449
+ const startTime = getCurrentUnixTimestamp();
22450
+ try {
22451
+ const metadata = {
22452
+ provider: "google-adk"
22453
+ };
22454
+ if (agentName) {
22455
+ metadata["google_adk.agent_name"] = agentName;
22456
+ }
22457
+ const modelName = extractModelName(parentContext);
22458
+ if (modelName) {
22459
+ metadata.model = modelName;
22460
+ }
22461
+ span.log({ metadata });
22462
+ } catch {
22463
+ }
22464
+ if (contextKey && agentName) {
22465
+ this.activeAgentSpans.set(agentContextKey(contextKey, agentName), span);
22466
+ }
22467
+ return { span, startTime, events: [], contextKey, name: agentName };
22468
+ };
22469
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart3(
22470
+ tracingChannel2,
22471
+ states,
22472
+ createState
22473
+ );
22474
+ const handlers = {
22475
+ start: (event) => {
22476
+ ensureState(states, event, () => createState(event));
22477
+ },
22478
+ end: (event) => {
22479
+ const state = states.get(event);
22480
+ if (!state) {
22481
+ return;
22482
+ }
22483
+ const result = event.result;
22484
+ if (isAsyncIterable3(result)) {
22485
+ bindAsyncIterableToCurrentSpan(result, state.span);
22486
+ patchStreamIfNeeded(result, {
22487
+ onChunk: (adkEvent) => {
22488
+ state.events.push(adkEvent);
22489
+ },
22490
+ onComplete: () => {
22491
+ finalizeAgentSpan(state, this.activeAgentSpans);
22492
+ states.delete(event);
22493
+ },
22494
+ onError: (error2) => {
22495
+ cleanupActiveAgentSpan(state, this.activeAgentSpans);
22496
+ state.span.log({ error: error2.message });
22497
+ state.span.end();
22498
+ states.delete(event);
22499
+ }
22500
+ });
22501
+ return;
22502
+ }
22503
+ try {
22504
+ state.span.log({ output: result });
22505
+ } finally {
22506
+ cleanupActiveAgentSpan(state, this.activeAgentSpans);
22507
+ state.span.end();
22508
+ states.delete(event);
22509
+ }
22510
+ },
22511
+ error: (event) => {
22512
+ const state = states.get(event);
22513
+ if (!state || !event.error) {
22514
+ return;
22515
+ }
22516
+ cleanupActiveAgentSpan(state, this.activeAgentSpans);
22517
+ state.span.log({ error: event.error.message });
22518
+ state.span.end();
22519
+ states.delete(event);
22520
+ }
22521
+ };
22522
+ tracingChannel2.subscribe(handlers);
22523
+ this.unsubscribers.push(() => {
22524
+ unbindCurrentSpanStore?.();
22525
+ tracingChannel2.unsubscribe(handlers);
22526
+ });
22527
+ }
22528
+ subscribeToToolRunAsync() {
22529
+ const tracingChannel2 = googleADKChannels.toolRunAsync.tracingChannel();
22530
+ const states = /* @__PURE__ */ new WeakMap();
22531
+ const handlers = {
22532
+ start: (event) => {
22533
+ const req = event.arguments[0] ?? {};
22534
+ const tool = event.self;
22535
+ const toolName = extractToolName(req, tool);
22536
+ const parentSpan = findToolParentSpan(
22537
+ req,
22538
+ this.activeAgentSpans,
22539
+ this.activeRunnerSpans
22540
+ );
22541
+ const createSpan = () => startSpan({
22542
+ name: toolName ? `tool: ${toolName}` : "Google ADK Tool",
22543
+ spanAttributes: {
22544
+ type: "tool" /* TOOL */
22545
+ },
22546
+ event: {
22547
+ input: req.args,
22548
+ metadata: {
22549
+ provider: "google-adk",
22550
+ ...toolName && { "google_adk.tool_name": toolName },
22551
+ ...extractToolCallId(req) && {
22552
+ "google_adk.tool_call_id": extractToolCallId(req)
22553
+ }
22554
+ }
22555
+ }
22556
+ });
22557
+ const span = parentSpan ? withCurrent(parentSpan, () => createSpan()) : createSpan();
22558
+ const startTime = getCurrentUnixTimestamp();
22559
+ states.set(event, { span, startTime });
22560
+ },
22561
+ asyncEnd: (event) => {
22562
+ const state = states.get(event);
22563
+ if (!state) {
22564
+ return;
22565
+ }
22566
+ try {
22567
+ const metrics = {};
22568
+ const end = getCurrentUnixTimestamp();
22569
+ metrics.start = state.startTime;
22570
+ metrics.end = end;
22571
+ metrics.duration = end - state.startTime;
22572
+ state.span.log({
22573
+ output: event.result,
22574
+ metrics: cleanMetrics2(metrics)
22575
+ });
22576
+ } finally {
22577
+ state.span.end();
22578
+ states.delete(event);
22579
+ }
22580
+ },
22581
+ error: (event) => {
22582
+ const state = states.get(event);
22583
+ if (!state || !event.error) {
22584
+ return;
22585
+ }
22586
+ state.span.log({ error: event.error.message });
22587
+ state.span.end();
22588
+ states.delete(event);
22589
+ }
22590
+ };
22591
+ tracingChannel2.subscribe(handlers);
22592
+ this.unsubscribers.push(() => {
22593
+ tracingChannel2.unsubscribe(handlers);
22594
+ });
22595
+ }
22596
+ };
22597
+ function ensureState(states, event, create) {
22598
+ const existing = states.get(event);
22599
+ if (existing) {
22600
+ return existing;
22601
+ }
22602
+ const created = create();
22603
+ states.set(event, created);
22604
+ return created;
22605
+ }
22606
+ function bindAsyncIterableToCurrentSpan(stream, span) {
22607
+ if (!isAsyncIterable3(stream)) {
22608
+ return stream;
22609
+ }
22610
+ if (Object.isFrozen(stream) || Object.isSealed(stream)) {
22611
+ return stream;
22612
+ }
22613
+ if ("next" in stream && typeof stream.next === "function") {
22614
+ if ("__braintrust_current_span_bound" in stream) {
22615
+ return stream;
22616
+ }
22617
+ try {
22618
+ const iterator = stream;
22619
+ const originalNext = iterator.next.bind(iterator);
22620
+ iterator.next = (...args) => withCurrent(span, () => originalNext(...args));
22621
+ if (typeof iterator.return === "function") {
22622
+ const originalReturn = iterator.return.bind(iterator);
22623
+ iterator.return = (...args) => withCurrent(span, () => originalReturn(...args));
22624
+ }
22625
+ if (typeof iterator.throw === "function") {
22626
+ const originalThrow = iterator.throw.bind(iterator);
22627
+ iterator.throw = (...args) => withCurrent(span, () => originalThrow(...args));
22628
+ }
22629
+ Object.defineProperty(stream, "__braintrust_current_span_bound", {
22630
+ value: true
22631
+ });
22632
+ return stream;
22633
+ } catch {
22634
+ return stream;
22635
+ }
22636
+ }
22637
+ const originalIteratorFn = stream[Symbol.asyncIterator];
22638
+ if ("__braintrust_current_span_bound" in originalIteratorFn && originalIteratorFn.__braintrust_current_span_bound) {
22639
+ return stream;
22640
+ }
22641
+ try {
22642
+ const patchedIteratorFn = function() {
22643
+ const iterator = originalIteratorFn.call(this);
22644
+ const originalNext = iterator.next.bind(iterator);
22645
+ iterator.next = (...args) => withCurrent(span, () => originalNext(...args));
22646
+ if (typeof iterator.return === "function") {
22647
+ const originalReturn = iterator.return.bind(iterator);
22648
+ iterator.return = (...args) => withCurrent(span, () => originalReturn(...args));
22649
+ }
22650
+ if (typeof iterator.throw === "function") {
22651
+ const originalThrow = iterator.throw.bind(iterator);
22652
+ iterator.throw = (...args) => withCurrent(span, () => originalThrow(...args));
22653
+ }
22654
+ return iterator;
22655
+ };
22656
+ Object.defineProperty(
22657
+ patchedIteratorFn,
22658
+ "__braintrust_current_span_bound",
22659
+ {
22660
+ value: true
22661
+ }
22662
+ );
22663
+ stream[Symbol.asyncIterator] = patchedIteratorFn;
22664
+ } catch {
22665
+ return stream;
22666
+ }
22667
+ return stream;
22668
+ }
22669
+ function bindCurrentSpanStoreToStart3(tracingChannel2, states, create) {
22670
+ const state = _internalGetGlobalState();
22671
+ const contextManager = state?.contextManager;
22672
+ const startChannel = tracingChannel2.start;
22673
+ const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
22674
+ if (!startChannel?.bindStore || !currentSpanStore) {
22675
+ return void 0;
22676
+ }
22677
+ startChannel.bindStore(currentSpanStore, (event) => {
22678
+ const span = ensureState(
22679
+ states,
22680
+ event,
22681
+ () => create(event)
22682
+ ).span;
22683
+ return contextManager.wrapSpanForStore(span);
22684
+ });
22685
+ return () => {
22686
+ startChannel.unbindStore?.(currentSpanStore);
22687
+ };
22688
+ }
22689
+ function extractRunnerContextKey(paramsOrContext) {
22690
+ const directUserId = "userId" in paramsOrContext ? paramsOrContext.userId : void 0;
22691
+ const directSessionId = "sessionId" in paramsOrContext ? paramsOrContext.sessionId : void 0;
22692
+ if (typeof directUserId === "string" && typeof directSessionId === "string") {
22693
+ return `${directUserId}:${directSessionId}`;
22694
+ }
22695
+ const invocationContext = paramsOrContext;
22696
+ return extractInvocationContextKey(invocationContext);
22697
+ }
22698
+ function extractInvocationContextKey(parentContext) {
22699
+ const session = parentContext?.session;
22700
+ const userId = session?.userId;
22701
+ const sessionId = session?.id;
22702
+ if (typeof userId !== "string" || typeof sessionId !== "string") {
22703
+ return void 0;
22704
+ }
22705
+ return `${userId}:${sessionId}`;
22706
+ }
22707
+ function findRunnerParentSpan(parentContext, activeRunnerSpans) {
22708
+ const contextKey = extractInvocationContextKey(parentContext);
22709
+ return contextKey ? activeRunnerSpans.get(contextKey) : void 0;
22710
+ }
22711
+ function cleanupActiveRunnerSpan(state, activeRunnerSpans) {
22712
+ if (state.contextKey) {
22713
+ activeRunnerSpans.delete(state.contextKey);
22714
+ }
22715
+ }
22716
+ function agentContextKey(contextKey, agentName) {
22717
+ return `${contextKey}:${agentName}`;
22718
+ }
22719
+ function cleanupActiveAgentSpan(state, activeAgentSpans) {
22720
+ if (state.contextKey && state.name) {
22721
+ activeAgentSpans.delete(agentContextKey(state.contextKey, state.name));
22722
+ }
22723
+ }
22724
+ function extractRunnerInput(paramsOrContext) {
22725
+ const content = "newMessage" in paramsOrContext ? paramsOrContext.newMessage : paramsOrContext.userContent;
22726
+ if (!content || typeof content !== "object") {
22727
+ return void 0;
22728
+ }
22729
+ const normalizedContent = content;
22730
+ if (normalizedContent.parts && Array.isArray(normalizedContent.parts)) {
22731
+ const textParts = normalizedContent.parts.filter((p) => p.text !== void 0).map((p) => p.text);
22732
+ if (textParts.length > 0) {
22733
+ return {
22734
+ messages: [
22735
+ {
22736
+ role: normalizedContent.role ?? "user",
22737
+ content: textParts.join("")
22738
+ }
22739
+ ]
22740
+ };
22741
+ }
22742
+ }
22743
+ return { messages: [normalizedContent] };
22744
+ }
22745
+ function extractRunnerMetadata(paramsOrContext) {
22746
+ const metadata = {
22747
+ provider: "google-adk"
22748
+ };
22749
+ const directUserId = "userId" in paramsOrContext ? paramsOrContext.userId : void 0;
22750
+ const directSessionId = "sessionId" in paramsOrContext ? paramsOrContext.sessionId : void 0;
22751
+ if (typeof directUserId === "string") {
22752
+ metadata["google_adk.user_id"] = directUserId;
22753
+ }
22754
+ if (typeof directSessionId === "string") {
22755
+ metadata["google_adk.session_id"] = directSessionId;
22756
+ }
22757
+ const session = "session" in paramsOrContext ? paramsOrContext.session : void 0;
22758
+ if (metadata["google_adk.user_id"] === void 0 && typeof session?.userId === "string") {
22759
+ metadata["google_adk.user_id"] = session.userId;
22760
+ }
22761
+ if (metadata["google_adk.session_id"] === void 0 && typeof session?.id === "string") {
22762
+ metadata["google_adk.session_id"] = session.id;
22763
+ }
22764
+ return metadata;
22765
+ }
22766
+ function extractAgentName(parentContext) {
22767
+ if (!parentContext) {
22768
+ return void 0;
22769
+ }
22770
+ const agent = parentContext.agent;
22771
+ return agent?.name;
22772
+ }
22773
+ function extractModelName(parentContext) {
22774
+ if (!parentContext) {
22775
+ return void 0;
22776
+ }
22777
+ const agent = parentContext.agent;
22778
+ if (!agent?.model) {
22779
+ return void 0;
22780
+ }
22781
+ if (typeof agent.model === "string") {
22782
+ return agent.model;
22783
+ }
22784
+ if (typeof agent.model === "object" && "model" in agent.model) {
22785
+ return agent.model.model;
22786
+ }
22787
+ return void 0;
22788
+ }
22789
+ function extractToolCallId(req) {
22790
+ const toolContext = req.toolContext;
22791
+ return toolContext?.functionCallId;
22792
+ }
22793
+ function extractToolName(req, tool) {
22794
+ if (typeof tool?.name === "string" && tool.name.length > 0) {
22795
+ return tool.name;
22796
+ }
22797
+ const toolContext = req.toolContext;
22798
+ const invocationContext = toolContext?.invocationContext;
22799
+ const invocationTool = invocationContext?.tool;
22800
+ const toolName = invocationTool?.name;
22801
+ return typeof toolName === "string" && toolName.length > 0 ? toolName : void 0;
22802
+ }
22803
+ function extractToolAgentName(req) {
22804
+ const toolContext = req.toolContext;
22805
+ const directName = toolContext?.agentName;
22806
+ if (typeof directName === "string" && directName.length > 0) {
22807
+ return directName;
22808
+ }
22809
+ const invocationContext = toolContext?.invocationContext;
22810
+ return extractAgentName(invocationContext);
22811
+ }
22812
+ function findToolParentSpan(req, activeAgentSpans, activeRunnerSpans) {
22813
+ const toolContext = req.toolContext;
22814
+ const invocationContext = toolContext?.invocationContext;
22815
+ const contextKey = extractInvocationContextKey(invocationContext);
22816
+ const agentName = extractToolAgentName(req);
22817
+ if (contextKey && agentName) {
22818
+ const agentSpan = activeAgentSpans.get(
22819
+ agentContextKey(contextKey, agentName)
22820
+ );
22821
+ if (agentSpan) {
22822
+ return agentSpan;
22823
+ }
22824
+ }
22825
+ return contextKey ? activeRunnerSpans.get(contextKey) : void 0;
22826
+ }
22827
+ function finalizeRunnerSpan(state, activeRunnerSpans) {
22828
+ try {
22829
+ const lastEvent = getLastNonPartialEvent(state.events);
22830
+ const metrics = {};
22831
+ const end = getCurrentUnixTimestamp();
22832
+ metrics.start = state.startTime;
22833
+ metrics.end = end;
22834
+ metrics.duration = end - state.startTime;
22835
+ const usage = aggregateUsageFromEvents(state.events);
22836
+ if (usage) {
22837
+ populateUsageMetrics2(metrics, usage);
22838
+ }
22839
+ state.span.log({
22840
+ output: lastEvent ? extractEventOutput(lastEvent) : void 0,
22841
+ metrics: cleanMetrics2(metrics)
22842
+ });
22843
+ } finally {
22844
+ cleanupActiveRunnerSpan(state, activeRunnerSpans);
22845
+ state.span.end();
22846
+ }
22847
+ }
22848
+ function finalizeAgentSpan(state, activeAgentSpans) {
22849
+ try {
22850
+ const lastEvent = getLastNonPartialEvent(state.events);
22851
+ const metrics = {};
22852
+ const end = getCurrentUnixTimestamp();
22853
+ metrics.start = state.startTime;
22854
+ metrics.end = end;
22855
+ metrics.duration = end - state.startTime;
22856
+ state.span.log({
22857
+ output: lastEvent ? extractEventOutput(lastEvent) : void 0,
22858
+ metrics: cleanMetrics2(metrics)
22859
+ });
22860
+ } finally {
22861
+ cleanupActiveAgentSpan(state, activeAgentSpans);
22862
+ state.span.end();
22863
+ }
22864
+ }
22865
+ function getLastNonPartialEvent(events) {
22866
+ for (let i = events.length - 1; i >= 0; i--) {
22867
+ if (!events[i].partial) {
22868
+ return events[i];
22869
+ }
22870
+ }
22871
+ return events.length > 0 ? events[events.length - 1] : void 0;
22872
+ }
22873
+ function extractEventOutput(event) {
22874
+ if (!event.content) {
22875
+ return void 0;
22876
+ }
22877
+ const output = {};
22878
+ if (event.content.role) {
22879
+ output.role = event.content.role;
22880
+ }
22881
+ if (event.content.parts && Array.isArray(event.content.parts)) {
22882
+ const textParts = event.content.parts.filter((p) => p.text !== void 0 && !p.thought).map((p) => p.text);
22883
+ const thoughtParts = event.content.parts.filter((p) => p.text !== void 0 && p.thought).map((p) => p.text);
22884
+ const functionCalls = event.content.parts.filter((p) => p.functionCall).map((p) => p.functionCall);
22885
+ if (textParts.length > 0) {
22886
+ output.content = textParts.join("");
22887
+ }
22888
+ if (thoughtParts.length > 0) {
22889
+ output.thought = thoughtParts.join("");
22890
+ }
22891
+ if (functionCalls.length > 0) {
22892
+ output.functionCalls = functionCalls;
22893
+ }
22894
+ }
22895
+ if (event.author) {
22896
+ output.author = event.author;
22897
+ }
22898
+ return Object.keys(output).length > 0 ? output : void 0;
22899
+ }
22900
+ function aggregateUsageFromEvents(events) {
22901
+ let hasUsage = false;
22902
+ const aggregated = {};
22903
+ for (const event of events) {
22904
+ if (!event.usageMetadata) {
22905
+ continue;
22906
+ }
22907
+ hasUsage = true;
22908
+ const usage = event.usageMetadata;
22909
+ if (usage.promptTokenCount !== void 0) {
22910
+ aggregated.promptTokenCount = (aggregated.promptTokenCount ?? 0) + usage.promptTokenCount;
22911
+ }
22912
+ if (usage.candidatesTokenCount !== void 0) {
22913
+ aggregated.candidatesTokenCount = (aggregated.candidatesTokenCount ?? 0) + usage.candidatesTokenCount;
22914
+ }
22915
+ if (usage.totalTokenCount !== void 0) {
22916
+ aggregated.totalTokenCount = (aggregated.totalTokenCount ?? 0) + usage.totalTokenCount;
22917
+ }
22918
+ if (usage.cachedContentTokenCount !== void 0) {
22919
+ aggregated.cachedContentTokenCount = (aggregated.cachedContentTokenCount ?? 0) + usage.cachedContentTokenCount;
22920
+ }
22921
+ if (usage.thoughtsTokenCount !== void 0) {
22922
+ aggregated.thoughtsTokenCount = (aggregated.thoughtsTokenCount ?? 0) + usage.thoughtsTokenCount;
22923
+ }
22924
+ }
22925
+ return hasUsage ? aggregated : void 0;
22926
+ }
22927
+ function populateUsageMetrics2(metrics, usage) {
22928
+ if (usage.promptTokenCount !== void 0) {
22929
+ metrics.prompt_tokens = usage.promptTokenCount;
22930
+ }
22931
+ if (usage.candidatesTokenCount !== void 0) {
22932
+ metrics.completion_tokens = usage.candidatesTokenCount;
22933
+ }
22934
+ if (usage.totalTokenCount !== void 0) {
22935
+ metrics.tokens = usage.totalTokenCount;
22936
+ }
22937
+ if (usage.cachedContentTokenCount !== void 0) {
22938
+ metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
22939
+ }
22940
+ if (usage.thoughtsTokenCount !== void 0) {
22941
+ metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
22942
+ }
22943
+ }
22944
+ function cleanMetrics2(metrics) {
22945
+ const cleaned = {};
22946
+ for (const [key, value] of Object.entries(metrics)) {
22947
+ if (value !== null && value !== void 0) {
22948
+ cleaned[key] = value;
22949
+ }
22950
+ }
22951
+ return cleaned;
22952
+ }
22953
+
22954
+ // src/instrumentation/plugins/cohere-channels.ts
22955
+ var cohereChannels = defineChannels("cohere-ai", {
22956
+ chat: channel({
22957
+ channelName: "chat",
22958
+ kind: "async"
22959
+ }),
22960
+ chatStream: channel({
22961
+ channelName: "chatStream",
22962
+ kind: "async"
22963
+ }),
22964
+ embed: channel({
22965
+ channelName: "embed",
22966
+ kind: "async"
22967
+ }),
22968
+ rerank: channel({
22969
+ channelName: "rerank",
22970
+ kind: "async"
22971
+ })
22972
+ });
22973
+
22974
+ // src/instrumentation/plugins/cohere-plugin.ts
22975
+ var CoherePlugin = class extends BasePlugin {
22976
+ onEnable() {
22977
+ this.subscribeToCohereChannels();
22978
+ }
22979
+ onDisable() {
22980
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
22981
+ }
22982
+ subscribeToCohereChannels() {
22983
+ this.unsubscribers.push(
22984
+ traceStreamingChannel(cohereChannels.chat, {
22985
+ name: "cohere.chat",
22986
+ type: "llm" /* LLM */,
22987
+ extractInput: extractChatInputWithMetadata2,
22988
+ extractOutput: (result) => extractCohereChatOutput(result),
22989
+ extractMetadata: (result) => extractCohereResponseMetadata(result),
22990
+ extractMetrics: (result, startTime) => {
22991
+ const metrics = parseCohereMetricsFromUsage(result);
22992
+ if (startTime) {
22993
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
22994
+ }
22995
+ return metrics;
22996
+ }
22997
+ })
22998
+ );
22999
+ this.unsubscribers.push(
23000
+ traceStreamingChannel(cohereChannels.chatStream, {
23001
+ name: "cohere.chatStream",
23002
+ type: "llm" /* LLM */,
23003
+ extractInput: extractChatInputWithMetadata2,
23004
+ extractOutput: () => void 0,
23005
+ extractMetadata: () => void 0,
23006
+ extractMetrics: () => ({}),
23007
+ aggregateChunks: aggregateCohereChatStreamChunks
23008
+ })
23009
+ );
23010
+ this.unsubscribers.push(
23011
+ traceAsyncChannel(cohereChannels.embed, {
23012
+ name: "cohere.embed",
23013
+ type: "llm" /* LLM */,
23014
+ extractInput: extractEmbedInputWithMetadata,
23015
+ extractOutput: extractCohereEmbeddingOutput,
23016
+ extractMetadata: (result) => extractCohereResponseMetadata(result),
23017
+ extractMetrics: (result) => parseCohereMetricsFromUsage(result)
23018
+ })
23019
+ );
23020
+ this.unsubscribers.push(
23021
+ traceAsyncChannel(cohereChannels.rerank, {
23022
+ name: "cohere.rerank",
23023
+ type: "llm" /* LLM */,
23024
+ extractInput: extractRerankInputWithMetadata,
23025
+ extractOutput: (result) => {
23026
+ if (!isObject(result) || !Array.isArray(result.results)) {
23027
+ return void 0;
23028
+ }
23029
+ return result.results.slice(0, 100).map((item) => ({
23030
+ index: isObject(item) ? item.index : void 0,
23031
+ relevance_score: isObject(item) ? (typeof item.relevanceScore === "number" ? item.relevanceScore : item.relevance_score) ?? null : null
23032
+ }));
23033
+ },
23034
+ extractMetadata: (result) => extractCohereResponseMetadata(result),
23035
+ extractMetrics: (result) => parseCohereMetricsFromUsage(result)
23036
+ })
23037
+ );
23038
+ }
23039
+ };
23040
+ var CHAT_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
23041
+ "conversationId",
23042
+ "conversation_id",
23043
+ "frequencyPenalty",
23044
+ "frequency_penalty",
23045
+ "k",
23046
+ "maxInputTokens",
23047
+ "max_input_tokens",
23048
+ "maxTokens",
23049
+ "max_tokens",
23050
+ "model",
23051
+ "p",
23052
+ "preamble",
23053
+ "presencePenalty",
23054
+ "presence_penalty",
23055
+ "priority",
23056
+ "promptTruncation",
23057
+ "prompt_truncation",
23058
+ "rawPrompting",
23059
+ "raw_prompting",
23060
+ "responseFormat",
23061
+ "response_format",
23062
+ "safetyMode",
23063
+ "safety_mode",
23064
+ "searchQueriesOnly",
23065
+ "search_queries_only",
23066
+ "seed",
23067
+ "stopSequences",
23068
+ "stop_sequences",
23069
+ "strictTools",
23070
+ "strict_tools",
23071
+ "temperature",
23072
+ "toolChoice",
23073
+ "tool_choice"
23074
+ ]);
23075
+ var EMBED_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
23076
+ "embeddingTypes",
23077
+ "embedding_types",
23078
+ "inputType",
23079
+ "input_type",
23080
+ "maxTokens",
23081
+ "max_tokens",
23082
+ "model",
23083
+ "outputDimension",
23084
+ "output_dimension",
23085
+ "priority",
23086
+ "truncate"
23087
+ ]);
23088
+ var RERANK_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
23089
+ "maxChunksPerDoc",
23090
+ "max_chunks_per_doc",
23091
+ "maxTokensPerDoc",
23092
+ "max_tokens_per_doc",
23093
+ "model",
23094
+ "priority",
23095
+ "rankFields",
23096
+ "rank_fields",
23097
+ "returnDocuments",
23098
+ "return_documents",
23099
+ "topN",
23100
+ "top_n"
23101
+ ]);
23102
+ var RESPONSE_METADATA_ALLOWLIST2 = /* @__PURE__ */ new Set([
23103
+ "finishReason",
23104
+ "finish_reason",
23105
+ "generationId",
23106
+ "generation_id",
23107
+ "id",
23108
+ "responseId",
23109
+ "responseType",
23110
+ "response_id",
23111
+ "response_type"
23112
+ ]);
23113
+ function normalizeArgs5(args) {
23114
+ if (Array.isArray(args)) {
23115
+ return args;
23116
+ }
23117
+ if (isArrayLike6(args)) {
23118
+ return Array.from(args);
23119
+ }
23120
+ return [args];
23121
+ }
23122
+ function isArrayLike6(value) {
23123
+ return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
23124
+ }
23125
+ function getRequestArg(args) {
23126
+ const firstObjectArg = normalizeArgs5(args).find((arg) => isObject(arg));
23127
+ return isObject(firstObjectArg) ? firstObjectArg : void 0;
23128
+ }
23129
+ function addCohereProviderMetadata(metadata) {
23130
+ return {
23131
+ ...metadata,
23132
+ provider: "cohere"
23133
+ };
23134
+ }
23135
+ function pickAllowedMetadata2(metadata, allowlist) {
23136
+ if (!metadata) {
23137
+ return {};
23138
+ }
23139
+ const picked = {};
23140
+ for (const key of allowlist) {
23141
+ const value = metadata[key];
23142
+ if (value !== void 0) {
23143
+ picked[key] = value;
23144
+ }
23145
+ }
23146
+ return picked;
23147
+ }
23148
+ function extractChatInputWithMetadata2(args) {
23149
+ const request = getRequestArg(args);
23150
+ const { message, messages, ...rawMetadata } = request || {};
23151
+ return {
23152
+ input: processInputAttachments(messages ?? message),
23153
+ metadata: addCohereProviderMetadata(
23154
+ pickAllowedMetadata2(rawMetadata, CHAT_REQUEST_METADATA_ALLOWLIST)
23155
+ )
23156
+ };
23157
+ }
23158
+ function extractEmbedInputWithMetadata(args) {
23159
+ const request = getRequestArg(args);
23160
+ const { inputs, texts, images, ...rawMetadata } = request || {};
23161
+ return {
23162
+ input: inputs ?? texts ?? images,
23163
+ metadata: addCohereProviderMetadata(
23164
+ pickAllowedMetadata2(rawMetadata, EMBED_REQUEST_METADATA_ALLOWLIST)
23165
+ )
23166
+ };
23167
+ }
23168
+ function extractRerankInputWithMetadata(args) {
23169
+ const request = getRequestArg(args);
23170
+ const { query, documents, ...rawMetadata } = request || {};
23171
+ return {
23172
+ input: {
23173
+ documents,
23174
+ query
23175
+ },
23176
+ metadata: addCohereProviderMetadata({
23177
+ ...pickAllowedMetadata2(rawMetadata, RERANK_REQUEST_METADATA_ALLOWLIST),
23178
+ ...Array.isArray(documents) ? { document_count: documents.length } : {}
23179
+ })
23180
+ };
23181
+ }
23182
+ function extractCohereResponseMetadata(result) {
23183
+ if (!isObject(result)) {
23184
+ return void 0;
23185
+ }
23186
+ const responseMetadata = pickAllowedMetadata2(
23187
+ result,
23188
+ RESPONSE_METADATA_ALLOWLIST2
23189
+ );
23190
+ const meta = isObject(result.meta) ? result.meta : void 0;
23191
+ 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;
23192
+ const metadata = {
23193
+ ...responseMetadata,
23194
+ ...apiVersion ? { api_version: apiVersion } : {}
23195
+ };
23196
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
23197
+ }
23198
+ function extractCohereChatOutput(result) {
23199
+ if (!isObject(result)) {
23200
+ return void 0;
23201
+ }
23202
+ if (isObject(result.message)) {
23203
+ return result.message;
23204
+ }
23205
+ if (typeof result.text !== "string") {
23206
+ return void 0;
23207
+ }
23208
+ const toolCalls = Array.isArray(result.toolCalls) ? result.toolCalls : Array.isArray(result.tool_calls) ? result.tool_calls : void 0;
23209
+ if (toolCalls && toolCalls.length > 0) {
23210
+ return {
23211
+ content: result.text,
23212
+ role: "assistant",
23213
+ toolCalls
23214
+ };
23215
+ }
23216
+ return result.text;
23217
+ }
23218
+ function extractCohereEmbeddingOutput(result) {
23219
+ if (!isObject(result)) {
23220
+ return void 0;
23221
+ }
23222
+ const embeddingLength = getFirstEmbeddingLength(result.embeddings);
23223
+ if (embeddingLength === void 0) {
23224
+ return void 0;
23225
+ }
23226
+ return {
23227
+ embedding_length: embeddingLength
23228
+ };
23229
+ }
23230
+ function getFirstEmbeddingLength(value) {
23231
+ if (Array.isArray(value) && Array.isArray(value[0])) {
23232
+ return value[0].length;
23233
+ }
23234
+ if (!isObject(value)) {
23235
+ return void 0;
23236
+ }
23237
+ for (const key of Object.keys(value)) {
23238
+ const entry = value[key];
23239
+ if (Array.isArray(entry) && Array.isArray(entry[0])) {
23240
+ return entry[0].length;
23241
+ }
23242
+ }
23243
+ return void 0;
23244
+ }
23245
+ function setMetricIfNumber(metrics, key, value) {
23246
+ if (typeof value === "number" && Number.isFinite(value)) {
23247
+ metrics[key] = value;
23248
+ }
23249
+ }
23250
+ function mergeUsageMetrics(metrics, usage) {
23251
+ if (!isObject(usage)) {
23252
+ return metrics;
23253
+ }
23254
+ const source = usage;
23255
+ setMetricIfNumber(
23256
+ metrics,
23257
+ "prompt_tokens",
23258
+ source.inputTokens ?? source.input_tokens
23259
+ );
23260
+ setMetricIfNumber(
23261
+ metrics,
23262
+ "completion_tokens",
23263
+ source.outputTokens ?? source.output_tokens
23264
+ );
23265
+ setMetricIfNumber(
23266
+ metrics,
23267
+ "tokens",
23268
+ source.totalTokens ?? source.total_tokens
23269
+ );
23270
+ setMetricIfNumber(
23271
+ metrics,
23272
+ "prompt_cached_tokens",
23273
+ source.cachedTokens ?? source.cached_tokens
23274
+ );
23275
+ const tokenContainer = isObject(source.tokens) ? source.tokens : void 0;
23276
+ if (tokenContainer) {
23277
+ setMetricIfNumber(
23278
+ metrics,
23279
+ "prompt_tokens",
23280
+ tokenContainer.inputTokens ?? tokenContainer.input_tokens
23281
+ );
23282
+ setMetricIfNumber(
23283
+ metrics,
23284
+ "completion_tokens",
23285
+ tokenContainer.outputTokens ?? tokenContainer.output_tokens
23286
+ );
23287
+ setMetricIfNumber(
23288
+ metrics,
23289
+ "tokens",
23290
+ tokenContainer.totalTokens ?? tokenContainer.total_tokens
23291
+ );
23292
+ }
23293
+ const billedUnits = (isObject(source.billedUnits) ? source.billedUnits : void 0) || (isObject(source.billed_units) ? source.billed_units : void 0);
23294
+ if (billedUnits) {
23295
+ setMetricIfNumber(
23296
+ metrics,
23297
+ "prompt_tokens",
23298
+ billedUnits.inputTokens ?? billedUnits.input_tokens
23299
+ );
23300
+ setMetricIfNumber(
23301
+ metrics,
23302
+ "completion_tokens",
23303
+ billedUnits.outputTokens ?? billedUnits.output_tokens
23304
+ );
23305
+ setMetricIfNumber(
23306
+ metrics,
23307
+ "search_units",
23308
+ billedUnits.searchUnits ?? billedUnits.search_units
23309
+ );
23310
+ setMetricIfNumber(metrics, "classifications", billedUnits.classifications);
23311
+ setMetricIfNumber(metrics, "images", billedUnits.images);
23312
+ setMetricIfNumber(
23313
+ metrics,
23314
+ "image_tokens",
23315
+ billedUnits.imageTokens ?? billedUnits.image_tokens
23316
+ );
23317
+ }
23318
+ return metrics;
23319
+ }
23320
+ function parseCohereMetricsFromUsage(source) {
23321
+ if (!isObject(source)) {
23322
+ return {};
20333
23323
  }
20334
- return metrics;
20335
- }
20336
- function extractDeltaText(content) {
20337
- if (typeof content === "string") {
20338
- return content;
23324
+ const metrics = {};
23325
+ mergeUsageMetrics(metrics, source);
23326
+ if ("usage" in source) {
23327
+ mergeUsageMetrics(metrics, source.usage);
20339
23328
  }
20340
- if (!Array.isArray(content)) {
20341
- return void 0;
23329
+ if ("meta" in source) {
23330
+ mergeUsageMetrics(metrics, source.meta);
20342
23331
  }
20343
- const textParts = content.map((part) => {
20344
- if (!isObject(part) || part.type !== "text") {
20345
- return "";
20346
- }
20347
- return typeof part.text === "string" ? part.text : "";
20348
- }).filter((part) => part.length > 0);
20349
- return textParts.length > 0 ? textParts.join("") : void 0;
20350
- }
20351
- function getDeltaToolCalls(delta) {
20352
- const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
20353
- return toolCalls.filter((toolCall) => isObject(toolCall));
23332
+ if (metrics.tokens === void 0 && typeof metrics.prompt_tokens === "number" && typeof metrics.completion_tokens === "number") {
23333
+ metrics.tokens = metrics.prompt_tokens + metrics.completion_tokens;
23334
+ }
23335
+ return metrics;
20354
23336
  }
20355
- function getToolCallIndex(toolCall) {
20356
- return typeof toolCall.index === "number" && toolCall.index >= 0 ? toolCall.index : void 0;
23337
+ function toToolCallArray(value) {
23338
+ if (Array.isArray(value)) {
23339
+ return value.filter((item) => isObject(item));
23340
+ }
23341
+ return isObject(value) ? [value] : [];
20357
23342
  }
20358
- function createMergedToolCallDelta(delta) {
20359
- return {
20360
- ...delta,
20361
- function: {
20362
- ...delta.function,
20363
- arguments: typeof delta.function?.arguments === "string" ? delta.function.arguments : ""
20364
- }
20365
- };
23343
+ function getToolCallIndex2(toolCall, fallbackIndex) {
23344
+ return typeof toolCall.index === "number" && Number.isInteger(toolCall.index) ? toolCall.index : fallbackIndex;
20366
23345
  }
20367
- function mergeToolCallDeltaPair(current, delta) {
20368
- const currentArguments = typeof current.function?.arguments === "string" ? current.function.arguments : "";
20369
- const deltaArguments = typeof delta.function?.arguments === "string" ? delta.function.arguments : "";
23346
+ function appendToolCallDelta(existing, incoming) {
23347
+ const currentArguments = isObject(existing?.function) && typeof existing.function.arguments === "string" ? existing.function.arguments : "";
23348
+ const incomingArguments = isObject(incoming.function) && typeof incoming.function.arguments === "string" ? incoming.function.arguments : "";
20370
23349
  return {
20371
- ...current,
20372
- ...delta,
23350
+ ...existing,
23351
+ ...incoming,
20373
23352
  function: {
20374
- ...current.function || {},
20375
- ...delta.function || {},
20376
- arguments: `${currentArguments}${deltaArguments}`
23353
+ ...isObject(existing?.function) ? existing.function : {},
23354
+ ...isObject(incoming.function) ? incoming.function : {},
23355
+ ...incomingArguments ? { arguments: `${currentArguments}${incomingArguments}` } : {}
20377
23356
  }
20378
23357
  };
20379
23358
  }
20380
- function mergeToolCallDeltas(toolCalls, deltas) {
20381
- if (deltas.length === 0) {
20382
- return toolCalls;
20383
- }
20384
- const merged = toolCalls ? [...toolCalls] : [];
20385
- const indexToPosition = /* @__PURE__ */ new Map();
20386
- const idToPosition = /* @__PURE__ */ new Map();
20387
- for (const [position, toolCall] of merged.entries()) {
20388
- const index = getToolCallIndex(toolCall);
20389
- if (index !== void 0 && !indexToPosition.has(index)) {
20390
- indexToPosition.set(index, position);
20391
- }
20392
- if (typeof toolCall.id === "string" && !idToPosition.has(toolCall.id)) {
20393
- idToPosition.set(toolCall.id, position);
20394
- }
20395
- }
20396
- for (const delta of deltas) {
20397
- const deltaIndex = getToolCallIndex(delta);
20398
- const existingByIndex = deltaIndex !== void 0 ? indexToPosition.get(deltaIndex) : void 0;
20399
- const existingById = typeof delta.id === "string" ? idToPosition.get(delta.id) : void 0;
20400
- const existingPosition = existingByIndex ?? existingById;
20401
- if (existingPosition === void 0) {
20402
- const newToolCall = createMergedToolCallDelta(delta);
20403
- merged.push(newToolCall);
20404
- const newPosition = merged.length - 1;
20405
- const newIndex = getToolCallIndex(newToolCall);
20406
- if (newIndex !== void 0 && !indexToPosition.has(newIndex)) {
20407
- indexToPosition.set(newIndex, newPosition);
20408
- }
20409
- if (typeof newToolCall.id === "string" && !idToPosition.has(newToolCall.id)) {
20410
- idToPosition.set(newToolCall.id, newPosition);
20411
- }
20412
- continue;
20413
- }
20414
- const mergedToolCall = mergeToolCallDeltaPair(
20415
- merged[existingPosition],
20416
- delta
20417
- );
20418
- merged[existingPosition] = mergedToolCall;
20419
- const mergedIndex = getToolCallIndex(mergedToolCall);
20420
- if (mergedIndex !== void 0 && !indexToPosition.has(mergedIndex)) {
20421
- indexToPosition.set(mergedIndex, existingPosition);
20422
- }
20423
- if (typeof mergedToolCall.id === "string" && !idToPosition.has(mergedToolCall.id)) {
20424
- idToPosition.set(mergedToolCall.id, existingPosition);
20425
- }
23359
+ function extractV8DeltaText(chunk) {
23360
+ if (!isObject(chunk.delta) || !isObject(chunk.delta.message)) {
23361
+ return void 0;
20426
23362
  }
20427
- return merged.length > 0 ? merged : void 0;
20428
- }
20429
- function getChoiceFinishReason(choice) {
20430
- if (typeof choice.finishReason === "string" || choice.finishReason === null) {
20431
- return choice.finishReason;
23363
+ const content = chunk.delta.message.content;
23364
+ if (typeof content === "string") {
23365
+ return content;
20432
23366
  }
20433
- if (typeof choice.finish_reason === "string" || choice.finish_reason === null) {
20434
- return choice.finish_reason;
23367
+ if (isObject(content) && typeof content.text === "string") {
23368
+ return content.text;
20435
23369
  }
20436
23370
  return void 0;
20437
23371
  }
20438
- function parseMistralMetricsFromUsage(usage) {
20439
- if (!isObject(usage)) {
20440
- return {};
20441
- }
20442
- const metrics = {};
20443
- for (const [name, value] of Object.entries(usage)) {
20444
- if (typeof value === "number") {
20445
- metrics[TOKEN_NAME_MAP4[name] || camelToSnake3(name)] = value;
20446
- continue;
20447
- }
20448
- if (!isObject(value)) {
23372
+ function aggregateCohereChatStreamChunks(chunks) {
23373
+ const textDeltas = [];
23374
+ const toolCallsByIndex = {};
23375
+ const toolCallOrder = [];
23376
+ let terminalResponse;
23377
+ let role;
23378
+ let finishReason;
23379
+ let metadata = {};
23380
+ let metrics = {};
23381
+ for (const chunk of chunks) {
23382
+ if (!isObject(chunk)) {
20449
23383
  continue;
20450
23384
  }
20451
- const prefix = TOKEN_DETAIL_PREFIX_MAP3[name];
20452
- if (!prefix) {
23385
+ const eventType = typeof chunk.eventType === "string" ? chunk.eventType : typeof chunk.event_type === "string" ? chunk.event_type : typeof chunk.type === "string" ? chunk.type : void 0;
23386
+ if (eventType === "text-generation" && typeof chunk.text === "string") {
23387
+ textDeltas.push(chunk.text);
20453
23388
  continue;
20454
23389
  }
20455
- for (const [nestedName, nestedValue] of Object.entries(value)) {
20456
- if (typeof nestedValue !== "number") {
20457
- continue;
23390
+ if (eventType === "tool-calls-generation") {
23391
+ const generatedToolCalls = toToolCallArray(
23392
+ Array.isArray(chunk.toolCalls) ? chunk.toolCalls : chunk.tool_calls
23393
+ );
23394
+ for (const [index, toolCall] of generatedToolCalls.entries()) {
23395
+ const normalizedIndex = getToolCallIndex2(toolCall, index);
23396
+ if (!toolCallOrder.includes(normalizedIndex)) {
23397
+ toolCallOrder.push(normalizedIndex);
23398
+ }
23399
+ toolCallsByIndex[normalizedIndex] = {
23400
+ ...toolCallsByIndex[normalizedIndex],
23401
+ ...toolCall
23402
+ };
23403
+ }
23404
+ if (typeof chunk.text === "string") {
23405
+ textDeltas.push(chunk.text);
20458
23406
  }
20459
- metrics[`${prefix}_${camelToSnake3(nestedName)}`] = nestedValue;
20460
- }
20461
- }
20462
- return metrics;
20463
- }
20464
- function aggregateMistralStreamChunks(chunks) {
20465
- const choiceAccumulators = /* @__PURE__ */ new Map();
20466
- const indexToAccumulatorKey = /* @__PURE__ */ new Map();
20467
- const positionToAccumulatorKey = /* @__PURE__ */ new Map();
20468
- let nextAccumulatorOrder = 0;
20469
- let metrics = {};
20470
- let metadata;
20471
- for (const event of chunks) {
20472
- const chunk = isMistralChatCompletionChunk(event?.data) ? event.data : void 0;
20473
- if (!chunk) {
20474
23407
  continue;
20475
23408
  }
20476
- if (isObject(chunk.usage)) {
23409
+ if (eventType === "stream-end" && isObject(chunk.response)) {
23410
+ terminalResponse = chunk.response;
20477
23411
  metrics = {
20478
23412
  ...metrics,
20479
- ...parseMistralMetricsFromUsage(chunk.usage)
23413
+ ...parseCohereMetricsFromUsage(chunk.response)
20480
23414
  };
23415
+ metadata = {
23416
+ ...metadata,
23417
+ ...extractCohereResponseMetadata(chunk.response) || {}
23418
+ };
23419
+ const responseFinishReason = typeof chunk.response.finishReason === "string" ? chunk.response.finishReason : typeof chunk.response.finish_reason === "string" ? chunk.response.finish_reason : void 0;
23420
+ finishReason = responseFinishReason ?? finishReason;
23421
+ continue;
20481
23422
  }
20482
- const chunkMetadata = extractMistralResponseMetadata(chunk);
20483
- if (chunkMetadata) {
20484
- metadata = { ...metadata || {}, ...chunkMetadata };
20485
- }
20486
- for (const [choicePosition, rawChoice] of (chunk.choices || []).entries()) {
20487
- if (!isMistralChunkChoice(rawChoice)) {
20488
- continue;
23423
+ if (eventType === "message-start") {
23424
+ if (typeof chunk.id === "string") {
23425
+ metadata.id = chunk.id;
20489
23426
  }
20490
- const choice = rawChoice;
20491
- const choiceIndex = typeof choice.index === "number" && choice.index >= 0 ? choice.index : void 0;
20492
- let accumulatorKey = choiceIndex !== void 0 ? indexToAccumulatorKey.get(choiceIndex) : void 0;
20493
- if (!accumulatorKey) {
20494
- accumulatorKey = positionToAccumulatorKey.get(choicePosition);
20495
- }
20496
- if (!accumulatorKey) {
20497
- const initialIndex = choiceIndex ?? choicePosition;
20498
- const keyPrefix = choiceIndex !== void 0 ? "index" : "position";
20499
- accumulatorKey = `${keyPrefix}:${initialIndex}`;
20500
- choiceAccumulators.set(accumulatorKey, {
20501
- index: initialIndex,
20502
- order: nextAccumulatorOrder++
20503
- });
20504
- }
20505
- const accumulator = choiceAccumulators.get(accumulatorKey);
20506
- if (!accumulator) {
20507
- continue;
23427
+ if (isObject(chunk.delta) && isObject(chunk.delta.message)) {
23428
+ const messageRole = chunk.delta.message.role;
23429
+ if (typeof messageRole === "string") {
23430
+ role = messageRole;
23431
+ }
20508
23432
  }
20509
- if (choiceIndex !== void 0) {
20510
- accumulator.index = choiceIndex;
20511
- indexToAccumulatorKey.set(choiceIndex, accumulatorKey);
23433
+ continue;
23434
+ }
23435
+ if (eventType === "content-delta") {
23436
+ const text = extractV8DeltaText(chunk);
23437
+ if (text) {
23438
+ textDeltas.push(text);
20512
23439
  }
20513
- positionToAccumulatorKey.set(choicePosition, accumulatorKey);
20514
- const delta = isObject(choice.delta) ? choice.delta : void 0;
20515
- if (delta) {
20516
- if (!accumulator.role && typeof delta.role === "string") {
20517
- accumulator.role = delta.role;
23440
+ continue;
23441
+ }
23442
+ if (eventType === "tool-call-start") {
23443
+ const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
23444
+ Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
23445
+ ) : [];
23446
+ for (const [index, toolCall] of toolCalls.entries()) {
23447
+ const normalizedIndex = getToolCallIndex2(
23448
+ toolCall,
23449
+ typeof chunk.index === "number" ? chunk.index : index
23450
+ );
23451
+ if (!toolCallOrder.includes(normalizedIndex)) {
23452
+ toolCallOrder.push(normalizedIndex);
20518
23453
  }
20519
- const deltaText = extractDeltaText(delta.content);
20520
- if (deltaText) {
20521
- accumulator.content = `${accumulator.content || ""}${deltaText}`;
23454
+ toolCallsByIndex[normalizedIndex] = {
23455
+ ...toolCallsByIndex[normalizedIndex],
23456
+ ...toolCall
23457
+ };
23458
+ }
23459
+ continue;
23460
+ }
23461
+ if (eventType === "tool-call-delta") {
23462
+ const toolCallDelta = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
23463
+ chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
23464
+ ) : [];
23465
+ if (toolCallDelta.length > 0) {
23466
+ const delta = toolCallDelta[0];
23467
+ const normalizedIndex = getToolCallIndex2(delta, chunk.index ?? 0);
23468
+ if (!toolCallOrder.includes(normalizedIndex)) {
23469
+ toolCallOrder.push(normalizedIndex);
20522
23470
  }
20523
- accumulator.toolCalls = mergeToolCallDeltas(
20524
- accumulator.toolCalls,
20525
- getDeltaToolCalls(delta)
23471
+ toolCallsByIndex[normalizedIndex] = appendToolCallDelta(
23472
+ toolCallsByIndex[normalizedIndex],
23473
+ delta
20526
23474
  );
20527
23475
  }
20528
- const choiceFinishReason = getChoiceFinishReason(choice);
20529
- if (choiceFinishReason !== void 0) {
20530
- accumulator.finishReason = choiceFinishReason;
23476
+ continue;
23477
+ }
23478
+ if (eventType === "message-end" && isObject(chunk.delta)) {
23479
+ const delta = chunk.delta;
23480
+ if (typeof delta.finishReason === "string") {
23481
+ finishReason = delta.finishReason;
23482
+ } else if (typeof delta.finish_reason === "string") {
23483
+ finishReason = delta.finish_reason;
23484
+ }
23485
+ if (delta.error !== void 0) {
23486
+ metadata.error = delta.error;
20531
23487
  }
23488
+ metrics = {
23489
+ ...metrics,
23490
+ ...parseCohereMetricsFromUsage(delta.usage)
23491
+ };
20532
23492
  }
20533
23493
  }
20534
- const output = Array.from(choiceAccumulators.values()).sort(
20535
- (left, right) => left.index === right.index ? left.order - right.order : left.index - right.index
20536
- ).map((choice) => ({
20537
- index: choice.index,
20538
- message: {
20539
- ...choice.role ? { role: choice.role } : {},
20540
- content: choice.content ?? null,
20541
- ...choice.toolCalls ? { toolCalls: choice.toolCalls } : {}
20542
- },
20543
- ...choice.finishReason !== void 0 ? { finishReason: choice.finishReason } : {}
20544
- }));
23494
+ const mergedToolCalls = toolCallOrder.sort((left, right) => left - right).map((index) => toolCallsByIndex[index]).filter((toolCall) => isObject(toolCall));
23495
+ let output = extractCohereChatOutput(terminalResponse);
23496
+ if (output === void 0) {
23497
+ const mergedText = textDeltas.join("");
23498
+ if (mergedToolCalls.length > 0 || role || mergedText.length > 0) {
23499
+ output = {
23500
+ ...role ? { role } : {},
23501
+ ...mergedText.length > 0 ? { content: mergedText } : {},
23502
+ ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
23503
+ };
23504
+ }
23505
+ }
23506
+ if (finishReason) {
23507
+ metadata = {
23508
+ ...metadata,
23509
+ finish_reason: finishReason
23510
+ };
23511
+ }
20545
23512
  return {
20546
- output,
23513
+ metadata,
20547
23514
  metrics,
20548
- ...metadata ? { metadata } : {}
23515
+ output
20549
23516
  };
20550
23517
  }
20551
23518
 
@@ -20557,9 +23524,12 @@ var BraintrustPlugin = class extends BasePlugin {
20557
23524
  aiSDKPlugin = null;
20558
23525
  claudeAgentSDKPlugin = null;
20559
23526
  googleGenAIPlugin = null;
23527
+ huggingFacePlugin = null;
20560
23528
  openRouterPlugin = null;
20561
23529
  openRouterAgentPlugin = null;
20562
23530
  mistralPlugin = null;
23531
+ googleADKPlugin = null;
23532
+ coherePlugin = null;
20563
23533
  constructor(config3 = {}) {
20564
23534
  super();
20565
23535
  this.config = config3;
@@ -20586,6 +23556,10 @@ var BraintrustPlugin = class extends BasePlugin {
20586
23556
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
20587
23557
  this.googleGenAIPlugin.enable();
20588
23558
  }
23559
+ if (integrations.huggingface !== false) {
23560
+ this.huggingFacePlugin = new HuggingFacePlugin();
23561
+ this.huggingFacePlugin.enable();
23562
+ }
20589
23563
  if (integrations.openrouter !== false) {
20590
23564
  this.openRouterPlugin = new OpenRouterPlugin();
20591
23565
  this.openRouterPlugin.enable();
@@ -20598,6 +23572,14 @@ var BraintrustPlugin = class extends BasePlugin {
20598
23572
  this.mistralPlugin = new MistralPlugin();
20599
23573
  this.mistralPlugin.enable();
20600
23574
  }
23575
+ if (integrations.googleADK !== false) {
23576
+ this.googleADKPlugin = new GoogleADKPlugin();
23577
+ this.googleADKPlugin.enable();
23578
+ }
23579
+ if (integrations.cohere !== false) {
23580
+ this.coherePlugin = new CoherePlugin();
23581
+ this.coherePlugin.enable();
23582
+ }
20601
23583
  }
20602
23584
  onDisable() {
20603
23585
  if (this.openaiPlugin) {
@@ -20620,6 +23602,10 @@ var BraintrustPlugin = class extends BasePlugin {
20620
23602
  this.googleGenAIPlugin.disable();
20621
23603
  this.googleGenAIPlugin = null;
20622
23604
  }
23605
+ if (this.huggingFacePlugin) {
23606
+ this.huggingFacePlugin.disable();
23607
+ this.huggingFacePlugin = null;
23608
+ }
20623
23609
  if (this.openRouterPlugin) {
20624
23610
  this.openRouterPlugin.disable();
20625
23611
  this.openRouterPlugin = null;
@@ -20632,6 +23618,14 @@ var BraintrustPlugin = class extends BasePlugin {
20632
23618
  this.mistralPlugin.disable();
20633
23619
  this.mistralPlugin = null;
20634
23620
  }
23621
+ if (this.googleADKPlugin) {
23622
+ this.googleADKPlugin.disable();
23623
+ this.googleADKPlugin = null;
23624
+ }
23625
+ if (this.coherePlugin) {
23626
+ this.coherePlugin.disable();
23627
+ this.coherePlugin = null;
23628
+ }
20635
23629
  }
20636
23630
  };
20637
23631
 
@@ -20703,10 +23697,12 @@ var PluginRegistry = class {
20703
23697
  vercel: true,
20704
23698
  aisdk: true,
20705
23699
  google: true,
23700
+ huggingface: true,
20706
23701
  claudeAgentSDK: true,
20707
23702
  openrouter: true,
20708
23703
  openrouterAgent: true,
20709
- mistral: true
23704
+ mistral: true,
23705
+ cohere: true
20710
23706
  };
20711
23707
  }
20712
23708
  /**
@@ -20929,7 +23925,7 @@ async function findCodeDefinition({
20929
23925
  if (location.type === "sandbox") {
20930
23926
  fn = evaluator.task;
20931
23927
  } else {
20932
- fn = location.position.type === "task" ? evaluator.task : evaluator.scores[location.position.index];
23928
+ fn = location.position.type === "task" ? evaluator.task : location.position.type === "scorer" ? (evaluator.scores ?? [])[location.position.index] : (evaluator.classifiers ?? [])[location.position.index];
20933
23929
  }
20934
23930
  } else if (location.type === "function") {
20935
23931
  fn = outFileModule.functions[location.index].handler;
@@ -21617,23 +24613,42 @@ async function uploadHandleBundles({
21617
24613
  function_type: "task",
21618
24614
  origin
21619
24615
  },
21620
- ...evaluator.evaluator.scores.map((score, i) => {
21621
- const name = scorerName(score, i);
21622
- return {
21623
- ...baseInfo,
21624
- // There is a very small chance that someone names a function with the same convention, but
21625
- // let's assume it's low enough that it doesn't matter.
21626
- ...formatNameAndSlug(["eval", namePrefix, "scorer", name]),
21627
- description: `Score ${name} for eval ${namePrefix}`,
21628
- location: {
21629
- type: "experiment",
21630
- eval_name: evaluator.evaluator.evalName,
21631
- position: { type: "scorer", index: i }
21632
- },
21633
- function_type: "scorer",
21634
- origin
21635
- };
21636
- })
24616
+ ...(evaluator.evaluator.scores ?? []).map(
24617
+ (score, i) => {
24618
+ const name = scorerName(score, i);
24619
+ return {
24620
+ ...baseInfo,
24621
+ // There is a very small chance that someone names a function with the same convention, but
24622
+ // let's assume it's low enough that it doesn't matter.
24623
+ ...formatNameAndSlug(["eval", namePrefix, "scorer", name]),
24624
+ description: `Score ${name} for eval ${namePrefix}`,
24625
+ location: {
24626
+ type: "experiment",
24627
+ eval_name: evaluator.evaluator.evalName,
24628
+ position: { type: "scorer", index: i }
24629
+ },
24630
+ function_type: "scorer",
24631
+ origin
24632
+ };
24633
+ }
24634
+ ),
24635
+ ...(evaluator.evaluator.classifiers ?? []).map(
24636
+ (classifier, i) => {
24637
+ const name = classifierName(classifier, i);
24638
+ return {
24639
+ ...baseInfo,
24640
+ ...formatNameAndSlug(["eval", namePrefix, "classifier", name]),
24641
+ description: `Classifier ${name} for eval ${namePrefix}`,
24642
+ location: {
24643
+ type: "experiment",
24644
+ eval_name: evaluator.evaluator.evalName,
24645
+ position: { type: "classifier", index: i }
24646
+ },
24647
+ function_type: "classifier",
24648
+ origin
24649
+ };
24650
+ }
24651
+ )
21637
24652
  ];
21638
24653
  bundleSpecs.push(...fileSpecs);
21639
24654
  if (setCurrent) {
@@ -21645,9 +24660,14 @@ async function uploadHandleBundles({
21645
24660
  ...resolvedParameters ? {
21646
24661
  parameters: serializeRemoteEvalParametersContainer(resolvedParameters)
21647
24662
  } : {},
21648
- scores: evaluator.evaluator.scores.map((score, i) => ({
24663
+ scores: (evaluator.evaluator.scores ?? []).map((score, i) => ({
21649
24664
  name: scorerName(score, i)
21650
- }))
24665
+ })),
24666
+ classifiers: (evaluator.evaluator.classifiers ?? []).map(
24667
+ (classifier, i) => ({
24668
+ name: classifierName(classifier, i)
24669
+ })
24670
+ )
21651
24671
  };
21652
24672
  bundleSpecs.push({
21653
24673
  ...baseInfo,
@@ -22423,7 +25443,8 @@ var baseAllowedHeaders = [
22423
25443
  "x-stainless-package-version",
22424
25444
  "x-stainless-runtime",
22425
25445
  "x-stainless-runtime-version",
22426
- "x-stainless-arch"
25446
+ "x-stainless-arch",
25447
+ "x-bt-use-gateway"
22427
25448
  ];
22428
25449
 
22429
25450
  // dev/stream.ts
@@ -22500,7 +25521,8 @@ var serializedParametersContainerSchema = import_v315.z.union([
22500
25521
  ]);
22501
25522
  var evaluatorDefinitionSchema = import_v315.z.object({
22502
25523
  parameters: serializedParametersContainerSchema.optional(),
22503
- scores: import_v315.z.array(import_v315.z.object({ name: import_v315.z.string() })).optional()
25524
+ scores: import_v315.z.array(import_v315.z.object({ name: import_v315.z.string() })).optional(),
25525
+ classifiers: import_v315.z.array(import_v315.z.object({ name: import_v315.z.string() })).optional()
22504
25526
  });
22505
25527
  var evaluatorDefinitionsSchema = import_v315.z.record(
22506
25528
  import_v315.z.string(),
@@ -22557,8 +25579,11 @@ function runDevServer(evaluators, opts) {
22557
25579
  }
22558
25580
  evalDefs[name] = {
22559
25581
  parameters,
22560
- scores: evaluator.scores.map((score, idx) => ({
25582
+ scores: (evaluator.scores ?? []).map((score, idx) => ({
22561
25583
  name: scorerName(score, idx)
25584
+ })),
25585
+ classifiers: (evaluator.classifiers ?? []).map((classifier, idx) => ({
25586
+ name: classifierName(classifier, idx)
22562
25587
  }))
22563
25588
  };
22564
25589
  }
@@ -22629,7 +25654,7 @@ function runDevServer(evaluators, opts) {
22629
25654
  {
22630
25655
  ...evaluator,
22631
25656
  data: evalData.data,
22632
- scores: evaluator.scores.concat(
25657
+ scores: (evaluator.scores ?? []).concat(
22633
25658
  scores?.map(
22634
25659
  (score) => makeScorer(
22635
25660
  state,