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/index.mjs CHANGED
@@ -2118,6 +2118,7 @@ var TopicMapData = z6.object({
2118
2118
  report_key: z6.string().optional(),
2119
2119
  topic_names: z6.record(z6.string()).optional(),
2120
2120
  generation_settings: TopicMapGenerationSettings.optional(),
2121
+ disable_reconciliation: z6.boolean().optional(),
2121
2122
  distance_threshold: z6.number().optional()
2122
2123
  });
2123
2124
  var BatchedFacetData = z6.object({
@@ -2448,28 +2449,6 @@ var EnvVar = z6.object({
2448
2449
  secret_type: z6.union([z6.string(), z6.null()]).optional(),
2449
2450
  secret_category: z6.enum(["env_var", "ai_provider", "sandbox_provider"]).optional().default("env_var")
2450
2451
  });
2451
- var EvalStatusPageTheme = z6.enum(["light", "dark"]);
2452
- var EvalStatusPageConfig = z6.object({
2453
- score_columns: z6.union([z6.array(z6.string()), z6.null()]),
2454
- metric_columns: z6.union([z6.array(z6.string()), z6.null()]),
2455
- grouping_field: z6.union([z6.string(), z6.null()]),
2456
- filter: z6.union([z6.string(), z6.null()]),
2457
- sort_by: z6.union([z6.string(), z6.null()]),
2458
- sort_order: z6.union([z6.enum(["asc", "desc"]), z6.null()]),
2459
- api_key: z6.union([z6.string(), z6.null()])
2460
- }).partial();
2461
- var EvalStatusPage = z6.object({
2462
- id: z6.string().uuid(),
2463
- project_id: z6.string().uuid(),
2464
- user_id: z6.union([z6.string(), z6.null()]).optional(),
2465
- created: z6.union([z6.string(), z6.null()]).optional(),
2466
- deleted_at: z6.union([z6.string(), z6.null()]).optional(),
2467
- name: z6.string(),
2468
- description: z6.union([z6.string(), z6.null()]).optional(),
2469
- logo_url: z6.union([z6.string(), z6.null()]).optional(),
2470
- theme: EvalStatusPageTheme,
2471
- config: EvalStatusPageConfig
2472
- });
2473
2452
  var RepoInfo = z6.union([
2474
2453
  z6.object({
2475
2454
  commit: z6.union([z6.string(), z6.null()]),
@@ -2496,6 +2475,15 @@ var Experiment = z6.object({
2496
2475
  deleted_at: z6.union([z6.string(), z6.null()]).optional(),
2497
2476
  dataset_id: z6.union([z6.string(), z6.null()]).optional(),
2498
2477
  dataset_version: z6.union([z6.string(), z6.null()]).optional(),
2478
+ internal_metadata: z6.union([
2479
+ z6.object({
2480
+ dataset_filter: z6.union([
2481
+ z6.object({}).partial().passthrough(),
2482
+ z6.null()
2483
+ ])
2484
+ }).partial().passthrough(),
2485
+ z6.null()
2486
+ ]).optional(),
2499
2487
  parameters_id: z6.union([z6.string(), z6.null()]).optional(),
2500
2488
  parameters_version: z6.union([z6.string(), z6.null()]).optional(),
2501
2489
  public: z6.boolean(),
@@ -3232,14 +3220,21 @@ var ProjectAutomation = z6.object({
3232
3220
  z6.object({ type: z6.literal("log_spans") }),
3233
3221
  z6.object({ type: z6.literal("btql_query"), btql_query: z6.string() })
3234
3222
  ]),
3223
+ scope: z6.union([SpanScope, TraceScope, GroupScope, z6.null()]).optional(),
3235
3224
  export_path: z6.string(),
3236
3225
  format: z6.enum(["jsonl", "parquet"]),
3237
3226
  interval_seconds: z6.number().gte(1).lte(2592e3),
3238
- credentials: z6.object({
3239
- type: z6.literal("aws_iam"),
3240
- role_arn: z6.string(),
3241
- external_id: z6.string()
3242
- }),
3227
+ credentials: z6.union([
3228
+ z6.object({
3229
+ type: z6.literal("aws_iam"),
3230
+ role_arn: z6.string(),
3231
+ external_id: z6.string()
3232
+ }),
3233
+ z6.object({
3234
+ type: z6.literal("gcp_service_account"),
3235
+ service_account_email: z6.string()
3236
+ })
3237
+ ]),
3243
3238
  batch_size: z6.union([z6.number(), z6.null()]).optional()
3244
3239
  }),
3245
3240
  z6.object({
@@ -3619,7 +3614,7 @@ var ViewOptions = z6.union([
3619
3614
  z6.object({ from: z6.string(), to: z6.string() }),
3620
3615
  z6.null()
3621
3616
  ]),
3622
- queryShape: z6.union([z6.enum(["traces", "spans"]), z6.null()]),
3617
+ queryShape: z6.union([z6.enum(["traces", "spans", "topics"]), z6.null()]),
3623
3618
  cluster: z6.union([z6.string(), z6.null()]),
3624
3619
  freezeColumns: z6.union([z6.boolean(), z6.null()])
3625
3620
  }).partial(),
@@ -4635,6 +4630,19 @@ var RESET_CONTEXT_MANAGER_STATE = Symbol.for(
4635
4630
  "braintrust.resetContextManagerState"
4636
4631
  );
4637
4632
  var DEFAULT_MAX_REQUEST_SIZE = 6 * 1024 * 1024;
4633
+ var datasetSnapshotRegisterResponseSchema = z8.object({
4634
+ dataset_snapshot: DatasetSnapshot,
4635
+ found_existing: z8.boolean().optional()
4636
+ });
4637
+ var datasetRestorePreviewResultSchema = z8.object({
4638
+ rows_to_restore: z8.number(),
4639
+ rows_to_delete: z8.number()
4640
+ });
4641
+ var datasetRestoreResultSchema = z8.object({
4642
+ xact_id: z8.string().nullable(),
4643
+ rows_restored: z8.number(),
4644
+ rows_deleted: z8.number()
4645
+ });
4638
4646
  var parametersRowSchema = z8.object({
4639
4647
  id: z8.string().uuid(),
4640
4648
  _xact_id: z8.string(),
@@ -6856,6 +6864,33 @@ Error: ${errorText}`;
6856
6864
  this.queue.enforceQueueSizeLimit(enforce);
6857
6865
  }
6858
6866
  };
6867
+ function isDatasetSnapshotNameLookup(lookup) {
6868
+ return "snapshotName" in lookup;
6869
+ }
6870
+ function assertDatasetSnapshotLookup(lookup) {
6871
+ const hasSnapshotName = lookup.snapshotName !== void 0;
6872
+ const hasXactId = lookup.xactId !== void 0;
6873
+ if (hasSnapshotName === hasXactId) {
6874
+ throw new Error("Exactly one of snapshotName or xactId must be provided");
6875
+ }
6876
+ }
6877
+ function getExperimentDatasetFilter({
6878
+ dataset,
6879
+ _internal_btql
6880
+ }) {
6881
+ if (_internal_btql !== void 0) {
6882
+ return _internal_btql;
6883
+ }
6884
+ if (!(dataset instanceof Dataset2)) {
6885
+ return void 0;
6886
+ }
6887
+ const datasetFilter = Reflect.get(dataset, "_internal_btql");
6888
+ return isObject(datasetFilter) ? datasetFilter : void 0;
6889
+ }
6890
+ function getInternalBtqlLimit(internalBtql) {
6891
+ const limit = internalBtql?.["limit"];
6892
+ return typeof limit === "number" ? limit : void 0;
6893
+ }
6859
6894
  function init(projectOrOptions, optionalOptions) {
6860
6895
  const options = (() => {
6861
6896
  if (typeof projectOrOptions === "string") {
@@ -6874,6 +6909,7 @@ function init(projectOrOptions, optionalOptions) {
6874
6909
  experiment,
6875
6910
  description,
6876
6911
  dataset,
6912
+ _internal_btql,
6877
6913
  parameters,
6878
6914
  baseExperiment,
6879
6915
  isPublic,
@@ -6982,16 +7018,24 @@ function init(projectOrOptions, optionalOptions) {
6982
7018
  args["ancestor_commits"] = await isomorph_default.getPastNAncestors();
6983
7019
  }
6984
7020
  if (dataset !== void 0) {
6985
- if ("id" in dataset && typeof dataset.id === "string" && !("__braintrust_dataset_marker" in dataset)) {
6986
- args["dataset_id"] = dataset.id;
6987
- if ("version" in dataset && dataset.version !== void 0) {
6988
- args["dataset_version"] = dataset.version;
6989
- }
6990
- } else {
6991
- args["dataset_id"] = await dataset.id;
6992
- args["dataset_version"] = await dataset.version();
7021
+ const datasetSelection = await serializeDatasetForExperiment({
7022
+ dataset,
7023
+ state
7024
+ });
7025
+ args["dataset_id"] = datasetSelection.datasetId;
7026
+ if (datasetSelection.datasetVersion !== void 0) {
7027
+ args["dataset_version"] = datasetSelection.datasetVersion;
6993
7028
  }
6994
7029
  }
7030
+ const datasetFilter = getExperimentDatasetFilter({
7031
+ dataset,
7032
+ _internal_btql
7033
+ });
7034
+ if (datasetFilter !== void 0) {
7035
+ args["internal_metadata"] = {
7036
+ dataset_filter: datasetFilter
7037
+ };
7038
+ }
6995
7039
  if (parameters !== void 0) {
6996
7040
  if (RemoteEvalParameters.isParameters(parameters)) {
6997
7041
  args["parameters_id"] = parameters.id;
@@ -7045,7 +7089,7 @@ function init(projectOrOptions, optionalOptions) {
7045
7089
  const ret = new Experiment2(
7046
7090
  state,
7047
7091
  lazyMetadata,
7048
- dataset !== void 0 && "version" in dataset ? dataset : void 0
7092
+ dataset !== void 0 ? dataset : void 0
7049
7093
  );
7050
7094
  if (options.setCurrent ?? true) {
7051
7095
  state.currentExperiment = ret;
@@ -7081,6 +7125,153 @@ function withLogger(callback, options = {}) {
7081
7125
  const logger = initLogger(options);
7082
7126
  return callback(logger);
7083
7127
  }
7128
+ async function getDatasetSnapshots(params) {
7129
+ const { state, datasetId } = params;
7130
+ return DatasetSnapshot.array().parse(
7131
+ await state.appConn().post_json("api/dataset_snapshot/get", {
7132
+ dataset_id: datasetId,
7133
+ ..."snapshotName" in params ? { name: params.snapshotName } : {},
7134
+ ..."xactId" in params ? { xact_id: params.xactId } : {}
7135
+ })
7136
+ );
7137
+ }
7138
+ async function getDatasetSnapshot(params) {
7139
+ assertDatasetSnapshotLookup(params);
7140
+ const snapshots = await getDatasetSnapshots(params);
7141
+ if (snapshots.length > 1) {
7142
+ throw new Error(
7143
+ 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}`
7144
+ );
7145
+ }
7146
+ return snapshots[0];
7147
+ }
7148
+ function normalizeDatasetSelection({
7149
+ version,
7150
+ environment,
7151
+ snapshotName
7152
+ }) {
7153
+ if (version !== void 0) {
7154
+ return { version };
7155
+ }
7156
+ if (snapshotName !== void 0) {
7157
+ return { snapshotName };
7158
+ }
7159
+ if (environment !== void 0) {
7160
+ return { environment };
7161
+ }
7162
+ return {};
7163
+ }
7164
+ async function resolveDatasetSnapshotName({
7165
+ state,
7166
+ datasetId,
7167
+ snapshotName
7168
+ }) {
7169
+ const match = await getDatasetSnapshot({
7170
+ state,
7171
+ datasetId,
7172
+ snapshotName
7173
+ });
7174
+ if (match === void 0) {
7175
+ throw new Error(
7176
+ `Dataset snapshot "${snapshotName}" not found for ${datasetId}`
7177
+ );
7178
+ }
7179
+ return match.xact_id;
7180
+ }
7181
+ async function resolveDatasetSnapshotNameForMetadata({
7182
+ state,
7183
+ lazyMetadata,
7184
+ snapshotName
7185
+ }) {
7186
+ const metadata = await lazyMetadata.get();
7187
+ return await resolveDatasetSnapshotName({
7188
+ state,
7189
+ datasetId: metadata.dataset.id,
7190
+ snapshotName
7191
+ });
7192
+ }
7193
+ async function resolveDatasetEnvironment({
7194
+ state,
7195
+ datasetId,
7196
+ environment
7197
+ }) {
7198
+ const environmentObjectPath = `environment-object/dataset/${datasetId}/${encodeURIComponent(environment)}`;
7199
+ const response = state.orgName == null ? await state.apiConn().get_json(environmentObjectPath) : await state.apiConn().get_json(environmentObjectPath, {
7200
+ org_name: state.orgName
7201
+ });
7202
+ return z8.object({ object_version: z8.string() }).parse(response).object_version;
7203
+ }
7204
+ async function resolveDatasetEnvironmentForMetadata({
7205
+ state,
7206
+ lazyMetadata,
7207
+ environment
7208
+ }) {
7209
+ const metadata = await lazyMetadata.get();
7210
+ return await resolveDatasetEnvironment({
7211
+ state,
7212
+ datasetId: metadata.dataset.id,
7213
+ environment
7214
+ });
7215
+ }
7216
+ async function serializeDatasetForExperiment({
7217
+ dataset,
7218
+ state
7219
+ }) {
7220
+ if (!Dataset2.isDataset(dataset)) {
7221
+ const selection2 = normalizeDatasetSelection(dataset);
7222
+ if (selection2.version !== void 0) {
7223
+ return {
7224
+ datasetId: dataset.id,
7225
+ datasetVersion: selection2.version
7226
+ };
7227
+ }
7228
+ if (selection2.snapshotName !== void 0) {
7229
+ return {
7230
+ datasetId: dataset.id,
7231
+ datasetVersion: await resolveDatasetSnapshotName({
7232
+ state,
7233
+ datasetId: dataset.id,
7234
+ snapshotName: selection2.snapshotName
7235
+ })
7236
+ };
7237
+ }
7238
+ if (selection2.environment !== void 0) {
7239
+ return {
7240
+ datasetId: dataset.id,
7241
+ datasetVersion: await resolveDatasetEnvironment({
7242
+ state,
7243
+ datasetId: dataset.id,
7244
+ environment: selection2.environment
7245
+ })
7246
+ };
7247
+ }
7248
+ return {
7249
+ datasetId: dataset.id
7250
+ };
7251
+ }
7252
+ const evalData = await dataset.toEvalData();
7253
+ const selection = normalizeDatasetSelection({
7254
+ version: evalData.dataset_version,
7255
+ environment: evalData.dataset_environment,
7256
+ snapshotName: evalData.dataset_snapshot_name
7257
+ });
7258
+ if (selection.version !== void 0) {
7259
+ return {
7260
+ datasetId: evalData.dataset_id,
7261
+ datasetVersion: selection.version
7262
+ };
7263
+ }
7264
+ const datasetVersion = await dataset.version();
7265
+ if (datasetVersion !== void 0) {
7266
+ return {
7267
+ datasetId: evalData.dataset_id,
7268
+ datasetVersion
7269
+ };
7270
+ }
7271
+ return {
7272
+ datasetId: evalData.dataset_id
7273
+ };
7274
+ }
7084
7275
  function initDataset(projectOrOptions, optionalOptions) {
7085
7276
  const options = (() => {
7086
7277
  if (typeof projectOrOptions === "string") {
@@ -7099,6 +7290,8 @@ function initDataset(projectOrOptions, optionalOptions) {
7099
7290
  dataset,
7100
7291
  description,
7101
7292
  version,
7293
+ snapshotName,
7294
+ environment,
7102
7295
  appUrl,
7103
7296
  apiKey,
7104
7297
  orgName,
@@ -7110,6 +7303,14 @@ function initDataset(projectOrOptions, optionalOptions) {
7110
7303
  state: stateArg,
7111
7304
  _internal_btql
7112
7305
  } = options;
7306
+ const selection = normalizeDatasetSelection({
7307
+ version,
7308
+ environment,
7309
+ snapshotName
7310
+ });
7311
+ const normalizedVersion = selection.version;
7312
+ const normalizedEnvironment = selection.environment;
7313
+ const normalizedSnapshotName = selection.snapshotName;
7113
7314
  const state = stateArg ?? _globalState;
7114
7315
  const lazyMetadata = new LazyValue(
7115
7316
  async () => {
@@ -7143,13 +7344,38 @@ function initDataset(projectOrOptions, optionalOptions) {
7143
7344
  };
7144
7345
  }
7145
7346
  );
7146
- return new Dataset2(
7347
+ const resolvedVersion = normalizedVersion !== void 0 ? normalizedVersion : normalizedSnapshotName !== void 0 ? new LazyValue(async () => {
7348
+ return await resolveDatasetSnapshotNameForMetadata({
7349
+ state,
7350
+ lazyMetadata,
7351
+ snapshotName: normalizedSnapshotName
7352
+ });
7353
+ }) : normalizedEnvironment !== void 0 ? new LazyValue(async () => {
7354
+ return await resolveDatasetEnvironmentForMetadata({
7355
+ state,
7356
+ lazyMetadata,
7357
+ environment: normalizedEnvironment
7358
+ });
7359
+ }) : void 0;
7360
+ const datasetObject = new Dataset2(
7147
7361
  stateArg ?? _globalState,
7148
7362
  lazyMetadata,
7149
- version,
7363
+ typeof resolvedVersion === "string" ? resolvedVersion : void 0,
7150
7364
  legacy,
7151
- _internal_btql
7365
+ _internal_btql,
7366
+ resolvedVersion instanceof LazyValue || normalizedEnvironment !== void 0 || normalizedSnapshotName !== void 0 ? {
7367
+ ...resolvedVersion instanceof LazyValue ? {
7368
+ lazyPinnedVersion: resolvedVersion
7369
+ } : {},
7370
+ ...normalizedEnvironment !== void 0 ? {
7371
+ pinnedEnvironment: normalizedEnvironment
7372
+ } : {},
7373
+ ...normalizedSnapshotName !== void 0 ? {
7374
+ pinnedSnapshotName: normalizedSnapshotName
7375
+ } : {}
7376
+ } : void 0
7152
7377
  );
7378
+ return datasetObject;
7153
7379
  }
7154
7380
  function withDataset(project, callback, options = {}) {
7155
7381
  debugLogger.forState(options.state).warn(
@@ -8145,11 +8371,20 @@ var ObjectFetcher = class {
8145
8371
  async getState() {
8146
8372
  throw new Error("ObjectFetcher subclasses must have a 'getState' method");
8147
8373
  }
8374
+ getPinnedVersion() {
8375
+ return this.pinnedVersion;
8376
+ }
8377
+ setPinnedVersion(pinnedVersion) {
8378
+ this.pinnedVersion = pinnedVersion;
8379
+ }
8380
+ getInternalBtql() {
8381
+ return this._internal_btql;
8382
+ }
8148
8383
  async *fetchRecordsFromApi(batchSize) {
8149
8384
  const state = await this.getState();
8150
8385
  const objectId = await this.id;
8151
8386
  const batchLimit = batchSize ?? DEFAULT_FETCH_BATCH_SIZE;
8152
- const internalLimit = this._internal_btql?.limit;
8387
+ const internalLimit = getInternalBtqlLimit(this._internal_btql);
8153
8388
  const limit = batchSize !== void 0 ? batchSize : internalLimit ?? batchLimit;
8154
8389
  const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
8155
8390
  Object.entries(this._internal_btql ?? {}).filter(
@@ -8963,7 +9198,7 @@ function splitLoggingData({
8963
9198
  return [serializableInternalData, lazyInternalData];
8964
9199
  }
8965
9200
  var Dataset2 = class extends ObjectFetcher {
8966
- constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql) {
9201
+ constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql, pinState) {
8967
9202
  const isLegacyDataset = legacy ?? DEFAULT_IS_LEGACY_DATASET;
8968
9203
  if (isLegacyDataset) {
8969
9204
  debugLogger.forState(state).warn(
@@ -8984,10 +9219,16 @@ var Dataset2 = class extends ObjectFetcher {
8984
9219
  );
8985
9220
  this.state = state;
8986
9221
  this.lazyMetadata = lazyMetadata;
9222
+ this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
9223
+ this.pinnedEnvironment = pinState?.pinnedEnvironment;
9224
+ this.pinnedSnapshotName = pinState?.pinnedSnapshotName;
8987
9225
  }
8988
9226
  lazyMetadata;
8989
9227
  __braintrust_dataset_marker = true;
8990
9228
  newRecords = 0;
9229
+ lazyPinnedVersion;
9230
+ pinnedEnvironment;
9231
+ pinnedSnapshotName;
8991
9232
  get id() {
8992
9233
  return (async () => {
8993
9234
  return (await this.lazyMetadata.get()).dataset.id;
@@ -9006,10 +9247,40 @@ var Dataset2 = class extends ObjectFetcher {
9006
9247
  get loggingState() {
9007
9248
  return this.state;
9008
9249
  }
9250
+ async toEvalData() {
9251
+ await this.getState();
9252
+ const metadata = await this.lazyMetadata.get();
9253
+ const pinnedVersion = this.getPinnedVersion();
9254
+ const internalBtql = this.getInternalBtql();
9255
+ return {
9256
+ dataset_id: metadata.dataset.id,
9257
+ ...this.pinnedEnvironment !== void 0 ? {
9258
+ dataset_environment: this.pinnedEnvironment
9259
+ } : {},
9260
+ ...this.pinnedEnvironment === void 0 && this.pinnedSnapshotName !== void 0 ? {
9261
+ dataset_snapshot_name: this.pinnedSnapshotName
9262
+ } : {},
9263
+ ...this.pinnedEnvironment === void 0 && this.pinnedSnapshotName === void 0 && pinnedVersion !== void 0 ? {
9264
+ dataset_version: pinnedVersion
9265
+ } : {},
9266
+ ...internalBtql !== void 0 ? { _internal_btql: internalBtql } : {}
9267
+ };
9268
+ }
9009
9269
  async getState() {
9010
9270
  await this.lazyMetadata.get();
9271
+ if (this.lazyPinnedVersion !== void 0 && this.getPinnedVersion() === void 0) {
9272
+ this.setPinnedVersion(await this.lazyPinnedVersion.get());
9273
+ }
9011
9274
  return this.state;
9012
9275
  }
9276
+ async version(options) {
9277
+ const pinnedVersion = this.getPinnedVersion();
9278
+ if (pinnedVersion !== void 0) {
9279
+ return pinnedVersion;
9280
+ }
9281
+ await this.getState();
9282
+ return await super.version(options);
9283
+ }
9013
9284
  validateEvent({
9014
9285
  metadata,
9015
9286
  expected,
@@ -9145,6 +9416,88 @@ var Dataset2 = class extends ObjectFetcher {
9145
9416
  this.state.bgLogger().log([args]);
9146
9417
  return id;
9147
9418
  }
9419
+ async createSnapshot({
9420
+ name,
9421
+ description,
9422
+ update
9423
+ }) {
9424
+ await this.flush();
9425
+ const state = await this.getState();
9426
+ const datasetId = await this.id;
9427
+ const currentVersion = await this.version();
9428
+ if (currentVersion === void 0) {
9429
+ throw new Error("Cannot create snapshot: dataset has no version");
9430
+ }
9431
+ const response = await state.appConn().post_json("api/dataset_snapshot/register", {
9432
+ dataset_id: datasetId,
9433
+ dataset_snapshot_name: name,
9434
+ description,
9435
+ xact_id: currentVersion,
9436
+ update
9437
+ });
9438
+ return datasetSnapshotRegisterResponseSchema.parse(response).dataset_snapshot;
9439
+ }
9440
+ async listSnapshots() {
9441
+ const state = await this.getState();
9442
+ return await getDatasetSnapshots({
9443
+ state,
9444
+ datasetId: await this.id
9445
+ });
9446
+ }
9447
+ async getSnapshot(lookup) {
9448
+ const state = await this.getState();
9449
+ const datasetId = await this.id;
9450
+ return await getDatasetSnapshot({
9451
+ state,
9452
+ datasetId,
9453
+ ...lookup
9454
+ });
9455
+ }
9456
+ async updateSnapshot(snapshotId, {
9457
+ name,
9458
+ description
9459
+ }) {
9460
+ const state = await this.getState();
9461
+ return DatasetSnapshot.parse(
9462
+ await state.appConn().post_json("api/dataset_snapshot/patch_id", {
9463
+ id: snapshotId,
9464
+ name,
9465
+ description
9466
+ })
9467
+ );
9468
+ }
9469
+ async deleteSnapshot(snapshotId) {
9470
+ const state = await this.getState();
9471
+ return DatasetSnapshot.parse(
9472
+ await state.appConn().post_json("api/dataset_snapshot/delete_id", {
9473
+ id: snapshotId
9474
+ })
9475
+ );
9476
+ }
9477
+ async restorePreview({
9478
+ version
9479
+ }) {
9480
+ await this.flush();
9481
+ const state = await this.getState();
9482
+ const datasetId = await this.id;
9483
+ return datasetRestorePreviewResultSchema.parse(
9484
+ await state.apiConn().post_json(`v1/dataset/${datasetId}/restore/preview`, {
9485
+ version
9486
+ })
9487
+ );
9488
+ }
9489
+ async restore({
9490
+ version
9491
+ }) {
9492
+ await this.flush();
9493
+ const state = await this.getState();
9494
+ const datasetId = await this.id;
9495
+ return datasetRestoreResultSchema.parse(
9496
+ await state.apiConn().post_json(`v1/dataset/${datasetId}/restore`, {
9497
+ version
9498
+ })
9499
+ );
9500
+ }
9148
9501
  /**
9149
9502
  * Summarize the dataset, including high level metrics about its size and other metadata.
9150
9503
  * @param summarizeData Whether to summarize the data. If false, only the metadata will be returned.
@@ -14402,6 +14755,9 @@ function llmParentKey(parentToolUseId) {
14402
14755
  function isSubAgentDelegationToolName(toolName) {
14403
14756
  return toolName === "Agent" || toolName === "Task";
14404
14757
  }
14758
+ function shouldParentToolAsTaskSibling(toolName) {
14759
+ return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
14760
+ }
14405
14761
  function filterSerializableOptions(options) {
14406
14762
  const allowedKeys = [
14407
14763
  "model",
@@ -14501,6 +14857,11 @@ function resolveTaskToolUseId(taskIdToToolUseId, message) {
14501
14857
  }
14502
14858
  return void 0;
14503
14859
  }
14860
+ function seedTaskToolUseIdMapping(taskIdToToolUseId, message) {
14861
+ if (typeof message.task_id === "string" && typeof message.tool_use_id === "string") {
14862
+ taskIdToToolUseId.set(message.task_id, message.tool_use_id);
14863
+ }
14864
+ }
14504
14865
  function extractUsageFromMessage(message) {
14505
14866
  const metrics = {};
14506
14867
  let usage;
@@ -14696,7 +15057,10 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
14696
15057
  }
14697
15058
  },
14698
15059
  name: parsed.displayName,
14699
- parent: await resolveParentSpan(toolUseID),
15060
+ parent: await resolveParentSpan(toolUseID, {
15061
+ agentId: input.agent_id,
15062
+ preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
15063
+ }),
14700
15064
  spanAttributes: { type: "tool" /* TOOL */ }
14701
15065
  });
14702
15066
  activeToolSpans.set(toolUseID, toolSpan);
@@ -14986,6 +15350,7 @@ async function finalizeCurrentMessageGroup(state) {
14986
15350
  state.currentMessages.length = 0;
14987
15351
  }
14988
15352
  function maybeTrackToolUseContext(state, message) {
15353
+ seedTaskToolUseIdMapping(state.taskIdToToolUseId, message);
14989
15354
  if (message.type !== "assistant" || !Array.isArray(message.message?.content)) {
14990
15355
  return;
14991
15356
  }
@@ -15040,6 +15405,34 @@ async function ensureSubAgentSpan(subAgentDetailsByToolUseId, rootSpan, activeTo
15040
15405
  subAgentSpans.set(parentToolUseId, subAgentSpan);
15041
15406
  return subAgentSpan;
15042
15407
  }
15408
+ async function ensureActiveLlmSpanForParentToolUse(rootSpan, activeLlmSpansByParentToolUse, subAgentDetailsByToolUseId, activeToolSpans, subAgentSpans, parentToolUseId, startTime) {
15409
+ const parentKey = llmParentKey(parentToolUseId);
15410
+ const existingLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
15411
+ if (existingLlmSpan) {
15412
+ return existingLlmSpan;
15413
+ }
15414
+ let llmParentSpan = await rootSpan.export();
15415
+ if (parentToolUseId) {
15416
+ const subAgentSpan = await ensureSubAgentSpan(
15417
+ subAgentDetailsByToolUseId,
15418
+ rootSpan,
15419
+ activeToolSpans,
15420
+ subAgentSpans,
15421
+ parentToolUseId
15422
+ );
15423
+ llmParentSpan = await subAgentSpan.export();
15424
+ }
15425
+ const llmSpan = startSpan({
15426
+ name: "anthropic.messages.create",
15427
+ parent: llmParentSpan,
15428
+ spanAttributes: {
15429
+ type: "llm" /* LLM */
15430
+ },
15431
+ startTime
15432
+ });
15433
+ activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
15434
+ return llmSpan;
15435
+ }
15043
15436
  async function maybeHandleTaskLifecycleMessage(state, message) {
15044
15437
  if (message.type !== "system") {
15045
15438
  return false;
@@ -15149,29 +15542,15 @@ async function handleStreamMessage(state, message) {
15149
15542
  }
15150
15543
  if (message.type === "assistant" && message.message?.usage) {
15151
15544
  const parentToolUseId = message.parent_tool_use_id ?? null;
15152
- const parentKey = llmParentKey(parentToolUseId);
15153
- if (!state.activeLlmSpansByParentToolUse.has(parentKey)) {
15154
- let llmParentSpan = await state.span.export();
15155
- if (parentToolUseId) {
15156
- const subAgentSpan = await ensureSubAgentSpan(
15157
- state.subAgentDetailsByToolUseId,
15158
- state.span,
15159
- state.activeToolSpans,
15160
- state.subAgentSpans,
15161
- parentToolUseId
15162
- );
15163
- llmParentSpan = await subAgentSpan.export();
15164
- }
15165
- const llmSpan = startSpan({
15166
- name: "anthropic.messages.create",
15167
- parent: llmParentSpan,
15168
- spanAttributes: {
15169
- type: "llm" /* LLM */
15170
- },
15171
- startTime: state.currentMessageStartTime
15172
- });
15173
- state.activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
15174
- }
15545
+ await ensureActiveLlmSpanForParentToolUse(
15546
+ state.span,
15547
+ state.activeLlmSpansByParentToolUse,
15548
+ state.subAgentDetailsByToolUseId,
15549
+ state.activeToolSpans,
15550
+ state.subAgentSpans,
15551
+ parentToolUseId,
15552
+ state.currentMessageStartTime
15553
+ );
15175
15554
  state.currentMessages.push(message);
15176
15555
  }
15177
15556
  if (message.type !== "result" || !message.usage) {
@@ -15318,10 +15697,35 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
15318
15697
  const localToolContext = createClaudeLocalToolContext();
15319
15698
  const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
15320
15699
  const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
15321
- const resolveToolUseParentSpan = async (toolUseID) => {
15322
- const parentToolUseId = toolUseToParent.get(toolUseID) ?? null;
15700
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
15701
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
15702
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
15323
15703
  const parentKey = llmParentKey(parentToolUseId);
15324
15704
  const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
15705
+ if (context?.preferTaskSiblingParent) {
15706
+ if (!activeLlmSpan) {
15707
+ await ensureActiveLlmSpanForParentToolUse(
15708
+ span,
15709
+ activeLlmSpansByParentToolUse,
15710
+ subAgentDetailsByToolUseId,
15711
+ activeToolSpans,
15712
+ subAgentSpans,
15713
+ parentToolUseId,
15714
+ getCurrentUnixTimestamp()
15715
+ );
15716
+ }
15717
+ if (parentToolUseId) {
15718
+ const subAgentSpan = await ensureSubAgentSpan(
15719
+ subAgentDetailsByToolUseId,
15720
+ span,
15721
+ activeToolSpans,
15722
+ subAgentSpans,
15723
+ parentToolUseId
15724
+ );
15725
+ return subAgentSpan.export();
15726
+ }
15727
+ return span.export();
15728
+ }
15325
15729
  if (activeLlmSpan) {
15326
15730
  return activeLlmSpan.export();
15327
15731
  }
@@ -15449,62 +15853,940 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
15449
15853
  }
15450
15854
  };
15451
15855
 
15452
- // src/instrumentation/plugins/google-genai-channels.ts
15453
- var googleGenAIChannels = defineChannels("@google/genai", {
15454
- generateContent: channel({
15455
- channelName: "models.generateContent",
15856
+ // src/instrumentation/plugins/cursor-sdk-channels.ts
15857
+ var cursorSDKChannels = defineChannels("@cursor/sdk", {
15858
+ create: channel({
15859
+ channelName: "Agent.create",
15456
15860
  kind: "async"
15457
15861
  }),
15458
- generateContentStream: channel({
15459
- channelName: "models.generateContentStream",
15862
+ resume: channel({
15863
+ channelName: "Agent.resume",
15460
15864
  kind: "async"
15461
15865
  }),
15462
- embedContent: channel({
15463
- channelName: "models.embedContent",
15866
+ prompt: channel({
15867
+ channelName: "Agent.prompt",
15868
+ kind: "async"
15869
+ }),
15870
+ send: channel({
15871
+ channelName: "agent.send",
15464
15872
  kind: "async"
15465
15873
  })
15466
15874
  });
15467
15875
 
15468
- // src/instrumentation/plugins/google-genai-plugin.ts
15469
- var GOOGLE_GENAI_INTERNAL_CONTEXT = {
15470
- caller_filename: "<node-internal>",
15471
- caller_functionname: "<node-internal>",
15472
- caller_lineno: 0
15473
- };
15474
- function createWrapperParityEvent(args) {
15475
- return {
15476
- context: GOOGLE_GENAI_INTERNAL_CONTEXT,
15477
- input: args.input,
15478
- metadata: args.metadata
15479
- };
15480
- }
15481
- var GoogleGenAIPlugin = class extends BasePlugin {
15876
+ // src/instrumentation/plugins/cursor-sdk-plugin.ts
15877
+ var PATCHED_AGENT = Symbol.for("braintrust.cursor-sdk.auto-patched-agent");
15878
+ var PATCHED_RUN = Symbol.for("braintrust.cursor-sdk.patched-run");
15879
+ var WRAPPED_AGENT = Symbol.for("braintrust.cursor-sdk.wrapped-agent");
15880
+ var CursorSDKPlugin = class extends BasePlugin {
15881
+ promptDepth = 0;
15482
15882
  onEnable() {
15483
- this.subscribeToGoogleGenAIChannels();
15883
+ this.subscribeToAgentFactories();
15884
+ this.subscribeToPrompt();
15885
+ this.subscribeToSend();
15484
15886
  }
15485
15887
  onDisable() {
15486
- this.unsubscribers = unsubscribeAll(this.unsubscribers);
15888
+ for (const unsubscribe of this.unsubscribers) {
15889
+ unsubscribe();
15890
+ }
15891
+ this.unsubscribers = [];
15892
+ this.promptDepth = 0;
15487
15893
  }
15488
- subscribeToGoogleGenAIChannels() {
15489
- this.subscribeToGenerateContentChannel();
15490
- this.subscribeToGenerateContentStreamChannel();
15491
- this.subscribeToEmbedContentChannel();
15894
+ subscribeToAgentFactories() {
15895
+ this.subscribeToAgentFactory(cursorSDKChannels.create);
15896
+ this.subscribeToAgentFactory(cursorSDKChannels.resume);
15492
15897
  }
15493
- subscribeToGenerateContentChannel() {
15494
- const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
15898
+ subscribeToAgentFactory(channel2) {
15899
+ const tracingChannel2 = channel2.tracingChannel();
15900
+ const handlers = {
15901
+ asyncEnd: (event) => {
15902
+ patchCursorAgentInPlace(event.result);
15903
+ },
15904
+ error: () => {
15905
+ }
15906
+ };
15907
+ tracingChannel2.subscribe(handlers);
15908
+ this.unsubscribers.push(() => {
15909
+ tracingChannel2.unsubscribe(handlers);
15910
+ });
15911
+ }
15912
+ subscribeToPrompt() {
15913
+ const channel2 = cursorSDKChannels.prompt.tracingChannel();
15495
15914
  const states = /* @__PURE__ */ new WeakMap();
15496
- const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
15497
- tracingChannel2,
15498
- states,
15499
- (event) => {
15500
- const params = event.arguments[0];
15501
- const input = serializeGenerateContentInput(params);
15502
- const metadata = extractGenerateContentMetadata(params);
15915
+ const handlers = {
15916
+ start: (event) => {
15917
+ this.promptDepth += 1;
15918
+ const message = event.arguments[0];
15919
+ const options = event.arguments[1];
15920
+ const metadata = {
15921
+ ...extractAgentOptionsMetadata(options),
15922
+ "cursor_sdk.operation": "Agent.prompt",
15923
+ provider: "cursor",
15924
+ ...event.moduleVersion ? { "cursor_sdk.version": event.moduleVersion } : {}
15925
+ };
15503
15926
  const span = startSpan({
15504
- name: "generate_content",
15505
- spanAttributes: {
15506
- type: "llm" /* LLM */
15507
- },
15927
+ name: "Cursor Agent",
15928
+ spanAttributes: { type: "task" /* TASK */ }
15929
+ });
15930
+ const startTime = getCurrentUnixTimestamp();
15931
+ safeLog(span, {
15932
+ input: sanitizeUserMessage(message),
15933
+ metadata
15934
+ });
15935
+ states.set(event, { metadata, span, startTime });
15936
+ },
15937
+ asyncEnd: (event) => {
15938
+ this.promptDepth = Math.max(0, this.promptDepth - 1);
15939
+ const state = states.get(event);
15940
+ if (!state) {
15941
+ return;
15942
+ }
15943
+ try {
15944
+ safeLog(state.span, {
15945
+ metadata: {
15946
+ ...state.metadata,
15947
+ ...extractRunResultMetadata(event.result)
15948
+ },
15949
+ metrics: buildDurationMetrics(state.startTime),
15950
+ output: event.result?.result ?? event.result
15951
+ });
15952
+ } finally {
15953
+ state.span.end();
15954
+ states.delete(event);
15955
+ }
15956
+ },
15957
+ error: (event) => {
15958
+ this.promptDepth = Math.max(0, this.promptDepth - 1);
15959
+ const state = states.get(event);
15960
+ if (!state || !event.error) {
15961
+ return;
15962
+ }
15963
+ safeLog(state.span, { error: event.error.message });
15964
+ state.span.end();
15965
+ states.delete(event);
15966
+ }
15967
+ };
15968
+ channel2.subscribe(handlers);
15969
+ this.unsubscribers.push(() => {
15970
+ channel2.unsubscribe(handlers);
15971
+ });
15972
+ }
15973
+ subscribeToSend() {
15974
+ const channel2 = cursorSDKChannels.send.tracingChannel();
15975
+ const states = /* @__PURE__ */ new WeakMap();
15976
+ const handlers = {
15977
+ start: (event) => {
15978
+ if (this.promptDepth > 0) {
15979
+ return;
15980
+ }
15981
+ const message = event.arguments[0];
15982
+ const sendOptions = event.arguments[1];
15983
+ const agent = event.agent;
15984
+ const metadata = {
15985
+ ...extractSendMetadata(sendOptions),
15986
+ ...agent ? extractAgentMetadata(agent) : {},
15987
+ "cursor_sdk.operation": "agent.send",
15988
+ provider: "cursor",
15989
+ ...event.moduleVersion ? { "cursor_sdk.version": event.moduleVersion } : {}
15990
+ };
15991
+ const span = startSpan({
15992
+ name: "Cursor Agent",
15993
+ spanAttributes: { type: "task" /* TASK */ }
15994
+ });
15995
+ const startTime = getCurrentUnixTimestamp();
15996
+ safeLog(span, {
15997
+ input: sanitizeUserMessage(message),
15998
+ metadata
15999
+ });
16000
+ const state = {
16001
+ activeToolSpans: /* @__PURE__ */ new Map(),
16002
+ agent,
16003
+ conversationText: [],
16004
+ deltaText: [],
16005
+ finalized: false,
16006
+ input: message,
16007
+ metadata,
16008
+ metrics: {},
16009
+ span,
16010
+ startTime,
16011
+ streamMessages: [],
16012
+ streamText: [],
16013
+ stepText: [],
16014
+ taskText: []
16015
+ };
16016
+ if (hasCursorCallbacks(sendOptions)) {
16017
+ event.arguments[1] = wrapSendOptionsCallbacks(sendOptions, state);
16018
+ }
16019
+ states.set(event, state);
16020
+ },
16021
+ asyncEnd: (event) => {
16022
+ const state = states.get(event);
16023
+ if (!state) {
16024
+ return;
16025
+ }
16026
+ if (!event.result) {
16027
+ return;
16028
+ }
16029
+ state.run = event.result;
16030
+ state.metadata = {
16031
+ ...state.metadata,
16032
+ ...extractRunMetadata(event.result)
16033
+ };
16034
+ patchCursorRun(event.result, state);
16035
+ },
16036
+ error: (event) => {
16037
+ const state = states.get(event);
16038
+ if (!state || !event.error) {
16039
+ return;
16040
+ }
16041
+ safeLog(state.span, { error: event.error.message });
16042
+ endOpenToolSpans(state, event.error.message);
16043
+ state.span.end();
16044
+ state.finalized = true;
16045
+ states.delete(event);
16046
+ }
16047
+ };
16048
+ channel2.subscribe(handlers);
16049
+ this.unsubscribers.push(() => {
16050
+ channel2.unsubscribe(handlers);
16051
+ });
16052
+ }
16053
+ };
16054
+ function patchCursorAgentInPlace(agent) {
16055
+ if (!agent || typeof agent !== "object") {
16056
+ return;
16057
+ }
16058
+ const agentRecord = agent;
16059
+ if (agentRecord[PATCHED_AGENT] || agentRecord[WRAPPED_AGENT] || typeof agentRecord.send !== "function") {
16060
+ return;
16061
+ }
16062
+ const originalSend = agentRecord.send.bind(agentRecord);
16063
+ try {
16064
+ Object.defineProperty(agentRecord, PATCHED_AGENT, {
16065
+ configurable: false,
16066
+ enumerable: false,
16067
+ value: true
16068
+ });
16069
+ Object.defineProperty(agentRecord, "send", {
16070
+ configurable: true,
16071
+ value(message, options) {
16072
+ const args = [message, options];
16073
+ return cursorSDKChannels.send.tracePromise(
16074
+ () => originalSend(...args),
16075
+ {
16076
+ agent: agentRecord,
16077
+ arguments: args,
16078
+ operation: "send"
16079
+ }
16080
+ );
16081
+ },
16082
+ writable: true
16083
+ });
16084
+ } catch {
16085
+ }
16086
+ }
16087
+ function wrapSendOptionsCallbacks(options, state) {
16088
+ const originalOnDelta = options.onDelta;
16089
+ const originalOnStep = options.onStep;
16090
+ return {
16091
+ ...options,
16092
+ async onDelta(args) {
16093
+ try {
16094
+ await handleInteractionUpdate(state, args.update);
16095
+ } catch (error) {
16096
+ logInstrumentationError("Cursor SDK onDelta", error);
16097
+ }
16098
+ if (originalOnDelta) {
16099
+ return originalOnDelta(args);
16100
+ }
16101
+ },
16102
+ async onStep(args) {
16103
+ try {
16104
+ handleStepUpdate(state, args.step);
16105
+ } catch (error) {
16106
+ logInstrumentationError("Cursor SDK onStep", error);
16107
+ }
16108
+ if (originalOnStep) {
16109
+ return originalOnStep(args);
16110
+ }
16111
+ }
16112
+ };
16113
+ }
16114
+ function hasCursorCallbacks(options) {
16115
+ return !!options && (typeof options.onDelta === "function" || typeof options.onStep === "function");
16116
+ }
16117
+ function patchCursorRun(run, state) {
16118
+ if (!run || typeof run !== "object") {
16119
+ return;
16120
+ }
16121
+ const runRecord = run;
16122
+ if (runRecord[PATCHED_RUN]) {
16123
+ return;
16124
+ }
16125
+ try {
16126
+ Object.defineProperty(runRecord, PATCHED_RUN, {
16127
+ configurable: false,
16128
+ enumerable: false,
16129
+ value: true
16130
+ });
16131
+ if (typeof runRecord.stream === "function") {
16132
+ const originalStream = runRecord.stream.bind(runRecord);
16133
+ Object.defineProperty(runRecord, "stream", {
16134
+ configurable: true,
16135
+ value() {
16136
+ const stream = originalStream();
16137
+ return patchCursorStream(stream, state);
16138
+ },
16139
+ writable: true
16140
+ });
16141
+ }
16142
+ if (typeof runRecord.wait === "function") {
16143
+ const originalWait = runRecord.wait.bind(runRecord);
16144
+ Object.defineProperty(runRecord, "wait", {
16145
+ configurable: true,
16146
+ async value() {
16147
+ try {
16148
+ const result = await originalWait();
16149
+ state.lastResult = result;
16150
+ await finalizeCursorRun(state, { result });
16151
+ return result;
16152
+ } catch (error) {
16153
+ await finalizeCursorRun(state, { error });
16154
+ throw error;
16155
+ }
16156
+ },
16157
+ writable: true
16158
+ });
16159
+ }
16160
+ if (typeof runRecord.conversation === "function") {
16161
+ const originalConversation = runRecord.conversation.bind(runRecord);
16162
+ Object.defineProperty(runRecord, "conversation", {
16163
+ configurable: true,
16164
+ async value() {
16165
+ try {
16166
+ const conversation = await originalConversation();
16167
+ await handleConversation(state, conversation);
16168
+ await finalizeCursorRun(state);
16169
+ return conversation;
16170
+ } catch (error) {
16171
+ await finalizeCursorRun(state, { error });
16172
+ throw error;
16173
+ }
16174
+ },
16175
+ writable: true
16176
+ });
16177
+ }
16178
+ } catch {
16179
+ void finalizeCursorRun(state, { output: run });
16180
+ }
16181
+ }
16182
+ async function* patchCursorStream(stream, state) {
16183
+ try {
16184
+ for await (const message of stream) {
16185
+ try {
16186
+ await handleStreamMessage2(state, message);
16187
+ } catch (error) {
16188
+ logInstrumentationError("Cursor SDK stream", error);
16189
+ }
16190
+ yield message;
16191
+ }
16192
+ await finalizeCursorRun(state);
16193
+ } catch (error) {
16194
+ await finalizeCursorRun(state, { error });
16195
+ throw error;
16196
+ }
16197
+ }
16198
+ async function handleInteractionUpdate(state, update) {
16199
+ switch (update.type) {
16200
+ case "text-delta":
16201
+ if (typeof update.text === "string") {
16202
+ state.deltaText.push(update.text);
16203
+ }
16204
+ return;
16205
+ case "token-delta":
16206
+ if (typeof update.tokens === "number") {
16207
+ state.metrics["cursor_sdk.delta_tokens"] = (state.metrics["cursor_sdk.delta_tokens"] ?? 0) + update.tokens;
16208
+ }
16209
+ return;
16210
+ case "tool-call-started":
16211
+ case "partial-tool-call":
16212
+ case "tool-call-completed":
16213
+ await handleToolUpdate(
16214
+ state,
16215
+ update
16216
+ );
16217
+ return;
16218
+ case "turn-ended":
16219
+ addUsageMetrics(
16220
+ state.metrics,
16221
+ update.usage
16222
+ );
16223
+ return;
16224
+ case "summary":
16225
+ if (typeof update.summary === "string") {
16226
+ state.taskText.push(update.summary);
16227
+ }
16228
+ return;
16229
+ case "step-completed":
16230
+ if (typeof update.stepDurationMs === "number") {
16231
+ state.metrics["cursor_sdk.step_duration_ms"] = (state.metrics["cursor_sdk.step_duration_ms"] ?? 0) + update.stepDurationMs;
16232
+ }
16233
+ state.metrics["cursor_sdk.steps"] = (state.metrics["cursor_sdk.steps"] ?? 0) + 1;
16234
+ return;
16235
+ default:
16236
+ return;
16237
+ }
16238
+ }
16239
+ async function handleToolUpdate(state, update) {
16240
+ const callId = update.callId;
16241
+ if (!callId) {
16242
+ return;
16243
+ }
16244
+ const toolCall = update.toolCall;
16245
+ const name = extractToolName(toolCall);
16246
+ const args = extractToolArgs(toolCall);
16247
+ const result = extractToolResult(toolCall);
16248
+ if (update.type === "tool-call-started" || update.type === "partial-tool-call") {
16249
+ if (!state.activeToolSpans.has(callId)) {
16250
+ state.activeToolSpans.set(
16251
+ callId,
16252
+ await startToolSpan(state, {
16253
+ args,
16254
+ callId,
16255
+ name,
16256
+ status: "running",
16257
+ toolCall
16258
+ })
16259
+ );
16260
+ }
16261
+ return;
16262
+ }
16263
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
16264
+ args,
16265
+ callId,
16266
+ name,
16267
+ status: "completed",
16268
+ toolCall
16269
+ });
16270
+ finishToolSpan(toolState, {
16271
+ error: toolCall?.status === "error" ? stringifyUnknown(result) : void 0,
16272
+ metadata: {
16273
+ "cursor_sdk.tool.status": toolCall?.status ?? "completed"
16274
+ },
16275
+ output: result
16276
+ });
16277
+ state.activeToolSpans.delete(callId);
16278
+ }
16279
+ async function handleStreamMessage2(state, message) {
16280
+ state.streamMessages.push(message);
16281
+ if (message.type === "system") {
16282
+ const systemMessage = message;
16283
+ state.metadata = {
16284
+ ...state.metadata,
16285
+ ...extractModelMetadata(systemMessage.model),
16286
+ ...systemMessage.agent_id ? { "cursor_sdk.agent_id": systemMessage.agent_id } : {},
16287
+ ...systemMessage.run_id ? { "cursor_sdk.run_id": systemMessage.run_id } : {},
16288
+ ...systemMessage.tools ? { "cursor_sdk.tools": systemMessage.tools } : {}
16289
+ };
16290
+ return;
16291
+ }
16292
+ if (message.type === "assistant") {
16293
+ const assistantMessage = message;
16294
+ for (const block of assistantMessage.message?.content ?? []) {
16295
+ if (block?.type === "text" && typeof block.text === "string") {
16296
+ state.streamText.push(block.text);
16297
+ } else if (block?.type === "tool_use" && block.id) {
16298
+ state.activeToolSpans.set(
16299
+ block.id,
16300
+ await startToolSpan(state, {
16301
+ args: block.input,
16302
+ callId: block.id,
16303
+ name: block.name,
16304
+ status: "running"
16305
+ })
16306
+ );
16307
+ }
16308
+ }
16309
+ return;
16310
+ }
16311
+ if (message.type === "tool_call") {
16312
+ await handleToolMessage(
16313
+ state,
16314
+ message
16315
+ );
16316
+ return;
16317
+ }
16318
+ if (message.type === "task" && typeof message.text === "string") {
16319
+ state.taskText.push(message.text);
16320
+ return;
16321
+ }
16322
+ if (message.type === "status" && message.status) {
16323
+ state.metadata["cursor_sdk.status"] = message.status;
16324
+ }
16325
+ }
16326
+ async function handleToolMessage(state, message) {
16327
+ const callId = message.call_id;
16328
+ if (!callId) {
16329
+ return;
16330
+ }
16331
+ if (message.status === "running") {
16332
+ if (!state.activeToolSpans.has(callId)) {
16333
+ state.activeToolSpans.set(
16334
+ callId,
16335
+ await startToolSpan(state, {
16336
+ args: message.args,
16337
+ callId,
16338
+ name: message.name,
16339
+ status: message.status,
16340
+ truncated: message.truncated
16341
+ })
16342
+ );
16343
+ }
16344
+ return;
16345
+ }
16346
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
16347
+ args: message.args,
16348
+ callId,
16349
+ name: message.name,
16350
+ status: message.status,
16351
+ truncated: message.truncated
16352
+ });
16353
+ finishToolSpan(toolState, {
16354
+ error: message.status === "error" ? stringifyUnknown(message.result) : void 0,
16355
+ metadata: {
16356
+ "cursor_sdk.tool.status": message.status
16357
+ },
16358
+ output: message.result
16359
+ });
16360
+ state.activeToolSpans.delete(callId);
16361
+ }
16362
+ async function handleConversation(state, turns) {
16363
+ state.conversationOutput = turns;
16364
+ for (const turn of turns) {
16365
+ if (turn.type === "agentConversationTurn") {
16366
+ for (const step of turn.turn?.steps ?? []) {
16367
+ await handleConversationStep(state, step);
16368
+ }
16369
+ } else if (turn.type === "shellConversationTurn") {
16370
+ const command = turn.turn?.shellCommand?.command;
16371
+ if (command) {
16372
+ const callId = `shell:${state.activeToolSpans.size}:${command}`;
16373
+ const toolState = await startToolSpan(state, {
16374
+ args: turn.turn?.shellCommand,
16375
+ callId,
16376
+ name: "shell",
16377
+ status: "completed"
16378
+ });
16379
+ finishToolSpan(toolState, {
16380
+ metadata: { "cursor_sdk.tool.status": "completed" },
16381
+ output: turn.turn?.shellOutput
16382
+ });
16383
+ }
16384
+ }
16385
+ }
16386
+ }
16387
+ async function handleConversationStep(state, step) {
16388
+ if (step.type === "assistantMessage" && typeof step.message?.text === "string") {
16389
+ state.conversationText.push(step.message.text);
16390
+ return;
16391
+ }
16392
+ if (step.type !== "toolCall") {
16393
+ return;
16394
+ }
16395
+ const toolCall = step.message;
16396
+ const callId = typeof toolCall?.callId === "string" ? toolCall.callId : `conversation-tool:${state.activeToolSpans.size}`;
16397
+ const toolState = await startToolSpan(state, {
16398
+ args: extractToolArgs(toolCall),
16399
+ callId,
16400
+ name: extractToolName(toolCall),
16401
+ status: toolCall?.status,
16402
+ toolCall
16403
+ });
16404
+ finishToolSpan(toolState, {
16405
+ error: toolCall?.status === "error" ? stringifyUnknown(toolCall.result) : void 0,
16406
+ metadata: {
16407
+ "cursor_sdk.tool.status": toolCall?.status ?? "completed"
16408
+ },
16409
+ output: extractToolResult(toolCall)
16410
+ });
16411
+ }
16412
+ function handleStepUpdate(state, step) {
16413
+ state.metrics["cursor_sdk.steps"] = (state.metrics["cursor_sdk.steps"] ?? 0) + 1;
16414
+ if (step.type) {
16415
+ const stepTypes = state.metadata["cursor_sdk.step_types"];
16416
+ if (Array.isArray(stepTypes)) {
16417
+ if (!stepTypes.includes(step.type)) {
16418
+ stepTypes.push(step.type);
16419
+ }
16420
+ } else {
16421
+ state.metadata["cursor_sdk.step_types"] = [step.type];
16422
+ }
16423
+ }
16424
+ if (step.type === "assistantMessage" && typeof step.message?.text === "string") {
16425
+ state.stepText.push(step.message.text);
16426
+ }
16427
+ }
16428
+ async function startToolSpan(state, args) {
16429
+ const name = args.name || "unknown";
16430
+ const metadata = {
16431
+ "cursor_sdk.tool.status": args.status,
16432
+ "gen_ai.tool.call.id": args.callId,
16433
+ "gen_ai.tool.name": name
16434
+ };
16435
+ if (args.truncated?.args !== void 0) {
16436
+ metadata["cursor_sdk.tool.args_truncated"] = args.truncated.args;
16437
+ }
16438
+ if (args.truncated?.result !== void 0) {
16439
+ metadata["cursor_sdk.tool.result_truncated"] = args.truncated.result;
16440
+ }
16441
+ const span = startSpan({
16442
+ event: {
16443
+ input: args.args,
16444
+ metadata
16445
+ },
16446
+ name: `tool: ${name}`,
16447
+ parent: await state.span.export(),
16448
+ spanAttributes: { type: "tool" /* TOOL */ }
16449
+ });
16450
+ let subAgentSpan;
16451
+ if (isSubAgentToolName(name)) {
16452
+ subAgentSpan = startSpan({
16453
+ event: {
16454
+ input: args.args,
16455
+ metadata: {
16456
+ "cursor_sdk.subagent.tool_call_id": args.callId,
16457
+ "gen_ai.tool.name": name
16458
+ }
16459
+ },
16460
+ name: formatSubAgentSpanName2(args.toolCall, args.args),
16461
+ parent: await span.export(),
16462
+ spanAttributes: { type: "task" /* TASK */ }
16463
+ });
16464
+ }
16465
+ return { span, subAgentSpan };
16466
+ }
16467
+ function finishToolSpan(toolState, result) {
16468
+ try {
16469
+ if (result.error) {
16470
+ safeLog(toolState.span, {
16471
+ error: result.error,
16472
+ metadata: result.metadata,
16473
+ output: result.output
16474
+ });
16475
+ if (toolState.subAgentSpan) {
16476
+ safeLog(toolState.subAgentSpan, {
16477
+ error: result.error,
16478
+ metadata: result.metadata,
16479
+ output: result.output
16480
+ });
16481
+ }
16482
+ } else {
16483
+ safeLog(toolState.span, {
16484
+ metadata: result.metadata,
16485
+ output: result.output
16486
+ });
16487
+ if (toolState.subAgentSpan) {
16488
+ safeLog(toolState.subAgentSpan, {
16489
+ metadata: result.metadata,
16490
+ output: result.output
16491
+ });
16492
+ }
16493
+ }
16494
+ } finally {
16495
+ toolState.subAgentSpan?.end();
16496
+ toolState.span.end();
16497
+ }
16498
+ }
16499
+ async function finalizeCursorRun(state, params = {}) {
16500
+ if (state.finalized) {
16501
+ return;
16502
+ }
16503
+ state.finalized = true;
16504
+ const error = params.error;
16505
+ const result = params.result ?? state.lastResult;
16506
+ 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);
16507
+ try {
16508
+ const metadata = {
16509
+ ...state.metadata,
16510
+ ...state.run ? extractRunMetadata(state.run) : {},
16511
+ ...result ? extractRunResultMetadata(result) : {}
16512
+ };
16513
+ if (error) {
16514
+ safeLog(state.span, {
16515
+ error: error instanceof Error ? error.message : String(error),
16516
+ metadata,
16517
+ metrics: {
16518
+ ...cleanMetrics(state.metrics),
16519
+ ...buildDurationMetrics(state.startTime)
16520
+ },
16521
+ output
16522
+ });
16523
+ } else {
16524
+ safeLog(state.span, {
16525
+ metadata,
16526
+ metrics: {
16527
+ ...cleanMetrics(state.metrics),
16528
+ ...buildDurationMetrics(state.startTime)
16529
+ },
16530
+ output
16531
+ });
16532
+ }
16533
+ } finally {
16534
+ endOpenToolSpans(state);
16535
+ state.span.end();
16536
+ }
16537
+ }
16538
+ function endOpenToolSpans(state, error) {
16539
+ for (const [, toolState] of state.activeToolSpans) {
16540
+ finishToolSpan(toolState, { error });
16541
+ }
16542
+ state.activeToolSpans.clear();
16543
+ }
16544
+ function sanitizeUserMessage(message) {
16545
+ if (typeof message === "string" || message === void 0) {
16546
+ return message;
16547
+ }
16548
+ return {
16549
+ ...message,
16550
+ images: message.images?.map((image) => {
16551
+ const imageRecord = image;
16552
+ return {
16553
+ ...typeof imageRecord.url === "string" ? { url: imageRecord.url } : {},
16554
+ ...typeof imageRecord.mimeType === "string" ? { mimeType: imageRecord.mimeType } : {},
16555
+ ...image.dimension ? { dimension: image.dimension } : {},
16556
+ hasData: typeof imageRecord.data === "string"
16557
+ };
16558
+ })
16559
+ };
16560
+ }
16561
+ function extractAgentOptionsMetadata(options) {
16562
+ if (!options) {
16563
+ return {};
16564
+ }
16565
+ return {
16566
+ ...extractModelMetadata(options.model),
16567
+ ...options.agentId ? { "cursor_sdk.agent_id": options.agentId } : {},
16568
+ ...options.name ? { "cursor_sdk.agent_name": options.name } : {},
16569
+ ...options.local ? {
16570
+ "cursor_sdk.runtime": "local",
16571
+ "cursor_sdk.local.cwd": Array.isArray(options.local.cwd) ? options.local.cwd.join(",") : options.local.cwd
16572
+ } : {},
16573
+ ...options.cloud ? {
16574
+ "cursor_sdk.runtime": "cloud",
16575
+ "cursor_sdk.cloud.auto_create_pr": options.cloud.autoCreatePR,
16576
+ "cursor_sdk.cloud.env_type": options.cloud.env?.type,
16577
+ "cursor_sdk.cloud.env_name": options.cloud.env?.name,
16578
+ "cursor_sdk.cloud.repos": options.cloud.repos?.map((repo) => repo.url).filter((url) => typeof url === "string")
16579
+ } : {}
16580
+ };
16581
+ }
16582
+ function extractSendMetadata(options) {
16583
+ if (!options) {
16584
+ return {};
16585
+ }
16586
+ return {
16587
+ ...extractModelMetadata(options.model),
16588
+ ...options.local?.force !== void 0 ? { "cursor_sdk.local.force": options.local.force } : {}
16589
+ };
16590
+ }
16591
+ function extractAgentMetadata(agent) {
16592
+ return {
16593
+ ...agent.agentId ? { "cursor_sdk.agent_id": agent.agentId } : {},
16594
+ ...extractModelMetadata(agent.model)
16595
+ };
16596
+ }
16597
+ function extractRunMetadata(run) {
16598
+ if (!run) {
16599
+ return {};
16600
+ }
16601
+ return {
16602
+ ...run.id ? { "cursor_sdk.run_id": run.id } : {},
16603
+ ...run.agentId ? { "cursor_sdk.agent_id": run.agentId } : {},
16604
+ ...run.status ? { "cursor_sdk.status": run.status } : {},
16605
+ ...run.durationMs !== void 0 ? { "cursor_sdk.duration_ms": run.durationMs } : {},
16606
+ ...extractModelMetadata(run.model),
16607
+ ...extractGitMetadata(run.git)
16608
+ };
16609
+ }
16610
+ function extractRunResultMetadata(result) {
16611
+ if (!result) {
16612
+ return {};
16613
+ }
16614
+ return {
16615
+ ...result.id ? { "cursor_sdk.run_id": result.id } : {},
16616
+ ...result.status ? { "cursor_sdk.status": result.status } : {},
16617
+ ...result.durationMs !== void 0 ? { "cursor_sdk.duration_ms": result.durationMs } : {},
16618
+ ...extractModelMetadata(result.model),
16619
+ ...extractGitMetadata(result.git)
16620
+ };
16621
+ }
16622
+ function extractGitMetadata(git) {
16623
+ const branches = git?.branches;
16624
+ if (!branches || branches.length === 0) {
16625
+ return {};
16626
+ }
16627
+ return {
16628
+ "cursor_sdk.git.branches": branches.map((branch) => ({
16629
+ branch: branch.branch,
16630
+ prUrl: branch.prUrl,
16631
+ repoUrl: branch.repoUrl
16632
+ }))
16633
+ };
16634
+ }
16635
+ function extractModelMetadata(model) {
16636
+ if (!model?.id) {
16637
+ return {};
16638
+ }
16639
+ return {
16640
+ model: model.id,
16641
+ "cursor_sdk.model": model.id,
16642
+ ...model.params ? { "cursor_sdk.model.params": model.params } : {}
16643
+ };
16644
+ }
16645
+ function addUsageMetrics(metrics, usage) {
16646
+ if (!usage) {
16647
+ return;
16648
+ }
16649
+ if (usage.inputTokens !== void 0) {
16650
+ metrics.prompt_tokens = (metrics.prompt_tokens ?? 0) + usage.inputTokens;
16651
+ }
16652
+ if (usage.outputTokens !== void 0) {
16653
+ metrics.completion_tokens = (metrics.completion_tokens ?? 0) + usage.outputTokens;
16654
+ }
16655
+ if (usage.cacheReadTokens !== void 0) {
16656
+ metrics.prompt_cached_tokens = (metrics.prompt_cached_tokens ?? 0) + usage.cacheReadTokens;
16657
+ }
16658
+ if (usage.cacheWriteTokens !== void 0) {
16659
+ metrics.prompt_cache_creation_tokens = (metrics.prompt_cache_creation_tokens ?? 0) + usage.cacheWriteTokens;
16660
+ }
16661
+ metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0) + (metrics.prompt_cached_tokens ?? 0) + (metrics.prompt_cache_creation_tokens ?? 0);
16662
+ }
16663
+ function buildDurationMetrics(startTime) {
16664
+ const end = getCurrentUnixTimestamp();
16665
+ return {
16666
+ duration: end - startTime,
16667
+ end,
16668
+ start: startTime
16669
+ };
16670
+ }
16671
+ function extractToolName(toolCall) {
16672
+ if (!toolCall) {
16673
+ return "unknown";
16674
+ }
16675
+ if (typeof toolCall.name === "string") {
16676
+ return toolCall.name;
16677
+ }
16678
+ if (typeof toolCall.type === "string") {
16679
+ return toolCall.type;
16680
+ }
16681
+ return "unknown";
16682
+ }
16683
+ function extractToolArgs(toolCall) {
16684
+ return toolCall && "args" in toolCall ? toolCall.args : void 0;
16685
+ }
16686
+ function extractToolResult(toolCall) {
16687
+ return toolCall && "result" in toolCall ? toolCall.result : void 0;
16688
+ }
16689
+ function isSubAgentToolName(name) {
16690
+ return name === "Agent" || name === "Task" || name === "task";
16691
+ }
16692
+ function formatSubAgentSpanName2(toolCall, args) {
16693
+ const details = toolCall ?? args;
16694
+ const description = getString(details, "description") ?? getString(details, "subagent_type") ?? getString(details, "type") ?? getString(details, "name");
16695
+ return description ? `Agent: ${description}` : "Agent: sub-agent";
16696
+ }
16697
+ function getString(obj, key) {
16698
+ const value = obj?.[key];
16699
+ return typeof value === "string" ? value : void 0;
16700
+ }
16701
+ function stringifyUnknown(value) {
16702
+ if (value instanceof Error) {
16703
+ return value.message;
16704
+ }
16705
+ if (typeof value === "string") {
16706
+ return value;
16707
+ }
16708
+ try {
16709
+ return JSON.stringify(value);
16710
+ } catch {
16711
+ return String(value);
16712
+ }
16713
+ }
16714
+ function safeLog(span, event) {
16715
+ try {
16716
+ span.log(event);
16717
+ } catch (error) {
16718
+ logInstrumentationError("Cursor SDK span log", error);
16719
+ }
16720
+ }
16721
+ function logInstrumentationError(context, error) {
16722
+ debugLogger.error(`Error processing ${context}:`, error);
16723
+ }
16724
+ function cleanMetrics(metrics) {
16725
+ const cleaned = {};
16726
+ for (const [key, value] of Object.entries(metrics)) {
16727
+ if (value !== void 0 && Number.isFinite(value)) {
16728
+ cleaned[key] = value;
16729
+ }
16730
+ }
16731
+ return cleaned;
16732
+ }
16733
+
16734
+ // src/instrumentation/plugins/google-genai-channels.ts
16735
+ var googleGenAIChannels = defineChannels("@google/genai", {
16736
+ generateContent: channel({
16737
+ channelName: "models.generateContent",
16738
+ kind: "async"
16739
+ }),
16740
+ generateContentStream: channel({
16741
+ channelName: "models.generateContentStream",
16742
+ kind: "async"
16743
+ }),
16744
+ embedContent: channel({
16745
+ channelName: "models.embedContent",
16746
+ kind: "async"
16747
+ })
16748
+ });
16749
+
16750
+ // src/instrumentation/plugins/google-genai-plugin.ts
16751
+ var GOOGLE_GENAI_INTERNAL_CONTEXT = {
16752
+ caller_filename: "<node-internal>",
16753
+ caller_functionname: "<node-internal>",
16754
+ caller_lineno: 0
16755
+ };
16756
+ function createWrapperParityEvent(args) {
16757
+ return {
16758
+ context: GOOGLE_GENAI_INTERNAL_CONTEXT,
16759
+ input: args.input,
16760
+ metadata: args.metadata
16761
+ };
16762
+ }
16763
+ var GoogleGenAIPlugin = class extends BasePlugin {
16764
+ onEnable() {
16765
+ this.subscribeToGoogleGenAIChannels();
16766
+ }
16767
+ onDisable() {
16768
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
16769
+ }
16770
+ subscribeToGoogleGenAIChannels() {
16771
+ this.subscribeToGenerateContentChannel();
16772
+ this.subscribeToGenerateContentStreamChannel();
16773
+ this.subscribeToEmbedContentChannel();
16774
+ }
16775
+ subscribeToGenerateContentChannel() {
16776
+ const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
16777
+ const states = /* @__PURE__ */ new WeakMap();
16778
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
16779
+ tracingChannel2,
16780
+ states,
16781
+ (event) => {
16782
+ const params = event.arguments[0];
16783
+ const input = serializeGenerateContentInput(params);
16784
+ const metadata = extractGenerateContentMetadata(params);
16785
+ const span = startSpan({
16786
+ name: "generate_content",
16787
+ spanAttributes: {
16788
+ type: "llm" /* LLM */
16789
+ },
15508
16790
  event: createWrapperParityEvent({ input, metadata })
15509
16791
  });
15510
16792
  return {
@@ -15541,7 +16823,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
15541
16823
  const responseMetadata = extractResponseMetadata(event.result);
15542
16824
  spanState.span.log({
15543
16825
  ...responseMetadata ? { metadata: responseMetadata } : {},
15544
- metrics: cleanMetrics(
16826
+ metrics: cleanMetrics2(
15545
16827
  extractGenerateContentMetrics(
15546
16828
  event.result,
15547
16829
  spanState.startTime
@@ -15642,7 +16924,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
15642
16924
  const output = summarizeEmbedContentOutput(event.result);
15643
16925
  spanState.span.log({
15644
16926
  ...output ? { output } : {},
15645
- metrics: cleanMetrics(
16927
+ metrics: cleanMetrics2(
15646
16928
  extractEmbedContentMetrics(event.result, spanState.startTime)
15647
16929
  )
15648
16930
  });
@@ -15739,7 +17021,7 @@ function patchGoogleGenAIStreamingResult(args) {
15739
17021
  );
15740
17022
  span.log({
15741
17023
  ...responseMetadata ? { metadata: responseMetadata } : {},
15742
- metrics: cleanMetrics(metricsWithoutEnd),
17024
+ metrics: cleanMetrics2(metricsWithoutEnd),
15743
17025
  output: options.result.aggregated
15744
17026
  });
15745
17027
  span.end(typeof end === "number" ? { endTime: end } : void 0);
@@ -16164,7 +17446,7 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
16164
17446
  }
16165
17447
  return { aggregated, metrics };
16166
17448
  }
16167
- function cleanMetrics(metrics) {
17449
+ function cleanMetrics2(metrics) {
16168
17450
  const cleaned = {};
16169
17451
  for (const [key, value] of Object.entries(metrics)) {
16170
17452
  if (value !== null && value !== void 0) {
@@ -16248,6 +17530,8 @@ var REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
16248
17530
  "stop",
16249
17531
  "stream",
16250
17532
  "temperature",
17533
+ "tool_choice",
17534
+ "tools",
16251
17535
  "top_p"
16252
17536
  ]);
16253
17537
  var RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
@@ -16510,7 +17794,10 @@ function aggregateChatCompletionChunks2(chunks) {
16510
17794
  for (const chunk of chunks) {
16511
17795
  for (const choice of chunk.choices ?? []) {
16512
17796
  const index = typeof choice.index === "number" ? choice.index : 0;
16513
- const existing = aggregatedChoices.get(index) ?? { content: "" };
17797
+ const existing = aggregatedChoices.get(index) ?? {
17798
+ content: "",
17799
+ toolCallsByIndex: /* @__PURE__ */ new Map()
17800
+ };
16514
17801
  const delta = isObject(choice.delta) ? choice.delta : void 0;
16515
17802
  const message = isObject(choice.message) ? choice.message : void 0;
16516
17803
  if (typeof delta?.content === "string") {
@@ -16526,6 +17813,10 @@ function aggregateChatCompletionChunks2(chunks) {
16526
17813
  if (choice.finish_reason !== void 0) {
16527
17814
  existing.finish_reason = choice.finish_reason;
16528
17815
  }
17816
+ const toolCallDeltas = getChatToolCallDeltas(delta) ?? getChatToolCallDeltas(message);
17817
+ if (toolCallDeltas) {
17818
+ mergeChatToolCallDeltas(existing.toolCallsByIndex, toolCallDeltas);
17819
+ }
16529
17820
  aggregatedChoices.set(index, existing);
16530
17821
  }
16531
17822
  }
@@ -16534,12 +17825,72 @@ function aggregateChatCompletionChunks2(chunks) {
16534
17825
  index,
16535
17826
  message: {
16536
17827
  content: choice.content,
16537
- role: choice.role ?? "assistant"
17828
+ role: choice.role ?? "assistant",
17829
+ ...choice.toolCallsByIndex.size > 0 ? {
17830
+ tool_calls: [...choice.toolCallsByIndex.entries()].sort(([leftIndex], [rightIndex]) => leftIndex - rightIndex).map(([, toolCall]) => toolCall)
17831
+ } : {}
16538
17832
  },
16539
17833
  ...choice.finish_reason !== void 0 ? { finish_reason: choice.finish_reason } : {}
16540
17834
  }))
16541
17835
  };
16542
17836
  }
17837
+ function getChatToolCallDeltas(value) {
17838
+ if (!Array.isArray(value?.tool_calls)) {
17839
+ return void 0;
17840
+ }
17841
+ const toolCalls = value.tool_calls.filter((toolCall) => isObject(toolCall));
17842
+ return toolCalls.length > 0 ? toolCalls : void 0;
17843
+ }
17844
+ function mergeChatToolCallDeltas(toolCallsByIndex, toolCallDeltas) {
17845
+ for (const toolDelta of toolCallDeltas) {
17846
+ const toolIndex = typeof toolDelta.index === "number" && toolDelta.index >= 0 ? toolDelta.index : 0;
17847
+ const existing = toolCallsByIndex.get(toolIndex);
17848
+ if (!existing) {
17849
+ toolCallsByIndex.set(toolIndex, createChatToolCall(toolDelta));
17850
+ continue;
17851
+ }
17852
+ mergeChatToolCall(existing, toolDelta);
17853
+ }
17854
+ }
17855
+ function createChatToolCall(toolDelta) {
17856
+ const toolFunction = isObject(toolDelta.function) ? toolDelta.function : {};
17857
+ const toolCallFunction = {
17858
+ arguments: typeof toolFunction.arguments === "string" ? toolFunction.arguments : ""
17859
+ };
17860
+ if (typeof toolFunction.name === "string") {
17861
+ toolCallFunction.name = toolFunction.name;
17862
+ }
17863
+ const toolCall = {
17864
+ function: toolCallFunction
17865
+ };
17866
+ if (typeof toolDelta.id === "string") {
17867
+ toolCall.id = toolDelta.id;
17868
+ }
17869
+ if (typeof toolDelta.type === "string") {
17870
+ toolCall.type = toolDelta.type;
17871
+ }
17872
+ return toolCall;
17873
+ }
17874
+ function mergeChatToolCall(existing, toolDelta) {
17875
+ const currentFunction = isObject(existing.function) ? existing.function : {};
17876
+ const deltaFunction = isObject(toolDelta.function) ? toolDelta.function : {};
17877
+ const currentArguments = typeof currentFunction.arguments === "string" ? currentFunction.arguments : "";
17878
+ const deltaArguments = typeof deltaFunction.arguments === "string" ? deltaFunction.arguments : "";
17879
+ if (typeof toolDelta.id === "string" && typeof existing.id !== "string") {
17880
+ existing.id = toolDelta.id;
17881
+ }
17882
+ if (typeof toolDelta.type === "string" && typeof existing.type !== "string") {
17883
+ existing.type = toolDelta.type;
17884
+ }
17885
+ const nextFunction = {
17886
+ ...currentFunction,
17887
+ arguments: `${currentArguments}${deltaArguments}`
17888
+ };
17889
+ if (typeof deltaFunction.name === "string" && typeof currentFunction.name !== "string") {
17890
+ nextFunction.name = deltaFunction.name;
17891
+ }
17892
+ existing.function = nextFunction;
17893
+ }
16543
17894
  function aggregateTextGenerationStreamChunks(chunks) {
16544
17895
  if (chunks.length === 0) {
16545
17896
  return void 0;
@@ -18584,6 +19935,8 @@ var MISTRAL_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
18584
19935
  "presence_penalty",
18585
19936
  "randomSeed",
18586
19937
  "random_seed",
19938
+ "reasoningEffort",
19939
+ "reasoning_effort",
18587
19940
  "responseFormat",
18588
19941
  "response_format",
18589
19942
  "safePrompt",
@@ -18707,22 +20060,114 @@ function extractMistralStreamingMetrics(result, startTime) {
18707
20060
  if (startTime) {
18708
20061
  metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
18709
20062
  }
18710
- return metrics;
20063
+ return metrics;
20064
+ }
20065
+ function extractDeltaText(content) {
20066
+ if (typeof content === "string") {
20067
+ return content;
20068
+ }
20069
+ if (!Array.isArray(content)) {
20070
+ return void 0;
20071
+ }
20072
+ const textParts = content.map((part) => {
20073
+ if (!isObject(part) || part.type !== "text") {
20074
+ return "";
20075
+ }
20076
+ return typeof part.text === "string" ? part.text : "";
20077
+ }).filter((part) => part.length > 0);
20078
+ return textParts.length > 0 ? textParts.join("") : void 0;
20079
+ }
20080
+ function normalizeMistralTextContentPart(part) {
20081
+ if (!isObject(part) || part.type !== "text" || typeof part.text !== "string") {
20082
+ return void 0;
20083
+ }
20084
+ return {
20085
+ type: "text",
20086
+ text: part.text
20087
+ };
20088
+ }
20089
+ function normalizeMistralThinkingContentPart(part) {
20090
+ if (!isObject(part) || part.type !== "thinking") {
20091
+ return void 0;
20092
+ }
20093
+ const thinking = Array.isArray(part.thinking) ? part.thinking.map((thinkingPart) => normalizeMistralTextContentPart(thinkingPart)).filter(
20094
+ (thinkingPart) => thinkingPart !== void 0 && typeof thinkingPart.text === "string"
20095
+ ) : [];
20096
+ return {
20097
+ type: "thinking",
20098
+ thinking
20099
+ };
20100
+ }
20101
+ function normalizeMistralContentParts(content) {
20102
+ if (!Array.isArray(content)) {
20103
+ return [];
20104
+ }
20105
+ return content.map((part) => {
20106
+ return normalizeMistralTextContentPart(part) || normalizeMistralThinkingContentPart(part);
20107
+ }).filter((part) => part !== void 0);
20108
+ }
20109
+ function mergeMistralTextSegments(left, right) {
20110
+ const merged = left.map((part) => ({ ...part }));
20111
+ for (const part of right) {
20112
+ const lastPart = merged[merged.length - 1];
20113
+ if (lastPart && lastPart.type === "text" && typeof lastPart.text === "string" && typeof part.text === "string") {
20114
+ lastPart.text += part.text;
20115
+ continue;
20116
+ }
20117
+ merged.push({ ...part });
20118
+ }
20119
+ return merged;
20120
+ }
20121
+ function mergeMistralContentParts(left, right) {
20122
+ const merged = [...(left || []).map((part) => structuredClone(part))];
20123
+ for (const part of right) {
20124
+ const lastPart = merged[merged.length - 1];
20125
+ if (part.type === "text" && lastPart?.type === "text" && typeof lastPart.text === "string" && typeof part.text === "string") {
20126
+ lastPart.text += part.text;
20127
+ continue;
20128
+ }
20129
+ if (part.type === "thinking" && lastPart?.type === "thinking" && Array.isArray(lastPart.thinking) && Array.isArray(part.thinking)) {
20130
+ lastPart.thinking = mergeMistralTextSegments(
20131
+ lastPart.thinking,
20132
+ part.thinking
20133
+ );
20134
+ continue;
20135
+ }
20136
+ merged.push(structuredClone(part));
20137
+ }
20138
+ return merged;
18711
20139
  }
18712
- function extractDeltaText(content) {
20140
+ function appendMistralContent(accumulator, content) {
18713
20141
  if (typeof content === "string") {
18714
- return content;
20142
+ if (accumulator.contentParts) {
20143
+ accumulator.contentParts = mergeMistralContentParts(
20144
+ accumulator.contentParts,
20145
+ [{ type: "text", text: content }]
20146
+ );
20147
+ return;
20148
+ }
20149
+ accumulator.content = `${accumulator.content || ""}${content}`;
20150
+ return;
18715
20151
  }
18716
- if (!Array.isArray(content)) {
18717
- return void 0;
20152
+ const normalizedContentParts = normalizeMistralContentParts(content);
20153
+ if (normalizedContentParts.length === 0) {
20154
+ return;
18718
20155
  }
18719
- const textParts = content.map((part) => {
18720
- if (!isObject(part) || part.type !== "text") {
18721
- return "";
20156
+ const hasStructuredContent = normalizedContentParts.some(
20157
+ (part) => part.type !== "text"
20158
+ );
20159
+ if (!accumulator.contentParts && !hasStructuredContent) {
20160
+ const text = extractDeltaText(content);
20161
+ if (text) {
20162
+ accumulator.content = `${accumulator.content || ""}${text}`;
18722
20163
  }
18723
- return typeof part.text === "string" ? part.text : "";
18724
- }).filter((part) => part.length > 0);
18725
- return textParts.length > 0 ? textParts.join("") : void 0;
20164
+ return;
20165
+ }
20166
+ accumulator.contentParts = mergeMistralContentParts(
20167
+ accumulator.contentParts || (accumulator.content ? [{ type: "text", text: accumulator.content }] : []),
20168
+ normalizedContentParts
20169
+ );
20170
+ delete accumulator.content;
18726
20171
  }
18727
20172
  function getDeltaToolCalls(delta) {
18728
20173
  const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
@@ -18892,10 +20337,7 @@ function aggregateMistralStreamChunks(chunks) {
18892
20337
  if (!accumulator.role && typeof delta.role === "string") {
18893
20338
  accumulator.role = delta.role;
18894
20339
  }
18895
- const deltaText = extractDeltaText(delta.content);
18896
- if (deltaText) {
18897
- accumulator.content = `${accumulator.content || ""}${deltaText}`;
18898
- }
20340
+ appendMistralContent(accumulator, delta.content);
18899
20341
  accumulator.toolCalls = mergeToolCallDeltas(
18900
20342
  accumulator.toolCalls,
18901
20343
  getDeltaToolCalls(delta)
@@ -18913,7 +20355,7 @@ function aggregateMistralStreamChunks(chunks) {
18913
20355
  index: choice.index,
18914
20356
  message: {
18915
20357
  ...choice.role ? { role: choice.role } : {},
18916
- content: choice.content ?? null,
20358
+ content: choice.contentParts ?? choice.content ?? null,
18917
20359
  ...choice.toolCalls ? { toolCalls: choice.toolCalls } : {}
18918
20360
  },
18919
20361
  ...choice.finishReason !== void 0 ? { finishReason: choice.finishReason } : {}
@@ -19152,7 +20594,7 @@ var GoogleADKPlugin = class extends BasePlugin {
19152
20594
  start: (event) => {
19153
20595
  const req = event.arguments[0] ?? {};
19154
20596
  const tool = event.self;
19155
- const toolName = extractToolName(req, tool);
20597
+ const toolName = extractToolName2(req, tool);
19156
20598
  const parentSpan = findToolParentSpan(
19157
20599
  req,
19158
20600
  this.activeAgentSpans,
@@ -19191,7 +20633,7 @@ var GoogleADKPlugin = class extends BasePlugin {
19191
20633
  metrics.duration = end - state.startTime;
19192
20634
  state.span.log({
19193
20635
  output: event.result,
19194
- metrics: cleanMetrics2(metrics)
20636
+ metrics: cleanMetrics3(metrics)
19195
20637
  });
19196
20638
  } finally {
19197
20639
  state.span.end();
@@ -19410,7 +20852,7 @@ function extractToolCallId(req) {
19410
20852
  const toolContext = req.toolContext;
19411
20853
  return toolContext?.functionCallId;
19412
20854
  }
19413
- function extractToolName(req, tool) {
20855
+ function extractToolName2(req, tool) {
19414
20856
  if (typeof tool?.name === "string" && tool.name.length > 0) {
19415
20857
  return tool.name;
19416
20858
  }
@@ -19458,7 +20900,7 @@ function finalizeRunnerSpan(state, activeRunnerSpans) {
19458
20900
  }
19459
20901
  state.span.log({
19460
20902
  output: lastEvent ? extractEventOutput(lastEvent) : void 0,
19461
- metrics: cleanMetrics2(metrics)
20903
+ metrics: cleanMetrics3(metrics)
19462
20904
  });
19463
20905
  } finally {
19464
20906
  cleanupActiveRunnerSpan(state, activeRunnerSpans);
@@ -19475,7 +20917,7 @@ function finalizeAgentSpan(state, activeAgentSpans) {
19475
20917
  metrics.duration = end - state.startTime;
19476
20918
  state.span.log({
19477
20919
  output: lastEvent ? extractEventOutput(lastEvent) : void 0,
19478
- metrics: cleanMetrics2(metrics)
20920
+ metrics: cleanMetrics3(metrics)
19479
20921
  });
19480
20922
  } finally {
19481
20923
  cleanupActiveAgentSpan(state, activeAgentSpans);
@@ -19561,7 +21003,7 @@ function populateUsageMetrics2(metrics, usage) {
19561
21003
  metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
19562
21004
  }
19563
21005
  }
19564
- function cleanMetrics2(metrics) {
21006
+ function cleanMetrics3(metrics) {
19565
21007
  const cleaned = {};
19566
21008
  for (const [key, value] of Object.entries(metrics)) {
19567
21009
  if (value !== null && value !== void 0) {
@@ -19689,6 +21131,11 @@ var CHAT_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
19689
21131
  "strictTools",
19690
21132
  "strict_tools",
19691
21133
  "temperature",
21134
+ "thinking",
21135
+ "thinkingTokenBudget",
21136
+ "thinkingType",
21137
+ "thinking_token_budget",
21138
+ "thinking_type",
19692
21139
  "toolChoice",
19693
21140
  "tool_choice"
19694
21141
  ]);
@@ -19909,6 +21356,11 @@ function mergeUsageMetrics(metrics, usage) {
19909
21356
  "tokens",
19910
21357
  tokenContainer.totalTokens ?? tokenContainer.total_tokens
19911
21358
  );
21359
+ setMetricIfNumber(
21360
+ metrics,
21361
+ "reasoning_tokens",
21362
+ tokenContainer.reasoningTokens ?? tokenContainer.reasoning_tokens ?? tokenContainer.thinkingTokens ?? tokenContainer.thinking_tokens
21363
+ );
19912
21364
  }
19913
21365
  const billedUnits = (isObject(source.billedUnits) ? source.billedUnits : void 0) || (isObject(source.billed_units) ? source.billed_units : void 0);
19914
21366
  if (billedUnits) {
@@ -19989,13 +21441,87 @@ function extractV8DeltaText(chunk) {
19989
21441
  }
19990
21442
  return void 0;
19991
21443
  }
21444
+ function getV8ContentIndex(chunk) {
21445
+ return typeof chunk.index === "number" ? chunk.index : 0;
21446
+ }
21447
+ function toContentBlockType(value) {
21448
+ return value === "text" || value === "thinking" ? value : void 0;
21449
+ }
21450
+ function getOrCreateContentBlock(contentBlocksByIndex, contentBlockOrder, index) {
21451
+ if (!contentBlockOrder.includes(index)) {
21452
+ contentBlockOrder.push(index);
21453
+ }
21454
+ if (!(index in contentBlocksByIndex)) {
21455
+ contentBlocksByIndex[index] = {
21456
+ text: "",
21457
+ thinking: ""
21458
+ };
21459
+ }
21460
+ return contentBlocksByIndex[index];
21461
+ }
21462
+ function appendV8ContentBlock(contentBlocksByIndex, contentBlockOrder, index, content) {
21463
+ if (typeof content === "string") {
21464
+ const block2 = getOrCreateContentBlock(
21465
+ contentBlocksByIndex,
21466
+ contentBlockOrder,
21467
+ index
21468
+ );
21469
+ block2.type ??= "text";
21470
+ block2.text += content;
21471
+ return;
21472
+ }
21473
+ if (!isObject(content)) {
21474
+ return;
21475
+ }
21476
+ const block = getOrCreateContentBlock(
21477
+ contentBlocksByIndex,
21478
+ contentBlockOrder,
21479
+ index
21480
+ );
21481
+ const contentType = toContentBlockType(content.type);
21482
+ if (contentType) {
21483
+ block.type = contentType;
21484
+ }
21485
+ if (typeof content.text === "string") {
21486
+ block.type ??= "text";
21487
+ block.text += content.text;
21488
+ }
21489
+ if (typeof content.thinking === "string") {
21490
+ block.type ??= "thinking";
21491
+ block.thinking += content.thinking;
21492
+ }
21493
+ }
21494
+ function serializeAggregatedContentBlocks(contentBlocksByIndex, contentBlockOrder) {
21495
+ return contentBlockOrder.sort((left, right) => left - right).flatMap((index) => {
21496
+ const block = contentBlocksByIndex[index];
21497
+ if (!block) {
21498
+ return [];
21499
+ }
21500
+ if (block.type === "thinking" && block.thinking.length > 0) {
21501
+ return [{ type: "thinking", thinking: block.thinking }];
21502
+ }
21503
+ if (block.text.length > 0) {
21504
+ return [{ type: "text", text: block.text }];
21505
+ }
21506
+ if (block.thinking.length > 0) {
21507
+ return [{ type: "thinking", thinking: block.thinking }];
21508
+ }
21509
+ return [];
21510
+ });
21511
+ }
21512
+ function hasThinkingContent(contentBlocks) {
21513
+ return contentBlocks.some((block) => block.type === "thinking");
21514
+ }
19992
21515
  function aggregateCohereChatStreamChunks(chunks) {
19993
21516
  const textDeltas = [];
21517
+ const contentBlocksByIndex = {};
21518
+ const contentBlockOrder = [];
19994
21519
  const toolCallsByIndex = {};
19995
21520
  const toolCallOrder = [];
19996
21521
  let terminalResponse;
19997
21522
  let role;
19998
21523
  let finishReason;
21524
+ let toolPlan = "";
19999
21525
  let metadata = {};
20000
21526
  let metrics = {};
20001
21527
  for (const chunk of chunks) {
@@ -20053,12 +21579,36 @@ function aggregateCohereChatStreamChunks(chunks) {
20053
21579
  continue;
20054
21580
  }
20055
21581
  if (eventType === "content-delta") {
21582
+ appendV8ContentBlock(
21583
+ contentBlocksByIndex,
21584
+ contentBlockOrder,
21585
+ getV8ContentIndex(chunk),
21586
+ isObject(chunk.delta) && isObject(chunk.delta.message) ? chunk.delta.message.content : void 0
21587
+ );
20056
21588
  const text = extractV8DeltaText(chunk);
20057
21589
  if (text) {
20058
21590
  textDeltas.push(text);
20059
21591
  }
20060
21592
  continue;
20061
21593
  }
21594
+ if (eventType === "content-start") {
21595
+ appendV8ContentBlock(
21596
+ contentBlocksByIndex,
21597
+ contentBlockOrder,
21598
+ getV8ContentIndex(chunk),
21599
+ isObject(chunk.delta) && isObject(chunk.delta.message) ? chunk.delta.message.content : void 0
21600
+ );
21601
+ continue;
21602
+ }
21603
+ if (eventType === "tool-plan-delta") {
21604
+ if (isObject(chunk.delta) && isObject(chunk.delta.message)) {
21605
+ 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;
21606
+ if (deltaToolPlan) {
21607
+ toolPlan += deltaToolPlan;
21608
+ }
21609
+ }
21610
+ continue;
21611
+ }
20062
21612
  if (eventType === "tool-call-start") {
20063
21613
  const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
20064
21614
  Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
@@ -20112,13 +21662,26 @@ function aggregateCohereChatStreamChunks(chunks) {
20112
21662
  }
20113
21663
  }
20114
21664
  const mergedToolCalls = toolCallOrder.sort((left, right) => left - right).map((index) => toolCallsByIndex[index]).filter((toolCall) => isObject(toolCall));
21665
+ const aggregatedContentBlocks = serializeAggregatedContentBlocks(
21666
+ contentBlocksByIndex,
21667
+ contentBlockOrder
21668
+ );
20115
21669
  let output = extractCohereChatOutput(terminalResponse);
20116
21670
  if (output === void 0) {
20117
21671
  const mergedText = textDeltas.join("");
20118
- if (mergedToolCalls.length > 0 || role || mergedText.length > 0) {
21672
+ const shouldUseStructuredContent = hasThinkingContent(aggregatedContentBlocks) || toolPlan.length > 0;
21673
+ if (shouldUseStructuredContent) {
21674
+ output = {
21675
+ ...role ? { role } : {},
21676
+ ...aggregatedContentBlocks.length > 0 ? { content: aggregatedContentBlocks } : {},
21677
+ ...toolPlan.length > 0 ? { toolPlan } : {},
21678
+ ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
21679
+ };
21680
+ } else if (mergedToolCalls.length > 0 || role || mergedText.length > 0 || aggregatedContentBlocks.length > 0) {
21681
+ const textContent = mergedText.length > 0 ? mergedText : aggregatedContentBlocks[0]?.type === "text" ? aggregatedContentBlocks[0].text : void 0;
20119
21682
  output = {
20120
21683
  ...role ? { role } : {},
20121
- ...mergedText.length > 0 ? { content: mergedText } : {},
21684
+ ...textContent ? { content: textContent } : {},
20122
21685
  ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
20123
21686
  };
20124
21687
  }
@@ -20136,6 +21699,98 @@ function aggregateCohereChatStreamChunks(chunks) {
20136
21699
  };
20137
21700
  }
20138
21701
 
21702
+ // src/instrumentation/plugins/groq-channels.ts
21703
+ var groqChannels = defineChannels("groq-sdk", {
21704
+ chatCompletionsCreate: channel({
21705
+ channelName: "chat.completions.create",
21706
+ kind: "async"
21707
+ }),
21708
+ embeddingsCreate: channel(
21709
+ {
21710
+ channelName: "embeddings.create",
21711
+ kind: "async"
21712
+ }
21713
+ )
21714
+ });
21715
+
21716
+ // src/instrumentation/plugins/groq-plugin.ts
21717
+ var GroqPlugin = class extends BasePlugin {
21718
+ onEnable() {
21719
+ this.unsubscribers.push(
21720
+ traceStreamingChannel(groqChannels.chatCompletionsCreate, {
21721
+ name: "groq.chat.completions.create",
21722
+ type: "llm" /* LLM */,
21723
+ extractInput: ([params]) => {
21724
+ const { messages, ...metadata } = params;
21725
+ return {
21726
+ input: processInputAttachments(messages),
21727
+ metadata: { ...metadata, provider: "groq" }
21728
+ };
21729
+ },
21730
+ extractOutput: (result) => result?.choices,
21731
+ extractMetrics: (result, startTime) => {
21732
+ const metrics = parseGroqMetrics(result);
21733
+ if (startTime) {
21734
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
21735
+ }
21736
+ return metrics;
21737
+ },
21738
+ aggregateChunks: aggregateGroqChatCompletionChunks
21739
+ })
21740
+ );
21741
+ this.unsubscribers.push(
21742
+ traceAsyncChannel(groqChannels.embeddingsCreate, {
21743
+ name: "groq.embeddings.create",
21744
+ type: "llm" /* LLM */,
21745
+ extractInput: ([params]) => {
21746
+ const { input, ...metadata } = params;
21747
+ return {
21748
+ input,
21749
+ metadata: { ...metadata, provider: "groq" }
21750
+ };
21751
+ },
21752
+ extractOutput: (result) => {
21753
+ const embedding = result?.data?.[0]?.embedding;
21754
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
21755
+ },
21756
+ extractMetrics: (result) => parseGroqMetrics(result)
21757
+ })
21758
+ );
21759
+ }
21760
+ onDisable() {
21761
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
21762
+ }
21763
+ };
21764
+ function parseGroqMetrics(result) {
21765
+ const metrics = parseMetricsFromUsage(result?.usage);
21766
+ const xGroq = result?.x_groq;
21767
+ if (!xGroq || typeof xGroq !== "object") {
21768
+ return metrics;
21769
+ }
21770
+ const extraUsage = "usage" in xGroq ? xGroq.usage : void 0;
21771
+ if (!extraUsage || typeof extraUsage !== "object") {
21772
+ return metrics;
21773
+ }
21774
+ const dramCachedTokens = extraUsage["dram_cached_tokens"];
21775
+ const sramCachedTokens = extraUsage["sram_cached_tokens"];
21776
+ return {
21777
+ ...metrics,
21778
+ ...typeof dramCachedTokens === "number" ? { dram_cached_tokens: dramCachedTokens } : {},
21779
+ ...typeof sramCachedTokens === "number" ? { sram_cached_tokens: sramCachedTokens } : {}
21780
+ };
21781
+ }
21782
+ function aggregateGroqChatCompletionChunks(chunks, streamResult, endEvent) {
21783
+ const aggregated = aggregateChatCompletionChunks(
21784
+ chunks,
21785
+ streamResult,
21786
+ endEvent
21787
+ );
21788
+ return {
21789
+ metrics: aggregated.metrics,
21790
+ output: aggregated.output
21791
+ };
21792
+ }
21793
+
20139
21794
  // src/instrumentation/braintrust-plugin.ts
20140
21795
  var BraintrustPlugin = class extends BasePlugin {
20141
21796
  config;
@@ -20143,6 +21798,7 @@ var BraintrustPlugin = class extends BasePlugin {
20143
21798
  anthropicPlugin = null;
20144
21799
  aiSDKPlugin = null;
20145
21800
  claudeAgentSDKPlugin = null;
21801
+ cursorSDKPlugin = null;
20146
21802
  googleGenAIPlugin = null;
20147
21803
  huggingFacePlugin = null;
20148
21804
  openRouterPlugin = null;
@@ -20150,6 +21806,7 @@ var BraintrustPlugin = class extends BasePlugin {
20150
21806
  mistralPlugin = null;
20151
21807
  googleADKPlugin = null;
20152
21808
  coherePlugin = null;
21809
+ groqPlugin = null;
20153
21810
  constructor(config = {}) {
20154
21811
  super();
20155
21812
  this.config = config;
@@ -20172,6 +21829,10 @@ var BraintrustPlugin = class extends BasePlugin {
20172
21829
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
20173
21830
  this.claudeAgentSDKPlugin.enable();
20174
21831
  }
21832
+ if (integrations.cursorSDK !== false && integrations.cursor !== false) {
21833
+ this.cursorSDKPlugin = new CursorSDKPlugin();
21834
+ this.cursorSDKPlugin.enable();
21835
+ }
20175
21836
  if (integrations.googleGenAI !== false && integrations.google !== false) {
20176
21837
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
20177
21838
  this.googleGenAIPlugin.enable();
@@ -20200,6 +21861,10 @@ var BraintrustPlugin = class extends BasePlugin {
20200
21861
  this.coherePlugin = new CoherePlugin();
20201
21862
  this.coherePlugin.enable();
20202
21863
  }
21864
+ if (integrations.groq !== false) {
21865
+ this.groqPlugin = new GroqPlugin();
21866
+ this.groqPlugin.enable();
21867
+ }
20203
21868
  }
20204
21869
  onDisable() {
20205
21870
  if (this.openaiPlugin) {
@@ -20218,6 +21883,10 @@ var BraintrustPlugin = class extends BasePlugin {
20218
21883
  this.claudeAgentSDKPlugin.disable();
20219
21884
  this.claudeAgentSDKPlugin = null;
20220
21885
  }
21886
+ if (this.cursorSDKPlugin) {
21887
+ this.cursorSDKPlugin.disable();
21888
+ this.cursorSDKPlugin = null;
21889
+ }
20221
21890
  if (this.googleGenAIPlugin) {
20222
21891
  this.googleGenAIPlugin.disable();
20223
21892
  this.googleGenAIPlugin = null;
@@ -20246,6 +21915,10 @@ var BraintrustPlugin = class extends BasePlugin {
20246
21915
  this.coherePlugin.disable();
20247
21916
  this.coherePlugin = null;
20248
21917
  }
21918
+ if (this.groqPlugin) {
21919
+ this.groqPlugin.disable();
21920
+ this.groqPlugin = null;
21921
+ }
20249
21922
  }
20250
21923
  };
20251
21924
 
@@ -20319,6 +21992,8 @@ var PluginRegistry = class {
20319
21992
  google: true,
20320
21993
  huggingface: true,
20321
21994
  claudeAgentSDK: true,
21995
+ cursor: true,
21996
+ cursorSDK: true,
20322
21997
  openrouter: true,
20323
21998
  openrouterAgent: true,
20324
21999
  mistral: true,
@@ -20335,7 +22010,11 @@ var PluginRegistry = class {
20335
22010
  if (disabledList) {
20336
22011
  const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
20337
22012
  for (const sdk of disabled) {
20338
- integrations[sdk] = false;
22013
+ if (sdk === "cursor-sdk") {
22014
+ integrations.cursorSDK = false;
22015
+ } else {
22016
+ integrations[sdk] = false;
22017
+ }
20339
22018
  }
20340
22019
  }
20341
22020
  return { integrations };
@@ -20516,8 +22195,10 @@ __export(exports_exports, {
20516
22195
  wrapAnthropic: () => wrapAnthropic,
20517
22196
  wrapClaudeAgentSDK: () => wrapClaudeAgentSDK,
20518
22197
  wrapCohere: () => wrapCohere,
22198
+ wrapCursorSDK: () => wrapCursorSDK,
20519
22199
  wrapGoogleADK: () => wrapGoogleADK,
20520
22200
  wrapGoogleGenAI: () => wrapGoogleGenAI,
22201
+ wrapGroq: () => wrapGroq,
20521
22202
  wrapHuggingFace: () => wrapHuggingFace,
20522
22203
  wrapMastraAgent: () => wrapMastraAgent,
20523
22204
  wrapMistral: () => wrapMistral,
@@ -22132,6 +23813,130 @@ function claudeAgentSDKProxy(sdk) {
22132
23813
  });
22133
23814
  }
22134
23815
 
23816
+ // src/wrappers/cursor-sdk.ts
23817
+ var WRAPPED_AGENT2 = Symbol.for("braintrust.cursor-sdk.wrapped-agent");
23818
+ function wrapCursorSDK(sdk) {
23819
+ if (!sdk || typeof sdk !== "object") {
23820
+ return sdk;
23821
+ }
23822
+ const maybeSDK = sdk;
23823
+ if (!maybeSDK.Agent || typeof maybeSDK.Agent !== "function") {
23824
+ console.warn("Unsupported Cursor SDK. Not wrapping.");
23825
+ return sdk;
23826
+ }
23827
+ const target = isModuleNamespace2(sdk) ? Object.setPrototypeOf({}, sdk) : sdk;
23828
+ return new Proxy(target, {
23829
+ get(target2, prop, receiver) {
23830
+ const value = Reflect.get(target2, prop, receiver);
23831
+ if (prop === "Agent" && typeof value === "function") {
23832
+ return wrapCursorAgentClass(value);
23833
+ }
23834
+ if (typeof value === "function") {
23835
+ return value.bind(target2);
23836
+ }
23837
+ return value;
23838
+ }
23839
+ });
23840
+ }
23841
+ function isModuleNamespace2(obj) {
23842
+ if (!obj || typeof obj !== "object") {
23843
+ return false;
23844
+ }
23845
+ if (obj.constructor?.name === "Module") {
23846
+ return true;
23847
+ }
23848
+ const keys = Object.keys(obj);
23849
+ if (keys.length === 0) {
23850
+ return false;
23851
+ }
23852
+ const descriptor = Object.getOwnPropertyDescriptor(obj, keys[0]);
23853
+ return descriptor ? !descriptor.configurable && !descriptor.writable : false;
23854
+ }
23855
+ function wrapCursorAgentClass(Agent) {
23856
+ const cache = /* @__PURE__ */ new Map();
23857
+ return new Proxy(Agent, {
23858
+ get(target, prop, receiver) {
23859
+ if (cache.has(prop)) {
23860
+ return cache.get(prop);
23861
+ }
23862
+ const value = Reflect.get(target, prop, receiver);
23863
+ if (prop === "create" && typeof value === "function") {
23864
+ const wrapped = async function(options) {
23865
+ const args = [options];
23866
+ return cursorSDKChannels.create.tracePromise(
23867
+ async () => wrapCursorAgent(await Reflect.apply(value, target, args)),
23868
+ { arguments: args }
23869
+ );
23870
+ };
23871
+ cache.set(prop, wrapped);
23872
+ return wrapped;
23873
+ }
23874
+ if (prop === "resume" && typeof value === "function") {
23875
+ const wrapped = async function(agentId, options) {
23876
+ const args = [agentId, options];
23877
+ return cursorSDKChannels.resume.tracePromise(
23878
+ async () => wrapCursorAgent(await Reflect.apply(value, target, args)),
23879
+ { arguments: args }
23880
+ );
23881
+ };
23882
+ cache.set(prop, wrapped);
23883
+ return wrapped;
23884
+ }
23885
+ if (prop === "prompt" && typeof value === "function") {
23886
+ const wrapped = async function(message, options) {
23887
+ const args = [message, options];
23888
+ return cursorSDKChannels.prompt.tracePromise(
23889
+ () => Reflect.apply(value, target, args),
23890
+ { arguments: args }
23891
+ );
23892
+ };
23893
+ cache.set(prop, wrapped);
23894
+ return wrapped;
23895
+ }
23896
+ if (typeof value === "function") {
23897
+ const bound = value.bind(target);
23898
+ cache.set(prop, bound);
23899
+ return bound;
23900
+ }
23901
+ return value;
23902
+ }
23903
+ });
23904
+ }
23905
+ function wrapCursorAgent(agent) {
23906
+ if (!agent || typeof agent !== "object") {
23907
+ return agent;
23908
+ }
23909
+ if (agent[WRAPPED_AGENT2]) {
23910
+ return agent;
23911
+ }
23912
+ const proxy = new Proxy(agent, {
23913
+ get(target, prop, receiver) {
23914
+ if (prop === WRAPPED_AGENT2) {
23915
+ return true;
23916
+ }
23917
+ const value = Reflect.get(target, prop, receiver);
23918
+ if (prop === "send" && typeof value === "function") {
23919
+ return function(message, options) {
23920
+ const args = [message, options];
23921
+ return cursorSDKChannels.send.tracePromise(
23922
+ () => Reflect.apply(value, target, args),
23923
+ {
23924
+ agent: target,
23925
+ arguments: args,
23926
+ operation: "send"
23927
+ }
23928
+ );
23929
+ };
23930
+ }
23931
+ if (typeof value === "function") {
23932
+ return value.bind(target);
23933
+ }
23934
+ return value;
23935
+ }
23936
+ });
23937
+ return proxy;
23938
+ }
23939
+
22135
23940
  // src/wrappers/google-genai.ts
22136
23941
  function wrapGoogleGenAI(googleGenAI) {
22137
23942
  if (!googleGenAI || typeof googleGenAI !== "object") {
@@ -22885,6 +24690,94 @@ function wrapRerank3(rerank) {
22885
24690
  });
22886
24691
  }
22887
24692
 
24693
+ // src/wrappers/groq.ts
24694
+ function wrapGroq(groq) {
24695
+ if (isSupportedGroqClient(groq)) {
24696
+ return groqProxy(groq);
24697
+ }
24698
+ console.warn("Unsupported Groq library. Not wrapping.");
24699
+ return groq;
24700
+ }
24701
+ function isRecord3(value) {
24702
+ return typeof value === "object" && value !== null;
24703
+ }
24704
+ function hasFunction4(value, methodName) {
24705
+ return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
24706
+ }
24707
+ function hasChat2(value) {
24708
+ return isRecord3(value) && isRecord3(value.completions) && hasFunction4(value.completions, "create");
24709
+ }
24710
+ function hasEmbeddings2(value) {
24711
+ return hasFunction4(value, "create");
24712
+ }
24713
+ function isSupportedGroqClient(value) {
24714
+ return isRecord3(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
24715
+ }
24716
+ function groqProxy(groq) {
24717
+ const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
24718
+ const completionProxy = groq.chat?.completions ? new Proxy(groq.chat.completions, {
24719
+ get(target, prop, receiver) {
24720
+ if (prop === "create") {
24721
+ return wrapChatCompletionsCreate(target.create.bind(target));
24722
+ }
24723
+ return Reflect.get(target, prop, receiver);
24724
+ }
24725
+ }) : void 0;
24726
+ const chatProxy3 = groq.chat ? new Proxy(groq.chat, {
24727
+ get(target, prop, receiver) {
24728
+ if (prop === "completions") {
24729
+ return completionProxy ?? target.completions;
24730
+ }
24731
+ return Reflect.get(target, prop, receiver);
24732
+ }
24733
+ }) : void 0;
24734
+ const embeddingsProxy3 = groq.embeddings ? new Proxy(groq.embeddings, {
24735
+ get(target, prop, receiver) {
24736
+ if (prop === "create") {
24737
+ return wrapEmbeddingsCreate2(target.create.bind(target));
24738
+ }
24739
+ return Reflect.get(target, prop, receiver);
24740
+ }
24741
+ }) : void 0;
24742
+ const topLevelProxy = new Proxy(groq, {
24743
+ get(target, prop, receiver) {
24744
+ switch (prop) {
24745
+ case "chat":
24746
+ return chatProxy3 ?? target.chat;
24747
+ case "embeddings":
24748
+ return embeddingsProxy3 ?? target.embeddings;
24749
+ }
24750
+ const value = Reflect.get(target, prop, target);
24751
+ if (typeof value !== "function") {
24752
+ return value;
24753
+ }
24754
+ const cachedValue = privateMethodWorkaroundCache.get(value);
24755
+ if (cachedValue) {
24756
+ return cachedValue;
24757
+ }
24758
+ const thisBoundValue = function(...args) {
24759
+ const thisArg = this === topLevelProxy ? target : this;
24760
+ const output = Reflect.apply(value, thisArg, args);
24761
+ return output === target ? topLevelProxy : output;
24762
+ };
24763
+ privateMethodWorkaroundCache.set(value, thisBoundValue);
24764
+ return thisBoundValue;
24765
+ }
24766
+ });
24767
+ return topLevelProxy;
24768
+ }
24769
+ function wrapChatCompletionsCreate(create) {
24770
+ return (request, options) => groqChannels.chatCompletionsCreate.tracePromise(
24771
+ () => create(request, options),
24772
+ { arguments: [request] }
24773
+ );
24774
+ }
24775
+ function wrapEmbeddingsCreate2(create) {
24776
+ return (request, options) => groqChannels.embeddingsCreate.tracePromise(() => create(request, options), {
24777
+ arguments: [request]
24778
+ });
24779
+ }
24780
+
22888
24781
  // src/wrappers/vitest/context-manager.ts
22889
24782
  var VitestContextManager = class {
22890
24783
  /**
@@ -26865,8 +28758,10 @@ export {
26865
28758
  wrapAnthropic,
26866
28759
  wrapClaudeAgentSDK,
26867
28760
  wrapCohere,
28761
+ wrapCursorSDK,
26868
28762
  wrapGoogleADK,
26869
28763
  wrapGoogleGenAI,
28764
+ wrapGroq,
26870
28765
  wrapHuggingFace,
26871
28766
  wrapMastraAgent,
26872
28767
  wrapMistral,