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
@@ -1881,6 +1881,7 @@ var TopicMapData = z6.object({
1881
1881
  report_key: z6.string().optional(),
1882
1882
  topic_names: z6.record(z6.string()).optional(),
1883
1883
  generation_settings: TopicMapGenerationSettings.optional(),
1884
+ disable_reconciliation: z6.boolean().optional(),
1884
1885
  distance_threshold: z6.number().optional()
1885
1886
  });
1886
1887
  var BatchedFacetData = z6.object({
@@ -2211,28 +2212,6 @@ var EnvVar = z6.object({
2211
2212
  secret_type: z6.union([z6.string(), z6.null()]).optional(),
2212
2213
  secret_category: z6.enum(["env_var", "ai_provider", "sandbox_provider"]).optional().default("env_var")
2213
2214
  });
2214
- var EvalStatusPageTheme = z6.enum(["light", "dark"]);
2215
- var EvalStatusPageConfig = z6.object({
2216
- score_columns: z6.union([z6.array(z6.string()), z6.null()]),
2217
- metric_columns: z6.union([z6.array(z6.string()), z6.null()]),
2218
- grouping_field: z6.union([z6.string(), z6.null()]),
2219
- filter: z6.union([z6.string(), z6.null()]),
2220
- sort_by: z6.union([z6.string(), z6.null()]),
2221
- sort_order: z6.union([z6.enum(["asc", "desc"]), z6.null()]),
2222
- api_key: z6.union([z6.string(), z6.null()])
2223
- }).partial();
2224
- var EvalStatusPage = z6.object({
2225
- id: z6.string().uuid(),
2226
- project_id: z6.string().uuid(),
2227
- user_id: z6.union([z6.string(), z6.null()]).optional(),
2228
- created: z6.union([z6.string(), z6.null()]).optional(),
2229
- deleted_at: z6.union([z6.string(), z6.null()]).optional(),
2230
- name: z6.string(),
2231
- description: z6.union([z6.string(), z6.null()]).optional(),
2232
- logo_url: z6.union([z6.string(), z6.null()]).optional(),
2233
- theme: EvalStatusPageTheme,
2234
- config: EvalStatusPageConfig
2235
- });
2236
2215
  var RepoInfo = z6.union([
2237
2216
  z6.object({
2238
2217
  commit: z6.union([z6.string(), z6.null()]),
@@ -2259,6 +2238,15 @@ var Experiment = z6.object({
2259
2238
  deleted_at: z6.union([z6.string(), z6.null()]).optional(),
2260
2239
  dataset_id: z6.union([z6.string(), z6.null()]).optional(),
2261
2240
  dataset_version: z6.union([z6.string(), z6.null()]).optional(),
2241
+ internal_metadata: z6.union([
2242
+ z6.object({
2243
+ dataset_filter: z6.union([
2244
+ z6.object({}).partial().passthrough(),
2245
+ z6.null()
2246
+ ])
2247
+ }).partial().passthrough(),
2248
+ z6.null()
2249
+ ]).optional(),
2262
2250
  parameters_id: z6.union([z6.string(), z6.null()]).optional(),
2263
2251
  parameters_version: z6.union([z6.string(), z6.null()]).optional(),
2264
2252
  public: z6.boolean(),
@@ -2995,14 +2983,21 @@ var ProjectAutomation = z6.object({
2995
2983
  z6.object({ type: z6.literal("log_spans") }),
2996
2984
  z6.object({ type: z6.literal("btql_query"), btql_query: z6.string() })
2997
2985
  ]),
2986
+ scope: z6.union([SpanScope, TraceScope, GroupScope, z6.null()]).optional(),
2998
2987
  export_path: z6.string(),
2999
2988
  format: z6.enum(["jsonl", "parquet"]),
3000
2989
  interval_seconds: z6.number().gte(1).lte(2592e3),
3001
- credentials: z6.object({
3002
- type: z6.literal("aws_iam"),
3003
- role_arn: z6.string(),
3004
- external_id: z6.string()
3005
- }),
2990
+ credentials: z6.union([
2991
+ z6.object({
2992
+ type: z6.literal("aws_iam"),
2993
+ role_arn: z6.string(),
2994
+ external_id: z6.string()
2995
+ }),
2996
+ z6.object({
2997
+ type: z6.literal("gcp_service_account"),
2998
+ service_account_email: z6.string()
2999
+ })
3000
+ ]),
3006
3001
  batch_size: z6.union([z6.number(), z6.null()]).optional()
3007
3002
  }),
3008
3003
  z6.object({
@@ -3382,7 +3377,7 @@ var ViewOptions = z6.union([
3382
3377
  z6.object({ from: z6.string(), to: z6.string() }),
3383
3378
  z6.null()
3384
3379
  ]),
3385
- queryShape: z6.union([z6.enum(["traces", "spans"]), z6.null()]),
3380
+ queryShape: z6.union([z6.enum(["traces", "spans", "topics"]), z6.null()]),
3386
3381
  cluster: z6.union([z6.string(), z6.null()]),
3387
3382
  freezeColumns: z6.union([z6.boolean(), z6.null()])
3388
3383
  }).partial(),
@@ -4370,6 +4365,19 @@ var RESET_CONTEXT_MANAGER_STATE = Symbol.for(
4370
4365
  "braintrust.resetContextManagerState"
4371
4366
  );
4372
4367
  var DEFAULT_MAX_REQUEST_SIZE = 6 * 1024 * 1024;
4368
+ var datasetSnapshotRegisterResponseSchema = z8.object({
4369
+ dataset_snapshot: DatasetSnapshot,
4370
+ found_existing: z8.boolean().optional()
4371
+ });
4372
+ var datasetRestorePreviewResultSchema = z8.object({
4373
+ rows_to_restore: z8.number(),
4374
+ rows_to_delete: z8.number()
4375
+ });
4376
+ var datasetRestoreResultSchema = z8.object({
4377
+ xact_id: z8.string().nullable(),
4378
+ rows_restored: z8.number(),
4379
+ rows_deleted: z8.number()
4380
+ });
4373
4381
  var parametersRowSchema = z8.object({
4374
4382
  id: z8.string().uuid(),
4375
4383
  _xact_id: z8.string(),
@@ -6366,6 +6374,40 @@ Error: ${errorText}`;
6366
6374
  this.queue.enforceQueueSizeLimit(enforce);
6367
6375
  }
6368
6376
  };
6377
+ function isDatasetSnapshotNameLookup(lookup) {
6378
+ return "snapshotName" in lookup;
6379
+ }
6380
+ function assertDatasetSnapshotLookup(lookup) {
6381
+ const hasSnapshotName = lookup.snapshotName !== void 0;
6382
+ const hasXactId = lookup.xactId !== void 0;
6383
+ if (hasSnapshotName === hasXactId) {
6384
+ throw new Error("Exactly one of snapshotName or xactId must be provided");
6385
+ }
6386
+ }
6387
+ function getInternalBtqlLimit(internalBtql) {
6388
+ const limit = internalBtql?.["limit"];
6389
+ return typeof limit === "number" ? limit : void 0;
6390
+ }
6391
+ async function getDatasetSnapshots(params) {
6392
+ const { state, datasetId } = params;
6393
+ return DatasetSnapshot.array().parse(
6394
+ await state.appConn().post_json("api/dataset_snapshot/get", {
6395
+ dataset_id: datasetId,
6396
+ ..."snapshotName" in params ? { name: params.snapshotName } : {},
6397
+ ..."xactId" in params ? { xact_id: params.xactId } : {}
6398
+ })
6399
+ );
6400
+ }
6401
+ async function getDatasetSnapshot(params) {
6402
+ assertDatasetSnapshotLookup(params);
6403
+ const snapshots = await getDatasetSnapshots(params);
6404
+ if (snapshots.length > 1) {
6405
+ throw new Error(
6406
+ 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}`
6407
+ );
6408
+ }
6409
+ return snapshots[0];
6410
+ }
6369
6411
  async function computeLoggerMetadata(state, {
6370
6412
  project_name,
6371
6413
  project_id
@@ -6780,11 +6822,20 @@ var ObjectFetcher = class {
6780
6822
  async getState() {
6781
6823
  throw new Error("ObjectFetcher subclasses must have a 'getState' method");
6782
6824
  }
6825
+ getPinnedVersion() {
6826
+ return this.pinnedVersion;
6827
+ }
6828
+ setPinnedVersion(pinnedVersion) {
6829
+ this.pinnedVersion = pinnedVersion;
6830
+ }
6831
+ getInternalBtql() {
6832
+ return this._internal_btql;
6833
+ }
6783
6834
  async *fetchRecordsFromApi(batchSize) {
6784
6835
  const state = await this.getState();
6785
6836
  const objectId = await this.id;
6786
6837
  const batchLimit = batchSize ?? DEFAULT_FETCH_BATCH_SIZE;
6787
- const internalLimit = this._internal_btql?.limit;
6838
+ const internalLimit = getInternalBtqlLimit(this._internal_btql);
6788
6839
  const limit = batchSize !== void 0 ? batchSize : internalLimit ?? batchLimit;
6789
6840
  const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
6790
6841
  Object.entries(this._internal_btql ?? {}).filter(
@@ -7558,7 +7609,7 @@ function splitLoggingData({
7558
7609
  return [serializableInternalData, lazyInternalData];
7559
7610
  }
7560
7611
  var Dataset2 = class extends ObjectFetcher {
7561
- constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql) {
7612
+ constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql, pinState) {
7562
7613
  const isLegacyDataset = legacy ?? DEFAULT_IS_LEGACY_DATASET;
7563
7614
  if (isLegacyDataset) {
7564
7615
  debugLogger.forState(state).warn(
@@ -7579,10 +7630,16 @@ var Dataset2 = class extends ObjectFetcher {
7579
7630
  );
7580
7631
  this.state = state;
7581
7632
  this.lazyMetadata = lazyMetadata;
7633
+ this.lazyPinnedVersion = pinState?.lazyPinnedVersion;
7634
+ this.pinnedEnvironment = pinState?.pinnedEnvironment;
7635
+ this.pinnedSnapshotName = pinState?.pinnedSnapshotName;
7582
7636
  }
7583
7637
  lazyMetadata;
7584
7638
  __braintrust_dataset_marker = true;
7585
7639
  newRecords = 0;
7640
+ lazyPinnedVersion;
7641
+ pinnedEnvironment;
7642
+ pinnedSnapshotName;
7586
7643
  get id() {
7587
7644
  return (async () => {
7588
7645
  return (await this.lazyMetadata.get()).dataset.id;
@@ -7601,10 +7658,40 @@ var Dataset2 = class extends ObjectFetcher {
7601
7658
  get loggingState() {
7602
7659
  return this.state;
7603
7660
  }
7661
+ async toEvalData() {
7662
+ await this.getState();
7663
+ const metadata = await this.lazyMetadata.get();
7664
+ const pinnedVersion = this.getPinnedVersion();
7665
+ const internalBtql = this.getInternalBtql();
7666
+ return {
7667
+ dataset_id: metadata.dataset.id,
7668
+ ...this.pinnedEnvironment !== void 0 ? {
7669
+ dataset_environment: this.pinnedEnvironment
7670
+ } : {},
7671
+ ...this.pinnedEnvironment === void 0 && this.pinnedSnapshotName !== void 0 ? {
7672
+ dataset_snapshot_name: this.pinnedSnapshotName
7673
+ } : {},
7674
+ ...this.pinnedEnvironment === void 0 && this.pinnedSnapshotName === void 0 && pinnedVersion !== void 0 ? {
7675
+ dataset_version: pinnedVersion
7676
+ } : {},
7677
+ ...internalBtql !== void 0 ? { _internal_btql: internalBtql } : {}
7678
+ };
7679
+ }
7604
7680
  async getState() {
7605
7681
  await this.lazyMetadata.get();
7682
+ if (this.lazyPinnedVersion !== void 0 && this.getPinnedVersion() === void 0) {
7683
+ this.setPinnedVersion(await this.lazyPinnedVersion.get());
7684
+ }
7606
7685
  return this.state;
7607
7686
  }
7687
+ async version(options) {
7688
+ const pinnedVersion = this.getPinnedVersion();
7689
+ if (pinnedVersion !== void 0) {
7690
+ return pinnedVersion;
7691
+ }
7692
+ await this.getState();
7693
+ return await super.version(options);
7694
+ }
7608
7695
  validateEvent({
7609
7696
  metadata,
7610
7697
  expected,
@@ -7740,6 +7827,88 @@ var Dataset2 = class extends ObjectFetcher {
7740
7827
  this.state.bgLogger().log([args]);
7741
7828
  return id;
7742
7829
  }
7830
+ async createSnapshot({
7831
+ name,
7832
+ description,
7833
+ update
7834
+ }) {
7835
+ await this.flush();
7836
+ const state = await this.getState();
7837
+ const datasetId = await this.id;
7838
+ const currentVersion = await this.version();
7839
+ if (currentVersion === void 0) {
7840
+ throw new Error("Cannot create snapshot: dataset has no version");
7841
+ }
7842
+ const response = await state.appConn().post_json("api/dataset_snapshot/register", {
7843
+ dataset_id: datasetId,
7844
+ dataset_snapshot_name: name,
7845
+ description,
7846
+ xact_id: currentVersion,
7847
+ update
7848
+ });
7849
+ return datasetSnapshotRegisterResponseSchema.parse(response).dataset_snapshot;
7850
+ }
7851
+ async listSnapshots() {
7852
+ const state = await this.getState();
7853
+ return await getDatasetSnapshots({
7854
+ state,
7855
+ datasetId: await this.id
7856
+ });
7857
+ }
7858
+ async getSnapshot(lookup) {
7859
+ const state = await this.getState();
7860
+ const datasetId = await this.id;
7861
+ return await getDatasetSnapshot({
7862
+ state,
7863
+ datasetId,
7864
+ ...lookup
7865
+ });
7866
+ }
7867
+ async updateSnapshot(snapshotId, {
7868
+ name,
7869
+ description
7870
+ }) {
7871
+ const state = await this.getState();
7872
+ return DatasetSnapshot.parse(
7873
+ await state.appConn().post_json("api/dataset_snapshot/patch_id", {
7874
+ id: snapshotId,
7875
+ name,
7876
+ description
7877
+ })
7878
+ );
7879
+ }
7880
+ async deleteSnapshot(snapshotId) {
7881
+ const state = await this.getState();
7882
+ return DatasetSnapshot.parse(
7883
+ await state.appConn().post_json("api/dataset_snapshot/delete_id", {
7884
+ id: snapshotId
7885
+ })
7886
+ );
7887
+ }
7888
+ async restorePreview({
7889
+ version
7890
+ }) {
7891
+ await this.flush();
7892
+ const state = await this.getState();
7893
+ const datasetId = await this.id;
7894
+ return datasetRestorePreviewResultSchema.parse(
7895
+ await state.apiConn().post_json(`v1/dataset/${datasetId}/restore/preview`, {
7896
+ version
7897
+ })
7898
+ );
7899
+ }
7900
+ async restore({
7901
+ version
7902
+ }) {
7903
+ await this.flush();
7904
+ const state = await this.getState();
7905
+ const datasetId = await this.id;
7906
+ return datasetRestoreResultSchema.parse(
7907
+ await state.apiConn().post_json(`v1/dataset/${datasetId}/restore`, {
7908
+ version
7909
+ })
7910
+ );
7911
+ }
7743
7912
  /**
7744
7913
  * Summarize the dataset, including high level metrics about its size and other metadata.
7745
7914
  * @param summarizeData Whether to summarize the data. If false, only the metadata will be returned.
@@ -12255,6 +12424,9 @@ function llmParentKey(parentToolUseId) {
12255
12424
  function isSubAgentDelegationToolName(toolName) {
12256
12425
  return toolName === "Agent" || toolName === "Task";
12257
12426
  }
12427
+ function shouldParentToolAsTaskSibling(toolName) {
12428
+ return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
12429
+ }
12258
12430
  function filterSerializableOptions(options) {
12259
12431
  const allowedKeys = [
12260
12432
  "model",
@@ -12354,6 +12526,11 @@ function resolveTaskToolUseId(taskIdToToolUseId, message) {
12354
12526
  }
12355
12527
  return void 0;
12356
12528
  }
12529
+ function seedTaskToolUseIdMapping(taskIdToToolUseId, message) {
12530
+ if (typeof message.task_id === "string" && typeof message.tool_use_id === "string") {
12531
+ taskIdToToolUseId.set(message.task_id, message.tool_use_id);
12532
+ }
12533
+ }
12357
12534
  function extractUsageFromMessage(message) {
12358
12535
  const metrics = {};
12359
12536
  let usage;
@@ -12549,7 +12726,10 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
12549
12726
  }
12550
12727
  },
12551
12728
  name: parsed.displayName,
12552
- parent: await resolveParentSpan(toolUseID),
12729
+ parent: await resolveParentSpan(toolUseID, {
12730
+ agentId: input.agent_id,
12731
+ preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
12732
+ }),
12553
12733
  spanAttributes: { type: "tool" /* TOOL */ }
12554
12734
  });
12555
12735
  activeToolSpans.set(toolUseID, toolSpan);
@@ -12839,6 +13019,7 @@ async function finalizeCurrentMessageGroup(state) {
12839
13019
  state.currentMessages.length = 0;
12840
13020
  }
12841
13021
  function maybeTrackToolUseContext(state, message) {
13022
+ seedTaskToolUseIdMapping(state.taskIdToToolUseId, message);
12842
13023
  if (message.type !== "assistant" || !Array.isArray(message.message?.content)) {
12843
13024
  return;
12844
13025
  }
@@ -12893,6 +13074,34 @@ async function ensureSubAgentSpan(subAgentDetailsByToolUseId, rootSpan, activeTo
12893
13074
  subAgentSpans.set(parentToolUseId, subAgentSpan);
12894
13075
  return subAgentSpan;
12895
13076
  }
13077
+ async function ensureActiveLlmSpanForParentToolUse(rootSpan, activeLlmSpansByParentToolUse, subAgentDetailsByToolUseId, activeToolSpans, subAgentSpans, parentToolUseId, startTime) {
13078
+ const parentKey = llmParentKey(parentToolUseId);
13079
+ const existingLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
13080
+ if (existingLlmSpan) {
13081
+ return existingLlmSpan;
13082
+ }
13083
+ let llmParentSpan = await rootSpan.export();
13084
+ if (parentToolUseId) {
13085
+ const subAgentSpan = await ensureSubAgentSpan(
13086
+ subAgentDetailsByToolUseId,
13087
+ rootSpan,
13088
+ activeToolSpans,
13089
+ subAgentSpans,
13090
+ parentToolUseId
13091
+ );
13092
+ llmParentSpan = await subAgentSpan.export();
13093
+ }
13094
+ const llmSpan = startSpan({
13095
+ name: "anthropic.messages.create",
13096
+ parent: llmParentSpan,
13097
+ spanAttributes: {
13098
+ type: "llm" /* LLM */
13099
+ },
13100
+ startTime
13101
+ });
13102
+ activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
13103
+ return llmSpan;
13104
+ }
12896
13105
  async function maybeHandleTaskLifecycleMessage(state, message) {
12897
13106
  if (message.type !== "system") {
12898
13107
  return false;
@@ -13002,29 +13211,15 @@ async function handleStreamMessage(state, message) {
13002
13211
  }
13003
13212
  if (message.type === "assistant" && message.message?.usage) {
13004
13213
  const parentToolUseId = message.parent_tool_use_id ?? null;
13005
- const parentKey = llmParentKey(parentToolUseId);
13006
- if (!state.activeLlmSpansByParentToolUse.has(parentKey)) {
13007
- let llmParentSpan = await state.span.export();
13008
- if (parentToolUseId) {
13009
- const subAgentSpan = await ensureSubAgentSpan(
13010
- state.subAgentDetailsByToolUseId,
13011
- state.span,
13012
- state.activeToolSpans,
13013
- state.subAgentSpans,
13014
- parentToolUseId
13015
- );
13016
- llmParentSpan = await subAgentSpan.export();
13017
- }
13018
- const llmSpan = startSpan({
13019
- name: "anthropic.messages.create",
13020
- parent: llmParentSpan,
13021
- spanAttributes: {
13022
- type: "llm" /* LLM */
13023
- },
13024
- startTime: state.currentMessageStartTime
13025
- });
13026
- state.activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
13027
- }
13214
+ await ensureActiveLlmSpanForParentToolUse(
13215
+ state.span,
13216
+ state.activeLlmSpansByParentToolUse,
13217
+ state.subAgentDetailsByToolUseId,
13218
+ state.activeToolSpans,
13219
+ state.subAgentSpans,
13220
+ parentToolUseId,
13221
+ state.currentMessageStartTime
13222
+ );
13028
13223
  state.currentMessages.push(message);
13029
13224
  }
13030
13225
  if (message.type !== "result" || !message.usage) {
@@ -13171,10 +13366,35 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
13171
13366
  const localToolContext = createClaudeLocalToolContext();
13172
13367
  const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
13173
13368
  const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
13174
- const resolveToolUseParentSpan = async (toolUseID) => {
13175
- const parentToolUseId = toolUseToParent.get(toolUseID) ?? null;
13369
+ const resolveToolUseParentSpan = async (toolUseID, context) => {
13370
+ const trackedParentToolUseId = toolUseToParent.get(toolUseID);
13371
+ const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
13176
13372
  const parentKey = llmParentKey(parentToolUseId);
13177
13373
  const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
13374
+ if (context?.preferTaskSiblingParent) {
13375
+ if (!activeLlmSpan) {
13376
+ await ensureActiveLlmSpanForParentToolUse(
13377
+ span,
13378
+ activeLlmSpansByParentToolUse,
13379
+ subAgentDetailsByToolUseId,
13380
+ activeToolSpans,
13381
+ subAgentSpans,
13382
+ parentToolUseId,
13383
+ getCurrentUnixTimestamp()
13384
+ );
13385
+ }
13386
+ if (parentToolUseId) {
13387
+ const subAgentSpan = await ensureSubAgentSpan(
13388
+ subAgentDetailsByToolUseId,
13389
+ span,
13390
+ activeToolSpans,
13391
+ subAgentSpans,
13392
+ parentToolUseId
13393
+ );
13394
+ return subAgentSpan.export();
13395
+ }
13396
+ return span.export();
13397
+ }
13178
13398
  if (activeLlmSpan) {
13179
13399
  return activeLlmSpan.export();
13180
13400
  }
@@ -13302,135 +13522,1013 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
13302
13522
  }
13303
13523
  };
13304
13524
 
13305
- // src/instrumentation/plugins/google-genai-channels.ts
13306
- var googleGenAIChannels = defineChannels("@google/genai", {
13307
- generateContent: channel({
13308
- channelName: "models.generateContent",
13525
+ // src/instrumentation/plugins/cursor-sdk-channels.ts
13526
+ var cursorSDKChannels = defineChannels("@cursor/sdk", {
13527
+ create: channel({
13528
+ channelName: "Agent.create",
13309
13529
  kind: "async"
13310
13530
  }),
13311
- generateContentStream: channel({
13312
- channelName: "models.generateContentStream",
13531
+ resume: channel({
13532
+ channelName: "Agent.resume",
13313
13533
  kind: "async"
13314
13534
  }),
13315
- embedContent: channel({
13316
- channelName: "models.embedContent",
13535
+ prompt: channel({
13536
+ channelName: "Agent.prompt",
13537
+ kind: "async"
13538
+ }),
13539
+ send: channel({
13540
+ channelName: "agent.send",
13317
13541
  kind: "async"
13318
13542
  })
13319
13543
  });
13320
13544
 
13321
- // src/instrumentation/plugins/google-genai-plugin.ts
13322
- var GOOGLE_GENAI_INTERNAL_CONTEXT = {
13323
- caller_filename: "<node-internal>",
13324
- caller_functionname: "<node-internal>",
13325
- caller_lineno: 0
13326
- };
13327
- function createWrapperParityEvent(args) {
13328
- return {
13329
- context: GOOGLE_GENAI_INTERNAL_CONTEXT,
13330
- input: args.input,
13331
- metadata: args.metadata
13332
- };
13333
- }
13334
- var GoogleGenAIPlugin = class extends BasePlugin {
13545
+ // src/instrumentation/plugins/cursor-sdk-plugin.ts
13546
+ var PATCHED_AGENT = Symbol.for("braintrust.cursor-sdk.auto-patched-agent");
13547
+ var PATCHED_RUN = Symbol.for("braintrust.cursor-sdk.patched-run");
13548
+ var WRAPPED_AGENT = Symbol.for("braintrust.cursor-sdk.wrapped-agent");
13549
+ var CursorSDKPlugin = class extends BasePlugin {
13550
+ promptDepth = 0;
13335
13551
  onEnable() {
13336
- this.subscribeToGoogleGenAIChannels();
13552
+ this.subscribeToAgentFactories();
13553
+ this.subscribeToPrompt();
13554
+ this.subscribeToSend();
13337
13555
  }
13338
13556
  onDisable() {
13339
- this.unsubscribers = unsubscribeAll(this.unsubscribers);
13557
+ for (const unsubscribe of this.unsubscribers) {
13558
+ unsubscribe();
13559
+ }
13560
+ this.unsubscribers = [];
13561
+ this.promptDepth = 0;
13340
13562
  }
13341
- subscribeToGoogleGenAIChannels() {
13342
- this.subscribeToGenerateContentChannel();
13343
- this.subscribeToGenerateContentStreamChannel();
13344
- this.subscribeToEmbedContentChannel();
13563
+ subscribeToAgentFactories() {
13564
+ this.subscribeToAgentFactory(cursorSDKChannels.create);
13565
+ this.subscribeToAgentFactory(cursorSDKChannels.resume);
13345
13566
  }
13346
- subscribeToGenerateContentChannel() {
13347
- const tracingChannel = googleGenAIChannels.generateContent.tracingChannel();
13348
- const states = /* @__PURE__ */ new WeakMap();
13349
- const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
13350
- tracingChannel,
13351
- states,
13352
- (event) => {
13353
- const params = event.arguments[0];
13354
- const input = serializeGenerateContentInput(params);
13355
- const metadata = extractGenerateContentMetadata(params);
13356
- const span = startSpan({
13357
- name: "generate_content",
13358
- spanAttributes: {
13359
- type: "llm" /* LLM */
13360
- },
13361
- event: createWrapperParityEvent({ input, metadata })
13362
- });
13363
- return {
13364
- span,
13365
- startTime: getCurrentUnixTimestamp()
13366
- };
13567
+ subscribeToAgentFactory(channel2) {
13568
+ const tracingChannel = channel2.tracingChannel();
13569
+ const handlers = {
13570
+ asyncEnd: (event) => {
13571
+ patchCursorAgentInPlace(event.result);
13572
+ },
13573
+ error: () => {
13367
13574
  }
13368
- );
13575
+ };
13576
+ tracingChannel.subscribe(handlers);
13577
+ this.unsubscribers.push(() => {
13578
+ tracingChannel.unsubscribe(handlers);
13579
+ });
13580
+ }
13581
+ subscribeToPrompt() {
13582
+ const channel2 = cursorSDKChannels.prompt.tracingChannel();
13583
+ const states = /* @__PURE__ */ new WeakMap();
13369
13584
  const handlers = {
13370
13585
  start: (event) => {
13371
- ensureSpanState(states, event, () => {
13372
- const params = event.arguments[0];
13373
- const input = serializeGenerateContentInput(params);
13374
- const metadata = extractGenerateContentMetadata(params);
13375
- const span = startSpan({
13376
- name: "generate_content",
13377
- spanAttributes: {
13378
- type: "llm" /* LLM */
13379
- },
13380
- event: createWrapperParityEvent({ input, metadata })
13381
- });
13382
- return {
13383
- span,
13384
- startTime: getCurrentUnixTimestamp()
13385
- };
13586
+ this.promptDepth += 1;
13587
+ const message = event.arguments[0];
13588
+ const options = event.arguments[1];
13589
+ const metadata = {
13590
+ ...extractAgentOptionsMetadata(options),
13591
+ "cursor_sdk.operation": "Agent.prompt",
13592
+ provider: "cursor",
13593
+ ...event.moduleVersion ? { "cursor_sdk.version": event.moduleVersion } : {}
13594
+ };
13595
+ const span = startSpan({
13596
+ name: "Cursor Agent",
13597
+ spanAttributes: { type: "task" /* TASK */ }
13386
13598
  });
13599
+ const startTime = getCurrentUnixTimestamp();
13600
+ safeLog(span, {
13601
+ input: sanitizeUserMessage(message),
13602
+ metadata
13603
+ });
13604
+ states.set(event, { metadata, span, startTime });
13387
13605
  },
13388
13606
  asyncEnd: (event) => {
13389
- const spanState = states.get(event);
13390
- if (!spanState) {
13607
+ this.promptDepth = Math.max(0, this.promptDepth - 1);
13608
+ const state = states.get(event);
13609
+ if (!state) {
13391
13610
  return;
13392
13611
  }
13393
13612
  try {
13394
- const responseMetadata = extractResponseMetadata(event.result);
13395
- spanState.span.log({
13396
- ...responseMetadata ? { metadata: responseMetadata } : {},
13397
- metrics: cleanMetrics(
13398
- extractGenerateContentMetrics(
13399
- event.result,
13400
- spanState.startTime
13401
- )
13402
- ),
13403
- output: event.result
13613
+ safeLog(state.span, {
13614
+ metadata: {
13615
+ ...state.metadata,
13616
+ ...extractRunResultMetadata(event.result)
13617
+ },
13618
+ metrics: buildDurationMetrics(state.startTime),
13619
+ output: event.result?.result ?? event.result
13404
13620
  });
13405
13621
  } finally {
13406
- spanState.span.end();
13622
+ state.span.end();
13407
13623
  states.delete(event);
13408
13624
  }
13409
13625
  },
13410
13626
  error: (event) => {
13411
- logErrorAndEndSpan(states, event);
13627
+ this.promptDepth = Math.max(0, this.promptDepth - 1);
13628
+ const state = states.get(event);
13629
+ if (!state || !event.error) {
13630
+ return;
13631
+ }
13632
+ safeLog(state.span, { error: event.error.message });
13633
+ state.span.end();
13634
+ states.delete(event);
13412
13635
  }
13413
13636
  };
13414
- tracingChannel.subscribe(handlers);
13637
+ channel2.subscribe(handlers);
13415
13638
  this.unsubscribers.push(() => {
13416
- unbindCurrentSpanStore?.();
13417
- tracingChannel.unsubscribe(handlers);
13639
+ channel2.unsubscribe(handlers);
13418
13640
  });
13419
13641
  }
13420
- subscribeToGenerateContentStreamChannel() {
13421
- const tracingChannel = googleGenAIChannels.generateContentStream.tracingChannel();
13642
+ subscribeToSend() {
13643
+ const channel2 = cursorSDKChannels.send.tracingChannel();
13644
+ const states = /* @__PURE__ */ new WeakMap();
13422
13645
  const handlers = {
13423
13646
  start: (event) => {
13424
- const streamEvent = event;
13425
- const params = event.arguments[0];
13426
- streamEvent.googleGenAIInput = serializeGenerateContentInput(params);
13427
- streamEvent.googleGenAIMetadata = extractGenerateContentMetadata(params);
13428
- streamEvent.googleGenAIStartTime = getCurrentUnixTimestamp();
13647
+ if (this.promptDepth > 0) {
13648
+ return;
13649
+ }
13650
+ const message = event.arguments[0];
13651
+ const sendOptions = event.arguments[1];
13652
+ const agent = event.agent;
13653
+ const metadata = {
13654
+ ...extractSendMetadata(sendOptions),
13655
+ ...agent ? extractAgentMetadata(agent) : {},
13656
+ "cursor_sdk.operation": "agent.send",
13657
+ provider: "cursor",
13658
+ ...event.moduleVersion ? { "cursor_sdk.version": event.moduleVersion } : {}
13659
+ };
13660
+ const span = startSpan({
13661
+ name: "Cursor Agent",
13662
+ spanAttributes: { type: "task" /* TASK */ }
13663
+ });
13664
+ const startTime = getCurrentUnixTimestamp();
13665
+ safeLog(span, {
13666
+ input: sanitizeUserMessage(message),
13667
+ metadata
13668
+ });
13669
+ const state = {
13670
+ activeToolSpans: /* @__PURE__ */ new Map(),
13671
+ agent,
13672
+ conversationText: [],
13673
+ deltaText: [],
13674
+ finalized: false,
13675
+ input: message,
13676
+ metadata,
13677
+ metrics: {},
13678
+ span,
13679
+ startTime,
13680
+ streamMessages: [],
13681
+ streamText: [],
13682
+ stepText: [],
13683
+ taskText: []
13684
+ };
13685
+ if (hasCursorCallbacks(sendOptions)) {
13686
+ event.arguments[1] = wrapSendOptionsCallbacks(sendOptions, state);
13687
+ }
13688
+ states.set(event, state);
13429
13689
  },
13430
13690
  asyncEnd: (event) => {
13431
- const streamEvent = event;
13432
- patchGoogleGenAIStreamingResult({
13433
- input: streamEvent.googleGenAIInput,
13691
+ const state = states.get(event);
13692
+ if (!state) {
13693
+ return;
13694
+ }
13695
+ if (!event.result) {
13696
+ return;
13697
+ }
13698
+ state.run = event.result;
13699
+ state.metadata = {
13700
+ ...state.metadata,
13701
+ ...extractRunMetadata(event.result)
13702
+ };
13703
+ patchCursorRun(event.result, state);
13704
+ },
13705
+ error: (event) => {
13706
+ const state = states.get(event);
13707
+ if (!state || !event.error) {
13708
+ return;
13709
+ }
13710
+ safeLog(state.span, { error: event.error.message });
13711
+ endOpenToolSpans(state, event.error.message);
13712
+ state.span.end();
13713
+ state.finalized = true;
13714
+ states.delete(event);
13715
+ }
13716
+ };
13717
+ channel2.subscribe(handlers);
13718
+ this.unsubscribers.push(() => {
13719
+ channel2.unsubscribe(handlers);
13720
+ });
13721
+ }
13722
+ };
13723
+ function patchCursorAgentInPlace(agent) {
13724
+ if (!agent || typeof agent !== "object") {
13725
+ return;
13726
+ }
13727
+ const agentRecord = agent;
13728
+ if (agentRecord[PATCHED_AGENT] || agentRecord[WRAPPED_AGENT] || typeof agentRecord.send !== "function") {
13729
+ return;
13730
+ }
13731
+ const originalSend = agentRecord.send.bind(agentRecord);
13732
+ try {
13733
+ Object.defineProperty(agentRecord, PATCHED_AGENT, {
13734
+ configurable: false,
13735
+ enumerable: false,
13736
+ value: true
13737
+ });
13738
+ Object.defineProperty(agentRecord, "send", {
13739
+ configurable: true,
13740
+ value(message, options) {
13741
+ const args = [message, options];
13742
+ return cursorSDKChannels.send.tracePromise(
13743
+ () => originalSend(...args),
13744
+ {
13745
+ agent: agentRecord,
13746
+ arguments: args,
13747
+ operation: "send"
13748
+ }
13749
+ );
13750
+ },
13751
+ writable: true
13752
+ });
13753
+ } catch {
13754
+ }
13755
+ }
13756
+ function wrapSendOptionsCallbacks(options, state) {
13757
+ const originalOnDelta = options.onDelta;
13758
+ const originalOnStep = options.onStep;
13759
+ return {
13760
+ ...options,
13761
+ async onDelta(args) {
13762
+ try {
13763
+ await handleInteractionUpdate(state, args.update);
13764
+ } catch (error) {
13765
+ logInstrumentationError("Cursor SDK onDelta", error);
13766
+ }
13767
+ if (originalOnDelta) {
13768
+ return originalOnDelta(args);
13769
+ }
13770
+ },
13771
+ async onStep(args) {
13772
+ try {
13773
+ handleStepUpdate(state, args.step);
13774
+ } catch (error) {
13775
+ logInstrumentationError("Cursor SDK onStep", error);
13776
+ }
13777
+ if (originalOnStep) {
13778
+ return originalOnStep(args);
13779
+ }
13780
+ }
13781
+ };
13782
+ }
13783
+ function hasCursorCallbacks(options) {
13784
+ return !!options && (typeof options.onDelta === "function" || typeof options.onStep === "function");
13785
+ }
13786
+ function patchCursorRun(run, state) {
13787
+ if (!run || typeof run !== "object") {
13788
+ return;
13789
+ }
13790
+ const runRecord = run;
13791
+ if (runRecord[PATCHED_RUN]) {
13792
+ return;
13793
+ }
13794
+ try {
13795
+ Object.defineProperty(runRecord, PATCHED_RUN, {
13796
+ configurable: false,
13797
+ enumerable: false,
13798
+ value: true
13799
+ });
13800
+ if (typeof runRecord.stream === "function") {
13801
+ const originalStream = runRecord.stream.bind(runRecord);
13802
+ Object.defineProperty(runRecord, "stream", {
13803
+ configurable: true,
13804
+ value() {
13805
+ const stream = originalStream();
13806
+ return patchCursorStream(stream, state);
13807
+ },
13808
+ writable: true
13809
+ });
13810
+ }
13811
+ if (typeof runRecord.wait === "function") {
13812
+ const originalWait = runRecord.wait.bind(runRecord);
13813
+ Object.defineProperty(runRecord, "wait", {
13814
+ configurable: true,
13815
+ async value() {
13816
+ try {
13817
+ const result = await originalWait();
13818
+ state.lastResult = result;
13819
+ await finalizeCursorRun(state, { result });
13820
+ return result;
13821
+ } catch (error) {
13822
+ await finalizeCursorRun(state, { error });
13823
+ throw error;
13824
+ }
13825
+ },
13826
+ writable: true
13827
+ });
13828
+ }
13829
+ if (typeof runRecord.conversation === "function") {
13830
+ const originalConversation = runRecord.conversation.bind(runRecord);
13831
+ Object.defineProperty(runRecord, "conversation", {
13832
+ configurable: true,
13833
+ async value() {
13834
+ try {
13835
+ const conversation = await originalConversation();
13836
+ await handleConversation(state, conversation);
13837
+ await finalizeCursorRun(state);
13838
+ return conversation;
13839
+ } catch (error) {
13840
+ await finalizeCursorRun(state, { error });
13841
+ throw error;
13842
+ }
13843
+ },
13844
+ writable: true
13845
+ });
13846
+ }
13847
+ } catch {
13848
+ void finalizeCursorRun(state, { output: run });
13849
+ }
13850
+ }
13851
+ async function* patchCursorStream(stream, state) {
13852
+ try {
13853
+ for await (const message of stream) {
13854
+ try {
13855
+ await handleStreamMessage2(state, message);
13856
+ } catch (error) {
13857
+ logInstrumentationError("Cursor SDK stream", error);
13858
+ }
13859
+ yield message;
13860
+ }
13861
+ await finalizeCursorRun(state);
13862
+ } catch (error) {
13863
+ await finalizeCursorRun(state, { error });
13864
+ throw error;
13865
+ }
13866
+ }
13867
+ async function handleInteractionUpdate(state, update) {
13868
+ switch (update.type) {
13869
+ case "text-delta":
13870
+ if (typeof update.text === "string") {
13871
+ state.deltaText.push(update.text);
13872
+ }
13873
+ return;
13874
+ case "token-delta":
13875
+ if (typeof update.tokens === "number") {
13876
+ state.metrics["cursor_sdk.delta_tokens"] = (state.metrics["cursor_sdk.delta_tokens"] ?? 0) + update.tokens;
13877
+ }
13878
+ return;
13879
+ case "tool-call-started":
13880
+ case "partial-tool-call":
13881
+ case "tool-call-completed":
13882
+ await handleToolUpdate(
13883
+ state,
13884
+ update
13885
+ );
13886
+ return;
13887
+ case "turn-ended":
13888
+ addUsageMetrics(
13889
+ state.metrics,
13890
+ update.usage
13891
+ );
13892
+ return;
13893
+ case "summary":
13894
+ if (typeof update.summary === "string") {
13895
+ state.taskText.push(update.summary);
13896
+ }
13897
+ return;
13898
+ case "step-completed":
13899
+ if (typeof update.stepDurationMs === "number") {
13900
+ state.metrics["cursor_sdk.step_duration_ms"] = (state.metrics["cursor_sdk.step_duration_ms"] ?? 0) + update.stepDurationMs;
13901
+ }
13902
+ state.metrics["cursor_sdk.steps"] = (state.metrics["cursor_sdk.steps"] ?? 0) + 1;
13903
+ return;
13904
+ default:
13905
+ return;
13906
+ }
13907
+ }
13908
+ async function handleToolUpdate(state, update) {
13909
+ const callId = update.callId;
13910
+ if (!callId) {
13911
+ return;
13912
+ }
13913
+ const toolCall = update.toolCall;
13914
+ const name = extractToolName(toolCall);
13915
+ const args = extractToolArgs(toolCall);
13916
+ const result = extractToolResult(toolCall);
13917
+ if (update.type === "tool-call-started" || update.type === "partial-tool-call") {
13918
+ if (!state.activeToolSpans.has(callId)) {
13919
+ state.activeToolSpans.set(
13920
+ callId,
13921
+ await startToolSpan(state, {
13922
+ args,
13923
+ callId,
13924
+ name,
13925
+ status: "running",
13926
+ toolCall
13927
+ })
13928
+ );
13929
+ }
13930
+ return;
13931
+ }
13932
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
13933
+ args,
13934
+ callId,
13935
+ name,
13936
+ status: "completed",
13937
+ toolCall
13938
+ });
13939
+ finishToolSpan(toolState, {
13940
+ error: toolCall?.status === "error" ? stringifyUnknown(result) : void 0,
13941
+ metadata: {
13942
+ "cursor_sdk.tool.status": toolCall?.status ?? "completed"
13943
+ },
13944
+ output: result
13945
+ });
13946
+ state.activeToolSpans.delete(callId);
13947
+ }
13948
+ async function handleStreamMessage2(state, message) {
13949
+ state.streamMessages.push(message);
13950
+ if (message.type === "system") {
13951
+ const systemMessage = message;
13952
+ state.metadata = {
13953
+ ...state.metadata,
13954
+ ...extractModelMetadata(systemMessage.model),
13955
+ ...systemMessage.agent_id ? { "cursor_sdk.agent_id": systemMessage.agent_id } : {},
13956
+ ...systemMessage.run_id ? { "cursor_sdk.run_id": systemMessage.run_id } : {},
13957
+ ...systemMessage.tools ? { "cursor_sdk.tools": systemMessage.tools } : {}
13958
+ };
13959
+ return;
13960
+ }
13961
+ if (message.type === "assistant") {
13962
+ const assistantMessage = message;
13963
+ for (const block of assistantMessage.message?.content ?? []) {
13964
+ if (block?.type === "text" && typeof block.text === "string") {
13965
+ state.streamText.push(block.text);
13966
+ } else if (block?.type === "tool_use" && block.id) {
13967
+ state.activeToolSpans.set(
13968
+ block.id,
13969
+ await startToolSpan(state, {
13970
+ args: block.input,
13971
+ callId: block.id,
13972
+ name: block.name,
13973
+ status: "running"
13974
+ })
13975
+ );
13976
+ }
13977
+ }
13978
+ return;
13979
+ }
13980
+ if (message.type === "tool_call") {
13981
+ await handleToolMessage(
13982
+ state,
13983
+ message
13984
+ );
13985
+ return;
13986
+ }
13987
+ if (message.type === "task" && typeof message.text === "string") {
13988
+ state.taskText.push(message.text);
13989
+ return;
13990
+ }
13991
+ if (message.type === "status" && message.status) {
13992
+ state.metadata["cursor_sdk.status"] = message.status;
13993
+ }
13994
+ }
13995
+ async function handleToolMessage(state, message) {
13996
+ const callId = message.call_id;
13997
+ if (!callId) {
13998
+ return;
13999
+ }
14000
+ if (message.status === "running") {
14001
+ if (!state.activeToolSpans.has(callId)) {
14002
+ state.activeToolSpans.set(
14003
+ callId,
14004
+ await startToolSpan(state, {
14005
+ args: message.args,
14006
+ callId,
14007
+ name: message.name,
14008
+ status: message.status,
14009
+ truncated: message.truncated
14010
+ })
14011
+ );
14012
+ }
14013
+ return;
14014
+ }
14015
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
14016
+ args: message.args,
14017
+ callId,
14018
+ name: message.name,
14019
+ status: message.status,
14020
+ truncated: message.truncated
14021
+ });
14022
+ finishToolSpan(toolState, {
14023
+ error: message.status === "error" ? stringifyUnknown(message.result) : void 0,
14024
+ metadata: {
14025
+ "cursor_sdk.tool.status": message.status
14026
+ },
14027
+ output: message.result
14028
+ });
14029
+ state.activeToolSpans.delete(callId);
14030
+ }
14031
+ async function handleConversation(state, turns) {
14032
+ state.conversationOutput = turns;
14033
+ for (const turn of turns) {
14034
+ if (turn.type === "agentConversationTurn") {
14035
+ for (const step of turn.turn?.steps ?? []) {
14036
+ await handleConversationStep(state, step);
14037
+ }
14038
+ } else if (turn.type === "shellConversationTurn") {
14039
+ const command = turn.turn?.shellCommand?.command;
14040
+ if (command) {
14041
+ const callId = `shell:${state.activeToolSpans.size}:${command}`;
14042
+ const toolState = await startToolSpan(state, {
14043
+ args: turn.turn?.shellCommand,
14044
+ callId,
14045
+ name: "shell",
14046
+ status: "completed"
14047
+ });
14048
+ finishToolSpan(toolState, {
14049
+ metadata: { "cursor_sdk.tool.status": "completed" },
14050
+ output: turn.turn?.shellOutput
14051
+ });
14052
+ }
14053
+ }
14054
+ }
14055
+ }
14056
+ async function handleConversationStep(state, step) {
14057
+ if (step.type === "assistantMessage" && typeof step.message?.text === "string") {
14058
+ state.conversationText.push(step.message.text);
14059
+ return;
14060
+ }
14061
+ if (step.type !== "toolCall") {
14062
+ return;
14063
+ }
14064
+ const toolCall = step.message;
14065
+ const callId = typeof toolCall?.callId === "string" ? toolCall.callId : `conversation-tool:${state.activeToolSpans.size}`;
14066
+ const toolState = await startToolSpan(state, {
14067
+ args: extractToolArgs(toolCall),
14068
+ callId,
14069
+ name: extractToolName(toolCall),
14070
+ status: toolCall?.status,
14071
+ toolCall
14072
+ });
14073
+ finishToolSpan(toolState, {
14074
+ error: toolCall?.status === "error" ? stringifyUnknown(toolCall.result) : void 0,
14075
+ metadata: {
14076
+ "cursor_sdk.tool.status": toolCall?.status ?? "completed"
14077
+ },
14078
+ output: extractToolResult(toolCall)
14079
+ });
14080
+ }
14081
+ function handleStepUpdate(state, step) {
14082
+ state.metrics["cursor_sdk.steps"] = (state.metrics["cursor_sdk.steps"] ?? 0) + 1;
14083
+ if (step.type) {
14084
+ const stepTypes = state.metadata["cursor_sdk.step_types"];
14085
+ if (Array.isArray(stepTypes)) {
14086
+ if (!stepTypes.includes(step.type)) {
14087
+ stepTypes.push(step.type);
14088
+ }
14089
+ } else {
14090
+ state.metadata["cursor_sdk.step_types"] = [step.type];
14091
+ }
14092
+ }
14093
+ if (step.type === "assistantMessage" && typeof step.message?.text === "string") {
14094
+ state.stepText.push(step.message.text);
14095
+ }
14096
+ }
14097
+ async function startToolSpan(state, args) {
14098
+ const name = args.name || "unknown";
14099
+ const metadata = {
14100
+ "cursor_sdk.tool.status": args.status,
14101
+ "gen_ai.tool.call.id": args.callId,
14102
+ "gen_ai.tool.name": name
14103
+ };
14104
+ if (args.truncated?.args !== void 0) {
14105
+ metadata["cursor_sdk.tool.args_truncated"] = args.truncated.args;
14106
+ }
14107
+ if (args.truncated?.result !== void 0) {
14108
+ metadata["cursor_sdk.tool.result_truncated"] = args.truncated.result;
14109
+ }
14110
+ const span = startSpan({
14111
+ event: {
14112
+ input: args.args,
14113
+ metadata
14114
+ },
14115
+ name: `tool: ${name}`,
14116
+ parent: await state.span.export(),
14117
+ spanAttributes: { type: "tool" /* TOOL */ }
14118
+ });
14119
+ let subAgentSpan;
14120
+ if (isSubAgentToolName(name)) {
14121
+ subAgentSpan = startSpan({
14122
+ event: {
14123
+ input: args.args,
14124
+ metadata: {
14125
+ "cursor_sdk.subagent.tool_call_id": args.callId,
14126
+ "gen_ai.tool.name": name
14127
+ }
14128
+ },
14129
+ name: formatSubAgentSpanName2(args.toolCall, args.args),
14130
+ parent: await span.export(),
14131
+ spanAttributes: { type: "task" /* TASK */ }
14132
+ });
14133
+ }
14134
+ return { span, subAgentSpan };
14135
+ }
14136
+ function finishToolSpan(toolState, result) {
14137
+ try {
14138
+ if (result.error) {
14139
+ safeLog(toolState.span, {
14140
+ error: result.error,
14141
+ metadata: result.metadata,
14142
+ output: result.output
14143
+ });
14144
+ if (toolState.subAgentSpan) {
14145
+ safeLog(toolState.subAgentSpan, {
14146
+ error: result.error,
14147
+ metadata: result.metadata,
14148
+ output: result.output
14149
+ });
14150
+ }
14151
+ } else {
14152
+ safeLog(toolState.span, {
14153
+ metadata: result.metadata,
14154
+ output: result.output
14155
+ });
14156
+ if (toolState.subAgentSpan) {
14157
+ safeLog(toolState.subAgentSpan, {
14158
+ metadata: result.metadata,
14159
+ output: result.output
14160
+ });
14161
+ }
14162
+ }
14163
+ } finally {
14164
+ toolState.subAgentSpan?.end();
14165
+ toolState.span.end();
14166
+ }
14167
+ }
14168
+ async function finalizeCursorRun(state, params = {}) {
14169
+ if (state.finalized) {
14170
+ return;
14171
+ }
14172
+ state.finalized = true;
14173
+ const error = params.error;
14174
+ const result = params.result ?? state.lastResult;
14175
+ 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);
14176
+ try {
14177
+ const metadata = {
14178
+ ...state.metadata,
14179
+ ...state.run ? extractRunMetadata(state.run) : {},
14180
+ ...result ? extractRunResultMetadata(result) : {}
14181
+ };
14182
+ if (error) {
14183
+ safeLog(state.span, {
14184
+ error: error instanceof Error ? error.message : String(error),
14185
+ metadata,
14186
+ metrics: {
14187
+ ...cleanMetrics(state.metrics),
14188
+ ...buildDurationMetrics(state.startTime)
14189
+ },
14190
+ output
14191
+ });
14192
+ } else {
14193
+ safeLog(state.span, {
14194
+ metadata,
14195
+ metrics: {
14196
+ ...cleanMetrics(state.metrics),
14197
+ ...buildDurationMetrics(state.startTime)
14198
+ },
14199
+ output
14200
+ });
14201
+ }
14202
+ } finally {
14203
+ endOpenToolSpans(state);
14204
+ state.span.end();
14205
+ }
14206
+ }
14207
+ function endOpenToolSpans(state, error) {
14208
+ for (const [, toolState] of state.activeToolSpans) {
14209
+ finishToolSpan(toolState, { error });
14210
+ }
14211
+ state.activeToolSpans.clear();
14212
+ }
14213
+ function sanitizeUserMessage(message) {
14214
+ if (typeof message === "string" || message === void 0) {
14215
+ return message;
14216
+ }
14217
+ return {
14218
+ ...message,
14219
+ images: message.images?.map((image) => {
14220
+ const imageRecord = image;
14221
+ return {
14222
+ ...typeof imageRecord.url === "string" ? { url: imageRecord.url } : {},
14223
+ ...typeof imageRecord.mimeType === "string" ? { mimeType: imageRecord.mimeType } : {},
14224
+ ...image.dimension ? { dimension: image.dimension } : {},
14225
+ hasData: typeof imageRecord.data === "string"
14226
+ };
14227
+ })
14228
+ };
14229
+ }
14230
+ function extractAgentOptionsMetadata(options) {
14231
+ if (!options) {
14232
+ return {};
14233
+ }
14234
+ return {
14235
+ ...extractModelMetadata(options.model),
14236
+ ...options.agentId ? { "cursor_sdk.agent_id": options.agentId } : {},
14237
+ ...options.name ? { "cursor_sdk.agent_name": options.name } : {},
14238
+ ...options.local ? {
14239
+ "cursor_sdk.runtime": "local",
14240
+ "cursor_sdk.local.cwd": Array.isArray(options.local.cwd) ? options.local.cwd.join(",") : options.local.cwd
14241
+ } : {},
14242
+ ...options.cloud ? {
14243
+ "cursor_sdk.runtime": "cloud",
14244
+ "cursor_sdk.cloud.auto_create_pr": options.cloud.autoCreatePR,
14245
+ "cursor_sdk.cloud.env_type": options.cloud.env?.type,
14246
+ "cursor_sdk.cloud.env_name": options.cloud.env?.name,
14247
+ "cursor_sdk.cloud.repos": options.cloud.repos?.map((repo) => repo.url).filter((url) => typeof url === "string")
14248
+ } : {}
14249
+ };
14250
+ }
14251
+ function extractSendMetadata(options) {
14252
+ if (!options) {
14253
+ return {};
14254
+ }
14255
+ return {
14256
+ ...extractModelMetadata(options.model),
14257
+ ...options.local?.force !== void 0 ? { "cursor_sdk.local.force": options.local.force } : {}
14258
+ };
14259
+ }
14260
+ function extractAgentMetadata(agent) {
14261
+ return {
14262
+ ...agent.agentId ? { "cursor_sdk.agent_id": agent.agentId } : {},
14263
+ ...extractModelMetadata(agent.model)
14264
+ };
14265
+ }
14266
+ function extractRunMetadata(run) {
14267
+ if (!run) {
14268
+ return {};
14269
+ }
14270
+ return {
14271
+ ...run.id ? { "cursor_sdk.run_id": run.id } : {},
14272
+ ...run.agentId ? { "cursor_sdk.agent_id": run.agentId } : {},
14273
+ ...run.status ? { "cursor_sdk.status": run.status } : {},
14274
+ ...run.durationMs !== void 0 ? { "cursor_sdk.duration_ms": run.durationMs } : {},
14275
+ ...extractModelMetadata(run.model),
14276
+ ...extractGitMetadata(run.git)
14277
+ };
14278
+ }
14279
+ function extractRunResultMetadata(result) {
14280
+ if (!result) {
14281
+ return {};
14282
+ }
14283
+ return {
14284
+ ...result.id ? { "cursor_sdk.run_id": result.id } : {},
14285
+ ...result.status ? { "cursor_sdk.status": result.status } : {},
14286
+ ...result.durationMs !== void 0 ? { "cursor_sdk.duration_ms": result.durationMs } : {},
14287
+ ...extractModelMetadata(result.model),
14288
+ ...extractGitMetadata(result.git)
14289
+ };
14290
+ }
14291
+ function extractGitMetadata(git) {
14292
+ const branches = git?.branches;
14293
+ if (!branches || branches.length === 0) {
14294
+ return {};
14295
+ }
14296
+ return {
14297
+ "cursor_sdk.git.branches": branches.map((branch) => ({
14298
+ branch: branch.branch,
14299
+ prUrl: branch.prUrl,
14300
+ repoUrl: branch.repoUrl
14301
+ }))
14302
+ };
14303
+ }
14304
+ function extractModelMetadata(model) {
14305
+ if (!model?.id) {
14306
+ return {};
14307
+ }
14308
+ return {
14309
+ model: model.id,
14310
+ "cursor_sdk.model": model.id,
14311
+ ...model.params ? { "cursor_sdk.model.params": model.params } : {}
14312
+ };
14313
+ }
14314
+ function addUsageMetrics(metrics, usage) {
14315
+ if (!usage) {
14316
+ return;
14317
+ }
14318
+ if (usage.inputTokens !== void 0) {
14319
+ metrics.prompt_tokens = (metrics.prompt_tokens ?? 0) + usage.inputTokens;
14320
+ }
14321
+ if (usage.outputTokens !== void 0) {
14322
+ metrics.completion_tokens = (metrics.completion_tokens ?? 0) + usage.outputTokens;
14323
+ }
14324
+ if (usage.cacheReadTokens !== void 0) {
14325
+ metrics.prompt_cached_tokens = (metrics.prompt_cached_tokens ?? 0) + usage.cacheReadTokens;
14326
+ }
14327
+ if (usage.cacheWriteTokens !== void 0) {
14328
+ metrics.prompt_cache_creation_tokens = (metrics.prompt_cache_creation_tokens ?? 0) + usage.cacheWriteTokens;
14329
+ }
14330
+ metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0) + (metrics.prompt_cached_tokens ?? 0) + (metrics.prompt_cache_creation_tokens ?? 0);
14331
+ }
14332
+ function buildDurationMetrics(startTime) {
14333
+ const end = getCurrentUnixTimestamp();
14334
+ return {
14335
+ duration: end - startTime,
14336
+ end,
14337
+ start: startTime
14338
+ };
14339
+ }
14340
+ function extractToolName(toolCall) {
14341
+ if (!toolCall) {
14342
+ return "unknown";
14343
+ }
14344
+ if (typeof toolCall.name === "string") {
14345
+ return toolCall.name;
14346
+ }
14347
+ if (typeof toolCall.type === "string") {
14348
+ return toolCall.type;
14349
+ }
14350
+ return "unknown";
14351
+ }
14352
+ function extractToolArgs(toolCall) {
14353
+ return toolCall && "args" in toolCall ? toolCall.args : void 0;
14354
+ }
14355
+ function extractToolResult(toolCall) {
14356
+ return toolCall && "result" in toolCall ? toolCall.result : void 0;
14357
+ }
14358
+ function isSubAgentToolName(name) {
14359
+ return name === "Agent" || name === "Task" || name === "task";
14360
+ }
14361
+ function formatSubAgentSpanName2(toolCall, args) {
14362
+ const details = toolCall ?? args;
14363
+ const description = getString(details, "description") ?? getString(details, "subagent_type") ?? getString(details, "type") ?? getString(details, "name");
14364
+ return description ? `Agent: ${description}` : "Agent: sub-agent";
14365
+ }
14366
+ function getString(obj, key) {
14367
+ const value = obj?.[key];
14368
+ return typeof value === "string" ? value : void 0;
14369
+ }
14370
+ function stringifyUnknown(value) {
14371
+ if (value instanceof Error) {
14372
+ return value.message;
14373
+ }
14374
+ if (typeof value === "string") {
14375
+ return value;
14376
+ }
14377
+ try {
14378
+ return JSON.stringify(value);
14379
+ } catch {
14380
+ return String(value);
14381
+ }
14382
+ }
14383
+ function safeLog(span, event) {
14384
+ try {
14385
+ span.log(event);
14386
+ } catch (error) {
14387
+ logInstrumentationError("Cursor SDK span log", error);
14388
+ }
14389
+ }
14390
+ function logInstrumentationError(context, error) {
14391
+ debugLogger.error(`Error processing ${context}:`, error);
14392
+ }
14393
+ function cleanMetrics(metrics) {
14394
+ const cleaned = {};
14395
+ for (const [key, value] of Object.entries(metrics)) {
14396
+ if (value !== void 0 && Number.isFinite(value)) {
14397
+ cleaned[key] = value;
14398
+ }
14399
+ }
14400
+ return cleaned;
14401
+ }
14402
+
14403
+ // src/instrumentation/plugins/google-genai-channels.ts
14404
+ var googleGenAIChannels = defineChannels("@google/genai", {
14405
+ generateContent: channel({
14406
+ channelName: "models.generateContent",
14407
+ kind: "async"
14408
+ }),
14409
+ generateContentStream: channel({
14410
+ channelName: "models.generateContentStream",
14411
+ kind: "async"
14412
+ }),
14413
+ embedContent: channel({
14414
+ channelName: "models.embedContent",
14415
+ kind: "async"
14416
+ })
14417
+ });
14418
+
14419
+ // src/instrumentation/plugins/google-genai-plugin.ts
14420
+ var GOOGLE_GENAI_INTERNAL_CONTEXT = {
14421
+ caller_filename: "<node-internal>",
14422
+ caller_functionname: "<node-internal>",
14423
+ caller_lineno: 0
14424
+ };
14425
+ function createWrapperParityEvent(args) {
14426
+ return {
14427
+ context: GOOGLE_GENAI_INTERNAL_CONTEXT,
14428
+ input: args.input,
14429
+ metadata: args.metadata
14430
+ };
14431
+ }
14432
+ var GoogleGenAIPlugin = class extends BasePlugin {
14433
+ onEnable() {
14434
+ this.subscribeToGoogleGenAIChannels();
14435
+ }
14436
+ onDisable() {
14437
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
14438
+ }
14439
+ subscribeToGoogleGenAIChannels() {
14440
+ this.subscribeToGenerateContentChannel();
14441
+ this.subscribeToGenerateContentStreamChannel();
14442
+ this.subscribeToEmbedContentChannel();
14443
+ }
14444
+ subscribeToGenerateContentChannel() {
14445
+ const tracingChannel = googleGenAIChannels.generateContent.tracingChannel();
14446
+ const states = /* @__PURE__ */ new WeakMap();
14447
+ const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
14448
+ tracingChannel,
14449
+ states,
14450
+ (event) => {
14451
+ const params = event.arguments[0];
14452
+ const input = serializeGenerateContentInput(params);
14453
+ const metadata = extractGenerateContentMetadata(params);
14454
+ const span = startSpan({
14455
+ name: "generate_content",
14456
+ spanAttributes: {
14457
+ type: "llm" /* LLM */
14458
+ },
14459
+ event: createWrapperParityEvent({ input, metadata })
14460
+ });
14461
+ return {
14462
+ span,
14463
+ startTime: getCurrentUnixTimestamp()
14464
+ };
14465
+ }
14466
+ );
14467
+ const handlers = {
14468
+ start: (event) => {
14469
+ ensureSpanState(states, event, () => {
14470
+ const params = event.arguments[0];
14471
+ const input = serializeGenerateContentInput(params);
14472
+ const metadata = extractGenerateContentMetadata(params);
14473
+ const span = startSpan({
14474
+ name: "generate_content",
14475
+ spanAttributes: {
14476
+ type: "llm" /* LLM */
14477
+ },
14478
+ event: createWrapperParityEvent({ input, metadata })
14479
+ });
14480
+ return {
14481
+ span,
14482
+ startTime: getCurrentUnixTimestamp()
14483
+ };
14484
+ });
14485
+ },
14486
+ asyncEnd: (event) => {
14487
+ const spanState = states.get(event);
14488
+ if (!spanState) {
14489
+ return;
14490
+ }
14491
+ try {
14492
+ const responseMetadata = extractResponseMetadata(event.result);
14493
+ spanState.span.log({
14494
+ ...responseMetadata ? { metadata: responseMetadata } : {},
14495
+ metrics: cleanMetrics2(
14496
+ extractGenerateContentMetrics(
14497
+ event.result,
14498
+ spanState.startTime
14499
+ )
14500
+ ),
14501
+ output: event.result
14502
+ });
14503
+ } finally {
14504
+ spanState.span.end();
14505
+ states.delete(event);
14506
+ }
14507
+ },
14508
+ error: (event) => {
14509
+ logErrorAndEndSpan(states, event);
14510
+ }
14511
+ };
14512
+ tracingChannel.subscribe(handlers);
14513
+ this.unsubscribers.push(() => {
14514
+ unbindCurrentSpanStore?.();
14515
+ tracingChannel.unsubscribe(handlers);
14516
+ });
14517
+ }
14518
+ subscribeToGenerateContentStreamChannel() {
14519
+ const tracingChannel = googleGenAIChannels.generateContentStream.tracingChannel();
14520
+ const handlers = {
14521
+ start: (event) => {
14522
+ const streamEvent = event;
14523
+ const params = event.arguments[0];
14524
+ streamEvent.googleGenAIInput = serializeGenerateContentInput(params);
14525
+ streamEvent.googleGenAIMetadata = extractGenerateContentMetadata(params);
14526
+ streamEvent.googleGenAIStartTime = getCurrentUnixTimestamp();
14527
+ },
14528
+ asyncEnd: (event) => {
14529
+ const streamEvent = event;
14530
+ patchGoogleGenAIStreamingResult({
14531
+ input: streamEvent.googleGenAIInput,
13434
14532
  metadata: streamEvent.googleGenAIMetadata,
13435
14533
  startTime: streamEvent.googleGenAIStartTime,
13436
14534
  result: streamEvent.result
@@ -13495,7 +14593,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
13495
14593
  const output = summarizeEmbedContentOutput(event.result);
13496
14594
  spanState.span.log({
13497
14595
  ...output ? { output } : {},
13498
- metrics: cleanMetrics(
14596
+ metrics: cleanMetrics2(
13499
14597
  extractEmbedContentMetrics(event.result, spanState.startTime)
13500
14598
  )
13501
14599
  });
@@ -13592,7 +14690,7 @@ function patchGoogleGenAIStreamingResult(args) {
13592
14690
  );
13593
14691
  span.log({
13594
14692
  ...responseMetadata ? { metadata: responseMetadata } : {},
13595
- metrics: cleanMetrics(metricsWithoutEnd),
14693
+ metrics: cleanMetrics2(metricsWithoutEnd),
13596
14694
  output: options.result.aggregated
13597
14695
  });
13598
14696
  span.end(typeof end === "number" ? { endTime: end } : void 0);
@@ -14017,7 +15115,7 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
14017
15115
  }
14018
15116
  return { aggregated, metrics };
14019
15117
  }
14020
- function cleanMetrics(metrics) {
15118
+ function cleanMetrics2(metrics) {
14021
15119
  const cleaned = {};
14022
15120
  for (const [key, value] of Object.entries(metrics)) {
14023
15121
  if (value !== null && value !== void 0) {
@@ -14101,6 +15199,8 @@ var REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
14101
15199
  "stop",
14102
15200
  "stream",
14103
15201
  "temperature",
15202
+ "tool_choice",
15203
+ "tools",
14104
15204
  "top_p"
14105
15205
  ]);
14106
15206
  var RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
@@ -14363,7 +15463,10 @@ function aggregateChatCompletionChunks2(chunks) {
14363
15463
  for (const chunk of chunks) {
14364
15464
  for (const choice of chunk.choices ?? []) {
14365
15465
  const index = typeof choice.index === "number" ? choice.index : 0;
14366
- const existing = aggregatedChoices.get(index) ?? { content: "" };
15466
+ const existing = aggregatedChoices.get(index) ?? {
15467
+ content: "",
15468
+ toolCallsByIndex: /* @__PURE__ */ new Map()
15469
+ };
14367
15470
  const delta = isObject(choice.delta) ? choice.delta : void 0;
14368
15471
  const message = isObject(choice.message) ? choice.message : void 0;
14369
15472
  if (typeof delta?.content === "string") {
@@ -14379,6 +15482,10 @@ function aggregateChatCompletionChunks2(chunks) {
14379
15482
  if (choice.finish_reason !== void 0) {
14380
15483
  existing.finish_reason = choice.finish_reason;
14381
15484
  }
15485
+ const toolCallDeltas = getChatToolCallDeltas(delta) ?? getChatToolCallDeltas(message);
15486
+ if (toolCallDeltas) {
15487
+ mergeChatToolCallDeltas(existing.toolCallsByIndex, toolCallDeltas);
15488
+ }
14382
15489
  aggregatedChoices.set(index, existing);
14383
15490
  }
14384
15491
  }
@@ -14387,12 +15494,72 @@ function aggregateChatCompletionChunks2(chunks) {
14387
15494
  index,
14388
15495
  message: {
14389
15496
  content: choice.content,
14390
- role: choice.role ?? "assistant"
15497
+ role: choice.role ?? "assistant",
15498
+ ...choice.toolCallsByIndex.size > 0 ? {
15499
+ tool_calls: [...choice.toolCallsByIndex.entries()].sort(([leftIndex], [rightIndex]) => leftIndex - rightIndex).map(([, toolCall]) => toolCall)
15500
+ } : {}
14391
15501
  },
14392
15502
  ...choice.finish_reason !== void 0 ? { finish_reason: choice.finish_reason } : {}
14393
15503
  }))
14394
15504
  };
14395
15505
  }
15506
+ function getChatToolCallDeltas(value) {
15507
+ if (!Array.isArray(value?.tool_calls)) {
15508
+ return void 0;
15509
+ }
15510
+ const toolCalls = value.tool_calls.filter((toolCall) => isObject(toolCall));
15511
+ return toolCalls.length > 0 ? toolCalls : void 0;
15512
+ }
15513
+ function mergeChatToolCallDeltas(toolCallsByIndex, toolCallDeltas) {
15514
+ for (const toolDelta of toolCallDeltas) {
15515
+ const toolIndex = typeof toolDelta.index === "number" && toolDelta.index >= 0 ? toolDelta.index : 0;
15516
+ const existing = toolCallsByIndex.get(toolIndex);
15517
+ if (!existing) {
15518
+ toolCallsByIndex.set(toolIndex, createChatToolCall(toolDelta));
15519
+ continue;
15520
+ }
15521
+ mergeChatToolCall(existing, toolDelta);
15522
+ }
15523
+ }
15524
+ function createChatToolCall(toolDelta) {
15525
+ const toolFunction = isObject(toolDelta.function) ? toolDelta.function : {};
15526
+ const toolCallFunction = {
15527
+ arguments: typeof toolFunction.arguments === "string" ? toolFunction.arguments : ""
15528
+ };
15529
+ if (typeof toolFunction.name === "string") {
15530
+ toolCallFunction.name = toolFunction.name;
15531
+ }
15532
+ const toolCall = {
15533
+ function: toolCallFunction
15534
+ };
15535
+ if (typeof toolDelta.id === "string") {
15536
+ toolCall.id = toolDelta.id;
15537
+ }
15538
+ if (typeof toolDelta.type === "string") {
15539
+ toolCall.type = toolDelta.type;
15540
+ }
15541
+ return toolCall;
15542
+ }
15543
+ function mergeChatToolCall(existing, toolDelta) {
15544
+ const currentFunction = isObject(existing.function) ? existing.function : {};
15545
+ const deltaFunction = isObject(toolDelta.function) ? toolDelta.function : {};
15546
+ const currentArguments = typeof currentFunction.arguments === "string" ? currentFunction.arguments : "";
15547
+ const deltaArguments = typeof deltaFunction.arguments === "string" ? deltaFunction.arguments : "";
15548
+ if (typeof toolDelta.id === "string" && typeof existing.id !== "string") {
15549
+ existing.id = toolDelta.id;
15550
+ }
15551
+ if (typeof toolDelta.type === "string" && typeof existing.type !== "string") {
15552
+ existing.type = toolDelta.type;
15553
+ }
15554
+ const nextFunction = {
15555
+ ...currentFunction,
15556
+ arguments: `${currentArguments}${deltaArguments}`
15557
+ };
15558
+ if (typeof deltaFunction.name === "string" && typeof currentFunction.name !== "string") {
15559
+ nextFunction.name = deltaFunction.name;
15560
+ }
15561
+ existing.function = nextFunction;
15562
+ }
14396
15563
  function aggregateTextGenerationStreamChunks(chunks) {
14397
15564
  if (chunks.length === 0) {
14398
15565
  return void 0;
@@ -16437,6 +17604,8 @@ var MISTRAL_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
16437
17604
  "presence_penalty",
16438
17605
  "randomSeed",
16439
17606
  "random_seed",
17607
+ "reasoningEffort",
17608
+ "reasoning_effort",
16440
17609
  "responseFormat",
16441
17610
  "response_format",
16442
17611
  "safePrompt",
@@ -16577,6 +17746,98 @@ function extractDeltaText(content) {
16577
17746
  }).filter((part) => part.length > 0);
16578
17747
  return textParts.length > 0 ? textParts.join("") : void 0;
16579
17748
  }
17749
+ function normalizeMistralTextContentPart(part) {
17750
+ if (!isObject(part) || part.type !== "text" || typeof part.text !== "string") {
17751
+ return void 0;
17752
+ }
17753
+ return {
17754
+ type: "text",
17755
+ text: part.text
17756
+ };
17757
+ }
17758
+ function normalizeMistralThinkingContentPart(part) {
17759
+ if (!isObject(part) || part.type !== "thinking") {
17760
+ return void 0;
17761
+ }
17762
+ const thinking = Array.isArray(part.thinking) ? part.thinking.map((thinkingPart) => normalizeMistralTextContentPart(thinkingPart)).filter(
17763
+ (thinkingPart) => thinkingPart !== void 0 && typeof thinkingPart.text === "string"
17764
+ ) : [];
17765
+ return {
17766
+ type: "thinking",
17767
+ thinking
17768
+ };
17769
+ }
17770
+ function normalizeMistralContentParts(content) {
17771
+ if (!Array.isArray(content)) {
17772
+ return [];
17773
+ }
17774
+ return content.map((part) => {
17775
+ return normalizeMistralTextContentPart(part) || normalizeMistralThinkingContentPart(part);
17776
+ }).filter((part) => part !== void 0);
17777
+ }
17778
+ function mergeMistralTextSegments(left, right) {
17779
+ const merged = left.map((part) => ({ ...part }));
17780
+ for (const part of right) {
17781
+ const lastPart = merged[merged.length - 1];
17782
+ if (lastPart && lastPart.type === "text" && typeof lastPart.text === "string" && typeof part.text === "string") {
17783
+ lastPart.text += part.text;
17784
+ continue;
17785
+ }
17786
+ merged.push({ ...part });
17787
+ }
17788
+ return merged;
17789
+ }
17790
+ function mergeMistralContentParts(left, right) {
17791
+ const merged = [...(left || []).map((part) => structuredClone(part))];
17792
+ for (const part of right) {
17793
+ const lastPart = merged[merged.length - 1];
17794
+ if (part.type === "text" && lastPart?.type === "text" && typeof lastPart.text === "string" && typeof part.text === "string") {
17795
+ lastPart.text += part.text;
17796
+ continue;
17797
+ }
17798
+ if (part.type === "thinking" && lastPart?.type === "thinking" && Array.isArray(lastPart.thinking) && Array.isArray(part.thinking)) {
17799
+ lastPart.thinking = mergeMistralTextSegments(
17800
+ lastPart.thinking,
17801
+ part.thinking
17802
+ );
17803
+ continue;
17804
+ }
17805
+ merged.push(structuredClone(part));
17806
+ }
17807
+ return merged;
17808
+ }
17809
+ function appendMistralContent(accumulator, content) {
17810
+ if (typeof content === "string") {
17811
+ if (accumulator.contentParts) {
17812
+ accumulator.contentParts = mergeMistralContentParts(
17813
+ accumulator.contentParts,
17814
+ [{ type: "text", text: content }]
17815
+ );
17816
+ return;
17817
+ }
17818
+ accumulator.content = `${accumulator.content || ""}${content}`;
17819
+ return;
17820
+ }
17821
+ const normalizedContentParts = normalizeMistralContentParts(content);
17822
+ if (normalizedContentParts.length === 0) {
17823
+ return;
17824
+ }
17825
+ const hasStructuredContent = normalizedContentParts.some(
17826
+ (part) => part.type !== "text"
17827
+ );
17828
+ if (!accumulator.contentParts && !hasStructuredContent) {
17829
+ const text = extractDeltaText(content);
17830
+ if (text) {
17831
+ accumulator.content = `${accumulator.content || ""}${text}`;
17832
+ }
17833
+ return;
17834
+ }
17835
+ accumulator.contentParts = mergeMistralContentParts(
17836
+ accumulator.contentParts || (accumulator.content ? [{ type: "text", text: accumulator.content }] : []),
17837
+ normalizedContentParts
17838
+ );
17839
+ delete accumulator.content;
17840
+ }
16580
17841
  function getDeltaToolCalls(delta) {
16581
17842
  const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
16582
17843
  return toolCalls.filter((toolCall) => isObject(toolCall));
@@ -16745,10 +18006,7 @@ function aggregateMistralStreamChunks(chunks) {
16745
18006
  if (!accumulator.role && typeof delta.role === "string") {
16746
18007
  accumulator.role = delta.role;
16747
18008
  }
16748
- const deltaText = extractDeltaText(delta.content);
16749
- if (deltaText) {
16750
- accumulator.content = `${accumulator.content || ""}${deltaText}`;
16751
- }
18009
+ appendMistralContent(accumulator, delta.content);
16752
18010
  accumulator.toolCalls = mergeToolCallDeltas(
16753
18011
  accumulator.toolCalls,
16754
18012
  getDeltaToolCalls(delta)
@@ -16766,7 +18024,7 @@ function aggregateMistralStreamChunks(chunks) {
16766
18024
  index: choice.index,
16767
18025
  message: {
16768
18026
  ...choice.role ? { role: choice.role } : {},
16769
- content: choice.content ?? null,
18027
+ content: choice.contentParts ?? choice.content ?? null,
16770
18028
  ...choice.toolCalls ? { toolCalls: choice.toolCalls } : {}
16771
18029
  },
16772
18030
  ...choice.finishReason !== void 0 ? { finishReason: choice.finishReason } : {}
@@ -17005,7 +18263,7 @@ var GoogleADKPlugin = class extends BasePlugin {
17005
18263
  start: (event) => {
17006
18264
  const req = event.arguments[0] ?? {};
17007
18265
  const tool = event.self;
17008
- const toolName = extractToolName(req, tool);
18266
+ const toolName = extractToolName2(req, tool);
17009
18267
  const parentSpan = findToolParentSpan(
17010
18268
  req,
17011
18269
  this.activeAgentSpans,
@@ -17044,7 +18302,7 @@ var GoogleADKPlugin = class extends BasePlugin {
17044
18302
  metrics.duration = end - state.startTime;
17045
18303
  state.span.log({
17046
18304
  output: event.result,
17047
- metrics: cleanMetrics2(metrics)
18305
+ metrics: cleanMetrics3(metrics)
17048
18306
  });
17049
18307
  } finally {
17050
18308
  state.span.end();
@@ -17263,7 +18521,7 @@ function extractToolCallId(req) {
17263
18521
  const toolContext = req.toolContext;
17264
18522
  return toolContext?.functionCallId;
17265
18523
  }
17266
- function extractToolName(req, tool) {
18524
+ function extractToolName2(req, tool) {
17267
18525
  if (typeof tool?.name === "string" && tool.name.length > 0) {
17268
18526
  return tool.name;
17269
18527
  }
@@ -17311,7 +18569,7 @@ function finalizeRunnerSpan(state, activeRunnerSpans) {
17311
18569
  }
17312
18570
  state.span.log({
17313
18571
  output: lastEvent ? extractEventOutput(lastEvent) : void 0,
17314
- metrics: cleanMetrics2(metrics)
18572
+ metrics: cleanMetrics3(metrics)
17315
18573
  });
17316
18574
  } finally {
17317
18575
  cleanupActiveRunnerSpan(state, activeRunnerSpans);
@@ -17328,7 +18586,7 @@ function finalizeAgentSpan(state, activeAgentSpans) {
17328
18586
  metrics.duration = end - state.startTime;
17329
18587
  state.span.log({
17330
18588
  output: lastEvent ? extractEventOutput(lastEvent) : void 0,
17331
- metrics: cleanMetrics2(metrics)
18589
+ metrics: cleanMetrics3(metrics)
17332
18590
  });
17333
18591
  } finally {
17334
18592
  cleanupActiveAgentSpan(state, activeAgentSpans);
@@ -17414,7 +18672,7 @@ function populateUsageMetrics2(metrics, usage) {
17414
18672
  metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
17415
18673
  }
17416
18674
  }
17417
- function cleanMetrics2(metrics) {
18675
+ function cleanMetrics3(metrics) {
17418
18676
  const cleaned = {};
17419
18677
  for (const [key, value] of Object.entries(metrics)) {
17420
18678
  if (value !== null && value !== void 0) {
@@ -17542,6 +18800,11 @@ var CHAT_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
17542
18800
  "strictTools",
17543
18801
  "strict_tools",
17544
18802
  "temperature",
18803
+ "thinking",
18804
+ "thinkingTokenBudget",
18805
+ "thinkingType",
18806
+ "thinking_token_budget",
18807
+ "thinking_type",
17545
18808
  "toolChoice",
17546
18809
  "tool_choice"
17547
18810
  ]);
@@ -17762,6 +19025,11 @@ function mergeUsageMetrics(metrics, usage) {
17762
19025
  "tokens",
17763
19026
  tokenContainer.totalTokens ?? tokenContainer.total_tokens
17764
19027
  );
19028
+ setMetricIfNumber(
19029
+ metrics,
19030
+ "reasoning_tokens",
19031
+ tokenContainer.reasoningTokens ?? tokenContainer.reasoning_tokens ?? tokenContainer.thinkingTokens ?? tokenContainer.thinking_tokens
19032
+ );
17765
19033
  }
17766
19034
  const billedUnits = (isObject(source.billedUnits) ? source.billedUnits : void 0) || (isObject(source.billed_units) ? source.billed_units : void 0);
17767
19035
  if (billedUnits) {
@@ -17842,13 +19110,87 @@ function extractV8DeltaText(chunk) {
17842
19110
  }
17843
19111
  return void 0;
17844
19112
  }
19113
+ function getV8ContentIndex(chunk) {
19114
+ return typeof chunk.index === "number" ? chunk.index : 0;
19115
+ }
19116
+ function toContentBlockType(value) {
19117
+ return value === "text" || value === "thinking" ? value : void 0;
19118
+ }
19119
+ function getOrCreateContentBlock(contentBlocksByIndex, contentBlockOrder, index) {
19120
+ if (!contentBlockOrder.includes(index)) {
19121
+ contentBlockOrder.push(index);
19122
+ }
19123
+ if (!(index in contentBlocksByIndex)) {
19124
+ contentBlocksByIndex[index] = {
19125
+ text: "",
19126
+ thinking: ""
19127
+ };
19128
+ }
19129
+ return contentBlocksByIndex[index];
19130
+ }
19131
+ function appendV8ContentBlock(contentBlocksByIndex, contentBlockOrder, index, content) {
19132
+ if (typeof content === "string") {
19133
+ const block2 = getOrCreateContentBlock(
19134
+ contentBlocksByIndex,
19135
+ contentBlockOrder,
19136
+ index
19137
+ );
19138
+ block2.type ??= "text";
19139
+ block2.text += content;
19140
+ return;
19141
+ }
19142
+ if (!isObject(content)) {
19143
+ return;
19144
+ }
19145
+ const block = getOrCreateContentBlock(
19146
+ contentBlocksByIndex,
19147
+ contentBlockOrder,
19148
+ index
19149
+ );
19150
+ const contentType = toContentBlockType(content.type);
19151
+ if (contentType) {
19152
+ block.type = contentType;
19153
+ }
19154
+ if (typeof content.text === "string") {
19155
+ block.type ??= "text";
19156
+ block.text += content.text;
19157
+ }
19158
+ if (typeof content.thinking === "string") {
19159
+ block.type ??= "thinking";
19160
+ block.thinking += content.thinking;
19161
+ }
19162
+ }
19163
+ function serializeAggregatedContentBlocks(contentBlocksByIndex, contentBlockOrder) {
19164
+ return contentBlockOrder.sort((left, right) => left - right).flatMap((index) => {
19165
+ const block = contentBlocksByIndex[index];
19166
+ if (!block) {
19167
+ return [];
19168
+ }
19169
+ if (block.type === "thinking" && block.thinking.length > 0) {
19170
+ return [{ type: "thinking", thinking: block.thinking }];
19171
+ }
19172
+ if (block.text.length > 0) {
19173
+ return [{ type: "text", text: block.text }];
19174
+ }
19175
+ if (block.thinking.length > 0) {
19176
+ return [{ type: "thinking", thinking: block.thinking }];
19177
+ }
19178
+ return [];
19179
+ });
19180
+ }
19181
+ function hasThinkingContent(contentBlocks) {
19182
+ return contentBlocks.some((block) => block.type === "thinking");
19183
+ }
17845
19184
  function aggregateCohereChatStreamChunks(chunks) {
17846
19185
  const textDeltas = [];
19186
+ const contentBlocksByIndex = {};
19187
+ const contentBlockOrder = [];
17847
19188
  const toolCallsByIndex = {};
17848
19189
  const toolCallOrder = [];
17849
19190
  let terminalResponse;
17850
19191
  let role;
17851
19192
  let finishReason;
19193
+ let toolPlan = "";
17852
19194
  let metadata = {};
17853
19195
  let metrics = {};
17854
19196
  for (const chunk of chunks) {
@@ -17906,12 +19248,36 @@ function aggregateCohereChatStreamChunks(chunks) {
17906
19248
  continue;
17907
19249
  }
17908
19250
  if (eventType === "content-delta") {
19251
+ appendV8ContentBlock(
19252
+ contentBlocksByIndex,
19253
+ contentBlockOrder,
19254
+ getV8ContentIndex(chunk),
19255
+ isObject(chunk.delta) && isObject(chunk.delta.message) ? chunk.delta.message.content : void 0
19256
+ );
17909
19257
  const text = extractV8DeltaText(chunk);
17910
19258
  if (text) {
17911
19259
  textDeltas.push(text);
17912
19260
  }
17913
19261
  continue;
17914
19262
  }
19263
+ if (eventType === "content-start") {
19264
+ appendV8ContentBlock(
19265
+ contentBlocksByIndex,
19266
+ contentBlockOrder,
19267
+ getV8ContentIndex(chunk),
19268
+ isObject(chunk.delta) && isObject(chunk.delta.message) ? chunk.delta.message.content : void 0
19269
+ );
19270
+ continue;
19271
+ }
19272
+ if (eventType === "tool-plan-delta") {
19273
+ if (isObject(chunk.delta) && isObject(chunk.delta.message)) {
19274
+ 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;
19275
+ if (deltaToolPlan) {
19276
+ toolPlan += deltaToolPlan;
19277
+ }
19278
+ }
19279
+ continue;
19280
+ }
17915
19281
  if (eventType === "tool-call-start") {
17916
19282
  const toolCalls = isObject(chunk.delta) && isObject(chunk.delta.message) ? toToolCallArray(
17917
19283
  Array.isArray(chunk.delta.message.toolCalls) ? chunk.delta.message.toolCalls : chunk.delta.message.toolCalls ?? chunk.delta.message.tool_calls
@@ -17965,13 +19331,26 @@ function aggregateCohereChatStreamChunks(chunks) {
17965
19331
  }
17966
19332
  }
17967
19333
  const mergedToolCalls = toolCallOrder.sort((left, right) => left - right).map((index) => toolCallsByIndex[index]).filter((toolCall) => isObject(toolCall));
19334
+ const aggregatedContentBlocks = serializeAggregatedContentBlocks(
19335
+ contentBlocksByIndex,
19336
+ contentBlockOrder
19337
+ );
17968
19338
  let output = extractCohereChatOutput(terminalResponse);
17969
19339
  if (output === void 0) {
17970
19340
  const mergedText = textDeltas.join("");
17971
- if (mergedToolCalls.length > 0 || role || mergedText.length > 0) {
19341
+ const shouldUseStructuredContent = hasThinkingContent(aggregatedContentBlocks) || toolPlan.length > 0;
19342
+ if (shouldUseStructuredContent) {
19343
+ output = {
19344
+ ...role ? { role } : {},
19345
+ ...aggregatedContentBlocks.length > 0 ? { content: aggregatedContentBlocks } : {},
19346
+ ...toolPlan.length > 0 ? { toolPlan } : {},
19347
+ ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
19348
+ };
19349
+ } else if (mergedToolCalls.length > 0 || role || mergedText.length > 0 || aggregatedContentBlocks.length > 0) {
19350
+ const textContent = mergedText.length > 0 ? mergedText : aggregatedContentBlocks[0]?.type === "text" ? aggregatedContentBlocks[0].text : void 0;
17972
19351
  output = {
17973
19352
  ...role ? { role } : {},
17974
- ...mergedText.length > 0 ? { content: mergedText } : {},
19353
+ ...textContent ? { content: textContent } : {},
17975
19354
  ...mergedToolCalls.length > 0 ? { toolCalls: mergedToolCalls } : {}
17976
19355
  };
17977
19356
  }
@@ -17989,6 +19368,98 @@ function aggregateCohereChatStreamChunks(chunks) {
17989
19368
  };
17990
19369
  }
17991
19370
 
19371
+ // src/instrumentation/plugins/groq-channels.ts
19372
+ var groqChannels = defineChannels("groq-sdk", {
19373
+ chatCompletionsCreate: channel({
19374
+ channelName: "chat.completions.create",
19375
+ kind: "async"
19376
+ }),
19377
+ embeddingsCreate: channel(
19378
+ {
19379
+ channelName: "embeddings.create",
19380
+ kind: "async"
19381
+ }
19382
+ )
19383
+ });
19384
+
19385
+ // src/instrumentation/plugins/groq-plugin.ts
19386
+ var GroqPlugin = class extends BasePlugin {
19387
+ onEnable() {
19388
+ this.unsubscribers.push(
19389
+ traceStreamingChannel(groqChannels.chatCompletionsCreate, {
19390
+ name: "groq.chat.completions.create",
19391
+ type: "llm" /* LLM */,
19392
+ extractInput: ([params]) => {
19393
+ const { messages, ...metadata } = params;
19394
+ return {
19395
+ input: processInputAttachments(messages),
19396
+ metadata: { ...metadata, provider: "groq" }
19397
+ };
19398
+ },
19399
+ extractOutput: (result) => result?.choices,
19400
+ extractMetrics: (result, startTime) => {
19401
+ const metrics = parseGroqMetrics(result);
19402
+ if (startTime) {
19403
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
19404
+ }
19405
+ return metrics;
19406
+ },
19407
+ aggregateChunks: aggregateGroqChatCompletionChunks
19408
+ })
19409
+ );
19410
+ this.unsubscribers.push(
19411
+ traceAsyncChannel(groqChannels.embeddingsCreate, {
19412
+ name: "groq.embeddings.create",
19413
+ type: "llm" /* LLM */,
19414
+ extractInput: ([params]) => {
19415
+ const { input, ...metadata } = params;
19416
+ return {
19417
+ input,
19418
+ metadata: { ...metadata, provider: "groq" }
19419
+ };
19420
+ },
19421
+ extractOutput: (result) => {
19422
+ const embedding = result?.data?.[0]?.embedding;
19423
+ return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
19424
+ },
19425
+ extractMetrics: (result) => parseGroqMetrics(result)
19426
+ })
19427
+ );
19428
+ }
19429
+ onDisable() {
19430
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
19431
+ }
19432
+ };
19433
+ function parseGroqMetrics(result) {
19434
+ const metrics = parseMetricsFromUsage(result?.usage);
19435
+ const xGroq = result?.x_groq;
19436
+ if (!xGroq || typeof xGroq !== "object") {
19437
+ return metrics;
19438
+ }
19439
+ const extraUsage = "usage" in xGroq ? xGroq.usage : void 0;
19440
+ if (!extraUsage || typeof extraUsage !== "object") {
19441
+ return metrics;
19442
+ }
19443
+ const dramCachedTokens = extraUsage["dram_cached_tokens"];
19444
+ const sramCachedTokens = extraUsage["sram_cached_tokens"];
19445
+ return {
19446
+ ...metrics,
19447
+ ...typeof dramCachedTokens === "number" ? { dram_cached_tokens: dramCachedTokens } : {},
19448
+ ...typeof sramCachedTokens === "number" ? { sram_cached_tokens: sramCachedTokens } : {}
19449
+ };
19450
+ }
19451
+ function aggregateGroqChatCompletionChunks(chunks, streamResult, endEvent) {
19452
+ const aggregated = aggregateChatCompletionChunks(
19453
+ chunks,
19454
+ streamResult,
19455
+ endEvent
19456
+ );
19457
+ return {
19458
+ metrics: aggregated.metrics,
19459
+ output: aggregated.output
19460
+ };
19461
+ }
19462
+
17992
19463
  // src/instrumentation/braintrust-plugin.ts
17993
19464
  var BraintrustPlugin = class extends BasePlugin {
17994
19465
  config;
@@ -17996,6 +19467,7 @@ var BraintrustPlugin = class extends BasePlugin {
17996
19467
  anthropicPlugin = null;
17997
19468
  aiSDKPlugin = null;
17998
19469
  claudeAgentSDKPlugin = null;
19470
+ cursorSDKPlugin = null;
17999
19471
  googleGenAIPlugin = null;
18000
19472
  huggingFacePlugin = null;
18001
19473
  openRouterPlugin = null;
@@ -18003,6 +19475,7 @@ var BraintrustPlugin = class extends BasePlugin {
18003
19475
  mistralPlugin = null;
18004
19476
  googleADKPlugin = null;
18005
19477
  coherePlugin = null;
19478
+ groqPlugin = null;
18006
19479
  constructor(config = {}) {
18007
19480
  super();
18008
19481
  this.config = config;
@@ -18025,6 +19498,10 @@ var BraintrustPlugin = class extends BasePlugin {
18025
19498
  this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
18026
19499
  this.claudeAgentSDKPlugin.enable();
18027
19500
  }
19501
+ if (integrations.cursorSDK !== false && integrations.cursor !== false) {
19502
+ this.cursorSDKPlugin = new CursorSDKPlugin();
19503
+ this.cursorSDKPlugin.enable();
19504
+ }
18028
19505
  if (integrations.googleGenAI !== false && integrations.google !== false) {
18029
19506
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
18030
19507
  this.googleGenAIPlugin.enable();
@@ -18053,6 +19530,10 @@ var BraintrustPlugin = class extends BasePlugin {
18053
19530
  this.coherePlugin = new CoherePlugin();
18054
19531
  this.coherePlugin.enable();
18055
19532
  }
19533
+ if (integrations.groq !== false) {
19534
+ this.groqPlugin = new GroqPlugin();
19535
+ this.groqPlugin.enable();
19536
+ }
18056
19537
  }
18057
19538
  onDisable() {
18058
19539
  if (this.openaiPlugin) {
@@ -18071,6 +19552,10 @@ var BraintrustPlugin = class extends BasePlugin {
18071
19552
  this.claudeAgentSDKPlugin.disable();
18072
19553
  this.claudeAgentSDKPlugin = null;
18073
19554
  }
19555
+ if (this.cursorSDKPlugin) {
19556
+ this.cursorSDKPlugin.disable();
19557
+ this.cursorSDKPlugin = null;
19558
+ }
18074
19559
  if (this.googleGenAIPlugin) {
18075
19560
  this.googleGenAIPlugin.disable();
18076
19561
  this.googleGenAIPlugin = null;
@@ -18099,6 +19584,10 @@ var BraintrustPlugin = class extends BasePlugin {
18099
19584
  this.coherePlugin.disable();
18100
19585
  this.coherePlugin = null;
18101
19586
  }
19587
+ if (this.groqPlugin) {
19588
+ this.groqPlugin.disable();
19589
+ this.groqPlugin = null;
19590
+ }
18102
19591
  }
18103
19592
  };
18104
19593
 
@@ -18172,6 +19661,8 @@ var PluginRegistry = class {
18172
19661
  google: true,
18173
19662
  huggingface: true,
18174
19663
  claudeAgentSDK: true,
19664
+ cursor: true,
19665
+ cursorSDK: true,
18175
19666
  openrouter: true,
18176
19667
  openrouterAgent: true,
18177
19668
  mistral: true,
@@ -18188,7 +19679,11 @@ var PluginRegistry = class {
18188
19679
  if (disabledList) {
18189
19680
  const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
18190
19681
  for (const sdk of disabled) {
18191
- integrations[sdk] = false;
19682
+ if (sdk === "cursor-sdk") {
19683
+ integrations.cursorSDK = false;
19684
+ } else {
19685
+ integrations[sdk] = false;
19686
+ }
18192
19687
  }
18193
19688
  }
18194
19689
  return { integrations };