braintrust 3.9.0 → 3.10.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 (42) hide show
  1. package/dev/dist/index.d.mts +107 -1
  2. package/dev/dist/index.d.ts +107 -1
  3. package/dev/dist/index.js +2126 -443
  4. package/dev/dist/index.mjs +1814 -131
  5. package/dist/auto-instrumentations/bundler/esbuild.cjs +166 -0
  6. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  7. package/dist/auto-instrumentations/bundler/rollup.cjs +166 -0
  8. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  9. package/dist/auto-instrumentations/bundler/vite.cjs +166 -0
  10. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  11. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +163 -0
  12. package/dist/auto-instrumentations/bundler/webpack.cjs +166 -0
  13. package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
  14. package/dist/auto-instrumentations/{chunk-KIMMUFAK.mjs → chunk-GZNXBBPU.mjs} +164 -1
  15. package/dist/auto-instrumentations/{chunk-G7F6HZGE.mjs → chunk-XWEQQOQH.mjs} +8 -1
  16. package/dist/auto-instrumentations/hook.mjs +255 -8
  17. package/dist/auto-instrumentations/index.cjs +256 -7
  18. package/dist/auto-instrumentations/index.d.mts +5 -1
  19. package/dist/auto-instrumentations/index.d.ts +5 -1
  20. package/dist/auto-instrumentations/index.mjs +96 -8
  21. package/dist/browser.d.mts +141 -7
  22. package/dist/browser.d.ts +141 -7
  23. package/dist/browser.js +2035 -140
  24. package/dist/browser.mjs +2035 -140
  25. package/dist/cli.js +1822 -139
  26. package/dist/edge-light.d.mts +1 -1
  27. package/dist/edge-light.d.ts +1 -1
  28. package/dist/edge-light.js +2035 -140
  29. package/dist/edge-light.mjs +2035 -140
  30. package/dist/index.d.mts +141 -7
  31. package/dist/index.d.ts +141 -7
  32. package/dist/index.js +2397 -502
  33. package/dist/index.mjs +2035 -140
  34. package/dist/instrumentation/index.d.mts +7 -0
  35. package/dist/instrumentation/index.d.ts +7 -0
  36. package/dist/instrumentation/index.js +1662 -167
  37. package/dist/instrumentation/index.mjs +1662 -167
  38. package/dist/workerd.d.mts +1 -1
  39. package/dist/workerd.d.ts +1 -1
  40. package/dist/workerd.js +2035 -140
  41. package/dist/workerd.mjs +2035 -140
  42. package/package.json +6 -6
package/dist/workerd.mjs CHANGED
@@ -1809,6 +1809,7 @@ var TopicMapData = z6.object({
1809
1809
  report_key: z6.string().optional(),
1810
1810
  topic_names: z6.record(z6.string()).optional(),
1811
1811
  generation_settings: TopicMapGenerationSettings.optional(),
1812
+ disable_reconciliation: z6.boolean().optional(),
1812
1813
  distance_threshold: z6.number().optional()
1813
1814
  });
1814
1815
  var BatchedFacetData = z6.object({
@@ -2139,28 +2140,6 @@ var EnvVar = z6.object({
2139
2140
  secret_type: z6.union([z6.string(), z6.null()]).optional(),
2140
2141
  secret_category: z6.enum(["env_var", "ai_provider", "sandbox_provider"]).optional().default("env_var")
2141
2142
  });
2142
- var EvalStatusPageTheme = z6.enum(["light", "dark"]);
2143
- var EvalStatusPageConfig = z6.object({
2144
- score_columns: z6.union([z6.array(z6.string()), z6.null()]),
2145
- metric_columns: z6.union([z6.array(z6.string()), z6.null()]),
2146
- grouping_field: z6.union([z6.string(), z6.null()]),
2147
- filter: z6.union([z6.string(), z6.null()]),
2148
- sort_by: z6.union([z6.string(), z6.null()]),
2149
- sort_order: z6.union([z6.enum(["asc", "desc"]), z6.null()]),
2150
- api_key: z6.union([z6.string(), z6.null()])
2151
- }).partial();
2152
- var EvalStatusPage = z6.object({
2153
- id: z6.string().uuid(),
2154
- project_id: z6.string().uuid(),
2155
- user_id: z6.union([z6.string(), z6.null()]).optional(),
2156
- created: z6.union([z6.string(), z6.null()]).optional(),
2157
- deleted_at: z6.union([z6.string(), z6.null()]).optional(),
2158
- name: z6.string(),
2159
- description: z6.union([z6.string(), z6.null()]).optional(),
2160
- logo_url: z6.union([z6.string(), z6.null()]).optional(),
2161
- theme: EvalStatusPageTheme,
2162
- config: EvalStatusPageConfig
2163
- });
2164
2143
  var RepoInfo = z6.union([
2165
2144
  z6.object({
2166
2145
  commit: z6.union([z6.string(), z6.null()]),
@@ -2187,6 +2166,15 @@ var Experiment = z6.object({
2187
2166
  deleted_at: z6.union([z6.string(), z6.null()]).optional(),
2188
2167
  dataset_id: z6.union([z6.string(), z6.null()]).optional(),
2189
2168
  dataset_version: z6.union([z6.string(), z6.null()]).optional(),
2169
+ internal_metadata: z6.union([
2170
+ z6.object({
2171
+ dataset_filter: z6.union([
2172
+ z6.object({}).partial().passthrough(),
2173
+ z6.null()
2174
+ ])
2175
+ }).partial().passthrough(),
2176
+ z6.null()
2177
+ ]).optional(),
2190
2178
  parameters_id: z6.union([z6.string(), z6.null()]).optional(),
2191
2179
  parameters_version: z6.union([z6.string(), z6.null()]).optional(),
2192
2180
  public: z6.boolean(),
@@ -2923,14 +2911,21 @@ var ProjectAutomation = z6.object({
2923
2911
  z6.object({ type: z6.literal("log_spans") }),
2924
2912
  z6.object({ type: z6.literal("btql_query"), btql_query: z6.string() })
2925
2913
  ]),
2914
+ scope: z6.union([SpanScope, TraceScope, GroupScope, z6.null()]).optional(),
2926
2915
  export_path: z6.string(),
2927
2916
  format: z6.enum(["jsonl", "parquet"]),
2928
2917
  interval_seconds: z6.number().gte(1).lte(2592e3),
2929
- credentials: z6.object({
2930
- type: z6.literal("aws_iam"),
2931
- role_arn: z6.string(),
2932
- external_id: z6.string()
2933
- }),
2918
+ credentials: z6.union([
2919
+ z6.object({
2920
+ type: z6.literal("aws_iam"),
2921
+ role_arn: z6.string(),
2922
+ external_id: z6.string()
2923
+ }),
2924
+ z6.object({
2925
+ type: z6.literal("gcp_service_account"),
2926
+ service_account_email: z6.string()
2927
+ })
2928
+ ]),
2934
2929
  batch_size: z6.union([z6.number(), z6.null()]).optional()
2935
2930
  }),
2936
2931
  z6.object({
@@ -3310,7 +3305,7 @@ var ViewOptions = z6.union([
3310
3305
  z6.object({ from: z6.string(), to: z6.string() }),
3311
3306
  z6.null()
3312
3307
  ]),
3313
- queryShape: z6.union([z6.enum(["traces", "spans"]), z6.null()]),
3308
+ queryShape: z6.union([z6.enum(["traces", "spans", "topics"]), z6.null()]),
3314
3309
  cluster: z6.union([z6.string(), z6.null()]),
3315
3310
  freezeColumns: z6.union([z6.boolean(), z6.null()])
3316
3311
  }).partial(),
@@ -4326,6 +4321,19 @@ var RESET_CONTEXT_MANAGER_STATE = Symbol.for(
4326
4321
  "braintrust.resetContextManagerState"
4327
4322
  );
4328
4323
  var DEFAULT_MAX_REQUEST_SIZE = 6 * 1024 * 1024;
4324
+ var datasetSnapshotRegisterResponseSchema = z8.object({
4325
+ dataset_snapshot: DatasetSnapshot,
4326
+ found_existing: z8.boolean().optional()
4327
+ });
4328
+ var datasetRestorePreviewResultSchema = z8.object({
4329
+ rows_to_restore: z8.number(),
4330
+ rows_to_delete: z8.number()
4331
+ });
4332
+ var datasetRestoreResultSchema = z8.object({
4333
+ xact_id: z8.string().nullable(),
4334
+ rows_restored: z8.number(),
4335
+ rows_deleted: z8.number()
4336
+ });
4329
4337
  var parametersRowSchema = z8.object({
4330
4338
  id: z8.string().uuid(),
4331
4339
  _xact_id: z8.string(),
@@ -6547,6 +6555,33 @@ Error: ${errorText}`;
6547
6555
  this.queue.enforceQueueSizeLimit(enforce);
6548
6556
  }
6549
6557
  };
6558
+ function isDatasetSnapshotNameLookup(lookup) {
6559
+ return "snapshotName" in lookup;
6560
+ }
6561
+ function assertDatasetSnapshotLookup(lookup) {
6562
+ const hasSnapshotName = lookup.snapshotName !== void 0;
6563
+ const hasXactId = lookup.xactId !== void 0;
6564
+ if (hasSnapshotName === hasXactId) {
6565
+ throw new Error("Exactly one of snapshotName or xactId must be provided");
6566
+ }
6567
+ }
6568
+ function getExperimentDatasetFilter({
6569
+ dataset,
6570
+ _internal_btql
6571
+ }) {
6572
+ if (_internal_btql !== void 0) {
6573
+ return _internal_btql;
6574
+ }
6575
+ if (!(dataset instanceof Dataset2)) {
6576
+ return void 0;
6577
+ }
6578
+ const datasetFilter = Reflect.get(dataset, "_internal_btql");
6579
+ return isObject(datasetFilter) ? datasetFilter : void 0;
6580
+ }
6581
+ function getInternalBtqlLimit(internalBtql) {
6582
+ const limit = internalBtql?.["limit"];
6583
+ return typeof limit === "number" ? limit : void 0;
6584
+ }
6550
6585
  function init(projectOrOptions, optionalOptions) {
6551
6586
  const options = (() => {
6552
6587
  if (typeof projectOrOptions === "string") {
@@ -6565,6 +6600,7 @@ function init(projectOrOptions, optionalOptions) {
6565
6600
  experiment,
6566
6601
  description,
6567
6602
  dataset,
6603
+ _internal_btql,
6568
6604
  parameters,
6569
6605
  baseExperiment,
6570
6606
  isPublic,
@@ -6673,16 +6709,24 @@ function init(projectOrOptions, optionalOptions) {
6673
6709
  args["ancestor_commits"] = await isomorph_default.getPastNAncestors();
6674
6710
  }
6675
6711
  if (dataset !== void 0) {
6676
- if ("id" in dataset && typeof dataset.id === "string" && !("__braintrust_dataset_marker" in dataset)) {
6677
- args["dataset_id"] = dataset.id;
6678
- if ("version" in dataset && dataset.version !== void 0) {
6679
- args["dataset_version"] = dataset.version;
6680
- }
6681
- } else {
6682
- args["dataset_id"] = await dataset.id;
6683
- args["dataset_version"] = await dataset.version();
6712
+ const datasetSelection = await serializeDatasetForExperiment({
6713
+ dataset,
6714
+ state
6715
+ });
6716
+ args["dataset_id"] = datasetSelection.datasetId;
6717
+ if (datasetSelection.datasetVersion !== void 0) {
6718
+ args["dataset_version"] = datasetSelection.datasetVersion;
6684
6719
  }
6685
6720
  }
6721
+ const datasetFilter = getExperimentDatasetFilter({
6722
+ dataset,
6723
+ _internal_btql
6724
+ });
6725
+ if (datasetFilter !== void 0) {
6726
+ args["internal_metadata"] = {
6727
+ dataset_filter: datasetFilter
6728
+ };
6729
+ }
6686
6730
  if (parameters !== void 0) {
6687
6731
  if (RemoteEvalParameters.isParameters(parameters)) {
6688
6732
  args["parameters_id"] = parameters.id;
@@ -6736,7 +6780,7 @@ function init(projectOrOptions, optionalOptions) {
6736
6780
  const ret = new Experiment2(
6737
6781
  state,
6738
6782
  lazyMetadata,
6739
- dataset !== void 0 && "version" in dataset ? dataset : void 0
6783
+ dataset !== void 0 ? dataset : void 0
6740
6784
  );
6741
6785
  if (options.setCurrent ?? true) {
6742
6786
  state.currentExperiment = ret;
@@ -6772,6 +6816,153 @@ function withLogger(callback, options = {}) {
6772
6816
  const logger = initLogger(options);
6773
6817
  return callback(logger);
6774
6818
  }
6819
+ async function getDatasetSnapshots(params) {
6820
+ const { state, datasetId } = params;
6821
+ return DatasetSnapshot.array().parse(
6822
+ await state.appConn().post_json("api/dataset_snapshot/get", {
6823
+ dataset_id: datasetId,
6824
+ ..."snapshotName" in params ? { name: params.snapshotName } : {},
6825
+ ..."xactId" in params ? { xact_id: params.xactId } : {}
6826
+ })
6827
+ );
6828
+ }
6829
+ async function getDatasetSnapshot(params) {
6830
+ assertDatasetSnapshotLookup(params);
6831
+ const snapshots = await getDatasetSnapshots(params);
6832
+ if (snapshots.length > 1) {
6833
+ throw new Error(
6834
+ isDatasetSnapshotNameLookup(params) ? `Expected a unique dataset snapshot named "${params.snapshotName}" for ${params.datasetId}` : `Expected a unique dataset snapshot for xact_id "${params.xactId}" in ${params.datasetId}`
6835
+ );
6836
+ }
6837
+ return snapshots[0];
6838
+ }
6839
+ function normalizeDatasetSelection({
6840
+ version,
6841
+ environment,
6842
+ snapshotName
6843
+ }) {
6844
+ if (version !== void 0) {
6845
+ return { version };
6846
+ }
6847
+ if (snapshotName !== void 0) {
6848
+ return { snapshotName };
6849
+ }
6850
+ if (environment !== void 0) {
6851
+ return { environment };
6852
+ }
6853
+ return {};
6854
+ }
6855
+ async function resolveDatasetSnapshotName({
6856
+ state,
6857
+ datasetId,
6858
+ snapshotName
6859
+ }) {
6860
+ const match = await getDatasetSnapshot({
6861
+ state,
6862
+ datasetId,
6863
+ snapshotName
6864
+ });
6865
+ if (match === void 0) {
6866
+ throw new Error(
6867
+ `Dataset snapshot "${snapshotName}" not found for ${datasetId}`
6868
+ );
6869
+ }
6870
+ return match.xact_id;
6871
+ }
6872
+ async function resolveDatasetSnapshotNameForMetadata({
6873
+ state,
6874
+ lazyMetadata,
6875
+ snapshotName
6876
+ }) {
6877
+ const metadata = await lazyMetadata.get();
6878
+ return await resolveDatasetSnapshotName({
6879
+ state,
6880
+ datasetId: metadata.dataset.id,
6881
+ snapshotName
6882
+ });
6883
+ }
6884
+ async function resolveDatasetEnvironment({
6885
+ state,
6886
+ datasetId,
6887
+ environment
6888
+ }) {
6889
+ const environmentObjectPath = `environment-object/dataset/${datasetId}/${encodeURIComponent(environment)}`;
6890
+ const response = state.orgName == null ? await state.apiConn().get_json(environmentObjectPath) : await state.apiConn().get_json(environmentObjectPath, {
6891
+ org_name: state.orgName
6892
+ });
6893
+ return z8.object({ object_version: z8.string() }).parse(response).object_version;
6894
+ }
6895
+ async function resolveDatasetEnvironmentForMetadata({
6896
+ state,
6897
+ lazyMetadata,
6898
+ environment
6899
+ }) {
6900
+ const metadata = await lazyMetadata.get();
6901
+ return await resolveDatasetEnvironment({
6902
+ state,
6903
+ datasetId: metadata.dataset.id,
6904
+ environment
6905
+ });
6906
+ }
6907
+ async function serializeDatasetForExperiment({
6908
+ dataset,
6909
+ state
6910
+ }) {
6911
+ if (!Dataset2.isDataset(dataset)) {
6912
+ const selection2 = normalizeDatasetSelection(dataset);
6913
+ if (selection2.version !== void 0) {
6914
+ return {
6915
+ datasetId: dataset.id,
6916
+ datasetVersion: selection2.version
6917
+ };
6918
+ }
6919
+ if (selection2.snapshotName !== void 0) {
6920
+ return {
6921
+ datasetId: dataset.id,
6922
+ datasetVersion: await resolveDatasetSnapshotName({
6923
+ state,
6924
+ datasetId: dataset.id,
6925
+ snapshotName: selection2.snapshotName
6926
+ })
6927
+ };
6928
+ }
6929
+ if (selection2.environment !== void 0) {
6930
+ return {
6931
+ datasetId: dataset.id,
6932
+ datasetVersion: await resolveDatasetEnvironment({
6933
+ state,
6934
+ datasetId: dataset.id,
6935
+ environment: selection2.environment
6936
+ })
6937
+ };
6938
+ }
6939
+ return {
6940
+ datasetId: dataset.id
6941
+ };
6942
+ }
6943
+ const evalData = await dataset.toEvalData();
6944
+ const selection = normalizeDatasetSelection({
6945
+ version: evalData.dataset_version,
6946
+ environment: evalData.dataset_environment,
6947
+ snapshotName: evalData.dataset_snapshot_name
6948
+ });
6949
+ if (selection.version !== void 0) {
6950
+ return {
6951
+ datasetId: evalData.dataset_id,
6952
+ datasetVersion: selection.version
6953
+ };
6954
+ }
6955
+ const datasetVersion = await dataset.version();
6956
+ if (datasetVersion !== void 0) {
6957
+ return {
6958
+ datasetId: evalData.dataset_id,
6959
+ datasetVersion
6960
+ };
6961
+ }
6962
+ return {
6963
+ datasetId: evalData.dataset_id
6964
+ };
6965
+ }
6775
6966
  function initDataset(projectOrOptions, optionalOptions) {
6776
6967
  const options = (() => {
6777
6968
  if (typeof projectOrOptions === "string") {
@@ -6790,6 +6981,8 @@ function initDataset(projectOrOptions, optionalOptions) {
6790
6981
  dataset,
6791
6982
  description,
6792
6983
  version,
6984
+ snapshotName,
6985
+ environment,
6793
6986
  appUrl,
6794
6987
  apiKey,
6795
6988
  orgName,
@@ -6801,6 +6994,14 @@ function initDataset(projectOrOptions, optionalOptions) {
6801
6994
  state: stateArg,
6802
6995
  _internal_btql
6803
6996
  } = options;
6997
+ const selection = normalizeDatasetSelection({
6998
+ version,
6999
+ environment,
7000
+ snapshotName
7001
+ });
7002
+ const normalizedVersion = selection.version;
7003
+ const normalizedEnvironment = selection.environment;
7004
+ const normalizedSnapshotName = selection.snapshotName;
6804
7005
  const state = stateArg ?? _globalState;
6805
7006
  const lazyMetadata = new LazyValue(
6806
7007
  async () => {
@@ -6834,13 +7035,38 @@ function initDataset(projectOrOptions, optionalOptions) {
6834
7035
  };
6835
7036
  }
6836
7037
  );
6837
- return new Dataset2(
7038
+ const resolvedVersion = normalizedVersion !== void 0 ? normalizedVersion : normalizedSnapshotName !== void 0 ? new LazyValue(async () => {
7039
+ return await resolveDatasetSnapshotNameForMetadata({
7040
+ state,
7041
+ lazyMetadata,
7042
+ snapshotName: normalizedSnapshotName
7043
+ });
7044
+ }) : normalizedEnvironment !== void 0 ? new LazyValue(async () => {
7045
+ return await resolveDatasetEnvironmentForMetadata({
7046
+ state,
7047
+ lazyMetadata,
7048
+ environment: normalizedEnvironment
7049
+ });
7050
+ }) : void 0;
7051
+ const datasetObject = new Dataset2(
6838
7052
  stateArg ?? _globalState,
6839
7053
  lazyMetadata,
6840
- version,
7054
+ typeof resolvedVersion === "string" ? resolvedVersion : void 0,
6841
7055
  legacy,
6842
- _internal_btql
7056
+ _internal_btql,
7057
+ resolvedVersion instanceof LazyValue || normalizedEnvironment !== void 0 || normalizedSnapshotName !== void 0 ? {
7058
+ ...resolvedVersion instanceof LazyValue ? {
7059
+ lazyPinnedVersion: resolvedVersion
7060
+ } : {},
7061
+ ...normalizedEnvironment !== void 0 ? {
7062
+ pinnedEnvironment: normalizedEnvironment
7063
+ } : {},
7064
+ ...normalizedSnapshotName !== void 0 ? {
7065
+ pinnedSnapshotName: normalizedSnapshotName
7066
+ } : {}
7067
+ } : void 0
6843
7068
  );
7069
+ return datasetObject;
6844
7070
  }
6845
7071
  function withDataset(project, callback, options = {}) {
6846
7072
  debugLogger.forState(options.state).warn(
@@ -7836,11 +8062,20 @@ var ObjectFetcher = class {
7836
8062
  async getState() {
7837
8063
  throw new Error("ObjectFetcher subclasses must have a 'getState' method");
7838
8064
  }
8065
+ getPinnedVersion() {
8066
+ return this.pinnedVersion;
8067
+ }
8068
+ setPinnedVersion(pinnedVersion) {
8069
+ this.pinnedVersion = pinnedVersion;
8070
+ }
8071
+ getInternalBtql() {
8072
+ return this._internal_btql;
8073
+ }
7839
8074
  async *fetchRecordsFromApi(batchSize) {
7840
8075
  const state = await this.getState();
7841
8076
  const objectId = await this.id;
7842
8077
  const batchLimit = batchSize ?? DEFAULT_FETCH_BATCH_SIZE;
7843
- const internalLimit = this._internal_btql?.limit;
8078
+ const internalLimit = getInternalBtqlLimit(this._internal_btql);
7844
8079
  const limit = batchSize !== void 0 ? batchSize : internalLimit ?? batchLimit;
7845
8080
  const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
7846
8081
  Object.entries(this._internal_btql ?? {}).filter(
@@ -8654,7 +8889,7 @@ function splitLoggingData({
8654
8889
  return [serializableInternalData, lazyInternalData];
8655
8890
  }
8656
8891
  var Dataset2 = class extends ObjectFetcher {
8657
- constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql) {
8892
+ constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql, pinState) {
8658
8893
  const isLegacyDataset = legacy ?? DEFAULT_IS_LEGACY_DATASET;
8659
8894
  if (isLegacyDataset) {
8660
8895
  debugLogger.forState(state).warn(
@@ -8675,10 +8910,16 @@ var Dataset2 = class extends ObjectFetcher {
8675
8910
  );
8676
8911
  this.state = state;
8677
8912
  this.lazyMetadata = lazyMetadata;
8913
+ this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
8914
+ this.pinnedEnvironment = pinState?.pinnedEnvironment;
8915
+ this.pinnedSnapshotName = pinState?.pinnedSnapshotName;
8678
8916
  }
8679
8917
  lazyMetadata;
8680
8918
  __braintrust_dataset_marker = true;
8681
8919
  newRecords = 0;
8920
+ lazyPinnedVersion;
8921
+ pinnedEnvironment;
8922
+ pinnedSnapshotName;
8682
8923
  get id() {
8683
8924
  return (async () => {
8684
8925
  return (await this.lazyMetadata.get()).dataset.id;
@@ -8697,10 +8938,40 @@ var Dataset2 = class extends ObjectFetcher {
8697
8938
  get loggingState() {
8698
8939
  return this.state;
8699
8940
  }
8941
+ async toEvalData() {
8942
+ await this.getState();
8943
+ const metadata = await this.lazyMetadata.get();
8944
+ const pinnedVersion = this.getPinnedVersion();
8945
+ const internalBtql = this.getInternalBtql();
8946
+ return {
8947
+ dataset_id: metadata.dataset.id,
8948
+ ...this.pinnedEnvironment !== void 0 ? {
8949
+ dataset_environment: this.pinnedEnvironment
8950
+ } : {},
8951
+ ...this.pinnedEnvironment === void 0 && this.pinnedSnapshotName !== void 0 ? {
8952
+ dataset_snapshot_name: this.pinnedSnapshotName
8953
+ } : {},
8954
+ ...this.pinnedEnvironment === void 0 && this.pinnedSnapshotName === void 0 && pinnedVersion !== void 0 ? {
8955
+ dataset_version: pinnedVersion
8956
+ } : {},
8957
+ ...internalBtql !== void 0 ? { _internal_btql: internalBtql } : {}
8958
+ };
8959
+ }
8700
8960
  async getState() {
8701
8961
  await this.lazyMetadata.get();
8962
+ if (this.lazyPinnedVersion !== void 0 && this.getPinnedVersion() === void 0) {
8963
+ this.setPinnedVersion(await this.lazyPinnedVersion.get());
8964
+ }
8702
8965
  return this.state;
8703
8966
  }
8967
+ async version(options) {
8968
+ const pinnedVersion = this.getPinnedVersion();
8969
+ if (pinnedVersion !== void 0) {
8970
+ return pinnedVersion;
8971
+ }
8972
+ await this.getState();
8973
+ return await super.version(options);
8974
+ }
8704
8975
  validateEvent({
8705
8976
  metadata,
8706
8977
  expected,
@@ -8836,6 +9107,88 @@ var Dataset2 = class extends ObjectFetcher {
8836
9107
  this.state.bgLogger().log([args]);
8837
9108
  return id;
8838
9109
  }
9110
+ async createSnapshot({
9111
+ name,
9112
+ description,
9113
+ update
9114
+ }) {
9115
+ await this.flush();
9116
+ const state = await this.getState();
9117
+ const datasetId = await this.id;
9118
+ const currentVersion = await this.version();
9119
+ if (currentVersion === void 0) {
9120
+ throw new Error("Cannot create snapshot: dataset has no version");
9121
+ }
9122
+ const response = await state.appConn().post_json("api/dataset_snapshot/register", {
9123
+ dataset_id: datasetId,
9124
+ dataset_snapshot_name: name,
9125
+ description,
9126
+ xact_id: currentVersion,
9127
+ update
9128
+ });
9129
+ return datasetSnapshotRegisterResponseSchema.parse(response).dataset_snapshot;
9130
+ }
9131
+ async listSnapshots() {
9132
+ const state = await this.getState();
9133
+ return await getDatasetSnapshots({
9134
+ state,
9135
+ datasetId: await this.id
9136
+ });
9137
+ }
9138
+ async getSnapshot(lookup) {
9139
+ const state = await this.getState();
9140
+ const datasetId = await this.id;
9141
+ return await getDatasetSnapshot({
9142
+ state,
9143
+ datasetId,
9144
+ ...lookup
9145
+ });
9146
+ }
9147
+ async updateSnapshot(snapshotId, {
9148
+ name,
9149
+ description
9150
+ }) {
9151
+ const state = await this.getState();
9152
+ return DatasetSnapshot.parse(
9153
+ await state.appConn().post_json("api/dataset_snapshot/patch_id", {
9154
+ id: snapshotId,
9155
+ name,
9156
+ description
9157
+ })
9158
+ );
9159
+ }
9160
+ async deleteSnapshot(snapshotId) {
9161
+ const state = await this.getState();
9162
+ return DatasetSnapshot.parse(
9163
+ await state.appConn().post_json("api/dataset_snapshot/delete_id", {
9164
+ id: snapshotId
9165
+ })
9166
+ );
9167
+ }
9168
+ async restorePreview({
9169
+ version
9170
+ }) {
9171
+ await this.flush();
9172
+ const state = await this.getState();
9173
+ const datasetId = await this.id;
9174
+ return datasetRestorePreviewResultSchema.parse(
9175
+ await state.apiConn().post_json(`v1/dataset/${datasetId}/restore/preview`, {
9176
+ version
9177
+ })
9178
+ );
9179
+ }
9180
+ async restore({
9181
+ version
9182
+ }) {
9183
+ await this.flush();
9184
+ const state = await this.getState();
9185
+ const datasetId = await this.id;
9186
+ return datasetRestoreResultSchema.parse(
9187
+ await state.apiConn().post_json(`v1/dataset/${datasetId}/restore`, {
9188
+ version
9189
+ })
9190
+ );
9191
+ }
8839
9192
  /**
8840
9193
  * Summarize the dataset, including high level metrics about its size and other metadata.
8841
9194
  * @param summarizeData Whether to summarize the data. If false, only the metadata will be returned.
@@ -14212,6 +14565,9 @@ function llmParentKey(parentToolUseId) {
14212
14565
  function isSubAgentDelegationToolName(toolName) {
14213
14566
  return toolName === "Agent" || toolName === "Task";
14214
14567
  }
14568
+ function shouldParentToolAsTaskSibling(toolName) {
14569
+ return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
14570
+ }
14215
14571
  function filterSerializableOptions(options) {
14216
14572
  const allowedKeys = [
14217
14573
  "model",
@@ -14311,6 +14667,11 @@ function resolveTaskToolUseId(taskIdToToolUseId, message) {
14311
14667
  }
14312
14668
  return void 0;
14313
14669
  }
14670
+ function seedTaskToolUseIdMapping(taskIdToToolUseId, message) {
14671
+ if (typeof message.task_id === "string" && typeof message.tool_use_id === "string") {
14672
+ taskIdToToolUseId.set(message.task_id, message.tool_use_id);
14673
+ }
14674
+ }
14314
14675
  function extractUsageFromMessage(message) {
14315
14676
  const metrics = {};
14316
14677
  let usage;
@@ -14506,7 +14867,10 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
14506
14867
  }
14507
14868
  },
14508
14869
  name: parsed.displayName,
14509
- parent: await resolveParentSpan(toolUseID),
14870
+ parent: await resolveParentSpan(toolUseID, {
14871
+ agentId: input.agent_id,
14872
+ preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
14873
+ }),
14510
14874
  spanAttributes: { type: "tool" /* TOOL */ }
14511
14875
  });
14512
14876
  activeToolSpans.set(toolUseID, toolSpan);
@@ -14796,6 +15160,7 @@ async function finalizeCurrentMessageGroup(state) {
14796
15160
  state.currentMessages.length = 0;
14797
15161
  }
14798
15162
  function maybeTrackToolUseContext(state, message) {
15163
+ seedTaskToolUseIdMapping(state.taskIdToToolUseId, message);
14799
15164
  if (message.type !== "assistant" || !Array.isArray(message.message?.content)) {
14800
15165
  return;
14801
15166
  }
@@ -14850,6 +15215,34 @@ async function ensureSubAgentSpan(subAgentDetailsByToolUseId, rootSpan, activeTo
14850
15215
  subAgentSpans.set(parentToolUseId, subAgentSpan);
14851
15216
  return subAgentSpan;
14852
15217
  }
15218
+ async function ensureActiveLlmSpanForParentToolUse(rootSpan, activeLlmSpansByParentToolUse, subAgentDetailsByToolUseId, activeToolSpans, subAgentSpans, parentToolUseId, startTime) {
15219
+ const parentKey = llmParentKey(parentToolUseId);
15220
+ const existingLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
15221
+ if (existingLlmSpan) {
15222
+ return existingLlmSpan;
15223
+ }
15224
+ let llmParentSpan = await rootSpan.export();
15225
+ if (parentToolUseId) {
15226
+ const subAgentSpan = await ensureSubAgentSpan(
15227
+ subAgentDetailsByToolUseId,
15228
+ rootSpan,
15229
+ activeToolSpans,
15230
+ subAgentSpans,
15231
+ parentToolUseId
15232
+ );
15233
+ llmParentSpan = await subAgentSpan.export();
15234
+ }
15235
+ const llmSpan = startSpan({
15236
+ name: "anthropic.messages.create",
15237
+ parent: llmParentSpan,
15238
+ spanAttributes: {
15239
+ type: "llm" /* LLM */
15240
+ },
15241
+ startTime
15242
+ });
15243
+ activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
15244
+ return llmSpan;
15245
+ }
14853
15246
  async function maybeHandleTaskLifecycleMessage(state, message) {
14854
15247
  if (message.type !== "system") {
14855
15248
  return false;
@@ -14959,29 +15352,15 @@ async function handleStreamMessage(state, message) {
14959
15352
  }
14960
15353
  if (message.type === "assistant" && message.message?.usage) {
14961
15354
  const parentToolUseId = message.parent_tool_use_id ?? null;
14962
- const parentKey = llmParentKey(parentToolUseId);
14963
- if (!state.activeLlmSpansByParentToolUse.has(parentKey)) {
14964
- let llmParentSpan = await state.span.export();
14965
- if (parentToolUseId) {
14966
- const subAgentSpan = await ensureSubAgentSpan(
14967
- state.subAgentDetailsByToolUseId,
14968
- state.span,
14969
- state.activeToolSpans,
14970
- state.subAgentSpans,
14971
- parentToolUseId
14972
- );
14973
- llmParentSpan = await subAgentSpan.export();
14974
- }
14975
- const llmSpan = startSpan({
14976
- name: "anthropic.messages.create",
14977
- parent: llmParentSpan,
14978
- spanAttributes: {
14979
- type: "llm" /* LLM */
14980
- },
14981
- startTime: state.currentMessageStartTime
14982
- });
14983
- state.activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
14984
- }
15355
+ await ensureActiveLlmSpanForParentToolUse(
15356
+ state.span,
15357
+ state.activeLlmSpansByParentToolUse,
15358
+ state.subAgentDetailsByToolUseId,
15359
+ state.activeToolSpans,
15360
+ state.subAgentSpans,
15361
+ parentToolUseId,
15362
+ state.currentMessageStartTime
15363
+ );
14985
15364
  state.currentMessages.push(message);
14986
15365
  }
14987
15366
  if (message.type !== "result" || !message.usage) {
@@ -15128,10 +15507,35 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
15128
15507
  const localToolContext = createClaudeLocalToolContext();
15129
15508
  const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
15130
15509
  const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
15131
- const resolveToolUseParentSpan = async (toolUseID) => {
15132
- const parentToolUseId = toolUseToParent.get(toolUseID) ?? null;
15510
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
15511
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
15512
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
15133
15513
  const parentKey = llmParentKey(parentToolUseId);
15134
15514
  const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
15515
+ if (context?.preferTaskSiblingParent) {
15516
+ if (!activeLlmSpan) {
15517
+ await ensureActiveLlmSpanForParentToolUse(
15518
+ span,
15519
+ activeLlmSpansByParentToolUse,
15520
+ subAgentDetailsByToolUseId,
15521
+ activeToolSpans,
15522
+ subAgentSpans,
15523
+ parentToolUseId,
15524
+ getCurrentUnixTimestamp()
15525
+ );
15526
+ }
15527
+ if (parentToolUseId) {
15528
+ const subAgentSpan = await ensureSubAgentSpan(
15529
+ subAgentDetailsByToolUseId,
15530
+ span,
15531
+ activeToolSpans,
15532
+ subAgentSpans,
15533
+ parentToolUseId
15534
+ );
15535
+ return subAgentSpan.export();
15536
+ }
15537
+ return span.export();
15538
+ }
15135
15539
  if (activeLlmSpan) {
15136
15540
  return activeLlmSpan.export();
15137
15541
  }
@@ -15259,62 +15663,940 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
15259
15663
  }
15260
15664
  };
15261
15665
 
15262
- // src/instrumentation/plugins/google-genai-channels.ts
15263
- var googleGenAIChannels = defineChannels("@google/genai", {
15264
- generateContent: channel({
15265
- channelName: "models.generateContent",
15666
+ // src/instrumentation/plugins/cursor-sdk-channels.ts
15667
+ var cursorSDKChannels = defineChannels("@cursor/sdk", {
15668
+ create: channel({
15669
+ channelName: "Agent.create",
15266
15670
  kind: "async"
15267
15671
  }),
15268
- generateContentStream: channel({
15269
- channelName: "models.generateContentStream",
15672
+ resume: channel({
15673
+ channelName: "Agent.resume",
15270
15674
  kind: "async"
15271
15675
  }),
15272
- embedContent: channel({
15273
- channelName: "models.embedContent",
15676
+ prompt: channel({
15677
+ channelName: "Agent.prompt",
15678
+ kind: "async"
15679
+ }),
15680
+ send: channel({
15681
+ channelName: "agent.send",
15274
15682
  kind: "async"
15275
15683
  })
15276
15684
  });
15277
15685
 
15278
- // src/instrumentation/plugins/google-genai-plugin.ts
15279
- var GOOGLE_GENAI_INTERNAL_CONTEXT = {
15280
- caller_filename: "<node-internal>",
15281
- caller_functionname: "<node-internal>",
15282
- caller_lineno: 0
15283
- };
15284
- function createWrapperParityEvent(args) {
15285
- return {
15286
- context: GOOGLE_GENAI_INTERNAL_CONTEXT,
15287
- input: args.input,
15288
- metadata: args.metadata
15289
- };
15290
- }
15291
- var GoogleGenAIPlugin = class extends BasePlugin {
15686
+ // src/instrumentation/plugins/cursor-sdk-plugin.ts
15687
+ var PATCHED_AGENT = Symbol.for("braintrust.cursor-sdk.auto-patched-agent");
15688
+ var PATCHED_RUN = Symbol.for("braintrust.cursor-sdk.patched-run");
15689
+ var WRAPPED_AGENT = Symbol.for("braintrust.cursor-sdk.wrapped-agent");
15690
+ var CursorSDKPlugin = class extends BasePlugin {
15691
+ promptDepth = 0;
15292
15692
  onEnable() {
15293
- this.subscribeToGoogleGenAIChannels();
15693
+ this.subscribeToAgentFactories();
15694
+ this.subscribeToPrompt();
15695
+ this.subscribeToSend();
15294
15696
  }
15295
15697
  onDisable() {
15296
- this.unsubscribers = unsubscribeAll(this.unsubscribers);
15698
+ for (const unsubscribe of this.unsubscribers) {
15699
+ unsubscribe();
15700
+ }
15701
+ this.unsubscribers = [];
15702
+ this.promptDepth = 0;
15297
15703
  }
15298
- subscribeToGoogleGenAIChannels() {
15299
- this.subscribeToGenerateContentChannel();
15300
- this.subscribeToGenerateContentStreamChannel();
15301
- this.subscribeToEmbedContentChannel();
15704
+ subscribeToAgentFactories() {
15705
+ this.subscribeToAgentFactory(cursorSDKChannels.create);
15706
+ this.subscribeToAgentFactory(cursorSDKChannels.resume);
15302
15707
  }
15303
- subscribeToGenerateContentChannel() {
15304
- const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
15708
+ subscribeToAgentFactory(channel2) {
15709
+ const tracingChannel2 = channel2.tracingChannel();
15710
+ const handlers = {
15711
+ asyncEnd: (event) => {
15712
+ patchCursorAgentInPlace(event.result);
15713
+ },
15714
+ error: () => {
15715
+ }
15716
+ };
15717
+ tracingChannel2.subscribe(handlers);
15718
+ this.unsubscribers.push(() => {
15719
+ tracingChannel2.unsubscribe(handlers);
15720
+ });
15721
+ }
15722
+ subscribeToPrompt() {
15723
+ const channel2 = cursorSDKChannels.prompt.tracingChannel();
15305
15724
  const states = /* @__PURE__ */ new WeakMap();
15306
- const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
15307
- tracingChannel2,
15308
- states,
15309
- (event) => {
15310
- const params = event.arguments[0];
15311
- const input = serializeGenerateContentInput(params);
15312
- const metadata = extractGenerateContentMetadata(params);
15725
+ const handlers = {
15726
+ start: (event) => {
15727
+ this.promptDepth += 1;
15728
+ const message = event.arguments[0];
15729
+ const options = event.arguments[1];
15730
+ const metadata = {
15731
+ ...extractAgentOptionsMetadata(options),
15732
+ "cursor_sdk.operation": "Agent.prompt",
15733
+ provider: "cursor",
15734
+ ...event.moduleVersion ? { "cursor_sdk.version": event.moduleVersion } : {}
15735
+ };
15313
15736
  const span = startSpan({
15314
- name: "generate_content",
15315
- spanAttributes: {
15316
- type: "llm" /* LLM */
15317
- },
15737
+ name: "Cursor Agent",
15738
+ spanAttributes: { type: "task" /* TASK */ }
15739
+ });
15740
+ const startTime = getCurrentUnixTimestamp();
15741
+ safeLog(span, {
15742
+ input: sanitizeUserMessage(message),
15743
+ metadata
15744
+ });
15745
+ states.set(event, { metadata, span, startTime });
15746
+ },
15747
+ asyncEnd: (event) => {
15748
+ this.promptDepth = Math.max(0, this.promptDepth - 1);
15749
+ const state = states.get(event);
15750
+ if (!state) {
15751
+ return;
15752
+ }
15753
+ try {
15754
+ safeLog(state.span, {
15755
+ metadata: {
15756
+ ...state.metadata,
15757
+ ...extractRunResultMetadata(event.result)
15758
+ },
15759
+ metrics: buildDurationMetrics(state.startTime),
15760
+ output: event.result?.result ?? event.result
15761
+ });
15762
+ } finally {
15763
+ state.span.end();
15764
+ states.delete(event);
15765
+ }
15766
+ },
15767
+ error: (event) => {
15768
+ this.promptDepth = Math.max(0, this.promptDepth - 1);
15769
+ const state = states.get(event);
15770
+ if (!state || !event.error) {
15771
+ return;
15772
+ }
15773
+ safeLog(state.span, { error: event.error.message });
15774
+ state.span.end();
15775
+ states.delete(event);
15776
+ }
15777
+ };
15778
+ channel2.subscribe(handlers);
15779
+ this.unsubscribers.push(() => {
15780
+ channel2.unsubscribe(handlers);
15781
+ });
15782
+ }
15783
+ subscribeToSend() {
15784
+ const channel2 = cursorSDKChannels.send.tracingChannel();
15785
+ const states = /* @__PURE__ */ new WeakMap();
15786
+ const handlers = {
15787
+ start: (event) => {
15788
+ if (this.promptDepth > 0) {
15789
+ return;
15790
+ }
15791
+ const message = event.arguments[0];
15792
+ const sendOptions = event.arguments[1];
15793
+ const agent = event.agent;
15794
+ const metadata = {
15795
+ ...extractSendMetadata(sendOptions),
15796
+ ...agent ? extractAgentMetadata(agent) : {},
15797
+ "cursor_sdk.operation": "agent.send",
15798
+ provider: "cursor",
15799
+ ...event.moduleVersion ? { "cursor_sdk.version": event.moduleVersion } : {}
15800
+ };
15801
+ const span = startSpan({
15802
+ name: "Cursor Agent",
15803
+ spanAttributes: { type: "task" /* TASK */ }
15804
+ });
15805
+ const startTime = getCurrentUnixTimestamp();
15806
+ safeLog(span, {
15807
+ input: sanitizeUserMessage(message),
15808
+ metadata
15809
+ });
15810
+ const state = {
15811
+ activeToolSpans: /* @__PURE__ */ new Map(),
15812
+ agent,
15813
+ conversationText: [],
15814
+ deltaText: [],
15815
+ finalized: false,
15816
+ input: message,
15817
+ metadata,
15818
+ metrics: {},
15819
+ span,
15820
+ startTime,
15821
+ streamMessages: [],
15822
+ streamText: [],
15823
+ stepText: [],
15824
+ taskText: []
15825
+ };
15826
+ if (hasCursorCallbacks(sendOptions)) {
15827
+ event.arguments[1] = wrapSendOptionsCallbacks(sendOptions, state);
15828
+ }
15829
+ states.set(event, state);
15830
+ },
15831
+ asyncEnd: (event) => {
15832
+ const state = states.get(event);
15833
+ if (!state) {
15834
+ return;
15835
+ }
15836
+ if (!event.result) {
15837
+ return;
15838
+ }
15839
+ state.run = event.result;
15840
+ state.metadata = {
15841
+ ...state.metadata,
15842
+ ...extractRunMetadata(event.result)
15843
+ };
15844
+ patchCursorRun(event.result, state);
15845
+ },
15846
+ error: (event) => {
15847
+ const state = states.get(event);
15848
+ if (!state || !event.error) {
15849
+ return;
15850
+ }
15851
+ safeLog(state.span, { error: event.error.message });
15852
+ endOpenToolSpans(state, event.error.message);
15853
+ state.span.end();
15854
+ state.finalized = true;
15855
+ states.delete(event);
15856
+ }
15857
+ };
15858
+ channel2.subscribe(handlers);
15859
+ this.unsubscribers.push(() => {
15860
+ channel2.unsubscribe(handlers);
15861
+ });
15862
+ }
15863
+ };
15864
+ function patchCursorAgentInPlace(agent) {
15865
+ if (!agent || typeof agent !== "object") {
15866
+ return;
15867
+ }
15868
+ const agentRecord = agent;
15869
+ if (agentRecord[PATCHED_AGENT] || agentRecord[WRAPPED_AGENT] || typeof agentRecord.send !== "function") {
15870
+ return;
15871
+ }
15872
+ const originalSend = agentRecord.send.bind(agentRecord);
15873
+ try {
15874
+ Object.defineProperty(agentRecord, PATCHED_AGENT, {
15875
+ configurable: false,
15876
+ enumerable: false,
15877
+ value: true
15878
+ });
15879
+ Object.defineProperty(agentRecord, "send", {
15880
+ configurable: true,
15881
+ value(message, options) {
15882
+ const args = [message, options];
15883
+ return cursorSDKChannels.send.tracePromise(
15884
+ () => originalSend(...args),
15885
+ {
15886
+ agent: agentRecord,
15887
+ arguments: args,
15888
+ operation: "send"
15889
+ }
15890
+ );
15891
+ },
15892
+ writable: true
15893
+ });
15894
+ } catch {
15895
+ }
15896
+ }
15897
+ function wrapSendOptionsCallbacks(options, state) {
15898
+ const originalOnDelta = options.onDelta;
15899
+ const originalOnStep = options.onStep;
15900
+ return {
15901
+ ...options,
15902
+ async onDelta(args) {
15903
+ try {
15904
+ await handleInteractionUpdate(state, args.update);
15905
+ } catch (error) {
15906
+ logInstrumentationError("Cursor SDK onDelta", error);
15907
+ }
15908
+ if (originalOnDelta) {
15909
+ return originalOnDelta(args);
15910
+ }
15911
+ },
15912
+ async onStep(args) {
15913
+ try {
15914
+ handleStepUpdate(state, args.step);
15915
+ } catch (error) {
15916
+ logInstrumentationError("Cursor SDK onStep", error);
15917
+ }
15918
+ if (originalOnStep) {
15919
+ return originalOnStep(args);
15920
+ }
15921
+ }
15922
+ };
15923
+ }
15924
+ function hasCursorCallbacks(options) {
15925
+ return !!options && (typeof options.onDelta === "function" || typeof options.onStep === "function");
15926
+ }
15927
+ function patchCursorRun(run, state) {
15928
+ if (!run || typeof run !== "object") {
15929
+ return;
15930
+ }
15931
+ const runRecord = run;
15932
+ if (runRecord[PATCHED_RUN]) {
15933
+ return;
15934
+ }
15935
+ try {
15936
+ Object.defineProperty(runRecord, PATCHED_RUN, {
15937
+ configurable: false,
15938
+ enumerable: false,
15939
+ value: true
15940
+ });
15941
+ if (typeof runRecord.stream === "function") {
15942
+ const originalStream = runRecord.stream.bind(runRecord);
15943
+ Object.defineProperty(runRecord, "stream", {
15944
+ configurable: true,
15945
+ value() {
15946
+ const stream = originalStream();
15947
+ return patchCursorStream(stream, state);
15948
+ },
15949
+ writable: true
15950
+ });
15951
+ }
15952
+ if (typeof runRecord.wait === "function") {
15953
+ const originalWait = runRecord.wait.bind(runRecord);
15954
+ Object.defineProperty(runRecord, "wait", {
15955
+ configurable: true,
15956
+ async value() {
15957
+ try {
15958
+ const result = await originalWait();
15959
+ state.lastResult = result;
15960
+ await finalizeCursorRun(state, { result });
15961
+ return result;
15962
+ } catch (error) {
15963
+ await finalizeCursorRun(state, { error });
15964
+ throw error;
15965
+ }
15966
+ },
15967
+ writable: true
15968
+ });
15969
+ }
15970
+ if (typeof runRecord.conversation === "function") {
15971
+ const originalConversation = runRecord.conversation.bind(runRecord);
15972
+ Object.defineProperty(runRecord, "conversation", {
15973
+ configurable: true,
15974
+ async value() {
15975
+ try {
15976
+ const conversation = await originalConversation();
15977
+ await handleConversation(state, conversation);
15978
+ await finalizeCursorRun(state);
15979
+ return conversation;
15980
+ } catch (error) {
15981
+ await finalizeCursorRun(state, { error });
15982
+ throw error;
15983
+ }
15984
+ },
15985
+ writable: true
15986
+ });
15987
+ }
15988
+ } catch {
15989
+ void finalizeCursorRun(state, { output: run });
15990
+ }
15991
+ }
15992
+ async function* patchCursorStream(stream, state) {
15993
+ try {
15994
+ for await (const message of stream) {
15995
+ try {
15996
+ await handleStreamMessage2(state, message);
15997
+ } catch (error) {
15998
+ logInstrumentationError("Cursor SDK stream", error);
15999
+ }
16000
+ yield message;
16001
+ }
16002
+ await finalizeCursorRun(state);
16003
+ } catch (error) {
16004
+ await finalizeCursorRun(state, { error });
16005
+ throw error;
16006
+ }
16007
+ }
16008
+ async function handleInteractionUpdate(state, update) {
16009
+ switch (update.type) {
16010
+ case "text-delta":
16011
+ if (typeof update.text === "string") {
16012
+ state.deltaText.push(update.text);
16013
+ }
16014
+ return;
16015
+ case "token-delta":
16016
+ if (typeof update.tokens === "number") {
16017
+ state.metrics["cursor_sdk.delta_tokens"] = (state.metrics["cursor_sdk.delta_tokens"] ?? 0) + update.tokens;
16018
+ }
16019
+ return;
16020
+ case "tool-call-started":
16021
+ case "partial-tool-call":
16022
+ case "tool-call-completed":
16023
+ await handleToolUpdate(
16024
+ state,
16025
+ update
16026
+ );
16027
+ return;
16028
+ case "turn-ended":
16029
+ addUsageMetrics(
16030
+ state.metrics,
16031
+ update.usage
16032
+ );
16033
+ return;
16034
+ case "summary":
16035
+ if (typeof update.summary === "string") {
16036
+ state.taskText.push(update.summary);
16037
+ }
16038
+ return;
16039
+ case "step-completed":
16040
+ if (typeof update.stepDurationMs === "number") {
16041
+ state.metrics["cursor_sdk.step_duration_ms"] = (state.metrics["cursor_sdk.step_duration_ms"] ?? 0) + update.stepDurationMs;
16042
+ }
16043
+ state.metrics["cursor_sdk.steps"] = (state.metrics["cursor_sdk.steps"] ?? 0) + 1;
16044
+ return;
16045
+ default:
16046
+ return;
16047
+ }
16048
+ }
16049
+ async function handleToolUpdate(state, update) {
16050
+ const callId = update.callId;
16051
+ if (!callId) {
16052
+ return;
16053
+ }
16054
+ const toolCall = update.toolCall;
16055
+ const name = extractToolName(toolCall);
16056
+ const args = extractToolArgs(toolCall);
16057
+ const result = extractToolResult(toolCall);
16058
+ if (update.type === "tool-call-started" || update.type === "partial-tool-call") {
16059
+ if (!state.activeToolSpans.has(callId)) {
16060
+ state.activeToolSpans.set(
16061
+ callId,
16062
+ await startToolSpan(state, {
16063
+ args,
16064
+ callId,
16065
+ name,
16066
+ status: "running",
16067
+ toolCall
16068
+ })
16069
+ );
16070
+ }
16071
+ return;
16072
+ }
16073
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
16074
+ args,
16075
+ callId,
16076
+ name,
16077
+ status: "completed",
16078
+ toolCall
16079
+ });
16080
+ finishToolSpan(toolState, {
16081
+ error: toolCall?.status === "error" ? stringifyUnknown(result) : void 0,
16082
+ metadata: {
16083
+ "cursor_sdk.tool.status": toolCall?.status ?? "completed"
16084
+ },
16085
+ output: result
16086
+ });
16087
+ state.activeToolSpans.delete(callId);
16088
+ }
16089
+ async function handleStreamMessage2(state, message) {
16090
+ state.streamMessages.push(message);
16091
+ if (message.type === "system") {
16092
+ const systemMessage = message;
16093
+ state.metadata = {
16094
+ ...state.metadata,
16095
+ ...extractModelMetadata(systemMessage.model),
16096
+ ...systemMessage.agent_id ? { "cursor_sdk.agent_id": systemMessage.agent_id } : {},
16097
+ ...systemMessage.run_id ? { "cursor_sdk.run_id": systemMessage.run_id } : {},
16098
+ ...systemMessage.tools ? { "cursor_sdk.tools": systemMessage.tools } : {}
16099
+ };
16100
+ return;
16101
+ }
16102
+ if (message.type === "assistant") {
16103
+ const assistantMessage = message;
16104
+ for (const block of assistantMessage.message?.content ?? []) {
16105
+ if (block?.type === "text" && typeof block.text === "string") {
16106
+ state.streamText.push(block.text);
16107
+ } else if (block?.type === "tool_use" && block.id) {
16108
+ state.activeToolSpans.set(
16109
+ block.id,
16110
+ await startToolSpan(state, {
16111
+ args: block.input,
16112
+ callId: block.id,
16113
+ name: block.name,
16114
+ status: "running"
16115
+ })
16116
+ );
16117
+ }
16118
+ }
16119
+ return;
16120
+ }
16121
+ if (message.type === "tool_call") {
16122
+ await handleToolMessage(
16123
+ state,
16124
+ message
16125
+ );
16126
+ return;
16127
+ }
16128
+ if (message.type === "task" && typeof message.text === "string") {
16129
+ state.taskText.push(message.text);
16130
+ return;
16131
+ }
16132
+ if (message.type === "status" && message.status) {
16133
+ state.metadata["cursor_sdk.status"] = message.status;
16134
+ }
16135
+ }
16136
+ async function handleToolMessage(state, message) {
16137
+ const callId = message.call_id;
16138
+ if (!callId) {
16139
+ return;
16140
+ }
16141
+ if (message.status === "running") {
16142
+ if (!state.activeToolSpans.has(callId)) {
16143
+ state.activeToolSpans.set(
16144
+ callId,
16145
+ await startToolSpan(state, {
16146
+ args: message.args,
16147
+ callId,
16148
+ name: message.name,
16149
+ status: message.status,
16150
+ truncated: message.truncated
16151
+ })
16152
+ );
16153
+ }
16154
+ return;
16155
+ }
16156
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
16157
+ args: message.args,
16158
+ callId,
16159
+ name: message.name,
16160
+ status: message.status,
16161
+ truncated: message.truncated
16162
+ });
16163
+ finishToolSpan(toolState, {
16164
+ error: message.status === "error" ? stringifyUnknown(message.result) : void 0,
16165
+ metadata: {
16166
+ "cursor_sdk.tool.status": message.status
16167
+ },
16168
+ output: message.result
16169
+ });
16170
+ state.activeToolSpans.delete(callId);
16171
+ }
16172
+ async function handleConversation(state, turns) {
16173
+ state.conversationOutput = turns;
16174
+ for (const turn of turns) {
16175
+ if (turn.type === "agentConversationTurn") {
16176
+ for (const step of turn.turn?.steps ?? []) {
16177
+ await handleConversationStep(state, step);
16178
+ }
16179
+ } else if (turn.type === "shellConversationTurn") {
16180
+ const command = turn.turn?.shellCommand?.command;
16181
+ if (command) {
16182
+ const callId = `shell:${state.activeToolSpans.size}:${command}`;
16183
+ const toolState = await startToolSpan(state, {
16184
+ args: turn.turn?.shellCommand,
16185
+ callId,
16186
+ name: "shell",
16187
+ status: "completed"
16188
+ });
16189
+ finishToolSpan(toolState, {
16190
+ metadata: { "cursor_sdk.tool.status": "completed" },
16191
+ output: turn.turn?.shellOutput
16192
+ });
16193
+ }
16194
+ }
16195
+ }
16196
+ }
16197
+ async function handleConversationStep(state, step) {
16198
+ if (step.type === "assistantMessage" && typeof step.message?.text === "string") {
16199
+ state.conversationText.push(step.message.text);
16200
+ return;
16201
+ }
16202
+ if (step.type !== "toolCall") {
16203
+ return;
16204
+ }
16205
+ const toolCall = step.message;
16206
+ const callId = typeof toolCall?.callId === "string" ? toolCall.callId : `conversation-tool:${state.activeToolSpans.size}`;
16207
+ const toolState = await startToolSpan(state, {
16208
+ args: extractToolArgs(toolCall),
16209
+ callId,
16210
+ name: extractToolName(toolCall),
16211
+ status: toolCall?.status,
16212
+ toolCall
16213
+ });
16214
+ finishToolSpan(toolState, {
16215
+ error: toolCall?.status === "error" ? stringifyUnknown(toolCall.result) : void 0,
16216
+ metadata: {
16217
+ "cursor_sdk.tool.status": toolCall?.status ?? "completed"
16218
+ },
16219
+ output: extractToolResult(toolCall)
16220
+ });
16221
+ }
16222
+ function handleStepUpdate(state, step) {
16223
+ state.metrics["cursor_sdk.steps"] = (state.metrics["cursor_sdk.steps"] ?? 0) + 1;
16224
+ if (step.type) {
16225
+ const stepTypes = state.metadata["cursor_sdk.step_types"];
16226
+ if (Array.isArray(stepTypes)) {
16227
+ if (!stepTypes.includes(step.type)) {
16228
+ stepTypes.push(step.type);
16229
+ }
16230
+ } else {
16231
+ state.metadata["cursor_sdk.step_types"] = [step.type];
16232
+ }
16233
+ }
16234
+ if (step.type === "assistantMessage" && typeof step.message?.text === "string") {
16235
+ state.stepText.push(step.message.text);
16236
+ }
16237
+ }
16238
+ async function startToolSpan(state, args) {
16239
+ const name = args.name || "unknown";
16240
+ const metadata = {
16241
+ "cursor_sdk.tool.status": args.status,
16242
+ "gen_ai.tool.call.id": args.callId,
16243
+ "gen_ai.tool.name": name
16244
+ };
16245
+ if (args.truncated?.args !== void 0) {
16246
+ metadata["cursor_sdk.tool.args_truncated"] = args.truncated.args;
16247
+ }
16248
+ if (args.truncated?.result !== void 0) {
16249
+ metadata["cursor_sdk.tool.result_truncated"] = args.truncated.result;
16250
+ }
16251
+ const span = startSpan({
16252
+ event: {
16253
+ input: args.args,
16254
+ metadata
16255
+ },
16256
+ name: `tool: ${name}`,
16257
+ parent: await state.span.export(),
16258
+ spanAttributes: { type: "tool" /* TOOL */ }
16259
+ });
16260
+ let subAgentSpan;
16261
+ if (isSubAgentToolName(name)) {
16262
+ subAgentSpan = startSpan({
16263
+ event: {
16264
+ input: args.args,
16265
+ metadata: {
16266
+ "cursor_sdk.subagent.tool_call_id": args.callId,
16267
+ "gen_ai.tool.name": name
16268
+ }
16269
+ },
16270
+ name: formatSubAgentSpanName2(args.toolCall, args.args),
16271
+ parent: await span.export(),
16272
+ spanAttributes: { type: "task" /* TASK */ }
16273
+ });
16274
+ }
16275
+ return { span, subAgentSpan };
16276
+ }
16277
+ function finishToolSpan(toolState, result) {
16278
+ try {
16279
+ if (result.error) {
16280
+ safeLog(toolState.span, {
16281
+ error: result.error,
16282
+ metadata: result.metadata,
16283
+ output: result.output
16284
+ });
16285
+ if (toolState.subAgentSpan) {
16286
+ safeLog(toolState.subAgentSpan, {
16287
+ error: result.error,
16288
+ metadata: result.metadata,
16289
+ output: result.output
16290
+ });
16291
+ }
16292
+ } else {
16293
+ safeLog(toolState.span, {
16294
+ metadata: result.metadata,
16295
+ output: result.output
16296
+ });
16297
+ if (toolState.subAgentSpan) {
16298
+ safeLog(toolState.subAgentSpan, {
16299
+ metadata: result.metadata,
16300
+ output: result.output
16301
+ });
16302
+ }
16303
+ }
16304
+ } finally {
16305
+ toolState.subAgentSpan?.end();
16306
+ toolState.span.end();
16307
+ }
16308
+ }
16309
+ async function finalizeCursorRun(state, params = {}) {
16310
+ if (state.finalized) {
16311
+ return;
16312
+ }
16313
+ state.finalized = true;
16314
+ const error = params.error;
16315
+ const result = params.result ?? state.lastResult;
16316
+ const output = params.output ?? result?.result ?? state.run?.result ?? (state.conversationText.length > 0 ? state.conversationText.join("\n") : void 0) ?? state.conversationOutput ?? (state.streamText.length > 0 ? state.streamText.join("") : void 0) ?? (state.deltaText.length > 0 ? state.deltaText.join("") : void 0) ?? (state.stepText.length > 0 ? state.stepText.join("\n") : void 0) ?? (state.taskText.length > 0 ? state.taskText.join("\n") : void 0);
16317
+ try {
16318
+ const metadata = {
16319
+ ...state.metadata,
16320
+ ...state.run ? extractRunMetadata(state.run) : {},
16321
+ ...result ? extractRunResultMetadata(result) : {}
16322
+ };
16323
+ if (error) {
16324
+ safeLog(state.span, {
16325
+ error: error instanceof Error ? error.message : String(error),
16326
+ metadata,
16327
+ metrics: {
16328
+ ...cleanMetrics(state.metrics),
16329
+ ...buildDurationMetrics(state.startTime)
16330
+ },
16331
+ output
16332
+ });
16333
+ } else {
16334
+ safeLog(state.span, {
16335
+ metadata,
16336
+ metrics: {
16337
+ ...cleanMetrics(state.metrics),
16338
+ ...buildDurationMetrics(state.startTime)
16339
+ },
16340
+ output
16341
+ });
16342
+ }
16343
+ } finally {
16344
+ endOpenToolSpans(state);
16345
+ state.span.end();
16346
+ }
16347
+ }
16348
+ function endOpenToolSpans(state, error) {
16349
+ for (const [, toolState] of state.activeToolSpans) {
16350
+ finishToolSpan(toolState, { error });
16351
+ }
16352
+ state.activeToolSpans.clear();
16353
+ }
16354
+ function sanitizeUserMessage(message) {
16355
+ if (typeof message === "string" || message === void 0) {
16356
+ return message;
16357
+ }
16358
+ return {
16359
+ ...message,
16360
+ images: message.images?.map((image) => {
16361
+ const imageRecord = image;
16362
+ return {
16363
+ ...typeof imageRecord.url === "string" ? { url: imageRecord.url } : {},
16364
+ ...typeof imageRecord.mimeType === "string" ? { mimeType: imageRecord.mimeType } : {},
16365
+ ...image.dimension ? { dimension: image.dimension } : {},
16366
+ hasData: typeof imageRecord.data === "string"
16367
+ };
16368
+ })
16369
+ };
16370
+ }
16371
+ function extractAgentOptionsMetadata(options) {
16372
+ if (!options) {
16373
+ return {};
16374
+ }
16375
+ return {
16376
+ ...extractModelMetadata(options.model),
16377
+ ...options.agentId ? { "cursor_sdk.agent_id": options.agentId } : {},
16378
+ ...options.name ? { "cursor_sdk.agent_name": options.name } : {},
16379
+ ...options.local ? {
16380
+ "cursor_sdk.runtime": "local",
16381
+ "cursor_sdk.local.cwd": Array.isArray(options.local.cwd) ? options.local.cwd.join(",") : options.local.cwd
16382
+ } : {},
16383
+ ...options.cloud ? {
16384
+ "cursor_sdk.runtime": "cloud",
16385
+ "cursor_sdk.cloud.auto_create_pr": options.cloud.autoCreatePR,
16386
+ "cursor_sdk.cloud.env_type": options.cloud.env?.type,
16387
+ "cursor_sdk.cloud.env_name": options.cloud.env?.name,
16388
+ "cursor_sdk.cloud.repos": options.cloud.repos?.map((repo) => repo.url).filter((url) => typeof url === "string")
16389
+ } : {}
16390
+ };
16391
+ }
16392
+ function extractSendMetadata(options) {
16393
+ if (!options) {
16394
+ return {};
16395
+ }
16396
+ return {
16397
+ ...extractModelMetadata(options.model),
16398
+ ...options.local?.force !== void 0 ? { "cursor_sdk.local.force": options.local.force } : {}
16399
+ };
16400
+ }
16401
+ function extractAgentMetadata(agent) {
16402
+ return {
16403
+ ...agent.agentId ? { "cursor_sdk.agent_id": agent.agentId } : {},
16404
+ ...extractModelMetadata(agent.model)
16405
+ };
16406
+ }
16407
+ function extractRunMetadata(run) {
16408
+ if (!run) {
16409
+ return {};
16410
+ }
16411
+ return {
16412
+ ...run.id ? { "cursor_sdk.run_id": run.id } : {},
16413
+ ...run.agentId ? { "cursor_sdk.agent_id": run.agentId } : {},
16414
+ ...run.status ? { "cursor_sdk.status": run.status } : {},
16415
+ ...run.durationMs !== void 0 ? { "cursor_sdk.duration_ms": run.durationMs } : {},
16416
+ ...extractModelMetadata(run.model),
16417
+ ...extractGitMetadata(run.git)
16418
+ };
16419
+ }
16420
+ function extractRunResultMetadata(result) {
16421
+ if (!result) {
16422
+ return {};
16423
+ }
16424
+ return {
16425
+ ...result.id ? { "cursor_sdk.run_id": result.id } : {},
16426
+ ...result.status ? { "cursor_sdk.status": result.status } : {},
16427
+ ...result.durationMs !== void 0 ? { "cursor_sdk.duration_ms": result.durationMs } : {},
16428
+ ...extractModelMetadata(result.model),
16429
+ ...extractGitMetadata(result.git)
16430
+ };
16431
+ }
16432
+ function extractGitMetadata(git) {
16433
+ const branches = git?.branches;
16434
+ if (!branches || branches.length === 0) {
16435
+ return {};
16436
+ }
16437
+ return {
16438
+ "cursor_sdk.git.branches": branches.map((branch) => ({
16439
+ branch: branch.branch,
16440
+ prUrl: branch.prUrl,
16441
+ repoUrl: branch.repoUrl
16442
+ }))
16443
+ };
16444
+ }
16445
+ function extractModelMetadata(model) {
16446
+ if (!model?.id) {
16447
+ return {};
16448
+ }
16449
+ return {
16450
+ model: model.id,
16451
+ "cursor_sdk.model": model.id,
16452
+ ...model.params ? { "cursor_sdk.model.params": model.params } : {}
16453
+ };
16454
+ }
16455
+ function addUsageMetrics(metrics, usage) {
16456
+ if (!usage) {
16457
+ return;
16458
+ }
16459
+ if (usage.inputTokens !== void 0) {
16460
+ metrics.prompt_tokens = (metrics.prompt_tokens ?? 0) + usage.inputTokens;
16461
+ }
16462
+ if (usage.outputTokens !== void 0) {
16463
+ metrics.completion_tokens = (metrics.completion_tokens ?? 0) + usage.outputTokens;
16464
+ }
16465
+ if (usage.cacheReadTokens !== void 0) {
16466
+ metrics.prompt_cached_tokens = (metrics.prompt_cached_tokens ?? 0) + usage.cacheReadTokens;
16467
+ }
16468
+ if (usage.cacheWriteTokens !== void 0) {
16469
+ metrics.prompt_cache_creation_tokens = (metrics.prompt_cache_creation_tokens ?? 0) + usage.cacheWriteTokens;
16470
+ }
16471
+ metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0) + (metrics.prompt_cached_tokens ?? 0) + (metrics.prompt_cache_creation_tokens ?? 0);
16472
+ }
16473
+ function buildDurationMetrics(startTime) {
16474
+ const end = getCurrentUnixTimestamp();
16475
+ return {
16476
+ duration: end - startTime,
16477
+ end,
16478
+ start: startTime
16479
+ };
16480
+ }
16481
+ function extractToolName(toolCall) {
16482
+ if (!toolCall) {
16483
+ return "unknown";
16484
+ }
16485
+ if (typeof toolCall.name === "string") {
16486
+ return toolCall.name;
16487
+ }
16488
+ if (typeof toolCall.type === "string") {
16489
+ return toolCall.type;
16490
+ }
16491
+ return "unknown";
16492
+ }
16493
+ function extractToolArgs(toolCall) {
16494
+ return toolCall && "args" in toolCall ? toolCall.args : void 0;
16495
+ }
16496
+ function extractToolResult(toolCall) {
16497
+ return toolCall && "result" in toolCall ? toolCall.result : void 0;
16498
+ }
16499
+ function isSubAgentToolName(name) {
16500
+ return name === "Agent" || name === "Task" || name === "task";
16501
+ }
16502
+ function formatSubAgentSpanName2(toolCall, args) {
16503
+ const details = toolCall ?? args;
16504
+ const description = getString(details, "description") ?? getString(details, "subagent_type") ?? getString(details, "type") ?? getString(details, "name");
16505
+ return description ? `Agent: ${description}` : "Agent: sub-agent";
16506
+ }
16507
+ function getString(obj, key) {
16508
+ const value = obj?.[key];
16509
+ return typeof value === "string" ? value : void 0;
16510
+ }
16511
+ function stringifyUnknown(value) {
16512
+ if (value instanceof Error) {
16513
+ return value.message;
16514
+ }
16515
+ if (typeof value === "string") {
16516
+ return value;
16517
+ }
16518
+ try {
16519
+ return JSON.stringify(value);
16520
+ } catch {
16521
+ return String(value);
16522
+ }
16523
+ }
16524
+ function safeLog(span, event) {
16525
+ try {
16526
+ span.log(event);
16527
+ } catch (error) {
16528
+ logInstrumentationError("Cursor SDK span log", error);
16529
+ }
16530
+ }
16531
+ function logInstrumentationError(context, error) {
16532
+ debugLogger.error(`Error processing ${context}:`, error);
16533
+ }
16534
+ function cleanMetrics(metrics) {
16535
+ const cleaned = {};
16536
+ for (const [key, value] of Object.entries(metrics)) {
16537
+ if (value !== void 0 && Number.isFinite(value)) {
16538
+ cleaned[key] = value;
16539
+ }
16540
+ }
16541
+ return cleaned;
16542
+ }
16543
+
16544
+ // src/instrumentation/plugins/google-genai-channels.ts
16545
+ var googleGenAIChannels = defineChannels("@google/genai", {
16546
+ generateContent: channel({
16547
+ channelName: "models.generateContent",
16548
+ kind: "async"
16549
+ }),
16550
+ generateContentStream: channel({
16551
+ channelName: "models.generateContentStream",
16552
+ kind: "async"
16553
+ }),
16554
+ embedContent: channel({
16555
+ channelName: "models.embedContent",
16556
+ kind: "async"
16557
+ })
16558
+ });
16559
+
16560
+ // src/instrumentation/plugins/google-genai-plugin.ts
16561
+ var GOOGLE_GENAI_INTERNAL_CONTEXT = {
16562
+ caller_filename: "<node-internal>",
16563
+ caller_functionname: "<node-internal>",
16564
+ caller_lineno: 0
16565
+ };
16566
+ function createWrapperParityEvent(args) {
16567
+ return {
16568
+ context: GOOGLE_GENAI_INTERNAL_CONTEXT,
16569
+ input: args.input,
16570
+ metadata: args.metadata
16571
+ };
16572
+ }
16573
+ var GoogleGenAIPlugin = class extends BasePlugin {
16574
+ onEnable() {
16575
+ this.subscribeToGoogleGenAIChannels();
16576
+ }
16577
+ onDisable() {
16578
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
16579
+ }
16580
+ subscribeToGoogleGenAIChannels() {
16581
+ this.subscribeToGenerateContentChannel();
16582
+ this.subscribeToGenerateContentStreamChannel();
16583
+ this.subscribeToEmbedContentChannel();
16584
+ }
16585
+ subscribeToGenerateContentChannel() {
16586
+ const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
16587
+ const states = /* @__PURE__ */ new WeakMap();
16588
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
16589
+ tracingChannel2,
16590
+ states,
16591
+ (event) => {
16592
+ const params = event.arguments[0];
16593
+ const input = serializeGenerateContentInput(params);
16594
+ const metadata = extractGenerateContentMetadata(params);
16595
+ const span = startSpan({
16596
+ name: "generate_content",
16597
+ spanAttributes: {
16598
+ type: "llm" /* LLM */
16599
+ },
15318
16600
  event: createWrapperParityEvent({ input, metadata })
15319
16601
  });
15320
16602
  return {
@@ -15351,7 +16633,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
15351
16633
  const responseMetadata = extractResponseMetadata(event.result);
15352
16634
  spanState.span.log({
15353
16635
  ...responseMetadata ? { metadata: responseMetadata } : {},
15354
- metrics: cleanMetrics(
16636
+ metrics: cleanMetrics2(
15355
16637
  extractGenerateContentMetrics(
15356
16638
  event.result,
15357
16639
  spanState.startTime
@@ -15452,7 +16734,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
15452
16734
  const output = summarizeEmbedContentOutput(event.result);
15453
16735
  spanState.span.log({
15454
16736
  ...output ? { output } : {},
15455
- metrics: cleanMetrics(
16737
+ metrics: cleanMetrics2(
15456
16738
  extractEmbedContentMetrics(event.result, spanState.startTime)
15457
16739
  )
15458
16740
  });
@@ -15549,7 +16831,7 @@ function patchGoogleGenAIStreamingResult(args) {
15549
16831
  );
15550
16832
  span.log({
15551
16833
  ...responseMetadata ? { metadata: responseMetadata } : {},
15552
- metrics: cleanMetrics(metricsWithoutEnd),
16834
+ metrics: cleanMetrics2(metricsWithoutEnd),
15553
16835
  output: options.result.aggregated
15554
16836
  });
15555
16837
  span.end(typeof end === "number" ? { endTime: end } : void 0);
@@ -15974,7 +17256,7 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
15974
17256
  }
15975
17257
  return { aggregated, metrics };
15976
17258
  }
15977
- function cleanMetrics(metrics) {
17259
+ function cleanMetrics2(metrics) {
15978
17260
  const cleaned = {};
15979
17261
  for (const [key, value] of Object.entries(metrics)) {
15980
17262
  if (value !== null && value !== void 0) {
@@ -16058,6 +17340,8 @@ var REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
16058
17340
  "stop",
16059
17341
  "stream",
16060
17342
  "temperature",
17343
+ "tool_choice",
17344
+ "tools",
16061
17345
  "top_p"
16062
17346
  ]);
16063
17347
  var RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
@@ -16320,7 +17604,10 @@ function aggregateChatCompletionChunks2(chunks) {
16320
17604
  for (const chunk of chunks) {
16321
17605
  for (const choice of chunk.choices ?? []) {
16322
17606
  const index = typeof choice.index === "number" ? choice.index : 0;
16323
- const existing = aggregatedChoices.get(index) ?? { content: "" };
17607
+ const existing = aggregatedChoices.get(index) ?? {
17608
+ content: "",
17609
+ toolCallsByIndex: /* @__PURE__ */ new Map()
17610
+ };
16324
17611
  const delta = isObject(choice.delta) ? choice.delta : void 0;
16325
17612
  const message = isObject(choice.message) ? choice.message : void 0;
16326
17613
  if (typeof delta?.content === "string") {
@@ -16336,6 +17623,10 @@ function aggregateChatCompletionChunks2(chunks) {
16336
17623
  if (choice.finish_reason !== void 0) {
16337
17624
  existing.finish_reason = choice.finish_reason;
16338
17625
  }
17626
+ const toolCallDeltas = getChatToolCallDeltas(delta) ?? getChatToolCallDeltas(message);
17627
+ if (toolCallDeltas) {
17628
+ mergeChatToolCallDeltas(existing.toolCallsByIndex, toolCallDeltas);
17629
+ }
16339
17630
  aggregatedChoices.set(index, existing);
16340
17631
  }
16341
17632
  }
@@ -16344,12 +17635,72 @@ function aggregateChatCompletionChunks2(chunks) {
16344
17635
  index,
16345
17636
  message: {
16346
17637
  content: choice.content,
16347
- role: choice.role ?? "assistant"
17638
+ role: choice.role ?? "assistant",
17639
+ ...choice.toolCallsByIndex.size > 0 ? {
17640
+ tool_calls: [...choice.toolCallsByIndex.entries()].sort(([leftIndex], [rightIndex]) => leftIndex - rightIndex).map(([, toolCall]) => toolCall)
17641
+ } : {}
16348
17642
  },
16349
17643
  ...choice.finish_reason !== void 0 ? { finish_reason: choice.finish_reason } : {}
16350
17644
  }))
16351
17645
  };
16352
17646
  }
17647
+ function getChatToolCallDeltas(value) {
17648
+ if (!Array.isArray(value?.tool_calls)) {
17649
+ return void 0;
17650
+ }
17651
+ const toolCalls = value.tool_calls.filter((toolCall) => isObject(toolCall));
17652
+ return toolCalls.length > 0 ? toolCalls : void 0;
17653
+ }
17654
+ function mergeChatToolCallDeltas(toolCallsByIndex, toolCallDeltas) {
17655
+ for (const toolDelta of toolCallDeltas) {
17656
+ const toolIndex = typeof toolDelta.index === "number" && toolDelta.index >= 0 ? toolDelta.index : 0;
17657
+ const existing = toolCallsByIndex.get(toolIndex);
17658
+ if (!existing) {
17659
+ toolCallsByIndex.set(toolIndex, createChatToolCall(toolDelta));
17660
+ continue;
17661
+ }
17662
+ mergeChatToolCall(existing, toolDelta);
17663
+ }
17664
+ }
17665
+ function createChatToolCall(toolDelta) {
17666
+ const toolFunction = isObject(toolDelta.function) ? toolDelta.function : {};
17667
+ const toolCallFunction = {
17668
+ arguments: typeof toolFunction.arguments === "string" ? toolFunction.arguments : ""
17669
+ };
17670
+ if (typeof toolFunction.name === "string") {
17671
+ toolCallFunction.name = toolFunction.name;
17672
+ }
17673
+ const toolCall = {
17674
+ function: toolCallFunction
17675
+ };
17676
+ if (typeof toolDelta.id === "string") {
17677
+ toolCall.id = toolDelta.id;
17678
+ }
17679
+ if (typeof toolDelta.type === "string") {
17680
+ toolCall.type = toolDelta.type;
17681
+ }
17682
+ return toolCall;
17683
+ }
17684
+ function mergeChatToolCall(existing, toolDelta) {
17685
+ const currentFunction = isObject(existing.function) ? existing.function : {};
17686
+ const deltaFunction = isObject(toolDelta.function) ? toolDelta.function : {};
17687
+ const currentArguments = typeof currentFunction.arguments === "string" ? currentFunction.arguments : "";
17688
+ const deltaArguments = typeof deltaFunction.arguments === "string" ? deltaFunction.arguments : "";
17689
+ if (typeof toolDelta.id === "string" && typeof existing.id !== "string") {
17690
+ existing.id = toolDelta.id;
17691
+ }
17692
+ if (typeof toolDelta.type === "string" && typeof existing.type !== "string") {
17693
+ existing.type = toolDelta.type;
17694
+ }
17695
+ const nextFunction = {
17696
+ ...currentFunction,
17697
+ arguments: `${currentArguments}${deltaArguments}`
17698
+ };
17699
+ if (typeof deltaFunction.name === "string" && typeof currentFunction.name !== "string") {
17700
+ nextFunction.name = deltaFunction.name;
17701
+ }
17702
+ existing.function = nextFunction;
17703
+ }
16353
17704
  function aggregateTextGenerationStreamChunks(chunks) {
16354
17705
  if (chunks.length === 0) {
16355
17706
  return void 0;
@@ -18394,6 +19745,8 @@ var MISTRAL_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
18394
19745
  "presence_penalty",
18395
19746
  "randomSeed",
18396
19747
  "random_seed",
19748
+ "reasoningEffort",
19749
+ "reasoning_effort",
18397
19750
  "responseFormat",
18398
19751
  "response_format",
18399
19752
  "safePrompt",
@@ -18517,22 +19870,114 @@ function extractMistralStreamingMetrics(result, startTime) {
18517
19870
  if (startTime) {
18518
19871
  metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
18519
19872
  }
18520
- return metrics;
19873
+ return metrics;
19874
+ }
19875
+ function extractDeltaText(content) {
19876
+ if (typeof content === "string") {
19877
+ return content;
19878
+ }
19879
+ if (!Array.isArray(content)) {
19880
+ return void 0;
19881
+ }
19882
+ const textParts = content.map((part) => {
19883
+ if (!isObject(part) || part.type !== "text") {
19884
+ return "";
19885
+ }
19886
+ return typeof part.text === "string" ? part.text : "";
19887
+ }).filter((part) => part.length > 0);
19888
+ return textParts.length > 0 ? textParts.join("") : void 0;
19889
+ }
19890
+ function normalizeMistralTextContentPart(part) {
19891
+ if (!isObject(part) || part.type !== "text" || typeof part.text !== "string") {
19892
+ return void 0;
19893
+ }
19894
+ return {
19895
+ type: "text",
19896
+ text: part.text
19897
+ };
19898
+ }
19899
+ function normalizeMistralThinkingContentPart(part) {
19900
+ if (!isObject(part) || part.type !== "thinking") {
19901
+ return void 0;
19902
+ }
19903
+ const thinking = Array.isArray(part.thinking) ? part.thinking.map((thinkingPart) => normalizeMistralTextContentPart(thinkingPart)).filter(
19904
+ (thinkingPart) => thinkingPart !== void 0 && typeof thinkingPart.text === "string"
19905
+ ) : [];
19906
+ return {
19907
+ type: "thinking",
19908
+ thinking
19909
+ };
19910
+ }
19911
+ function normalizeMistralContentParts(content) {
19912
+ if (!Array.isArray(content)) {
19913
+ return [];
19914
+ }
19915
+ return content.map((part) => {
19916
+ return normalizeMistralTextContentPart(part) || normalizeMistralThinkingContentPart(part);
19917
+ }).filter((part) => part !== void 0);
19918
+ }
19919
+ function mergeMistralTextSegments(left, right) {
19920
+ const merged = left.map((part) => ({ ...part }));
19921
+ for (const part of right) {
19922
+ const lastPart = merged[merged.length - 1];
19923
+ if (lastPart && lastPart.type === "text" && typeof lastPart.text === "string" && typeof part.text === "string") {
19924
+ lastPart.text += part.text;
19925
+ continue;
19926
+ }
19927
+ merged.push({ ...part });
19928
+ }
19929
+ return merged;
19930
+ }
19931
+ function mergeMistralContentParts(left, right) {
19932
+ const merged = [...(left || []).map((part) => structuredClone(part))];
19933
+ for (const part of right) {
19934
+ const lastPart = merged[merged.length - 1];
19935
+ if (part.type === "text" && lastPart?.type === "text" && typeof lastPart.text === "string" && typeof part.text === "string") {
19936
+ lastPart.text += part.text;
19937
+ continue;
19938
+ }
19939
+ if (part.type === "thinking" && lastPart?.type === "thinking" && Array.isArray(lastPart.thinking) && Array.isArray(part.thinking)) {
19940
+ lastPart.thinking = mergeMistralTextSegments(
19941
+ lastPart.thinking,
19942
+ part.thinking
19943
+ );
19944
+ continue;
19945
+ }
19946
+ merged.push(structuredClone(part));
19947
+ }
19948
+ return merged;
18521
19949
  }
18522
- function extractDeltaText(content) {
19950
+ function appendMistralContent(accumulator, content) {
18523
19951
  if (typeof content === "string") {
18524
- return content;
19952
+ if (accumulator.contentParts) {
19953
+ accumulator.contentParts = mergeMistralContentParts(
19954
+ accumulator.contentParts,
19955
+ [{ type: "text", text: content }]
19956
+ );
19957
+ return;
19958
+ }
19959
+ accumulator.content = `${accumulator.content || ""}${content}`;
19960
+ return;
18525
19961
  }
18526
- if (!Array.isArray(content)) {
18527
- return void 0;
19962
+ const normalizedContentParts = normalizeMistralContentParts(content);
19963
+ if (normalizedContentParts.length === 0) {
19964
+ return;
18528
19965
  }
18529
- const textParts = content.map((part) => {
18530
- if (!isObject(part) || part.type !== "text") {
18531
- return "";
19966
+ const hasStructuredContent = normalizedContentParts.some(
19967
+ (part) => part.type !== "text"
19968
+ );
19969
+ if (!accumulator.contentParts && !hasStructuredContent) {
19970
+ const text = extractDeltaText(content);
19971
+ if (text) {
19972
+ accumulator.content = `${accumulator.content || ""}${text}`;
18532
19973
  }
18533
- return typeof part.text === "string" ? part.text : "";
18534
- }).filter((part) => part.length > 0);
18535
- return textParts.length > 0 ? textParts.join("") : void 0;
19974
+ return;
19975
+ }
19976
+ accumulator.contentParts = mergeMistralContentParts(
19977
+ accumulator.contentParts || (accumulator.content ? [{ type: "text", text: accumulator.content }] : []),
19978
+ normalizedContentParts
19979
+ );
19980
+ delete accumulator.content;
18536
19981
  }
18537
19982
  function getDeltaToolCalls(delta) {
18538
19983
  const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
@@ -18702,10 +20147,7 @@ function aggregateMistralStreamChunks(chunks) {
18702
20147
  if (!accumulator.role && typeof delta.role === "string") {
18703
20148
  accumulator.role = delta.role;
18704
20149
  }
18705
- const deltaText = extractDeltaText(delta.content);
18706
- if (deltaText) {
18707
- accumulator.content = `${accumulator.content || ""}${deltaText}`;
18708
- }
20150
+ appendMistralContent(accumulator, delta.content);
18709
20151
  accumulator.toolCalls = mergeToolCallDeltas(
18710
20152
  accumulator.toolCalls,
18711
20153
  getDeltaToolCalls(delta)
@@ -18723,7 +20165,7 @@ function aggregateMistralStreamChunks(chunks) {
18723
20165
  index: choice.index,
18724
20166
  message: {
18725
20167
  ...choice.role ? { role: choice.role } : {},
18726
- content: choice.content ?? null,
20168
+ content: choice.contentParts ?? choice.content ?? null,
18727
20169
  ...choice.toolCalls ? { toolCalls: choice.toolCalls } : {}
18728
20170
  },
18729
20171
  ...choice.finishReason !== void 0 ? { finishReason: choice.finishReason } : {}
@@ -18962,7 +20404,7 @@ var GoogleADKPlugin = class extends BasePlugin {
18962
20404
  start: (event) => {
18963
20405
  const req = event.arguments[0] ?? {};
18964
20406
  const tool = event.self;
18965
- const toolName = extractToolName(req, tool);
20407
+ const toolName = extractToolName2(req, tool);
18966
20408
  const parentSpan = findToolParentSpan(
18967
20409
  req,
18968
20410
  this.activeAgentSpans,
@@ -19001,7 +20443,7 @@ var GoogleADKPlugin = class extends BasePlugin {
19001
20443
  metrics.duration = end - state.startTime;
19002
20444
  state.span.log({
19003
20445
  output: event.result,
19004
- metrics: cleanMetrics2(metrics)
20446
+ metrics: cleanMetrics3(metrics)
19005
20447
  });
19006
20448
  } finally {
19007
20449
  state.span.end();
@@ -19220,7 +20662,7 @@ function extractToolCallId(req) {
19220
20662
  const toolContext = req.toolContext;
19221
20663
  return toolContext?.functionCallId;
19222
20664
  }
19223
- function extractToolName(req, tool) {
20665
+ function extractToolName2(req, tool) {
19224
20666
  if (typeof tool?.name === "string" && tool.name.length > 0) {
19225
20667
  return tool.name;
19226
20668
  }
@@ -19268,7 +20710,7 @@ function finalizeRunnerSpan(state, activeRunnerSpans) {
19268
20710
  }
19269
20711
  state.span.log({
19270
20712
  output: lastEvent ? extractEventOutput(lastEvent) : void 0,
19271
- metrics: cleanMetrics2(metrics)
20713
+ metrics: cleanMetrics3(metrics)
19272
20714
  });
19273
20715
  } finally {
19274
20716
  cleanupActiveRunnerSpan(state, activeRunnerSpans);
@@ -19285,7 +20727,7 @@ function finalizeAgentSpan(state, activeAgentSpans) {
19285
20727
  metrics.duration = end - state.startTime;
19286
20728
  state.span.log({
19287
20729
  output: lastEvent ? extractEventOutput(lastEvent) : void 0,
19288
- metrics: cleanMetrics2(metrics)
20730
+ metrics: cleanMetrics3(metrics)
19289
20731
  });
19290
20732
  } finally {
19291
20733
  cleanupActiveAgentSpan(state, activeAgentSpans);
@@ -19371,7 +20813,7 @@ function populateUsageMetrics2(metrics, usage) {
19371
20813
  metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
19372
20814
  }
19373
20815
  }
19374
- function cleanMetrics2(metrics) {
20816
+ function cleanMetrics3(metrics) {
19375
20817
  const cleaned = {};
19376
20818
  for (const [key, value] of Object.entries(metrics)) {
19377
20819
  if (value !== null && value !== void 0) {
@@ -19499,6 +20941,11 @@ var CHAT_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
19499
20941
  "strictTools",
19500
20942
  "strict_tools",
19501
20943
  "temperature",
20944
+ "thinking",
20945
+ "thinkingTokenBudget",
20946
+ "thinkingType",
20947
+ "thinking_token_budget",
20948
+ "thinking_type",
19502
20949
  "toolChoice",
19503
20950
  "tool_choice"
19504
20951
  ]);
@@ -19719,6 +21166,11 @@ function mergeUsageMetrics(metrics, usage) {
19719
21166
  "tokens",
19720
21167
  tokenContainer.totalTokens ?? tokenContainer.total_tokens
19721
21168
  );
21169
+ setMetricIfNumber(
21170
+ metrics,
21171
+ "reasoning_tokens",
21172
+ tokenContainer.reasoningTokens ?? tokenContainer.reasoning_tokens ?? tokenContainer.thinkingTokens ?? tokenContainer.thinking_tokens
21173
+ );
19722
21174
  }
19723
21175
  const billedUnits = (isObject(source.billedUnits) ? source.billedUnits : void 0) || (isObject(source.billed_units) ? source.billed_units : void 0);
19724
21176
  if (billedUnits) {
@@ -19799,13 +21251,87 @@ function extractV8DeltaText(chunk) {
19799
21251
  }
19800
21252
  return void 0;
19801
21253
  }
21254
+ function getV8ContentIndex(chunk) {
21255
+ return typeof chunk.index === "number" ? chunk.index : 0;
21256
+ }
21257
+ function toContentBlockType(value) {
21258
+ return value === "text" || value === "thinking" ? value : void 0;
21259
+ }
21260
+ function getOrCreateContentBlock(contentBlocksByIndex, contentBlockOrder, index) {
21261
+ if (!contentBlockOrder.includes(index)) {
21262
+ contentBlockOrder.push(index);
21263
+ }
21264
+ if (!(index in contentBlocksByIndex)) {
21265
+ contentBlocksByIndex[index] = {
21266
+ text: "",
21267
+ thinking: ""
21268
+ };
21269
+ }
21270
+ return contentBlocksByIndex[index];
21271
+ }
21272
+ function appendV8ContentBlock(contentBlocksByIndex, contentBlockOrder, index, content) {
21273
+ if (typeof content === "string") {
21274
+ const block2 = getOrCreateContentBlock(
21275
+ contentBlocksByIndex,
21276
+ contentBlockOrder,
21277
+ index
21278
+ );
21279
+ block2.type ??= "text";
21280
+ block2.text += content;
21281
+ return;
21282
+ }
21283
+ if (!isObject(content)) {
21284
+ return;
21285
+ }
21286
+ const block = getOrCreateContentBlock(
21287
+ contentBlocksByIndex,
21288
+ contentBlockOrder,
21289
+ index
21290
+ );
21291
+ const contentType = toContentBlockType(content.type);
21292
+ if (contentType) {
21293
+ block.type = contentType;
21294
+ }
21295
+ if (typeof content.text === "string") {
21296
+ block.type ??= "text";
21297
+ block.text += content.text;
21298
+ }
21299
+ if (typeof content.thinking === "string") {
21300
+ block.type ??= "thinking";
21301
+ block.thinking += content.thinking;
21302
+ }
21303
+ }
21304
+ function serializeAggregatedContentBlocks(contentBlocksByIndex, contentBlockOrder) {
21305
+ return contentBlockOrder.sort((left, right) => left - right).flatMap((index) => {
21306
+ const block = contentBlocksByIndex[index];
21307
+ if (!block) {
21308
+ return [];
21309
+ }
21310
+ if (block.type === "thinking" && block.thinking.length > 0) {
21311
+ return [{ type: "thinking", thinking: block.thinking }];
21312
+ }
21313
+ if (block.text.length > 0) {
21314
+ return [{ type: "text", text: block.text }];
21315
+ }
21316
+ if (block.thinking.length > 0) {
21317
+ return [{ type: "thinking", thinking: block.thinking }];
21318
+ }
21319
+ return [];
21320
+ });
21321
+ }
21322
+ function hasThinkingContent(contentBlocks) {
21323
+ return contentBlocks.some((block) => block.type === "thinking");
21324
+ }
19802
21325
  function aggregateCohereChatStreamChunks(chunks) {
19803
21326
  const textDeltas = [];
21327
+ const contentBlocksByIndex = {};
21328
+ const contentBlockOrder = [];
19804
21329
  const toolCallsByIndex = {};
19805
21330
  const toolCallOrder = [];
19806
21331
  let terminalResponse;
19807
21332
  let role;
19808
21333
  let finishReason;
21334
+ let toolPlan = "";
19809
21335
  let metadata = {};
19810
21336
  let metrics = {};
19811
21337
  for (const chunk of chunks) {
@@ -19863,12 +21389,36 @@ function aggregateCohereChatStreamChunks(chunks) {
19863
21389
  continue;
19864
21390
  }
19865
21391
  if (eventType === "content-delta") {
21392
+ appendV8ContentBlock(
21393
+ contentBlocksByIndex,
21394
+ contentBlockOrder,
21395
+ getV8ContentIndex(chunk),
21396
+ isObject(chunk.delta) && isObject(chunk.delta.message) ? chunk.delta.message.content : void 0
21397
+ );
19866
21398
  const text = extractV8DeltaText(chunk);
19867
21399
  if (text) {
19868
21400
  textDeltas.push(text);
19869
21401
  }
19870
21402
  continue;
19871
21403
  }
21404
+ if (eventType === "content-start") {
21405
+ appendV8ContentBlock(
21406
+ contentBlocksByIndex,
21407
+ contentBlockOrder,
21408
+ getV8ContentIndex(chunk),
21409
+ isObject(chunk.delta) && isObject(chunk.delta.message) ? chunk.delta.message.content : void 0
21410
+ );
21411
+ continue;
21412
+ }
21413
+ if (eventType === "tool-plan-delta") {
21414
+ if (isObject(chunk.delta) && isObject(chunk.delta.message)) {
21415
+ const deltaToolPlan = typeof chunk.delta.message.toolPlan === "string" ? chunk.delta.message.toolPlan : typeof chunk.delta.message.tool_plan === "string" ? chunk.delta.message.tool_plan : void 0;
21416
+ if (deltaToolPlan) {
21417
+ toolPlan += deltaToolPlan;
21418
+ }
21419
+ }
21420
+ continue;
21421
+ }
19872
21422
  if (eventType === "tool-call-start") {
19873
21423
  const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
19874
21424
  Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
@@ -19922,13 +21472,26 @@ function aggregateCohereChatStreamChunks(chunks) {
19922
21472
  }
19923
21473
  }
19924
21474
  const mergedToolCalls = toolCallOrder.sort((left, right) => left - right).map((index) => toolCallsByIndex[index]).filter((toolCall) => isObject(toolCall));
21475
+ const aggregatedContentBlocks = serializeAggregatedContentBlocks(
21476
+ contentBlocksByIndex,
21477
+ contentBlockOrder
21478
+ );
19925
21479
  let output = extractCohereChatOutput(terminalResponse);
19926
21480
  if (output === void 0) {
19927
21481
  const mergedText = textDeltas.join("");
19928
- if (mergedToolCalls.length > 0 || role || mergedText.length > 0) {
21482
+ const shouldUseStructuredContent = hasThinkingContent(aggregatedContentBlocks) || toolPlan.length > 0;
21483
+ if (shouldUseStructuredContent) {
21484
+ output = {
21485
+ ...role ? { role } : {},
21486
+ ...aggregatedContentBlocks.length > 0 ? { content: aggregatedContentBlocks } : {},
21487
+ ...toolPlan.length > 0 ? { toolPlan } : {},
21488
+ ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
21489
+ };
21490
+ } else if (mergedToolCalls.length > 0 || role || mergedText.length > 0 || aggregatedContentBlocks.length > 0) {
21491
+ const textContent = mergedText.length > 0 ? mergedText : aggregatedContentBlocks[0]?.type === "text" ? aggregatedContentBlocks[0].text : void 0;
19929
21492
  output = {
19930
21493
  ...role ? { role } : {},
19931
- ...mergedText.length > 0 ? { content: mergedText } : {},
21494
+ ...textContent ? { content: textContent } : {},
19932
21495
  ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
19933
21496
  };
19934
21497
  }
@@ -19946,6 +21509,98 @@ function aggregateCohereChatStreamChunks(chunks) {
19946
21509
  };
19947
21510
  }
19948
21511
 
21512
+ // src/instrumentation/plugins/groq-channels.ts
21513
+ var groqChannels = defineChannels("groq-sdk", {
21514
+ chatCompletionsCreate: channel({
21515
+ channelName: "chat.completions.create",
21516
+ kind: "async"
21517
+ }),
21518
+ embeddingsCreate: channel(
21519
+ {
21520
+ channelName: "embeddings.create",
21521
+ kind: "async"
21522
+ }
21523
+ )
21524
+ });
21525
+
21526
+ // src/instrumentation/plugins/groq-plugin.ts
21527
+ var GroqPlugin = class extends BasePlugin {
21528
+ onEnable() {
21529
+ this.unsubscribers.push(
21530
+ traceStreamingChannel(groqChannels.chatCompletionsCreate, {
21531
+ name: "groq.chat.completions.create",
21532
+ type: "llm" /* LLM */,
21533
+ extractInput: ([params]) => {
21534
+ const { messages, ...metadata } = params;
21535
+ return {
21536
+ input: processInputAttachments(messages),
21537
+ metadata: { ...metadata, provider: "groq" }
21538
+ };
21539
+ },
21540
+ extractOutput: (result) => result?.choices,
21541
+ extractMetrics: (result, startTime) => {
21542
+ const metrics = parseGroqMetrics(result);
21543
+ if (startTime) {
21544
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
21545
+ }
21546
+ return metrics;
21547
+ },
21548
+ aggregateChunks: aggregateGroqChatCompletionChunks
21549
+ })
21550
+ );
21551
+ this.unsubscribers.push(
21552
+ traceAsyncChannel(groqChannels.embeddingsCreate, {
21553
+ name: "groq.embeddings.create",
21554
+ type: "llm" /* LLM */,
21555
+ extractInput: ([params]) => {
21556
+ const { input, ...metadata } = params;
21557
+ return {
21558
+ input,
21559
+ metadata: { ...metadata, provider: "groq" }
21560
+ };
21561
+ },
21562
+ extractOutput: (result) => {
21563
+ const embedding = result?.data?.[0]?.embedding;
21564
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
21565
+ },
21566
+ extractMetrics: (result) => parseGroqMetrics(result)
21567
+ })
21568
+ );
21569
+ }
21570
+ onDisable() {
21571
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
21572
+ }
21573
+ };
21574
+ function parseGroqMetrics(result) {
21575
+ const metrics = parseMetricsFromUsage(result?.usage);
21576
+ const xGroq = result?.x_groq;
21577
+ if (!xGroq || typeof xGroq !== "object") {
21578
+ return metrics;
21579
+ }
21580
+ const extraUsage = "usage" in xGroq ? xGroq.usage : void 0;
21581
+ if (!extraUsage || typeof extraUsage !== "object") {
21582
+ return metrics;
21583
+ }
21584
+ const dramCachedTokens = extraUsage["dram_cached_tokens"];
21585
+ const sramCachedTokens = extraUsage["sram_cached_tokens"];
21586
+ return {
21587
+ ...metrics,
21588
+ ...typeof dramCachedTokens === "number" ? { dram_cached_tokens: dramCachedTokens } : {},
21589
+ ...typeof sramCachedTokens === "number" ? { sram_cached_tokens: sramCachedTokens } : {}
21590
+ };
21591
+ }
21592
+ function aggregateGroqChatCompletionChunks(chunks, streamResult, endEvent) {
21593
+ const aggregated = aggregateChatCompletionChunks(
21594
+ chunks,
21595
+ streamResult,
21596
+ endEvent
21597
+ );
21598
+ return {
21599
+ metrics: aggregated.metrics,
21600
+ output: aggregated.output
21601
+ };
21602
+ }
21603
+
19949
21604
  // src/instrumentation/braintrust-plugin.ts
19950
21605
  var BraintrustPlugin = class extends BasePlugin {
19951
21606
  config;
@@ -19953,6 +21608,7 @@ var BraintrustPlugin = class extends BasePlugin {
19953
21608
  anthropicPlugin = null;
19954
21609
  aiSDKPlugin = null;
19955
21610
  claudeAgentSDKPlugin = null;
21611
+ cursorSDKPlugin = null;
19956
21612
  googleGenAIPlugin = null;
19957
21613
  huggingFacePlugin = null;
19958
21614
  openRouterPlugin = null;
@@ -19960,6 +21616,7 @@ var BraintrustPlugin = class extends BasePlugin {
19960
21616
  mistralPlugin = null;
19961
21617
  googleADKPlugin = null;
19962
21618
  coherePlugin = null;
21619
+ groqPlugin = null;
19963
21620
  constructor(config = {}) {
19964
21621
  super();
19965
21622
  this.config = config;
@@ -19982,6 +21639,10 @@ var BraintrustPlugin = class extends BasePlugin {
19982
21639
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
19983
21640
  this.claudeAgentSDKPlugin.enable();
19984
21641
  }
21642
+ if (integrations.cursorSDK !== false && integrations.cursor !== false) {
21643
+ this.cursorSDKPlugin = new CursorSDKPlugin();
21644
+ this.cursorSDKPlugin.enable();
21645
+ }
19985
21646
  if (integrations.googleGenAI !== false && integrations.google !== false) {
19986
21647
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
19987
21648
  this.googleGenAIPlugin.enable();
@@ -20010,6 +21671,10 @@ var BraintrustPlugin = class extends BasePlugin {
20010
21671
  this.coherePlugin = new CoherePlugin();
20011
21672
  this.coherePlugin.enable();
20012
21673
  }
21674
+ if (integrations.groq !== false) {
21675
+ this.groqPlugin = new GroqPlugin();
21676
+ this.groqPlugin.enable();
21677
+ }
20013
21678
  }
20014
21679
  onDisable() {
20015
21680
  if (this.openaiPlugin) {
@@ -20028,6 +21693,10 @@ var BraintrustPlugin = class extends BasePlugin {
20028
21693
  this.claudeAgentSDKPlugin.disable();
20029
21694
  this.claudeAgentSDKPlugin = null;
20030
21695
  }
21696
+ if (this.cursorSDKPlugin) {
21697
+ this.cursorSDKPlugin.disable();
21698
+ this.cursorSDKPlugin = null;
21699
+ }
20031
21700
  if (this.googleGenAIPlugin) {
20032
21701
  this.googleGenAIPlugin.disable();
20033
21702
  this.googleGenAIPlugin = null;
@@ -20056,6 +21725,10 @@ var BraintrustPlugin = class extends BasePlugin {
20056
21725
  this.coherePlugin.disable();
20057
21726
  this.coherePlugin = null;
20058
21727
  }
21728
+ if (this.groqPlugin) {
21729
+ this.groqPlugin.disable();
21730
+ this.groqPlugin = null;
21731
+ }
20059
21732
  }
20060
21733
  };
20061
21734
 
@@ -20129,6 +21802,8 @@ var PluginRegistry = class {
20129
21802
  google: true,
20130
21803
  huggingface: true,
20131
21804
  claudeAgentSDK: true,
21805
+ cursor: true,
21806
+ cursorSDK: true,
20132
21807
  openrouter: true,
20133
21808
  openrouterAgent: true,
20134
21809
  mistral: true,
@@ -20145,7 +21820,11 @@ var PluginRegistry = class {
20145
21820
  if (disabledList) {
20146
21821
  const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
20147
21822
  for (const sdk of disabled) {
20148
- integrations[sdk] = false;
21823
+ if (sdk === "cursor-sdk") {
21824
+ integrations.cursorSDK = false;
21825
+ } else {
21826
+ integrations[sdk] = false;
21827
+ }
20149
21828
  }
20150
21829
  }
20151
21830
  return { integrations };
@@ -20324,8 +22003,10 @@ __export(exports_exports, {
20324
22003
  wrapAnthropic: () => wrapAnthropic,
20325
22004
  wrapClaudeAgentSDK: () => wrapClaudeAgentSDK,
20326
22005
  wrapCohere: () => wrapCohere,
22006
+ wrapCursorSDK: () => wrapCursorSDK,
20327
22007
  wrapGoogleADK: () => wrapGoogleADK,
20328
22008
  wrapGoogleGenAI: () => wrapGoogleGenAI,
22009
+ wrapGroq: () => wrapGroq,
20329
22010
  wrapHuggingFace: () => wrapHuggingFace,
20330
22011
  wrapMastraAgent: () => wrapMastraAgent,
20331
22012
  wrapMistral: () => wrapMistral,
@@ -21940,6 +23621,130 @@ function claudeAgentSDKProxy(sdk) {
21940
23621
  });
21941
23622
  }
21942
23623
 
23624
+ // src/wrappers/cursor-sdk.ts
23625
+ var WRAPPED_AGENT2 = Symbol.for("braintrust.cursor-sdk.wrapped-agent");
23626
+ function wrapCursorSDK(sdk) {
23627
+ if (!sdk || typeof sdk !== "object") {
23628
+ return sdk;
23629
+ }
23630
+ const maybeSDK = sdk;
23631
+ if (!maybeSDK.Agent || typeof maybeSDK.Agent !== "function") {
23632
+ console.warn("Unsupported Cursor SDK. Not wrapping.");
23633
+ return sdk;
23634
+ }
23635
+ const target = isModuleNamespace2(sdk) ? Object.setPrototypeOf({}, sdk) : sdk;
23636
+ return new Proxy(target, {
23637
+ get(target2, prop, receiver) {
23638
+ const value = Reflect.get(target2, prop, receiver);
23639
+ if (prop === "Agent" && typeof value === "function") {
23640
+ return wrapCursorAgentClass(value);
23641
+ }
23642
+ if (typeof value === "function") {
23643
+ return value.bind(target2);
23644
+ }
23645
+ return value;
23646
+ }
23647
+ });
23648
+ }
23649
+ function isModuleNamespace2(obj) {
23650
+ if (!obj || typeof obj !== "object") {
23651
+ return false;
23652
+ }
23653
+ if (obj.constructor?.name === "Module") {
23654
+ return true;
23655
+ }
23656
+ const keys = Object.keys(obj);
23657
+ if (keys.length === 0) {
23658
+ return false;
23659
+ }
23660
+ const descriptor = Object.getOwnPropertyDescriptor(obj, keys[0]);
23661
+ return descriptor ? !descriptor.configurable && !descriptor.writable : false;
23662
+ }
23663
+ function wrapCursorAgentClass(Agent) {
23664
+ const cache = /* @__PURE__ */ new Map();
23665
+ return new Proxy(Agent, {
23666
+ get(target, prop, receiver) {
23667
+ if (cache.has(prop)) {
23668
+ return cache.get(prop);
23669
+ }
23670
+ const value = Reflect.get(target, prop, receiver);
23671
+ if (prop === "create" && typeof value === "function") {
23672
+ const wrapped = async function(options) {
23673
+ const args = [options];
23674
+ return cursorSDKChannels.create.tracePromise(
23675
+ async () => wrapCursorAgent(await Reflect.apply(value, target, args)),
23676
+ { arguments: args }
23677
+ );
23678
+ };
23679
+ cache.set(prop, wrapped);
23680
+ return wrapped;
23681
+ }
23682
+ if (prop === "resume" && typeof value === "function") {
23683
+ const wrapped = async function(agentId, options) {
23684
+ const args = [agentId, options];
23685
+ return cursorSDKChannels.resume.tracePromise(
23686
+ async () => wrapCursorAgent(await Reflect.apply(value, target, args)),
23687
+ { arguments: args }
23688
+ );
23689
+ };
23690
+ cache.set(prop, wrapped);
23691
+ return wrapped;
23692
+ }
23693
+ if (prop === "prompt" && typeof value === "function") {
23694
+ const wrapped = async function(message, options) {
23695
+ const args = [message, options];
23696
+ return cursorSDKChannels.prompt.tracePromise(
23697
+ () => Reflect.apply(value, target, args),
23698
+ { arguments: args }
23699
+ );
23700
+ };
23701
+ cache.set(prop, wrapped);
23702
+ return wrapped;
23703
+ }
23704
+ if (typeof value === "function") {
23705
+ const bound = value.bind(target);
23706
+ cache.set(prop, bound);
23707
+ return bound;
23708
+ }
23709
+ return value;
23710
+ }
23711
+ });
23712
+ }
23713
+ function wrapCursorAgent(agent) {
23714
+ if (!agent || typeof agent !== "object") {
23715
+ return agent;
23716
+ }
23717
+ if (agent[WRAPPED_AGENT2]) {
23718
+ return agent;
23719
+ }
23720
+ const proxy = new Proxy(agent, {
23721
+ get(target, prop, receiver) {
23722
+ if (prop === WRAPPED_AGENT2) {
23723
+ return true;
23724
+ }
23725
+ const value = Reflect.get(target, prop, receiver);
23726
+ if (prop === "send" && typeof value === "function") {
23727
+ return function(message, options) {
23728
+ const args = [message, options];
23729
+ return cursorSDKChannels.send.tracePromise(
23730
+ () => Reflect.apply(value, target, args),
23731
+ {
23732
+ agent: target,
23733
+ arguments: args,
23734
+ operation: "send"
23735
+ }
23736
+ );
23737
+ };
23738
+ }
23739
+ if (typeof value === "function") {
23740
+ return value.bind(target);
23741
+ }
23742
+ return value;
23743
+ }
23744
+ });
23745
+ return proxy;
23746
+ }
23747
+
21943
23748
  // src/wrappers/google-genai.ts
21944
23749
  function wrapGoogleGenAI(googleGenAI) {
21945
23750
  if (!googleGenAI || typeof googleGenAI !== "object") {
@@ -22693,6 +24498,94 @@ function wrapRerank3(rerank) {
22693
24498
  });
22694
24499
  }
22695
24500
 
24501
+ // src/wrappers/groq.ts
24502
+ function wrapGroq(groq) {
24503
+ if (isSupportedGroqClient(groq)) {
24504
+ return groqProxy(groq);
24505
+ }
24506
+ console.warn("Unsupported Groq library. Not wrapping.");
24507
+ return groq;
24508
+ }
24509
+ function isRecord3(value) {
24510
+ return typeof value === "object" && value !== null;
24511
+ }
24512
+ function hasFunction4(value, methodName) {
24513
+ return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
24514
+ }
24515
+ function hasChat2(value) {
24516
+ return isRecord3(value) && isRecord3(value.completions) && hasFunction4(value.completions, "create");
24517
+ }
24518
+ function hasEmbeddings2(value) {
24519
+ return hasFunction4(value, "create");
24520
+ }
24521
+ function isSupportedGroqClient(value) {
24522
+ return isRecord3(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
24523
+ }
24524
+ function groqProxy(groq) {
24525
+ const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
24526
+ const completionProxy = groq.chat?.completions ? new Proxy(groq.chat.completions, {
24527
+ get(target, prop, receiver) {
24528
+ if (prop === "create") {
24529
+ return wrapChatCompletionsCreate(target.create.bind(target));
24530
+ }
24531
+ return Reflect.get(target, prop, receiver);
24532
+ }
24533
+ }) : void 0;
24534
+ const chatProxy3 = groq.chat ? new Proxy(groq.chat, {
24535
+ get(target, prop, receiver) {
24536
+ if (prop === "completions") {
24537
+ return completionProxy ?? target.completions;
24538
+ }
24539
+ return Reflect.get(target, prop, receiver);
24540
+ }
24541
+ }) : void 0;
24542
+ const embeddingsProxy3 = groq.embeddings ? new Proxy(groq.embeddings, {
24543
+ get(target, prop, receiver) {
24544
+ if (prop === "create") {
24545
+ return wrapEmbeddingsCreate2(target.create.bind(target));
24546
+ }
24547
+ return Reflect.get(target, prop, receiver);
24548
+ }
24549
+ }) : void 0;
24550
+ const topLevelProxy = new Proxy(groq, {
24551
+ get(target, prop, receiver) {
24552
+ switch (prop) {
24553
+ case "chat":
24554
+ return chatProxy3 ?? target.chat;
24555
+ case "embeddings":
24556
+ return embeddingsProxy3 ?? target.embeddings;
24557
+ }
24558
+ const value = Reflect.get(target, prop, target);
24559
+ if (typeof value !== "function") {
24560
+ return value;
24561
+ }
24562
+ const cachedValue = privateMethodWorkaroundCache.get(value);
24563
+ if (cachedValue) {
24564
+ return cachedValue;
24565
+ }
24566
+ const thisBoundValue = function(...args) {
24567
+ const thisArg = this === topLevelProxy ? target : this;
24568
+ const output = Reflect.apply(value, thisArg, args);
24569
+ return output === target ? topLevelProxy : output;
24570
+ };
24571
+ privateMethodWorkaroundCache.set(value, thisBoundValue);
24572
+ return thisBoundValue;
24573
+ }
24574
+ });
24575
+ return topLevelProxy;
24576
+ }
24577
+ function wrapChatCompletionsCreate(create) {
24578
+ return (request, options) => groqChannels.chatCompletionsCreate.tracePromise(
24579
+ () => create(request, options),
24580
+ { arguments: [request] }
24581
+ );
24582
+ }
24583
+ function wrapEmbeddingsCreate2(create) {
24584
+ return (request, options) => groqChannels.embeddingsCreate.tracePromise(() => create(request, options), {
24585
+ arguments: [request]
24586
+ });
24587
+ }
24588
+
22696
24589
  // src/wrappers/vitest/context-manager.ts
22697
24590
  var VitestContextManager = class {
22698
24591
  /**
@@ -26673,8 +28566,10 @@ export {
26673
28566
  wrapAnthropic,
26674
28567
  wrapClaudeAgentSDK,
26675
28568
  wrapCohere,
28569
+ wrapCursorSDK,
26676
28570
  wrapGoogleADK,
26677
28571
  wrapGoogleGenAI,
28572
+ wrapGroq,
26678
28573
  wrapHuggingFace,
26679
28574
  wrapMastraAgent,
26680
28575
  wrapMistral,