@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
@@ -3,17 +3,19 @@ import {
3
3
  HttpClient,
4
4
  awaitOnExit,
5
5
  awaitPendingRequests,
6
+ experimentIdWireFields,
6
7
  flushTraces,
7
8
  parseRetryAfterMs,
8
9
  serializePayloadBody
9
- } from "./chunk-6IM35I7O.js";
10
+ } from "./chunk-TX3HZEQO.js";
10
11
  export {
11
12
  BitfabError,
12
13
  HttpClient,
13
14
  awaitOnExit,
14
15
  awaitPendingRequests,
16
+ experimentIdWireFields,
15
17
  flushTraces,
16
18
  parseRetryAfterMs,
17
19
  serializePayloadBody
18
20
  };
19
- //# sourceMappingURL=http-FXLIHCQK.js.map
21
+ //# sourceMappingURL=http-GYCMIHBO.js.map
@@ -3,18 +3,20 @@ import {
3
3
  HttpClient,
4
4
  awaitOnExit,
5
5
  awaitPendingRequests,
6
+ experimentIdWireFields,
6
7
  flushTraces,
7
8
  parseRetryAfterMs,
8
9
  serializePayloadBody
9
- } from "./chunk-FBMHGUIK.js";
10
+ } from "./chunk-ZSCAAX44.js";
10
11
  import "./chunk-BAOIRE5T.js";
11
12
  export {
12
13
  BitfabError,
13
14
  HttpClient,
14
15
  awaitOnExit,
15
16
  awaitPendingRequests,
17
+ experimentIdWireFields,
16
18
  flushTraces,
17
19
  parseRetryAfterMs,
18
20
  serializePayloadBody
19
21
  };
20
- //# sourceMappingURL=http-HJJR2ZCE.js.map
22
+ //# sourceMappingURL=http-XDEB3KJG.js.map
package/dist/index.cjs CHANGED
@@ -42,7 +42,7 @@ var __version__, __packageName__;
42
42
  var init_version_generated = __esm({
43
43
  "src/version.generated.ts"() {
44
44
  "use strict";
45
- __version__ = "0.59.0";
45
+ __version__ = "0.60.0";
46
46
  __packageName__ = "@bitfab/sdk";
47
47
  }
48
48
  });
@@ -2104,6 +2104,7 @@ __export(http_exports, {
2104
2104
  HttpClient: () => HttpClient,
2105
2105
  awaitOnExit: () => awaitOnExit,
2106
2106
  awaitPendingRequests: () => awaitPendingRequests,
2107
+ experimentIdWireFields: () => experimentIdWireFields,
2107
2108
  flushTraces: () => flushTraces,
2108
2109
  parseRetryAfterMs: () => parseRetryAfterMs,
2109
2110
  serializePayloadBody: () => serializePayloadBody
@@ -2272,6 +2273,9 @@ function warnDroppedExternalTrace(error) {
2272
2273
  `a trace was dropped because the send step failed: ${describeError(error)}`
2273
2274
  );
2274
2275
  }
2276
+ function experimentIdWireFields(experimentId) {
2277
+ return { experimentId, testRunId: experimentId };
2278
+ }
2275
2279
  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;
2276
2280
  var init_http = __esm({
2277
2281
  "src/http.ts"() {
@@ -2876,7 +2880,7 @@ var init_http = __esm({
2876
2880
  }
2877
2881
  /**
2878
2882
  * Start a replay session by fetching historical traces.
2879
- * Blocking call - creates a test run and returns lightweight item references.
2883
+ * Blocking call - creates an experiment and returns lightweight item references.
2880
2884
  */
2881
2885
  async startReplay(traceFunctionKey, limit, traceIds, name, codeChangeDescription, codeChangeFiles, includeDbBranchLease, experimentGroupId, datasetIds, graderIds, dbBranchSettings, attempts, includeOriginalMetadata, onlyWithAssertions, judgeAssertions) {
2882
2886
  const payload = { traceFunctionKey };
@@ -2932,9 +2936,20 @@ var init_http = __esm({
2932
2936
  payload.git = git;
2933
2937
  }
2934
2938
  const timeout = includeDbBranchLease ? REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS : 3e4;
2935
- return this.request("/api/sdk/replay/start", payload, {
2936
- timeout
2937
- });
2939
+ const response = await this.request(
2940
+ "/api/sdk/replay/start",
2941
+ payload,
2942
+ { timeout }
2943
+ );
2944
+ const { testRunId, testRunUrl, ...rest } = response;
2945
+ const experimentId = response.experimentId ?? testRunId;
2946
+ const experimentUrl = response.experimentUrl ?? testRunUrl;
2947
+ if (experimentId === void 0 || experimentUrl === void 0) {
2948
+ throw new BitfabError(
2949
+ "Replay start response is missing the experiment ID or URL."
2950
+ );
2951
+ }
2952
+ return { ...rest, experimentId, experimentUrl };
2938
2953
  }
2939
2954
  /**
2940
2955
  * Fetch an external span by ID.
@@ -3031,21 +3046,21 @@ var init_http = __esm({
3031
3046
  * has a final status AND at least that many persisted spans, which is what
3032
3047
  * makes this a real barrier rather than a "the row exists" check.
3033
3048
  */
3034
- async getReplayStatus(testRunId, expectedSpanCounts) {
3049
+ async getReplayStatus(experimentId, expectedSpanCounts) {
3035
3050
  return this.request(
3036
3051
  "/api/sdk/replay/status",
3037
- { testRunId, expectedSpanCounts },
3052
+ { ...experimentIdWireFields(experimentId), expectedSpanCounts },
3038
3053
  { timeout: 3e4 }
3039
3054
  );
3040
3055
  }
3041
3056
  /**
3042
- * Mark a replay test run as completed.
3057
+ * Mark a replay experiment as completed.
3043
3058
  * Blocking call.
3044
3059
  */
3045
- async completeReplay(testRunId) {
3060
+ async completeReplay(experimentId) {
3046
3061
  return this.request(
3047
3062
  "/api/sdk/replay/complete",
3048
- { testRunId },
3063
+ experimentIdWireFields(experimentId),
3049
3064
  { timeout: REPLAY_COMPLETE_REQUEST_TIMEOUT_MS }
3050
3065
  );
3051
3066
  }
@@ -3067,11 +3082,11 @@ var init_http = __esm({
3067
3082
  * snapshot + preview branch and polls operations to readiness, which
3068
3083
  * can take seconds.
3069
3084
  */
3070
- async resolveDbBranchLease(testRunId, traceId, dbBranchSettings, attempt) {
3085
+ async resolveDbBranchLease(experimentId, traceId, dbBranchSettings, attempt) {
3071
3086
  return this.request(
3072
3087
  "/api/sdk/replay/resolveDbBranchLease",
3073
3088
  {
3074
- testRunId,
3089
+ ...experimentIdWireFields(experimentId),
3075
3090
  traceId,
3076
3091
  dbBranchSettings,
3077
3092
  ...attempt !== void 0 && attempt > 0 ? { attempt } : {}
@@ -3660,7 +3675,7 @@ function replayJsonReplacer(_key, value) {
3660
3675
  function serializeReplayResult(result) {
3661
3676
  return JSON.stringify(result, replayJsonReplacer, 2);
3662
3677
  }
3663
- async function preserveReplayFailure(operation, items, testRunId, testRunUrl) {
3678
+ async function preserveReplayFailure(operation, items, experimentId, experimentUrl) {
3664
3679
  try {
3665
3680
  return await operation();
3666
3681
  } catch (cause) {
@@ -3670,8 +3685,8 @@ async function preserveReplayFailure(operation, items, testRunId, testRunUrl) {
3670
3685
  throw new ReplayError(
3671
3686
  errorMessage(cause),
3672
3687
  items,
3673
- testRunId,
3674
- testRunUrl,
3688
+ experimentId,
3689
+ experimentUrl,
3675
3690
  cause
3676
3691
  );
3677
3692
  }
@@ -3725,7 +3740,7 @@ function buildMockTree(rootNode) {
3725
3740
  }
3726
3741
  return { spans };
3727
3742
  }
3728
- async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy, resolvedOverrides, replayedTraceId, attempt, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
3743
+ async function processItem(httpClient, serverItem, fn, experimentId, mockStrategy, resolvedOverrides, replayedTraceId, attempt, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
3729
3744
  let lease = includeDbBranchLease ? serverItem.dbBranchLease : void 0;
3730
3745
  let leaseError = includeDbBranchLease ? serverItem.dbBranchLeaseError : void 0;
3731
3746
  let dbSnapshotRef = serverItem.dbSnapshotRef;
@@ -3745,7 +3760,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
3745
3760
  let resolved2;
3746
3761
  try {
3747
3762
  resolved2 = await httpClient.resolveDbBranchLease(
3748
- testRunId,
3763
+ experimentId,
3749
3764
  originalTraceId,
3750
3765
  dbBranchSettings,
3751
3766
  attempt
@@ -3857,7 +3872,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
3857
3872
  replayStarted = performance.now();
3858
3873
  const maybePromise = runWithReplayContext(
3859
3874
  {
3860
- testRunId,
3875
+ experimentId,
3861
3876
  traceId: replayedTraceId,
3862
3877
  inputSourceSpanId: span.id,
3863
3878
  inputSourceTraceId: span.externalTraceId,
@@ -3940,14 +3955,14 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
3940
3955
  originalTraceOutline: null
3941
3956
  };
3942
3957
  }
3943
- async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds) {
3958
+ async function waitForReplayPersistence(httpClient, experimentId, replayedTraceIds) {
3944
3959
  const deferredSettled = await httpClient.settleDeferredWork(
3945
3960
  REPLAY_PERSISTENCE_TIMEOUT_MS
3946
3961
  );
3947
3962
  if (!deferredSettled) {
3948
3963
  httpClient.takeTraceDeliveries(replayedTraceIds);
3949
3964
  throw new BitfabError(
3950
- `Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (testRunId ${testRunId}).`
3965
+ `Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (experiment ${experimentId}).`
3951
3966
  );
3952
3967
  }
3953
3968
  if (!httpClient.hasClosedDeliveries(replayedTraceIds)) {
@@ -3976,7 +3991,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
3976
3991
  let missing = Object.keys(expectedSpanCounts).length;
3977
3992
  while (true) {
3978
3993
  const status = await httpClient.getReplayStatus(
3979
- testRunId,
3994
+ experimentId,
3980
3995
  expectedSpanCounts
3981
3996
  );
3982
3997
  const ready = status.traceIds ?? {};
@@ -3995,7 +4010,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
3995
4010
  }
3996
4011
  const cause = flushed ? "" : " Delivery was also not confirmed before the flush deadline, so the spans likely never reached the server.";
3997
4012
  throw new BitfabError(
3998
- `Replay traces were not fully persisted before the delivery deadline (testRunId ${testRunId}, missing ${missing} of ${Object.keys(expectedSpanCounts).length} trace(s)).${cause}`
4013
+ `Replay traces were not fully persisted before the delivery deadline (experiment ${experimentId}, missing ${missing} of ${Object.keys(expectedSpanCounts).length} trace(s)).${cause}`
3999
4014
  );
4000
4015
  }
4001
4016
  function sleepForReplayPersistence(ms) {
@@ -4062,8 +4077,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4062
4077
  }
4063
4078
  }
4064
4079
  const {
4065
- testRunId,
4066
- testRunUrl,
4080
+ experimentId,
4081
+ experimentUrl,
4067
4082
  items: serverItems
4068
4083
  } = await httpClient.startReplay(
4069
4084
  traceFunctionKey,
@@ -4096,7 +4111,14 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4096
4111
  }
4097
4112
  }
4098
4113
  const mockStrategy = options?.mock ?? "marked";
4099
- const fullTestRunUrl = `${serviceUrl}${testRunUrl}`;
4114
+ const fullExperimentUrl = `${serviceUrl}${experimentUrl}`;
4115
+ try {
4116
+ options?.onExperimentStart?.({
4117
+ experimentId,
4118
+ experimentUrl: fullExperimentUrl
4119
+ });
4120
+ } catch {
4121
+ }
4100
4122
  const resolvedOverrides = [
4101
4123
  ...normalizeMockOverrides(options?.mockOverride),
4102
4124
  ...registeredOverrides
@@ -4109,7 +4131,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4109
4131
  httpClient,
4110
4132
  serverItem,
4111
4133
  fn,
4112
- testRunId,
4134
+ experimentId,
4113
4135
  mockStrategy,
4114
4136
  resolvedOverrides,
4115
4137
  replayedTraceIds[index],
@@ -4164,7 +4186,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4164
4186
  }
4165
4187
  try {
4166
4188
  onItemFinish?.({
4167
- testRunId,
4189
+ experimentId,
4190
+ testRunId: experimentId,
4168
4191
  completed,
4169
4192
  total,
4170
4193
  succeeded,
@@ -4212,7 +4235,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4212
4235
  try {
4213
4236
  options.onItemStart?.({
4214
4237
  type: "started",
4215
- testRunId,
4238
+ experimentId,
4239
+ testRunId: experimentId,
4216
4240
  started,
4217
4241
  completed,
4218
4242
  total,
@@ -4231,21 +4255,23 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4231
4255
  } : void 0
4232
4256
  );
4233
4257
  if (options?.dryRun === true) {
4234
- await httpClient.completeReplay(testRunId).catch(() => void 0);
4258
+ await httpClient.completeReplay(experimentId).catch(() => void 0);
4235
4259
  const dryResult = {
4236
4260
  items: resultItems,
4237
- testRunId,
4238
- testRunUrl: fullTestRunUrl,
4261
+ experimentId,
4262
+ experimentUrl: fullExperimentUrl,
4263
+ testRunId: experimentId,
4264
+ testRunUrl: fullExperimentUrl,
4239
4265
  attempts
4240
4266
  };
4241
4267
  await writeReplayResultFile(dryResult);
4242
4268
  return dryResult;
4243
4269
  }
4244
4270
  const deliveredTraceIds = await preserveReplayFailure(
4245
- () => waitForReplayPersistence(httpClient, testRunId, replayedTraceIds),
4271
+ () => waitForReplayPersistence(httpClient, experimentId, replayedTraceIds),
4246
4272
  resultItems,
4247
- testRunId,
4248
- fullTestRunUrl
4273
+ experimentId,
4274
+ fullExperimentUrl
4249
4275
  );
4250
4276
  for (let index = 0; index < resultItems.length; index += 1) {
4251
4277
  const localId = replayedTraceIds[index];
@@ -4255,10 +4281,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4255
4281
  }
4256
4282
  }
4257
4283
  const completeResult = await preserveReplayFailure(
4258
- () => httpClient.completeReplay(testRunId),
4284
+ () => httpClient.completeReplay(experimentId),
4259
4285
  resultItems,
4260
- testRunId,
4261
- fullTestRunUrl
4286
+ experimentId,
4287
+ fullExperimentUrl
4262
4288
  );
4263
4289
  const serverTraceIds = completeResult.traceIds;
4264
4290
  const replayTokens = completeResult.tokens;
@@ -4285,20 +4311,20 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4285
4311
  if (completedCount > 0 && missing.length === completedCount) {
4286
4312
  const serverCount = completeResult.traceCount !== void 0 ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.` : "";
4287
4313
  const cause = new BitfabError(
4288
- `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.`
4314
+ `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.`
4289
4315
  );
4290
4316
  throw new ReplayError(
4291
4317
  cause.message,
4292
4318
  resultItems,
4293
- testRunId,
4294
- fullTestRunUrl,
4319
+ experimentId,
4320
+ fullExperimentUrl,
4295
4321
  cause
4296
4322
  );
4297
4323
  }
4298
4324
  if (missing.length > 0) {
4299
4325
  try {
4300
4326
  console.error(
4301
- `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.`
4327
+ `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.`
4302
4328
  );
4303
4329
  } catch {
4304
4330
  }
@@ -4306,8 +4332,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4306
4332
  }
4307
4333
  const result = {
4308
4334
  items: resultItems,
4309
- testRunId,
4310
- testRunUrl: fullTestRunUrl,
4335
+ experimentId,
4336
+ experimentUrl: fullExperimentUrl,
4337
+ testRunId: experimentId,
4338
+ testRunUrl: fullExperimentUrl,
4311
4339
  attempts
4312
4340
  };
4313
4341
  await writeReplayResultFile(result);
@@ -4315,7 +4343,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4315
4343
  try {
4316
4344
  options?.onProgress?.({
4317
4345
  type: "complete",
4318
- testRunId,
4346
+ experimentId,
4347
+ testRunId: experimentId,
4319
4348
  completed: total,
4320
4349
  total,
4321
4350
  succeeded,
@@ -4365,13 +4394,15 @@ var init_replay = __esm({
4365
4394
  MAX_REPLAY_ATTEMPTS = 100;
4366
4395
  BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
4367
4396
  ReplayError = class extends BitfabError {
4368
- constructor(message, items, testRunId, testRunUrl, cause) {
4369
- super(message, testRunUrl);
4397
+ constructor(message, items, experimentId, experimentUrl, cause) {
4398
+ super(message, experimentUrl);
4370
4399
  this.items = items;
4371
- this.testRunId = testRunId;
4372
- this.testRunUrl = testRunUrl;
4400
+ this.experimentId = experimentId;
4401
+ this.experimentUrl = experimentUrl;
4373
4402
  this.cause = cause;
4374
4403
  this.name = "ReplayError";
4404
+ this.testRunId = experimentId;
4405
+ this.testRunUrl = experimentUrl;
4375
4406
  }
4376
4407
  };
4377
4408
  DbBranchReplayError = class extends BitfabError {
@@ -6057,6 +6088,7 @@ var GradersClient = class {
6057
6088
  init_http();
6058
6089
 
6059
6090
  // src/labels.ts
6091
+ init_http();
6060
6092
  var LABELS_PATH = "/api/sdk/traces/labels";
6061
6093
  var HUMAN_LABELS_PATH = "/api/sdk/traces/labels/human";
6062
6094
  function labelEvidencePath(traceId, assertionId) {
@@ -6066,27 +6098,27 @@ var LabelsClient = class {
6066
6098
  constructor(httpClient) {
6067
6099
  this.httpClient = httpClient;
6068
6100
  }
6069
- async save(update, testRunId) {
6070
- const [outcome] = await this.saveAll([update], testRunId);
6101
+ async save(update, experimentId) {
6102
+ const [outcome] = await this.saveAll([update], experimentId);
6071
6103
  return outcome;
6072
6104
  }
6073
- async saveAll(updates, testRunId) {
6105
+ async saveAll(updates, experimentId) {
6074
6106
  const response = await this.httpClient.request(
6075
6107
  LABELS_PATH,
6076
6108
  {
6077
6109
  labels: updates,
6078
- ...testRunId === void 0 ? {} : { testRunId }
6110
+ ...experimentId === void 0 ? {} : experimentIdWireFields(experimentId)
6079
6111
  }
6080
6112
  );
6081
6113
  return response.labels;
6082
6114
  }
6083
6115
  /** Withhold a verdict for a trace or replay attempt whose check did not run. */
6084
- async skip(target, testRunId) {
6085
- return this.save({ ...target, skip: true }, testRunId);
6116
+ async skip(target, experimentId) {
6117
+ return this.save({ ...target, skip: true }, experimentId);
6086
6118
  }
6087
6119
  /** Clear a previous verdict for a trace, replay attempt, or assertion. */
6088
- async archive(target, testRunId) {
6089
- return this.save({ ...target, archive: true }, testRunId);
6120
+ async archive(target, experimentId) {
6121
+ return this.save({ ...target, archive: true }, experimentId);
6090
6122
  }
6091
6123
  async saveHuman(update) {
6092
6124
  const [outcome] = await this.saveHumanAll([update]);
@@ -8444,6 +8476,15 @@ var BitfabVercelAiHandler = class {
8444
8476
 
8445
8477
  // src/client.ts
8446
8478
  init_warnOnce();
8479
+ function resolveSpanExperimentId(options) {
8480
+ const { experimentId, testRunId } = options;
8481
+ if (experimentId !== void 0 && testRunId !== void 0 && experimentId !== testRunId) {
8482
+ throw new BitfabError(
8483
+ `experimentId ("${experimentId}") and its deprecated alias testRunId ("${testRunId}") were both passed with different values. Pass only experimentId.`
8484
+ );
8485
+ }
8486
+ return experimentId ?? testRunId;
8487
+ }
8447
8488
  var TRUNCATION_LIMIT_ORDER = [
8448
8489
  "max_depth",
8449
8490
  "max_captured_subtree_spans"
@@ -9033,13 +9074,12 @@ var Bitfab = class {
9033
9074
  "bitfab.node({ capture: false }) cannot use mockOnReplay: true because an uncaptured node has no recorded output."
9034
9075
  );
9035
9076
  }
9077
+ const experimentId = resolveSpanExperimentId(options);
9036
9078
  return {
9037
9079
  capture,
9038
9080
  type: options.type ?? "custom",
9039
9081
  ...options.name !== void 0 && { name: options.name },
9040
- ...options.testRunId !== void 0 && {
9041
- testRunId: options.testRunId
9042
- },
9082
+ ...experimentId !== void 0 && { experimentId },
9043
9083
  ...options.mockOnReplay !== void 0 && {
9044
9084
  mockOnReplay: options.mockOnReplay
9045
9085
  },
@@ -9174,6 +9214,7 @@ var Bitfab = class {
9174
9214
  return invokeWithoutNode();
9175
9215
  }
9176
9216
  const mockOnReplay = nodeConfiguration?.mockOnReplay ?? options.mockOnReplayDefault;
9217
+ const nodeExperimentId = nodeConfiguration === void 0 ? void 0 : resolveSpanExperimentId(nodeConfiguration);
9177
9218
  const childOptions = {
9178
9219
  name: spanName,
9179
9220
  type: nodeConfiguration?.type ?? "function",
@@ -9184,8 +9225,8 @@ var Bitfab = class {
9184
9225
  captureContent: true,
9185
9226
  autoTraceDefinition: definition,
9186
9227
  ...declaredNode && { declaredNode },
9187
- ...nodeConfiguration?.testRunId !== void 0 && {
9188
- testRunId: nodeConfiguration.testRunId
9228
+ ...nodeExperimentId !== void 0 && {
9229
+ experimentId: nodeExperimentId
9189
9230
  },
9190
9231
  ...mockOnReplay !== void 0 && {
9191
9232
  mockOnReplay
@@ -9846,6 +9887,7 @@ var Bitfab = class {
9846
9887
  const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
9847
9888
  const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
9848
9889
  const self = this;
9890
+ const optionExperimentId = resolveSpanExperimentId(options);
9849
9891
  const fnIsAsyncFunction = fn.constructor.name === "AsyncFunction";
9850
9892
  const fnReturnsPromise = fnIsAsyncFunction || (() => {
9851
9893
  try {
@@ -9948,7 +9990,7 @@ var Bitfab = class {
9948
9990
  const inputs = args;
9949
9991
  const startedAt = nowIsoTimestamp();
9950
9992
  const replayCtxAtStart = getReplayContext();
9951
- const testRunId = replayCtxAtStart?.testRunId ?? options.testRunId;
9993
+ const experimentId = replayCtxAtStart?.experimentId ?? optionExperimentId;
9952
9994
  if (isRootSpan && !activeTraceStates.has(traceId)) {
9953
9995
  const dbSnapshotRef = buildSnapshotRef(self.dbSnapshot, startedAt);
9954
9996
  self.simulationPlan.refresh();
@@ -9957,7 +9999,7 @@ var Bitfab = class {
9957
9999
  traceFunctionKey,
9958
10000
  startedAt,
9959
10001
  contexts: [],
9960
- ...testRunId !== void 0 && { testRunId },
10002
+ ...experimentId !== void 0 && { experimentId },
9961
10003
  ...replayCtxAtStart?.inputSourceTraceId && {
9962
10004
  inputSourceTraceId: replayCtxAtStart.inputSourceTraceId
9963
10005
  },
@@ -10003,7 +10045,7 @@ var Bitfab = class {
10003
10045
  contexts: newContext.contexts,
10004
10046
  prompt: newContext.prompt,
10005
10047
  endedAt,
10006
- ...testRunId !== void 0 && { testRunId },
10048
+ ...experimentId !== void 0 && { experimentId },
10007
10049
  ...replayCtx?.inputSourceSpanId && {
10008
10050
  inputSourceSpanId: replayCtx.inputSourceSpanId
10009
10051
  }
@@ -10024,7 +10066,7 @@ var Bitfab = class {
10024
10066
  name: traceState?.name,
10025
10067
  metadata: callerTraceMetadata(traceId),
10026
10068
  contexts: traceState?.contexts ?? [],
10027
- testRunId: traceState?.testRunId,
10069
+ experimentId: traceState?.experimentId,
10028
10070
  inputSourceTraceId: traceState?.inputSourceTraceId,
10029
10071
  replayAttempt: traceState?.replayAttempt,
10030
10072
  dbSnapshotRef: traceState?.dbSnapshotRef,
@@ -10338,9 +10380,6 @@ var Bitfab = class {
10338
10380
  return {
10339
10381
  traceId,
10340
10382
  addContext: (context) => {
10341
- if (!this.shouldRecord()) {
10342
- return Promise.resolve();
10343
- }
10344
10383
  if (typeof context !== "object" || context === null) {
10345
10384
  return Promise.resolve();
10346
10385
  }
@@ -10349,27 +10388,18 @@ var Bitfab = class {
10349
10388
  });
10350
10389
  },
10351
10390
  setMetadata: (metadata) => {
10352
- if (!this.shouldRecord()) {
10353
- return Promise.resolve();
10354
- }
10355
10391
  if (typeof metadata !== "object" || metadata === null) {
10356
10392
  return Promise.resolve();
10357
10393
  }
10358
10394
  return this.httpClient.patchTrace(traceId, { mergeMetadata: metadata });
10359
10395
  },
10360
10396
  setSessionId: (sessionId) => {
10361
- if (!this.shouldRecord()) {
10362
- return Promise.resolve();
10363
- }
10364
10397
  if (typeof sessionId !== "string" || sessionId.length === 0) {
10365
10398
  return Promise.resolve();
10366
10399
  }
10367
10400
  return this.httpClient.patchTrace(traceId, { setSessionId: sessionId });
10368
10401
  },
10369
10402
  setName: (name) => {
10370
- if (!this.shouldRecord()) {
10371
- return Promise.resolve();
10372
- }
10373
10403
  if (typeof name !== "string" || name.length === 0) {
10374
10404
  return Promise.resolve();
10375
10405
  }
@@ -10495,7 +10525,7 @@ var Bitfab = class {
10495
10525
  completed: true,
10496
10526
  ...params.dropped && { dropped: true },
10497
10527
  ...params.sessionId && { sessionId: params.sessionId },
10498
- ...params.testRunId && { testRunId: params.testRunId }
10528
+ ...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId)
10499
10529
  });
10500
10530
  }
10501
10531
  sendsSpanOnCompletion(context) {
@@ -10607,7 +10637,7 @@ var Bitfab = class {
10607
10637
  },
10608
10638
  ...params.declaredNode === true && { [DECLARED_NODE_FIELD]: true },
10609
10639
  rawSpan: externalSpan,
10610
- ...params.testRunId && { testRunId: params.testRunId },
10640
+ ...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId),
10611
10641
  ...params.mocked && { mocked: true },
10612
10642
  ...params.mockTarget && { mockTarget: params.mockTarget },
10613
10643
  ...params.mockSource && { mockSource: params.mockSource }