braintrust 3.9.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dev/dist/index.d.mts +107 -1
  2. package/dev/dist/index.d.ts +107 -1
  3. package/dev/dist/index.js +2126 -443
  4. package/dev/dist/index.mjs +1814 -131
  5. package/dist/auto-instrumentations/bundler/esbuild.cjs +166 -0
  6. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  7. package/dist/auto-instrumentations/bundler/rollup.cjs +166 -0
  8. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  9. package/dist/auto-instrumentations/bundler/vite.cjs +166 -0
  10. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  11. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +163 -0
  12. package/dist/auto-instrumentations/bundler/webpack.cjs +166 -0
  13. package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
  14. package/dist/auto-instrumentations/{chunk-KIMMUFAK.mjs → chunk-GZNXBBPU.mjs} +164 -1
  15. package/dist/auto-instrumentations/{chunk-G7F6HZGE.mjs → chunk-XWEQQOQH.mjs} +8 -1
  16. package/dist/auto-instrumentations/hook.mjs +255 -8
  17. package/dist/auto-instrumentations/index.cjs +256 -7
  18. package/dist/auto-instrumentations/index.d.mts +5 -1
  19. package/dist/auto-instrumentations/index.d.ts +5 -1
  20. package/dist/auto-instrumentations/index.mjs +96 -8
  21. package/dist/browser.d.mts +141 -7
  22. package/dist/browser.d.ts +141 -7
  23. package/dist/browser.js +2035 -140
  24. package/dist/browser.mjs +2035 -140
  25. package/dist/cli.js +1822 -139
  26. package/dist/edge-light.d.mts +1 -1
  27. package/dist/edge-light.d.ts +1 -1
  28. package/dist/edge-light.js +2035 -140
  29. package/dist/edge-light.mjs +2035 -140
  30. package/dist/index.d.mts +141 -7
  31. package/dist/index.d.ts +141 -7
  32. package/dist/index.js +2397 -502
  33. package/dist/index.mjs +2035 -140
  34. package/dist/instrumentation/index.d.mts +7 -0
  35. package/dist/instrumentation/index.d.ts +7 -0
  36. package/dist/instrumentation/index.js +1662 -167
  37. package/dist/instrumentation/index.mjs +1662 -167
  38. package/dist/workerd.d.mts +1 -1
  39. package/dist/workerd.d.ts +1 -1
  40. package/dist/workerd.js +2035 -140
  41. package/dist/workerd.mjs +2035 -140
  42. package/package.json +6 -6
package/dist/workerd.js CHANGED
@@ -159,8 +159,10 @@ __export(workerd_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,
@@ -1978,6 +1980,7 @@ var TopicMapData = import_v36.z.object({
1978
1980
  report_key: import_v36.z.string().optional(),
1979
1981
  topic_names: import_v36.z.record(import_v36.z.string()).optional(),
1980
1982
  generation_settings: TopicMapGenerationSettings.optional(),
1983
+ disable_reconciliation: import_v36.z.boolean().optional(),
1981
1984
  distance_threshold: import_v36.z.number().optional()
1982
1985
  });
1983
1986
  var BatchedFacetData = import_v36.z.object({
@@ -2308,28 +2311,6 @@ var EnvVar = import_v36.z.object({
2308
2311
  secret_type: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2309
2312
  secret_category: import_v36.z.enum(["env_var", "ai_provider", "sandbox_provider"]).optional().default("env_var")
2310
2313
  });
2311
- var EvalStatusPageTheme = import_v36.z.enum(["light", "dark"]);
2312
- var EvalStatusPageConfig = import_v36.z.object({
2313
- score_columns: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
2314
- metric_columns: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]),
2315
- grouping_field: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
2316
- filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
2317
- sort_by: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
2318
- sort_order: import_v36.z.union([import_v36.z.enum(["asc", "desc"]), import_v36.z.null()]),
2319
- api_key: import_v36.z.union([import_v36.z.string(), import_v36.z.null()])
2320
- }).partial();
2321
- var EvalStatusPage = import_v36.z.object({
2322
- id: import_v36.z.string().uuid(),
2323
- project_id: import_v36.z.string().uuid(),
2324
- user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2325
- created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2326
- deleted_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2327
- name: import_v36.z.string(),
2328
- description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2329
- logo_url: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2330
- theme: EvalStatusPageTheme,
2331
- config: EvalStatusPageConfig
2332
- });
2333
2314
  var RepoInfo = import_v36.z.union([
2334
2315
  import_v36.z.object({
2335
2316
  commit: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
@@ -2356,6 +2337,15 @@ var Experiment = import_v36.z.object({
2356
2337
  deleted_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2357
2338
  dataset_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2358
2339
  dataset_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2340
+ internal_metadata: import_v36.z.union([
2341
+ import_v36.z.object({
2342
+ dataset_filter: import_v36.z.union([
2343
+ import_v36.z.object({}).partial().passthrough(),
2344
+ import_v36.z.null()
2345
+ ])
2346
+ }).partial().passthrough(),
2347
+ import_v36.z.null()
2348
+ ]).optional(),
2359
2349
  parameters_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2360
2350
  parameters_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
2361
2351
  public: import_v36.z.boolean(),
@@ -3092,14 +3082,21 @@ var ProjectAutomation = import_v36.z.object({
3092
3082
  import_v36.z.object({ type: import_v36.z.literal("log_spans") }),
3093
3083
  import_v36.z.object({ type: import_v36.z.literal("btql_query"), btql_query: import_v36.z.string() })
3094
3084
  ]),
3085
+ scope: import_v36.z.union([SpanScope, TraceScope, GroupScope, import_v36.z.null()]).optional(),
3095
3086
  export_path: import_v36.z.string(),
3096
3087
  format: import_v36.z.enum(["jsonl", "parquet"]),
3097
3088
  interval_seconds: import_v36.z.number().gte(1).lte(2592e3),
3098
- credentials: import_v36.z.object({
3099
- type: import_v36.z.literal("aws_iam"),
3100
- role_arn: import_v36.z.string(),
3101
- external_id: import_v36.z.string()
3102
- }),
3089
+ credentials: import_v36.z.union([
3090
+ import_v36.z.object({
3091
+ type: import_v36.z.literal("aws_iam"),
3092
+ role_arn: import_v36.z.string(),
3093
+ external_id: import_v36.z.string()
3094
+ }),
3095
+ import_v36.z.object({
3096
+ type: import_v36.z.literal("gcp_service_account"),
3097
+ service_account_email: import_v36.z.string()
3098
+ })
3099
+ ]),
3103
3100
  batch_size: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
3104
3101
  }),
3105
3102
  import_v36.z.object({
@@ -3479,7 +3476,7 @@ var ViewOptions = import_v36.z.union([
3479
3476
  import_v36.z.object({ from: import_v36.z.string(), to: import_v36.z.string() }),
3480
3477
  import_v36.z.null()
3481
3478
  ]),
3482
- queryShape: import_v36.z.union([import_v36.z.enum(["traces", "spans"]), import_v36.z.null()]),
3479
+ queryShape: import_v36.z.union([import_v36.z.enum(["traces", "spans", "topics"]), import_v36.z.null()]),
3483
3480
  cluster: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
3484
3481
  freezeColumns: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()])
3485
3482
  }).partial(),
@@ -4493,6 +4490,19 @@ var RESET_CONTEXT_MANAGER_STATE = Symbol.for(
4493
4490
  "braintrust.resetContextManagerState"
4494
4491
  );
4495
4492
  var DEFAULT_MAX_REQUEST_SIZE = 6 * 1024 * 1024;
4493
+ var datasetSnapshotRegisterResponseSchema = import_v38.z.object({
4494
+ dataset_snapshot: DatasetSnapshot,
4495
+ found_existing: import_v38.z.boolean().optional()
4496
+ });
4497
+ var datasetRestorePreviewResultSchema = import_v38.z.object({
4498
+ rows_to_restore: import_v38.z.number(),
4499
+ rows_to_delete: import_v38.z.number()
4500
+ });
4501
+ var datasetRestoreResultSchema = import_v38.z.object({
4502
+ xact_id: import_v38.z.string().nullable(),
4503
+ rows_restored: import_v38.z.number(),
4504
+ rows_deleted: import_v38.z.number()
4505
+ });
4496
4506
  var parametersRowSchema = import_v38.z.object({
4497
4507
  id: import_v38.z.string().uuid(),
4498
4508
  _xact_id: import_v38.z.string(),
@@ -6714,6 +6724,33 @@ Error: ${errorText}`;
6714
6724
  this.queue.enforceQueueSizeLimit(enforce);
6715
6725
  }
6716
6726
  };
6727
+ function isDatasetSnapshotNameLookup(lookup) {
6728
+ return "snapshotName" in lookup;
6729
+ }
6730
+ function assertDatasetSnapshotLookup(lookup) {
6731
+ const hasSnapshotName = lookup.snapshotName !== void 0;
6732
+ const hasXactId = lookup.xactId !== void 0;
6733
+ if (hasSnapshotName === hasXactId) {
6734
+ throw new Error("Exactly one of snapshotName or xactId must be provided");
6735
+ }
6736
+ }
6737
+ function getExperimentDatasetFilter({
6738
+ dataset,
6739
+ _internal_btql
6740
+ }) {
6741
+ if (_internal_btql !== void 0) {
6742
+ return _internal_btql;
6743
+ }
6744
+ if (!(dataset instanceof Dataset2)) {
6745
+ return void 0;
6746
+ }
6747
+ const datasetFilter = Reflect.get(dataset, "_internal_btql");
6748
+ return isObject(datasetFilter) ? datasetFilter : void 0;
6749
+ }
6750
+ function getInternalBtqlLimit(internalBtql) {
6751
+ const limit = internalBtql?.["limit"];
6752
+ return typeof limit === "number" ? limit : void 0;
6753
+ }
6717
6754
  function init(projectOrOptions, optionalOptions) {
6718
6755
  const options = (() => {
6719
6756
  if (typeof projectOrOptions === "string") {
@@ -6732,6 +6769,7 @@ function init(projectOrOptions, optionalOptions) {
6732
6769
  experiment,
6733
6770
  description,
6734
6771
  dataset,
6772
+ _internal_btql,
6735
6773
  parameters,
6736
6774
  baseExperiment,
6737
6775
  isPublic,
@@ -6840,16 +6878,24 @@ function init(projectOrOptions, optionalOptions) {
6840
6878
  args["ancestor_commits"] = await isomorph_default.getPastNAncestors();
6841
6879
  }
6842
6880
  if (dataset !== void 0) {
6843
- if ("id" in dataset && typeof dataset.id === "string" && !("__braintrust_dataset_marker" in dataset)) {
6844
- args["dataset_id"] = dataset.id;
6845
- if ("version" in dataset && dataset.version !== void 0) {
6846
- args["dataset_version"] = dataset.version;
6847
- }
6848
- } else {
6849
- args["dataset_id"] = await dataset.id;
6850
- args["dataset_version"] = await dataset.version();
6881
+ const datasetSelection = await serializeDatasetForExperiment({
6882
+ dataset,
6883
+ state
6884
+ });
6885
+ args["dataset_id"] = datasetSelection.datasetId;
6886
+ if (datasetSelection.datasetVersion !== void 0) {
6887
+ args["dataset_version"] = datasetSelection.datasetVersion;
6851
6888
  }
6852
6889
  }
6890
+ const datasetFilter = getExperimentDatasetFilter({
6891
+ dataset,
6892
+ _internal_btql
6893
+ });
6894
+ if (datasetFilter !== void 0) {
6895
+ args["internal_metadata"] = {
6896
+ dataset_filter: datasetFilter
6897
+ };
6898
+ }
6853
6899
  if (parameters !== void 0) {
6854
6900
  if (RemoteEvalParameters.isParameters(parameters)) {
6855
6901
  args["parameters_id"] = parameters.id;
@@ -6903,7 +6949,7 @@ function init(projectOrOptions, optionalOptions) {
6903
6949
  const ret = new Experiment2(
6904
6950
  state,
6905
6951
  lazyMetadata,
6906
- dataset !== void 0 && "version" in dataset ? dataset : void 0
6952
+ dataset !== void 0 ? dataset : void 0
6907
6953
  );
6908
6954
  if (options.setCurrent ?? true) {
6909
6955
  state.currentExperiment = ret;
@@ -6939,6 +6985,153 @@ function withLogger(callback, options = {}) {
6939
6985
  const logger = initLogger(options);
6940
6986
  return callback(logger);
6941
6987
  }
6988
+ async function getDatasetSnapshots(params) {
6989
+ const { state, datasetId } = params;
6990
+ return DatasetSnapshot.array().parse(
6991
+ await state.appConn().post_json("api/dataset_snapshot/get", {
6992
+ dataset_id: datasetId,
6993
+ ..."snapshotName" in params ? { name: params.snapshotName } : {},
6994
+ ..."xactId" in params ? { xact_id: params.xactId } : {}
6995
+ })
6996
+ );
6997
+ }
6998
+ async function getDatasetSnapshot(params) {
6999
+ assertDatasetSnapshotLookup(params);
7000
+ const snapshots = await getDatasetSnapshots(params);
7001
+ if (snapshots.length > 1) {
7002
+ throw new Error(
7003
+ 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}`
7004
+ );
7005
+ }
7006
+ return snapshots[0];
7007
+ }
7008
+ function normalizeDatasetSelection({
7009
+ version,
7010
+ environment,
7011
+ snapshotName
7012
+ }) {
7013
+ if (version !== void 0) {
7014
+ return { version };
7015
+ }
7016
+ if (snapshotName !== void 0) {
7017
+ return { snapshotName };
7018
+ }
7019
+ if (environment !== void 0) {
7020
+ return { environment };
7021
+ }
7022
+ return {};
7023
+ }
7024
+ async function resolveDatasetSnapshotName({
7025
+ state,
7026
+ datasetId,
7027
+ snapshotName
7028
+ }) {
7029
+ const match = await getDatasetSnapshot({
7030
+ state,
7031
+ datasetId,
7032
+ snapshotName
7033
+ });
7034
+ if (match === void 0) {
7035
+ throw new Error(
7036
+ `Dataset snapshot "${snapshotName}" not found for ${datasetId}`
7037
+ );
7038
+ }
7039
+ return match.xact_id;
7040
+ }
7041
+ async function resolveDatasetSnapshotNameForMetadata({
7042
+ state,
7043
+ lazyMetadata,
7044
+ snapshotName
7045
+ }) {
7046
+ const metadata = await lazyMetadata.get();
7047
+ return await resolveDatasetSnapshotName({
7048
+ state,
7049
+ datasetId: metadata.dataset.id,
7050
+ snapshotName
7051
+ });
7052
+ }
7053
+ async function resolveDatasetEnvironment({
7054
+ state,
7055
+ datasetId,
7056
+ environment
7057
+ }) {
7058
+ const environmentObjectPath = `environment-object/dataset/${datasetId}/${encodeURIComponent(environment)}`;
7059
+ const response = state.orgName == null ? await state.apiConn().get_json(environmentObjectPath) : await state.apiConn().get_json(environmentObjectPath, {
7060
+ org_name: state.orgName
7061
+ });
7062
+ return import_v38.z.object({ object_version: import_v38.z.string() }).parse(response).object_version;
7063
+ }
7064
+ async function resolveDatasetEnvironmentForMetadata({
7065
+ state,
7066
+ lazyMetadata,
7067
+ environment
7068
+ }) {
7069
+ const metadata = await lazyMetadata.get();
7070
+ return await resolveDatasetEnvironment({
7071
+ state,
7072
+ datasetId: metadata.dataset.id,
7073
+ environment
7074
+ });
7075
+ }
7076
+ async function serializeDatasetForExperiment({
7077
+ dataset,
7078
+ state
7079
+ }) {
7080
+ if (!Dataset2.isDataset(dataset)) {
7081
+ const selection2 = normalizeDatasetSelection(dataset);
7082
+ if (selection2.version !== void 0) {
7083
+ return {
7084
+ datasetId: dataset.id,
7085
+ datasetVersion: selection2.version
7086
+ };
7087
+ }
7088
+ if (selection2.snapshotName !== void 0) {
7089
+ return {
7090
+ datasetId: dataset.id,
7091
+ datasetVersion: await resolveDatasetSnapshotName({
7092
+ state,
7093
+ datasetId: dataset.id,
7094
+ snapshotName: selection2.snapshotName
7095
+ })
7096
+ };
7097
+ }
7098
+ if (selection2.environment !== void 0) {
7099
+ return {
7100
+ datasetId: dataset.id,
7101
+ datasetVersion: await resolveDatasetEnvironment({
7102
+ state,
7103
+ datasetId: dataset.id,
7104
+ environment: selection2.environment
7105
+ })
7106
+ };
7107
+ }
7108
+ return {
7109
+ datasetId: dataset.id
7110
+ };
7111
+ }
7112
+ const evalData = await dataset.toEvalData();
7113
+ const selection = normalizeDatasetSelection({
7114
+ version: evalData.dataset_version,
7115
+ environment: evalData.dataset_environment,
7116
+ snapshotName: evalData.dataset_snapshot_name
7117
+ });
7118
+ if (selection.version !== void 0) {
7119
+ return {
7120
+ datasetId: evalData.dataset_id,
7121
+ datasetVersion: selection.version
7122
+ };
7123
+ }
7124
+ const datasetVersion = await dataset.version();
7125
+ if (datasetVersion !== void 0) {
7126
+ return {
7127
+ datasetId: evalData.dataset_id,
7128
+ datasetVersion
7129
+ };
7130
+ }
7131
+ return {
7132
+ datasetId: evalData.dataset_id
7133
+ };
7134
+ }
6942
7135
  function initDataset(projectOrOptions, optionalOptions) {
6943
7136
  const options = (() => {
6944
7137
  if (typeof projectOrOptions === "string") {
@@ -6957,6 +7150,8 @@ function initDataset(projectOrOptions, optionalOptions) {
6957
7150
  dataset,
6958
7151
  description,
6959
7152
  version,
7153
+ snapshotName,
7154
+ environment,
6960
7155
  appUrl,
6961
7156
  apiKey,
6962
7157
  orgName,
@@ -6968,6 +7163,14 @@ function initDataset(projectOrOptions, optionalOptions) {
6968
7163
  state: stateArg,
6969
7164
  _internal_btql
6970
7165
  } = options;
7166
+ const selection = normalizeDatasetSelection({
7167
+ version,
7168
+ environment,
7169
+ snapshotName
7170
+ });
7171
+ const normalizedVersion = selection.version;
7172
+ const normalizedEnvironment = selection.environment;
7173
+ const normalizedSnapshotName = selection.snapshotName;
6971
7174
  const state = stateArg ?? _globalState;
6972
7175
  const lazyMetadata = new LazyValue(
6973
7176
  async () => {
@@ -7001,13 +7204,38 @@ function initDataset(projectOrOptions, optionalOptions) {
7001
7204
  };
7002
7205
  }
7003
7206
  );
7004
- return new Dataset2(
7207
+ const resolvedVersion = normalizedVersion !== void 0 ? normalizedVersion : normalizedSnapshotName !== void 0 ? new LazyValue(async () => {
7208
+ return await resolveDatasetSnapshotNameForMetadata({
7209
+ state,
7210
+ lazyMetadata,
7211
+ snapshotName: normalizedSnapshotName
7212
+ });
7213
+ }) : normalizedEnvironment !== void 0 ? new LazyValue(async () => {
7214
+ return await resolveDatasetEnvironmentForMetadata({
7215
+ state,
7216
+ lazyMetadata,
7217
+ environment: normalizedEnvironment
7218
+ });
7219
+ }) : void 0;
7220
+ const datasetObject = new Dataset2(
7005
7221
  stateArg ?? _globalState,
7006
7222
  lazyMetadata,
7007
- version,
7223
+ typeof resolvedVersion === "string" ? resolvedVersion : void 0,
7008
7224
  legacy,
7009
- _internal_btql
7225
+ _internal_btql,
7226
+ resolvedVersion instanceof LazyValue || normalizedEnvironment !== void 0 || normalizedSnapshotName !== void 0 ? {
7227
+ ...resolvedVersion instanceof LazyValue ? {
7228
+ lazyPinnedVersion: resolvedVersion
7229
+ } : {},
7230
+ ...normalizedEnvironment !== void 0 ? {
7231
+ pinnedEnvironment: normalizedEnvironment
7232
+ } : {},
7233
+ ...normalizedSnapshotName !== void 0 ? {
7234
+ pinnedSnapshotName: normalizedSnapshotName
7235
+ } : {}
7236
+ } : void 0
7010
7237
  );
7238
+ return datasetObject;
7011
7239
  }
7012
7240
  function withDataset(project, callback, options = {}) {
7013
7241
  debugLogger.forState(options.state).warn(
@@ -8003,11 +8231,20 @@ var ObjectFetcher = class {
8003
8231
  async getState() {
8004
8232
  throw new Error("ObjectFetcher subclasses must have a 'getState' method");
8005
8233
  }
8234
+ getPinnedVersion() {
8235
+ return this.pinnedVersion;
8236
+ }
8237
+ setPinnedVersion(pinnedVersion) {
8238
+ this.pinnedVersion = pinnedVersion;
8239
+ }
8240
+ getInternalBtql() {
8241
+ return this._internal_btql;
8242
+ }
8006
8243
  async *fetchRecordsFromApi(batchSize) {
8007
8244
  const state = await this.getState();
8008
8245
  const objectId = await this.id;
8009
8246
  const batchLimit = batchSize ?? DEFAULT_FETCH_BATCH_SIZE;
8010
- const internalLimit = this._internal_btql?.limit;
8247
+ const internalLimit = getInternalBtqlLimit(this._internal_btql);
8011
8248
  const limit = batchSize !== void 0 ? batchSize : internalLimit ?? batchLimit;
8012
8249
  const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
8013
8250
  Object.entries(this._internal_btql ?? {}).filter(
@@ -8821,7 +9058,7 @@ function splitLoggingData({
8821
9058
  return [serializableInternalData, lazyInternalData];
8822
9059
  }
8823
9060
  var Dataset2 = class extends ObjectFetcher {
8824
- constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql) {
9061
+ constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql, pinState) {
8825
9062
  const isLegacyDataset = legacy ?? DEFAULT_IS_LEGACY_DATASET;
8826
9063
  if (isLegacyDataset) {
8827
9064
  debugLogger.forState(state).warn(
@@ -8842,10 +9079,16 @@ var Dataset2 = class extends ObjectFetcher {
8842
9079
  );
8843
9080
  this.state = state;
8844
9081
  this.lazyMetadata = lazyMetadata;
9082
+ this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
9083
+ this.pinnedEnvironment = pinState?.pinnedEnvironment;
9084
+ this.pinnedSnapshotName = pinState?.pinnedSnapshotName;
8845
9085
  }
8846
9086
  lazyMetadata;
8847
9087
  __braintrust_dataset_marker = true;
8848
9088
  newRecords = 0;
9089
+ lazyPinnedVersion;
9090
+ pinnedEnvironment;
9091
+ pinnedSnapshotName;
8849
9092
  get id() {
8850
9093
  return (async () => {
8851
9094
  return (await this.lazyMetadata.get()).dataset.id;
@@ -8864,10 +9107,40 @@ var Dataset2 = class extends ObjectFetcher {
8864
9107
  get loggingState() {
8865
9108
  return this.state;
8866
9109
  }
9110
+ async toEvalData() {
9111
+ await this.getState();
9112
+ const metadata = await this.lazyMetadata.get();
9113
+ const pinnedVersion = this.getPinnedVersion();
9114
+ const internalBtql = this.getInternalBtql();
9115
+ return {
9116
+ dataset_id: metadata.dataset.id,
9117
+ ...this.pinnedEnvironment !== void 0 ? {
9118
+ dataset_environment: this.pinnedEnvironment
9119
+ } : {},
9120
+ ...this.pinnedEnvironment === void 0 && this.pinnedSnapshotName !== void 0 ? {
9121
+ dataset_snapshot_name: this.pinnedSnapshotName
9122
+ } : {},
9123
+ ...this.pinnedEnvironment === void 0 && this.pinnedSnapshotName === void 0 && pinnedVersion !== void 0 ? {
9124
+ dataset_version: pinnedVersion
9125
+ } : {},
9126
+ ...internalBtql !== void 0 ? { _internal_btql: internalBtql } : {}
9127
+ };
9128
+ }
8867
9129
  async getState() {
8868
9130
  await this.lazyMetadata.get();
9131
+ if (this.lazyPinnedVersion !== void 0 && this.getPinnedVersion() === void 0) {
9132
+ this.setPinnedVersion(await this.lazyPinnedVersion.get());
9133
+ }
8869
9134
  return this.state;
8870
9135
  }
9136
+ async version(options) {
9137
+ const pinnedVersion = this.getPinnedVersion();
9138
+ if (pinnedVersion !== void 0) {
9139
+ return pinnedVersion;
9140
+ }
9141
+ await this.getState();
9142
+ return await super.version(options);
9143
+ }
8871
9144
  validateEvent({
8872
9145
  metadata,
8873
9146
  expected,
@@ -9003,6 +9276,88 @@ var Dataset2 = class extends ObjectFetcher {
9003
9276
  this.state.bgLogger().log([args]);
9004
9277
  return id;
9005
9278
  }
9279
+ async createSnapshot({
9280
+ name,
9281
+ description,
9282
+ update
9283
+ }) {
9284
+ await this.flush();
9285
+ const state = await this.getState();
9286
+ const datasetId = await this.id;
9287
+ const currentVersion = await this.version();
9288
+ if (currentVersion === void 0) {
9289
+ throw new Error("Cannot create snapshot: dataset has no version");
9290
+ }
9291
+ const response = await state.appConn().post_json("api/dataset_snapshot/register", {
9292
+ dataset_id: datasetId,
9293
+ dataset_snapshot_name: name,
9294
+ description,
9295
+ xact_id: currentVersion,
9296
+ update
9297
+ });
9298
+ return datasetSnapshotRegisterResponseSchema.parse(response).dataset_snapshot;
9299
+ }
9300
+ async listSnapshots() {
9301
+ const state = await this.getState();
9302
+ return await getDatasetSnapshots({
9303
+ state,
9304
+ datasetId: await this.id
9305
+ });
9306
+ }
9307
+ async getSnapshot(lookup) {
9308
+ const state = await this.getState();
9309
+ const datasetId = await this.id;
9310
+ return await getDatasetSnapshot({
9311
+ state,
9312
+ datasetId,
9313
+ ...lookup
9314
+ });
9315
+ }
9316
+ async updateSnapshot(snapshotId, {
9317
+ name,
9318
+ description
9319
+ }) {
9320
+ const state = await this.getState();
9321
+ return DatasetSnapshot.parse(
9322
+ await state.appConn().post_json("api/dataset_snapshot/patch_id", {
9323
+ id: snapshotId,
9324
+ name,
9325
+ description
9326
+ })
9327
+ );
9328
+ }
9329
+ async deleteSnapshot(snapshotId) {
9330
+ const state = await this.getState();
9331
+ return DatasetSnapshot.parse(
9332
+ await state.appConn().post_json("api/dataset_snapshot/delete_id", {
9333
+ id: snapshotId
9334
+ })
9335
+ );
9336
+ }
9337
+ async restorePreview({
9338
+ version
9339
+ }) {
9340
+ await this.flush();
9341
+ const state = await this.getState();
9342
+ const datasetId = await this.id;
9343
+ return datasetRestorePreviewResultSchema.parse(
9344
+ await state.apiConn().post_json(`v1/dataset/${datasetId}/restore/preview`, {
9345
+ version
9346
+ })
9347
+ );
9348
+ }
9349
+ async restore({
9350
+ version
9351
+ }) {
9352
+ await this.flush();
9353
+ const state = await this.getState();
9354
+ const datasetId = await this.id;
9355
+ return datasetRestoreResultSchema.parse(
9356
+ await state.apiConn().post_json(`v1/dataset/${datasetId}/restore`, {
9357
+ version
9358
+ })
9359
+ );
9360
+ }
9006
9361
  /**
9007
9362
  * Summarize the dataset, including high level metrics about its size and other metadata.
9008
9363
  * @param summarizeData Whether to summarize the data. If false, only the metadata will be returned.
@@ -14379,6 +14734,9 @@ function llmParentKey(parentToolUseId) {
14379
14734
  function isSubAgentDelegationToolName(toolName) {
14380
14735
  return toolName === "Agent" || toolName === "Task";
14381
14736
  }
14737
+ function shouldParentToolAsTaskSibling(toolName) {
14738
+ return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
14739
+ }
14382
14740
  function filterSerializableOptions(options) {
14383
14741
  const allowedKeys = [
14384
14742
  "model",
@@ -14478,6 +14836,11 @@ function resolveTaskToolUseId(taskIdToToolUseId, message) {
14478
14836
  }
14479
14837
  return void 0;
14480
14838
  }
14839
+ function seedTaskToolUseIdMapping(taskIdToToolUseId, message) {
14840
+ if (typeof message.task_id === "string" && typeof message.tool_use_id === "string") {
14841
+ taskIdToToolUseId.set(message.task_id, message.tool_use_id);
14842
+ }
14843
+ }
14481
14844
  function extractUsageFromMessage(message) {
14482
14845
  const metrics = {};
14483
14846
  let usage;
@@ -14673,7 +15036,10 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
14673
15036
  }
14674
15037
  },
14675
15038
  name: parsed.displayName,
14676
- parent: await resolveParentSpan(toolUseID),
15039
+ parent: await resolveParentSpan(toolUseID, {
15040
+ agentId: input.agent_id,
15041
+ preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
15042
+ }),
14677
15043
  spanAttributes: { type: "tool" /* TOOL */ }
14678
15044
  });
14679
15045
  activeToolSpans.set(toolUseID, toolSpan);
@@ -14963,6 +15329,7 @@ async function finalizeCurrentMessageGroup(state) {
14963
15329
  state.currentMessages.length = 0;
14964
15330
  }
14965
15331
  function maybeTrackToolUseContext(state, message) {
15332
+ seedTaskToolUseIdMapping(state.taskIdToToolUseId, message);
14966
15333
  if (message.type !== "assistant" || !Array.isArray(message.message?.content)) {
14967
15334
  return;
14968
15335
  }
@@ -15017,6 +15384,34 @@ async function ensureSubAgentSpan(subAgentDetailsByToolUseId, rootSpan, activeTo
15017
15384
  subAgentSpans.set(parentToolUseId, subAgentSpan);
15018
15385
  return subAgentSpan;
15019
15386
  }
15387
+ async function ensureActiveLlmSpanForParentToolUse(rootSpan, activeLlmSpansByParentToolUse, subAgentDetailsByToolUseId, activeToolSpans, subAgentSpans, parentToolUseId, startTime) {
15388
+ const parentKey = llmParentKey(parentToolUseId);
15389
+ const existingLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
15390
+ if (existingLlmSpan) {
15391
+ return existingLlmSpan;
15392
+ }
15393
+ let llmParentSpan = await rootSpan.export();
15394
+ if (parentToolUseId) {
15395
+ const subAgentSpan = await ensureSubAgentSpan(
15396
+ subAgentDetailsByToolUseId,
15397
+ rootSpan,
15398
+ activeToolSpans,
15399
+ subAgentSpans,
15400
+ parentToolUseId
15401
+ );
15402
+ llmParentSpan = await subAgentSpan.export();
15403
+ }
15404
+ const llmSpan = startSpan({
15405
+ name: "anthropic.messages.create",
15406
+ parent: llmParentSpan,
15407
+ spanAttributes: {
15408
+ type: "llm" /* LLM */
15409
+ },
15410
+ startTime
15411
+ });
15412
+ activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
15413
+ return llmSpan;
15414
+ }
15020
15415
  async function maybeHandleTaskLifecycleMessage(state, message) {
15021
15416
  if (message.type !== "system") {
15022
15417
  return false;
@@ -15126,29 +15521,15 @@ async function handleStreamMessage(state, message) {
15126
15521
  }
15127
15522
  if (message.type === "assistant" && message.message?.usage) {
15128
15523
  const parentToolUseId = message.parent_tool_use_id ?? null;
15129
- const parentKey = llmParentKey(parentToolUseId);
15130
- if (!state.activeLlmSpansByParentToolUse.has(parentKey)) {
15131
- let llmParentSpan = await state.span.export();
15132
- if (parentToolUseId) {
15133
- const subAgentSpan = await ensureSubAgentSpan(
15134
- state.subAgentDetailsByToolUseId,
15135
- state.span,
15136
- state.activeToolSpans,
15137
- state.subAgentSpans,
15138
- parentToolUseId
15139
- );
15140
- llmParentSpan = await subAgentSpan.export();
15141
- }
15142
- const llmSpan = startSpan({
15143
- name: "anthropic.messages.create",
15144
- parent: llmParentSpan,
15145
- spanAttributes: {
15146
- type: "llm" /* LLM */
15147
- },
15148
- startTime: state.currentMessageStartTime
15149
- });
15150
- state.activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
15151
- }
15524
+ await ensureActiveLlmSpanForParentToolUse(
15525
+ state.span,
15526
+ state.activeLlmSpansByParentToolUse,
15527
+ state.subAgentDetailsByToolUseId,
15528
+ state.activeToolSpans,
15529
+ state.subAgentSpans,
15530
+ parentToolUseId,
15531
+ state.currentMessageStartTime
15532
+ );
15152
15533
  state.currentMessages.push(message);
15153
15534
  }
15154
15535
  if (message.type !== "result" || !message.usage) {
@@ -15295,10 +15676,35 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
15295
15676
  const localToolContext = createClaudeLocalToolContext();
15296
15677
  const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
15297
15678
  const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
15298
- const resolveToolUseParentSpan = async (toolUseID) => {
15299
- const parentToolUseId = toolUseToParent.get(toolUseID) ?? null;
15679
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
15680
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
15681
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
15300
15682
  const parentKey = llmParentKey(parentToolUseId);
15301
15683
  const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
15684
+ if (context?.preferTaskSiblingParent) {
15685
+ if (!activeLlmSpan) {
15686
+ await ensureActiveLlmSpanForParentToolUse(
15687
+ span,
15688
+ activeLlmSpansByParentToolUse,
15689
+ subAgentDetailsByToolUseId,
15690
+ activeToolSpans,
15691
+ subAgentSpans,
15692
+ parentToolUseId,
15693
+ getCurrentUnixTimestamp()
15694
+ );
15695
+ }
15696
+ if (parentToolUseId) {
15697
+ const subAgentSpan = await ensureSubAgentSpan(
15698
+ subAgentDetailsByToolUseId,
15699
+ span,
15700
+ activeToolSpans,
15701
+ subAgentSpans,
15702
+ parentToolUseId
15703
+ );
15704
+ return subAgentSpan.export();
15705
+ }
15706
+ return span.export();
15707
+ }
15302
15708
  if (activeLlmSpan) {
15303
15709
  return activeLlmSpan.export();
15304
15710
  }
@@ -15426,62 +15832,940 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
15426
15832
  }
15427
15833
  };
15428
15834
 
15429
- // src/instrumentation/plugins/google-genai-channels.ts
15430
- var googleGenAIChannels = defineChannels("@google/genai", {
15431
- generateContent: channel({
15432
- channelName: "models.generateContent",
15835
+ // src/instrumentation/plugins/cursor-sdk-channels.ts
15836
+ var cursorSDKChannels = defineChannels("@cursor/sdk", {
15837
+ create: channel({
15838
+ channelName: "Agent.create",
15433
15839
  kind: "async"
15434
15840
  }),
15435
- generateContentStream: channel({
15436
- channelName: "models.generateContentStream",
15841
+ resume: channel({
15842
+ channelName: "Agent.resume",
15437
15843
  kind: "async"
15438
15844
  }),
15439
- embedContent: channel({
15440
- channelName: "models.embedContent",
15845
+ prompt: channel({
15846
+ channelName: "Agent.prompt",
15847
+ kind: "async"
15848
+ }),
15849
+ send: channel({
15850
+ channelName: "agent.send",
15441
15851
  kind: "async"
15442
15852
  })
15443
15853
  });
15444
15854
 
15445
- // src/instrumentation/plugins/google-genai-plugin.ts
15446
- var GOOGLE_GENAI_INTERNAL_CONTEXT = {
15447
- caller_filename: "<node-internal>",
15448
- caller_functionname: "<node-internal>",
15449
- caller_lineno: 0
15450
- };
15451
- function createWrapperParityEvent(args) {
15452
- return {
15453
- context: GOOGLE_GENAI_INTERNAL_CONTEXT,
15454
- input: args.input,
15455
- metadata: args.metadata
15456
- };
15457
- }
15458
- var GoogleGenAIPlugin = class extends BasePlugin {
15855
+ // src/instrumentation/plugins/cursor-sdk-plugin.ts
15856
+ var PATCHED_AGENT = Symbol.for("braintrust.cursor-sdk.auto-patched-agent");
15857
+ var PATCHED_RUN = Symbol.for("braintrust.cursor-sdk.patched-run");
15858
+ var WRAPPED_AGENT = Symbol.for("braintrust.cursor-sdk.wrapped-agent");
15859
+ var CursorSDKPlugin = class extends BasePlugin {
15860
+ promptDepth = 0;
15459
15861
  onEnable() {
15460
- this.subscribeToGoogleGenAIChannels();
15862
+ this.subscribeToAgentFactories();
15863
+ this.subscribeToPrompt();
15864
+ this.subscribeToSend();
15461
15865
  }
15462
15866
  onDisable() {
15463
- this.unsubscribers = unsubscribeAll(this.unsubscribers);
15867
+ for (const unsubscribe of this.unsubscribers) {
15868
+ unsubscribe();
15869
+ }
15870
+ this.unsubscribers = [];
15871
+ this.promptDepth = 0;
15464
15872
  }
15465
- subscribeToGoogleGenAIChannels() {
15466
- this.subscribeToGenerateContentChannel();
15467
- this.subscribeToGenerateContentStreamChannel();
15468
- this.subscribeToEmbedContentChannel();
15873
+ subscribeToAgentFactories() {
15874
+ this.subscribeToAgentFactory(cursorSDKChannels.create);
15875
+ this.subscribeToAgentFactory(cursorSDKChannels.resume);
15469
15876
  }
15470
- subscribeToGenerateContentChannel() {
15471
- const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
15877
+ subscribeToAgentFactory(channel2) {
15878
+ const tracingChannel2 = channel2.tracingChannel();
15879
+ const handlers = {
15880
+ asyncEnd: (event) => {
15881
+ patchCursorAgentInPlace(event.result);
15882
+ },
15883
+ error: () => {
15884
+ }
15885
+ };
15886
+ tracingChannel2.subscribe(handlers);
15887
+ this.unsubscribers.push(() => {
15888
+ tracingChannel2.unsubscribe(handlers);
15889
+ });
15890
+ }
15891
+ subscribeToPrompt() {
15892
+ const channel2 = cursorSDKChannels.prompt.tracingChannel();
15472
15893
  const states = /* @__PURE__ */ new WeakMap();
15473
- const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
15474
- tracingChannel2,
15475
- states,
15476
- (event) => {
15477
- const params = event.arguments[0];
15478
- const input = serializeGenerateContentInput(params);
15479
- const metadata = extractGenerateContentMetadata(params);
15894
+ const handlers = {
15895
+ start: (event) => {
15896
+ this.promptDepth += 1;
15897
+ const message = event.arguments[0];
15898
+ const options = event.arguments[1];
15899
+ const metadata = {
15900
+ ...extractAgentOptionsMetadata(options),
15901
+ "cursor_sdk.operation": "Agent.prompt",
15902
+ provider: "cursor",
15903
+ ...event.moduleVersion ? { "cursor_sdk.version": event.moduleVersion } : {}
15904
+ };
15480
15905
  const span = startSpan({
15481
- name: "generate_content",
15482
- spanAttributes: {
15483
- type: "llm" /* LLM */
15484
- },
15906
+ name: "Cursor Agent",
15907
+ spanAttributes: { type: "task" /* TASK */ }
15908
+ });
15909
+ const startTime = getCurrentUnixTimestamp();
15910
+ safeLog(span, {
15911
+ input: sanitizeUserMessage(message),
15912
+ metadata
15913
+ });
15914
+ states.set(event, { metadata, span, startTime });
15915
+ },
15916
+ asyncEnd: (event) => {
15917
+ this.promptDepth = Math.max(0, this.promptDepth - 1);
15918
+ const state = states.get(event);
15919
+ if (!state) {
15920
+ return;
15921
+ }
15922
+ try {
15923
+ safeLog(state.span, {
15924
+ metadata: {
15925
+ ...state.metadata,
15926
+ ...extractRunResultMetadata(event.result)
15927
+ },
15928
+ metrics: buildDurationMetrics(state.startTime),
15929
+ output: event.result?.result ?? event.result
15930
+ });
15931
+ } finally {
15932
+ state.span.end();
15933
+ states.delete(event);
15934
+ }
15935
+ },
15936
+ error: (event) => {
15937
+ this.promptDepth = Math.max(0, this.promptDepth - 1);
15938
+ const state = states.get(event);
15939
+ if (!state || !event.error) {
15940
+ return;
15941
+ }
15942
+ safeLog(state.span, { error: event.error.message });
15943
+ state.span.end();
15944
+ states.delete(event);
15945
+ }
15946
+ };
15947
+ channel2.subscribe(handlers);
15948
+ this.unsubscribers.push(() => {
15949
+ channel2.unsubscribe(handlers);
15950
+ });
15951
+ }
15952
+ subscribeToSend() {
15953
+ const channel2 = cursorSDKChannels.send.tracingChannel();
15954
+ const states = /* @__PURE__ */ new WeakMap();
15955
+ const handlers = {
15956
+ start: (event) => {
15957
+ if (this.promptDepth > 0) {
15958
+ return;
15959
+ }
15960
+ const message = event.arguments[0];
15961
+ const sendOptions = event.arguments[1];
15962
+ const agent = event.agent;
15963
+ const metadata = {
15964
+ ...extractSendMetadata(sendOptions),
15965
+ ...agent ? extractAgentMetadata(agent) : {},
15966
+ "cursor_sdk.operation": "agent.send",
15967
+ provider: "cursor",
15968
+ ...event.moduleVersion ? { "cursor_sdk.version": event.moduleVersion } : {}
15969
+ };
15970
+ const span = startSpan({
15971
+ name: "Cursor Agent",
15972
+ spanAttributes: { type: "task" /* TASK */ }
15973
+ });
15974
+ const startTime = getCurrentUnixTimestamp();
15975
+ safeLog(span, {
15976
+ input: sanitizeUserMessage(message),
15977
+ metadata
15978
+ });
15979
+ const state = {
15980
+ activeToolSpans: /* @__PURE__ */ new Map(),
15981
+ agent,
15982
+ conversationText: [],
15983
+ deltaText: [],
15984
+ finalized: false,
15985
+ input: message,
15986
+ metadata,
15987
+ metrics: {},
15988
+ span,
15989
+ startTime,
15990
+ streamMessages: [],
15991
+ streamText: [],
15992
+ stepText: [],
15993
+ taskText: []
15994
+ };
15995
+ if (hasCursorCallbacks(sendOptions)) {
15996
+ event.arguments[1] = wrapSendOptionsCallbacks(sendOptions, state);
15997
+ }
15998
+ states.set(event, state);
15999
+ },
16000
+ asyncEnd: (event) => {
16001
+ const state = states.get(event);
16002
+ if (!state) {
16003
+ return;
16004
+ }
16005
+ if (!event.result) {
16006
+ return;
16007
+ }
16008
+ state.run = event.result;
16009
+ state.metadata = {
16010
+ ...state.metadata,
16011
+ ...extractRunMetadata(event.result)
16012
+ };
16013
+ patchCursorRun(event.result, state);
16014
+ },
16015
+ error: (event) => {
16016
+ const state = states.get(event);
16017
+ if (!state || !event.error) {
16018
+ return;
16019
+ }
16020
+ safeLog(state.span, { error: event.error.message });
16021
+ endOpenToolSpans(state, event.error.message);
16022
+ state.span.end();
16023
+ state.finalized = true;
16024
+ states.delete(event);
16025
+ }
16026
+ };
16027
+ channel2.subscribe(handlers);
16028
+ this.unsubscribers.push(() => {
16029
+ channel2.unsubscribe(handlers);
16030
+ });
16031
+ }
16032
+ };
16033
+ function patchCursorAgentInPlace(agent) {
16034
+ if (!agent || typeof agent !== "object") {
16035
+ return;
16036
+ }
16037
+ const agentRecord = agent;
16038
+ if (agentRecord[PATCHED_AGENT] || agentRecord[WRAPPED_AGENT] || typeof agentRecord.send !== "function") {
16039
+ return;
16040
+ }
16041
+ const originalSend = agentRecord.send.bind(agentRecord);
16042
+ try {
16043
+ Object.defineProperty(agentRecord, PATCHED_AGENT, {
16044
+ configurable: false,
16045
+ enumerable: false,
16046
+ value: true
16047
+ });
16048
+ Object.defineProperty(agentRecord, "send", {
16049
+ configurable: true,
16050
+ value(message, options) {
16051
+ const args = [message, options];
16052
+ return cursorSDKChannels.send.tracePromise(
16053
+ () => originalSend(...args),
16054
+ {
16055
+ agent: agentRecord,
16056
+ arguments: args,
16057
+ operation: "send"
16058
+ }
16059
+ );
16060
+ },
16061
+ writable: true
16062
+ });
16063
+ } catch {
16064
+ }
16065
+ }
16066
+ function wrapSendOptionsCallbacks(options, state) {
16067
+ const originalOnDelta = options.onDelta;
16068
+ const originalOnStep = options.onStep;
16069
+ return {
16070
+ ...options,
16071
+ async onDelta(args) {
16072
+ try {
16073
+ await handleInteractionUpdate(state, args.update);
16074
+ } catch (error) {
16075
+ logInstrumentationError("Cursor SDK onDelta", error);
16076
+ }
16077
+ if (originalOnDelta) {
16078
+ return originalOnDelta(args);
16079
+ }
16080
+ },
16081
+ async onStep(args) {
16082
+ try {
16083
+ handleStepUpdate(state, args.step);
16084
+ } catch (error) {
16085
+ logInstrumentationError("Cursor SDK onStep", error);
16086
+ }
16087
+ if (originalOnStep) {
16088
+ return originalOnStep(args);
16089
+ }
16090
+ }
16091
+ };
16092
+ }
16093
+ function hasCursorCallbacks(options) {
16094
+ return !!options && (typeof options.onDelta === "function" || typeof options.onStep === "function");
16095
+ }
16096
+ function patchCursorRun(run, state) {
16097
+ if (!run || typeof run !== "object") {
16098
+ return;
16099
+ }
16100
+ const runRecord = run;
16101
+ if (runRecord[PATCHED_RUN]) {
16102
+ return;
16103
+ }
16104
+ try {
16105
+ Object.defineProperty(runRecord, PATCHED_RUN, {
16106
+ configurable: false,
16107
+ enumerable: false,
16108
+ value: true
16109
+ });
16110
+ if (typeof runRecord.stream === "function") {
16111
+ const originalStream = runRecord.stream.bind(runRecord);
16112
+ Object.defineProperty(runRecord, "stream", {
16113
+ configurable: true,
16114
+ value() {
16115
+ const stream = originalStream();
16116
+ return patchCursorStream(stream, state);
16117
+ },
16118
+ writable: true
16119
+ });
16120
+ }
16121
+ if (typeof runRecord.wait === "function") {
16122
+ const originalWait = runRecord.wait.bind(runRecord);
16123
+ Object.defineProperty(runRecord, "wait", {
16124
+ configurable: true,
16125
+ async value() {
16126
+ try {
16127
+ const result = await originalWait();
16128
+ state.lastResult = result;
16129
+ await finalizeCursorRun(state, { result });
16130
+ return result;
16131
+ } catch (error) {
16132
+ await finalizeCursorRun(state, { error });
16133
+ throw error;
16134
+ }
16135
+ },
16136
+ writable: true
16137
+ });
16138
+ }
16139
+ if (typeof runRecord.conversation === "function") {
16140
+ const originalConversation = runRecord.conversation.bind(runRecord);
16141
+ Object.defineProperty(runRecord, "conversation", {
16142
+ configurable: true,
16143
+ async value() {
16144
+ try {
16145
+ const conversation = await originalConversation();
16146
+ await handleConversation(state, conversation);
16147
+ await finalizeCursorRun(state);
16148
+ return conversation;
16149
+ } catch (error) {
16150
+ await finalizeCursorRun(state, { error });
16151
+ throw error;
16152
+ }
16153
+ },
16154
+ writable: true
16155
+ });
16156
+ }
16157
+ } catch {
16158
+ void finalizeCursorRun(state, { output: run });
16159
+ }
16160
+ }
16161
+ async function* patchCursorStream(stream, state) {
16162
+ try {
16163
+ for await (const message of stream) {
16164
+ try {
16165
+ await handleStreamMessage2(state, message);
16166
+ } catch (error) {
16167
+ logInstrumentationError("Cursor SDK stream", error);
16168
+ }
16169
+ yield message;
16170
+ }
16171
+ await finalizeCursorRun(state);
16172
+ } catch (error) {
16173
+ await finalizeCursorRun(state, { error });
16174
+ throw error;
16175
+ }
16176
+ }
16177
+ async function handleInteractionUpdate(state, update) {
16178
+ switch (update.type) {
16179
+ case "text-delta":
16180
+ if (typeof update.text === "string") {
16181
+ state.deltaText.push(update.text);
16182
+ }
16183
+ return;
16184
+ case "token-delta":
16185
+ if (typeof update.tokens === "number") {
16186
+ state.metrics["cursor_sdk.delta_tokens"] = (state.metrics["cursor_sdk.delta_tokens"] ?? 0) + update.tokens;
16187
+ }
16188
+ return;
16189
+ case "tool-call-started":
16190
+ case "partial-tool-call":
16191
+ case "tool-call-completed":
16192
+ await handleToolUpdate(
16193
+ state,
16194
+ update
16195
+ );
16196
+ return;
16197
+ case "turn-ended":
16198
+ addUsageMetrics(
16199
+ state.metrics,
16200
+ update.usage
16201
+ );
16202
+ return;
16203
+ case "summary":
16204
+ if (typeof update.summary === "string") {
16205
+ state.taskText.push(update.summary);
16206
+ }
16207
+ return;
16208
+ case "step-completed":
16209
+ if (typeof update.stepDurationMs === "number") {
16210
+ state.metrics["cursor_sdk.step_duration_ms"] = (state.metrics["cursor_sdk.step_duration_ms"] ?? 0) + update.stepDurationMs;
16211
+ }
16212
+ state.metrics["cursor_sdk.steps"] = (state.metrics["cursor_sdk.steps"] ?? 0) + 1;
16213
+ return;
16214
+ default:
16215
+ return;
16216
+ }
16217
+ }
16218
+ async function handleToolUpdate(state, update) {
16219
+ const callId = update.callId;
16220
+ if (!callId) {
16221
+ return;
16222
+ }
16223
+ const toolCall = update.toolCall;
16224
+ const name = extractToolName(toolCall);
16225
+ const args = extractToolArgs(toolCall);
16226
+ const result = extractToolResult(toolCall);
16227
+ if (update.type === "tool-call-started" || update.type === "partial-tool-call") {
16228
+ if (!state.activeToolSpans.has(callId)) {
16229
+ state.activeToolSpans.set(
16230
+ callId,
16231
+ await startToolSpan(state, {
16232
+ args,
16233
+ callId,
16234
+ name,
16235
+ status: "running",
16236
+ toolCall
16237
+ })
16238
+ );
16239
+ }
16240
+ return;
16241
+ }
16242
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
16243
+ args,
16244
+ callId,
16245
+ name,
16246
+ status: "completed",
16247
+ toolCall
16248
+ });
16249
+ finishToolSpan(toolState, {
16250
+ error: toolCall?.status === "error" ? stringifyUnknown(result) : void 0,
16251
+ metadata: {
16252
+ "cursor_sdk.tool.status": toolCall?.status ?? "completed"
16253
+ },
16254
+ output: result
16255
+ });
16256
+ state.activeToolSpans.delete(callId);
16257
+ }
16258
+ async function handleStreamMessage2(state, message) {
16259
+ state.streamMessages.push(message);
16260
+ if (message.type === "system") {
16261
+ const systemMessage = message;
16262
+ state.metadata = {
16263
+ ...state.metadata,
16264
+ ...extractModelMetadata(systemMessage.model),
16265
+ ...systemMessage.agent_id ? { "cursor_sdk.agent_id": systemMessage.agent_id } : {},
16266
+ ...systemMessage.run_id ? { "cursor_sdk.run_id": systemMessage.run_id } : {},
16267
+ ...systemMessage.tools ? { "cursor_sdk.tools": systemMessage.tools } : {}
16268
+ };
16269
+ return;
16270
+ }
16271
+ if (message.type === "assistant") {
16272
+ const assistantMessage = message;
16273
+ for (const block of assistantMessage.message?.content ?? []) {
16274
+ if (block?.type === "text" && typeof block.text === "string") {
16275
+ state.streamText.push(block.text);
16276
+ } else if (block?.type === "tool_use" && block.id) {
16277
+ state.activeToolSpans.set(
16278
+ block.id,
16279
+ await startToolSpan(state, {
16280
+ args: block.input,
16281
+ callId: block.id,
16282
+ name: block.name,
16283
+ status: "running"
16284
+ })
16285
+ );
16286
+ }
16287
+ }
16288
+ return;
16289
+ }
16290
+ if (message.type === "tool_call") {
16291
+ await handleToolMessage(
16292
+ state,
16293
+ message
16294
+ );
16295
+ return;
16296
+ }
16297
+ if (message.type === "task" && typeof message.text === "string") {
16298
+ state.taskText.push(message.text);
16299
+ return;
16300
+ }
16301
+ if (message.type === "status" && message.status) {
16302
+ state.metadata["cursor_sdk.status"] = message.status;
16303
+ }
16304
+ }
16305
+ async function handleToolMessage(state, message) {
16306
+ const callId = message.call_id;
16307
+ if (!callId) {
16308
+ return;
16309
+ }
16310
+ if (message.status === "running") {
16311
+ if (!state.activeToolSpans.has(callId)) {
16312
+ state.activeToolSpans.set(
16313
+ callId,
16314
+ await startToolSpan(state, {
16315
+ args: message.args,
16316
+ callId,
16317
+ name: message.name,
16318
+ status: message.status,
16319
+ truncated: message.truncated
16320
+ })
16321
+ );
16322
+ }
16323
+ return;
16324
+ }
16325
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
16326
+ args: message.args,
16327
+ callId,
16328
+ name: message.name,
16329
+ status: message.status,
16330
+ truncated: message.truncated
16331
+ });
16332
+ finishToolSpan(toolState, {
16333
+ error: message.status === "error" ? stringifyUnknown(message.result) : void 0,
16334
+ metadata: {
16335
+ "cursor_sdk.tool.status": message.status
16336
+ },
16337
+ output: message.result
16338
+ });
16339
+ state.activeToolSpans.delete(callId);
16340
+ }
16341
+ async function handleConversation(state, turns) {
16342
+ state.conversationOutput = turns;
16343
+ for (const turn of turns) {
16344
+ if (turn.type === "agentConversationTurn") {
16345
+ for (const step of turn.turn?.steps ?? []) {
16346
+ await handleConversationStep(state, step);
16347
+ }
16348
+ } else if (turn.type === "shellConversationTurn") {
16349
+ const command = turn.turn?.shellCommand?.command;
16350
+ if (command) {
16351
+ const callId = `shell:${state.activeToolSpans.size}:${command}`;
16352
+ const toolState = await startToolSpan(state, {
16353
+ args: turn.turn?.shellCommand,
16354
+ callId,
16355
+ name: "shell",
16356
+ status: "completed"
16357
+ });
16358
+ finishToolSpan(toolState, {
16359
+ metadata: { "cursor_sdk.tool.status": "completed" },
16360
+ output: turn.turn?.shellOutput
16361
+ });
16362
+ }
16363
+ }
16364
+ }
16365
+ }
16366
+ async function handleConversationStep(state, step) {
16367
+ if (step.type === "assistantMessage" && typeof step.message?.text === "string") {
16368
+ state.conversationText.push(step.message.text);
16369
+ return;
16370
+ }
16371
+ if (step.type !== "toolCall") {
16372
+ return;
16373
+ }
16374
+ const toolCall = step.message;
16375
+ const callId = typeof toolCall?.callId === "string" ? toolCall.callId : `conversation-tool:${state.activeToolSpans.size}`;
16376
+ const toolState = await startToolSpan(state, {
16377
+ args: extractToolArgs(toolCall),
16378
+ callId,
16379
+ name: extractToolName(toolCall),
16380
+ status: toolCall?.status,
16381
+ toolCall
16382
+ });
16383
+ finishToolSpan(toolState, {
16384
+ error: toolCall?.status === "error" ? stringifyUnknown(toolCall.result) : void 0,
16385
+ metadata: {
16386
+ "cursor_sdk.tool.status": toolCall?.status ?? "completed"
16387
+ },
16388
+ output: extractToolResult(toolCall)
16389
+ });
16390
+ }
16391
+ function handleStepUpdate(state, step) {
16392
+ state.metrics["cursor_sdk.steps"] = (state.metrics["cursor_sdk.steps"] ?? 0) + 1;
16393
+ if (step.type) {
16394
+ const stepTypes = state.metadata["cursor_sdk.step_types"];
16395
+ if (Array.isArray(stepTypes)) {
16396
+ if (!stepTypes.includes(step.type)) {
16397
+ stepTypes.push(step.type);
16398
+ }
16399
+ } else {
16400
+ state.metadata["cursor_sdk.step_types"] = [step.type];
16401
+ }
16402
+ }
16403
+ if (step.type === "assistantMessage" && typeof step.message?.text === "string") {
16404
+ state.stepText.push(step.message.text);
16405
+ }
16406
+ }
16407
+ async function startToolSpan(state, args) {
16408
+ const name = args.name || "unknown";
16409
+ const metadata = {
16410
+ "cursor_sdk.tool.status": args.status,
16411
+ "gen_ai.tool.call.id": args.callId,
16412
+ "gen_ai.tool.name": name
16413
+ };
16414
+ if (args.truncated?.args !== void 0) {
16415
+ metadata["cursor_sdk.tool.args_truncated"] = args.truncated.args;
16416
+ }
16417
+ if (args.truncated?.result !== void 0) {
16418
+ metadata["cursor_sdk.tool.result_truncated"] = args.truncated.result;
16419
+ }
16420
+ const span = startSpan({
16421
+ event: {
16422
+ input: args.args,
16423
+ metadata
16424
+ },
16425
+ name: `tool: ${name}`,
16426
+ parent: await state.span.export(),
16427
+ spanAttributes: { type: "tool" /* TOOL */ }
16428
+ });
16429
+ let subAgentSpan;
16430
+ if (isSubAgentToolName(name)) {
16431
+ subAgentSpan = startSpan({
16432
+ event: {
16433
+ input: args.args,
16434
+ metadata: {
16435
+ "cursor_sdk.subagent.tool_call_id": args.callId,
16436
+ "gen_ai.tool.name": name
16437
+ }
16438
+ },
16439
+ name: formatSubAgentSpanName2(args.toolCall, args.args),
16440
+ parent: await span.export(),
16441
+ spanAttributes: { type: "task" /* TASK */ }
16442
+ });
16443
+ }
16444
+ return { span, subAgentSpan };
16445
+ }
16446
+ function finishToolSpan(toolState, result) {
16447
+ try {
16448
+ if (result.error) {
16449
+ safeLog(toolState.span, {
16450
+ error: result.error,
16451
+ metadata: result.metadata,
16452
+ output: result.output
16453
+ });
16454
+ if (toolState.subAgentSpan) {
16455
+ safeLog(toolState.subAgentSpan, {
16456
+ error: result.error,
16457
+ metadata: result.metadata,
16458
+ output: result.output
16459
+ });
16460
+ }
16461
+ } else {
16462
+ safeLog(toolState.span, {
16463
+ metadata: result.metadata,
16464
+ output: result.output
16465
+ });
16466
+ if (toolState.subAgentSpan) {
16467
+ safeLog(toolState.subAgentSpan, {
16468
+ metadata: result.metadata,
16469
+ output: result.output
16470
+ });
16471
+ }
16472
+ }
16473
+ } finally {
16474
+ toolState.subAgentSpan?.end();
16475
+ toolState.span.end();
16476
+ }
16477
+ }
16478
+ async function finalizeCursorRun(state, params = {}) {
16479
+ if (state.finalized) {
16480
+ return;
16481
+ }
16482
+ state.finalized = true;
16483
+ const error = params.error;
16484
+ const result = params.result ?? state.lastResult;
16485
+ 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);
16486
+ try {
16487
+ const metadata = {
16488
+ ...state.metadata,
16489
+ ...state.run ? extractRunMetadata(state.run) : {},
16490
+ ...result ? extractRunResultMetadata(result) : {}
16491
+ };
16492
+ if (error) {
16493
+ safeLog(state.span, {
16494
+ error: error instanceof Error ? error.message : String(error),
16495
+ metadata,
16496
+ metrics: {
16497
+ ...cleanMetrics(state.metrics),
16498
+ ...buildDurationMetrics(state.startTime)
16499
+ },
16500
+ output
16501
+ });
16502
+ } else {
16503
+ safeLog(state.span, {
16504
+ metadata,
16505
+ metrics: {
16506
+ ...cleanMetrics(state.metrics),
16507
+ ...buildDurationMetrics(state.startTime)
16508
+ },
16509
+ output
16510
+ });
16511
+ }
16512
+ } finally {
16513
+ endOpenToolSpans(state);
16514
+ state.span.end();
16515
+ }
16516
+ }
16517
+ function endOpenToolSpans(state, error) {
16518
+ for (const [, toolState] of state.activeToolSpans) {
16519
+ finishToolSpan(toolState, { error });
16520
+ }
16521
+ state.activeToolSpans.clear();
16522
+ }
16523
+ function sanitizeUserMessage(message) {
16524
+ if (typeof message === "string" || message === void 0) {
16525
+ return message;
16526
+ }
16527
+ return {
16528
+ ...message,
16529
+ images: message.images?.map((image) => {
16530
+ const imageRecord = image;
16531
+ return {
16532
+ ...typeof imageRecord.url === "string" ? { url: imageRecord.url } : {},
16533
+ ...typeof imageRecord.mimeType === "string" ? { mimeType: imageRecord.mimeType } : {},
16534
+ ...image.dimension ? { dimension: image.dimension } : {},
16535
+ hasData: typeof imageRecord.data === "string"
16536
+ };
16537
+ })
16538
+ };
16539
+ }
16540
+ function extractAgentOptionsMetadata(options) {
16541
+ if (!options) {
16542
+ return {};
16543
+ }
16544
+ return {
16545
+ ...extractModelMetadata(options.model),
16546
+ ...options.agentId ? { "cursor_sdk.agent_id": options.agentId } : {},
16547
+ ...options.name ? { "cursor_sdk.agent_name": options.name } : {},
16548
+ ...options.local ? {
16549
+ "cursor_sdk.runtime": "local",
16550
+ "cursor_sdk.local.cwd": Array.isArray(options.local.cwd) ? options.local.cwd.join(",") : options.local.cwd
16551
+ } : {},
16552
+ ...options.cloud ? {
16553
+ "cursor_sdk.runtime": "cloud",
16554
+ "cursor_sdk.cloud.auto_create_pr": options.cloud.autoCreatePR,
16555
+ "cursor_sdk.cloud.env_type": options.cloud.env?.type,
16556
+ "cursor_sdk.cloud.env_name": options.cloud.env?.name,
16557
+ "cursor_sdk.cloud.repos": options.cloud.repos?.map((repo) => repo.url).filter((url) => typeof url === "string")
16558
+ } : {}
16559
+ };
16560
+ }
16561
+ function extractSendMetadata(options) {
16562
+ if (!options) {
16563
+ return {};
16564
+ }
16565
+ return {
16566
+ ...extractModelMetadata(options.model),
16567
+ ...options.local?.force !== void 0 ? { "cursor_sdk.local.force": options.local.force } : {}
16568
+ };
16569
+ }
16570
+ function extractAgentMetadata(agent) {
16571
+ return {
16572
+ ...agent.agentId ? { "cursor_sdk.agent_id": agent.agentId } : {},
16573
+ ...extractModelMetadata(agent.model)
16574
+ };
16575
+ }
16576
+ function extractRunMetadata(run) {
16577
+ if (!run) {
16578
+ return {};
16579
+ }
16580
+ return {
16581
+ ...run.id ? { "cursor_sdk.run_id": run.id } : {},
16582
+ ...run.agentId ? { "cursor_sdk.agent_id": run.agentId } : {},
16583
+ ...run.status ? { "cursor_sdk.status": run.status } : {},
16584
+ ...run.durationMs !== void 0 ? { "cursor_sdk.duration_ms": run.durationMs } : {},
16585
+ ...extractModelMetadata(run.model),
16586
+ ...extractGitMetadata(run.git)
16587
+ };
16588
+ }
16589
+ function extractRunResultMetadata(result) {
16590
+ if (!result) {
16591
+ return {};
16592
+ }
16593
+ return {
16594
+ ...result.id ? { "cursor_sdk.run_id": result.id } : {},
16595
+ ...result.status ? { "cursor_sdk.status": result.status } : {},
16596
+ ...result.durationMs !== void 0 ? { "cursor_sdk.duration_ms": result.durationMs } : {},
16597
+ ...extractModelMetadata(result.model),
16598
+ ...extractGitMetadata(result.git)
16599
+ };
16600
+ }
16601
+ function extractGitMetadata(git) {
16602
+ const branches = git?.branches;
16603
+ if (!branches || branches.length === 0) {
16604
+ return {};
16605
+ }
16606
+ return {
16607
+ "cursor_sdk.git.branches": branches.map((branch) => ({
16608
+ branch: branch.branch,
16609
+ prUrl: branch.prUrl,
16610
+ repoUrl: branch.repoUrl
16611
+ }))
16612
+ };
16613
+ }
16614
+ function extractModelMetadata(model) {
16615
+ if (!model?.id) {
16616
+ return {};
16617
+ }
16618
+ return {
16619
+ model: model.id,
16620
+ "cursor_sdk.model": model.id,
16621
+ ...model.params ? { "cursor_sdk.model.params": model.params } : {}
16622
+ };
16623
+ }
16624
+ function addUsageMetrics(metrics, usage) {
16625
+ if (!usage) {
16626
+ return;
16627
+ }
16628
+ if (usage.inputTokens !== void 0) {
16629
+ metrics.prompt_tokens = (metrics.prompt_tokens ?? 0) + usage.inputTokens;
16630
+ }
16631
+ if (usage.outputTokens !== void 0) {
16632
+ metrics.completion_tokens = (metrics.completion_tokens ?? 0) + usage.outputTokens;
16633
+ }
16634
+ if (usage.cacheReadTokens !== void 0) {
16635
+ metrics.prompt_cached_tokens = (metrics.prompt_cached_tokens ?? 0) + usage.cacheReadTokens;
16636
+ }
16637
+ if (usage.cacheWriteTokens !== void 0) {
16638
+ metrics.prompt_cache_creation_tokens = (metrics.prompt_cache_creation_tokens ?? 0) + usage.cacheWriteTokens;
16639
+ }
16640
+ metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0) + (metrics.prompt_cached_tokens ?? 0) + (metrics.prompt_cache_creation_tokens ?? 0);
16641
+ }
16642
+ function buildDurationMetrics(startTime) {
16643
+ const end = getCurrentUnixTimestamp();
16644
+ return {
16645
+ duration: end - startTime,
16646
+ end,
16647
+ start: startTime
16648
+ };
16649
+ }
16650
+ function extractToolName(toolCall) {
16651
+ if (!toolCall) {
16652
+ return "unknown";
16653
+ }
16654
+ if (typeof toolCall.name === "string") {
16655
+ return toolCall.name;
16656
+ }
16657
+ if (typeof toolCall.type === "string") {
16658
+ return toolCall.type;
16659
+ }
16660
+ return "unknown";
16661
+ }
16662
+ function extractToolArgs(toolCall) {
16663
+ return toolCall && "args" in toolCall ? toolCall.args : void 0;
16664
+ }
16665
+ function extractToolResult(toolCall) {
16666
+ return toolCall && "result" in toolCall ? toolCall.result : void 0;
16667
+ }
16668
+ function isSubAgentToolName(name) {
16669
+ return name === "Agent" || name === "Task" || name === "task";
16670
+ }
16671
+ function formatSubAgentSpanName2(toolCall, args) {
16672
+ const details = toolCall ?? args;
16673
+ const description = getString(details, "description") ?? getString(details, "subagent_type") ?? getString(details, "type") ?? getString(details, "name");
16674
+ return description ? `Agent: ${description}` : "Agent: sub-agent";
16675
+ }
16676
+ function getString(obj, key) {
16677
+ const value = obj?.[key];
16678
+ return typeof value === "string" ? value : void 0;
16679
+ }
16680
+ function stringifyUnknown(value) {
16681
+ if (value instanceof Error) {
16682
+ return value.message;
16683
+ }
16684
+ if (typeof value === "string") {
16685
+ return value;
16686
+ }
16687
+ try {
16688
+ return JSON.stringify(value);
16689
+ } catch {
16690
+ return String(value);
16691
+ }
16692
+ }
16693
+ function safeLog(span, event) {
16694
+ try {
16695
+ span.log(event);
16696
+ } catch (error) {
16697
+ logInstrumentationError("Cursor SDK span log", error);
16698
+ }
16699
+ }
16700
+ function logInstrumentationError(context, error) {
16701
+ debugLogger.error(`Error processing ${context}:`, error);
16702
+ }
16703
+ function cleanMetrics(metrics) {
16704
+ const cleaned = {};
16705
+ for (const [key, value] of Object.entries(metrics)) {
16706
+ if (value !== void 0 && Number.isFinite(value)) {
16707
+ cleaned[key] = value;
16708
+ }
16709
+ }
16710
+ return cleaned;
16711
+ }
16712
+
16713
+ // src/instrumentation/plugins/google-genai-channels.ts
16714
+ var googleGenAIChannels = defineChannels("@google/genai", {
16715
+ generateContent: channel({
16716
+ channelName: "models.generateContent",
16717
+ kind: "async"
16718
+ }),
16719
+ generateContentStream: channel({
16720
+ channelName: "models.generateContentStream",
16721
+ kind: "async"
16722
+ }),
16723
+ embedContent: channel({
16724
+ channelName: "models.embedContent",
16725
+ kind: "async"
16726
+ })
16727
+ });
16728
+
16729
+ // src/instrumentation/plugins/google-genai-plugin.ts
16730
+ var GOOGLE_GENAI_INTERNAL_CONTEXT = {
16731
+ caller_filename: "<node-internal>",
16732
+ caller_functionname: "<node-internal>",
16733
+ caller_lineno: 0
16734
+ };
16735
+ function createWrapperParityEvent(args) {
16736
+ return {
16737
+ context: GOOGLE_GENAI_INTERNAL_CONTEXT,
16738
+ input: args.input,
16739
+ metadata: args.metadata
16740
+ };
16741
+ }
16742
+ var GoogleGenAIPlugin = class extends BasePlugin {
16743
+ onEnable() {
16744
+ this.subscribeToGoogleGenAIChannels();
16745
+ }
16746
+ onDisable() {
16747
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
16748
+ }
16749
+ subscribeToGoogleGenAIChannels() {
16750
+ this.subscribeToGenerateContentChannel();
16751
+ this.subscribeToGenerateContentStreamChannel();
16752
+ this.subscribeToEmbedContentChannel();
16753
+ }
16754
+ subscribeToGenerateContentChannel() {
16755
+ const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
16756
+ const states = /* @__PURE__ */ new WeakMap();
16757
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
16758
+ tracingChannel2,
16759
+ states,
16760
+ (event) => {
16761
+ const params = event.arguments[0];
16762
+ const input = serializeGenerateContentInput(params);
16763
+ const metadata = extractGenerateContentMetadata(params);
16764
+ const span = startSpan({
16765
+ name: "generate_content",
16766
+ spanAttributes: {
16767
+ type: "llm" /* LLM */
16768
+ },
15485
16769
  event: createWrapperParityEvent({ input, metadata })
15486
16770
  });
15487
16771
  return {
@@ -15518,7 +16802,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
15518
16802
  const responseMetadata = extractResponseMetadata(event.result);
15519
16803
  spanState.span.log({
15520
16804
  ...responseMetadata ? { metadata: responseMetadata } : {},
15521
- metrics: cleanMetrics(
16805
+ metrics: cleanMetrics2(
15522
16806
  extractGenerateContentMetrics(
15523
16807
  event.result,
15524
16808
  spanState.startTime
@@ -15619,7 +16903,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
15619
16903
  const output = summarizeEmbedContentOutput(event.result);
15620
16904
  spanState.span.log({
15621
16905
  ...output ? { output } : {},
15622
- metrics: cleanMetrics(
16906
+ metrics: cleanMetrics2(
15623
16907
  extractEmbedContentMetrics(event.result, spanState.startTime)
15624
16908
  )
15625
16909
  });
@@ -15716,7 +17000,7 @@ function patchGoogleGenAIStreamingResult(args) {
15716
17000
  );
15717
17001
  span.log({
15718
17002
  ...responseMetadata ? { metadata: responseMetadata } : {},
15719
- metrics: cleanMetrics(metricsWithoutEnd),
17003
+ metrics: cleanMetrics2(metricsWithoutEnd),
15720
17004
  output: options.result.aggregated
15721
17005
  });
15722
17006
  span.end(typeof end === "number" ? { endTime: end } : void 0);
@@ -16141,7 +17425,7 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
16141
17425
  }
16142
17426
  return { aggregated, metrics };
16143
17427
  }
16144
- function cleanMetrics(metrics) {
17428
+ function cleanMetrics2(metrics) {
16145
17429
  const cleaned = {};
16146
17430
  for (const [key, value] of Object.entries(metrics)) {
16147
17431
  if (value !== null && value !== void 0) {
@@ -16225,6 +17509,8 @@ var REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
16225
17509
  "stop",
16226
17510
  "stream",
16227
17511
  "temperature",
17512
+ "tool_choice",
17513
+ "tools",
16228
17514
  "top_p"
16229
17515
  ]);
16230
17516
  var RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
@@ -16487,7 +17773,10 @@ function aggregateChatCompletionChunks2(chunks) {
16487
17773
  for (const chunk of chunks) {
16488
17774
  for (const choice of chunk.choices ?? []) {
16489
17775
  const index = typeof choice.index === "number" ? choice.index : 0;
16490
- const existing = aggregatedChoices.get(index) ?? { content: "" };
17776
+ const existing = aggregatedChoices.get(index) ?? {
17777
+ content: "",
17778
+ toolCallsByIndex: /* @__PURE__ */ new Map()
17779
+ };
16491
17780
  const delta = isObject(choice.delta) ? choice.delta : void 0;
16492
17781
  const message = isObject(choice.message) ? choice.message : void 0;
16493
17782
  if (typeof delta?.content === "string") {
@@ -16503,6 +17792,10 @@ function aggregateChatCompletionChunks2(chunks) {
16503
17792
  if (choice.finish_reason !== void 0) {
16504
17793
  existing.finish_reason = choice.finish_reason;
16505
17794
  }
17795
+ const toolCallDeltas = getChatToolCallDeltas(delta) ?? getChatToolCallDeltas(message);
17796
+ if (toolCallDeltas) {
17797
+ mergeChatToolCallDeltas(existing.toolCallsByIndex, toolCallDeltas);
17798
+ }
16506
17799
  aggregatedChoices.set(index, existing);
16507
17800
  }
16508
17801
  }
@@ -16511,12 +17804,72 @@ function aggregateChatCompletionChunks2(chunks) {
16511
17804
  index,
16512
17805
  message: {
16513
17806
  content: choice.content,
16514
- role: choice.role ?? "assistant"
17807
+ role: choice.role ?? "assistant",
17808
+ ...choice.toolCallsByIndex.size > 0 ? {
17809
+ tool_calls: [...choice.toolCallsByIndex.entries()].sort(([leftIndex], [rightIndex]) => leftIndex - rightIndex).map(([, toolCall]) => toolCall)
17810
+ } : {}
16515
17811
  },
16516
17812
  ...choice.finish_reason !== void 0 ? { finish_reason: choice.finish_reason } : {}
16517
17813
  }))
16518
17814
  };
16519
17815
  }
17816
+ function getChatToolCallDeltas(value) {
17817
+ if (!Array.isArray(value?.tool_calls)) {
17818
+ return void 0;
17819
+ }
17820
+ const toolCalls = value.tool_calls.filter((toolCall) => isObject(toolCall));
17821
+ return toolCalls.length > 0 ? toolCalls : void 0;
17822
+ }
17823
+ function mergeChatToolCallDeltas(toolCallsByIndex, toolCallDeltas) {
17824
+ for (const toolDelta of toolCallDeltas) {
17825
+ const toolIndex = typeof toolDelta.index === "number" && toolDelta.index >= 0 ? toolDelta.index : 0;
17826
+ const existing = toolCallsByIndex.get(toolIndex);
17827
+ if (!existing) {
17828
+ toolCallsByIndex.set(toolIndex, createChatToolCall(toolDelta));
17829
+ continue;
17830
+ }
17831
+ mergeChatToolCall(existing, toolDelta);
17832
+ }
17833
+ }
17834
+ function createChatToolCall(toolDelta) {
17835
+ const toolFunction = isObject(toolDelta.function) ? toolDelta.function : {};
17836
+ const toolCallFunction = {
17837
+ arguments: typeof toolFunction.arguments === "string" ? toolFunction.arguments : ""
17838
+ };
17839
+ if (typeof toolFunction.name === "string") {
17840
+ toolCallFunction.name = toolFunction.name;
17841
+ }
17842
+ const toolCall = {
17843
+ function: toolCallFunction
17844
+ };
17845
+ if (typeof toolDelta.id === "string") {
17846
+ toolCall.id = toolDelta.id;
17847
+ }
17848
+ if (typeof toolDelta.type === "string") {
17849
+ toolCall.type = toolDelta.type;
17850
+ }
17851
+ return toolCall;
17852
+ }
17853
+ function mergeChatToolCall(existing, toolDelta) {
17854
+ const currentFunction = isObject(existing.function) ? existing.function : {};
17855
+ const deltaFunction = isObject(toolDelta.function) ? toolDelta.function : {};
17856
+ const currentArguments = typeof currentFunction.arguments === "string" ? currentFunction.arguments : "";
17857
+ const deltaArguments = typeof deltaFunction.arguments === "string" ? deltaFunction.arguments : "";
17858
+ if (typeof toolDelta.id === "string" && typeof existing.id !== "string") {
17859
+ existing.id = toolDelta.id;
17860
+ }
17861
+ if (typeof toolDelta.type === "string" && typeof existing.type !== "string") {
17862
+ existing.type = toolDelta.type;
17863
+ }
17864
+ const nextFunction = {
17865
+ ...currentFunction,
17866
+ arguments: `${currentArguments}${deltaArguments}`
17867
+ };
17868
+ if (typeof deltaFunction.name === "string" && typeof currentFunction.name !== "string") {
17869
+ nextFunction.name = deltaFunction.name;
17870
+ }
17871
+ existing.function = nextFunction;
17872
+ }
16520
17873
  function aggregateTextGenerationStreamChunks(chunks) {
16521
17874
  if (chunks.length === 0) {
16522
17875
  return void 0;
@@ -18561,6 +19914,8 @@ var MISTRAL_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
18561
19914
  "presence_penalty",
18562
19915
  "randomSeed",
18563
19916
  "random_seed",
19917
+ "reasoningEffort",
19918
+ "reasoning_effort",
18564
19919
  "responseFormat",
18565
19920
  "response_format",
18566
19921
  "safePrompt",
@@ -18684,22 +20039,114 @@ function extractMistralStreamingMetrics(result, startTime) {
18684
20039
  if (startTime) {
18685
20040
  metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
18686
20041
  }
18687
- return metrics;
20042
+ return metrics;
20043
+ }
20044
+ function extractDeltaText(content) {
20045
+ if (typeof content === "string") {
20046
+ return content;
20047
+ }
20048
+ if (!Array.isArray(content)) {
20049
+ return void 0;
20050
+ }
20051
+ const textParts = content.map((part) => {
20052
+ if (!isObject(part) || part.type !== "text") {
20053
+ return "";
20054
+ }
20055
+ return typeof part.text === "string" ? part.text : "";
20056
+ }).filter((part) => part.length > 0);
20057
+ return textParts.length > 0 ? textParts.join("") : void 0;
20058
+ }
20059
+ function normalizeMistralTextContentPart(part) {
20060
+ if (!isObject(part) || part.type !== "text" || typeof part.text !== "string") {
20061
+ return void 0;
20062
+ }
20063
+ return {
20064
+ type: "text",
20065
+ text: part.text
20066
+ };
20067
+ }
20068
+ function normalizeMistralThinkingContentPart(part) {
20069
+ if (!isObject(part) || part.type !== "thinking") {
20070
+ return void 0;
20071
+ }
20072
+ const thinking = Array.isArray(part.thinking) ? part.thinking.map((thinkingPart) => normalizeMistralTextContentPart(thinkingPart)).filter(
20073
+ (thinkingPart) => thinkingPart !== void 0 && typeof thinkingPart.text === "string"
20074
+ ) : [];
20075
+ return {
20076
+ type: "thinking",
20077
+ thinking
20078
+ };
20079
+ }
20080
+ function normalizeMistralContentParts(content) {
20081
+ if (!Array.isArray(content)) {
20082
+ return [];
20083
+ }
20084
+ return content.map((part) => {
20085
+ return normalizeMistralTextContentPart(part) || normalizeMistralThinkingContentPart(part);
20086
+ }).filter((part) => part !== void 0);
20087
+ }
20088
+ function mergeMistralTextSegments(left, right) {
20089
+ const merged = left.map((part) => ({ ...part }));
20090
+ for (const part of right) {
20091
+ const lastPart = merged[merged.length - 1];
20092
+ if (lastPart && lastPart.type === "text" && typeof lastPart.text === "string" && typeof part.text === "string") {
20093
+ lastPart.text += part.text;
20094
+ continue;
20095
+ }
20096
+ merged.push({ ...part });
20097
+ }
20098
+ return merged;
20099
+ }
20100
+ function mergeMistralContentParts(left, right) {
20101
+ const merged = [...(left || []).map((part) => structuredClone(part))];
20102
+ for (const part of right) {
20103
+ const lastPart = merged[merged.length - 1];
20104
+ if (part.type === "text" && lastPart?.type === "text" && typeof lastPart.text === "string" && typeof part.text === "string") {
20105
+ lastPart.text += part.text;
20106
+ continue;
20107
+ }
20108
+ if (part.type === "thinking" && lastPart?.type === "thinking" && Array.isArray(lastPart.thinking) && Array.isArray(part.thinking)) {
20109
+ lastPart.thinking = mergeMistralTextSegments(
20110
+ lastPart.thinking,
20111
+ part.thinking
20112
+ );
20113
+ continue;
20114
+ }
20115
+ merged.push(structuredClone(part));
20116
+ }
20117
+ return merged;
18688
20118
  }
18689
- function extractDeltaText(content) {
20119
+ function appendMistralContent(accumulator, content) {
18690
20120
  if (typeof content === "string") {
18691
- return content;
20121
+ if (accumulator.contentParts) {
20122
+ accumulator.contentParts = mergeMistralContentParts(
20123
+ accumulator.contentParts,
20124
+ [{ type: "text", text: content }]
20125
+ );
20126
+ return;
20127
+ }
20128
+ accumulator.content = `${accumulator.content || ""}${content}`;
20129
+ return;
18692
20130
  }
18693
- if (!Array.isArray(content)) {
18694
- return void 0;
20131
+ const normalizedContentParts = normalizeMistralContentParts(content);
20132
+ if (normalizedContentParts.length === 0) {
20133
+ return;
18695
20134
  }
18696
- const textParts = content.map((part) => {
18697
- if (!isObject(part) || part.type !== "text") {
18698
- return "";
20135
+ const hasStructuredContent = normalizedContentParts.some(
20136
+ (part) => part.type !== "text"
20137
+ );
20138
+ if (!accumulator.contentParts && !hasStructuredContent) {
20139
+ const text = extractDeltaText(content);
20140
+ if (text) {
20141
+ accumulator.content = `${accumulator.content || ""}${text}`;
18699
20142
  }
18700
- return typeof part.text === "string" ? part.text : "";
18701
- }).filter((part) => part.length > 0);
18702
- return textParts.length > 0 ? textParts.join("") : void 0;
20143
+ return;
20144
+ }
20145
+ accumulator.contentParts = mergeMistralContentParts(
20146
+ accumulator.contentParts || (accumulator.content ? [{ type: "text", text: accumulator.content }] : []),
20147
+ normalizedContentParts
20148
+ );
20149
+ delete accumulator.content;
18703
20150
  }
18704
20151
  function getDeltaToolCalls(delta) {
18705
20152
  const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
@@ -18869,10 +20316,7 @@ function aggregateMistralStreamChunks(chunks) {
18869
20316
  if (!accumulator.role && typeof delta.role === "string") {
18870
20317
  accumulator.role = delta.role;
18871
20318
  }
18872
- const deltaText = extractDeltaText(delta.content);
18873
- if (deltaText) {
18874
- accumulator.content = `${accumulator.content || ""}${deltaText}`;
18875
- }
20319
+ appendMistralContent(accumulator, delta.content);
18876
20320
  accumulator.toolCalls = mergeToolCallDeltas(
18877
20321
  accumulator.toolCalls,
18878
20322
  getDeltaToolCalls(delta)
@@ -18890,7 +20334,7 @@ function aggregateMistralStreamChunks(chunks) {
18890
20334
  index: choice.index,
18891
20335
  message: {
18892
20336
  ...choice.role ? { role: choice.role } : {},
18893
- content: choice.content ?? null,
20337
+ content: choice.contentParts ?? choice.content ?? null,
18894
20338
  ...choice.toolCalls ? { toolCalls: choice.toolCalls } : {}
18895
20339
  },
18896
20340
  ...choice.finishReason !== void 0 ? { finishReason: choice.finishReason } : {}
@@ -19129,7 +20573,7 @@ var GoogleADKPlugin = class extends BasePlugin {
19129
20573
  start: (event) => {
19130
20574
  const req = event.arguments[0] ?? {};
19131
20575
  const tool = event.self;
19132
- const toolName = extractToolName(req, tool);
20576
+ const toolName = extractToolName2(req, tool);
19133
20577
  const parentSpan = findToolParentSpan(
19134
20578
  req,
19135
20579
  this.activeAgentSpans,
@@ -19168,7 +20612,7 @@ var GoogleADKPlugin = class extends BasePlugin {
19168
20612
  metrics.duration = end - state.startTime;
19169
20613
  state.span.log({
19170
20614
  output: event.result,
19171
- metrics: cleanMetrics2(metrics)
20615
+ metrics: cleanMetrics3(metrics)
19172
20616
  });
19173
20617
  } finally {
19174
20618
  state.span.end();
@@ -19387,7 +20831,7 @@ function extractToolCallId(req) {
19387
20831
  const toolContext = req.toolContext;
19388
20832
  return toolContext?.functionCallId;
19389
20833
  }
19390
- function extractToolName(req, tool) {
20834
+ function extractToolName2(req, tool) {
19391
20835
  if (typeof tool?.name === "string" && tool.name.length > 0) {
19392
20836
  return tool.name;
19393
20837
  }
@@ -19435,7 +20879,7 @@ function finalizeRunnerSpan(state, activeRunnerSpans) {
19435
20879
  }
19436
20880
  state.span.log({
19437
20881
  output: lastEvent ? extractEventOutput(lastEvent) : void 0,
19438
- metrics: cleanMetrics2(metrics)
20882
+ metrics: cleanMetrics3(metrics)
19439
20883
  });
19440
20884
  } finally {
19441
20885
  cleanupActiveRunnerSpan(state, activeRunnerSpans);
@@ -19452,7 +20896,7 @@ function finalizeAgentSpan(state, activeAgentSpans) {
19452
20896
  metrics.duration = end - state.startTime;
19453
20897
  state.span.log({
19454
20898
  output: lastEvent ? extractEventOutput(lastEvent) : void 0,
19455
- metrics: cleanMetrics2(metrics)
20899
+ metrics: cleanMetrics3(metrics)
19456
20900
  });
19457
20901
  } finally {
19458
20902
  cleanupActiveAgentSpan(state, activeAgentSpans);
@@ -19538,7 +20982,7 @@ function populateUsageMetrics2(metrics, usage) {
19538
20982
  metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
19539
20983
  }
19540
20984
  }
19541
- function cleanMetrics2(metrics) {
20985
+ function cleanMetrics3(metrics) {
19542
20986
  const cleaned = {};
19543
20987
  for (const [key, value] of Object.entries(metrics)) {
19544
20988
  if (value !== null && value !== void 0) {
@@ -19666,6 +21110,11 @@ var CHAT_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
19666
21110
  "strictTools",
19667
21111
  "strict_tools",
19668
21112
  "temperature",
21113
+ "thinking",
21114
+ "thinkingTokenBudget",
21115
+ "thinkingType",
21116
+ "thinking_token_budget",
21117
+ "thinking_type",
19669
21118
  "toolChoice",
19670
21119
  "tool_choice"
19671
21120
  ]);
@@ -19886,6 +21335,11 @@ function mergeUsageMetrics(metrics, usage) {
19886
21335
  "tokens",
19887
21336
  tokenContainer.totalTokens ?? tokenContainer.total_tokens
19888
21337
  );
21338
+ setMetricIfNumber(
21339
+ metrics,
21340
+ "reasoning_tokens",
21341
+ tokenContainer.reasoningTokens ?? tokenContainer.reasoning_tokens ?? tokenContainer.thinkingTokens ?? tokenContainer.thinking_tokens
21342
+ );
19889
21343
  }
19890
21344
  const billedUnits = (isObject(source.billedUnits) ? source.billedUnits : void 0) || (isObject(source.billed_units) ? source.billed_units : void 0);
19891
21345
  if (billedUnits) {
@@ -19966,13 +21420,87 @@ function extractV8DeltaText(chunk) {
19966
21420
  }
19967
21421
  return void 0;
19968
21422
  }
21423
+ function getV8ContentIndex(chunk) {
21424
+ return typeof chunk.index === "number" ? chunk.index : 0;
21425
+ }
21426
+ function toContentBlockType(value) {
21427
+ return value === "text" || value === "thinking" ? value : void 0;
21428
+ }
21429
+ function getOrCreateContentBlock(contentBlocksByIndex, contentBlockOrder, index) {
21430
+ if (!contentBlockOrder.includes(index)) {
21431
+ contentBlockOrder.push(index);
21432
+ }
21433
+ if (!(index in contentBlocksByIndex)) {
21434
+ contentBlocksByIndex[index] = {
21435
+ text: "",
21436
+ thinking: ""
21437
+ };
21438
+ }
21439
+ return contentBlocksByIndex[index];
21440
+ }
21441
+ function appendV8ContentBlock(contentBlocksByIndex, contentBlockOrder, index, content) {
21442
+ if (typeof content === "string") {
21443
+ const block2 = getOrCreateContentBlock(
21444
+ contentBlocksByIndex,
21445
+ contentBlockOrder,
21446
+ index
21447
+ );
21448
+ block2.type ??= "text";
21449
+ block2.text += content;
21450
+ return;
21451
+ }
21452
+ if (!isObject(content)) {
21453
+ return;
21454
+ }
21455
+ const block = getOrCreateContentBlock(
21456
+ contentBlocksByIndex,
21457
+ contentBlockOrder,
21458
+ index
21459
+ );
21460
+ const contentType = toContentBlockType(content.type);
21461
+ if (contentType) {
21462
+ block.type = contentType;
21463
+ }
21464
+ if (typeof content.text === "string") {
21465
+ block.type ??= "text";
21466
+ block.text += content.text;
21467
+ }
21468
+ if (typeof content.thinking === "string") {
21469
+ block.type ??= "thinking";
21470
+ block.thinking += content.thinking;
21471
+ }
21472
+ }
21473
+ function serializeAggregatedContentBlocks(contentBlocksByIndex, contentBlockOrder) {
21474
+ return contentBlockOrder.sort((left, right) => left - right).flatMap((index) => {
21475
+ const block = contentBlocksByIndex[index];
21476
+ if (!block) {
21477
+ return [];
21478
+ }
21479
+ if (block.type === "thinking" && block.thinking.length > 0) {
21480
+ return [{ type: "thinking", thinking: block.thinking }];
21481
+ }
21482
+ if (block.text.length > 0) {
21483
+ return [{ type: "text", text: block.text }];
21484
+ }
21485
+ if (block.thinking.length > 0) {
21486
+ return [{ type: "thinking", thinking: block.thinking }];
21487
+ }
21488
+ return [];
21489
+ });
21490
+ }
21491
+ function hasThinkingContent(contentBlocks) {
21492
+ return contentBlocks.some((block) => block.type === "thinking");
21493
+ }
19969
21494
  function aggregateCohereChatStreamChunks(chunks) {
19970
21495
  const textDeltas = [];
21496
+ const contentBlocksByIndex = {};
21497
+ const contentBlockOrder = [];
19971
21498
  const toolCallsByIndex = {};
19972
21499
  const toolCallOrder = [];
19973
21500
  let terminalResponse;
19974
21501
  let role;
19975
21502
  let finishReason;
21503
+ let toolPlan = "";
19976
21504
  let metadata = {};
19977
21505
  let metrics = {};
19978
21506
  for (const chunk of chunks) {
@@ -20030,12 +21558,36 @@ function aggregateCohereChatStreamChunks(chunks) {
20030
21558
  continue;
20031
21559
  }
20032
21560
  if (eventType === "content-delta") {
21561
+ appendV8ContentBlock(
21562
+ contentBlocksByIndex,
21563
+ contentBlockOrder,
21564
+ getV8ContentIndex(chunk),
21565
+ isObject(chunk.delta) && isObject(chunk.delta.message) ? chunk.delta.message.content : void 0
21566
+ );
20033
21567
  const text = extractV8DeltaText(chunk);
20034
21568
  if (text) {
20035
21569
  textDeltas.push(text);
20036
21570
  }
20037
21571
  continue;
20038
21572
  }
21573
+ if (eventType === "content-start") {
21574
+ appendV8ContentBlock(
21575
+ contentBlocksByIndex,
21576
+ contentBlockOrder,
21577
+ getV8ContentIndex(chunk),
21578
+ isObject(chunk.delta) && isObject(chunk.delta.message) ? chunk.delta.message.content : void 0
21579
+ );
21580
+ continue;
21581
+ }
21582
+ if (eventType === "tool-plan-delta") {
21583
+ if (isObject(chunk.delta) && isObject(chunk.delta.message)) {
21584
+ 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;
21585
+ if (deltaToolPlan) {
21586
+ toolPlan += deltaToolPlan;
21587
+ }
21588
+ }
21589
+ continue;
21590
+ }
20039
21591
  if (eventType === "tool-call-start") {
20040
21592
  const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
20041
21593
  Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
@@ -20089,13 +21641,26 @@ function aggregateCohereChatStreamChunks(chunks) {
20089
21641
  }
20090
21642
  }
20091
21643
  const mergedToolCalls = toolCallOrder.sort((left, right) => left - right).map((index) => toolCallsByIndex[index]).filter((toolCall) => isObject(toolCall));
21644
+ const aggregatedContentBlocks = serializeAggregatedContentBlocks(
21645
+ contentBlocksByIndex,
21646
+ contentBlockOrder
21647
+ );
20092
21648
  let output = extractCohereChatOutput(terminalResponse);
20093
21649
  if (output === void 0) {
20094
21650
  const mergedText = textDeltas.join("");
20095
- if (mergedToolCalls.length > 0 || role || mergedText.length > 0) {
21651
+ const shouldUseStructuredContent = hasThinkingContent(aggregatedContentBlocks) || toolPlan.length > 0;
21652
+ if (shouldUseStructuredContent) {
21653
+ output = {
21654
+ ...role ? { role } : {},
21655
+ ...aggregatedContentBlocks.length > 0 ? { content: aggregatedContentBlocks } : {},
21656
+ ...toolPlan.length > 0 ? { toolPlan } : {},
21657
+ ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
21658
+ };
21659
+ } else if (mergedToolCalls.length > 0 || role || mergedText.length > 0 || aggregatedContentBlocks.length > 0) {
21660
+ const textContent = mergedText.length > 0 ? mergedText : aggregatedContentBlocks[0]?.type === "text" ? aggregatedContentBlocks[0].text : void 0;
20096
21661
  output = {
20097
21662
  ...role ? { role } : {},
20098
- ...mergedText.length > 0 ? { content: mergedText } : {},
21663
+ ...textContent ? { content: textContent } : {},
20099
21664
  ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
20100
21665
  };
20101
21666
  }
@@ -20113,6 +21678,98 @@ function aggregateCohereChatStreamChunks(chunks) {
20113
21678
  };
20114
21679
  }
20115
21680
 
21681
+ // src/instrumentation/plugins/groq-channels.ts
21682
+ var groqChannels = defineChannels("groq-sdk", {
21683
+ chatCompletionsCreate: channel({
21684
+ channelName: "chat.completions.create",
21685
+ kind: "async"
21686
+ }),
21687
+ embeddingsCreate: channel(
21688
+ {
21689
+ channelName: "embeddings.create",
21690
+ kind: "async"
21691
+ }
21692
+ )
21693
+ });
21694
+
21695
+ // src/instrumentation/plugins/groq-plugin.ts
21696
+ var GroqPlugin = class extends BasePlugin {
21697
+ onEnable() {
21698
+ this.unsubscribers.push(
21699
+ traceStreamingChannel(groqChannels.chatCompletionsCreate, {
21700
+ name: "groq.chat.completions.create",
21701
+ type: "llm" /* LLM */,
21702
+ extractInput: ([params]) => {
21703
+ const { messages, ...metadata } = params;
21704
+ return {
21705
+ input: processInputAttachments(messages),
21706
+ metadata: { ...metadata, provider: "groq" }
21707
+ };
21708
+ },
21709
+ extractOutput: (result) => result?.choices,
21710
+ extractMetrics: (result, startTime) => {
21711
+ const metrics = parseGroqMetrics(result);
21712
+ if (startTime) {
21713
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
21714
+ }
21715
+ return metrics;
21716
+ },
21717
+ aggregateChunks: aggregateGroqChatCompletionChunks
21718
+ })
21719
+ );
21720
+ this.unsubscribers.push(
21721
+ traceAsyncChannel(groqChannels.embeddingsCreate, {
21722
+ name: "groq.embeddings.create",
21723
+ type: "llm" /* LLM */,
21724
+ extractInput: ([params]) => {
21725
+ const { input, ...metadata } = params;
21726
+ return {
21727
+ input,
21728
+ metadata: { ...metadata, provider: "groq" }
21729
+ };
21730
+ },
21731
+ extractOutput: (result) => {
21732
+ const embedding = result?.data?.[0]?.embedding;
21733
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
21734
+ },
21735
+ extractMetrics: (result) => parseGroqMetrics(result)
21736
+ })
21737
+ );
21738
+ }
21739
+ onDisable() {
21740
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
21741
+ }
21742
+ };
21743
+ function parseGroqMetrics(result) {
21744
+ const metrics = parseMetricsFromUsage(result?.usage);
21745
+ const xGroq = result?.x_groq;
21746
+ if (!xGroq || typeof xGroq !== "object") {
21747
+ return metrics;
21748
+ }
21749
+ const extraUsage = "usage" in xGroq ? xGroq.usage : void 0;
21750
+ if (!extraUsage || typeof extraUsage !== "object") {
21751
+ return metrics;
21752
+ }
21753
+ const dramCachedTokens = extraUsage["dram_cached_tokens"];
21754
+ const sramCachedTokens = extraUsage["sram_cached_tokens"];
21755
+ return {
21756
+ ...metrics,
21757
+ ...typeof dramCachedTokens === "number" ? { dram_cached_tokens: dramCachedTokens } : {},
21758
+ ...typeof sramCachedTokens === "number" ? { sram_cached_tokens: sramCachedTokens } : {}
21759
+ };
21760
+ }
21761
+ function aggregateGroqChatCompletionChunks(chunks, streamResult, endEvent) {
21762
+ const aggregated = aggregateChatCompletionChunks(
21763
+ chunks,
21764
+ streamResult,
21765
+ endEvent
21766
+ );
21767
+ return {
21768
+ metrics: aggregated.metrics,
21769
+ output: aggregated.output
21770
+ };
21771
+ }
21772
+
20116
21773
  // src/instrumentation/braintrust-plugin.ts
20117
21774
  var BraintrustPlugin = class extends BasePlugin {
20118
21775
  config;
@@ -20120,6 +21777,7 @@ var BraintrustPlugin = class extends BasePlugin {
20120
21777
  anthropicPlugin = null;
20121
21778
  aiSDKPlugin = null;
20122
21779
  claudeAgentSDKPlugin = null;
21780
+ cursorSDKPlugin = null;
20123
21781
  googleGenAIPlugin = null;
20124
21782
  huggingFacePlugin = null;
20125
21783
  openRouterPlugin = null;
@@ -20127,6 +21785,7 @@ var BraintrustPlugin = class extends BasePlugin {
20127
21785
  mistralPlugin = null;
20128
21786
  googleADKPlugin = null;
20129
21787
  coherePlugin = null;
21788
+ groqPlugin = null;
20130
21789
  constructor(config = {}) {
20131
21790
  super();
20132
21791
  this.config = config;
@@ -20149,6 +21808,10 @@ var BraintrustPlugin = class extends BasePlugin {
20149
21808
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
20150
21809
  this.claudeAgentSDKPlugin.enable();
20151
21810
  }
21811
+ if (integrations.cursorSDK !== false && integrations.cursor !== false) {
21812
+ this.cursorSDKPlugin = new CursorSDKPlugin();
21813
+ this.cursorSDKPlugin.enable();
21814
+ }
20152
21815
  if (integrations.googleGenAI !== false && integrations.google !== false) {
20153
21816
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
20154
21817
  this.googleGenAIPlugin.enable();
@@ -20177,6 +21840,10 @@ var BraintrustPlugin = class extends BasePlugin {
20177
21840
  this.coherePlugin = new CoherePlugin();
20178
21841
  this.coherePlugin.enable();
20179
21842
  }
21843
+ if (integrations.groq !== false) {
21844
+ this.groqPlugin = new GroqPlugin();
21845
+ this.groqPlugin.enable();
21846
+ }
20180
21847
  }
20181
21848
  onDisable() {
20182
21849
  if (this.openaiPlugin) {
@@ -20195,6 +21862,10 @@ var BraintrustPlugin = class extends BasePlugin {
20195
21862
  this.claudeAgentSDKPlugin.disable();
20196
21863
  this.claudeAgentSDKPlugin = null;
20197
21864
  }
21865
+ if (this.cursorSDKPlugin) {
21866
+ this.cursorSDKPlugin.disable();
21867
+ this.cursorSDKPlugin = null;
21868
+ }
20198
21869
  if (this.googleGenAIPlugin) {
20199
21870
  this.googleGenAIPlugin.disable();
20200
21871
  this.googleGenAIPlugin = null;
@@ -20223,6 +21894,10 @@ var BraintrustPlugin = class extends BasePlugin {
20223
21894
  this.coherePlugin.disable();
20224
21895
  this.coherePlugin = null;
20225
21896
  }
21897
+ if (this.groqPlugin) {
21898
+ this.groqPlugin.disable();
21899
+ this.groqPlugin = null;
21900
+ }
20226
21901
  }
20227
21902
  };
20228
21903
 
@@ -20296,6 +21971,8 @@ var PluginRegistry = class {
20296
21971
  google: true,
20297
21972
  huggingface: true,
20298
21973
  claudeAgentSDK: true,
21974
+ cursor: true,
21975
+ cursorSDK: true,
20299
21976
  openrouter: true,
20300
21977
  openrouterAgent: true,
20301
21978
  mistral: true,
@@ -20312,7 +21989,11 @@ var PluginRegistry = class {
20312
21989
  if (disabledList) {
20313
21990
  const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
20314
21991
  for (const sdk of disabled) {
20315
- integrations[sdk] = false;
21992
+ if (sdk === "cursor-sdk") {
21993
+ integrations.cursorSDK = false;
21994
+ } else {
21995
+ integrations[sdk] = false;
21996
+ }
20316
21997
  }
20317
21998
  }
20318
21999
  return { integrations };
@@ -20491,8 +22172,10 @@ __export(exports_exports, {
20491
22172
  wrapAnthropic: () => wrapAnthropic,
20492
22173
  wrapClaudeAgentSDK: () => wrapClaudeAgentSDK,
20493
22174
  wrapCohere: () => wrapCohere,
22175
+ wrapCursorSDK: () => wrapCursorSDK,
20494
22176
  wrapGoogleADK: () => wrapGoogleADK,
20495
22177
  wrapGoogleGenAI: () => wrapGoogleGenAI,
22178
+ wrapGroq: () => wrapGroq,
20496
22179
  wrapHuggingFace: () => wrapHuggingFace,
20497
22180
  wrapMastraAgent: () => wrapMastraAgent,
20498
22181
  wrapMistral: () => wrapMistral,
@@ -22107,6 +23790,130 @@ function claudeAgentSDKProxy(sdk) {
22107
23790
  });
22108
23791
  }
22109
23792
 
23793
+ // src/wrappers/cursor-sdk.ts
23794
+ var WRAPPED_AGENT2 = Symbol.for("braintrust.cursor-sdk.wrapped-agent");
23795
+ function wrapCursorSDK(sdk) {
23796
+ if (!sdk || typeof sdk !== "object") {
23797
+ return sdk;
23798
+ }
23799
+ const maybeSDK = sdk;
23800
+ if (!maybeSDK.Agent || typeof maybeSDK.Agent !== "function") {
23801
+ console.warn("Unsupported Cursor SDK. Not wrapping.");
23802
+ return sdk;
23803
+ }
23804
+ const target = isModuleNamespace2(sdk) ? Object.setPrototypeOf({}, sdk) : sdk;
23805
+ return new Proxy(target, {
23806
+ get(target2, prop, receiver) {
23807
+ const value = Reflect.get(target2, prop, receiver);
23808
+ if (prop === "Agent" && typeof value === "function") {
23809
+ return wrapCursorAgentClass(value);
23810
+ }
23811
+ if (typeof value === "function") {
23812
+ return value.bind(target2);
23813
+ }
23814
+ return value;
23815
+ }
23816
+ });
23817
+ }
23818
+ function isModuleNamespace2(obj) {
23819
+ if (!obj || typeof obj !== "object") {
23820
+ return false;
23821
+ }
23822
+ if (obj.constructor?.name === "Module") {
23823
+ return true;
23824
+ }
23825
+ const keys = Object.keys(obj);
23826
+ if (keys.length === 0) {
23827
+ return false;
23828
+ }
23829
+ const descriptor = Object.getOwnPropertyDescriptor(obj, keys[0]);
23830
+ return descriptor ? !descriptor.configurable && !descriptor.writable : false;
23831
+ }
23832
+ function wrapCursorAgentClass(Agent) {
23833
+ const cache = /* @__PURE__ */ new Map();
23834
+ return new Proxy(Agent, {
23835
+ get(target, prop, receiver) {
23836
+ if (cache.has(prop)) {
23837
+ return cache.get(prop);
23838
+ }
23839
+ const value = Reflect.get(target, prop, receiver);
23840
+ if (prop === "create" && typeof value === "function") {
23841
+ const wrapped = async function(options) {
23842
+ const args = [options];
23843
+ return cursorSDKChannels.create.tracePromise(
23844
+ async () => wrapCursorAgent(await Reflect.apply(value, target, args)),
23845
+ { arguments: args }
23846
+ );
23847
+ };
23848
+ cache.set(prop, wrapped);
23849
+ return wrapped;
23850
+ }
23851
+ if (prop === "resume" && typeof value === "function") {
23852
+ const wrapped = async function(agentId, options) {
23853
+ const args = [agentId, options];
23854
+ return cursorSDKChannels.resume.tracePromise(
23855
+ async () => wrapCursorAgent(await Reflect.apply(value, target, args)),
23856
+ { arguments: args }
23857
+ );
23858
+ };
23859
+ cache.set(prop, wrapped);
23860
+ return wrapped;
23861
+ }
23862
+ if (prop === "prompt" && typeof value === "function") {
23863
+ const wrapped = async function(message, options) {
23864
+ const args = [message, options];
23865
+ return cursorSDKChannels.prompt.tracePromise(
23866
+ () => Reflect.apply(value, target, args),
23867
+ { arguments: args }
23868
+ );
23869
+ };
23870
+ cache.set(prop, wrapped);
23871
+ return wrapped;
23872
+ }
23873
+ if (typeof value === "function") {
23874
+ const bound = value.bind(target);
23875
+ cache.set(prop, bound);
23876
+ return bound;
23877
+ }
23878
+ return value;
23879
+ }
23880
+ });
23881
+ }
23882
+ function wrapCursorAgent(agent) {
23883
+ if (!agent || typeof agent !== "object") {
23884
+ return agent;
23885
+ }
23886
+ if (agent[WRAPPED_AGENT2]) {
23887
+ return agent;
23888
+ }
23889
+ const proxy = new Proxy(agent, {
23890
+ get(target, prop, receiver) {
23891
+ if (prop === WRAPPED_AGENT2) {
23892
+ return true;
23893
+ }
23894
+ const value = Reflect.get(target, prop, receiver);
23895
+ if (prop === "send" && typeof value === "function") {
23896
+ return function(message, options) {
23897
+ const args = [message, options];
23898
+ return cursorSDKChannels.send.tracePromise(
23899
+ () => Reflect.apply(value, target, args),
23900
+ {
23901
+ agent: target,
23902
+ arguments: args,
23903
+ operation: "send"
23904
+ }
23905
+ );
23906
+ };
23907
+ }
23908
+ if (typeof value === "function") {
23909
+ return value.bind(target);
23910
+ }
23911
+ return value;
23912
+ }
23913
+ });
23914
+ return proxy;
23915
+ }
23916
+
22110
23917
  // src/wrappers/google-genai.ts
22111
23918
  function wrapGoogleGenAI(googleGenAI) {
22112
23919
  if (!googleGenAI || typeof googleGenAI !== "object") {
@@ -22860,6 +24667,94 @@ function wrapRerank3(rerank) {
22860
24667
  });
22861
24668
  }
22862
24669
 
24670
+ // src/wrappers/groq.ts
24671
+ function wrapGroq(groq) {
24672
+ if (isSupportedGroqClient(groq)) {
24673
+ return groqProxy(groq);
24674
+ }
24675
+ console.warn("Unsupported Groq library. Not wrapping.");
24676
+ return groq;
24677
+ }
24678
+ function isRecord3(value) {
24679
+ return typeof value === "object" && value !== null;
24680
+ }
24681
+ function hasFunction4(value, methodName) {
24682
+ return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
24683
+ }
24684
+ function hasChat2(value) {
24685
+ return isRecord3(value) && isRecord3(value.completions) && hasFunction4(value.completions, "create");
24686
+ }
24687
+ function hasEmbeddings2(value) {
24688
+ return hasFunction4(value, "create");
24689
+ }
24690
+ function isSupportedGroqClient(value) {
24691
+ return isRecord3(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
24692
+ }
24693
+ function groqProxy(groq) {
24694
+ const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
24695
+ const completionProxy = groq.chat?.completions ? new Proxy(groq.chat.completions, {
24696
+ get(target, prop, receiver) {
24697
+ if (prop === "create") {
24698
+ return wrapChatCompletionsCreate(target.create.bind(target));
24699
+ }
24700
+ return Reflect.get(target, prop, receiver);
24701
+ }
24702
+ }) : void 0;
24703
+ const chatProxy3 = groq.chat ? new Proxy(groq.chat, {
24704
+ get(target, prop, receiver) {
24705
+ if (prop === "completions") {
24706
+ return completionProxy ?? target.completions;
24707
+ }
24708
+ return Reflect.get(target, prop, receiver);
24709
+ }
24710
+ }) : void 0;
24711
+ const embeddingsProxy3 = groq.embeddings ? new Proxy(groq.embeddings, {
24712
+ get(target, prop, receiver) {
24713
+ if (prop === "create") {
24714
+ return wrapEmbeddingsCreate2(target.create.bind(target));
24715
+ }
24716
+ return Reflect.get(target, prop, receiver);
24717
+ }
24718
+ }) : void 0;
24719
+ const topLevelProxy = new Proxy(groq, {
24720
+ get(target, prop, receiver) {
24721
+ switch (prop) {
24722
+ case "chat":
24723
+ return chatProxy3 ?? target.chat;
24724
+ case "embeddings":
24725
+ return embeddingsProxy3 ?? target.embeddings;
24726
+ }
24727
+ const value = Reflect.get(target, prop, target);
24728
+ if (typeof value !== "function") {
24729
+ return value;
24730
+ }
24731
+ const cachedValue = privateMethodWorkaroundCache.get(value);
24732
+ if (cachedValue) {
24733
+ return cachedValue;
24734
+ }
24735
+ const thisBoundValue = function(...args) {
24736
+ const thisArg = this === topLevelProxy ? target : this;
24737
+ const output = Reflect.apply(value, thisArg, args);
24738
+ return output === target ? topLevelProxy : output;
24739
+ };
24740
+ privateMethodWorkaroundCache.set(value, thisBoundValue);
24741
+ return thisBoundValue;
24742
+ }
24743
+ });
24744
+ return topLevelProxy;
24745
+ }
24746
+ function wrapChatCompletionsCreate(create) {
24747
+ return (request, options) => groqChannels.chatCompletionsCreate.tracePromise(
24748
+ () => create(request, options),
24749
+ { arguments: [request] }
24750
+ );
24751
+ }
24752
+ function wrapEmbeddingsCreate2(create) {
24753
+ return (request, options) => groqChannels.embeddingsCreate.tracePromise(() => create(request, options), {
24754
+ arguments: [request]
24755
+ });
24756
+ }
24757
+
22863
24758
  // src/wrappers/vitest/context-manager.ts
22864
24759
  var VitestContextManager = class {
22865
24760
  /**