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/browser.js CHANGED
@@ -159,8 +159,10 @@ __export(browser_exports, {
159
159
  wrapAnthropic: () => wrapAnthropic,
160
160
  wrapClaudeAgentSDK: () => wrapClaudeAgentSDK,
161
161
  wrapCohere: () => wrapCohere,
162
+ wrapCursorSDK: () => wrapCursorSDK,
162
163
  wrapGoogleADK: () => wrapGoogleADK,
163
164
  wrapGoogleGenAI: () => wrapGoogleGenAI,
165
+ wrapGroq: () => wrapGroq,
164
166
  wrapHuggingFace: () => wrapHuggingFace,
165
167
  wrapMastraAgent: () => wrapMastraAgent,
166
168
  wrapMistral: () => wrapMistral,
@@ -1981,6 +1983,7 @@ var TopicMapData = import_v36.z.object({
1981
1983
  report_key: import_v36.z.string().optional(),
1982
1984
  topic_names: import_v36.z.record(import_v36.z.string()).optional(),
1983
1985
  generation_settings: TopicMapGenerationSettings.optional(),
1986
+ disable_reconciliation: import_v36.z.boolean().optional(),
1984
1987
  distance_threshold: import_v36.z.number().optional()
1985
1988
  });
1986
1989
  var BatchedFacetData = import_v36.z.object({
@@ -2311,28 +2314,6 @@ var EnvVar = import_v36.z.object({
2311
2314
  secret_type: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2312
2315
  secret_category: import_v36.z.enum(["env_var", "ai_provider", "sandbox_provider"]).optional().default("env_var")
2313
2316
  });
2314
- var EvalStatusPageTheme = import_v36.z.enum(["light", "dark"]);
2315
- var EvalStatusPageConfig = import_v36.z.object({
2316
- score_columns: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
2317
- metric_columns: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
2318
- grouping_field: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
2319
- filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
2320
- sort_by: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
2321
- sort_order: import_v36.z.union([import_v36.z.enum(["asc", "desc"]), import_v36.z.null()]),
2322
- api_key: import_v36.z.union([import_v36.z.string(), import_v36.z.null()])
2323
- }).partial();
2324
- var EvalStatusPage = import_v36.z.object({
2325
- id: import_v36.z.string().uuid(),
2326
- project_id: import_v36.z.string().uuid(),
2327
- user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2328
- created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2329
- deleted_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2330
- name: import_v36.z.string(),
2331
- description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2332
- logo_url: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2333
- theme: EvalStatusPageTheme,
2334
- config: EvalStatusPageConfig
2335
- });
2336
2317
  var RepoInfo = import_v36.z.union([
2337
2318
  import_v36.z.object({
2338
2319
  commit: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
@@ -2359,6 +2340,15 @@ var Experiment = import_v36.z.object({
2359
2340
  deleted_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2360
2341
  dataset_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2361
2342
  dataset_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2343
+ internal_metadata: import_v36.z.union([
2344
+ import_v36.z.object({
2345
+ dataset_filter: import_v36.z.union([
2346
+ import_v36.z.object({}).partial().passthrough(),
2347
+ import_v36.z.null()
2348
+ ])
2349
+ }).partial().passthrough(),
2350
+ import_v36.z.null()
2351
+ ]).optional(),
2362
2352
  parameters_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2363
2353
  parameters_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2364
2354
  public: import_v36.z.boolean(),
@@ -3095,14 +3085,21 @@ var ProjectAutomation = import_v36.z.object({
3095
3085
  import_v36.z.object({ type: import_v36.z.literal("log_spans") }),
3096
3086
  import_v36.z.object({ type: import_v36.z.literal("btql_query"), btql_query: import_v36.z.string() })
3097
3087
  ]),
3088
+ scope: import_v36.z.union([SpanScope, TraceScope, GroupScope, import_v36.z.null()]).optional(),
3098
3089
  export_path: import_v36.z.string(),
3099
3090
  format: import_v36.z.enum(["jsonl", "parquet"]),
3100
3091
  interval_seconds: import_v36.z.number().gte(1).lte(2592e3),
3101
- credentials: import_v36.z.object({
3102
- type: import_v36.z.literal("aws_iam"),
3103
- role_arn: import_v36.z.string(),
3104
- external_id: import_v36.z.string()
3105
- }),
3092
+ credentials: import_v36.z.union([
3093
+ import_v36.z.object({
3094
+ type: import_v36.z.literal("aws_iam"),
3095
+ role_arn: import_v36.z.string(),
3096
+ external_id: import_v36.z.string()
3097
+ }),
3098
+ import_v36.z.object({
3099
+ type: import_v36.z.literal("gcp_service_account"),
3100
+ service_account_email: import_v36.z.string()
3101
+ })
3102
+ ]),
3106
3103
  batch_size: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
3107
3104
  }),
3108
3105
  import_v36.z.object({
@@ -3482,7 +3479,7 @@ var ViewOptions = import_v36.z.union([
3482
3479
  import_v36.z.object({ from: import_v36.z.string(), to: import_v36.z.string() }),
3483
3480
  import_v36.z.null()
3484
3481
  ]),
3485
- queryShape: import_v36.z.union([import_v36.z.enum(["traces", "spans"]), import_v36.z.null()]),
3482
+ queryShape: import_v36.z.union([import_v36.z.enum(["traces", "spans", "topics"]), import_v36.z.null()]),
3486
3483
  cluster: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3487
3484
  freezeColumns: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()])
3488
3485
  }).partial(),
@@ -4496,6 +4493,19 @@ var RESET_CONTEXT_MANAGER_STATE = Symbol.for(
4496
4493
  "braintrust.resetContextManagerState"
4497
4494
  );
4498
4495
  var DEFAULT_MAX_REQUEST_SIZE = 6 * 1024 * 1024;
4496
+ var datasetSnapshotRegisterResponseSchema = import_v38.z.object({
4497
+ dataset_snapshot: DatasetSnapshot,
4498
+ found_existing: import_v38.z.boolean().optional()
4499
+ });
4500
+ var datasetRestorePreviewResultSchema = import_v38.z.object({
4501
+ rows_to_restore: import_v38.z.number(),
4502
+ rows_to_delete: import_v38.z.number()
4503
+ });
4504
+ var datasetRestoreResultSchema = import_v38.z.object({
4505
+ xact_id: import_v38.z.string().nullable(),
4506
+ rows_restored: import_v38.z.number(),
4507
+ rows_deleted: import_v38.z.number()
4508
+ });
4499
4509
  var parametersRowSchema = import_v38.z.object({
4500
4510
  id: import_v38.z.string().uuid(),
4501
4511
  _xact_id: import_v38.z.string(),
@@ -6717,6 +6727,33 @@ Error: ${errorText}`;
6717
6727
  this.queue.enforceQueueSizeLimit(enforce);
6718
6728
  }
6719
6729
  };
6730
+ function isDatasetSnapshotNameLookup(lookup) {
6731
+ return "snapshotName" in lookup;
6732
+ }
6733
+ function assertDatasetSnapshotLookup(lookup) {
6734
+ const hasSnapshotName = lookup.snapshotName !== void 0;
6735
+ const hasXactId = lookup.xactId !== void 0;
6736
+ if (hasSnapshotName === hasXactId) {
6737
+ throw new Error("Exactly one of snapshotName or xactId must be provided");
6738
+ }
6739
+ }
6740
+ function getExperimentDatasetFilter({
6741
+ dataset,
6742
+ _internal_btql
6743
+ }) {
6744
+ if (_internal_btql !== void 0) {
6745
+ return _internal_btql;
6746
+ }
6747
+ if (!(dataset instanceof Dataset2)) {
6748
+ return void 0;
6749
+ }
6750
+ const datasetFilter = Reflect.get(dataset, "_internal_btql");
6751
+ return isObject(datasetFilter) ? datasetFilter : void 0;
6752
+ }
6753
+ function getInternalBtqlLimit(internalBtql) {
6754
+ const limit = internalBtql?.["limit"];
6755
+ return typeof limit === "number" ? limit : void 0;
6756
+ }
6720
6757
  function init(projectOrOptions, optionalOptions) {
6721
6758
  const options = (() => {
6722
6759
  if (typeof projectOrOptions === "string") {
@@ -6735,6 +6772,7 @@ function init(projectOrOptions, optionalOptions) {
6735
6772
  experiment,
6736
6773
  description,
6737
6774
  dataset,
6775
+ _internal_btql,
6738
6776
  parameters,
6739
6777
  baseExperiment,
6740
6778
  isPublic,
@@ -6843,16 +6881,24 @@ function init(projectOrOptions, optionalOptions) {
6843
6881
  args["ancestor_commits"] = await isomorph_default.getPastNAncestors();
6844
6882
  }
6845
6883
  if (dataset !== void 0) {
6846
- if ("id" in dataset && typeof dataset.id === "string" && !("__braintrust_dataset_marker" in dataset)) {
6847
- args["dataset_id"] = dataset.id;
6848
- if ("version" in dataset && dataset.version !== void 0) {
6849
- args["dataset_version"] = dataset.version;
6850
- }
6851
- } else {
6852
- args["dataset_id"] = await dataset.id;
6853
- args["dataset_version"] = await dataset.version();
6884
+ const datasetSelection = await serializeDatasetForExperiment({
6885
+ dataset,
6886
+ state
6887
+ });
6888
+ args["dataset_id"] = datasetSelection.datasetId;
6889
+ if (datasetSelection.datasetVersion !== void 0) {
6890
+ args["dataset_version"] = datasetSelection.datasetVersion;
6854
6891
  }
6855
6892
  }
6893
+ const datasetFilter = getExperimentDatasetFilter({
6894
+ dataset,
6895
+ _internal_btql
6896
+ });
6897
+ if (datasetFilter !== void 0) {
6898
+ args["internal_metadata"] = {
6899
+ dataset_filter: datasetFilter
6900
+ };
6901
+ }
6856
6902
  if (parameters !== void 0) {
6857
6903
  if (RemoteEvalParameters.isParameters(parameters)) {
6858
6904
  args["parameters_id"] = parameters.id;
@@ -6906,7 +6952,7 @@ function init(projectOrOptions, optionalOptions) {
6906
6952
  const ret = new Experiment2(
6907
6953
  state,
6908
6954
  lazyMetadata,
6909
- dataset !== void 0 && "version" in dataset ? dataset : void 0
6955
+ dataset !== void 0 ? dataset : void 0
6910
6956
  );
6911
6957
  if (options.setCurrent ?? true) {
6912
6958
  state.currentExperiment = ret;
@@ -6942,6 +6988,153 @@ function withLogger(callback, options = {}) {
6942
6988
  const logger = initLogger(options);
6943
6989
  return callback(logger);
6944
6990
  }
6991
+ async function getDatasetSnapshots(params) {
6992
+ const { state, datasetId } = params;
6993
+ return DatasetSnapshot.array().parse(
6994
+ await state.appConn().post_json("api/dataset_snapshot/get", {
6995
+ dataset_id: datasetId,
6996
+ ..."snapshotName" in params ? { name: params.snapshotName } : {},
6997
+ ..."xactId" in params ? { xact_id: params.xactId } : {}
6998
+ })
6999
+ );
7000
+ }
7001
+ async function getDatasetSnapshot(params) {
7002
+ assertDatasetSnapshotLookup(params);
7003
+ const snapshots = await getDatasetSnapshots(params);
7004
+ if (snapshots.length > 1) {
7005
+ throw new Error(
7006
+ 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}`
7007
+ );
7008
+ }
7009
+ return snapshots[0];
7010
+ }
7011
+ function normalizeDatasetSelection({
7012
+ version,
7013
+ environment,
7014
+ snapshotName
7015
+ }) {
7016
+ if (version !== void 0) {
7017
+ return { version };
7018
+ }
7019
+ if (snapshotName !== void 0) {
7020
+ return { snapshotName };
7021
+ }
7022
+ if (environment !== void 0) {
7023
+ return { environment };
7024
+ }
7025
+ return {};
7026
+ }
7027
+ async function resolveDatasetSnapshotName({
7028
+ state,
7029
+ datasetId,
7030
+ snapshotName
7031
+ }) {
7032
+ const match = await getDatasetSnapshot({
7033
+ state,
7034
+ datasetId,
7035
+ snapshotName
7036
+ });
7037
+ if (match === void 0) {
7038
+ throw new Error(
7039
+ `Dataset snapshot "${snapshotName}" not found for ${datasetId}`
7040
+ );
7041
+ }
7042
+ return match.xact_id;
7043
+ }
7044
+ async function resolveDatasetSnapshotNameForMetadata({
7045
+ state,
7046
+ lazyMetadata,
7047
+ snapshotName
7048
+ }) {
7049
+ const metadata = await lazyMetadata.get();
7050
+ return await resolveDatasetSnapshotName({
7051
+ state,
7052
+ datasetId: metadata.dataset.id,
7053
+ snapshotName
7054
+ });
7055
+ }
7056
+ async function resolveDatasetEnvironment({
7057
+ state,
7058
+ datasetId,
7059
+ environment
7060
+ }) {
7061
+ const environmentObjectPath = `environment-object/dataset/${datasetId}/${encodeURIComponent(environment)}`;
7062
+ const response = state.orgName == null ? await state.apiConn().get_json(environmentObjectPath) : await state.apiConn().get_json(environmentObjectPath, {
7063
+ org_name: state.orgName
7064
+ });
7065
+ return import_v38.z.object({ object_version: import_v38.z.string() }).parse(response).object_version;
7066
+ }
7067
+ async function resolveDatasetEnvironmentForMetadata({
7068
+ state,
7069
+ lazyMetadata,
7070
+ environment
7071
+ }) {
7072
+ const metadata = await lazyMetadata.get();
7073
+ return await resolveDatasetEnvironment({
7074
+ state,
7075
+ datasetId: metadata.dataset.id,
7076
+ environment
7077
+ });
7078
+ }
7079
+ async function serializeDatasetForExperiment({
7080
+ dataset,
7081
+ state
7082
+ }) {
7083
+ if (!Dataset2.isDataset(dataset)) {
7084
+ const selection2 = normalizeDatasetSelection(dataset);
7085
+ if (selection2.version !== void 0) {
7086
+ return {
7087
+ datasetId: dataset.id,
7088
+ datasetVersion: selection2.version
7089
+ };
7090
+ }
7091
+ if (selection2.snapshotName !== void 0) {
7092
+ return {
7093
+ datasetId: dataset.id,
7094
+ datasetVersion: await resolveDatasetSnapshotName({
7095
+ state,
7096
+ datasetId: dataset.id,
7097
+ snapshotName: selection2.snapshotName
7098
+ })
7099
+ };
7100
+ }
7101
+ if (selection2.environment !== void 0) {
7102
+ return {
7103
+ datasetId: dataset.id,
7104
+ datasetVersion: await resolveDatasetEnvironment({
7105
+ state,
7106
+ datasetId: dataset.id,
7107
+ environment: selection2.environment
7108
+ })
7109
+ };
7110
+ }
7111
+ return {
7112
+ datasetId: dataset.id
7113
+ };
7114
+ }
7115
+ const evalData = await dataset.toEvalData();
7116
+ const selection = normalizeDatasetSelection({
7117
+ version: evalData.dataset_version,
7118
+ environment: evalData.dataset_environment,
7119
+ snapshotName: evalData.dataset_snapshot_name
7120
+ });
7121
+ if (selection.version !== void 0) {
7122
+ return {
7123
+ datasetId: evalData.dataset_id,
7124
+ datasetVersion: selection.version
7125
+ };
7126
+ }
7127
+ const datasetVersion = await dataset.version();
7128
+ if (datasetVersion !== void 0) {
7129
+ return {
7130
+ datasetId: evalData.dataset_id,
7131
+ datasetVersion
7132
+ };
7133
+ }
7134
+ return {
7135
+ datasetId: evalData.dataset_id
7136
+ };
7137
+ }
6945
7138
  function initDataset(projectOrOptions, optionalOptions) {
6946
7139
  const options = (() => {
6947
7140
  if (typeof projectOrOptions === "string") {
@@ -6960,6 +7153,8 @@ function initDataset(projectOrOptions, optionalOptions) {
6960
7153
  dataset,
6961
7154
  description,
6962
7155
  version,
7156
+ snapshotName,
7157
+ environment,
6963
7158
  appUrl,
6964
7159
  apiKey,
6965
7160
  orgName,
@@ -6971,6 +7166,14 @@ function initDataset(projectOrOptions, optionalOptions) {
6971
7166
  state: stateArg,
6972
7167
  _internal_btql
6973
7168
  } = options;
7169
+ const selection = normalizeDatasetSelection({
7170
+ version,
7171
+ environment,
7172
+ snapshotName
7173
+ });
7174
+ const normalizedVersion = selection.version;
7175
+ const normalizedEnvironment = selection.environment;
7176
+ const normalizedSnapshotName = selection.snapshotName;
6974
7177
  const state = stateArg ?? _globalState;
6975
7178
  const lazyMetadata = new LazyValue(
6976
7179
  async () => {
@@ -7004,13 +7207,38 @@ function initDataset(projectOrOptions, optionalOptions) {
7004
7207
  };
7005
7208
  }
7006
7209
  );
7007
- return new Dataset2(
7210
+ const resolvedVersion = normalizedVersion !== void 0 ? normalizedVersion : normalizedSnapshotName !== void 0 ? new LazyValue(async () => {
7211
+ return await resolveDatasetSnapshotNameForMetadata({
7212
+ state,
7213
+ lazyMetadata,
7214
+ snapshotName: normalizedSnapshotName
7215
+ });
7216
+ }) : normalizedEnvironment !== void 0 ? new LazyValue(async () => {
7217
+ return await resolveDatasetEnvironmentForMetadata({
7218
+ state,
7219
+ lazyMetadata,
7220
+ environment: normalizedEnvironment
7221
+ });
7222
+ }) : void 0;
7223
+ const datasetObject = new Dataset2(
7008
7224
  stateArg ?? _globalState,
7009
7225
  lazyMetadata,
7010
- version,
7226
+ typeof resolvedVersion === "string" ? resolvedVersion : void 0,
7011
7227
  legacy,
7012
- _internal_btql
7228
+ _internal_btql,
7229
+ resolvedVersion instanceof LazyValue || normalizedEnvironment !== void 0 || normalizedSnapshotName !== void 0 ? {
7230
+ ...resolvedVersion instanceof LazyValue ? {
7231
+ lazyPinnedVersion: resolvedVersion
7232
+ } : {},
7233
+ ...normalizedEnvironment !== void 0 ? {
7234
+ pinnedEnvironment: normalizedEnvironment
7235
+ } : {},
7236
+ ...normalizedSnapshotName !== void 0 ? {
7237
+ pinnedSnapshotName: normalizedSnapshotName
7238
+ } : {}
7239
+ } : void 0
7013
7240
  );
7241
+ return datasetObject;
7014
7242
  }
7015
7243
  function withDataset(project, callback, options = {}) {
7016
7244
  debugLogger.forState(options.state).warn(
@@ -8006,11 +8234,20 @@ var ObjectFetcher = class {
8006
8234
  async getState() {
8007
8235
  throw new Error("ObjectFetcher subclasses must have a 'getState' method");
8008
8236
  }
8237
+ getPinnedVersion() {
8238
+ return this.pinnedVersion;
8239
+ }
8240
+ setPinnedVersion(pinnedVersion) {
8241
+ this.pinnedVersion = pinnedVersion;
8242
+ }
8243
+ getInternalBtql() {
8244
+ return this._internal_btql;
8245
+ }
8009
8246
  async *fetchRecordsFromApi(batchSize) {
8010
8247
  const state = await this.getState();
8011
8248
  const objectId = await this.id;
8012
8249
  const batchLimit = batchSize ?? DEFAULT_FETCH_BATCH_SIZE;
8013
- const internalLimit = this._internal_btql?.limit;
8250
+ const internalLimit = getInternalBtqlLimit(this._internal_btql);
8014
8251
  const limit = batchSize !== void 0 ? batchSize : internalLimit ?? batchLimit;
8015
8252
  const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
8016
8253
  Object.entries(this._internal_btql ?? {}).filter(
@@ -8824,7 +9061,7 @@ function splitLoggingData({
8824
9061
  return [serializableInternalData, lazyInternalData];
8825
9062
  }
8826
9063
  var Dataset2 = class extends ObjectFetcher {
8827
- constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql) {
9064
+ constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql, pinState) {
8828
9065
  const isLegacyDataset = legacy ?? DEFAULT_IS_LEGACY_DATASET;
8829
9066
  if (isLegacyDataset) {
8830
9067
  debugLogger.forState(state).warn(
@@ -8845,10 +9082,16 @@ var Dataset2 = class extends ObjectFetcher {
8845
9082
  );
8846
9083
  this.state = state;
8847
9084
  this.lazyMetadata = lazyMetadata;
9085
+ this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
9086
+ this.pinnedEnvironment = pinState?.pinnedEnvironment;
9087
+ this.pinnedSnapshotName = pinState?.pinnedSnapshotName;
8848
9088
  }
8849
9089
  lazyMetadata;
8850
9090
  __braintrust_dataset_marker = true;
8851
9091
  newRecords = 0;
9092
+ lazyPinnedVersion;
9093
+ pinnedEnvironment;
9094
+ pinnedSnapshotName;
8852
9095
  get id() {
8853
9096
  return (async () => {
8854
9097
  return (await this.lazyMetadata.get()).dataset.id;
@@ -8867,10 +9110,40 @@ var Dataset2 = class extends ObjectFetcher {
8867
9110
  get loggingState() {
8868
9111
  return this.state;
8869
9112
  }
9113
+ async toEvalData() {
9114
+ await this.getState();
9115
+ const metadata = await this.lazyMetadata.get();
9116
+ const pinnedVersion = this.getPinnedVersion();
9117
+ const internalBtql = this.getInternalBtql();
9118
+ return {
9119
+ dataset_id: metadata.dataset.id,
9120
+ ...this.pinnedEnvironment !== void 0 ? {
9121
+ dataset_environment: this.pinnedEnvironment
9122
+ } : {},
9123
+ ...this.pinnedEnvironment === void 0 && this.pinnedSnapshotName !== void 0 ? {
9124
+ dataset_snapshot_name: this.pinnedSnapshotName
9125
+ } : {},
9126
+ ...this.pinnedEnvironment === void 0 && this.pinnedSnapshotName === void 0 && pinnedVersion !== void 0 ? {
9127
+ dataset_version: pinnedVersion
9128
+ } : {},
9129
+ ...internalBtql !== void 0 ? { _internal_btql: internalBtql } : {}
9130
+ };
9131
+ }
8870
9132
  async getState() {
8871
9133
  await this.lazyMetadata.get();
9134
+ if (this.lazyPinnedVersion !== void 0 && this.getPinnedVersion() === void 0) {
9135
+ this.setPinnedVersion(await this.lazyPinnedVersion.get());
9136
+ }
8872
9137
  return this.state;
8873
9138
  }
9139
+ async version(options) {
9140
+ const pinnedVersion = this.getPinnedVersion();
9141
+ if (pinnedVersion !== void 0) {
9142
+ return pinnedVersion;
9143
+ }
9144
+ await this.getState();
9145
+ return await super.version(options);
9146
+ }
8874
9147
  validateEvent({
8875
9148
  metadata,
8876
9149
  expected,
@@ -9006,6 +9279,88 @@ var Dataset2 = class extends ObjectFetcher {
9006
9279
  this.state.bgLogger().log([args]);
9007
9280
  return id;
9008
9281
  }
9282
+ async createSnapshot({
9283
+ name,
9284
+ description,
9285
+ update
9286
+ }) {
9287
+ await this.flush();
9288
+ const state = await this.getState();
9289
+ const datasetId = await this.id;
9290
+ const currentVersion = await this.version();
9291
+ if (currentVersion === void 0) {
9292
+ throw new Error("Cannot create snapshot: dataset has no version");
9293
+ }
9294
+ const response = await state.appConn().post_json("api/dataset_snapshot/register", {
9295
+ dataset_id: datasetId,
9296
+ dataset_snapshot_name: name,
9297
+ description,
9298
+ xact_id: currentVersion,
9299
+ update
9300
+ });
9301
+ return datasetSnapshotRegisterResponseSchema.parse(response).dataset_snapshot;
9302
+ }
9303
+ async listSnapshots() {
9304
+ const state = await this.getState();
9305
+ return await getDatasetSnapshots({
9306
+ state,
9307
+ datasetId: await this.id
9308
+ });
9309
+ }
9310
+ async getSnapshot(lookup) {
9311
+ const state = await this.getState();
9312
+ const datasetId = await this.id;
9313
+ return await getDatasetSnapshot({
9314
+ state,
9315
+ datasetId,
9316
+ ...lookup
9317
+ });
9318
+ }
9319
+ async updateSnapshot(snapshotId, {
9320
+ name,
9321
+ description
9322
+ }) {
9323
+ const state = await this.getState();
9324
+ return DatasetSnapshot.parse(
9325
+ await state.appConn().post_json("api/dataset_snapshot/patch_id", {
9326
+ id: snapshotId,
9327
+ name,
9328
+ description
9329
+ })
9330
+ );
9331
+ }
9332
+ async deleteSnapshot(snapshotId) {
9333
+ const state = await this.getState();
9334
+ return DatasetSnapshot.parse(
9335
+ await state.appConn().post_json("api/dataset_snapshot/delete_id", {
9336
+ id: snapshotId
9337
+ })
9338
+ );
9339
+ }
9340
+ async restorePreview({
9341
+ version
9342
+ }) {
9343
+ await this.flush();
9344
+ const state = await this.getState();
9345
+ const datasetId = await this.id;
9346
+ return datasetRestorePreviewResultSchema.parse(
9347
+ await state.apiConn().post_json(`v1/dataset/${datasetId}/restore/preview`, {
9348
+ version
9349
+ })
9350
+ );
9351
+ }
9352
+ async restore({
9353
+ version
9354
+ }) {
9355
+ await this.flush();
9356
+ const state = await this.getState();
9357
+ const datasetId = await this.id;
9358
+ return datasetRestoreResultSchema.parse(
9359
+ await state.apiConn().post_json(`v1/dataset/${datasetId}/restore`, {
9360
+ version
9361
+ })
9362
+ );
9363
+ }
9009
9364
  /**
9010
9365
  * Summarize the dataset, including high level metrics about its size and other metadata.
9011
9366
  * @param summarizeData Whether to summarize the data. If false, only the metadata will be returned.
@@ -14263,6 +14618,9 @@ function llmParentKey(parentToolUseId) {
14263
14618
  function isSubAgentDelegationToolName(toolName) {
14264
14619
  return toolName === "Agent" || toolName === "Task";
14265
14620
  }
14621
+ function shouldParentToolAsTaskSibling(toolName) {
14622
+ return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
14623
+ }
14266
14624
  function filterSerializableOptions(options) {
14267
14625
  const allowedKeys = [
14268
14626
  "model",
@@ -14362,6 +14720,11 @@ function resolveTaskToolUseId(taskIdToToolUseId, message) {
14362
14720
  }
14363
14721
  return void 0;
14364
14722
  }
14723
+ function seedTaskToolUseIdMapping(taskIdToToolUseId, message) {
14724
+ if (typeof message.task_id === "string" && typeof message.tool_use_id === "string") {
14725
+ taskIdToToolUseId.set(message.task_id, message.tool_use_id);
14726
+ }
14727
+ }
14365
14728
  function extractUsageFromMessage(message) {
14366
14729
  const metrics = {};
14367
14730
  let usage;
@@ -14557,7 +14920,10 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
14557
14920
  }
14558
14921
  },
14559
14922
  name: parsed.displayName,
14560
- parent: await resolveParentSpan(toolUseID),
14923
+ parent: await resolveParentSpan(toolUseID, {
14924
+ agentId: input.agent_id,
14925
+ preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
14926
+ }),
14561
14927
  spanAttributes: { type: "tool" /* TOOL */ }
14562
14928
  });
14563
14929
  activeToolSpans.set(toolUseID, toolSpan);
@@ -14847,6 +15213,7 @@ async function finalizeCurrentMessageGroup(state) {
14847
15213
  state.currentMessages.length = 0;
14848
15214
  }
14849
15215
  function maybeTrackToolUseContext(state, message) {
15216
+ seedTaskToolUseIdMapping(state.taskIdToToolUseId, message);
14850
15217
  if (message.type !== "assistant" || !Array.isArray(message.message?.content)) {
14851
15218
  return;
14852
15219
  }
@@ -14901,6 +15268,34 @@ async function ensureSubAgentSpan(subAgentDetailsByToolUseId, rootSpan, activeTo
14901
15268
  subAgentSpans.set(parentToolUseId, subAgentSpan);
14902
15269
  return subAgentSpan;
14903
15270
  }
15271
+ async function ensureActiveLlmSpanForParentToolUse(rootSpan, activeLlmSpansByParentToolUse, subAgentDetailsByToolUseId, activeToolSpans, subAgentSpans, parentToolUseId, startTime) {
15272
+ const parentKey = llmParentKey(parentToolUseId);
15273
+ const existingLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
15274
+ if (existingLlmSpan) {
15275
+ return existingLlmSpan;
15276
+ }
15277
+ let llmParentSpan = await rootSpan.export();
15278
+ if (parentToolUseId) {
15279
+ const subAgentSpan = await ensureSubAgentSpan(
15280
+ subAgentDetailsByToolUseId,
15281
+ rootSpan,
15282
+ activeToolSpans,
15283
+ subAgentSpans,
15284
+ parentToolUseId
15285
+ );
15286
+ llmParentSpan = await subAgentSpan.export();
15287
+ }
15288
+ const llmSpan = startSpan({
15289
+ name: "anthropic.messages.create",
15290
+ parent: llmParentSpan,
15291
+ spanAttributes: {
15292
+ type: "llm" /* LLM */
15293
+ },
15294
+ startTime
15295
+ });
15296
+ activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
15297
+ return llmSpan;
15298
+ }
14904
15299
  async function maybeHandleTaskLifecycleMessage(state, message) {
14905
15300
  if (message.type !== "system") {
14906
15301
  return false;
@@ -15010,29 +15405,15 @@ async function handleStreamMessage(state, message) {
15010
15405
  }
15011
15406
  if (message.type === "assistant" && message.message?.usage) {
15012
15407
  const parentToolUseId = message.parent_tool_use_id ?? null;
15013
- const parentKey = llmParentKey(parentToolUseId);
15014
- if (!state.activeLlmSpansByParentToolUse.has(parentKey)) {
15015
- let llmParentSpan = await state.span.export();
15016
- if (parentToolUseId) {
15017
- const subAgentSpan = await ensureSubAgentSpan(
15018
- state.subAgentDetailsByToolUseId,
15019
- state.span,
15020
- state.activeToolSpans,
15021
- state.subAgentSpans,
15022
- parentToolUseId
15023
- );
15024
- llmParentSpan = await subAgentSpan.export();
15025
- }
15026
- const llmSpan = startSpan({
15027
- name: "anthropic.messages.create",
15028
- parent: llmParentSpan,
15029
- spanAttributes: {
15030
- type: "llm" /* LLM */
15031
- },
15032
- startTime: state.currentMessageStartTime
15033
- });
15034
- state.activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
15035
- }
15408
+ await ensureActiveLlmSpanForParentToolUse(
15409
+ state.span,
15410
+ state.activeLlmSpansByParentToolUse,
15411
+ state.subAgentDetailsByToolUseId,
15412
+ state.activeToolSpans,
15413
+ state.subAgentSpans,
15414
+ parentToolUseId,
15415
+ state.currentMessageStartTime
15416
+ );
15036
15417
  state.currentMessages.push(message);
15037
15418
  }
15038
15419
  if (message.type !== "result" || !message.usage) {
@@ -15179,10 +15560,35 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
15179
15560
  const localToolContext = createClaudeLocalToolContext();
15180
15561
  const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
15181
15562
  const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
15182
- const resolveToolUseParentSpan = async (toolUseID) => {
15183
- const parentToolUseId = toolUseToParent.get(toolUseID) ?? null;
15563
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
15564
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
15565
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
15184
15566
  const parentKey = llmParentKey(parentToolUseId);
15185
15567
  const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
15568
+ if (context?.preferTaskSiblingParent) {
15569
+ if (!activeLlmSpan) {
15570
+ await ensureActiveLlmSpanForParentToolUse(
15571
+ span,
15572
+ activeLlmSpansByParentToolUse,
15573
+ subAgentDetailsByToolUseId,
15574
+ activeToolSpans,
15575
+ subAgentSpans,
15576
+ parentToolUseId,
15577
+ getCurrentUnixTimestamp()
15578
+ );
15579
+ }
15580
+ if (parentToolUseId) {
15581
+ const subAgentSpan = await ensureSubAgentSpan(
15582
+ subAgentDetailsByToolUseId,
15583
+ span,
15584
+ activeToolSpans,
15585
+ subAgentSpans,
15586
+ parentToolUseId
15587
+ );
15588
+ return subAgentSpan.export();
15589
+ }
15590
+ return span.export();
15591
+ }
15186
15592
  if (activeLlmSpan) {
15187
15593
  return activeLlmSpan.export();
15188
15594
  }
@@ -15310,62 +15716,940 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
15310
15716
  }
15311
15717
  };
15312
15718
 
15313
- // src/instrumentation/plugins/google-genai-channels.ts
15314
- var googleGenAIChannels = defineChannels("@google/genai", {
15315
- generateContent: channel({
15316
- channelName: "models.generateContent",
15719
+ // src/instrumentation/plugins/cursor-sdk-channels.ts
15720
+ var cursorSDKChannels = defineChannels("@cursor/sdk", {
15721
+ create: channel({
15722
+ channelName: "Agent.create",
15317
15723
  kind: "async"
15318
15724
  }),
15319
- generateContentStream: channel({
15320
- channelName: "models.generateContentStream",
15725
+ resume: channel({
15726
+ channelName: "Agent.resume",
15321
15727
  kind: "async"
15322
15728
  }),
15323
- embedContent: channel({
15324
- channelName: "models.embedContent",
15729
+ prompt: channel({
15730
+ channelName: "Agent.prompt",
15731
+ kind: "async"
15732
+ }),
15733
+ send: channel({
15734
+ channelName: "agent.send",
15325
15735
  kind: "async"
15326
15736
  })
15327
15737
  });
15328
15738
 
15329
- // src/instrumentation/plugins/google-genai-plugin.ts
15330
- var GOOGLE_GENAI_INTERNAL_CONTEXT = {
15331
- caller_filename: "<node-internal>",
15332
- caller_functionname: "<node-internal>",
15333
- caller_lineno: 0
15334
- };
15335
- function createWrapperParityEvent(args) {
15336
- return {
15337
- context: GOOGLE_GENAI_INTERNAL_CONTEXT,
15338
- input: args.input,
15339
- metadata: args.metadata
15340
- };
15341
- }
15342
- var GoogleGenAIPlugin = class extends BasePlugin {
15739
+ // src/instrumentation/plugins/cursor-sdk-plugin.ts
15740
+ var PATCHED_AGENT = Symbol.for("braintrust.cursor-sdk.auto-patched-agent");
15741
+ var PATCHED_RUN = Symbol.for("braintrust.cursor-sdk.patched-run");
15742
+ var WRAPPED_AGENT = Symbol.for("braintrust.cursor-sdk.wrapped-agent");
15743
+ var CursorSDKPlugin = class extends BasePlugin {
15744
+ promptDepth = 0;
15343
15745
  onEnable() {
15344
- this.subscribeToGoogleGenAIChannels();
15746
+ this.subscribeToAgentFactories();
15747
+ this.subscribeToPrompt();
15748
+ this.subscribeToSend();
15345
15749
  }
15346
15750
  onDisable() {
15347
- this.unsubscribers = unsubscribeAll(this.unsubscribers);
15751
+ for (const unsubscribe of this.unsubscribers) {
15752
+ unsubscribe();
15753
+ }
15754
+ this.unsubscribers = [];
15755
+ this.promptDepth = 0;
15348
15756
  }
15349
- subscribeToGoogleGenAIChannels() {
15350
- this.subscribeToGenerateContentChannel();
15351
- this.subscribeToGenerateContentStreamChannel();
15352
- this.subscribeToEmbedContentChannel();
15757
+ subscribeToAgentFactories() {
15758
+ this.subscribeToAgentFactory(cursorSDKChannels.create);
15759
+ this.subscribeToAgentFactory(cursorSDKChannels.resume);
15353
15760
  }
15354
- subscribeToGenerateContentChannel() {
15355
- const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
15761
+ subscribeToAgentFactory(channel2) {
15762
+ const tracingChannel2 = channel2.tracingChannel();
15763
+ const handlers = {
15764
+ asyncEnd: (event) => {
15765
+ patchCursorAgentInPlace(event.result);
15766
+ },
15767
+ error: () => {
15768
+ }
15769
+ };
15770
+ tracingChannel2.subscribe(handlers);
15771
+ this.unsubscribers.push(() => {
15772
+ tracingChannel2.unsubscribe(handlers);
15773
+ });
15774
+ }
15775
+ subscribeToPrompt() {
15776
+ const channel2 = cursorSDKChannels.prompt.tracingChannel();
15356
15777
  const states = /* @__PURE__ */ new WeakMap();
15357
- const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
15358
- tracingChannel2,
15359
- states,
15360
- (event) => {
15361
- const params = event.arguments[0];
15362
- const input = serializeGenerateContentInput(params);
15363
- const metadata = extractGenerateContentMetadata(params);
15778
+ const handlers = {
15779
+ start: (event) => {
15780
+ this.promptDepth += 1;
15781
+ const message = event.arguments[0];
15782
+ const options = event.arguments[1];
15783
+ const metadata = {
15784
+ ...extractAgentOptionsMetadata(options),
15785
+ "cursor_sdk.operation": "Agent.prompt",
15786
+ provider: "cursor",
15787
+ ...event.moduleVersion ? { "cursor_sdk.version": event.moduleVersion } : {}
15788
+ };
15364
15789
  const span = startSpan({
15365
- name: "generate_content",
15366
- spanAttributes: {
15367
- type: "llm" /* LLM */
15368
- },
15790
+ name: "Cursor Agent",
15791
+ spanAttributes: { type: "task" /* TASK */ }
15792
+ });
15793
+ const startTime = getCurrentUnixTimestamp();
15794
+ safeLog(span, {
15795
+ input: sanitizeUserMessage(message),
15796
+ metadata
15797
+ });
15798
+ states.set(event, { metadata, span, startTime });
15799
+ },
15800
+ asyncEnd: (event) => {
15801
+ this.promptDepth = Math.max(0, this.promptDepth - 1);
15802
+ const state = states.get(event);
15803
+ if (!state) {
15804
+ return;
15805
+ }
15806
+ try {
15807
+ safeLog(state.span, {
15808
+ metadata: {
15809
+ ...state.metadata,
15810
+ ...extractRunResultMetadata(event.result)
15811
+ },
15812
+ metrics: buildDurationMetrics(state.startTime),
15813
+ output: event.result?.result ?? event.result
15814
+ });
15815
+ } finally {
15816
+ state.span.end();
15817
+ states.delete(event);
15818
+ }
15819
+ },
15820
+ error: (event) => {
15821
+ this.promptDepth = Math.max(0, this.promptDepth - 1);
15822
+ const state = states.get(event);
15823
+ if (!state || !event.error) {
15824
+ return;
15825
+ }
15826
+ safeLog(state.span, { error: event.error.message });
15827
+ state.span.end();
15828
+ states.delete(event);
15829
+ }
15830
+ };
15831
+ channel2.subscribe(handlers);
15832
+ this.unsubscribers.push(() => {
15833
+ channel2.unsubscribe(handlers);
15834
+ });
15835
+ }
15836
+ subscribeToSend() {
15837
+ const channel2 = cursorSDKChannels.send.tracingChannel();
15838
+ const states = /* @__PURE__ */ new WeakMap();
15839
+ const handlers = {
15840
+ start: (event) => {
15841
+ if (this.promptDepth > 0) {
15842
+ return;
15843
+ }
15844
+ const message = event.arguments[0];
15845
+ const sendOptions = event.arguments[1];
15846
+ const agent = event.agent;
15847
+ const metadata = {
15848
+ ...extractSendMetadata(sendOptions),
15849
+ ...agent ? extractAgentMetadata(agent) : {},
15850
+ "cursor_sdk.operation": "agent.send",
15851
+ provider: "cursor",
15852
+ ...event.moduleVersion ? { "cursor_sdk.version": event.moduleVersion } : {}
15853
+ };
15854
+ const span = startSpan({
15855
+ name: "Cursor Agent",
15856
+ spanAttributes: { type: "task" /* TASK */ }
15857
+ });
15858
+ const startTime = getCurrentUnixTimestamp();
15859
+ safeLog(span, {
15860
+ input: sanitizeUserMessage(message),
15861
+ metadata
15862
+ });
15863
+ const state = {
15864
+ activeToolSpans: /* @__PURE__ */ new Map(),
15865
+ agent,
15866
+ conversationText: [],
15867
+ deltaText: [],
15868
+ finalized: false,
15869
+ input: message,
15870
+ metadata,
15871
+ metrics: {},
15872
+ span,
15873
+ startTime,
15874
+ streamMessages: [],
15875
+ streamText: [],
15876
+ stepText: [],
15877
+ taskText: []
15878
+ };
15879
+ if (hasCursorCallbacks(sendOptions)) {
15880
+ event.arguments[1] = wrapSendOptionsCallbacks(sendOptions, state);
15881
+ }
15882
+ states.set(event, state);
15883
+ },
15884
+ asyncEnd: (event) => {
15885
+ const state = states.get(event);
15886
+ if (!state) {
15887
+ return;
15888
+ }
15889
+ if (!event.result) {
15890
+ return;
15891
+ }
15892
+ state.run = event.result;
15893
+ state.metadata = {
15894
+ ...state.metadata,
15895
+ ...extractRunMetadata(event.result)
15896
+ };
15897
+ patchCursorRun(event.result, state);
15898
+ },
15899
+ error: (event) => {
15900
+ const state = states.get(event);
15901
+ if (!state || !event.error) {
15902
+ return;
15903
+ }
15904
+ safeLog(state.span, { error: event.error.message });
15905
+ endOpenToolSpans(state, event.error.message);
15906
+ state.span.end();
15907
+ state.finalized = true;
15908
+ states.delete(event);
15909
+ }
15910
+ };
15911
+ channel2.subscribe(handlers);
15912
+ this.unsubscribers.push(() => {
15913
+ channel2.unsubscribe(handlers);
15914
+ });
15915
+ }
15916
+ };
15917
+ function patchCursorAgentInPlace(agent) {
15918
+ if (!agent || typeof agent !== "object") {
15919
+ return;
15920
+ }
15921
+ const agentRecord = agent;
15922
+ if (agentRecord[PATCHED_AGENT] || agentRecord[WRAPPED_AGENT] || typeof agentRecord.send !== "function") {
15923
+ return;
15924
+ }
15925
+ const originalSend = agentRecord.send.bind(agentRecord);
15926
+ try {
15927
+ Object.defineProperty(agentRecord, PATCHED_AGENT, {
15928
+ configurable: false,
15929
+ enumerable: false,
15930
+ value: true
15931
+ });
15932
+ Object.defineProperty(agentRecord, "send", {
15933
+ configurable: true,
15934
+ value(message, options) {
15935
+ const args = [message, options];
15936
+ return cursorSDKChannels.send.tracePromise(
15937
+ () => originalSend(...args),
15938
+ {
15939
+ agent: agentRecord,
15940
+ arguments: args,
15941
+ operation: "send"
15942
+ }
15943
+ );
15944
+ },
15945
+ writable: true
15946
+ });
15947
+ } catch {
15948
+ }
15949
+ }
15950
+ function wrapSendOptionsCallbacks(options, state) {
15951
+ const originalOnDelta = options.onDelta;
15952
+ const originalOnStep = options.onStep;
15953
+ return {
15954
+ ...options,
15955
+ async onDelta(args) {
15956
+ try {
15957
+ await handleInteractionUpdate(state, args.update);
15958
+ } catch (error) {
15959
+ logInstrumentationError("Cursor SDK onDelta", error);
15960
+ }
15961
+ if (originalOnDelta) {
15962
+ return originalOnDelta(args);
15963
+ }
15964
+ },
15965
+ async onStep(args) {
15966
+ try {
15967
+ handleStepUpdate(state, args.step);
15968
+ } catch (error) {
15969
+ logInstrumentationError("Cursor SDK onStep", error);
15970
+ }
15971
+ if (originalOnStep) {
15972
+ return originalOnStep(args);
15973
+ }
15974
+ }
15975
+ };
15976
+ }
15977
+ function hasCursorCallbacks(options) {
15978
+ return !!options && (typeof options.onDelta === "function" || typeof options.onStep === "function");
15979
+ }
15980
+ function patchCursorRun(run, state) {
15981
+ if (!run || typeof run !== "object") {
15982
+ return;
15983
+ }
15984
+ const runRecord = run;
15985
+ if (runRecord[PATCHED_RUN]) {
15986
+ return;
15987
+ }
15988
+ try {
15989
+ Object.defineProperty(runRecord, PATCHED_RUN, {
15990
+ configurable: false,
15991
+ enumerable: false,
15992
+ value: true
15993
+ });
15994
+ if (typeof runRecord.stream === "function") {
15995
+ const originalStream = runRecord.stream.bind(runRecord);
15996
+ Object.defineProperty(runRecord, "stream", {
15997
+ configurable: true,
15998
+ value() {
15999
+ const stream = originalStream();
16000
+ return patchCursorStream(stream, state);
16001
+ },
16002
+ writable: true
16003
+ });
16004
+ }
16005
+ if (typeof runRecord.wait === "function") {
16006
+ const originalWait = runRecord.wait.bind(runRecord);
16007
+ Object.defineProperty(runRecord, "wait", {
16008
+ configurable: true,
16009
+ async value() {
16010
+ try {
16011
+ const result = await originalWait();
16012
+ state.lastResult = result;
16013
+ await finalizeCursorRun(state, { result });
16014
+ return result;
16015
+ } catch (error) {
16016
+ await finalizeCursorRun(state, { error });
16017
+ throw error;
16018
+ }
16019
+ },
16020
+ writable: true
16021
+ });
16022
+ }
16023
+ if (typeof runRecord.conversation === "function") {
16024
+ const originalConversation = runRecord.conversation.bind(runRecord);
16025
+ Object.defineProperty(runRecord, "conversation", {
16026
+ configurable: true,
16027
+ async value() {
16028
+ try {
16029
+ const conversation = await originalConversation();
16030
+ await handleConversation(state, conversation);
16031
+ await finalizeCursorRun(state);
16032
+ return conversation;
16033
+ } catch (error) {
16034
+ await finalizeCursorRun(state, { error });
16035
+ throw error;
16036
+ }
16037
+ },
16038
+ writable: true
16039
+ });
16040
+ }
16041
+ } catch {
16042
+ void finalizeCursorRun(state, { output: run });
16043
+ }
16044
+ }
16045
+ async function* patchCursorStream(stream, state) {
16046
+ try {
16047
+ for await (const message of stream) {
16048
+ try {
16049
+ await handleStreamMessage2(state, message);
16050
+ } catch (error) {
16051
+ logInstrumentationError("Cursor SDK stream", error);
16052
+ }
16053
+ yield message;
16054
+ }
16055
+ await finalizeCursorRun(state);
16056
+ } catch (error) {
16057
+ await finalizeCursorRun(state, { error });
16058
+ throw error;
16059
+ }
16060
+ }
16061
+ async function handleInteractionUpdate(state, update) {
16062
+ switch (update.type) {
16063
+ case "text-delta":
16064
+ if (typeof update.text === "string") {
16065
+ state.deltaText.push(update.text);
16066
+ }
16067
+ return;
16068
+ case "token-delta":
16069
+ if (typeof update.tokens === "number") {
16070
+ state.metrics["cursor_sdk.delta_tokens"] = (state.metrics["cursor_sdk.delta_tokens"] ?? 0) + update.tokens;
16071
+ }
16072
+ return;
16073
+ case "tool-call-started":
16074
+ case "partial-tool-call":
16075
+ case "tool-call-completed":
16076
+ await handleToolUpdate(
16077
+ state,
16078
+ update
16079
+ );
16080
+ return;
16081
+ case "turn-ended":
16082
+ addUsageMetrics(
16083
+ state.metrics,
16084
+ update.usage
16085
+ );
16086
+ return;
16087
+ case "summary":
16088
+ if (typeof update.summary === "string") {
16089
+ state.taskText.push(update.summary);
16090
+ }
16091
+ return;
16092
+ case "step-completed":
16093
+ if (typeof update.stepDurationMs === "number") {
16094
+ state.metrics["cursor_sdk.step_duration_ms"] = (state.metrics["cursor_sdk.step_duration_ms"] ?? 0) + update.stepDurationMs;
16095
+ }
16096
+ state.metrics["cursor_sdk.steps"] = (state.metrics["cursor_sdk.steps"] ?? 0) + 1;
16097
+ return;
16098
+ default:
16099
+ return;
16100
+ }
16101
+ }
16102
+ async function handleToolUpdate(state, update) {
16103
+ const callId = update.callId;
16104
+ if (!callId) {
16105
+ return;
16106
+ }
16107
+ const toolCall = update.toolCall;
16108
+ const name = extractToolName(toolCall);
16109
+ const args = extractToolArgs(toolCall);
16110
+ const result = extractToolResult(toolCall);
16111
+ if (update.type === "tool-call-started" || update.type === "partial-tool-call") {
16112
+ if (!state.activeToolSpans.has(callId)) {
16113
+ state.activeToolSpans.set(
16114
+ callId,
16115
+ await startToolSpan(state, {
16116
+ args,
16117
+ callId,
16118
+ name,
16119
+ status: "running",
16120
+ toolCall
16121
+ })
16122
+ );
16123
+ }
16124
+ return;
16125
+ }
16126
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
16127
+ args,
16128
+ callId,
16129
+ name,
16130
+ status: "completed",
16131
+ toolCall
16132
+ });
16133
+ finishToolSpan(toolState, {
16134
+ error: toolCall?.status === "error" ? stringifyUnknown(result) : void 0,
16135
+ metadata: {
16136
+ "cursor_sdk.tool.status": toolCall?.status ?? "completed"
16137
+ },
16138
+ output: result
16139
+ });
16140
+ state.activeToolSpans.delete(callId);
16141
+ }
16142
+ async function handleStreamMessage2(state, message) {
16143
+ state.streamMessages.push(message);
16144
+ if (message.type === "system") {
16145
+ const systemMessage = message;
16146
+ state.metadata = {
16147
+ ...state.metadata,
16148
+ ...extractModelMetadata(systemMessage.model),
16149
+ ...systemMessage.agent_id ? { "cursor_sdk.agent_id": systemMessage.agent_id } : {},
16150
+ ...systemMessage.run_id ? { "cursor_sdk.run_id": systemMessage.run_id } : {},
16151
+ ...systemMessage.tools ? { "cursor_sdk.tools": systemMessage.tools } : {}
16152
+ };
16153
+ return;
16154
+ }
16155
+ if (message.type === "assistant") {
16156
+ const assistantMessage = message;
16157
+ for (const block of assistantMessage.message?.content ?? []) {
16158
+ if (block?.type === "text" && typeof block.text === "string") {
16159
+ state.streamText.push(block.text);
16160
+ } else if (block?.type === "tool_use" && block.id) {
16161
+ state.activeToolSpans.set(
16162
+ block.id,
16163
+ await startToolSpan(state, {
16164
+ args: block.input,
16165
+ callId: block.id,
16166
+ name: block.name,
16167
+ status: "running"
16168
+ })
16169
+ );
16170
+ }
16171
+ }
16172
+ return;
16173
+ }
16174
+ if (message.type === "tool_call") {
16175
+ await handleToolMessage(
16176
+ state,
16177
+ message
16178
+ );
16179
+ return;
16180
+ }
16181
+ if (message.type === "task" && typeof message.text === "string") {
16182
+ state.taskText.push(message.text);
16183
+ return;
16184
+ }
16185
+ if (message.type === "status" && message.status) {
16186
+ state.metadata["cursor_sdk.status"] = message.status;
16187
+ }
16188
+ }
16189
+ async function handleToolMessage(state, message) {
16190
+ const callId = message.call_id;
16191
+ if (!callId) {
16192
+ return;
16193
+ }
16194
+ if (message.status === "running") {
16195
+ if (!state.activeToolSpans.has(callId)) {
16196
+ state.activeToolSpans.set(
16197
+ callId,
16198
+ await startToolSpan(state, {
16199
+ args: message.args,
16200
+ callId,
16201
+ name: message.name,
16202
+ status: message.status,
16203
+ truncated: message.truncated
16204
+ })
16205
+ );
16206
+ }
16207
+ return;
16208
+ }
16209
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
16210
+ args: message.args,
16211
+ callId,
16212
+ name: message.name,
16213
+ status: message.status,
16214
+ truncated: message.truncated
16215
+ });
16216
+ finishToolSpan(toolState, {
16217
+ error: message.status === "error" ? stringifyUnknown(message.result) : void 0,
16218
+ metadata: {
16219
+ "cursor_sdk.tool.status": message.status
16220
+ },
16221
+ output: message.result
16222
+ });
16223
+ state.activeToolSpans.delete(callId);
16224
+ }
16225
+ async function handleConversation(state, turns) {
16226
+ state.conversationOutput = turns;
16227
+ for (const turn of turns) {
16228
+ if (turn.type === "agentConversationTurn") {
16229
+ for (const step of turn.turn?.steps ?? []) {
16230
+ await handleConversationStep(state, step);
16231
+ }
16232
+ } else if (turn.type === "shellConversationTurn") {
16233
+ const command = turn.turn?.shellCommand?.command;
16234
+ if (command) {
16235
+ const callId = `shell:${state.activeToolSpans.size}:${command}`;
16236
+ const toolState = await startToolSpan(state, {
16237
+ args: turn.turn?.shellCommand,
16238
+ callId,
16239
+ name: "shell",
16240
+ status: "completed"
16241
+ });
16242
+ finishToolSpan(toolState, {
16243
+ metadata: { "cursor_sdk.tool.status": "completed" },
16244
+ output: turn.turn?.shellOutput
16245
+ });
16246
+ }
16247
+ }
16248
+ }
16249
+ }
16250
+ async function handleConversationStep(state, step) {
16251
+ if (step.type === "assistantMessage" && typeof step.message?.text === "string") {
16252
+ state.conversationText.push(step.message.text);
16253
+ return;
16254
+ }
16255
+ if (step.type !== "toolCall") {
16256
+ return;
16257
+ }
16258
+ const toolCall = step.message;
16259
+ const callId = typeof toolCall?.callId === "string" ? toolCall.callId : `conversation-tool:${state.activeToolSpans.size}`;
16260
+ const toolState = await startToolSpan(state, {
16261
+ args: extractToolArgs(toolCall),
16262
+ callId,
16263
+ name: extractToolName(toolCall),
16264
+ status: toolCall?.status,
16265
+ toolCall
16266
+ });
16267
+ finishToolSpan(toolState, {
16268
+ error: toolCall?.status === "error" ? stringifyUnknown(toolCall.result) : void 0,
16269
+ metadata: {
16270
+ "cursor_sdk.tool.status": toolCall?.status ?? "completed"
16271
+ },
16272
+ output: extractToolResult(toolCall)
16273
+ });
16274
+ }
16275
+ function handleStepUpdate(state, step) {
16276
+ state.metrics["cursor_sdk.steps"] = (state.metrics["cursor_sdk.steps"] ?? 0) + 1;
16277
+ if (step.type) {
16278
+ const stepTypes = state.metadata["cursor_sdk.step_types"];
16279
+ if (Array.isArray(stepTypes)) {
16280
+ if (!stepTypes.includes(step.type)) {
16281
+ stepTypes.push(step.type);
16282
+ }
16283
+ } else {
16284
+ state.metadata["cursor_sdk.step_types"] = [step.type];
16285
+ }
16286
+ }
16287
+ if (step.type === "assistantMessage" && typeof step.message?.text === "string") {
16288
+ state.stepText.push(step.message.text);
16289
+ }
16290
+ }
16291
+ async function startToolSpan(state, args) {
16292
+ const name = args.name || "unknown";
16293
+ const metadata = {
16294
+ "cursor_sdk.tool.status": args.status,
16295
+ "gen_ai.tool.call.id": args.callId,
16296
+ "gen_ai.tool.name": name
16297
+ };
16298
+ if (args.truncated?.args !== void 0) {
16299
+ metadata["cursor_sdk.tool.args_truncated"] = args.truncated.args;
16300
+ }
16301
+ if (args.truncated?.result !== void 0) {
16302
+ metadata["cursor_sdk.tool.result_truncated"] = args.truncated.result;
16303
+ }
16304
+ const span = startSpan({
16305
+ event: {
16306
+ input: args.args,
16307
+ metadata
16308
+ },
16309
+ name: `tool: ${name}`,
16310
+ parent: await state.span.export(),
16311
+ spanAttributes: { type: "tool" /* TOOL */ }
16312
+ });
16313
+ let subAgentSpan;
16314
+ if (isSubAgentToolName(name)) {
16315
+ subAgentSpan = startSpan({
16316
+ event: {
16317
+ input: args.args,
16318
+ metadata: {
16319
+ "cursor_sdk.subagent.tool_call_id": args.callId,
16320
+ "gen_ai.tool.name": name
16321
+ }
16322
+ },
16323
+ name: formatSubAgentSpanName2(args.toolCall, args.args),
16324
+ parent: await span.export(),
16325
+ spanAttributes: { type: "task" /* TASK */ }
16326
+ });
16327
+ }
16328
+ return { span, subAgentSpan };
16329
+ }
16330
+ function finishToolSpan(toolState, result) {
16331
+ try {
16332
+ if (result.error) {
16333
+ safeLog(toolState.span, {
16334
+ error: result.error,
16335
+ metadata: result.metadata,
16336
+ output: result.output
16337
+ });
16338
+ if (toolState.subAgentSpan) {
16339
+ safeLog(toolState.subAgentSpan, {
16340
+ error: result.error,
16341
+ metadata: result.metadata,
16342
+ output: result.output
16343
+ });
16344
+ }
16345
+ } else {
16346
+ safeLog(toolState.span, {
16347
+ metadata: result.metadata,
16348
+ output: result.output
16349
+ });
16350
+ if (toolState.subAgentSpan) {
16351
+ safeLog(toolState.subAgentSpan, {
16352
+ metadata: result.metadata,
16353
+ output: result.output
16354
+ });
16355
+ }
16356
+ }
16357
+ } finally {
16358
+ toolState.subAgentSpan?.end();
16359
+ toolState.span.end();
16360
+ }
16361
+ }
16362
+ async function finalizeCursorRun(state, params = {}) {
16363
+ if (state.finalized) {
16364
+ return;
16365
+ }
16366
+ state.finalized = true;
16367
+ const error = params.error;
16368
+ const result = params.result ?? state.lastResult;
16369
+ 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);
16370
+ try {
16371
+ const metadata = {
16372
+ ...state.metadata,
16373
+ ...state.run ? extractRunMetadata(state.run) : {},
16374
+ ...result ? extractRunResultMetadata(result) : {}
16375
+ };
16376
+ if (error) {
16377
+ safeLog(state.span, {
16378
+ error: error instanceof Error ? error.message : String(error),
16379
+ metadata,
16380
+ metrics: {
16381
+ ...cleanMetrics(state.metrics),
16382
+ ...buildDurationMetrics(state.startTime)
16383
+ },
16384
+ output
16385
+ });
16386
+ } else {
16387
+ safeLog(state.span, {
16388
+ metadata,
16389
+ metrics: {
16390
+ ...cleanMetrics(state.metrics),
16391
+ ...buildDurationMetrics(state.startTime)
16392
+ },
16393
+ output
16394
+ });
16395
+ }
16396
+ } finally {
16397
+ endOpenToolSpans(state);
16398
+ state.span.end();
16399
+ }
16400
+ }
16401
+ function endOpenToolSpans(state, error) {
16402
+ for (const [, toolState] of state.activeToolSpans) {
16403
+ finishToolSpan(toolState, { error });
16404
+ }
16405
+ state.activeToolSpans.clear();
16406
+ }
16407
+ function sanitizeUserMessage(message) {
16408
+ if (typeof message === "string" || message === void 0) {
16409
+ return message;
16410
+ }
16411
+ return {
16412
+ ...message,
16413
+ images: message.images?.map((image) => {
16414
+ const imageRecord = image;
16415
+ return {
16416
+ ...typeof imageRecord.url === "string" ? { url: imageRecord.url } : {},
16417
+ ...typeof imageRecord.mimeType === "string" ? { mimeType: imageRecord.mimeType } : {},
16418
+ ...image.dimension ? { dimension: image.dimension } : {},
16419
+ hasData: typeof imageRecord.data === "string"
16420
+ };
16421
+ })
16422
+ };
16423
+ }
16424
+ function extractAgentOptionsMetadata(options) {
16425
+ if (!options) {
16426
+ return {};
16427
+ }
16428
+ return {
16429
+ ...extractModelMetadata(options.model),
16430
+ ...options.agentId ? { "cursor_sdk.agent_id": options.agentId } : {},
16431
+ ...options.name ? { "cursor_sdk.agent_name": options.name } : {},
16432
+ ...options.local ? {
16433
+ "cursor_sdk.runtime": "local",
16434
+ "cursor_sdk.local.cwd": Array.isArray(options.local.cwd) ? options.local.cwd.join(",") : options.local.cwd
16435
+ } : {},
16436
+ ...options.cloud ? {
16437
+ "cursor_sdk.runtime": "cloud",
16438
+ "cursor_sdk.cloud.auto_create_pr": options.cloud.autoCreatePR,
16439
+ "cursor_sdk.cloud.env_type": options.cloud.env?.type,
16440
+ "cursor_sdk.cloud.env_name": options.cloud.env?.name,
16441
+ "cursor_sdk.cloud.repos": options.cloud.repos?.map((repo) => repo.url).filter((url) => typeof url === "string")
16442
+ } : {}
16443
+ };
16444
+ }
16445
+ function extractSendMetadata(options) {
16446
+ if (!options) {
16447
+ return {};
16448
+ }
16449
+ return {
16450
+ ...extractModelMetadata(options.model),
16451
+ ...options.local?.force !== void 0 ? { "cursor_sdk.local.force": options.local.force } : {}
16452
+ };
16453
+ }
16454
+ function extractAgentMetadata(agent) {
16455
+ return {
16456
+ ...agent.agentId ? { "cursor_sdk.agent_id": agent.agentId } : {},
16457
+ ...extractModelMetadata(agent.model)
16458
+ };
16459
+ }
16460
+ function extractRunMetadata(run) {
16461
+ if (!run) {
16462
+ return {};
16463
+ }
16464
+ return {
16465
+ ...run.id ? { "cursor_sdk.run_id": run.id } : {},
16466
+ ...run.agentId ? { "cursor_sdk.agent_id": run.agentId } : {},
16467
+ ...run.status ? { "cursor_sdk.status": run.status } : {},
16468
+ ...run.durationMs !== void 0 ? { "cursor_sdk.duration_ms": run.durationMs } : {},
16469
+ ...extractModelMetadata(run.model),
16470
+ ...extractGitMetadata(run.git)
16471
+ };
16472
+ }
16473
+ function extractRunResultMetadata(result) {
16474
+ if (!result) {
16475
+ return {};
16476
+ }
16477
+ return {
16478
+ ...result.id ? { "cursor_sdk.run_id": result.id } : {},
16479
+ ...result.status ? { "cursor_sdk.status": result.status } : {},
16480
+ ...result.durationMs !== void 0 ? { "cursor_sdk.duration_ms": result.durationMs } : {},
16481
+ ...extractModelMetadata(result.model),
16482
+ ...extractGitMetadata(result.git)
16483
+ };
16484
+ }
16485
+ function extractGitMetadata(git) {
16486
+ const branches = git?.branches;
16487
+ if (!branches || branches.length === 0) {
16488
+ return {};
16489
+ }
16490
+ return {
16491
+ "cursor_sdk.git.branches": branches.map((branch) => ({
16492
+ branch: branch.branch,
16493
+ prUrl: branch.prUrl,
16494
+ repoUrl: branch.repoUrl
16495
+ }))
16496
+ };
16497
+ }
16498
+ function extractModelMetadata(model) {
16499
+ if (!model?.id) {
16500
+ return {};
16501
+ }
16502
+ return {
16503
+ model: model.id,
16504
+ "cursor_sdk.model": model.id,
16505
+ ...model.params ? { "cursor_sdk.model.params": model.params } : {}
16506
+ };
16507
+ }
16508
+ function addUsageMetrics(metrics, usage) {
16509
+ if (!usage) {
16510
+ return;
16511
+ }
16512
+ if (usage.inputTokens !== void 0) {
16513
+ metrics.prompt_tokens = (metrics.prompt_tokens ?? 0) + usage.inputTokens;
16514
+ }
16515
+ if (usage.outputTokens !== void 0) {
16516
+ metrics.completion_tokens = (metrics.completion_tokens ?? 0) + usage.outputTokens;
16517
+ }
16518
+ if (usage.cacheReadTokens !== void 0) {
16519
+ metrics.prompt_cached_tokens = (metrics.prompt_cached_tokens ?? 0) + usage.cacheReadTokens;
16520
+ }
16521
+ if (usage.cacheWriteTokens !== void 0) {
16522
+ metrics.prompt_cache_creation_tokens = (metrics.prompt_cache_creation_tokens ?? 0) + usage.cacheWriteTokens;
16523
+ }
16524
+ metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0) + (metrics.prompt_cached_tokens ?? 0) + (metrics.prompt_cache_creation_tokens ?? 0);
16525
+ }
16526
+ function buildDurationMetrics(startTime) {
16527
+ const end = getCurrentUnixTimestamp();
16528
+ return {
16529
+ duration: end - startTime,
16530
+ end,
16531
+ start: startTime
16532
+ };
16533
+ }
16534
+ function extractToolName(toolCall) {
16535
+ if (!toolCall) {
16536
+ return "unknown";
16537
+ }
16538
+ if (typeof toolCall.name === "string") {
16539
+ return toolCall.name;
16540
+ }
16541
+ if (typeof toolCall.type === "string") {
16542
+ return toolCall.type;
16543
+ }
16544
+ return "unknown";
16545
+ }
16546
+ function extractToolArgs(toolCall) {
16547
+ return toolCall && "args" in toolCall ? toolCall.args : void 0;
16548
+ }
16549
+ function extractToolResult(toolCall) {
16550
+ return toolCall && "result" in toolCall ? toolCall.result : void 0;
16551
+ }
16552
+ function isSubAgentToolName(name) {
16553
+ return name === "Agent" || name === "Task" || name === "task";
16554
+ }
16555
+ function formatSubAgentSpanName2(toolCall, args) {
16556
+ const details = toolCall ?? args;
16557
+ const description = getString(details, "description") ?? getString(details, "subagent_type") ?? getString(details, "type") ?? getString(details, "name");
16558
+ return description ? `Agent: ${description}` : "Agent: sub-agent";
16559
+ }
16560
+ function getString(obj, key) {
16561
+ const value = obj?.[key];
16562
+ return typeof value === "string" ? value : void 0;
16563
+ }
16564
+ function stringifyUnknown(value) {
16565
+ if (value instanceof Error) {
16566
+ return value.message;
16567
+ }
16568
+ if (typeof value === "string") {
16569
+ return value;
16570
+ }
16571
+ try {
16572
+ return JSON.stringify(value);
16573
+ } catch {
16574
+ return String(value);
16575
+ }
16576
+ }
16577
+ function safeLog(span, event) {
16578
+ try {
16579
+ span.log(event);
16580
+ } catch (error) {
16581
+ logInstrumentationError("Cursor SDK span log", error);
16582
+ }
16583
+ }
16584
+ function logInstrumentationError(context, error) {
16585
+ debugLogger.error(`Error processing ${context}:`, error);
16586
+ }
16587
+ function cleanMetrics(metrics) {
16588
+ const cleaned = {};
16589
+ for (const [key, value] of Object.entries(metrics)) {
16590
+ if (value !== void 0 && Number.isFinite(value)) {
16591
+ cleaned[key] = value;
16592
+ }
16593
+ }
16594
+ return cleaned;
16595
+ }
16596
+
16597
+ // src/instrumentation/plugins/google-genai-channels.ts
16598
+ var googleGenAIChannels = defineChannels("@google/genai", {
16599
+ generateContent: channel({
16600
+ channelName: "models.generateContent",
16601
+ kind: "async"
16602
+ }),
16603
+ generateContentStream: channel({
16604
+ channelName: "models.generateContentStream",
16605
+ kind: "async"
16606
+ }),
16607
+ embedContent: channel({
16608
+ channelName: "models.embedContent",
16609
+ kind: "async"
16610
+ })
16611
+ });
16612
+
16613
+ // src/instrumentation/plugins/google-genai-plugin.ts
16614
+ var GOOGLE_GENAI_INTERNAL_CONTEXT = {
16615
+ caller_filename: "<node-internal>",
16616
+ caller_functionname: "<node-internal>",
16617
+ caller_lineno: 0
16618
+ };
16619
+ function createWrapperParityEvent(args) {
16620
+ return {
16621
+ context: GOOGLE_GENAI_INTERNAL_CONTEXT,
16622
+ input: args.input,
16623
+ metadata: args.metadata
16624
+ };
16625
+ }
16626
+ var GoogleGenAIPlugin = class extends BasePlugin {
16627
+ onEnable() {
16628
+ this.subscribeToGoogleGenAIChannels();
16629
+ }
16630
+ onDisable() {
16631
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
16632
+ }
16633
+ subscribeToGoogleGenAIChannels() {
16634
+ this.subscribeToGenerateContentChannel();
16635
+ this.subscribeToGenerateContentStreamChannel();
16636
+ this.subscribeToEmbedContentChannel();
16637
+ }
16638
+ subscribeToGenerateContentChannel() {
16639
+ const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
16640
+ const states = /* @__PURE__ */ new WeakMap();
16641
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
16642
+ tracingChannel2,
16643
+ states,
16644
+ (event) => {
16645
+ const params = event.arguments[0];
16646
+ const input = serializeGenerateContentInput(params);
16647
+ const metadata = extractGenerateContentMetadata(params);
16648
+ const span = startSpan({
16649
+ name: "generate_content",
16650
+ spanAttributes: {
16651
+ type: "llm" /* LLM */
16652
+ },
15369
16653
  event: createWrapperParityEvent({ input, metadata })
15370
16654
  });
15371
16655
  return {
@@ -15402,7 +16686,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
15402
16686
  const responseMetadata = extractResponseMetadata(event.result);
15403
16687
  spanState.span.log({
15404
16688
  ...responseMetadata ? { metadata: responseMetadata } : {},
15405
- metrics: cleanMetrics(
16689
+ metrics: cleanMetrics2(
15406
16690
  extractGenerateContentMetrics(
15407
16691
  event.result,
15408
16692
  spanState.startTime
@@ -15503,7 +16787,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
15503
16787
  const output = summarizeEmbedContentOutput(event.result);
15504
16788
  spanState.span.log({
15505
16789
  ...output ? { output } : {},
15506
- metrics: cleanMetrics(
16790
+ metrics: cleanMetrics2(
15507
16791
  extractEmbedContentMetrics(event.result, spanState.startTime)
15508
16792
  )
15509
16793
  });
@@ -15600,7 +16884,7 @@ function patchGoogleGenAIStreamingResult(args) {
15600
16884
  );
15601
16885
  span.log({
15602
16886
  ...responseMetadata ? { metadata: responseMetadata } : {},
15603
- metrics: cleanMetrics(metricsWithoutEnd),
16887
+ metrics: cleanMetrics2(metricsWithoutEnd),
15604
16888
  output: options.result.aggregated
15605
16889
  });
15606
16890
  span.end(typeof end === "number" ? { endTime: end } : void 0);
@@ -16025,7 +17309,7 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
16025
17309
  }
16026
17310
  return { aggregated, metrics };
16027
17311
  }
16028
- function cleanMetrics(metrics) {
17312
+ function cleanMetrics2(metrics) {
16029
17313
  const cleaned = {};
16030
17314
  for (const [key, value] of Object.entries(metrics)) {
16031
17315
  if (value !== null && value !== void 0) {
@@ -16109,6 +17393,8 @@ var REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
16109
17393
  "stop",
16110
17394
  "stream",
16111
17395
  "temperature",
17396
+ "tool_choice",
17397
+ "tools",
16112
17398
  "top_p"
16113
17399
  ]);
16114
17400
  var RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
@@ -16371,7 +17657,10 @@ function aggregateChatCompletionChunks2(chunks) {
16371
17657
  for (const chunk of chunks) {
16372
17658
  for (const choice of chunk.choices ?? []) {
16373
17659
  const index = typeof choice.index === "number" ? choice.index : 0;
16374
- const existing = aggregatedChoices.get(index) ?? { content: "" };
17660
+ const existing = aggregatedChoices.get(index) ?? {
17661
+ content: "",
17662
+ toolCallsByIndex: /* @__PURE__ */ new Map()
17663
+ };
16375
17664
  const delta = isObject(choice.delta) ? choice.delta : void 0;
16376
17665
  const message = isObject(choice.message) ? choice.message : void 0;
16377
17666
  if (typeof delta?.content === "string") {
@@ -16387,6 +17676,10 @@ function aggregateChatCompletionChunks2(chunks) {
16387
17676
  if (choice.finish_reason !== void 0) {
16388
17677
  existing.finish_reason = choice.finish_reason;
16389
17678
  }
17679
+ const toolCallDeltas = getChatToolCallDeltas(delta) ?? getChatToolCallDeltas(message);
17680
+ if (toolCallDeltas) {
17681
+ mergeChatToolCallDeltas(existing.toolCallsByIndex, toolCallDeltas);
17682
+ }
16390
17683
  aggregatedChoices.set(index, existing);
16391
17684
  }
16392
17685
  }
@@ -16395,12 +17688,72 @@ function aggregateChatCompletionChunks2(chunks) {
16395
17688
  index,
16396
17689
  message: {
16397
17690
  content: choice.content,
16398
- role: choice.role ?? "assistant"
17691
+ role: choice.role ?? "assistant",
17692
+ ...choice.toolCallsByIndex.size > 0 ? {
17693
+ tool_calls: [...choice.toolCallsByIndex.entries()].sort(([leftIndex], [rightIndex]) => leftIndex - rightIndex).map(([, toolCall]) => toolCall)
17694
+ } : {}
16399
17695
  },
16400
17696
  ...choice.finish_reason !== void 0 ? { finish_reason: choice.finish_reason } : {}
16401
17697
  }))
16402
17698
  };
16403
17699
  }
17700
+ function getChatToolCallDeltas(value) {
17701
+ if (!Array.isArray(value?.tool_calls)) {
17702
+ return void 0;
17703
+ }
17704
+ const toolCalls = value.tool_calls.filter((toolCall) => isObject(toolCall));
17705
+ return toolCalls.length > 0 ? toolCalls : void 0;
17706
+ }
17707
+ function mergeChatToolCallDeltas(toolCallsByIndex, toolCallDeltas) {
17708
+ for (const toolDelta of toolCallDeltas) {
17709
+ const toolIndex = typeof toolDelta.index === "number" && toolDelta.index >= 0 ? toolDelta.index : 0;
17710
+ const existing = toolCallsByIndex.get(toolIndex);
17711
+ if (!existing) {
17712
+ toolCallsByIndex.set(toolIndex, createChatToolCall(toolDelta));
17713
+ continue;
17714
+ }
17715
+ mergeChatToolCall(existing, toolDelta);
17716
+ }
17717
+ }
17718
+ function createChatToolCall(toolDelta) {
17719
+ const toolFunction = isObject(toolDelta.function) ? toolDelta.function : {};
17720
+ const toolCallFunction = {
17721
+ arguments: typeof toolFunction.arguments === "string" ? toolFunction.arguments : ""
17722
+ };
17723
+ if (typeof toolFunction.name === "string") {
17724
+ toolCallFunction.name = toolFunction.name;
17725
+ }
17726
+ const toolCall = {
17727
+ function: toolCallFunction
17728
+ };
17729
+ if (typeof toolDelta.id === "string") {
17730
+ toolCall.id = toolDelta.id;
17731
+ }
17732
+ if (typeof toolDelta.type === "string") {
17733
+ toolCall.type = toolDelta.type;
17734
+ }
17735
+ return toolCall;
17736
+ }
17737
+ function mergeChatToolCall(existing, toolDelta) {
17738
+ const currentFunction = isObject(existing.function) ? existing.function : {};
17739
+ const deltaFunction = isObject(toolDelta.function) ? toolDelta.function : {};
17740
+ const currentArguments = typeof currentFunction.arguments === "string" ? currentFunction.arguments : "";
17741
+ const deltaArguments = typeof deltaFunction.arguments === "string" ? deltaFunction.arguments : "";
17742
+ if (typeof toolDelta.id === "string" && typeof existing.id !== "string") {
17743
+ existing.id = toolDelta.id;
17744
+ }
17745
+ if (typeof toolDelta.type === "string" && typeof existing.type !== "string") {
17746
+ existing.type = toolDelta.type;
17747
+ }
17748
+ const nextFunction = {
17749
+ ...currentFunction,
17750
+ arguments: `${currentArguments}${deltaArguments}`
17751
+ };
17752
+ if (typeof deltaFunction.name === "string" && typeof currentFunction.name !== "string") {
17753
+ nextFunction.name = deltaFunction.name;
17754
+ }
17755
+ existing.function = nextFunction;
17756
+ }
16404
17757
  function aggregateTextGenerationStreamChunks(chunks) {
16405
17758
  if (chunks.length === 0) {
16406
17759
  return void 0;
@@ -18445,6 +19798,8 @@ var MISTRAL_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
18445
19798
  "presence_penalty",
18446
19799
  "randomSeed",
18447
19800
  "random_seed",
19801
+ "reasoningEffort",
19802
+ "reasoning_effort",
18448
19803
  "responseFormat",
18449
19804
  "response_format",
18450
19805
  "safePrompt",
@@ -18568,22 +19923,114 @@ function extractMistralStreamingMetrics(result, startTime) {
18568
19923
  if (startTime) {
18569
19924
  metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
18570
19925
  }
18571
- return metrics;
19926
+ return metrics;
19927
+ }
19928
+ function extractDeltaText(content) {
19929
+ if (typeof content === "string") {
19930
+ return content;
19931
+ }
19932
+ if (!Array.isArray(content)) {
19933
+ return void 0;
19934
+ }
19935
+ const textParts = content.map((part) => {
19936
+ if (!isObject(part) || part.type !== "text") {
19937
+ return "";
19938
+ }
19939
+ return typeof part.text === "string" ? part.text : "";
19940
+ }).filter((part) => part.length > 0);
19941
+ return textParts.length > 0 ? textParts.join("") : void 0;
19942
+ }
19943
+ function normalizeMistralTextContentPart(part) {
19944
+ if (!isObject(part) || part.type !== "text" || typeof part.text !== "string") {
19945
+ return void 0;
19946
+ }
19947
+ return {
19948
+ type: "text",
19949
+ text: part.text
19950
+ };
19951
+ }
19952
+ function normalizeMistralThinkingContentPart(part) {
19953
+ if (!isObject(part) || part.type !== "thinking") {
19954
+ return void 0;
19955
+ }
19956
+ const thinking = Array.isArray(part.thinking) ? part.thinking.map((thinkingPart) => normalizeMistralTextContentPart(thinkingPart)).filter(
19957
+ (thinkingPart) => thinkingPart !== void 0 && typeof thinkingPart.text === "string"
19958
+ ) : [];
19959
+ return {
19960
+ type: "thinking",
19961
+ thinking
19962
+ };
19963
+ }
19964
+ function normalizeMistralContentParts(content) {
19965
+ if (!Array.isArray(content)) {
19966
+ return [];
19967
+ }
19968
+ return content.map((part) => {
19969
+ return normalizeMistralTextContentPart(part) || normalizeMistralThinkingContentPart(part);
19970
+ }).filter((part) => part !== void 0);
19971
+ }
19972
+ function mergeMistralTextSegments(left, right) {
19973
+ const merged = left.map((part) => ({ ...part }));
19974
+ for (const part of right) {
19975
+ const lastPart = merged[merged.length - 1];
19976
+ if (lastPart && lastPart.type === "text" && typeof lastPart.text === "string" && typeof part.text === "string") {
19977
+ lastPart.text += part.text;
19978
+ continue;
19979
+ }
19980
+ merged.push({ ...part });
19981
+ }
19982
+ return merged;
19983
+ }
19984
+ function mergeMistralContentParts(left, right) {
19985
+ const merged = [...(left || []).map((part) => structuredClone(part))];
19986
+ for (const part of right) {
19987
+ const lastPart = merged[merged.length - 1];
19988
+ if (part.type === "text" && lastPart?.type === "text" && typeof lastPart.text === "string" && typeof part.text === "string") {
19989
+ lastPart.text += part.text;
19990
+ continue;
19991
+ }
19992
+ if (part.type === "thinking" && lastPart?.type === "thinking" && Array.isArray(lastPart.thinking) && Array.isArray(part.thinking)) {
19993
+ lastPart.thinking = mergeMistralTextSegments(
19994
+ lastPart.thinking,
19995
+ part.thinking
19996
+ );
19997
+ continue;
19998
+ }
19999
+ merged.push(structuredClone(part));
20000
+ }
20001
+ return merged;
18572
20002
  }
18573
- function extractDeltaText(content) {
20003
+ function appendMistralContent(accumulator, content) {
18574
20004
  if (typeof content === "string") {
18575
- return content;
20005
+ if (accumulator.contentParts) {
20006
+ accumulator.contentParts = mergeMistralContentParts(
20007
+ accumulator.contentParts,
20008
+ [{ type: "text", text: content }]
20009
+ );
20010
+ return;
20011
+ }
20012
+ accumulator.content = `${accumulator.content || ""}${content}`;
20013
+ return;
18576
20014
  }
18577
- if (!Array.isArray(content)) {
18578
- return void 0;
20015
+ const normalizedContentParts = normalizeMistralContentParts(content);
20016
+ if (normalizedContentParts.length === 0) {
20017
+ return;
18579
20018
  }
18580
- const textParts = content.map((part) => {
18581
- if (!isObject(part) || part.type !== "text") {
18582
- return "";
20019
+ const hasStructuredContent = normalizedContentParts.some(
20020
+ (part) => part.type !== "text"
20021
+ );
20022
+ if (!accumulator.contentParts && !hasStructuredContent) {
20023
+ const text = extractDeltaText(content);
20024
+ if (text) {
20025
+ accumulator.content = `${accumulator.content || ""}${text}`;
18583
20026
  }
18584
- return typeof part.text === "string" ? part.text : "";
18585
- }).filter((part) => part.length > 0);
18586
- return textParts.length > 0 ? textParts.join("") : void 0;
20027
+ return;
20028
+ }
20029
+ accumulator.contentParts = mergeMistralContentParts(
20030
+ accumulator.contentParts || (accumulator.content ? [{ type: "text", text: accumulator.content }] : []),
20031
+ normalizedContentParts
20032
+ );
20033
+ delete accumulator.content;
18587
20034
  }
18588
20035
  function getDeltaToolCalls(delta) {
18589
20036
  const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
@@ -18753,10 +20200,7 @@ function aggregateMistralStreamChunks(chunks) {
18753
20200
  if (!accumulator.role && typeof delta.role === "string") {
18754
20201
  accumulator.role = delta.role;
18755
20202
  }
18756
- const deltaText = extractDeltaText(delta.content);
18757
- if (deltaText) {
18758
- accumulator.content = `${accumulator.content || ""}${deltaText}`;
18759
- }
20203
+ appendMistralContent(accumulator, delta.content);
18760
20204
  accumulator.toolCalls = mergeToolCallDeltas(
18761
20205
  accumulator.toolCalls,
18762
20206
  getDeltaToolCalls(delta)
@@ -18774,7 +20218,7 @@ function aggregateMistralStreamChunks(chunks) {
18774
20218
  index: choice.index,
18775
20219
  message: {
18776
20220
  ...choice.role ? { role: choice.role } : {},
18777
- content: choice.content ?? null,
20221
+ content: choice.contentParts ?? choice.content ?? null,
18778
20222
  ...choice.toolCalls ? { toolCalls: choice.toolCalls } : {}
18779
20223
  },
18780
20224
  ...choice.finishReason !== void 0 ? { finishReason: choice.finishReason } : {}
@@ -19013,7 +20457,7 @@ var GoogleADKPlugin = class extends BasePlugin {
19013
20457
  start: (event) => {
19014
20458
  const req = event.arguments[0] ?? {};
19015
20459
  const tool = event.self;
19016
- const toolName = extractToolName(req, tool);
20460
+ const toolName = extractToolName2(req, tool);
19017
20461
  const parentSpan = findToolParentSpan(
19018
20462
  req,
19019
20463
  this.activeAgentSpans,
@@ -19052,7 +20496,7 @@ var GoogleADKPlugin = class extends BasePlugin {
19052
20496
  metrics.duration = end - state.startTime;
19053
20497
  state.span.log({
19054
20498
  output: event.result,
19055
- metrics: cleanMetrics2(metrics)
20499
+ metrics: cleanMetrics3(metrics)
19056
20500
  });
19057
20501
  } finally {
19058
20502
  state.span.end();
@@ -19271,7 +20715,7 @@ function extractToolCallId(req) {
19271
20715
  const toolContext = req.toolContext;
19272
20716
  return toolContext?.functionCallId;
19273
20717
  }
19274
- function extractToolName(req, tool) {
20718
+ function extractToolName2(req, tool) {
19275
20719
  if (typeof tool?.name === "string" && tool.name.length > 0) {
19276
20720
  return tool.name;
19277
20721
  }
@@ -19319,7 +20763,7 @@ function finalizeRunnerSpan(state, activeRunnerSpans) {
19319
20763
  }
19320
20764
  state.span.log({
19321
20765
  output: lastEvent ? extractEventOutput(lastEvent) : void 0,
19322
- metrics: cleanMetrics2(metrics)
20766
+ metrics: cleanMetrics3(metrics)
19323
20767
  });
19324
20768
  } finally {
19325
20769
  cleanupActiveRunnerSpan(state, activeRunnerSpans);
@@ -19336,7 +20780,7 @@ function finalizeAgentSpan(state, activeAgentSpans) {
19336
20780
  metrics.duration = end - state.startTime;
19337
20781
  state.span.log({
19338
20782
  output: lastEvent ? extractEventOutput(lastEvent) : void 0,
19339
- metrics: cleanMetrics2(metrics)
20783
+ metrics: cleanMetrics3(metrics)
19340
20784
  });
19341
20785
  } finally {
19342
20786
  cleanupActiveAgentSpan(state, activeAgentSpans);
@@ -19422,7 +20866,7 @@ function populateUsageMetrics2(metrics, usage) {
19422
20866
  metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
19423
20867
  }
19424
20868
  }
19425
- function cleanMetrics2(metrics) {
20869
+ function cleanMetrics3(metrics) {
19426
20870
  const cleaned = {};
19427
20871
  for (const [key, value] of Object.entries(metrics)) {
19428
20872
  if (value !== null && value !== void 0) {
@@ -19550,6 +20994,11 @@ var CHAT_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
19550
20994
  "strictTools",
19551
20995
  "strict_tools",
19552
20996
  "temperature",
20997
+ "thinking",
20998
+ "thinkingTokenBudget",
20999
+ "thinkingType",
21000
+ "thinking_token_budget",
21001
+ "thinking_type",
19553
21002
  "toolChoice",
19554
21003
  "tool_choice"
19555
21004
  ]);
@@ -19770,6 +21219,11 @@ function mergeUsageMetrics(metrics, usage) {
19770
21219
  "tokens",
19771
21220
  tokenContainer.totalTokens ?? tokenContainer.total_tokens
19772
21221
  );
21222
+ setMetricIfNumber(
21223
+ metrics,
21224
+ "reasoning_tokens",
21225
+ tokenContainer.reasoningTokens ?? tokenContainer.reasoning_tokens ?? tokenContainer.thinkingTokens ?? tokenContainer.thinking_tokens
21226
+ );
19773
21227
  }
19774
21228
  const billedUnits = (isObject(source.billedUnits) ? source.billedUnits : void 0) || (isObject(source.billed_units) ? source.billed_units : void 0);
19775
21229
  if (billedUnits) {
@@ -19850,13 +21304,87 @@ function extractV8DeltaText(chunk) {
19850
21304
  }
19851
21305
  return void 0;
19852
21306
  }
21307
+ function getV8ContentIndex(chunk) {
21308
+ return typeof chunk.index === "number" ? chunk.index : 0;
21309
+ }
21310
+ function toContentBlockType(value) {
21311
+ return value === "text" || value === "thinking" ? value : void 0;
21312
+ }
21313
+ function getOrCreateContentBlock(contentBlocksByIndex, contentBlockOrder, index) {
21314
+ if (!contentBlockOrder.includes(index)) {
21315
+ contentBlockOrder.push(index);
21316
+ }
21317
+ if (!(index in contentBlocksByIndex)) {
21318
+ contentBlocksByIndex[index] = {
21319
+ text: "",
21320
+ thinking: ""
21321
+ };
21322
+ }
21323
+ return contentBlocksByIndex[index];
21324
+ }
21325
+ function appendV8ContentBlock(contentBlocksByIndex, contentBlockOrder, index, content) {
21326
+ if (typeof content === "string") {
21327
+ const block2 = getOrCreateContentBlock(
21328
+ contentBlocksByIndex,
21329
+ contentBlockOrder,
21330
+ index
21331
+ );
21332
+ block2.type ??= "text";
21333
+ block2.text += content;
21334
+ return;
21335
+ }
21336
+ if (!isObject(content)) {
21337
+ return;
21338
+ }
21339
+ const block = getOrCreateContentBlock(
21340
+ contentBlocksByIndex,
21341
+ contentBlockOrder,
21342
+ index
21343
+ );
21344
+ const contentType = toContentBlockType(content.type);
21345
+ if (contentType) {
21346
+ block.type = contentType;
21347
+ }
21348
+ if (typeof content.text === "string") {
21349
+ block.type ??= "text";
21350
+ block.text += content.text;
21351
+ }
21352
+ if (typeof content.thinking === "string") {
21353
+ block.type ??= "thinking";
21354
+ block.thinking += content.thinking;
21355
+ }
21356
+ }
21357
+ function serializeAggregatedContentBlocks(contentBlocksByIndex, contentBlockOrder) {
21358
+ return contentBlockOrder.sort((left, right) => left - right).flatMap((index) => {
21359
+ const block = contentBlocksByIndex[index];
21360
+ if (!block) {
21361
+ return [];
21362
+ }
21363
+ if (block.type === "thinking" && block.thinking.length > 0) {
21364
+ return [{ type: "thinking", thinking: block.thinking }];
21365
+ }
21366
+ if (block.text.length > 0) {
21367
+ return [{ type: "text", text: block.text }];
21368
+ }
21369
+ if (block.thinking.length > 0) {
21370
+ return [{ type: "thinking", thinking: block.thinking }];
21371
+ }
21372
+ return [];
21373
+ });
21374
+ }
21375
+ function hasThinkingContent(contentBlocks) {
21376
+ return contentBlocks.some((block) => block.type === "thinking");
21377
+ }
19853
21378
  function aggregateCohereChatStreamChunks(chunks) {
19854
21379
  const textDeltas = [];
21380
+ const contentBlocksByIndex = {};
21381
+ const contentBlockOrder = [];
19855
21382
  const toolCallsByIndex = {};
19856
21383
  const toolCallOrder = [];
19857
21384
  let terminalResponse;
19858
21385
  let role;
19859
21386
  let finishReason;
21387
+ let toolPlan = "";
19860
21388
  let metadata = {};
19861
21389
  let metrics = {};
19862
21390
  for (const chunk of chunks) {
@@ -19914,12 +21442,36 @@ function aggregateCohereChatStreamChunks(chunks) {
19914
21442
  continue;
19915
21443
  }
19916
21444
  if (eventType === "content-delta") {
21445
+ appendV8ContentBlock(
21446
+ contentBlocksByIndex,
21447
+ contentBlockOrder,
21448
+ getV8ContentIndex(chunk),
21449
+ isObject(chunk.delta) && isObject(chunk.delta.message) ? chunk.delta.message.content : void 0
21450
+ );
19917
21451
  const text = extractV8DeltaText(chunk);
19918
21452
  if (text) {
19919
21453
  textDeltas.push(text);
19920
21454
  }
19921
21455
  continue;
19922
21456
  }
21457
+ if (eventType === "content-start") {
21458
+ appendV8ContentBlock(
21459
+ contentBlocksByIndex,
21460
+ contentBlockOrder,
21461
+ getV8ContentIndex(chunk),
21462
+ isObject(chunk.delta) && isObject(chunk.delta.message) ? chunk.delta.message.content : void 0
21463
+ );
21464
+ continue;
21465
+ }
21466
+ if (eventType === "tool-plan-delta") {
21467
+ if (isObject(chunk.delta) && isObject(chunk.delta.message)) {
21468
+ 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;
21469
+ if (deltaToolPlan) {
21470
+ toolPlan += deltaToolPlan;
21471
+ }
21472
+ }
21473
+ continue;
21474
+ }
19923
21475
  if (eventType === "tool-call-start") {
19924
21476
  const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
19925
21477
  Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
@@ -19973,13 +21525,26 @@ function aggregateCohereChatStreamChunks(chunks) {
19973
21525
  }
19974
21526
  }
19975
21527
  const mergedToolCalls = toolCallOrder.sort((left, right) => left - right).map((index) => toolCallsByIndex[index]).filter((toolCall) => isObject(toolCall));
21528
+ const aggregatedContentBlocks = serializeAggregatedContentBlocks(
21529
+ contentBlocksByIndex,
21530
+ contentBlockOrder
21531
+ );
19976
21532
  let output = extractCohereChatOutput(terminalResponse);
19977
21533
  if (output === void 0) {
19978
21534
  const mergedText = textDeltas.join("");
19979
- if (mergedToolCalls.length > 0 || role || mergedText.length > 0) {
21535
+ const shouldUseStructuredContent = hasThinkingContent(aggregatedContentBlocks) || toolPlan.length > 0;
21536
+ if (shouldUseStructuredContent) {
21537
+ output = {
21538
+ ...role ? { role } : {},
21539
+ ...aggregatedContentBlocks.length > 0 ? { content: aggregatedContentBlocks } : {},
21540
+ ...toolPlan.length > 0 ? { toolPlan } : {},
21541
+ ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
21542
+ };
21543
+ } else if (mergedToolCalls.length > 0 || role || mergedText.length > 0 || aggregatedContentBlocks.length > 0) {
21544
+ const textContent = mergedText.length > 0 ? mergedText : aggregatedContentBlocks[0]?.type === "text" ? aggregatedContentBlocks[0].text : void 0;
19980
21545
  output = {
19981
21546
  ...role ? { role } : {},
19982
- ...mergedText.length > 0 ? { content: mergedText } : {},
21547
+ ...textContent ? { content: textContent } : {},
19983
21548
  ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
19984
21549
  };
19985
21550
  }
@@ -19997,6 +21562,98 @@ function aggregateCohereChatStreamChunks(chunks) {
19997
21562
  };
19998
21563
  }
19999
21564
 
21565
+ // src/instrumentation/plugins/groq-channels.ts
21566
+ var groqChannels = defineChannels("groq-sdk", {
21567
+ chatCompletionsCreate: channel({
21568
+ channelName: "chat.completions.create",
21569
+ kind: "async"
21570
+ }),
21571
+ embeddingsCreate: channel(
21572
+ {
21573
+ channelName: "embeddings.create",
21574
+ kind: "async"
21575
+ }
21576
+ )
21577
+ });
21578
+
21579
+ // src/instrumentation/plugins/groq-plugin.ts
21580
+ var GroqPlugin = class extends BasePlugin {
21581
+ onEnable() {
21582
+ this.unsubscribers.push(
21583
+ traceStreamingChannel(groqChannels.chatCompletionsCreate, {
21584
+ name: "groq.chat.completions.create",
21585
+ type: "llm" /* LLM */,
21586
+ extractInput: ([params]) => {
21587
+ const { messages, ...metadata } = params;
21588
+ return {
21589
+ input: processInputAttachments(messages),
21590
+ metadata: { ...metadata, provider: "groq" }
21591
+ };
21592
+ },
21593
+ extractOutput: (result) => result?.choices,
21594
+ extractMetrics: (result, startTime) => {
21595
+ const metrics = parseGroqMetrics(result);
21596
+ if (startTime) {
21597
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
21598
+ }
21599
+ return metrics;
21600
+ },
21601
+ aggregateChunks: aggregateGroqChatCompletionChunks
21602
+ })
21603
+ );
21604
+ this.unsubscribers.push(
21605
+ traceAsyncChannel(groqChannels.embeddingsCreate, {
21606
+ name: "groq.embeddings.create",
21607
+ type: "llm" /* LLM */,
21608
+ extractInput: ([params]) => {
21609
+ const { input, ...metadata } = params;
21610
+ return {
21611
+ input,
21612
+ metadata: { ...metadata, provider: "groq" }
21613
+ };
21614
+ },
21615
+ extractOutput: (result) => {
21616
+ const embedding = result?.data?.[0]?.embedding;
21617
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
21618
+ },
21619
+ extractMetrics: (result) => parseGroqMetrics(result)
21620
+ })
21621
+ );
21622
+ }
21623
+ onDisable() {
21624
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
21625
+ }
21626
+ };
21627
+ function parseGroqMetrics(result) {
21628
+ const metrics = parseMetricsFromUsage(result?.usage);
21629
+ const xGroq = result?.x_groq;
21630
+ if (!xGroq || typeof xGroq !== "object") {
21631
+ return metrics;
21632
+ }
21633
+ const extraUsage = "usage" in xGroq ? xGroq.usage : void 0;
21634
+ if (!extraUsage || typeof extraUsage !== "object") {
21635
+ return metrics;
21636
+ }
21637
+ const dramCachedTokens = extraUsage["dram_cached_tokens"];
21638
+ const sramCachedTokens = extraUsage["sram_cached_tokens"];
21639
+ return {
21640
+ ...metrics,
21641
+ ...typeof dramCachedTokens === "number" ? { dram_cached_tokens: dramCachedTokens } : {},
21642
+ ...typeof sramCachedTokens === "number" ? { sram_cached_tokens: sramCachedTokens } : {}
21643
+ };
21644
+ }
21645
+ function aggregateGroqChatCompletionChunks(chunks, streamResult, endEvent) {
21646
+ const aggregated = aggregateChatCompletionChunks(
21647
+ chunks,
21648
+ streamResult,
21649
+ endEvent
21650
+ );
21651
+ return {
21652
+ metrics: aggregated.metrics,
21653
+ output: aggregated.output
21654
+ };
21655
+ }
21656
+
20000
21657
  // src/instrumentation/braintrust-plugin.ts
20001
21658
  var BraintrustPlugin = class extends BasePlugin {
20002
21659
  config;
@@ -20004,6 +21661,7 @@ var BraintrustPlugin = class extends BasePlugin {
20004
21661
  anthropicPlugin = null;
20005
21662
  aiSDKPlugin = null;
20006
21663
  claudeAgentSDKPlugin = null;
21664
+ cursorSDKPlugin = null;
20007
21665
  googleGenAIPlugin = null;
20008
21666
  huggingFacePlugin = null;
20009
21667
  openRouterPlugin = null;
@@ -20011,6 +21669,7 @@ var BraintrustPlugin = class extends BasePlugin {
20011
21669
  mistralPlugin = null;
20012
21670
  googleADKPlugin = null;
20013
21671
  coherePlugin = null;
21672
+ groqPlugin = null;
20014
21673
  constructor(config = {}) {
20015
21674
  super();
20016
21675
  this.config = config;
@@ -20033,6 +21692,10 @@ var BraintrustPlugin = class extends BasePlugin {
20033
21692
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
20034
21693
  this.claudeAgentSDKPlugin.enable();
20035
21694
  }
21695
+ if (integrations.cursorSDK !== false && integrations.cursor !== false) {
21696
+ this.cursorSDKPlugin = new CursorSDKPlugin();
21697
+ this.cursorSDKPlugin.enable();
21698
+ }
20036
21699
  if (integrations.googleGenAI !== false && integrations.google !== false) {
20037
21700
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
20038
21701
  this.googleGenAIPlugin.enable();
@@ -20061,6 +21724,10 @@ var BraintrustPlugin = class extends BasePlugin {
20061
21724
  this.coherePlugin = new CoherePlugin();
20062
21725
  this.coherePlugin.enable();
20063
21726
  }
21727
+ if (integrations.groq !== false) {
21728
+ this.groqPlugin = new GroqPlugin();
21729
+ this.groqPlugin.enable();
21730
+ }
20064
21731
  }
20065
21732
  onDisable() {
20066
21733
  if (this.openaiPlugin) {
@@ -20079,6 +21746,10 @@ var BraintrustPlugin = class extends BasePlugin {
20079
21746
  this.claudeAgentSDKPlugin.disable();
20080
21747
  this.claudeAgentSDKPlugin = null;
20081
21748
  }
21749
+ if (this.cursorSDKPlugin) {
21750
+ this.cursorSDKPlugin.disable();
21751
+ this.cursorSDKPlugin = null;
21752
+ }
20082
21753
  if (this.googleGenAIPlugin) {
20083
21754
  this.googleGenAIPlugin.disable();
20084
21755
  this.googleGenAIPlugin = null;
@@ -20107,6 +21778,10 @@ var BraintrustPlugin = class extends BasePlugin {
20107
21778
  this.coherePlugin.disable();
20108
21779
  this.coherePlugin = null;
20109
21780
  }
21781
+ if (this.groqPlugin) {
21782
+ this.groqPlugin.disable();
21783
+ this.groqPlugin = null;
21784
+ }
20110
21785
  }
20111
21786
  };
20112
21787
 
@@ -20180,6 +21855,8 @@ var PluginRegistry = class {
20180
21855
  google: true,
20181
21856
  huggingface: true,
20182
21857
  claudeAgentSDK: true,
21858
+ cursor: true,
21859
+ cursorSDK: true,
20183
21860
  openrouter: true,
20184
21861
  openrouterAgent: true,
20185
21862
  mistral: true,
@@ -20196,7 +21873,11 @@ var PluginRegistry = class {
20196
21873
  if (disabledList) {
20197
21874
  const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
20198
21875
  for (const sdk of disabled) {
20199
- integrations[sdk] = false;
21876
+ if (sdk === "cursor-sdk") {
21877
+ integrations.cursorSDK = false;
21878
+ } else {
21879
+ integrations[sdk] = false;
21880
+ }
20200
21881
  }
20201
21882
  }
20202
21883
  return { integrations };
@@ -20456,8 +22137,10 @@ __export(exports_exports, {
20456
22137
  wrapAnthropic: () => wrapAnthropic,
20457
22138
  wrapClaudeAgentSDK: () => wrapClaudeAgentSDK,
20458
22139
  wrapCohere: () => wrapCohere,
22140
+ wrapCursorSDK: () => wrapCursorSDK,
20459
22141
  wrapGoogleADK: () => wrapGoogleADK,
20460
22142
  wrapGoogleGenAI: () => wrapGoogleGenAI,
22143
+ wrapGroq: () => wrapGroq,
20461
22144
  wrapHuggingFace: () => wrapHuggingFace,
20462
22145
  wrapMastraAgent: () => wrapMastraAgent,
20463
22146
  wrapMistral: () => wrapMistral,
@@ -22072,6 +23755,130 @@ function claudeAgentSDKProxy(sdk) {
22072
23755
  });
22073
23756
  }
22074
23757
 
23758
+ // src/wrappers/cursor-sdk.ts
23759
+ var WRAPPED_AGENT2 = Symbol.for("braintrust.cursor-sdk.wrapped-agent");
23760
+ function wrapCursorSDK(sdk) {
23761
+ if (!sdk || typeof sdk !== "object") {
23762
+ return sdk;
23763
+ }
23764
+ const maybeSDK = sdk;
23765
+ if (!maybeSDK.Agent || typeof maybeSDK.Agent !== "function") {
23766
+ console.warn("Unsupported Cursor SDK. Not wrapping.");
23767
+ return sdk;
23768
+ }
23769
+ const target = isModuleNamespace2(sdk) ? Object.setPrototypeOf({}, sdk) : sdk;
23770
+ return new Proxy(target, {
23771
+ get(target2, prop, receiver) {
23772
+ const value = Reflect.get(target2, prop, receiver);
23773
+ if (prop === "Agent" && typeof value === "function") {
23774
+ return wrapCursorAgentClass(value);
23775
+ }
23776
+ if (typeof value === "function") {
23777
+ return value.bind(target2);
23778
+ }
23779
+ return value;
23780
+ }
23781
+ });
23782
+ }
23783
+ function isModuleNamespace2(obj) {
23784
+ if (!obj || typeof obj !== "object") {
23785
+ return false;
23786
+ }
23787
+ if (obj.constructor?.name === "Module") {
23788
+ return true;
23789
+ }
23790
+ const keys = Object.keys(obj);
23791
+ if (keys.length === 0) {
23792
+ return false;
23793
+ }
23794
+ const descriptor = Object.getOwnPropertyDescriptor(obj, keys[0]);
23795
+ return descriptor ? !descriptor.configurable && !descriptor.writable : false;
23796
+ }
23797
+ function wrapCursorAgentClass(Agent) {
23798
+ const cache = /* @__PURE__ */ new Map();
23799
+ return new Proxy(Agent, {
23800
+ get(target, prop, receiver) {
23801
+ if (cache.has(prop)) {
23802
+ return cache.get(prop);
23803
+ }
23804
+ const value = Reflect.get(target, prop, receiver);
23805
+ if (prop === "create" && typeof value === "function") {
23806
+ const wrapped = async function(options) {
23807
+ const args = [options];
23808
+ return cursorSDKChannels.create.tracePromise(
23809
+ async () => wrapCursorAgent(await Reflect.apply(value, target, args)),
23810
+ { arguments: args }
23811
+ );
23812
+ };
23813
+ cache.set(prop, wrapped);
23814
+ return wrapped;
23815
+ }
23816
+ if (prop === "resume" && typeof value === "function") {
23817
+ const wrapped = async function(agentId, options) {
23818
+ const args = [agentId, options];
23819
+ return cursorSDKChannels.resume.tracePromise(
23820
+ async () => wrapCursorAgent(await Reflect.apply(value, target, args)),
23821
+ { arguments: args }
23822
+ );
23823
+ };
23824
+ cache.set(prop, wrapped);
23825
+ return wrapped;
23826
+ }
23827
+ if (prop === "prompt" && typeof value === "function") {
23828
+ const wrapped = async function(message, options) {
23829
+ const args = [message, options];
23830
+ return cursorSDKChannels.prompt.tracePromise(
23831
+ () => Reflect.apply(value, target, args),
23832
+ { arguments: args }
23833
+ );
23834
+ };
23835
+ cache.set(prop, wrapped);
23836
+ return wrapped;
23837
+ }
23838
+ if (typeof value === "function") {
23839
+ const bound = value.bind(target);
23840
+ cache.set(prop, bound);
23841
+ return bound;
23842
+ }
23843
+ return value;
23844
+ }
23845
+ });
23846
+ }
23847
+ function wrapCursorAgent(agent) {
23848
+ if (!agent || typeof agent !== "object") {
23849
+ return agent;
23850
+ }
23851
+ if (agent[WRAPPED_AGENT2]) {
23852
+ return agent;
23853
+ }
23854
+ const proxy = new Proxy(agent, {
23855
+ get(target, prop, receiver) {
23856
+ if (prop === WRAPPED_AGENT2) {
23857
+ return true;
23858
+ }
23859
+ const value = Reflect.get(target, prop, receiver);
23860
+ if (prop === "send" && typeof value === "function") {
23861
+ return function(message, options) {
23862
+ const args = [message, options];
23863
+ return cursorSDKChannels.send.tracePromise(
23864
+ () => Reflect.apply(value, target, args),
23865
+ {
23866
+ agent: target,
23867
+ arguments: args,
23868
+ operation: "send"
23869
+ }
23870
+ );
23871
+ };
23872
+ }
23873
+ if (typeof value === "function") {
23874
+ return value.bind(target);
23875
+ }
23876
+ return value;
23877
+ }
23878
+ });
23879
+ return proxy;
23880
+ }
23881
+
22075
23882
  // src/wrappers/google-genai.ts
22076
23883
  function wrapGoogleGenAI(googleGenAI) {
22077
23884
  if (!googleGenAI || typeof googleGenAI !== "object") {
@@ -22825,6 +24632,94 @@ function wrapRerank3(rerank) {
22825
24632
  });
22826
24633
  }
22827
24634
 
24635
+ // src/wrappers/groq.ts
24636
+ function wrapGroq(groq) {
24637
+ if (isSupportedGroqClient(groq)) {
24638
+ return groqProxy(groq);
24639
+ }
24640
+ console.warn("Unsupported Groq library. Not wrapping.");
24641
+ return groq;
24642
+ }
24643
+ function isRecord3(value) {
24644
+ return typeof value === "object" && value !== null;
24645
+ }
24646
+ function hasFunction4(value, methodName) {
24647
+ return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
24648
+ }
24649
+ function hasChat2(value) {
24650
+ return isRecord3(value) && isRecord3(value.completions) && hasFunction4(value.completions, "create");
24651
+ }
24652
+ function hasEmbeddings2(value) {
24653
+ return hasFunction4(value, "create");
24654
+ }
24655
+ function isSupportedGroqClient(value) {
24656
+ return isRecord3(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
24657
+ }
24658
+ function groqProxy(groq) {
24659
+ const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
24660
+ const completionProxy = groq.chat?.completions ? new Proxy(groq.chat.completions, {
24661
+ get(target, prop, receiver) {
24662
+ if (prop === "create") {
24663
+ return wrapChatCompletionsCreate(target.create.bind(target));
24664
+ }
24665
+ return Reflect.get(target, prop, receiver);
24666
+ }
24667
+ }) : void 0;
24668
+ const chatProxy3 = groq.chat ? new Proxy(groq.chat, {
24669
+ get(target, prop, receiver) {
24670
+ if (prop === "completions") {
24671
+ return completionProxy ?? target.completions;
24672
+ }
24673
+ return Reflect.get(target, prop, receiver);
24674
+ }
24675
+ }) : void 0;
24676
+ const embeddingsProxy3 = groq.embeddings ? new Proxy(groq.embeddings, {
24677
+ get(target, prop, receiver) {
24678
+ if (prop === "create") {
24679
+ return wrapEmbeddingsCreate2(target.create.bind(target));
24680
+ }
24681
+ return Reflect.get(target, prop, receiver);
24682
+ }
24683
+ }) : void 0;
24684
+ const topLevelProxy = new Proxy(groq, {
24685
+ get(target, prop, receiver) {
24686
+ switch (prop) {
24687
+ case "chat":
24688
+ return chatProxy3 ?? target.chat;
24689
+ case "embeddings":
24690
+ return embeddingsProxy3 ?? target.embeddings;
24691
+ }
24692
+ const value = Reflect.get(target, prop, target);
24693
+ if (typeof value !== "function") {
24694
+ return value;
24695
+ }
24696
+ const cachedValue = privateMethodWorkaroundCache.get(value);
24697
+ if (cachedValue) {
24698
+ return cachedValue;
24699
+ }
24700
+ const thisBoundValue = function(...args) {
24701
+ const thisArg = this === topLevelProxy ? target : this;
24702
+ const output = Reflect.apply(value, thisArg, args);
24703
+ return output === target ? topLevelProxy : output;
24704
+ };
24705
+ privateMethodWorkaroundCache.set(value, thisBoundValue);
24706
+ return thisBoundValue;
24707
+ }
24708
+ });
24709
+ return topLevelProxy;
24710
+ }
24711
+ function wrapChatCompletionsCreate(create) {
24712
+ return (request, options) => groqChannels.chatCompletionsCreate.tracePromise(
24713
+ () => create(request, options),
24714
+ { arguments: [request] }
24715
+ );
24716
+ }
24717
+ function wrapEmbeddingsCreate2(create) {
24718
+ return (request, options) => groqChannels.embeddingsCreate.tracePromise(() => create(request, options), {
24719
+ arguments: [request]
24720
+ });
24721
+ }
24722
+
22828
24723
  // src/wrappers/vitest/context-manager.ts
22829
24724
  var VitestContextManager = class {
22830
24725
  /**