@bitfab/sdk 0.59.0 → 0.60.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 (41) hide show
  1. package/dist/autoTrace.cjs.map +1 -1
  2. package/dist/autoTrace.d.cts +2 -0
  3. package/dist/autoTrace.d.ts +2 -0
  4. package/dist/autoTrace.js +1 -1
  5. package/dist/{chunk-ETZUSSF6.js → chunk-5DNB7EN7.js} +1 -1
  6. package/dist/chunk-5DNB7EN7.js.map +1 -0
  7. package/dist/{chunk-4BNE5ETI.js → chunk-6PBK5RCL.js} +54 -38
  8. package/dist/chunk-6PBK5RCL.js.map +1 -0
  9. package/dist/{chunk-IW23QVY3.js → chunk-CLME47O6.js} +18 -10
  10. package/dist/chunk-CLME47O6.js.map +1 -0
  11. package/dist/{chunk-KGIKT4UT.js → chunk-M5QNFJSF.js} +37 -38
  12. package/dist/chunk-M5QNFJSF.js.map +1 -0
  13. package/dist/{chunk-6IM35I7O.js → chunk-TX3HZEQO.js} +29 -14
  14. package/dist/chunk-TX3HZEQO.js.map +1 -0
  15. package/dist/{chunk-FBMHGUIK.js → chunk-ZSCAAX44.js} +29 -14
  16. package/dist/chunk-ZSCAAX44.js.map +1 -0
  17. package/dist/{http-FXLIHCQK.js → http-GYCMIHBO.js} +4 -2
  18. package/dist/{http-HJJR2ZCE.js → http-XDEB3KJG.js} +4 -2
  19. package/dist/index.cjs +109 -79
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +71 -36
  22. package/dist/index.d.ts +71 -36
  23. package/dist/index.js +4 -4
  24. package/dist/node.cjs +109 -79
  25. package/dist/node.cjs.map +1 -1
  26. package/dist/node.d.cts +1 -1
  27. package/dist/node.d.ts +1 -1
  28. package/dist/node.js +4 -4
  29. package/dist/{replay-WBWGCZF7.js → replay-C3BMTZZI.js} +3 -3
  30. package/dist/replayCli.js +2 -2
  31. package/dist/seedCli.js +2 -2
  32. package/package.json +1 -1
  33. package/dist/chunk-4BNE5ETI.js.map +0 -1
  34. package/dist/chunk-6IM35I7O.js.map +0 -1
  35. package/dist/chunk-ETZUSSF6.js.map +0 -1
  36. package/dist/chunk-FBMHGUIK.js.map +0 -1
  37. package/dist/chunk-IW23QVY3.js.map +0 -1
  38. package/dist/chunk-KGIKT4UT.js.map +0 -1
  39. /package/dist/{http-FXLIHCQK.js.map → http-GYCMIHBO.js.map} +0 -0
  40. /package/dist/{http-HJJR2ZCE.js.map → http-XDEB3KJG.js.map} +0 -0
  41. /package/dist/{replay-WBWGCZF7.js.map → replay-C3BMTZZI.js.map} +0 -0
package/dist/node.cjs CHANGED
@@ -88,7 +88,7 @@ var __version__, __packageName__;
88
88
  var init_version_generated = __esm({
89
89
  "src/version.generated.ts"() {
90
90
  "use strict";
91
- __version__ = "0.59.0";
91
+ __version__ = "0.60.0";
92
92
  __packageName__ = "@bitfab/sdk";
93
93
  }
94
94
  });
@@ -2111,6 +2111,7 @@ __export(http_exports, {
2111
2111
  HttpClient: () => HttpClient,
2112
2112
  awaitOnExit: () => awaitOnExit,
2113
2113
  awaitPendingRequests: () => awaitPendingRequests,
2114
+ experimentIdWireFields: () => experimentIdWireFields,
2114
2115
  flushTraces: () => flushTraces,
2115
2116
  parseRetryAfterMs: () => parseRetryAfterMs,
2116
2117
  serializePayloadBody: () => serializePayloadBody
@@ -2279,6 +2280,9 @@ function warnDroppedExternalTrace(error) {
2279
2280
  `a trace was dropped because the send step failed: ${describeError(error)}`
2280
2281
  );
2281
2282
  }
2283
+ function experimentIdWireFields(experimentId) {
2284
+ return { experimentId, testRunId: experimentId };
2285
+ }
2282
2286
  var REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS, REPLAY_COMPLETE_REQUEST_TIMEOUT_MS, OTLP_TRACES_ENDPOINT, RETRYABLE_STATUSES, EXIT_FLUSH_TIMEOUT_MS, DEFAULT_LIFECYCLE_TIMEOUT_MS2, pendingTracePromises, liveHttpClients, carrierSeq, HttpClient;
2283
2287
  var init_http = __esm({
2284
2288
  "src/http.ts"() {
@@ -2883,7 +2887,7 @@ var init_http = __esm({
2883
2887
  }
2884
2888
  /**
2885
2889
  * Start a replay session by fetching historical traces.
2886
- * Blocking call - creates a test run and returns lightweight item references.
2890
+ * Blocking call - creates an experiment and returns lightweight item references.
2887
2891
  */
2888
2892
  async startReplay(traceFunctionKey, limit, traceIds, name, codeChangeDescription, codeChangeFiles, includeDbBranchLease, experimentGroupId, datasetIds, graderIds, dbBranchSettings, attempts, includeOriginalMetadata, onlyWithAssertions, judgeAssertions) {
2889
2893
  const payload = { traceFunctionKey };
@@ -2939,9 +2943,20 @@ var init_http = __esm({
2939
2943
  payload.git = git;
2940
2944
  }
2941
2945
  const timeout = includeDbBranchLease ? REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS : 3e4;
2942
- return this.request("/api/sdk/replay/start", payload, {
2943
- timeout
2944
- });
2946
+ const response = await this.request(
2947
+ "/api/sdk/replay/start",
2948
+ payload,
2949
+ { timeout }
2950
+ );
2951
+ const { testRunId, testRunUrl, ...rest } = response;
2952
+ const experimentId = response.experimentId ?? testRunId;
2953
+ const experimentUrl = response.experimentUrl ?? testRunUrl;
2954
+ if (experimentId === void 0 || experimentUrl === void 0) {
2955
+ throw new BitfabError(
2956
+ "Replay start response is missing the experiment ID or URL."
2957
+ );
2958
+ }
2959
+ return { ...rest, experimentId, experimentUrl };
2945
2960
  }
2946
2961
  /**
2947
2962
  * Fetch an external span by ID.
@@ -3038,21 +3053,21 @@ var init_http = __esm({
3038
3053
  * has a final status AND at least that many persisted spans, which is what
3039
3054
  * makes this a real barrier rather than a "the row exists" check.
3040
3055
  */
3041
- async getReplayStatus(testRunId, expectedSpanCounts) {
3056
+ async getReplayStatus(experimentId, expectedSpanCounts) {
3042
3057
  return this.request(
3043
3058
  "/api/sdk/replay/status",
3044
- { testRunId, expectedSpanCounts },
3059
+ { ...experimentIdWireFields(experimentId), expectedSpanCounts },
3045
3060
  { timeout: 3e4 }
3046
3061
  );
3047
3062
  }
3048
3063
  /**
3049
- * Mark a replay test run as completed.
3064
+ * Mark a replay experiment as completed.
3050
3065
  * Blocking call.
3051
3066
  */
3052
- async completeReplay(testRunId) {
3067
+ async completeReplay(experimentId) {
3053
3068
  return this.request(
3054
3069
  "/api/sdk/replay/complete",
3055
- { testRunId },
3070
+ experimentIdWireFields(experimentId),
3056
3071
  { timeout: REPLAY_COMPLETE_REQUEST_TIMEOUT_MS }
3057
3072
  );
3058
3073
  }
@@ -3074,11 +3089,11 @@ var init_http = __esm({
3074
3089
  * snapshot + preview branch and polls operations to readiness, which
3075
3090
  * can take seconds.
3076
3091
  */
3077
- async resolveDbBranchLease(testRunId, traceId, dbBranchSettings, attempt) {
3092
+ async resolveDbBranchLease(experimentId, traceId, dbBranchSettings, attempt) {
3078
3093
  return this.request(
3079
3094
  "/api/sdk/replay/resolveDbBranchLease",
3080
3095
  {
3081
- testRunId,
3096
+ ...experimentIdWireFields(experimentId),
3082
3097
  traceId,
3083
3098
  dbBranchSettings,
3084
3099
  ...attempt !== void 0 && attempt > 0 ? { attempt } : {}
@@ -3667,7 +3682,7 @@ function replayJsonReplacer(_key, value) {
3667
3682
  function serializeReplayResult(result) {
3668
3683
  return JSON.stringify(result, replayJsonReplacer, 2);
3669
3684
  }
3670
- async function preserveReplayFailure(operation, items, testRunId, testRunUrl) {
3685
+ async function preserveReplayFailure(operation, items, experimentId, experimentUrl) {
3671
3686
  try {
3672
3687
  return await operation();
3673
3688
  } catch (cause) {
@@ -3677,8 +3692,8 @@ async function preserveReplayFailure(operation, items, testRunId, testRunUrl) {
3677
3692
  throw new ReplayError(
3678
3693
  errorMessage(cause),
3679
3694
  items,
3680
- testRunId,
3681
- testRunUrl,
3695
+ experimentId,
3696
+ experimentUrl,
3682
3697
  cause
3683
3698
  );
3684
3699
  }
@@ -3732,7 +3747,7 @@ function buildMockTree(rootNode) {
3732
3747
  }
3733
3748
  return { spans };
3734
3749
  }
3735
- async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy, resolvedOverrides, replayedTraceId, attempt, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
3750
+ async function processItem(httpClient, serverItem, fn, experimentId, mockStrategy, resolvedOverrides, replayedTraceId, attempt, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
3736
3751
  let lease = includeDbBranchLease ? serverItem.dbBranchLease : void 0;
3737
3752
  let leaseError = includeDbBranchLease ? serverItem.dbBranchLeaseError : void 0;
3738
3753
  let dbSnapshotRef = serverItem.dbSnapshotRef;
@@ -3752,7 +3767,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
3752
3767
  let resolved2;
3753
3768
  try {
3754
3769
  resolved2 = await httpClient.resolveDbBranchLease(
3755
- testRunId,
3770
+ experimentId,
3756
3771
  originalTraceId,
3757
3772
  dbBranchSettings,
3758
3773
  attempt
@@ -3864,7 +3879,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
3864
3879
  replayStarted = performance.now();
3865
3880
  const maybePromise = runWithReplayContext(
3866
3881
  {
3867
- testRunId,
3882
+ experimentId,
3868
3883
  traceId: replayedTraceId,
3869
3884
  inputSourceSpanId: span.id,
3870
3885
  inputSourceTraceId: span.externalTraceId,
@@ -3947,14 +3962,14 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
3947
3962
  originalTraceOutline: null
3948
3963
  };
3949
3964
  }
3950
- async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds) {
3965
+ async function waitForReplayPersistence(httpClient, experimentId, replayedTraceIds) {
3951
3966
  const deferredSettled = await httpClient.settleDeferredWork(
3952
3967
  REPLAY_PERSISTENCE_TIMEOUT_MS
3953
3968
  );
3954
3969
  if (!deferredSettled) {
3955
3970
  httpClient.takeTraceDeliveries(replayedTraceIds);
3956
3971
  throw new BitfabError(
3957
- `Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (testRunId ${testRunId}).`
3972
+ `Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (experiment ${experimentId}).`
3958
3973
  );
3959
3974
  }
3960
3975
  if (!httpClient.hasClosedDeliveries(replayedTraceIds)) {
@@ -3983,7 +3998,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
3983
3998
  let missing = Object.keys(expectedSpanCounts).length;
3984
3999
  while (true) {
3985
4000
  const status = await httpClient.getReplayStatus(
3986
- testRunId,
4001
+ experimentId,
3987
4002
  expectedSpanCounts
3988
4003
  );
3989
4004
  const ready = status.traceIds ?? {};
@@ -4002,7 +4017,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
4002
4017
  }
4003
4018
  const cause = flushed ? "" : " Delivery was also not confirmed before the flush deadline, so the spans likely never reached the server.";
4004
4019
  throw new BitfabError(
4005
- `Replay traces were not fully persisted before the delivery deadline (testRunId ${testRunId}, missing ${missing} of ${Object.keys(expectedSpanCounts).length} trace(s)).${cause}`
4020
+ `Replay traces were not fully persisted before the delivery deadline (experiment ${experimentId}, missing ${missing} of ${Object.keys(expectedSpanCounts).length} trace(s)).${cause}`
4006
4021
  );
4007
4022
  }
4008
4023
  function sleepForReplayPersistence(ms) {
@@ -4069,8 +4084,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4069
4084
  }
4070
4085
  }
4071
4086
  const {
4072
- testRunId,
4073
- testRunUrl,
4087
+ experimentId,
4088
+ experimentUrl,
4074
4089
  items: serverItems
4075
4090
  } = await httpClient.startReplay(
4076
4091
  traceFunctionKey,
@@ -4103,7 +4118,14 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4103
4118
  }
4104
4119
  }
4105
4120
  const mockStrategy = options?.mock ?? "marked";
4106
- const fullTestRunUrl = `${serviceUrl}${testRunUrl}`;
4121
+ const fullExperimentUrl = `${serviceUrl}${experimentUrl}`;
4122
+ try {
4123
+ options?.onExperimentStart?.({
4124
+ experimentId,
4125
+ experimentUrl: fullExperimentUrl
4126
+ });
4127
+ } catch {
4128
+ }
4107
4129
  const resolvedOverrides = [
4108
4130
  ...normalizeMockOverrides(options?.mockOverride),
4109
4131
  ...registeredOverrides
@@ -4116,7 +4138,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4116
4138
  httpClient,
4117
4139
  serverItem,
4118
4140
  fn,
4119
- testRunId,
4141
+ experimentId,
4120
4142
  mockStrategy,
4121
4143
  resolvedOverrides,
4122
4144
  replayedTraceIds[index],
@@ -4171,7 +4193,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4171
4193
  }
4172
4194
  try {
4173
4195
  onItemFinish?.({
4174
- testRunId,
4196
+ experimentId,
4197
+ testRunId: experimentId,
4175
4198
  completed,
4176
4199
  total,
4177
4200
  succeeded,
@@ -4219,7 +4242,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4219
4242
  try {
4220
4243
  options.onItemStart?.({
4221
4244
  type: "started",
4222
- testRunId,
4245
+ experimentId,
4246
+ testRunId: experimentId,
4223
4247
  started,
4224
4248
  completed,
4225
4249
  total,
@@ -4238,21 +4262,23 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4238
4262
  } : void 0
4239
4263
  );
4240
4264
  if (options?.dryRun === true) {
4241
- await httpClient.completeReplay(testRunId).catch(() => void 0);
4265
+ await httpClient.completeReplay(experimentId).catch(() => void 0);
4242
4266
  const dryResult = {
4243
4267
  items: resultItems,
4244
- testRunId,
4245
- testRunUrl: fullTestRunUrl,
4268
+ experimentId,
4269
+ experimentUrl: fullExperimentUrl,
4270
+ testRunId: experimentId,
4271
+ testRunUrl: fullExperimentUrl,
4246
4272
  attempts
4247
4273
  };
4248
4274
  await writeReplayResultFile(dryResult);
4249
4275
  return dryResult;
4250
4276
  }
4251
4277
  const deliveredTraceIds = await preserveReplayFailure(
4252
- () => waitForReplayPersistence(httpClient, testRunId, replayedTraceIds),
4278
+ () => waitForReplayPersistence(httpClient, experimentId, replayedTraceIds),
4253
4279
  resultItems,
4254
- testRunId,
4255
- fullTestRunUrl
4280
+ experimentId,
4281
+ fullExperimentUrl
4256
4282
  );
4257
4283
  for (let index = 0; index < resultItems.length; index += 1) {
4258
4284
  const localId = replayedTraceIds[index];
@@ -4262,10 +4288,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4262
4288
  }
4263
4289
  }
4264
4290
  const completeResult = await preserveReplayFailure(
4265
- () => httpClient.completeReplay(testRunId),
4291
+ () => httpClient.completeReplay(experimentId),
4266
4292
  resultItems,
4267
- testRunId,
4268
- fullTestRunUrl
4293
+ experimentId,
4294
+ fullExperimentUrl
4269
4295
  );
4270
4296
  const serverTraceIds = completeResult.traceIds;
4271
4297
  const replayTokens = completeResult.tokens;
@@ -4292,20 +4318,20 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4292
4318
  if (completedCount > 0 && missing.length === completedCount) {
4293
4319
  const serverCount = completeResult.traceCount !== void 0 ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.` : "";
4294
4320
  const cause = new BitfabError(
4295
- `Replay completed but the server has no persisted trace for any of the ${completedCount} completed item(s) (testRunId ${testRunId}).${serverCount} Trace uploads were awaited, so either the uploads failed (check for "Bitfab: Failed to create" errors above) or the replayed function is not wrapped with withSpan.`
4321
+ `Replay completed but the server has no persisted trace for any of the ${completedCount} completed item(s) (experiment ${experimentId}).${serverCount} Trace uploads were awaited, so either the uploads failed (check for "Bitfab: Failed to create" errors above) or the replayed function is not wrapped with withSpan.`
4296
4322
  );
4297
4323
  throw new ReplayError(
4298
4324
  cause.message,
4299
4325
  resultItems,
4300
- testRunId,
4301
- fullTestRunUrl,
4326
+ experimentId,
4327
+ fullExperimentUrl,
4302
4328
  cause
4303
4329
  );
4304
4330
  }
4305
4331
  if (missing.length > 0) {
4306
4332
  try {
4307
4333
  console.error(
4308
- `Bitfab: server has no persisted trace for ${missing.length} of ${completedCount} completed replay item(s) (testRunId ${testRunId}). Their replay token usage is unavailable and they cannot be labeled.`
4334
+ `Bitfab: server has no persisted trace for ${missing.length} of ${completedCount} completed replay item(s) (experiment ${experimentId}). Their replay token usage is unavailable and they cannot be labeled.`
4309
4335
  );
4310
4336
  } catch {
4311
4337
  }
@@ -4313,8 +4339,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4313
4339
  }
4314
4340
  const result = {
4315
4341
  items: resultItems,
4316
- testRunId,
4317
- testRunUrl: fullTestRunUrl,
4342
+ experimentId,
4343
+ experimentUrl: fullExperimentUrl,
4344
+ testRunId: experimentId,
4345
+ testRunUrl: fullExperimentUrl,
4318
4346
  attempts
4319
4347
  };
4320
4348
  await writeReplayResultFile(result);
@@ -4322,7 +4350,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4322
4350
  try {
4323
4351
  options?.onProgress?.({
4324
4352
  type: "complete",
4325
- testRunId,
4353
+ experimentId,
4354
+ testRunId: experimentId,
4326
4355
  completed: total,
4327
4356
  total,
4328
4357
  succeeded,
@@ -4372,13 +4401,15 @@ var init_replay = __esm({
4372
4401
  MAX_REPLAY_ATTEMPTS = 100;
4373
4402
  BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
4374
4403
  ReplayError = class extends BitfabError {
4375
- constructor(message, items, testRunId, testRunUrl, cause) {
4376
- super(message, testRunUrl);
4404
+ constructor(message, items, experimentId, experimentUrl, cause) {
4405
+ super(message, experimentUrl);
4377
4406
  this.items = items;
4378
- this.testRunId = testRunId;
4379
- this.testRunUrl = testRunUrl;
4407
+ this.experimentId = experimentId;
4408
+ this.experimentUrl = experimentUrl;
4380
4409
  this.cause = cause;
4381
4410
  this.name = "ReplayError";
4411
+ this.testRunId = experimentId;
4412
+ this.testRunUrl = experimentUrl;
4382
4413
  }
4383
4414
  };
4384
4415
  DbBranchReplayError = class extends BitfabError {
@@ -6071,6 +6102,7 @@ var GradersClient = class {
6071
6102
  init_http();
6072
6103
 
6073
6104
  // src/labels.ts
6105
+ init_http();
6074
6106
  var LABELS_PATH = "/api/sdk/traces/labels";
6075
6107
  var HUMAN_LABELS_PATH = "/api/sdk/traces/labels/human";
6076
6108
  function labelEvidencePath(traceId, assertionId) {
@@ -6080,27 +6112,27 @@ var LabelsClient = class {
6080
6112
  constructor(httpClient) {
6081
6113
  this.httpClient = httpClient;
6082
6114
  }
6083
- async save(update, testRunId) {
6084
- const [outcome] = await this.saveAll([update], testRunId);
6115
+ async save(update, experimentId) {
6116
+ const [outcome] = await this.saveAll([update], experimentId);
6085
6117
  return outcome;
6086
6118
  }
6087
- async saveAll(updates, testRunId) {
6119
+ async saveAll(updates, experimentId) {
6088
6120
  const response = await this.httpClient.request(
6089
6121
  LABELS_PATH,
6090
6122
  {
6091
6123
  labels: updates,
6092
- ...testRunId === void 0 ? {} : { testRunId }
6124
+ ...experimentId === void 0 ? {} : experimentIdWireFields(experimentId)
6093
6125
  }
6094
6126
  );
6095
6127
  return response.labels;
6096
6128
  }
6097
6129
  /** Withhold a verdict for a trace or replay attempt whose check did not run. */
6098
- async skip(target, testRunId) {
6099
- return this.save({ ...target, skip: true }, testRunId);
6130
+ async skip(target, experimentId) {
6131
+ return this.save({ ...target, skip: true }, experimentId);
6100
6132
  }
6101
6133
  /** Clear a previous verdict for a trace, replay attempt, or assertion. */
6102
- async archive(target, testRunId) {
6103
- return this.save({ ...target, archive: true }, testRunId);
6134
+ async archive(target, experimentId) {
6135
+ return this.save({ ...target, archive: true }, experimentId);
6104
6136
  }
6105
6137
  async saveHuman(update) {
6106
6138
  const [outcome] = await this.saveHumanAll([update]);
@@ -8458,6 +8490,15 @@ var BitfabVercelAiHandler = class {
8458
8490
 
8459
8491
  // src/client.ts
8460
8492
  init_warnOnce();
8493
+ function resolveSpanExperimentId(options) {
8494
+ const { experimentId, testRunId } = options;
8495
+ if (experimentId !== void 0 && testRunId !== void 0 && experimentId !== testRunId) {
8496
+ throw new BitfabError(
8497
+ `experimentId ("${experimentId}") and its deprecated alias testRunId ("${testRunId}") were both passed with different values. Pass only experimentId.`
8498
+ );
8499
+ }
8500
+ return experimentId ?? testRunId;
8501
+ }
8461
8502
  var TRUNCATION_LIMIT_ORDER = [
8462
8503
  "max_depth",
8463
8504
  "max_captured_subtree_spans"
@@ -9047,13 +9088,12 @@ var Bitfab = class {
9047
9088
  "bitfab.node({ capture: false }) cannot use mockOnReplay: true because an uncaptured node has no recorded output."
9048
9089
  );
9049
9090
  }
9091
+ const experimentId = resolveSpanExperimentId(options);
9050
9092
  return {
9051
9093
  capture,
9052
9094
  type: options.type ?? "custom",
9053
9095
  ...options.name !== void 0 && { name: options.name },
9054
- ...options.testRunId !== void 0 && {
9055
- testRunId: options.testRunId
9056
- },
9096
+ ...experimentId !== void 0 && { experimentId },
9057
9097
  ...options.mockOnReplay !== void 0 && {
9058
9098
  mockOnReplay: options.mockOnReplay
9059
9099
  },
@@ -9188,6 +9228,7 @@ var Bitfab = class {
9188
9228
  return invokeWithoutNode();
9189
9229
  }
9190
9230
  const mockOnReplay = nodeConfiguration?.mockOnReplay ?? options.mockOnReplayDefault;
9231
+ const nodeExperimentId = nodeConfiguration === void 0 ? void 0 : resolveSpanExperimentId(nodeConfiguration);
9191
9232
  const childOptions = {
9192
9233
  name: spanName,
9193
9234
  type: nodeConfiguration?.type ?? "function",
@@ -9198,8 +9239,8 @@ var Bitfab = class {
9198
9239
  captureContent: true,
9199
9240
  autoTraceDefinition: definition,
9200
9241
  ...declaredNode && { declaredNode },
9201
- ...nodeConfiguration?.testRunId !== void 0 && {
9202
- testRunId: nodeConfiguration.testRunId
9242
+ ...nodeExperimentId !== void 0 && {
9243
+ experimentId: nodeExperimentId
9203
9244
  },
9204
9245
  ...mockOnReplay !== void 0 && {
9205
9246
  mockOnReplay
@@ -9860,6 +9901,7 @@ var Bitfab = class {
9860
9901
  const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
9861
9902
  const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
9862
9903
  const self = this;
9904
+ const optionExperimentId = resolveSpanExperimentId(options);
9863
9905
  const fnIsAsyncFunction = fn.constructor.name === "AsyncFunction";
9864
9906
  const fnReturnsPromise = fnIsAsyncFunction || (() => {
9865
9907
  try {
@@ -9962,7 +10004,7 @@ var Bitfab = class {
9962
10004
  const inputs = args;
9963
10005
  const startedAt = nowIsoTimestamp();
9964
10006
  const replayCtxAtStart = getReplayContext();
9965
- const testRunId = replayCtxAtStart?.testRunId ?? options.testRunId;
10007
+ const experimentId = replayCtxAtStart?.experimentId ?? optionExperimentId;
9966
10008
  if (isRootSpan && !activeTraceStates.has(traceId)) {
9967
10009
  const dbSnapshotRef = buildSnapshotRef(self.dbSnapshot, startedAt);
9968
10010
  self.simulationPlan.refresh();
@@ -9971,7 +10013,7 @@ var Bitfab = class {
9971
10013
  traceFunctionKey,
9972
10014
  startedAt,
9973
10015
  contexts: [],
9974
- ...testRunId !== void 0 && { testRunId },
10016
+ ...experimentId !== void 0 && { experimentId },
9975
10017
  ...replayCtxAtStart?.inputSourceTraceId && {
9976
10018
  inputSourceTraceId: replayCtxAtStart.inputSourceTraceId
9977
10019
  },
@@ -10017,7 +10059,7 @@ var Bitfab = class {
10017
10059
  contexts: newContext.contexts,
10018
10060
  prompt: newContext.prompt,
10019
10061
  endedAt,
10020
- ...testRunId !== void 0 && { testRunId },
10062
+ ...experimentId !== void 0 && { experimentId },
10021
10063
  ...replayCtx?.inputSourceSpanId && {
10022
10064
  inputSourceSpanId: replayCtx.inputSourceSpanId
10023
10065
  }
@@ -10038,7 +10080,7 @@ var Bitfab = class {
10038
10080
  name: traceState?.name,
10039
10081
  metadata: callerTraceMetadata(traceId),
10040
10082
  contexts: traceState?.contexts ?? [],
10041
- testRunId: traceState?.testRunId,
10083
+ experimentId: traceState?.experimentId,
10042
10084
  inputSourceTraceId: traceState?.inputSourceTraceId,
10043
10085
  replayAttempt: traceState?.replayAttempt,
10044
10086
  dbSnapshotRef: traceState?.dbSnapshotRef,
@@ -10352,9 +10394,6 @@ var Bitfab = class {
10352
10394
  return {
10353
10395
  traceId,
10354
10396
  addContext: (context) => {
10355
- if (!this.shouldRecord()) {
10356
- return Promise.resolve();
10357
- }
10358
10397
  if (typeof context !== "object" || context === null) {
10359
10398
  return Promise.resolve();
10360
10399
  }
@@ -10363,27 +10402,18 @@ var Bitfab = class {
10363
10402
  });
10364
10403
  },
10365
10404
  setMetadata: (metadata) => {
10366
- if (!this.shouldRecord()) {
10367
- return Promise.resolve();
10368
- }
10369
10405
  if (typeof metadata !== "object" || metadata === null) {
10370
10406
  return Promise.resolve();
10371
10407
  }
10372
10408
  return this.httpClient.patchTrace(traceId, { mergeMetadata: metadata });
10373
10409
  },
10374
10410
  setSessionId: (sessionId) => {
10375
- if (!this.shouldRecord()) {
10376
- return Promise.resolve();
10377
- }
10378
10411
  if (typeof sessionId !== "string" || sessionId.length === 0) {
10379
10412
  return Promise.resolve();
10380
10413
  }
10381
10414
  return this.httpClient.patchTrace(traceId, { setSessionId: sessionId });
10382
10415
  },
10383
10416
  setName: (name) => {
10384
- if (!this.shouldRecord()) {
10385
- return Promise.resolve();
10386
- }
10387
10417
  if (typeof name !== "string" || name.length === 0) {
10388
10418
  return Promise.resolve();
10389
10419
  }
@@ -10509,7 +10539,7 @@ var Bitfab = class {
10509
10539
  completed: true,
10510
10540
  ...params.dropped && { dropped: true },
10511
10541
  ...params.sessionId && { sessionId: params.sessionId },
10512
- ...params.testRunId && { testRunId: params.testRunId }
10542
+ ...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId)
10513
10543
  });
10514
10544
  }
10515
10545
  sendsSpanOnCompletion(context) {
@@ -10621,7 +10651,7 @@ var Bitfab = class {
10621
10651
  },
10622
10652
  ...params.declaredNode === true && { [DECLARED_NODE_FIELD]: true },
10623
10653
  rawSpan: externalSpan,
10624
- ...params.testRunId && { testRunId: params.testRunId },
10654
+ ...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId),
10625
10655
  ...params.mocked && { mocked: true },
10626
10656
  ...params.mockTarget && { mockTarget: params.mockTarget },
10627
10657
  ...params.mockSource && { mockSource: params.mockSource }