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/cli.js CHANGED
@@ -1232,7 +1232,7 @@ var require_package = __commonJS({
1232
1232
  "package.json"(exports2, module2) {
1233
1233
  module2.exports = {
1234
1234
  name: "braintrust",
1235
- version: "3.9.0",
1235
+ version: "3.10.0",
1236
1236
  description: "SDK for integrating Braintrust",
1237
1237
  repository: {
1238
1238
  type: "git",
@@ -1311,13 +1311,13 @@ var require_package = __commonJS({
1311
1311
  types: "./dist/auto-instrumentations/bundler/vite.d.ts",
1312
1312
  import: "./dist/auto-instrumentations/bundler/vite.mjs",
1313
1313
  module: "./dist/auto-instrumentations/bundler/vite.mjs",
1314
- require: "./dist/auto-instrumentations/bundler/vite.js"
1314
+ require: "./dist/auto-instrumentations/bundler/vite.cjs"
1315
1315
  },
1316
1316
  "./webpack": {
1317
1317
  types: "./dist/auto-instrumentations/bundler/webpack.d.ts",
1318
1318
  import: "./dist/auto-instrumentations/bundler/webpack.mjs",
1319
1319
  module: "./dist/auto-instrumentations/bundler/webpack.mjs",
1320
- require: "./dist/auto-instrumentations/bundler/webpack.js"
1320
+ require: "./dist/auto-instrumentations/bundler/webpack.cjs"
1321
1321
  },
1322
1322
  "./webpack-loader": {
1323
1323
  types: "./dist/auto-instrumentations/bundler/webpack-loader.d.ts",
@@ -1327,13 +1327,13 @@ var require_package = __commonJS({
1327
1327
  types: "./dist/auto-instrumentations/bundler/esbuild.d.ts",
1328
1328
  import: "./dist/auto-instrumentations/bundler/esbuild.mjs",
1329
1329
  module: "./dist/auto-instrumentations/bundler/esbuild.mjs",
1330
- require: "./dist/auto-instrumentations/bundler/esbuild.js"
1330
+ require: "./dist/auto-instrumentations/bundler/esbuild.cjs"
1331
1331
  },
1332
1332
  "./rollup": {
1333
1333
  types: "./dist/auto-instrumentations/bundler/rollup.d.ts",
1334
1334
  import: "./dist/auto-instrumentations/bundler/rollup.mjs",
1335
1335
  module: "./dist/auto-instrumentations/bundler/rollup.mjs",
1336
- require: "./dist/auto-instrumentations/bundler/rollup.js"
1336
+ require: "./dist/auto-instrumentations/bundler/rollup.cjs"
1337
1337
  }
1338
1338
  },
1339
1339
  files: [
@@ -1345,7 +1345,7 @@ var require_package = __commonJS({
1345
1345
  build: 'cross-env NODE_OPTIONS="--max-old-space-size=8192" tsup',
1346
1346
  "check:typings": "tsc --noEmit",
1347
1347
  watch: "tsup --watch",
1348
- clean: "rm -r dist/* && rm -r dev/dist/*",
1348
+ clean: "rm -r dist/* && rm -r dev/dist/* && rm -r util/dist/*",
1349
1349
  docs: "typedoc --options typedoc.json src/node/index.ts",
1350
1350
  test: 'vitest run --exclude "src/wrappers/**/*.test.ts" --exclude "src/otel/**/*.test.ts" --exclude "smoke/**/*.test.ts" --exclude "src/zod/**/*.test.ts" --exclude "tests/api-compatibility/**"',
1351
1351
  "test:core": "pnpm prune && pnpm test",
@@ -3319,6 +3319,7 @@ var TopicMapData = import_v36.z.object({
3319
3319
  report_key: import_v36.z.string().optional(),
3320
3320
  topic_names: import_v36.z.record(import_v36.z.string()).optional(),
3321
3321
  generation_settings: TopicMapGenerationSettings.optional(),
3322
+ disable_reconciliation: import_v36.z.boolean().optional(),
3322
3323
  distance_threshold: import_v36.z.number().optional()
3323
3324
  });
3324
3325
  var BatchedFacetData = import_v36.z.object({
@@ -3649,28 +3650,6 @@ var EnvVar = import_v36.z.object({
3649
3650
  secret_type: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3650
3651
  secret_category: import_v36.z.enum(["env_var", "ai_provider", "sandbox_provider"]).optional().default("env_var")
3651
3652
  });
3652
- var EvalStatusPageTheme = import_v36.z.enum(["light", "dark"]);
3653
- var EvalStatusPageConfig = import_v36.z.object({
3654
- score_columns: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
3655
- metric_columns: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
3656
- grouping_field: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3657
- filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3658
- sort_by: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3659
- sort_order: import_v36.z.union([import_v36.z.enum(["asc", "desc"]), import_v36.z.null()]),
3660
- api_key: import_v36.z.union([import_v36.z.string(), import_v36.z.null()])
3661
- }).partial();
3662
- var EvalStatusPage = import_v36.z.object({
3663
- id: import_v36.z.string().uuid(),
3664
- project_id: import_v36.z.string().uuid(),
3665
- user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3666
- created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3667
- deleted_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3668
- name: import_v36.z.string(),
3669
- description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3670
- logo_url: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3671
- theme: EvalStatusPageTheme,
3672
- config: EvalStatusPageConfig
3673
- });
3674
3653
  var RepoInfo = import_v36.z.union([
3675
3654
  import_v36.z.object({
3676
3655
  commit: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
@@ -3697,6 +3676,15 @@ var Experiment = import_v36.z.object({
3697
3676
  deleted_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3698
3677
  dataset_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3699
3678
  dataset_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3679
+ internal_metadata: import_v36.z.union([
3680
+ import_v36.z.object({
3681
+ dataset_filter: import_v36.z.union([
3682
+ import_v36.z.object({}).partial().passthrough(),
3683
+ import_v36.z.null()
3684
+ ])
3685
+ }).partial().passthrough(),
3686
+ import_v36.z.null()
3687
+ ]).optional(),
3700
3688
  parameters_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3701
3689
  parameters_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
3702
3690
  public: import_v36.z.boolean(),
@@ -4433,14 +4421,21 @@ var ProjectAutomation = import_v36.z.object({
4433
4421
  import_v36.z.object({ type: import_v36.z.literal("log_spans") }),
4434
4422
  import_v36.z.object({ type: import_v36.z.literal("btql_query"), btql_query: import_v36.z.string() })
4435
4423
  ]),
4424
+ scope: import_v36.z.union([SpanScope, TraceScope, GroupScope, import_v36.z.null()]).optional(),
4436
4425
  export_path: import_v36.z.string(),
4437
4426
  format: import_v36.z.enum(["jsonl", "parquet"]),
4438
4427
  interval_seconds: import_v36.z.number().gte(1).lte(2592e3),
4439
- credentials: import_v36.z.object({
4440
- type: import_v36.z.literal("aws_iam"),
4441
- role_arn: import_v36.z.string(),
4442
- external_id: import_v36.z.string()
4443
- }),
4428
+ credentials: import_v36.z.union([
4429
+ import_v36.z.object({
4430
+ type: import_v36.z.literal("aws_iam"),
4431
+ role_arn: import_v36.z.string(),
4432
+ external_id: import_v36.z.string()
4433
+ }),
4434
+ import_v36.z.object({
4435
+ type: import_v36.z.literal("gcp_service_account"),
4436
+ service_account_email: import_v36.z.string()
4437
+ })
4438
+ ]),
4444
4439
  batch_size: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
4445
4440
  }),
4446
4441
  import_v36.z.object({
@@ -4820,7 +4815,7 @@ var ViewOptions = import_v36.z.union([
4820
4815
  import_v36.z.object({ from: import_v36.z.string(), to: import_v36.z.string() }),
4821
4816
  import_v36.z.null()
4822
4817
  ]),
4823
- queryShape: import_v36.z.union([import_v36.z.enum(["traces", "spans"]), import_v36.z.null()]),
4818
+ queryShape: import_v36.z.union([import_v36.z.enum(["traces", "spans", "topics"]), import_v36.z.null()]),
4824
4819
  cluster: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
4825
4820
  freezeColumns: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()])
4826
4821
  }).partial(),
@@ -5834,6 +5829,19 @@ var RESET_CONTEXT_MANAGER_STATE = Symbol.for(
5834
5829
  "braintrust.resetContextManagerState"
5835
5830
  );
5836
5831
  var DEFAULT_MAX_REQUEST_SIZE = 6 * 1024 * 1024;
5832
+ var datasetSnapshotRegisterResponseSchema = import_v38.z.object({
5833
+ dataset_snapshot: DatasetSnapshot,
5834
+ found_existing: import_v38.z.boolean().optional()
5835
+ });
5836
+ var datasetRestorePreviewResultSchema = import_v38.z.object({
5837
+ rows_to_restore: import_v38.z.number(),
5838
+ rows_to_delete: import_v38.z.number()
5839
+ });
5840
+ var datasetRestoreResultSchema = import_v38.z.object({
5841
+ xact_id: import_v38.z.string().nullable(),
5842
+ rows_restored: import_v38.z.number(),
5843
+ rows_deleted: import_v38.z.number()
5844
+ });
5837
5845
  var parametersRowSchema = import_v38.z.object({
5838
5846
  id: import_v38.z.string().uuid(),
5839
5847
  _xact_id: import_v38.z.string(),
@@ -7843,6 +7851,33 @@ Error: ${errorText}`;
7843
7851
  this.queue.enforceQueueSizeLimit(enforce);
7844
7852
  }
7845
7853
  };
7854
+ function isDatasetSnapshotNameLookup(lookup) {
7855
+ return "snapshotName" in lookup;
7856
+ }
7857
+ function assertDatasetSnapshotLookup(lookup) {
7858
+ const hasSnapshotName = lookup.snapshotName !== void 0;
7859
+ const hasXactId = lookup.xactId !== void 0;
7860
+ if (hasSnapshotName === hasXactId) {
7861
+ throw new Error("Exactly one of snapshotName or xactId must be provided");
7862
+ }
7863
+ }
7864
+ function getExperimentDatasetFilter({
7865
+ dataset,
7866
+ _internal_btql
7867
+ }) {
7868
+ if (_internal_btql !== void 0) {
7869
+ return _internal_btql;
7870
+ }
7871
+ if (!(dataset instanceof Dataset2)) {
7872
+ return void 0;
7873
+ }
7874
+ const datasetFilter = Reflect.get(dataset, "_internal_btql");
7875
+ return isObject(datasetFilter) ? datasetFilter : void 0;
7876
+ }
7877
+ function getInternalBtqlLimit(internalBtql) {
7878
+ const limit = internalBtql?.["limit"];
7879
+ return typeof limit === "number" ? limit : void 0;
7880
+ }
7846
7881
  function init(projectOrOptions, optionalOptions) {
7847
7882
  const options = (() => {
7848
7883
  if (typeof projectOrOptions === "string") {
@@ -7861,6 +7896,7 @@ function init(projectOrOptions, optionalOptions) {
7861
7896
  experiment,
7862
7897
  description,
7863
7898
  dataset,
7899
+ _internal_btql,
7864
7900
  parameters,
7865
7901
  baseExperiment,
7866
7902
  isPublic,
@@ -7969,16 +8005,24 @@ function init(projectOrOptions, optionalOptions) {
7969
8005
  args["ancestor_commits"] = await isomorph_default.getPastNAncestors();
7970
8006
  }
7971
8007
  if (dataset !== void 0) {
7972
- if ("id" in dataset && typeof dataset.id === "string" && !("__braintrust_dataset_marker" in dataset)) {
7973
- args["dataset_id"] = dataset.id;
7974
- if ("version" in dataset && dataset.version !== void 0) {
7975
- args["dataset_version"] = dataset.version;
7976
- }
7977
- } else {
7978
- args["dataset_id"] = await dataset.id;
7979
- args["dataset_version"] = await dataset.version();
8008
+ const datasetSelection = await serializeDatasetForExperiment({
8009
+ dataset,
8010
+ state
8011
+ });
8012
+ args["dataset_id"] = datasetSelection.datasetId;
8013
+ if (datasetSelection.datasetVersion !== void 0) {
8014
+ args["dataset_version"] = datasetSelection.datasetVersion;
7980
8015
  }
7981
8016
  }
8017
+ const datasetFilter = getExperimentDatasetFilter({
8018
+ dataset,
8019
+ _internal_btql
8020
+ });
8021
+ if (datasetFilter !== void 0) {
8022
+ args["internal_metadata"] = {
8023
+ dataset_filter: datasetFilter
8024
+ };
8025
+ }
7982
8026
  if (parameters !== void 0) {
7983
8027
  if (RemoteEvalParameters.isParameters(parameters)) {
7984
8028
  args["parameters_id"] = parameters.id;
@@ -8032,13 +8076,160 @@ function init(projectOrOptions, optionalOptions) {
8032
8076
  const ret = new Experiment2(
8033
8077
  state,
8034
8078
  lazyMetadata,
8035
- dataset !== void 0 && "version" in dataset ? dataset : void 0
8079
+ dataset !== void 0 ? dataset : void 0
8036
8080
  );
8037
8081
  if (options.setCurrent ?? true) {
8038
8082
  state.currentExperiment = ret;
8039
8083
  }
8040
8084
  return ret;
8041
8085
  }
8086
+ async function getDatasetSnapshots(params) {
8087
+ const { state, datasetId } = params;
8088
+ return DatasetSnapshot.array().parse(
8089
+ await state.appConn().post_json("api/dataset_snapshot/get", {
8090
+ dataset_id: datasetId,
8091
+ ..."snapshotName" in params ? { name: params.snapshotName } : {},
8092
+ ..."xactId" in params ? { xact_id: params.xactId } : {}
8093
+ })
8094
+ );
8095
+ }
8096
+ async function getDatasetSnapshot(params) {
8097
+ assertDatasetSnapshotLookup(params);
8098
+ const snapshots = await getDatasetSnapshots(params);
8099
+ if (snapshots.length > 1) {
8100
+ throw new Error(
8101
+ 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}`
8102
+ );
8103
+ }
8104
+ return snapshots[0];
8105
+ }
8106
+ function normalizeDatasetSelection({
8107
+ version: version2,
8108
+ environment,
8109
+ snapshotName
8110
+ }) {
8111
+ if (version2 !== void 0) {
8112
+ return { version: version2 };
8113
+ }
8114
+ if (snapshotName !== void 0) {
8115
+ return { snapshotName };
8116
+ }
8117
+ if (environment !== void 0) {
8118
+ return { environment };
8119
+ }
8120
+ return {};
8121
+ }
8122
+ async function resolveDatasetSnapshotName({
8123
+ state,
8124
+ datasetId,
8125
+ snapshotName
8126
+ }) {
8127
+ const match = await getDatasetSnapshot({
8128
+ state,
8129
+ datasetId,
8130
+ snapshotName
8131
+ });
8132
+ if (match === void 0) {
8133
+ throw new Error(
8134
+ `Dataset snapshot "${snapshotName}" not found for ${datasetId}`
8135
+ );
8136
+ }
8137
+ return match.xact_id;
8138
+ }
8139
+ async function resolveDatasetSnapshotNameForMetadata({
8140
+ state,
8141
+ lazyMetadata,
8142
+ snapshotName
8143
+ }) {
8144
+ const metadata = await lazyMetadata.get();
8145
+ return await resolveDatasetSnapshotName({
8146
+ state,
8147
+ datasetId: metadata.dataset.id,
8148
+ snapshotName
8149
+ });
8150
+ }
8151
+ async function resolveDatasetEnvironment({
8152
+ state,
8153
+ datasetId,
8154
+ environment
8155
+ }) {
8156
+ const environmentObjectPath = `environment-object/dataset/${datasetId}/${encodeURIComponent(environment)}`;
8157
+ const response = state.orgName == null ? await state.apiConn().get_json(environmentObjectPath) : await state.apiConn().get_json(environmentObjectPath, {
8158
+ org_name: state.orgName
8159
+ });
8160
+ return import_v38.z.object({ object_version: import_v38.z.string() }).parse(response).object_version;
8161
+ }
8162
+ async function resolveDatasetEnvironmentForMetadata({
8163
+ state,
8164
+ lazyMetadata,
8165
+ environment
8166
+ }) {
8167
+ const metadata = await lazyMetadata.get();
8168
+ return await resolveDatasetEnvironment({
8169
+ state,
8170
+ datasetId: metadata.dataset.id,
8171
+ environment
8172
+ });
8173
+ }
8174
+ async function serializeDatasetForExperiment({
8175
+ dataset,
8176
+ state
8177
+ }) {
8178
+ if (!Dataset2.isDataset(dataset)) {
8179
+ const selection2 = normalizeDatasetSelection(dataset);
8180
+ if (selection2.version !== void 0) {
8181
+ return {
8182
+ datasetId: dataset.id,
8183
+ datasetVersion: selection2.version
8184
+ };
8185
+ }
8186
+ if (selection2.snapshotName !== void 0) {
8187
+ return {
8188
+ datasetId: dataset.id,
8189
+ datasetVersion: await resolveDatasetSnapshotName({
8190
+ state,
8191
+ datasetId: dataset.id,
8192
+ snapshotName: selection2.snapshotName
8193
+ })
8194
+ };
8195
+ }
8196
+ if (selection2.environment !== void 0) {
8197
+ return {
8198
+ datasetId: dataset.id,
8199
+ datasetVersion: await resolveDatasetEnvironment({
8200
+ state,
8201
+ datasetId: dataset.id,
8202
+ environment: selection2.environment
8203
+ })
8204
+ };
8205
+ }
8206
+ return {
8207
+ datasetId: dataset.id
8208
+ };
8209
+ }
8210
+ const evalData = await dataset.toEvalData();
8211
+ const selection = normalizeDatasetSelection({
8212
+ version: evalData.dataset_version,
8213
+ environment: evalData.dataset_environment,
8214
+ snapshotName: evalData.dataset_snapshot_name
8215
+ });
8216
+ if (selection.version !== void 0) {
8217
+ return {
8218
+ datasetId: evalData.dataset_id,
8219
+ datasetVersion: selection.version
8220
+ };
8221
+ }
8222
+ const datasetVersion = await dataset.version();
8223
+ if (datasetVersion !== void 0) {
8224
+ return {
8225
+ datasetId: evalData.dataset_id,
8226
+ datasetVersion
8227
+ };
8228
+ }
8229
+ return {
8230
+ datasetId: evalData.dataset_id
8231
+ };
8232
+ }
8042
8233
  function initDataset(projectOrOptions, optionalOptions) {
8043
8234
  const options = (() => {
8044
8235
  if (typeof projectOrOptions === "string") {
@@ -8057,6 +8248,8 @@ function initDataset(projectOrOptions, optionalOptions) {
8057
8248
  dataset,
8058
8249
  description,
8059
8250
  version: version2,
8251
+ snapshotName,
8252
+ environment,
8060
8253
  appUrl,
8061
8254
  apiKey,
8062
8255
  orgName,
@@ -8068,6 +8261,14 @@ function initDataset(projectOrOptions, optionalOptions) {
8068
8261
  state: stateArg,
8069
8262
  _internal_btql
8070
8263
  } = options;
8264
+ const selection = normalizeDatasetSelection({
8265
+ version: version2,
8266
+ environment,
8267
+ snapshotName
8268
+ });
8269
+ const normalizedVersion = selection.version;
8270
+ const normalizedEnvironment = selection.environment;
8271
+ const normalizedSnapshotName = selection.snapshotName;
8071
8272
  const state = stateArg ?? _globalState;
8072
8273
  const lazyMetadata = new LazyValue(
8073
8274
  async () => {
@@ -8101,13 +8302,38 @@ function initDataset(projectOrOptions, optionalOptions) {
8101
8302
  };
8102
8303
  }
8103
8304
  );
8104
- return new Dataset2(
8305
+ const resolvedVersion = normalizedVersion !== void 0 ? normalizedVersion : normalizedSnapshotName !== void 0 ? new LazyValue(async () => {
8306
+ return await resolveDatasetSnapshotNameForMetadata({
8307
+ state,
8308
+ lazyMetadata,
8309
+ snapshotName: normalizedSnapshotName
8310
+ });
8311
+ }) : normalizedEnvironment !== void 0 ? new LazyValue(async () => {
8312
+ return await resolveDatasetEnvironmentForMetadata({
8313
+ state,
8314
+ lazyMetadata,
8315
+ environment: normalizedEnvironment
8316
+ });
8317
+ }) : void 0;
8318
+ const datasetObject = new Dataset2(
8105
8319
  stateArg ?? _globalState,
8106
8320
  lazyMetadata,
8107
- version2,
8321
+ typeof resolvedVersion === "string" ? resolvedVersion : void 0,
8108
8322
  legacy,
8109
- _internal_btql
8323
+ _internal_btql,
8324
+ resolvedVersion instanceof LazyValue || normalizedEnvironment !== void 0 || normalizedSnapshotName !== void 0 ? {
8325
+ ...resolvedVersion instanceof LazyValue ? {
8326
+ lazyPinnedVersion: resolvedVersion
8327
+ } : {},
8328
+ ...normalizedEnvironment !== void 0 ? {
8329
+ pinnedEnvironment: normalizedEnvironment
8330
+ } : {},
8331
+ ...normalizedSnapshotName !== void 0 ? {
8332
+ pinnedSnapshotName: normalizedSnapshotName
8333
+ } : {}
8334
+ } : void 0
8110
8335
  );
8336
+ return datasetObject;
8111
8337
  }
8112
8338
  async function computeLoggerMetadata(state, {
8113
8339
  project_name,
@@ -8599,11 +8825,20 @@ var ObjectFetcher = class {
8599
8825
  async getState() {
8600
8826
  throw new Error("ObjectFetcher subclasses must have a 'getState' method");
8601
8827
  }
8828
+ getPinnedVersion() {
8829
+ return this.pinnedVersion;
8830
+ }
8831
+ setPinnedVersion(pinnedVersion) {
8832
+ this.pinnedVersion = pinnedVersion;
8833
+ }
8834
+ getInternalBtql() {
8835
+ return this._internal_btql;
8836
+ }
8602
8837
  async *fetchRecordsFromApi(batchSize) {
8603
8838
  const state = await this.getState();
8604
8839
  const objectId = await this.id;
8605
8840
  const batchLimit = batchSize ?? DEFAULT_FETCH_BATCH_SIZE;
8606
- const internalLimit = this._internal_btql?.limit;
8841
+ const internalLimit = getInternalBtqlLimit(this._internal_btql);
8607
8842
  const limit = batchSize !== void 0 ? batchSize : internalLimit ?? batchLimit;
8608
8843
  const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
8609
8844
  Object.entries(this._internal_btql ?? {}).filter(
@@ -9417,7 +9652,7 @@ function splitLoggingData({
9417
9652
  return [serializableInternalData, lazyInternalData];
9418
9653
  }
9419
9654
  var Dataset2 = class extends ObjectFetcher {
9420
- constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql) {
9655
+ constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql, pinState) {
9421
9656
  const isLegacyDataset = legacy ?? DEFAULT_IS_LEGACY_DATASET;
9422
9657
  if (isLegacyDataset) {
9423
9658
  debugLogger.forState(state).warn(
@@ -9438,10 +9673,16 @@ var Dataset2 = class extends ObjectFetcher {
9438
9673
  );
9439
9674
  this.state = state;
9440
9675
  this.lazyMetadata = lazyMetadata;
9676
+ this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
9677
+ this.pinnedEnvironment = pinState?.pinnedEnvironment;
9678
+ this.pinnedSnapshotName = pinState?.pinnedSnapshotName;
9441
9679
  }
9442
9680
  lazyMetadata;
9443
9681
  __braintrust_dataset_marker = true;
9444
9682
  newRecords = 0;
9683
+ lazyPinnedVersion;
9684
+ pinnedEnvironment;
9685
+ pinnedSnapshotName;
9445
9686
  get id() {
9446
9687
  return (async () => {
9447
9688
  return (await this.lazyMetadata.get()).dataset.id;
@@ -9460,10 +9701,40 @@ var Dataset2 = class extends ObjectFetcher {
9460
9701
  get loggingState() {
9461
9702
  return this.state;
9462
9703
  }
9704
+ async toEvalData() {
9705
+ await this.getState();
9706
+ const metadata = await this.lazyMetadata.get();
9707
+ const pinnedVersion = this.getPinnedVersion();
9708
+ const internalBtql = this.getInternalBtql();
9709
+ return {
9710
+ dataset_id: metadata.dataset.id,
9711
+ ...this.pinnedEnvironment !== void 0 ? {
9712
+ dataset_environment: this.pinnedEnvironment
9713
+ } : {},
9714
+ ...this.pinnedEnvironment === void 0 && this.pinnedSnapshotName !== void 0 ? {
9715
+ dataset_snapshot_name: this.pinnedSnapshotName
9716
+ } : {},
9717
+ ...this.pinnedEnvironment === void 0 && this.pinnedSnapshotName === void 0 && pinnedVersion !== void 0 ? {
9718
+ dataset_version: pinnedVersion
9719
+ } : {},
9720
+ ...internalBtql !== void 0 ? { _internal_btql: internalBtql } : {}
9721
+ };
9722
+ }
9463
9723
  async getState() {
9464
9724
  await this.lazyMetadata.get();
9725
+ if (this.lazyPinnedVersion !== void 0 && this.getPinnedVersion() === void 0) {
9726
+ this.setPinnedVersion(await this.lazyPinnedVersion.get());
9727
+ }
9465
9728
  return this.state;
9466
9729
  }
9730
+ async version(options) {
9731
+ const pinnedVersion = this.getPinnedVersion();
9732
+ if (pinnedVersion !== void 0) {
9733
+ return pinnedVersion;
9734
+ }
9735
+ await this.getState();
9736
+ return await super.version(options);
9737
+ }
9467
9738
  validateEvent({
9468
9739
  metadata,
9469
9740
  expected,
@@ -9599,6 +9870,88 @@ var Dataset2 = class extends ObjectFetcher {
9599
9870
  this.state.bgLogger().log([args]);
9600
9871
  return id;
9601
9872
  }
9873
+ async createSnapshot({
9874
+ name,
9875
+ description,
9876
+ update
9877
+ }) {
9878
+ await this.flush();
9879
+ const state = await this.getState();
9880
+ const datasetId = await this.id;
9881
+ const currentVersion = await this.version();
9882
+ if (currentVersion === void 0) {
9883
+ throw new Error("Cannot create snapshot: dataset has no version");
9884
+ }
9885
+ const response = await state.appConn().post_json("api/dataset_snapshot/register", {
9886
+ dataset_id: datasetId,
9887
+ dataset_snapshot_name: name,
9888
+ description,
9889
+ xact_id: currentVersion,
9890
+ update
9891
+ });
9892
+ return datasetSnapshotRegisterResponseSchema.parse(response).dataset_snapshot;
9893
+ }
9894
+ async listSnapshots() {
9895
+ const state = await this.getState();
9896
+ return await getDatasetSnapshots({
9897
+ state,
9898
+ datasetId: await this.id
9899
+ });
9900
+ }
9901
+ async getSnapshot(lookup) {
9902
+ const state = await this.getState();
9903
+ const datasetId = await this.id;
9904
+ return await getDatasetSnapshot({
9905
+ state,
9906
+ datasetId,
9907
+ ...lookup
9908
+ });
9909
+ }
9910
+ async updateSnapshot(snapshotId, {
9911
+ name,
9912
+ description
9913
+ }) {
9914
+ const state = await this.getState();
9915
+ return DatasetSnapshot.parse(
9916
+ await state.appConn().post_json("api/dataset_snapshot/patch_id", {
9917
+ id: snapshotId,
9918
+ name,
9919
+ description
9920
+ })
9921
+ );
9922
+ }
9923
+ async deleteSnapshot(snapshotId) {
9924
+ const state = await this.getState();
9925
+ return DatasetSnapshot.parse(
9926
+ await state.appConn().post_json("api/dataset_snapshot/delete_id", {
9927
+ id: snapshotId
9928
+ })
9929
+ );
9930
+ }
9931
+ async restorePreview({
9932
+ version: version2
9933
+ }) {
9934
+ await this.flush();
9935
+ const state = await this.getState();
9936
+ const datasetId = await this.id;
9937
+ return datasetRestorePreviewResultSchema.parse(
9938
+ await state.apiConn().post_json(`v1/dataset/${datasetId}/restore/preview`, {
9939
+ version: version2
9940
+ })
9941
+ );
9942
+ }
9943
+ async restore({
9944
+ version: version2
9945
+ }) {
9946
+ await this.flush();
9947
+ const state = await this.getState();
9948
+ const datasetId = await this.id;
9949
+ return datasetRestoreResultSchema.parse(
9950
+ await state.apiConn().post_json(`v1/dataset/${datasetId}/restore`, {
9951
+ version: version2
9952
+ })
9953
+ );
9954
+ }
9602
9955
  /**
9603
9956
  * Summarize the dataset, including high level metrics about its size and other metadata.
9604
9957
  * @param summarizeData Whether to summarize the data. If false, only the metadata will be returned.
@@ -17782,6 +18135,9 @@ function llmParentKey(parentToolUseId) {
17782
18135
  function isSubAgentDelegationToolName(toolName) {
17783
18136
  return toolName === "Agent" || toolName === "Task";
17784
18137
  }
18138
+ function shouldParentToolAsTaskSibling(toolName) {
18139
+ return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
18140
+ }
17785
18141
  function filterSerializableOptions(options) {
17786
18142
  const allowedKeys = [
17787
18143
  "model",
@@ -17881,6 +18237,11 @@ function resolveTaskToolUseId(taskIdToToolUseId, message) {
17881
18237
  }
17882
18238
  return void 0;
17883
18239
  }
18240
+ function seedTaskToolUseIdMapping(taskIdToToolUseId, message) {
18241
+ if (typeof message.task_id === "string" && typeof message.tool_use_id === "string") {
18242
+ taskIdToToolUseId.set(message.task_id, message.tool_use_id);
18243
+ }
18244
+ }
17884
18245
  function extractUsageFromMessage(message) {
17885
18246
  const metrics = {};
17886
18247
  let usage;
@@ -18076,7 +18437,10 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
18076
18437
  }
18077
18438
  },
18078
18439
  name: parsed.displayName,
18079
- parent: await resolveParentSpan(toolUseID),
18440
+ parent: await resolveParentSpan(toolUseID, {
18441
+ agentId: input.agent_id,
18442
+ preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
18443
+ }),
18080
18444
  spanAttributes: { type: "tool" /* TOOL */ }
18081
18445
  });
18082
18446
  activeToolSpans.set(toolUseID, toolSpan);
@@ -18366,6 +18730,7 @@ async function finalizeCurrentMessageGroup(state) {
18366
18730
  state.currentMessages.length = 0;
18367
18731
  }
18368
18732
  function maybeTrackToolUseContext(state, message) {
18733
+ seedTaskToolUseIdMapping(state.taskIdToToolUseId, message);
18369
18734
  if (message.type !== "assistant" || !Array.isArray(message.message?.content)) {
18370
18735
  return;
18371
18736
  }
@@ -18420,6 +18785,34 @@ async function ensureSubAgentSpan(subAgentDetailsByToolUseId, rootSpan, activeTo
18420
18785
  subAgentSpans.set(parentToolUseId, subAgentSpan);
18421
18786
  return subAgentSpan;
18422
18787
  }
18788
+ async function ensureActiveLlmSpanForParentToolUse(rootSpan, activeLlmSpansByParentToolUse, subAgentDetailsByToolUseId, activeToolSpans, subAgentSpans, parentToolUseId, startTime) {
18789
+ const parentKey = llmParentKey(parentToolUseId);
18790
+ const existingLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
18791
+ if (existingLlmSpan) {
18792
+ return existingLlmSpan;
18793
+ }
18794
+ let llmParentSpan = await rootSpan.export();
18795
+ if (parentToolUseId) {
18796
+ const subAgentSpan = await ensureSubAgentSpan(
18797
+ subAgentDetailsByToolUseId,
18798
+ rootSpan,
18799
+ activeToolSpans,
18800
+ subAgentSpans,
18801
+ parentToolUseId
18802
+ );
18803
+ llmParentSpan = await subAgentSpan.export();
18804
+ }
18805
+ const llmSpan = startSpan({
18806
+ name: "anthropic.messages.create",
18807
+ parent: llmParentSpan,
18808
+ spanAttributes: {
18809
+ type: "llm" /* LLM */
18810
+ },
18811
+ startTime
18812
+ });
18813
+ activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
18814
+ return llmSpan;
18815
+ }
18423
18816
  async function maybeHandleTaskLifecycleMessage(state, message) {
18424
18817
  if (message.type !== "system") {
18425
18818
  return false;
@@ -18529,29 +18922,15 @@ async function handleStreamMessage(state, message) {
18529
18922
  }
18530
18923
  if (message.type === "assistant" && message.message?.usage) {
18531
18924
  const parentToolUseId = message.parent_tool_use_id ?? null;
18532
- const parentKey = llmParentKey(parentToolUseId);
18533
- if (!state.activeLlmSpansByParentToolUse.has(parentKey)) {
18534
- let llmParentSpan = await state.span.export();
18535
- if (parentToolUseId) {
18536
- const subAgentSpan = await ensureSubAgentSpan(
18537
- state.subAgentDetailsByToolUseId,
18538
- state.span,
18539
- state.activeToolSpans,
18540
- state.subAgentSpans,
18541
- parentToolUseId
18542
- );
18543
- llmParentSpan = await subAgentSpan.export();
18544
- }
18545
- const llmSpan = startSpan({
18546
- name: "anthropic.messages.create",
18547
- parent: llmParentSpan,
18548
- spanAttributes: {
18549
- type: "llm" /* LLM */
18550
- },
18551
- startTime: state.currentMessageStartTime
18552
- });
18553
- state.activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
18554
- }
18925
+ await ensureActiveLlmSpanForParentToolUse(
18926
+ state.span,
18927
+ state.activeLlmSpansByParentToolUse,
18928
+ state.subAgentDetailsByToolUseId,
18929
+ state.activeToolSpans,
18930
+ state.subAgentSpans,
18931
+ parentToolUseId,
18932
+ state.currentMessageStartTime
18933
+ );
18555
18934
  state.currentMessages.push(message);
18556
18935
  }
18557
18936
  if (message.type !== "result" || !message.usage) {
@@ -18698,10 +19077,35 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
18698
19077
  const localToolContext = createClaudeLocalToolContext();
18699
19078
  const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
18700
19079
  const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
18701
- const resolveToolUseParentSpan = async (toolUseID) => {
18702
- const parentToolUseId = toolUseToParent.get(toolUseID) ?? null;
19080
+ const resolveToolUseParentSpan = async (toolUseID, context2) => {
19081
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
19082
+ const parentToolUseId = trackedParentToolUseId ?? (context2?.agentId ? taskIdToToolUseId.get(context2.agentId) ?? null : null);
18703
19083
  const parentKey = llmParentKey(parentToolUseId);
18704
19084
  const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
19085
+ if (context2?.preferTaskSiblingParent) {
19086
+ if (!activeLlmSpan) {
19087
+ await ensureActiveLlmSpanForParentToolUse(
19088
+ span,
19089
+ activeLlmSpansByParentToolUse,
19090
+ subAgentDetailsByToolUseId,
19091
+ activeToolSpans,
19092
+ subAgentSpans,
19093
+ parentToolUseId,
19094
+ getCurrentUnixTimestamp()
19095
+ );
19096
+ }
19097
+ if (parentToolUseId) {
19098
+ const subAgentSpan = await ensureSubAgentSpan(
19099
+ subAgentDetailsByToolUseId,
19100
+ span,
19101
+ activeToolSpans,
19102
+ subAgentSpans,
19103
+ parentToolUseId
19104
+ );
19105
+ return subAgentSpan.export();
19106
+ }
19107
+ return span.export();
19108
+ }
18705
19109
  if (activeLlmSpan) {
18706
19110
  return activeLlmSpan.export();
18707
19111
  }
@@ -18829,66 +19233,944 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
18829
19233
  }
18830
19234
  };
18831
19235
 
18832
- // src/instrumentation/plugins/google-genai-channels.ts
18833
- var googleGenAIChannels = defineChannels("@google/genai", {
18834
- generateContent: channel({
18835
- channelName: "models.generateContent",
19236
+ // src/instrumentation/plugins/cursor-sdk-channels.ts
19237
+ var cursorSDKChannels = defineChannels("@cursor/sdk", {
19238
+ create: channel({
19239
+ channelName: "Agent.create",
18836
19240
  kind: "async"
18837
19241
  }),
18838
- generateContentStream: channel({
18839
- channelName: "models.generateContentStream",
19242
+ resume: channel({
19243
+ channelName: "Agent.resume",
18840
19244
  kind: "async"
18841
19245
  }),
18842
- embedContent: channel({
18843
- channelName: "models.embedContent",
19246
+ prompt: channel({
19247
+ channelName: "Agent.prompt",
19248
+ kind: "async"
19249
+ }),
19250
+ send: channel({
19251
+ channelName: "agent.send",
18844
19252
  kind: "async"
18845
19253
  })
18846
19254
  });
18847
19255
 
18848
- // src/instrumentation/plugins/google-genai-plugin.ts
18849
- var GOOGLE_GENAI_INTERNAL_CONTEXT = {
18850
- caller_filename: "<node-internal>",
18851
- caller_functionname: "<node-internal>",
18852
- caller_lineno: 0
18853
- };
18854
- function createWrapperParityEvent(args) {
18855
- return {
18856
- context: GOOGLE_GENAI_INTERNAL_CONTEXT,
18857
- input: args.input,
18858
- metadata: args.metadata
18859
- };
18860
- }
18861
- var GoogleGenAIPlugin = class extends BasePlugin {
19256
+ // src/instrumentation/plugins/cursor-sdk-plugin.ts
19257
+ var PATCHED_AGENT = Symbol.for("braintrust.cursor-sdk.auto-patched-agent");
19258
+ var PATCHED_RUN = Symbol.for("braintrust.cursor-sdk.patched-run");
19259
+ var WRAPPED_AGENT = Symbol.for("braintrust.cursor-sdk.wrapped-agent");
19260
+ var CursorSDKPlugin = class extends BasePlugin {
19261
+ promptDepth = 0;
18862
19262
  onEnable() {
18863
- this.subscribeToGoogleGenAIChannels();
19263
+ this.subscribeToAgentFactories();
19264
+ this.subscribeToPrompt();
19265
+ this.subscribeToSend();
18864
19266
  }
18865
19267
  onDisable() {
18866
- this.unsubscribers = unsubscribeAll(this.unsubscribers);
19268
+ for (const unsubscribe of this.unsubscribers) {
19269
+ unsubscribe();
19270
+ }
19271
+ this.unsubscribers = [];
19272
+ this.promptDepth = 0;
18867
19273
  }
18868
- subscribeToGoogleGenAIChannels() {
18869
- this.subscribeToGenerateContentChannel();
18870
- this.subscribeToGenerateContentStreamChannel();
18871
- this.subscribeToEmbedContentChannel();
19274
+ subscribeToAgentFactories() {
19275
+ this.subscribeToAgentFactory(cursorSDKChannels.create);
19276
+ this.subscribeToAgentFactory(cursorSDKChannels.resume);
18872
19277
  }
18873
- subscribeToGenerateContentChannel() {
18874
- const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
19278
+ subscribeToAgentFactory(channel2) {
19279
+ const tracingChannel2 = channel2.tracingChannel();
19280
+ const handlers = {
19281
+ asyncEnd: (event) => {
19282
+ patchCursorAgentInPlace(event.result);
19283
+ },
19284
+ error: () => {
19285
+ }
19286
+ };
19287
+ tracingChannel2.subscribe(handlers);
19288
+ this.unsubscribers.push(() => {
19289
+ tracingChannel2.unsubscribe(handlers);
19290
+ });
19291
+ }
19292
+ subscribeToPrompt() {
19293
+ const channel2 = cursorSDKChannels.prompt.tracingChannel();
18875
19294
  const states = /* @__PURE__ */ new WeakMap();
18876
- const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
18877
- tracingChannel2,
18878
- states,
18879
- (event) => {
18880
- const params = event.arguments[0];
18881
- const input = serializeGenerateContentInput(params);
18882
- const metadata = extractGenerateContentMetadata(params);
19295
+ const handlers = {
19296
+ start: (event) => {
19297
+ this.promptDepth += 1;
19298
+ const message = event.arguments[0];
19299
+ const options = event.arguments[1];
19300
+ const metadata = {
19301
+ ...extractAgentOptionsMetadata(options),
19302
+ "cursor_sdk.operation": "Agent.prompt",
19303
+ provider: "cursor",
19304
+ ...event.moduleVersion ? { "cursor_sdk.version": event.moduleVersion } : {}
19305
+ };
18883
19306
  const span = startSpan({
18884
- name: "generate_content",
18885
- spanAttributes: {
18886
- type: "llm" /* LLM */
18887
- },
18888
- event: createWrapperParityEvent({ input, metadata })
19307
+ name: "Cursor Agent",
19308
+ spanAttributes: { type: "task" /* TASK */ }
18889
19309
  });
18890
- return {
18891
- span,
19310
+ const startTime = getCurrentUnixTimestamp();
19311
+ safeLog(span, {
19312
+ input: sanitizeUserMessage(message),
19313
+ metadata
19314
+ });
19315
+ states.set(event, { metadata, span, startTime });
19316
+ },
19317
+ asyncEnd: (event) => {
19318
+ this.promptDepth = Math.max(0, this.promptDepth - 1);
19319
+ const state = states.get(event);
19320
+ if (!state) {
19321
+ return;
19322
+ }
19323
+ try {
19324
+ safeLog(state.span, {
19325
+ metadata: {
19326
+ ...state.metadata,
19327
+ ...extractRunResultMetadata(event.result)
19328
+ },
19329
+ metrics: buildDurationMetrics(state.startTime),
19330
+ output: event.result?.result ?? event.result
19331
+ });
19332
+ } finally {
19333
+ state.span.end();
19334
+ states.delete(event);
19335
+ }
19336
+ },
19337
+ error: (event) => {
19338
+ this.promptDepth = Math.max(0, this.promptDepth - 1);
19339
+ const state = states.get(event);
19340
+ if (!state || !event.error) {
19341
+ return;
19342
+ }
19343
+ safeLog(state.span, { error: event.error.message });
19344
+ state.span.end();
19345
+ states.delete(event);
19346
+ }
19347
+ };
19348
+ channel2.subscribe(handlers);
19349
+ this.unsubscribers.push(() => {
19350
+ channel2.unsubscribe(handlers);
19351
+ });
19352
+ }
19353
+ subscribeToSend() {
19354
+ const channel2 = cursorSDKChannels.send.tracingChannel();
19355
+ const states = /* @__PURE__ */ new WeakMap();
19356
+ const handlers = {
19357
+ start: (event) => {
19358
+ if (this.promptDepth > 0) {
19359
+ return;
19360
+ }
19361
+ const message = event.arguments[0];
19362
+ const sendOptions = event.arguments[1];
19363
+ const agent = event.agent;
19364
+ const metadata = {
19365
+ ...extractSendMetadata(sendOptions),
19366
+ ...agent ? extractAgentMetadata(agent) : {},
19367
+ "cursor_sdk.operation": "agent.send",
19368
+ provider: "cursor",
19369
+ ...event.moduleVersion ? { "cursor_sdk.version": event.moduleVersion } : {}
19370
+ };
19371
+ const span = startSpan({
19372
+ name: "Cursor Agent",
19373
+ spanAttributes: { type: "task" /* TASK */ }
19374
+ });
19375
+ const startTime = getCurrentUnixTimestamp();
19376
+ safeLog(span, {
19377
+ input: sanitizeUserMessage(message),
19378
+ metadata
19379
+ });
19380
+ const state = {
19381
+ activeToolSpans: /* @__PURE__ */ new Map(),
19382
+ agent,
19383
+ conversationText: [],
19384
+ deltaText: [],
19385
+ finalized: false,
19386
+ input: message,
19387
+ metadata,
19388
+ metrics: {},
19389
+ span,
19390
+ startTime,
19391
+ streamMessages: [],
19392
+ streamText: [],
19393
+ stepText: [],
19394
+ taskText: []
19395
+ };
19396
+ if (hasCursorCallbacks(sendOptions)) {
19397
+ event.arguments[1] = wrapSendOptionsCallbacks(sendOptions, state);
19398
+ }
19399
+ states.set(event, state);
19400
+ },
19401
+ asyncEnd: (event) => {
19402
+ const state = states.get(event);
19403
+ if (!state) {
19404
+ return;
19405
+ }
19406
+ if (!event.result) {
19407
+ return;
19408
+ }
19409
+ state.run = event.result;
19410
+ state.metadata = {
19411
+ ...state.metadata,
19412
+ ...extractRunMetadata(event.result)
19413
+ };
19414
+ patchCursorRun(event.result, state);
19415
+ },
19416
+ error: (event) => {
19417
+ const state = states.get(event);
19418
+ if (!state || !event.error) {
19419
+ return;
19420
+ }
19421
+ safeLog(state.span, { error: event.error.message });
19422
+ endOpenToolSpans(state, event.error.message);
19423
+ state.span.end();
19424
+ state.finalized = true;
19425
+ states.delete(event);
19426
+ }
19427
+ };
19428
+ channel2.subscribe(handlers);
19429
+ this.unsubscribers.push(() => {
19430
+ channel2.unsubscribe(handlers);
19431
+ });
19432
+ }
19433
+ };
19434
+ function patchCursorAgentInPlace(agent) {
19435
+ if (!agent || typeof agent !== "object") {
19436
+ return;
19437
+ }
19438
+ const agentRecord = agent;
19439
+ if (agentRecord[PATCHED_AGENT] || agentRecord[WRAPPED_AGENT] || typeof agentRecord.send !== "function") {
19440
+ return;
19441
+ }
19442
+ const originalSend = agentRecord.send.bind(agentRecord);
19443
+ try {
19444
+ Object.defineProperty(agentRecord, PATCHED_AGENT, {
19445
+ configurable: false,
19446
+ enumerable: false,
19447
+ value: true
19448
+ });
19449
+ Object.defineProperty(agentRecord, "send", {
19450
+ configurable: true,
19451
+ value(message, options) {
19452
+ const args = [message, options];
19453
+ return cursorSDKChannels.send.tracePromise(
19454
+ () => originalSend(...args),
19455
+ {
19456
+ agent: agentRecord,
19457
+ arguments: args,
19458
+ operation: "send"
19459
+ }
19460
+ );
19461
+ },
19462
+ writable: true
19463
+ });
19464
+ } catch {
19465
+ }
19466
+ }
19467
+ function wrapSendOptionsCallbacks(options, state) {
19468
+ const originalOnDelta = options.onDelta;
19469
+ const originalOnStep = options.onStep;
19470
+ return {
19471
+ ...options,
19472
+ async onDelta(args) {
19473
+ try {
19474
+ await handleInteractionUpdate(state, args.update);
19475
+ } catch (error2) {
19476
+ logInstrumentationError("Cursor SDK onDelta", error2);
19477
+ }
19478
+ if (originalOnDelta) {
19479
+ return originalOnDelta(args);
19480
+ }
19481
+ },
19482
+ async onStep(args) {
19483
+ try {
19484
+ handleStepUpdate(state, args.step);
19485
+ } catch (error2) {
19486
+ logInstrumentationError("Cursor SDK onStep", error2);
19487
+ }
19488
+ if (originalOnStep) {
19489
+ return originalOnStep(args);
19490
+ }
19491
+ }
19492
+ };
19493
+ }
19494
+ function hasCursorCallbacks(options) {
19495
+ return !!options && (typeof options.onDelta === "function" || typeof options.onStep === "function");
19496
+ }
19497
+ function patchCursorRun(run2, state) {
19498
+ if (!run2 || typeof run2 !== "object") {
19499
+ return;
19500
+ }
19501
+ const runRecord = run2;
19502
+ if (runRecord[PATCHED_RUN]) {
19503
+ return;
19504
+ }
19505
+ try {
19506
+ Object.defineProperty(runRecord, PATCHED_RUN, {
19507
+ configurable: false,
19508
+ enumerable: false,
19509
+ value: true
19510
+ });
19511
+ if (typeof runRecord.stream === "function") {
19512
+ const originalStream = runRecord.stream.bind(runRecord);
19513
+ Object.defineProperty(runRecord, "stream", {
19514
+ configurable: true,
19515
+ value() {
19516
+ const stream = originalStream();
19517
+ return patchCursorStream(stream, state);
19518
+ },
19519
+ writable: true
19520
+ });
19521
+ }
19522
+ if (typeof runRecord.wait === "function") {
19523
+ const originalWait = runRecord.wait.bind(runRecord);
19524
+ Object.defineProperty(runRecord, "wait", {
19525
+ configurable: true,
19526
+ async value() {
19527
+ try {
19528
+ const result = await originalWait();
19529
+ state.lastResult = result;
19530
+ await finalizeCursorRun(state, { result });
19531
+ return result;
19532
+ } catch (error2) {
19533
+ await finalizeCursorRun(state, { error: error2 });
19534
+ throw error2;
19535
+ }
19536
+ },
19537
+ writable: true
19538
+ });
19539
+ }
19540
+ if (typeof runRecord.conversation === "function") {
19541
+ const originalConversation = runRecord.conversation.bind(runRecord);
19542
+ Object.defineProperty(runRecord, "conversation", {
19543
+ configurable: true,
19544
+ async value() {
19545
+ try {
19546
+ const conversation = await originalConversation();
19547
+ await handleConversation(state, conversation);
19548
+ await finalizeCursorRun(state);
19549
+ return conversation;
19550
+ } catch (error2) {
19551
+ await finalizeCursorRun(state, { error: error2 });
19552
+ throw error2;
19553
+ }
19554
+ },
19555
+ writable: true
19556
+ });
19557
+ }
19558
+ } catch {
19559
+ void finalizeCursorRun(state, { output: run2 });
19560
+ }
19561
+ }
19562
+ async function* patchCursorStream(stream, state) {
19563
+ try {
19564
+ for await (const message of stream) {
19565
+ try {
19566
+ await handleStreamMessage2(state, message);
19567
+ } catch (error2) {
19568
+ logInstrumentationError("Cursor SDK stream", error2);
19569
+ }
19570
+ yield message;
19571
+ }
19572
+ await finalizeCursorRun(state);
19573
+ } catch (error2) {
19574
+ await finalizeCursorRun(state, { error: error2 });
19575
+ throw error2;
19576
+ }
19577
+ }
19578
+ async function handleInteractionUpdate(state, update) {
19579
+ switch (update.type) {
19580
+ case "text-delta":
19581
+ if (typeof update.text === "string") {
19582
+ state.deltaText.push(update.text);
19583
+ }
19584
+ return;
19585
+ case "token-delta":
19586
+ if (typeof update.tokens === "number") {
19587
+ state.metrics["cursor_sdk.delta_tokens"] = (state.metrics["cursor_sdk.delta_tokens"] ?? 0) + update.tokens;
19588
+ }
19589
+ return;
19590
+ case "tool-call-started":
19591
+ case "partial-tool-call":
19592
+ case "tool-call-completed":
19593
+ await handleToolUpdate(
19594
+ state,
19595
+ update
19596
+ );
19597
+ return;
19598
+ case "turn-ended":
19599
+ addUsageMetrics(
19600
+ state.metrics,
19601
+ update.usage
19602
+ );
19603
+ return;
19604
+ case "summary":
19605
+ if (typeof update.summary === "string") {
19606
+ state.taskText.push(update.summary);
19607
+ }
19608
+ return;
19609
+ case "step-completed":
19610
+ if (typeof update.stepDurationMs === "number") {
19611
+ state.metrics["cursor_sdk.step_duration_ms"] = (state.metrics["cursor_sdk.step_duration_ms"] ?? 0) + update.stepDurationMs;
19612
+ }
19613
+ state.metrics["cursor_sdk.steps"] = (state.metrics["cursor_sdk.steps"] ?? 0) + 1;
19614
+ return;
19615
+ default:
19616
+ return;
19617
+ }
19618
+ }
19619
+ async function handleToolUpdate(state, update) {
19620
+ const callId = update.callId;
19621
+ if (!callId) {
19622
+ return;
19623
+ }
19624
+ const toolCall = update.toolCall;
19625
+ const name = extractToolName(toolCall);
19626
+ const args = extractToolArgs(toolCall);
19627
+ const result = extractToolResult(toolCall);
19628
+ if (update.type === "tool-call-started" || update.type === "partial-tool-call") {
19629
+ if (!state.activeToolSpans.has(callId)) {
19630
+ state.activeToolSpans.set(
19631
+ callId,
19632
+ await startToolSpan(state, {
19633
+ args,
19634
+ callId,
19635
+ name,
19636
+ status: "running",
19637
+ toolCall
19638
+ })
19639
+ );
19640
+ }
19641
+ return;
19642
+ }
19643
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
19644
+ args,
19645
+ callId,
19646
+ name,
19647
+ status: "completed",
19648
+ toolCall
19649
+ });
19650
+ finishToolSpan(toolState, {
19651
+ error: toolCall?.status === "error" ? stringifyUnknown(result) : void 0,
19652
+ metadata: {
19653
+ "cursor_sdk.tool.status": toolCall?.status ?? "completed"
19654
+ },
19655
+ output: result
19656
+ });
19657
+ state.activeToolSpans.delete(callId);
19658
+ }
19659
+ async function handleStreamMessage2(state, message) {
19660
+ state.streamMessages.push(message);
19661
+ if (message.type === "system") {
19662
+ const systemMessage = message;
19663
+ state.metadata = {
19664
+ ...state.metadata,
19665
+ ...extractModelMetadata(systemMessage.model),
19666
+ ...systemMessage.agent_id ? { "cursor_sdk.agent_id": systemMessage.agent_id } : {},
19667
+ ...systemMessage.run_id ? { "cursor_sdk.run_id": systemMessage.run_id } : {},
19668
+ ...systemMessage.tools ? { "cursor_sdk.tools": systemMessage.tools } : {}
19669
+ };
19670
+ return;
19671
+ }
19672
+ if (message.type === "assistant") {
19673
+ const assistantMessage = message;
19674
+ for (const block of assistantMessage.message?.content ?? []) {
19675
+ if (block?.type === "text" && typeof block.text === "string") {
19676
+ state.streamText.push(block.text);
19677
+ } else if (block?.type === "tool_use" && block.id) {
19678
+ state.activeToolSpans.set(
19679
+ block.id,
19680
+ await startToolSpan(state, {
19681
+ args: block.input,
19682
+ callId: block.id,
19683
+ name: block.name,
19684
+ status: "running"
19685
+ })
19686
+ );
19687
+ }
19688
+ }
19689
+ return;
19690
+ }
19691
+ if (message.type === "tool_call") {
19692
+ await handleToolMessage(
19693
+ state,
19694
+ message
19695
+ );
19696
+ return;
19697
+ }
19698
+ if (message.type === "task" && typeof message.text === "string") {
19699
+ state.taskText.push(message.text);
19700
+ return;
19701
+ }
19702
+ if (message.type === "status" && message.status) {
19703
+ state.metadata["cursor_sdk.status"] = message.status;
19704
+ }
19705
+ }
19706
+ async function handleToolMessage(state, message) {
19707
+ const callId = message.call_id;
19708
+ if (!callId) {
19709
+ return;
19710
+ }
19711
+ if (message.status === "running") {
19712
+ if (!state.activeToolSpans.has(callId)) {
19713
+ state.activeToolSpans.set(
19714
+ callId,
19715
+ await startToolSpan(state, {
19716
+ args: message.args,
19717
+ callId,
19718
+ name: message.name,
19719
+ status: message.status,
19720
+ truncated: message.truncated
19721
+ })
19722
+ );
19723
+ }
19724
+ return;
19725
+ }
19726
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
19727
+ args: message.args,
19728
+ callId,
19729
+ name: message.name,
19730
+ status: message.status,
19731
+ truncated: message.truncated
19732
+ });
19733
+ finishToolSpan(toolState, {
19734
+ error: message.status === "error" ? stringifyUnknown(message.result) : void 0,
19735
+ metadata: {
19736
+ "cursor_sdk.tool.status": message.status
19737
+ },
19738
+ output: message.result
19739
+ });
19740
+ state.activeToolSpans.delete(callId);
19741
+ }
19742
+ async function handleConversation(state, turns) {
19743
+ state.conversationOutput = turns;
19744
+ for (const turn of turns) {
19745
+ if (turn.type === "agentConversationTurn") {
19746
+ for (const step of turn.turn?.steps ?? []) {
19747
+ await handleConversationStep(state, step);
19748
+ }
19749
+ } else if (turn.type === "shellConversationTurn") {
19750
+ const command = turn.turn?.shellCommand?.command;
19751
+ if (command) {
19752
+ const callId = `shell:${state.activeToolSpans.size}:${command}`;
19753
+ const toolState = await startToolSpan(state, {
19754
+ args: turn.turn?.shellCommand,
19755
+ callId,
19756
+ name: "shell",
19757
+ status: "completed"
19758
+ });
19759
+ finishToolSpan(toolState, {
19760
+ metadata: { "cursor_sdk.tool.status": "completed" },
19761
+ output: turn.turn?.shellOutput
19762
+ });
19763
+ }
19764
+ }
19765
+ }
19766
+ }
19767
+ async function handleConversationStep(state, step) {
19768
+ if (step.type === "assistantMessage" && typeof step.message?.text === "string") {
19769
+ state.conversationText.push(step.message.text);
19770
+ return;
19771
+ }
19772
+ if (step.type !== "toolCall") {
19773
+ return;
19774
+ }
19775
+ const toolCall = step.message;
19776
+ const callId = typeof toolCall?.callId === "string" ? toolCall.callId : `conversation-tool:${state.activeToolSpans.size}`;
19777
+ const toolState = await startToolSpan(state, {
19778
+ args: extractToolArgs(toolCall),
19779
+ callId,
19780
+ name: extractToolName(toolCall),
19781
+ status: toolCall?.status,
19782
+ toolCall
19783
+ });
19784
+ finishToolSpan(toolState, {
19785
+ error: toolCall?.status === "error" ? stringifyUnknown(toolCall.result) : void 0,
19786
+ metadata: {
19787
+ "cursor_sdk.tool.status": toolCall?.status ?? "completed"
19788
+ },
19789
+ output: extractToolResult(toolCall)
19790
+ });
19791
+ }
19792
+ function handleStepUpdate(state, step) {
19793
+ state.metrics["cursor_sdk.steps"] = (state.metrics["cursor_sdk.steps"] ?? 0) + 1;
19794
+ if (step.type) {
19795
+ const stepTypes = state.metadata["cursor_sdk.step_types"];
19796
+ if (Array.isArray(stepTypes)) {
19797
+ if (!stepTypes.includes(step.type)) {
19798
+ stepTypes.push(step.type);
19799
+ }
19800
+ } else {
19801
+ state.metadata["cursor_sdk.step_types"] = [step.type];
19802
+ }
19803
+ }
19804
+ if (step.type === "assistantMessage" && typeof step.message?.text === "string") {
19805
+ state.stepText.push(step.message.text);
19806
+ }
19807
+ }
19808
+ async function startToolSpan(state, args) {
19809
+ const name = args.name || "unknown";
19810
+ const metadata = {
19811
+ "cursor_sdk.tool.status": args.status,
19812
+ "gen_ai.tool.call.id": args.callId,
19813
+ "gen_ai.tool.name": name
19814
+ };
19815
+ if (args.truncated?.args !== void 0) {
19816
+ metadata["cursor_sdk.tool.args_truncated"] = args.truncated.args;
19817
+ }
19818
+ if (args.truncated?.result !== void 0) {
19819
+ metadata["cursor_sdk.tool.result_truncated"] = args.truncated.result;
19820
+ }
19821
+ const span = startSpan({
19822
+ event: {
19823
+ input: args.args,
19824
+ metadata
19825
+ },
19826
+ name: `tool: ${name}`,
19827
+ parent: await state.span.export(),
19828
+ spanAttributes: { type: "tool" /* TOOL */ }
19829
+ });
19830
+ let subAgentSpan;
19831
+ if (isSubAgentToolName(name)) {
19832
+ subAgentSpan = startSpan({
19833
+ event: {
19834
+ input: args.args,
19835
+ metadata: {
19836
+ "cursor_sdk.subagent.tool_call_id": args.callId,
19837
+ "gen_ai.tool.name": name
19838
+ }
19839
+ },
19840
+ name: formatSubAgentSpanName2(args.toolCall, args.args),
19841
+ parent: await span.export(),
19842
+ spanAttributes: { type: "task" /* TASK */ }
19843
+ });
19844
+ }
19845
+ return { span, subAgentSpan };
19846
+ }
19847
+ function finishToolSpan(toolState, result) {
19848
+ try {
19849
+ if (result.error) {
19850
+ safeLog(toolState.span, {
19851
+ error: result.error,
19852
+ metadata: result.metadata,
19853
+ output: result.output
19854
+ });
19855
+ if (toolState.subAgentSpan) {
19856
+ safeLog(toolState.subAgentSpan, {
19857
+ error: result.error,
19858
+ metadata: result.metadata,
19859
+ output: result.output
19860
+ });
19861
+ }
19862
+ } else {
19863
+ safeLog(toolState.span, {
19864
+ metadata: result.metadata,
19865
+ output: result.output
19866
+ });
19867
+ if (toolState.subAgentSpan) {
19868
+ safeLog(toolState.subAgentSpan, {
19869
+ metadata: result.metadata,
19870
+ output: result.output
19871
+ });
19872
+ }
19873
+ }
19874
+ } finally {
19875
+ toolState.subAgentSpan?.end();
19876
+ toolState.span.end();
19877
+ }
19878
+ }
19879
+ async function finalizeCursorRun(state, params = {}) {
19880
+ if (state.finalized) {
19881
+ return;
19882
+ }
19883
+ state.finalized = true;
19884
+ const error2 = params.error;
19885
+ const result = params.result ?? state.lastResult;
19886
+ 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);
19887
+ try {
19888
+ const metadata = {
19889
+ ...state.metadata,
19890
+ ...state.run ? extractRunMetadata(state.run) : {},
19891
+ ...result ? extractRunResultMetadata(result) : {}
19892
+ };
19893
+ if (error2) {
19894
+ safeLog(state.span, {
19895
+ error: error2 instanceof Error ? error2.message : String(error2),
19896
+ metadata,
19897
+ metrics: {
19898
+ ...cleanMetrics(state.metrics),
19899
+ ...buildDurationMetrics(state.startTime)
19900
+ },
19901
+ output
19902
+ });
19903
+ } else {
19904
+ safeLog(state.span, {
19905
+ metadata,
19906
+ metrics: {
19907
+ ...cleanMetrics(state.metrics),
19908
+ ...buildDurationMetrics(state.startTime)
19909
+ },
19910
+ output
19911
+ });
19912
+ }
19913
+ } finally {
19914
+ endOpenToolSpans(state);
19915
+ state.span.end();
19916
+ }
19917
+ }
19918
+ function endOpenToolSpans(state, error2) {
19919
+ for (const [, toolState] of state.activeToolSpans) {
19920
+ finishToolSpan(toolState, { error: error2 });
19921
+ }
19922
+ state.activeToolSpans.clear();
19923
+ }
19924
+ function sanitizeUserMessage(message) {
19925
+ if (typeof message === "string" || message === void 0) {
19926
+ return message;
19927
+ }
19928
+ return {
19929
+ ...message,
19930
+ images: message.images?.map((image) => {
19931
+ const imageRecord = image;
19932
+ return {
19933
+ ...typeof imageRecord.url === "string" ? { url: imageRecord.url } : {},
19934
+ ...typeof imageRecord.mimeType === "string" ? { mimeType: imageRecord.mimeType } : {},
19935
+ ...image.dimension ? { dimension: image.dimension } : {},
19936
+ hasData: typeof imageRecord.data === "string"
19937
+ };
19938
+ })
19939
+ };
19940
+ }
19941
+ function extractAgentOptionsMetadata(options) {
19942
+ if (!options) {
19943
+ return {};
19944
+ }
19945
+ return {
19946
+ ...extractModelMetadata(options.model),
19947
+ ...options.agentId ? { "cursor_sdk.agent_id": options.agentId } : {},
19948
+ ...options.name ? { "cursor_sdk.agent_name": options.name } : {},
19949
+ ...options.local ? {
19950
+ "cursor_sdk.runtime": "local",
19951
+ "cursor_sdk.local.cwd": Array.isArray(options.local.cwd) ? options.local.cwd.join(",") : options.local.cwd
19952
+ } : {},
19953
+ ...options.cloud ? {
19954
+ "cursor_sdk.runtime": "cloud",
19955
+ "cursor_sdk.cloud.auto_create_pr": options.cloud.autoCreatePR,
19956
+ "cursor_sdk.cloud.env_type": options.cloud.env?.type,
19957
+ "cursor_sdk.cloud.env_name": options.cloud.env?.name,
19958
+ "cursor_sdk.cloud.repos": options.cloud.repos?.map((repo) => repo.url).filter((url) => typeof url === "string")
19959
+ } : {}
19960
+ };
19961
+ }
19962
+ function extractSendMetadata(options) {
19963
+ if (!options) {
19964
+ return {};
19965
+ }
19966
+ return {
19967
+ ...extractModelMetadata(options.model),
19968
+ ...options.local?.force !== void 0 ? { "cursor_sdk.local.force": options.local.force } : {}
19969
+ };
19970
+ }
19971
+ function extractAgentMetadata(agent) {
19972
+ return {
19973
+ ...agent.agentId ? { "cursor_sdk.agent_id": agent.agentId } : {},
19974
+ ...extractModelMetadata(agent.model)
19975
+ };
19976
+ }
19977
+ function extractRunMetadata(run2) {
19978
+ if (!run2) {
19979
+ return {};
19980
+ }
19981
+ return {
19982
+ ...run2.id ? { "cursor_sdk.run_id": run2.id } : {},
19983
+ ...run2.agentId ? { "cursor_sdk.agent_id": run2.agentId } : {},
19984
+ ...run2.status ? { "cursor_sdk.status": run2.status } : {},
19985
+ ...run2.durationMs !== void 0 ? { "cursor_sdk.duration_ms": run2.durationMs } : {},
19986
+ ...extractModelMetadata(run2.model),
19987
+ ...extractGitMetadata(run2.git)
19988
+ };
19989
+ }
19990
+ function extractRunResultMetadata(result) {
19991
+ if (!result) {
19992
+ return {};
19993
+ }
19994
+ return {
19995
+ ...result.id ? { "cursor_sdk.run_id": result.id } : {},
19996
+ ...result.status ? { "cursor_sdk.status": result.status } : {},
19997
+ ...result.durationMs !== void 0 ? { "cursor_sdk.duration_ms": result.durationMs } : {},
19998
+ ...extractModelMetadata(result.model),
19999
+ ...extractGitMetadata(result.git)
20000
+ };
20001
+ }
20002
+ function extractGitMetadata(git) {
20003
+ const branches = git?.branches;
20004
+ if (!branches || branches.length === 0) {
20005
+ return {};
20006
+ }
20007
+ return {
20008
+ "cursor_sdk.git.branches": branches.map((branch) => ({
20009
+ branch: branch.branch,
20010
+ prUrl: branch.prUrl,
20011
+ repoUrl: branch.repoUrl
20012
+ }))
20013
+ };
20014
+ }
20015
+ function extractModelMetadata(model) {
20016
+ if (!model?.id) {
20017
+ return {};
20018
+ }
20019
+ return {
20020
+ model: model.id,
20021
+ "cursor_sdk.model": model.id,
20022
+ ...model.params ? { "cursor_sdk.model.params": model.params } : {}
20023
+ };
20024
+ }
20025
+ function addUsageMetrics(metrics, usage) {
20026
+ if (!usage) {
20027
+ return;
20028
+ }
20029
+ if (usage.inputTokens !== void 0) {
20030
+ metrics.prompt_tokens = (metrics.prompt_tokens ?? 0) + usage.inputTokens;
20031
+ }
20032
+ if (usage.outputTokens !== void 0) {
20033
+ metrics.completion_tokens = (metrics.completion_tokens ?? 0) + usage.outputTokens;
20034
+ }
20035
+ if (usage.cacheReadTokens !== void 0) {
20036
+ metrics.prompt_cached_tokens = (metrics.prompt_cached_tokens ?? 0) + usage.cacheReadTokens;
20037
+ }
20038
+ if (usage.cacheWriteTokens !== void 0) {
20039
+ metrics.prompt_cache_creation_tokens = (metrics.prompt_cache_creation_tokens ?? 0) + usage.cacheWriteTokens;
20040
+ }
20041
+ metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0) + (metrics.prompt_cached_tokens ?? 0) + (metrics.prompt_cache_creation_tokens ?? 0);
20042
+ }
20043
+ function buildDurationMetrics(startTime) {
20044
+ const end = getCurrentUnixTimestamp();
20045
+ return {
20046
+ duration: end - startTime,
20047
+ end,
20048
+ start: startTime
20049
+ };
20050
+ }
20051
+ function extractToolName(toolCall) {
20052
+ if (!toolCall) {
20053
+ return "unknown";
20054
+ }
20055
+ if (typeof toolCall.name === "string") {
20056
+ return toolCall.name;
20057
+ }
20058
+ if (typeof toolCall.type === "string") {
20059
+ return toolCall.type;
20060
+ }
20061
+ return "unknown";
20062
+ }
20063
+ function extractToolArgs(toolCall) {
20064
+ return toolCall && "args" in toolCall ? toolCall.args : void 0;
20065
+ }
20066
+ function extractToolResult(toolCall) {
20067
+ return toolCall && "result" in toolCall ? toolCall.result : void 0;
20068
+ }
20069
+ function isSubAgentToolName(name) {
20070
+ return name === "Agent" || name === "Task" || name === "task";
20071
+ }
20072
+ function formatSubAgentSpanName2(toolCall, args) {
20073
+ const details = toolCall ?? args;
20074
+ const description = getString(details, "description") ?? getString(details, "subagent_type") ?? getString(details, "type") ?? getString(details, "name");
20075
+ return description ? `Agent: ${description}` : "Agent: sub-agent";
20076
+ }
20077
+ function getString(obj, key) {
20078
+ const value = obj?.[key];
20079
+ return typeof value === "string" ? value : void 0;
20080
+ }
20081
+ function stringifyUnknown(value) {
20082
+ if (value instanceof Error) {
20083
+ return value.message;
20084
+ }
20085
+ if (typeof value === "string") {
20086
+ return value;
20087
+ }
20088
+ try {
20089
+ return JSON.stringify(value);
20090
+ } catch {
20091
+ return String(value);
20092
+ }
20093
+ }
20094
+ function safeLog(span, event) {
20095
+ try {
20096
+ span.log(event);
20097
+ } catch (error2) {
20098
+ logInstrumentationError("Cursor SDK span log", error2);
20099
+ }
20100
+ }
20101
+ function logInstrumentationError(context2, error2) {
20102
+ debugLogger.error(`Error processing ${context2}:`, error2);
20103
+ }
20104
+ function cleanMetrics(metrics) {
20105
+ const cleaned = {};
20106
+ for (const [key, value] of Object.entries(metrics)) {
20107
+ if (value !== void 0 && Number.isFinite(value)) {
20108
+ cleaned[key] = value;
20109
+ }
20110
+ }
20111
+ return cleaned;
20112
+ }
20113
+
20114
+ // src/instrumentation/plugins/google-genai-channels.ts
20115
+ var googleGenAIChannels = defineChannels("@google/genai", {
20116
+ generateContent: channel({
20117
+ channelName: "models.generateContent",
20118
+ kind: "async"
20119
+ }),
20120
+ generateContentStream: channel({
20121
+ channelName: "models.generateContentStream",
20122
+ kind: "async"
20123
+ }),
20124
+ embedContent: channel({
20125
+ channelName: "models.embedContent",
20126
+ kind: "async"
20127
+ })
20128
+ });
20129
+
20130
+ // src/instrumentation/plugins/google-genai-plugin.ts
20131
+ var GOOGLE_GENAI_INTERNAL_CONTEXT = {
20132
+ caller_filename: "<node-internal>",
20133
+ caller_functionname: "<node-internal>",
20134
+ caller_lineno: 0
20135
+ };
20136
+ function createWrapperParityEvent(args) {
20137
+ return {
20138
+ context: GOOGLE_GENAI_INTERNAL_CONTEXT,
20139
+ input: args.input,
20140
+ metadata: args.metadata
20141
+ };
20142
+ }
20143
+ var GoogleGenAIPlugin = class extends BasePlugin {
20144
+ onEnable() {
20145
+ this.subscribeToGoogleGenAIChannels();
20146
+ }
20147
+ onDisable() {
20148
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
20149
+ }
20150
+ subscribeToGoogleGenAIChannels() {
20151
+ this.subscribeToGenerateContentChannel();
20152
+ this.subscribeToGenerateContentStreamChannel();
20153
+ this.subscribeToEmbedContentChannel();
20154
+ }
20155
+ subscribeToGenerateContentChannel() {
20156
+ const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
20157
+ const states = /* @__PURE__ */ new WeakMap();
20158
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
20159
+ tracingChannel2,
20160
+ states,
20161
+ (event) => {
20162
+ const params = event.arguments[0];
20163
+ const input = serializeGenerateContentInput(params);
20164
+ const metadata = extractGenerateContentMetadata(params);
20165
+ const span = startSpan({
20166
+ name: "generate_content",
20167
+ spanAttributes: {
20168
+ type: "llm" /* LLM */
20169
+ },
20170
+ event: createWrapperParityEvent({ input, metadata })
20171
+ });
20172
+ return {
20173
+ span,
18892
20174
  startTime: getCurrentUnixTimestamp()
18893
20175
  };
18894
20176
  }
@@ -18921,7 +20203,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
18921
20203
  const responseMetadata = extractResponseMetadata(event.result);
18922
20204
  spanState.span.log({
18923
20205
  ...responseMetadata ? { metadata: responseMetadata } : {},
18924
- metrics: cleanMetrics(
20206
+ metrics: cleanMetrics2(
18925
20207
  extractGenerateContentMetrics(
18926
20208
  event.result,
18927
20209
  spanState.startTime
@@ -19022,7 +20304,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
19022
20304
  const output = summarizeEmbedContentOutput(event.result);
19023
20305
  spanState.span.log({
19024
20306
  ...output ? { output } : {},
19025
- metrics: cleanMetrics(
20307
+ metrics: cleanMetrics2(
19026
20308
  extractEmbedContentMetrics(event.result, spanState.startTime)
19027
20309
  )
19028
20310
  });
@@ -19119,7 +20401,7 @@ function patchGoogleGenAIStreamingResult(args) {
19119
20401
  );
19120
20402
  span.log({
19121
20403
  ...responseMetadata ? { metadata: responseMetadata } : {},
19122
- metrics: cleanMetrics(metricsWithoutEnd),
20404
+ metrics: cleanMetrics2(metricsWithoutEnd),
19123
20405
  output: options.result.aggregated
19124
20406
  });
19125
20407
  span.end(typeof end === "number" ? { endTime: end } : void 0);
@@ -19544,7 +20826,7 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
19544
20826
  }
19545
20827
  return { aggregated, metrics };
19546
20828
  }
19547
- function cleanMetrics(metrics) {
20829
+ function cleanMetrics2(metrics) {
19548
20830
  const cleaned = {};
19549
20831
  for (const [key, value] of Object.entries(metrics)) {
19550
20832
  if (value !== null && value !== void 0) {
@@ -19628,6 +20910,8 @@ var REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
19628
20910
  "stop",
19629
20911
  "stream",
19630
20912
  "temperature",
20913
+ "tool_choice",
20914
+ "tools",
19631
20915
  "top_p"
19632
20916
  ]);
19633
20917
  var RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
@@ -19890,7 +21174,10 @@ function aggregateChatCompletionChunks2(chunks) {
19890
21174
  for (const chunk of chunks) {
19891
21175
  for (const choice of chunk.choices ?? []) {
19892
21176
  const index = typeof choice.index === "number" ? choice.index : 0;
19893
- const existing = aggregatedChoices.get(index) ?? { content: "" };
21177
+ const existing = aggregatedChoices.get(index) ?? {
21178
+ content: "",
21179
+ toolCallsByIndex: /* @__PURE__ */ new Map()
21180
+ };
19894
21181
  const delta = isObject(choice.delta) ? choice.delta : void 0;
19895
21182
  const message = isObject(choice.message) ? choice.message : void 0;
19896
21183
  if (typeof delta?.content === "string") {
@@ -19906,6 +21193,10 @@ function aggregateChatCompletionChunks2(chunks) {
19906
21193
  if (choice.finish_reason !== void 0) {
19907
21194
  existing.finish_reason = choice.finish_reason;
19908
21195
  }
21196
+ const toolCallDeltas = getChatToolCallDeltas(delta) ?? getChatToolCallDeltas(message);
21197
+ if (toolCallDeltas) {
21198
+ mergeChatToolCallDeltas(existing.toolCallsByIndex, toolCallDeltas);
21199
+ }
19909
21200
  aggregatedChoices.set(index, existing);
19910
21201
  }
19911
21202
  }
@@ -19914,12 +21205,72 @@ function aggregateChatCompletionChunks2(chunks) {
19914
21205
  index,
19915
21206
  message: {
19916
21207
  content: choice.content,
19917
- role: choice.role ?? "assistant"
21208
+ role: choice.role ?? "assistant",
21209
+ ...choice.toolCallsByIndex.size > 0 ? {
21210
+ tool_calls: [...choice.toolCallsByIndex.entries()].sort(([leftIndex], [rightIndex]) => leftIndex - rightIndex).map(([, toolCall]) => toolCall)
21211
+ } : {}
19918
21212
  },
19919
21213
  ...choice.finish_reason !== void 0 ? { finish_reason: choice.finish_reason } : {}
19920
21214
  }))
19921
21215
  };
19922
21216
  }
21217
+ function getChatToolCallDeltas(value) {
21218
+ if (!Array.isArray(value?.tool_calls)) {
21219
+ return void 0;
21220
+ }
21221
+ const toolCalls = value.tool_calls.filter((toolCall) => isObject(toolCall));
21222
+ return toolCalls.length > 0 ? toolCalls : void 0;
21223
+ }
21224
+ function mergeChatToolCallDeltas(toolCallsByIndex, toolCallDeltas) {
21225
+ for (const toolDelta of toolCallDeltas) {
21226
+ const toolIndex = typeof toolDelta.index === "number" && toolDelta.index >= 0 ? toolDelta.index : 0;
21227
+ const existing = toolCallsByIndex.get(toolIndex);
21228
+ if (!existing) {
21229
+ toolCallsByIndex.set(toolIndex, createChatToolCall(toolDelta));
21230
+ continue;
21231
+ }
21232
+ mergeChatToolCall(existing, toolDelta);
21233
+ }
21234
+ }
21235
+ function createChatToolCall(toolDelta) {
21236
+ const toolFunction = isObject(toolDelta.function) ? toolDelta.function : {};
21237
+ const toolCallFunction = {
21238
+ arguments: typeof toolFunction.arguments === "string" ? toolFunction.arguments : ""
21239
+ };
21240
+ if (typeof toolFunction.name === "string") {
21241
+ toolCallFunction.name = toolFunction.name;
21242
+ }
21243
+ const toolCall = {
21244
+ function: toolCallFunction
21245
+ };
21246
+ if (typeof toolDelta.id === "string") {
21247
+ toolCall.id = toolDelta.id;
21248
+ }
21249
+ if (typeof toolDelta.type === "string") {
21250
+ toolCall.type = toolDelta.type;
21251
+ }
21252
+ return toolCall;
21253
+ }
21254
+ function mergeChatToolCall(existing, toolDelta) {
21255
+ const currentFunction = isObject(existing.function) ? existing.function : {};
21256
+ const deltaFunction = isObject(toolDelta.function) ? toolDelta.function : {};
21257
+ const currentArguments = typeof currentFunction.arguments === "string" ? currentFunction.arguments : "";
21258
+ const deltaArguments = typeof deltaFunction.arguments === "string" ? deltaFunction.arguments : "";
21259
+ if (typeof toolDelta.id === "string" && typeof existing.id !== "string") {
21260
+ existing.id = toolDelta.id;
21261
+ }
21262
+ if (typeof toolDelta.type === "string" && typeof existing.type !== "string") {
21263
+ existing.type = toolDelta.type;
21264
+ }
21265
+ const nextFunction = {
21266
+ ...currentFunction,
21267
+ arguments: `${currentArguments}${deltaArguments}`
21268
+ };
21269
+ if (typeof deltaFunction.name === "string" && typeof currentFunction.name !== "string") {
21270
+ nextFunction.name = deltaFunction.name;
21271
+ }
21272
+ existing.function = nextFunction;
21273
+ }
19923
21274
  function aggregateTextGenerationStreamChunks(chunks) {
19924
21275
  if (chunks.length === 0) {
19925
21276
  return void 0;
@@ -21964,6 +23315,8 @@ var MISTRAL_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
21964
23315
  "presence_penalty",
21965
23316
  "randomSeed",
21966
23317
  "random_seed",
23318
+ "reasoningEffort",
23319
+ "reasoning_effort",
21967
23320
  "responseFormat",
21968
23321
  "response_format",
21969
23322
  "safePrompt",
@@ -22104,6 +23457,98 @@ function extractDeltaText(content) {
22104
23457
  }).filter((part) => part.length > 0);
22105
23458
  return textParts.length > 0 ? textParts.join("") : void 0;
22106
23459
  }
23460
+ function normalizeMistralTextContentPart(part) {
23461
+ if (!isObject(part) || part.type !== "text" || typeof part.text !== "string") {
23462
+ return void 0;
23463
+ }
23464
+ return {
23465
+ type: "text",
23466
+ text: part.text
23467
+ };
23468
+ }
23469
+ function normalizeMistralThinkingContentPart(part) {
23470
+ if (!isObject(part) || part.type !== "thinking") {
23471
+ return void 0;
23472
+ }
23473
+ const thinking = Array.isArray(part.thinking) ? part.thinking.map((thinkingPart) => normalizeMistralTextContentPart(thinkingPart)).filter(
23474
+ (thinkingPart) => thinkingPart !== void 0 && typeof thinkingPart.text === "string"
23475
+ ) : [];
23476
+ return {
23477
+ type: "thinking",
23478
+ thinking
23479
+ };
23480
+ }
23481
+ function normalizeMistralContentParts(content) {
23482
+ if (!Array.isArray(content)) {
23483
+ return [];
23484
+ }
23485
+ return content.map((part) => {
23486
+ return normalizeMistralTextContentPart(part) || normalizeMistralThinkingContentPart(part);
23487
+ }).filter((part) => part !== void 0);
23488
+ }
23489
+ function mergeMistralTextSegments(left, right) {
23490
+ const merged = left.map((part) => ({ ...part }));
23491
+ for (const part of right) {
23492
+ const lastPart = merged[merged.length - 1];
23493
+ if (lastPart && lastPart.type === "text" && typeof lastPart.text === "string" && typeof part.text === "string") {
23494
+ lastPart.text += part.text;
23495
+ continue;
23496
+ }
23497
+ merged.push({ ...part });
23498
+ }
23499
+ return merged;
23500
+ }
23501
+ function mergeMistralContentParts(left, right) {
23502
+ const merged = [...(left || []).map((part) => structuredClone(part))];
23503
+ for (const part of right) {
23504
+ const lastPart = merged[merged.length - 1];
23505
+ if (part.type === "text" && lastPart?.type === "text" && typeof lastPart.text === "string" && typeof part.text === "string") {
23506
+ lastPart.text += part.text;
23507
+ continue;
23508
+ }
23509
+ if (part.type === "thinking" && lastPart?.type === "thinking" && Array.isArray(lastPart.thinking) && Array.isArray(part.thinking)) {
23510
+ lastPart.thinking = mergeMistralTextSegments(
23511
+ lastPart.thinking,
23512
+ part.thinking
23513
+ );
23514
+ continue;
23515
+ }
23516
+ merged.push(structuredClone(part));
23517
+ }
23518
+ return merged;
23519
+ }
23520
+ function appendMistralContent(accumulator, content) {
23521
+ if (typeof content === "string") {
23522
+ if (accumulator.contentParts) {
23523
+ accumulator.contentParts = mergeMistralContentParts(
23524
+ accumulator.contentParts,
23525
+ [{ type: "text", text: content }]
23526
+ );
23527
+ return;
23528
+ }
23529
+ accumulator.content = `${accumulator.content || ""}${content}`;
23530
+ return;
23531
+ }
23532
+ const normalizedContentParts = normalizeMistralContentParts(content);
23533
+ if (normalizedContentParts.length === 0) {
23534
+ return;
23535
+ }
23536
+ const hasStructuredContent = normalizedContentParts.some(
23537
+ (part) => part.type !== "text"
23538
+ );
23539
+ if (!accumulator.contentParts && !hasStructuredContent) {
23540
+ const text = extractDeltaText(content);
23541
+ if (text) {
23542
+ accumulator.content = `${accumulator.content || ""}${text}`;
23543
+ }
23544
+ return;
23545
+ }
23546
+ accumulator.contentParts = mergeMistralContentParts(
23547
+ accumulator.contentParts || (accumulator.content ? [{ type: "text", text: accumulator.content }] : []),
23548
+ normalizedContentParts
23549
+ );
23550
+ delete accumulator.content;
23551
+ }
22107
23552
  function getDeltaToolCalls(delta) {
22108
23553
  const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
22109
23554
  return toolCalls.filter((toolCall) => isObject(toolCall));
@@ -22272,10 +23717,7 @@ function aggregateMistralStreamChunks(chunks) {
22272
23717
  if (!accumulator.role && typeof delta.role === "string") {
22273
23718
  accumulator.role = delta.role;
22274
23719
  }
22275
- const deltaText = extractDeltaText(delta.content);
22276
- if (deltaText) {
22277
- accumulator.content = `${accumulator.content || ""}${deltaText}`;
22278
- }
23720
+ appendMistralContent(accumulator, delta.content);
22279
23721
  accumulator.toolCalls = mergeToolCallDeltas(
22280
23722
  accumulator.toolCalls,
22281
23723
  getDeltaToolCalls(delta)
@@ -22293,7 +23735,7 @@ function aggregateMistralStreamChunks(chunks) {
22293
23735
  index: choice.index,
22294
23736
  message: {
22295
23737
  ...choice.role ? { role: choice.role } : {},
22296
- content: choice.content ?? null,
23738
+ content: choice.contentParts ?? choice.content ?? null,
22297
23739
  ...choice.toolCalls ? { toolCalls: choice.toolCalls } : {}
22298
23740
  },
22299
23741
  ...choice.finishReason !== void 0 ? { finishReason: choice.finishReason } : {}
@@ -22532,7 +23974,7 @@ var GoogleADKPlugin = class extends BasePlugin {
22532
23974
  start: (event) => {
22533
23975
  const req = event.arguments[0] ?? {};
22534
23976
  const tool = event.self;
22535
- const toolName = extractToolName(req, tool);
23977
+ const toolName = extractToolName2(req, tool);
22536
23978
  const parentSpan = findToolParentSpan(
22537
23979
  req,
22538
23980
  this.activeAgentSpans,
@@ -22571,7 +24013,7 @@ var GoogleADKPlugin = class extends BasePlugin {
22571
24013
  metrics.duration = end - state.startTime;
22572
24014
  state.span.log({
22573
24015
  output: event.result,
22574
- metrics: cleanMetrics2(metrics)
24016
+ metrics: cleanMetrics3(metrics)
22575
24017
  });
22576
24018
  } finally {
22577
24019
  state.span.end();
@@ -22790,7 +24232,7 @@ function extractToolCallId(req) {
22790
24232
  const toolContext = req.toolContext;
22791
24233
  return toolContext?.functionCallId;
22792
24234
  }
22793
- function extractToolName(req, tool) {
24235
+ function extractToolName2(req, tool) {
22794
24236
  if (typeof tool?.name === "string" && tool.name.length > 0) {
22795
24237
  return tool.name;
22796
24238
  }
@@ -22838,7 +24280,7 @@ function finalizeRunnerSpan(state, activeRunnerSpans) {
22838
24280
  }
22839
24281
  state.span.log({
22840
24282
  output: lastEvent ? extractEventOutput(lastEvent) : void 0,
22841
- metrics: cleanMetrics2(metrics)
24283
+ metrics: cleanMetrics3(metrics)
22842
24284
  });
22843
24285
  } finally {
22844
24286
  cleanupActiveRunnerSpan(state, activeRunnerSpans);
@@ -22855,7 +24297,7 @@ function finalizeAgentSpan(state, activeAgentSpans) {
22855
24297
  metrics.duration = end - state.startTime;
22856
24298
  state.span.log({
22857
24299
  output: lastEvent ? extractEventOutput(lastEvent) : void 0,
22858
- metrics: cleanMetrics2(metrics)
24300
+ metrics: cleanMetrics3(metrics)
22859
24301
  });
22860
24302
  } finally {
22861
24303
  cleanupActiveAgentSpan(state, activeAgentSpans);
@@ -22941,7 +24383,7 @@ function populateUsageMetrics2(metrics, usage) {
22941
24383
  metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
22942
24384
  }
22943
24385
  }
22944
- function cleanMetrics2(metrics) {
24386
+ function cleanMetrics3(metrics) {
22945
24387
  const cleaned = {};
22946
24388
  for (const [key, value] of Object.entries(metrics)) {
22947
24389
  if (value !== null && value !== void 0) {
@@ -23069,6 +24511,11 @@ var CHAT_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
23069
24511
  "strictTools",
23070
24512
  "strict_tools",
23071
24513
  "temperature",
24514
+ "thinking",
24515
+ "thinkingTokenBudget",
24516
+ "thinkingType",
24517
+ "thinking_token_budget",
24518
+ "thinking_type",
23072
24519
  "toolChoice",
23073
24520
  "tool_choice"
23074
24521
  ]);
@@ -23289,6 +24736,11 @@ function mergeUsageMetrics(metrics, usage) {
23289
24736
  "tokens",
23290
24737
  tokenContainer.totalTokens ?? tokenContainer.total_tokens
23291
24738
  );
24739
+ setMetricIfNumber(
24740
+ metrics,
24741
+ "reasoning_tokens",
24742
+ tokenContainer.reasoningTokens ?? tokenContainer.reasoning_tokens ?? tokenContainer.thinkingTokens ?? tokenContainer.thinking_tokens
24743
+ );
23292
24744
  }
23293
24745
  const billedUnits = (isObject(source.billedUnits) ? source.billedUnits : void 0) || (isObject(source.billed_units) ? source.billed_units : void 0);
23294
24746
  if (billedUnits) {
@@ -23369,13 +24821,87 @@ function extractV8DeltaText(chunk) {
23369
24821
  }
23370
24822
  return void 0;
23371
24823
  }
24824
+ function getV8ContentIndex(chunk) {
24825
+ return typeof chunk.index === "number" ? chunk.index : 0;
24826
+ }
24827
+ function toContentBlockType(value) {
24828
+ return value === "text" || value === "thinking" ? value : void 0;
24829
+ }
24830
+ function getOrCreateContentBlock(contentBlocksByIndex, contentBlockOrder, index) {
24831
+ if (!contentBlockOrder.includes(index)) {
24832
+ contentBlockOrder.push(index);
24833
+ }
24834
+ if (!(index in contentBlocksByIndex)) {
24835
+ contentBlocksByIndex[index] = {
24836
+ text: "",
24837
+ thinking: ""
24838
+ };
24839
+ }
24840
+ return contentBlocksByIndex[index];
24841
+ }
24842
+ function appendV8ContentBlock(contentBlocksByIndex, contentBlockOrder, index, content) {
24843
+ if (typeof content === "string") {
24844
+ const block2 = getOrCreateContentBlock(
24845
+ contentBlocksByIndex,
24846
+ contentBlockOrder,
24847
+ index
24848
+ );
24849
+ block2.type ??= "text";
24850
+ block2.text += content;
24851
+ return;
24852
+ }
24853
+ if (!isObject(content)) {
24854
+ return;
24855
+ }
24856
+ const block = getOrCreateContentBlock(
24857
+ contentBlocksByIndex,
24858
+ contentBlockOrder,
24859
+ index
24860
+ );
24861
+ const contentType = toContentBlockType(content.type);
24862
+ if (contentType) {
24863
+ block.type = contentType;
24864
+ }
24865
+ if (typeof content.text === "string") {
24866
+ block.type ??= "text";
24867
+ block.text += content.text;
24868
+ }
24869
+ if (typeof content.thinking === "string") {
24870
+ block.type ??= "thinking";
24871
+ block.thinking += content.thinking;
24872
+ }
24873
+ }
24874
+ function serializeAggregatedContentBlocks(contentBlocksByIndex, contentBlockOrder) {
24875
+ return contentBlockOrder.sort((left, right) => left - right).flatMap((index) => {
24876
+ const block = contentBlocksByIndex[index];
24877
+ if (!block) {
24878
+ return [];
24879
+ }
24880
+ if (block.type === "thinking" && block.thinking.length > 0) {
24881
+ return [{ type: "thinking", thinking: block.thinking }];
24882
+ }
24883
+ if (block.text.length > 0) {
24884
+ return [{ type: "text", text: block.text }];
24885
+ }
24886
+ if (block.thinking.length > 0) {
24887
+ return [{ type: "thinking", thinking: block.thinking }];
24888
+ }
24889
+ return [];
24890
+ });
24891
+ }
24892
+ function hasThinkingContent(contentBlocks) {
24893
+ return contentBlocks.some((block) => block.type === "thinking");
24894
+ }
23372
24895
  function aggregateCohereChatStreamChunks(chunks) {
23373
24896
  const textDeltas = [];
24897
+ const contentBlocksByIndex = {};
24898
+ const contentBlockOrder = [];
23374
24899
  const toolCallsByIndex = {};
23375
24900
  const toolCallOrder = [];
23376
24901
  let terminalResponse;
23377
24902
  let role;
23378
24903
  let finishReason;
24904
+ let toolPlan = "";
23379
24905
  let metadata = {};
23380
24906
  let metrics = {};
23381
24907
  for (const chunk of chunks) {
@@ -23433,12 +24959,36 @@ function aggregateCohereChatStreamChunks(chunks) {
23433
24959
  continue;
23434
24960
  }
23435
24961
  if (eventType === "content-delta") {
24962
+ appendV8ContentBlock(
24963
+ contentBlocksByIndex,
24964
+ contentBlockOrder,
24965
+ getV8ContentIndex(chunk),
24966
+ isObject(chunk.delta) && isObject(chunk.delta.message) ? chunk.delta.message.content : void 0
24967
+ );
23436
24968
  const text = extractV8DeltaText(chunk);
23437
24969
  if (text) {
23438
24970
  textDeltas.push(text);
23439
24971
  }
23440
24972
  continue;
23441
24973
  }
24974
+ if (eventType === "content-start") {
24975
+ appendV8ContentBlock(
24976
+ contentBlocksByIndex,
24977
+ contentBlockOrder,
24978
+ getV8ContentIndex(chunk),
24979
+ isObject(chunk.delta) && isObject(chunk.delta.message) ? chunk.delta.message.content : void 0
24980
+ );
24981
+ continue;
24982
+ }
24983
+ if (eventType === "tool-plan-delta") {
24984
+ if (isObject(chunk.delta) && isObject(chunk.delta.message)) {
24985
+ 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;
24986
+ if (deltaToolPlan) {
24987
+ toolPlan += deltaToolPlan;
24988
+ }
24989
+ }
24990
+ continue;
24991
+ }
23442
24992
  if (eventType === "tool-call-start") {
23443
24993
  const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
23444
24994
  Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
@@ -23492,13 +25042,26 @@ function aggregateCohereChatStreamChunks(chunks) {
23492
25042
  }
23493
25043
  }
23494
25044
  const mergedToolCalls = toolCallOrder.sort((left, right) => left - right).map((index) => toolCallsByIndex[index]).filter((toolCall) => isObject(toolCall));
25045
+ const aggregatedContentBlocks = serializeAggregatedContentBlocks(
25046
+ contentBlocksByIndex,
25047
+ contentBlockOrder
25048
+ );
23495
25049
  let output = extractCohereChatOutput(terminalResponse);
23496
25050
  if (output === void 0) {
23497
25051
  const mergedText = textDeltas.join("");
23498
- if (mergedToolCalls.length > 0 || role || mergedText.length > 0) {
25052
+ const shouldUseStructuredContent = hasThinkingContent(aggregatedContentBlocks) || toolPlan.length > 0;
25053
+ if (shouldUseStructuredContent) {
25054
+ output = {
25055
+ ...role ? { role } : {},
25056
+ ...aggregatedContentBlocks.length > 0 ? { content: aggregatedContentBlocks } : {},
25057
+ ...toolPlan.length > 0 ? { toolPlan } : {},
25058
+ ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
25059
+ };
25060
+ } else if (mergedToolCalls.length > 0 || role || mergedText.length > 0 || aggregatedContentBlocks.length > 0) {
25061
+ const textContent = mergedText.length > 0 ? mergedText : aggregatedContentBlocks[0]?.type === "text" ? aggregatedContentBlocks[0].text : void 0;
23499
25062
  output = {
23500
25063
  ...role ? { role } : {},
23501
- ...mergedText.length > 0 ? { content: mergedText } : {},
25064
+ ...textContent ? { content: textContent } : {},
23502
25065
  ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
23503
25066
  };
23504
25067
  }
@@ -23516,6 +25079,98 @@ function aggregateCohereChatStreamChunks(chunks) {
23516
25079
  };
23517
25080
  }
23518
25081
 
25082
+ // src/instrumentation/plugins/groq-channels.ts
25083
+ var groqChannels = defineChannels("groq-sdk", {
25084
+ chatCompletionsCreate: channel({
25085
+ channelName: "chat.completions.create",
25086
+ kind: "async"
25087
+ }),
25088
+ embeddingsCreate: channel(
25089
+ {
25090
+ channelName: "embeddings.create",
25091
+ kind: "async"
25092
+ }
25093
+ )
25094
+ });
25095
+
25096
+ // src/instrumentation/plugins/groq-plugin.ts
25097
+ var GroqPlugin = class extends BasePlugin {
25098
+ onEnable() {
25099
+ this.unsubscribers.push(
25100
+ traceStreamingChannel(groqChannels.chatCompletionsCreate, {
25101
+ name: "groq.chat.completions.create",
25102
+ type: "llm" /* LLM */,
25103
+ extractInput: ([params]) => {
25104
+ const { messages, ...metadata } = params;
25105
+ return {
25106
+ input: processInputAttachments(messages),
25107
+ metadata: { ...metadata, provider: "groq" }
25108
+ };
25109
+ },
25110
+ extractOutput: (result) => result?.choices,
25111
+ extractMetrics: (result, startTime) => {
25112
+ const metrics = parseGroqMetrics(result);
25113
+ if (startTime) {
25114
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
25115
+ }
25116
+ return metrics;
25117
+ },
25118
+ aggregateChunks: aggregateGroqChatCompletionChunks
25119
+ })
25120
+ );
25121
+ this.unsubscribers.push(
25122
+ traceAsyncChannel(groqChannels.embeddingsCreate, {
25123
+ name: "groq.embeddings.create",
25124
+ type: "llm" /* LLM */,
25125
+ extractInput: ([params]) => {
25126
+ const { input, ...metadata } = params;
25127
+ return {
25128
+ input,
25129
+ metadata: { ...metadata, provider: "groq" }
25130
+ };
25131
+ },
25132
+ extractOutput: (result) => {
25133
+ const embedding = result?.data?.[0]?.embedding;
25134
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
25135
+ },
25136
+ extractMetrics: (result) => parseGroqMetrics(result)
25137
+ })
25138
+ );
25139
+ }
25140
+ onDisable() {
25141
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
25142
+ }
25143
+ };
25144
+ function parseGroqMetrics(result) {
25145
+ const metrics = parseMetricsFromUsage(result?.usage);
25146
+ const xGroq = result?.x_groq;
25147
+ if (!xGroq || typeof xGroq !== "object") {
25148
+ return metrics;
25149
+ }
25150
+ const extraUsage = "usage" in xGroq ? xGroq.usage : void 0;
25151
+ if (!extraUsage || typeof extraUsage !== "object") {
25152
+ return metrics;
25153
+ }
25154
+ const dramCachedTokens = extraUsage["dram_cached_tokens"];
25155
+ const sramCachedTokens = extraUsage["sram_cached_tokens"];
25156
+ return {
25157
+ ...metrics,
25158
+ ...typeof dramCachedTokens === "number" ? { dram_cached_tokens: dramCachedTokens } : {},
25159
+ ...typeof sramCachedTokens === "number" ? { sram_cached_tokens: sramCachedTokens } : {}
25160
+ };
25161
+ }
25162
+ function aggregateGroqChatCompletionChunks(chunks, streamResult, endEvent) {
25163
+ const aggregated = aggregateChatCompletionChunks(
25164
+ chunks,
25165
+ streamResult,
25166
+ endEvent
25167
+ );
25168
+ return {
25169
+ metrics: aggregated.metrics,
25170
+ output: aggregated.output
25171
+ };
25172
+ }
25173
+
23519
25174
  // src/instrumentation/braintrust-plugin.ts
23520
25175
  var BraintrustPlugin = class extends BasePlugin {
23521
25176
  config;
@@ -23523,6 +25178,7 @@ var BraintrustPlugin = class extends BasePlugin {
23523
25178
  anthropicPlugin = null;
23524
25179
  aiSDKPlugin = null;
23525
25180
  claudeAgentSDKPlugin = null;
25181
+ cursorSDKPlugin = null;
23526
25182
  googleGenAIPlugin = null;
23527
25183
  huggingFacePlugin = null;
23528
25184
  openRouterPlugin = null;
@@ -23530,6 +25186,7 @@ var BraintrustPlugin = class extends BasePlugin {
23530
25186
  mistralPlugin = null;
23531
25187
  googleADKPlugin = null;
23532
25188
  coherePlugin = null;
25189
+ groqPlugin = null;
23533
25190
  constructor(config3 = {}) {
23534
25191
  super();
23535
25192
  this.config = config3;
@@ -23552,6 +25209,10 @@ var BraintrustPlugin = class extends BasePlugin {
23552
25209
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
23553
25210
  this.claudeAgentSDKPlugin.enable();
23554
25211
  }
25212
+ if (integrations.cursorSDK !== false && integrations.cursor !== false) {
25213
+ this.cursorSDKPlugin = new CursorSDKPlugin();
25214
+ this.cursorSDKPlugin.enable();
25215
+ }
23555
25216
  if (integrations.googleGenAI !== false && integrations.google !== false) {
23556
25217
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
23557
25218
  this.googleGenAIPlugin.enable();
@@ -23580,6 +25241,10 @@ var BraintrustPlugin = class extends BasePlugin {
23580
25241
  this.coherePlugin = new CoherePlugin();
23581
25242
  this.coherePlugin.enable();
23582
25243
  }
25244
+ if (integrations.groq !== false) {
25245
+ this.groqPlugin = new GroqPlugin();
25246
+ this.groqPlugin.enable();
25247
+ }
23583
25248
  }
23584
25249
  onDisable() {
23585
25250
  if (this.openaiPlugin) {
@@ -23598,6 +25263,10 @@ var BraintrustPlugin = class extends BasePlugin {
23598
25263
  this.claudeAgentSDKPlugin.disable();
23599
25264
  this.claudeAgentSDKPlugin = null;
23600
25265
  }
25266
+ if (this.cursorSDKPlugin) {
25267
+ this.cursorSDKPlugin.disable();
25268
+ this.cursorSDKPlugin = null;
25269
+ }
23601
25270
  if (this.googleGenAIPlugin) {
23602
25271
  this.googleGenAIPlugin.disable();
23603
25272
  this.googleGenAIPlugin = null;
@@ -23626,6 +25295,10 @@ var BraintrustPlugin = class extends BasePlugin {
23626
25295
  this.coherePlugin.disable();
23627
25296
  this.coherePlugin = null;
23628
25297
  }
25298
+ if (this.groqPlugin) {
25299
+ this.groqPlugin.disable();
25300
+ this.groqPlugin = null;
25301
+ }
23629
25302
  }
23630
25303
  };
23631
25304
 
@@ -23699,6 +25372,8 @@ var PluginRegistry = class {
23699
25372
  google: true,
23700
25373
  huggingface: true,
23701
25374
  claudeAgentSDK: true,
25375
+ cursor: true,
25376
+ cursorSDK: true,
23702
25377
  openrouter: true,
23703
25378
  openrouterAgent: true,
23704
25379
  mistral: true,
@@ -23715,7 +25390,11 @@ var PluginRegistry = class {
23715
25390
  if (disabledList) {
23716
25391
  const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
23717
25392
  for (const sdk of disabled) {
23718
- integrations[sdk] = false;
25393
+ if (sdk === "cursor-sdk") {
25394
+ integrations.cursorSDK = false;
25395
+ } else {
25396
+ integrations[sdk] = false;
25397
+ }
23719
25398
  }
23720
25399
  }
23721
25400
  return { integrations };
@@ -25751,6 +27430,8 @@ async function getDataset(state, data) {
25751
27430
  state,
25752
27431
  project: data.project_name,
25753
27432
  dataset: data.dataset_name,
27433
+ version: data.dataset_version ?? void 0,
27434
+ environment: data.dataset_environment ?? void 0,
25754
27435
  _internal_btql: data._internal_btql ?? void 0
25755
27436
  });
25756
27437
  } else if ("dataset_id" in data) {
@@ -25762,6 +27443,8 @@ async function getDataset(state, data) {
25762
27443
  state,
25763
27444
  projectId: datasetInfo.projectId,
25764
27445
  dataset: datasetInfo.dataset,
27446
+ version: data.dataset_version ?? void 0,
27447
+ environment: data.dataset_environment ?? void 0,
25765
27448
  _internal_btql: data._internal_btql ?? void 0
25766
27449
  });
25767
27450
  } else {
@@ -26303,7 +27986,7 @@ async function collectFiles(inputPath, mode) {
26303
27986
  const prefix = mode === "eval" ? ".eval" : "";
26304
27987
  console.warn(
26305
27988
  warning2(
26306
- `Reading ${inputPath} because it was specified directly. Rename it to end in ${prefix}.ts or .${prefix}.js to include it automatically when you specify a directory.`
27989
+ `Reading ${inputPath} because it was specified directly. Rename it to end in ${prefix}.ts or ${prefix}.js to include it automatically when you specify a directory.`
26307
27990
  )
26308
27991
  );
26309
27992
  }