@bitfab/sdk 0.61.0 → 0.61.2

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 (141) hide show
  1. package/README.md +8 -5
  2. package/dist/autoTrace.cjs +1 -1
  3. package/dist/autoTrace.cjs.map +1 -1
  4. package/dist/autoTrace.js +1 -1
  5. package/dist/chunk-6R33XLNY.js +28 -0
  6. package/dist/chunk-6R33XLNY.js.map +1 -0
  7. package/dist/{chunk-5DNB7EN7.js → chunk-BMJNDIVA.js} +2 -2
  8. package/dist/chunk-BMJNDIVA.js.map +1 -0
  9. package/dist/{chunk-5IQRMYJP.js → chunk-DSVQPSAL.js} +122 -52
  10. package/dist/chunk-DSVQPSAL.js.map +1 -0
  11. package/dist/{chunk-PURSV2TW.js → chunk-HNEKBDI7.js} +7 -7
  12. package/dist/{chunk-PURSV2TW.js.map → chunk-HNEKBDI7.js.map} +1 -1
  13. package/dist/{chunk-5BM2IXP6.js → chunk-IR5KCKHF.js} +42 -2
  14. package/dist/{chunk-5BM2IXP6.js.map → chunk-IR5KCKHF.js.map} +1 -1
  15. package/dist/chunk-OXFZJP4E.js +30 -0
  16. package/dist/chunk-OXFZJP4E.js.map +1 -0
  17. package/dist/chunk-PACLPKDH.js +513 -0
  18. package/dist/chunk-PACLPKDH.js.map +1 -0
  19. package/dist/{chunk-YELSIC3R.js → chunk-SJPMWVJ3.js} +42 -2
  20. package/dist/{chunk-YELSIC3R.js.map → chunk-SJPMWVJ3.js.map} +1 -1
  21. package/dist/{chunk-UFGNWMWI.js → chunk-X5DRPZJJ.js} +171 -48
  22. package/dist/chunk-X5DRPZJJ.js.map +1 -0
  23. package/dist/{http-34JZXPJP.js → http-OEABHRHY.js} +2 -2
  24. package/dist/{http-TMPQJHDB.js → http-RNI6PKQ3.js} +2 -2
  25. package/dist/index.cjs +212 -49
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +27 -1
  28. package/dist/index.d.ts +27 -1
  29. package/dist/index.js +4 -4
  30. package/dist/node.cjs +212 -49
  31. package/dist/node.cjs.map +1 -1
  32. package/dist/node.js +4 -4
  33. package/dist/{replay-HTRWQTOY.js → replay-3ERB6W6N.js} +3 -3
  34. package/dist/replayCli.js +4 -3
  35. package/dist/replayCli.js.map +1 -1
  36. package/dist/seedCli.js +2 -2
  37. package/dist/transform/babel.cjs +418 -0
  38. package/dist/transform/babel.cjs.map +1 -0
  39. package/dist/transform/babel.d.cts +27 -0
  40. package/dist/transform/babel.d.ts +27 -0
  41. package/dist/transform/babel.js +379 -0
  42. package/dist/transform/babel.js.map +1 -0
  43. package/dist/transform/bun.cjs +586 -0
  44. package/dist/transform/bun.cjs.map +1 -0
  45. package/dist/transform/bun.d.cts +12 -0
  46. package/dist/transform/bun.d.ts +12 -0
  47. package/dist/transform/bun.js +14 -0
  48. package/dist/transform/bun.js.map +1 -0
  49. package/dist/transform/esbuild.cjs +586 -0
  50. package/dist/transform/esbuild.cjs.map +1 -0
  51. package/dist/transform/esbuild.d.cts +12 -0
  52. package/dist/transform/esbuild.d.ts +12 -0
  53. package/dist/transform/esbuild.js +14 -0
  54. package/dist/transform/esbuild.js.map +1 -0
  55. package/dist/transform/loaderRuntime.cjs +627 -0
  56. package/dist/transform/loaderRuntime.cjs.map +1 -0
  57. package/dist/transform/loaderRuntime.d.cts +12 -0
  58. package/dist/transform/loaderRuntime.d.ts +12 -0
  59. package/dist/transform/loaderRuntime.js +93 -0
  60. package/dist/transform/loaderRuntime.js.map +1 -0
  61. package/dist/transform/nest.cjs +589 -0
  62. package/dist/transform/nest.cjs.map +1 -0
  63. package/dist/transform/nest.d.cts +16 -0
  64. package/dist/transform/nest.d.ts +16 -0
  65. package/dist/transform/nest.js +17 -0
  66. package/dist/transform/nest.js.map +1 -0
  67. package/dist/transform/next.cjs +641 -0
  68. package/dist/transform/next.cjs.map +1 -0
  69. package/dist/transform/next.d.cts +40 -0
  70. package/dist/transform/next.d.ts +40 -0
  71. package/dist/transform/next.js +69 -0
  72. package/dist/transform/next.js.map +1 -0
  73. package/dist/transform/nodeLoader.js +640 -0
  74. package/dist/transform/nodeLoader.js.map +1 -0
  75. package/dist/transform/register.js +5 -0
  76. package/dist/transform/register.js.map +1 -0
  77. package/dist/transform/rolldown.cjs +586 -0
  78. package/dist/transform/rolldown.cjs.map +1 -0
  79. package/dist/transform/rolldown.d.cts +12 -0
  80. package/dist/transform/rolldown.d.ts +12 -0
  81. package/dist/transform/rolldown.js +14 -0
  82. package/dist/transform/rolldown.js.map +1 -0
  83. package/dist/transform/rollup.cjs +586 -0
  84. package/dist/transform/rollup.cjs.map +1 -0
  85. package/dist/transform/rollup.d.cts +12 -0
  86. package/dist/transform/rollup.d.ts +12 -0
  87. package/dist/transform/rollup.js +14 -0
  88. package/dist/transform/rollup.js.map +1 -0
  89. package/dist/transform/rsbuild.cjs +586 -0
  90. package/dist/transform/rsbuild.cjs.map +1 -0
  91. package/dist/transform/rsbuild.d.cts +12 -0
  92. package/dist/transform/rsbuild.d.ts +12 -0
  93. package/dist/transform/rsbuild.js +14 -0
  94. package/dist/transform/rsbuild.js.map +1 -0
  95. package/dist/transform/rspack.cjs +586 -0
  96. package/dist/transform/rspack.cjs.map +1 -0
  97. package/dist/transform/rspack.d.cts +12 -0
  98. package/dist/transform/rspack.d.ts +12 -0
  99. package/dist/transform/rspack.js +14 -0
  100. package/dist/transform/rspack.js.map +1 -0
  101. package/dist/transform/swc.cjs +592 -0
  102. package/dist/transform/swc.cjs.map +1 -0
  103. package/dist/transform/swc.d.cts +32 -0
  104. package/dist/transform/swc.d.ts +32 -0
  105. package/dist/transform/swc.js +33 -0
  106. package/dist/transform/swc.js.map +1 -0
  107. package/dist/transform/typescript.cjs +566 -0
  108. package/dist/transform/typescript.cjs.map +1 -0
  109. package/dist/transform/typescript.d.cts +22 -0
  110. package/dist/transform/typescript.d.ts +22 -0
  111. package/dist/transform/typescript.js +10 -0
  112. package/dist/transform/typescript.js.map +1 -0
  113. package/dist/transform/unplugin.cjs +583 -0
  114. package/dist/transform/unplugin.cjs.map +1 -0
  115. package/dist/transform/unplugin.d.cts +6 -0
  116. package/dist/transform/unplugin.d.ts +6 -0
  117. package/dist/transform/unplugin.js +9 -0
  118. package/dist/transform/unplugin.js.map +1 -0
  119. package/dist/transform/vite.cjs +586 -0
  120. package/dist/transform/vite.cjs.map +1 -0
  121. package/dist/transform/vite.d.cts +15 -0
  122. package/dist/transform/vite.d.ts +15 -0
  123. package/dist/transform/vite.js +14 -0
  124. package/dist/transform/vite.js.map +1 -0
  125. package/dist/transform/webpack.cjs +586 -0
  126. package/dist/transform/webpack.cjs.map +1 -0
  127. package/dist/transform/webpack.d.cts +12 -0
  128. package/dist/transform/webpack.d.ts +12 -0
  129. package/dist/transform/webpack.js +14 -0
  130. package/dist/transform/webpack.js.map +1 -0
  131. package/dist/transformOptions-Df2_Chtc.d.cts +10 -0
  132. package/dist/transformOptions-Df2_Chtc.d.ts +10 -0
  133. package/package.json +167 -7
  134. package/transform-loader.cjs +19 -0
  135. package/transform-loader.d.cts +19 -0
  136. package/dist/chunk-5DNB7EN7.js.map +0 -1
  137. package/dist/chunk-5IQRMYJP.js.map +0 -1
  138. package/dist/chunk-UFGNWMWI.js.map +0 -1
  139. /package/dist/{http-34JZXPJP.js.map → http-OEABHRHY.js.map} +0 -0
  140. /package/dist/{http-TMPQJHDB.js.map → http-RNI6PKQ3.js.map} +0 -0
  141. /package/dist/{replay-HTRWQTOY.js.map → replay-3ERB6W6N.js.map} +0 -0
package/dist/index.d.cts CHANGED
@@ -603,6 +603,7 @@ declare class HttpClient {
603
603
  * Blocking call - creates an experiment and returns lightweight item references.
604
604
  */
605
605
  startReplay(traceFunctionKey: string, limit: number | undefined, traceIds?: string[], name?: string, codeChangeDescription?: string | null, codeChangeFiles?: CodeChangeFile[] | null, includeDbBranchLease?: boolean, experimentGroupId?: string, datasetIds?: string[], graderIds?: string[], dbBranchSettings?: DbBranchSettings, attempts?: number, includeOriginalMetadata?: boolean, onlyWithAssertions?: boolean, judgeAssertions?: boolean): Promise<StartReplayResponse>;
606
+ resumeReplay(experimentId: string, traceFunctionKey: string, codeChangeFiles?: CodeChangeFile[] | null, force?: boolean): Promise<ResumeReplayResponse>;
606
607
  /**
607
608
  * Fetch an external span by ID.
608
609
  * Blocking GET request.
@@ -748,6 +749,28 @@ interface StartReplayResponse {
748
749
  originalMetadata?: Record<string, unknown>;
749
750
  }>;
750
751
  }
752
+ type StartReplayItem = StartReplayResponse["items"][number];
753
+ interface ResumeReplayWorkPair {
754
+ itemIndex: number;
755
+ attempt: number;
756
+ }
757
+ interface ResumeReplayFinishedItem {
758
+ originalTraceId: string;
759
+ attempt: number;
760
+ traceId: string;
761
+ hasError: boolean;
762
+ }
763
+ interface ResumeReplayResponse {
764
+ experimentId: string;
765
+ experimentUrl: string;
766
+ attempts: number;
767
+ items: StartReplayItem[];
768
+ work: ResumeReplayWorkPair[];
769
+ finished: ResumeReplayFinishedItem[];
770
+ skippedOriginalTraceIds: string[];
771
+ includeDbBranchLease: boolean;
772
+ dbBranchSettings: DbBranchSettings | null;
773
+ }
751
774
  interface ExternalSpanResponse {
752
775
  id: string;
753
776
  externalTraceId: string;
@@ -2046,6 +2069,8 @@ interface ReplayOptions {
2046
2069
  * callback never crashes the run.
2047
2070
  */
2048
2071
  onExperimentStart?: (experiment: ReplayExperiment) => void;
2072
+ resume?: string;
2073
+ force?: boolean;
2049
2074
  }
2050
2075
  /** The experiment a replay records into, passed to {@link ReplayOptions.onExperimentStart}. */
2051
2076
  interface ReplayExperiment {
@@ -2304,6 +2329,7 @@ interface ReplayItem<T> {
2304
2329
  dbBranchTimings: DbBranchTimings | null;
2305
2330
  traceOutline: TraceOutline | null;
2306
2331
  originalTraceOutline: TraceOutline | null;
2332
+ carriedOver?: boolean;
2307
2333
  }
2308
2334
 
2309
2335
  interface ReplayResult<T> {
@@ -3719,7 +3745,7 @@ interface CommitRef {
3719
3745
  /**
3720
3746
  * SDK version from package.json (injected at build time)
3721
3747
  */
3722
- declare const __version__ = "0.61.0";
3748
+ declare const __version__ = "0.61.2";
3723
3749
 
3724
3750
  /**
3725
3751
  * Constants for the Bitfab SDK.
package/dist/index.d.ts CHANGED
@@ -603,6 +603,7 @@ declare class HttpClient {
603
603
  * Blocking call - creates an experiment and returns lightweight item references.
604
604
  */
605
605
  startReplay(traceFunctionKey: string, limit: number | undefined, traceIds?: string[], name?: string, codeChangeDescription?: string | null, codeChangeFiles?: CodeChangeFile[] | null, includeDbBranchLease?: boolean, experimentGroupId?: string, datasetIds?: string[], graderIds?: string[], dbBranchSettings?: DbBranchSettings, attempts?: number, includeOriginalMetadata?: boolean, onlyWithAssertions?: boolean, judgeAssertions?: boolean): Promise<StartReplayResponse>;
606
+ resumeReplay(experimentId: string, traceFunctionKey: string, codeChangeFiles?: CodeChangeFile[] | null, force?: boolean): Promise<ResumeReplayResponse>;
606
607
  /**
607
608
  * Fetch an external span by ID.
608
609
  * Blocking GET request.
@@ -748,6 +749,28 @@ interface StartReplayResponse {
748
749
  originalMetadata?: Record<string, unknown>;
749
750
  }>;
750
751
  }
752
+ type StartReplayItem = StartReplayResponse["items"][number];
753
+ interface ResumeReplayWorkPair {
754
+ itemIndex: number;
755
+ attempt: number;
756
+ }
757
+ interface ResumeReplayFinishedItem {
758
+ originalTraceId: string;
759
+ attempt: number;
760
+ traceId: string;
761
+ hasError: boolean;
762
+ }
763
+ interface ResumeReplayResponse {
764
+ experimentId: string;
765
+ experimentUrl: string;
766
+ attempts: number;
767
+ items: StartReplayItem[];
768
+ work: ResumeReplayWorkPair[];
769
+ finished: ResumeReplayFinishedItem[];
770
+ skippedOriginalTraceIds: string[];
771
+ includeDbBranchLease: boolean;
772
+ dbBranchSettings: DbBranchSettings | null;
773
+ }
751
774
  interface ExternalSpanResponse {
752
775
  id: string;
753
776
  externalTraceId: string;
@@ -2046,6 +2069,8 @@ interface ReplayOptions {
2046
2069
  * callback never crashes the run.
2047
2070
  */
2048
2071
  onExperimentStart?: (experiment: ReplayExperiment) => void;
2072
+ resume?: string;
2073
+ force?: boolean;
2049
2074
  }
2050
2075
  /** The experiment a replay records into, passed to {@link ReplayOptions.onExperimentStart}. */
2051
2076
  interface ReplayExperiment {
@@ -2304,6 +2329,7 @@ interface ReplayItem<T> {
2304
2329
  dbBranchTimings: DbBranchTimings | null;
2305
2330
  traceOutline: TraceOutline | null;
2306
2331
  originalTraceOutline: TraceOutline | null;
2332
+ carriedOver?: boolean;
2307
2333
  }
2308
2334
 
2309
2335
  interface ReplayResult<T> {
@@ -3719,7 +3745,7 @@ interface CommitRef {
3719
3745
  /**
3720
3746
  * SDK version from package.json (injected at build time)
3721
3747
  */
3722
- declare const __version__ = "0.61.0";
3748
+ declare const __version__ = "0.61.2";
3723
3749
 
3724
3750
  /**
3725
3751
  * Constants for the Bitfab SDK.
package/dist/index.js CHANGED
@@ -26,8 +26,8 @@ import {
26
26
  getCurrentTrace,
27
27
  reseedFromRegistry,
28
28
  seedFromRegistry
29
- } from "./chunk-PURSV2TW.js";
30
- import "./chunk-5DNB7EN7.js";
29
+ } from "./chunk-HNEKBDI7.js";
30
+ import "./chunk-BMJNDIVA.js";
31
31
  import {
32
32
  BITFAB_PROGRESS_PREFIX,
33
33
  DbBranchReplayError,
@@ -35,7 +35,7 @@ import {
35
35
  ReplayError,
36
36
  reportReplayProgress,
37
37
  serializeReplayResult
38
- } from "./chunk-UFGNWMWI.js";
38
+ } from "./chunk-X5DRPZJJ.js";
39
39
  import {
40
40
  BitfabError,
41
41
  DEFAULT_SERVICE_URL,
@@ -43,7 +43,7 @@ import {
43
43
  MixedTracingError,
44
44
  __version__,
45
45
  flushTraces
46
- } from "./chunk-YELSIC3R.js";
46
+ } from "./chunk-SJPMWVJ3.js";
47
47
  import "./chunk-BAOIRE5T.js";
48
48
  export {
49
49
  AssertionCategoriesClient,
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.61.0";
91
+ __version__ = "0.61.2";
92
92
  __packageName__ = "@bitfab/sdk";
93
93
  }
94
94
  });
@@ -2958,6 +2958,46 @@ var init_http = __esm({
2958
2958
  }
2959
2959
  return { ...rest, experimentId, experimentUrl };
2960
2960
  }
2961
+ async resumeReplay(experimentId, traceFunctionKey, codeChangeFiles, force) {
2962
+ const payload = {
2963
+ experimentId,
2964
+ traceFunctionKey,
2965
+ lazyDbBranchLease: true
2966
+ };
2967
+ if (force === true) {
2968
+ payload.force = true;
2969
+ }
2970
+ if (codeChangeFiles !== void 0) {
2971
+ payload.codeChangeFiles = codeChangeFiles;
2972
+ }
2973
+ const git = await resolvedGitState();
2974
+ if (git && !isEmptyGitState(git)) {
2975
+ payload.git = git;
2976
+ }
2977
+ const response = await this.request(
2978
+ "/api/sdk/replay/resume",
2979
+ payload,
2980
+ { timeout: REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS }
2981
+ );
2982
+ const { testRunId, testRunUrl, ...rest } = response;
2983
+ const resumedExperimentId = response.experimentId ?? testRunId;
2984
+ const experimentUrl = response.experimentUrl ?? testRunUrl;
2985
+ if (resumedExperimentId === void 0 || experimentUrl === void 0) {
2986
+ throw new BitfabError(
2987
+ "Replay resume response is missing the experiment ID or URL."
2988
+ );
2989
+ }
2990
+ return {
2991
+ ...rest,
2992
+ experimentId: resumedExperimentId,
2993
+ experimentUrl,
2994
+ work: rest.work ?? [],
2995
+ finished: rest.finished ?? [],
2996
+ skippedOriginalTraceIds: rest.skippedOriginalTraceIds ?? [],
2997
+ includeDbBranchLease: rest.includeDbBranchLease ?? false,
2998
+ dbBranchSettings: rest.dbBranchSettings ?? null
2999
+ };
3000
+ }
2961
3001
  /**
2962
3002
  * Fetch an external span by ID.
2963
3003
  * Blocking GET request.
@@ -3593,6 +3633,88 @@ function expandReplayWork(serverItems, attempts) {
3593
3633
  (_, attempt) => serverItems.map((serverItem) => ({ serverItem, attempt }))
3594
3634
  ).flat();
3595
3635
  }
3636
+ function validateResume(resume, options) {
3637
+ if (resume.trim().length === 0) {
3638
+ throw new BitfabError("resume must be the ID of the experiment to resume.");
3639
+ }
3640
+ const conflicting = RESUME_CONFLICTING_OPTIONS.filter(
3641
+ (name) => options[name] !== void 0 && options[name] !== false
3642
+ );
3643
+ if (conflicting.length > 0) {
3644
+ throw new BitfabError(
3645
+ `resume continues experiment ${resume} with the traces, attempts, and graders it started with, so it cannot be combined with ${conflicting.join(", ")}. Drop those options, or start a new replay without resume.`
3646
+ );
3647
+ }
3648
+ }
3649
+ async function resumeReplaySession(httpClient, experimentId, traceFunctionKey, codeChangeFiles, force, requestedDbBranch) {
3650
+ const response = await httpClient.resumeReplay(
3651
+ experimentId,
3652
+ traceFunctionKey,
3653
+ codeChangeFiles,
3654
+ force
3655
+ );
3656
+ const work = response.work.map(({ itemIndex, attempt }) => {
3657
+ const serverItem = response.items[itemIndex];
3658
+ if (serverItem === void 0) {
3659
+ throw new BitfabError(
3660
+ `Replay resume for experiment ${response.experimentId} named item ${itemIndex}, but the server returned only ${response.items.length} item(s).`
3661
+ );
3662
+ }
3663
+ return { serverItem, attempt };
3664
+ });
3665
+ if (response.skippedOriginalTraceIds.length > 0) {
3666
+ try {
3667
+ console.warn(
3668
+ `Bitfab: ${response.skippedOriginalTraceIds.length} trace(s) selected when experiment ${response.experimentId} started no longer exist, so resume skips them: ${response.skippedOriginalTraceIds.join(", ")}`
3669
+ );
3670
+ } catch {
3671
+ }
3672
+ }
3673
+ if (requestedDbBranch !== void 0 && dbBranchEnabled(requestedDbBranch) !== response.includeDbBranchLease) {
3674
+ try {
3675
+ console.warn(
3676
+ `Bitfab: experiment ${response.experimentId} started with database branching ${response.includeDbBranchLease ? "on" : "off"}, so resume keeps it ${response.includeDbBranchLease ? "on" : "off"} and ignores the dbBranch option passed here.`
3677
+ );
3678
+ } catch {
3679
+ }
3680
+ }
3681
+ return {
3682
+ experimentId: response.experimentId,
3683
+ experimentUrl: response.experimentUrl,
3684
+ attempts: response.attempts,
3685
+ work,
3686
+ finished: response.finished,
3687
+ includeDbBranchLease: response.includeDbBranchLease,
3688
+ dbBranchSettings: response.dbBranchSettings ?? void 0
3689
+ };
3690
+ }
3691
+ function carriedOverReplayItem(finished) {
3692
+ return {
3693
+ traceId: finished.traceId,
3694
+ originalTraceId: finished.originalTraceId,
3695
+ originalSpanId: "",
3696
+ sourceTraceId: finished.originalTraceId,
3697
+ sourceSpanId: "",
3698
+ attempt: finished.attempt,
3699
+ input: [],
3700
+ result: void 0,
3701
+ originalOutput: void 0,
3702
+ error: finished.hasError ? CARRIED_OVER_ERROR : null,
3703
+ traceError: null,
3704
+ replayError: null,
3705
+ durationMs: null,
3706
+ originalDurationMs: null,
3707
+ originalTokens: null,
3708
+ originalModel: null,
3709
+ tokens: null,
3710
+ model: null,
3711
+ dbSnapshotRef: null,
3712
+ dbBranchTimings: null,
3713
+ traceOutline: null,
3714
+ originalTraceOutline: null,
3715
+ carriedOver: true
3716
+ };
3717
+ }
3596
3718
  function resolveAttempts(attempts) {
3597
3719
  if (attempts === void 0) {
3598
3720
  return 1;
@@ -4045,6 +4167,13 @@ async function mapWithConcurrency2(tasks, maxConcurrency, onSettled, onStarted)
4045
4167
  return results;
4046
4168
  }
4047
4169
  async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, registeredOverrides = []) {
4170
+ if (options?.resume !== void 0) {
4171
+ validateResume(options.resume, options);
4172
+ } else if (options?.force === true) {
4173
+ throw new BitfabError(
4174
+ "force only applies when resuming an experiment. Pass it together with resume."
4175
+ );
4176
+ }
4048
4177
  if (options?.traceIds !== void 0) {
4049
4178
  if (options.traceIds.length === 0) {
4050
4179
  throw new BitfabError("traceIds must contain at least one trace ID.");
@@ -4064,7 +4193,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4064
4193
  } catch {
4065
4194
  }
4066
4195
  }
4067
- const attempts = resolveAttempts(options?.attempts);
4196
+ const requestedAttempts = resolveAttempts(options?.attempts);
4068
4197
  const maxConcurrency = options?.maxConcurrency ?? 10;
4069
4198
  if (!Number.isInteger(maxConcurrency) || maxConcurrency < 1) {
4070
4199
  throw new BitfabError(
@@ -4083,40 +4212,59 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4083
4212
  }
4084
4213
  }
4085
4214
  }
4086
- const {
4087
- experimentId,
4088
- experimentUrl,
4089
- items: serverItems
4090
- } = await httpClient.startReplay(
4091
- traceFunctionKey,
4092
- // limit is meaningless with explicit traceIds (the ID list determines
4093
- // the count), so it's omitted from the request entirely.
4094
- options?.traceIds ? void 0 : options?.limit ?? 5,
4095
- options?.traceIds,
4096
- options?.name,
4097
- codeChangeDescription,
4098
- codeChangeFiles,
4099
- // A dry run executes nothing, so a branch would be provisioned (and billed)
4100
- // for code that never runs, and a seeded source's refusal would fail the item
4101
- // before it could report its resolved inputs.
4102
- dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true,
4103
- options?.experimentGroupId,
4104
- datasetIds,
4105
- options?.graderIds,
4106
- resolveDbBranchSettings(options?.dbBranch),
4107
- attempts,
4108
- options?.adaptInputs !== void 0,
4109
- options?.onlyWithAssertions,
4110
- options?.judgeAssertions
4111
- );
4112
- if (serverItems.length === 0) {
4113
- try {
4114
- console.warn(
4115
- `Bitfab: no traces matched "${traceFunctionKey}", so this replay ran nothing. Capture a trace, or seed one with seedTrace, before replaying.`
4116
- );
4117
- } catch {
4215
+ const includeDbBranchLease = dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true;
4216
+ let session;
4217
+ if (options?.resume === void 0) {
4218
+ const started2 = await httpClient.startReplay(
4219
+ traceFunctionKey,
4220
+ // limit is meaningless with explicit traceIds (the ID list determines
4221
+ // the count), so it's omitted from the request entirely.
4222
+ options?.traceIds ? void 0 : options?.limit ?? 5,
4223
+ options?.traceIds,
4224
+ options?.name,
4225
+ codeChangeDescription,
4226
+ codeChangeFiles,
4227
+ // A dry run executes nothing, so a branch would be provisioned (and billed)
4228
+ // for code that never runs, and a seeded source's refusal would fail the item
4229
+ // before it could report its resolved inputs.
4230
+ includeDbBranchLease,
4231
+ options?.experimentGroupId,
4232
+ datasetIds,
4233
+ options?.graderIds,
4234
+ resolveDbBranchSettings(options?.dbBranch),
4235
+ requestedAttempts,
4236
+ options?.adaptInputs !== void 0,
4237
+ options?.onlyWithAssertions,
4238
+ options?.judgeAssertions
4239
+ );
4240
+ if (started2.items.length === 0) {
4241
+ try {
4242
+ console.warn(
4243
+ `Bitfab: no traces matched "${traceFunctionKey}", so this replay ran nothing. Capture a trace, or seed one with seedTrace, before replaying.`
4244
+ );
4245
+ } catch {
4246
+ }
4118
4247
  }
4248
+ session = {
4249
+ experimentId: started2.experimentId,
4250
+ experimentUrl: started2.experimentUrl,
4251
+ attempts: requestedAttempts,
4252
+ work: expandReplayWork(started2.items, requestedAttempts),
4253
+ finished: [],
4254
+ includeDbBranchLease,
4255
+ dbBranchSettings: resolveDbBranchSettings(options?.dbBranch)
4256
+ };
4257
+ } else {
4258
+ session = await resumeReplaySession(
4259
+ httpClient,
4260
+ options.resume,
4261
+ traceFunctionKey,
4262
+ codeChangeFiles,
4263
+ options.force,
4264
+ options.dbBranch
4265
+ );
4119
4266
  }
4267
+ const { experimentId, experimentUrl, attempts } = session;
4120
4268
  const mockStrategy = options?.mock ?? "marked";
4121
4269
  const fullExperimentUrl = `${serviceUrl}${experimentUrl}`;
4122
4270
  try {
@@ -4130,7 +4278,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4130
4278
  ...normalizeMockOverrides(options?.mockOverride),
4131
4279
  ...registeredOverrides
4132
4280
  ];
4133
- const workItems = expandReplayWork(serverItems, attempts);
4281
+ const workItems = session.work;
4282
+ const carriedOverItems = session.finished.map(
4283
+ (finished) => carriedOverReplayItem(finished)
4284
+ );
4134
4285
  const replayedTraceIds = workItems.map(() => randomUuid());
4135
4286
  httpClient.trackTraceDeliveries(replayedTraceIds);
4136
4287
  const tasks = workItems.map(
@@ -4143,18 +4294,18 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4143
4294
  resolvedOverrides,
4144
4295
  replayedTraceIds[index],
4145
4296
  attempt,
4146
- dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true,
4147
- resolveDbBranchSettings(options?.dbBranch),
4297
+ session.includeDbBranchLease,
4298
+ session.dbBranchSettings,
4148
4299
  options?.adaptInputs,
4149
4300
  options?.dryRun === true
4150
4301
  )
4151
4302
  );
4152
- const total = tasks.length;
4303
+ const total = tasks.length + carriedOverItems.length;
4153
4304
  const onItemFinish = options?.onItemFinish ?? options?.onProgress;
4154
- let completed = 0;
4155
- let started = 0;
4156
- let succeeded = 0;
4157
- let errored = 0;
4305
+ let completed = carriedOverItems.length;
4306
+ let started = carriedOverItems.length;
4307
+ let errored = carriedOverItems.filter((item) => item.error !== null).length;
4308
+ let succeeded = completed - errored;
4158
4309
  let flushInFlight = null;
4159
4310
  let flushPending = false;
4160
4311
  const flushFinishedItemTrace = () => {
@@ -4174,7 +4325,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4174
4325
  }
4175
4326
  return flushInFlight;
4176
4327
  };
4177
- const resultItems = await mapWithConcurrency2(
4328
+ const ranItems = await mapWithConcurrency2(
4178
4329
  tasks,
4179
4330
  maxConcurrency,
4180
4331
  async (item, index) => {
@@ -4261,6 +4412,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4261
4412
  }
4262
4413
  } : void 0
4263
4414
  );
4415
+ const resultItems = [...carriedOverItems, ...ranItems];
4264
4416
  if (options?.dryRun === true) {
4265
4417
  await httpClient.completeReplay(experimentId).catch(() => void 0);
4266
4418
  const dryResult = {
@@ -4280,11 +4432,11 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4280
4432
  experimentId,
4281
4433
  fullExperimentUrl
4282
4434
  );
4283
- for (let index = 0; index < resultItems.length; index += 1) {
4435
+ for (let index = 0; index < ranItems.length; index += 1) {
4284
4436
  const localId = replayedTraceIds[index];
4285
4437
  const readBack = localId ? deliveredTraceIds[localId] : void 0;
4286
4438
  if (readBack !== void 0) {
4287
- resultItems[index].traceId = readBack;
4439
+ ranItems[index].traceId = readBack;
4288
4440
  }
4289
4441
  }
4290
4442
  const completeResult = await preserveReplayFailure(
@@ -4298,8 +4450,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4298
4450
  if (serverTraceIds !== void 0) {
4299
4451
  const missing = [];
4300
4452
  let completedCount = 0;
4301
- for (let index = 0; index < resultItems.length; index += 1) {
4302
- const item = resultItems[index];
4453
+ for (let index = 0; index < ranItems.length; index += 1) {
4454
+ const item = ranItems[index];
4303
4455
  const localId = replayedTraceIds[index];
4304
4456
  const mapped = localId ? serverTraceIds[localId] : void 0;
4305
4457
  item.traceId = item.traceId ?? mapped ?? null;
@@ -4385,7 +4537,7 @@ async function writeReplayResultFile(result) {
4385
4537
  }
4386
4538
  }
4387
4539
  }
4388
- var REPLAY_PERSISTENCE_TIMEOUT_MS, MAX_REPLAY_ATTEMPTS, BITFAB_PROGRESS_PREFIX, ReplayError, DbBranchReplayError;
4540
+ var REPLAY_PERSISTENCE_TIMEOUT_MS, MAX_REPLAY_ATTEMPTS, RESUME_CONFLICTING_OPTIONS, CARRIED_OVER_ERROR, BITFAB_PROGRESS_PREFIX, ReplayError, DbBranchReplayError;
4389
4541
  var init_replay = __esm({
4390
4542
  "src/replay.ts"() {
4391
4543
  "use strict";
@@ -4399,6 +4551,17 @@ var init_replay = __esm({
4399
4551
  init_serialize();
4400
4552
  REPLAY_PERSISTENCE_TIMEOUT_MS = 3e4;
4401
4553
  MAX_REPLAY_ATTEMPTS = 100;
4554
+ RESUME_CONFLICTING_OPTIONS = [
4555
+ "traceIds",
4556
+ "limit",
4557
+ "datasetId",
4558
+ "datasetIds",
4559
+ "attempts",
4560
+ "graderIds",
4561
+ "onlyWithAssertions",
4562
+ "dryRun"
4563
+ ];
4564
+ CARRIED_OVER_ERROR = "This item errored in an earlier run of this experiment, before it was resumed.";
4402
4565
  BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
4403
4566
  ReplayError = class extends BitfabError {
4404
4567
  constructor(message, items, experimentId, experimentUrl, cause) {
@@ -5231,7 +5394,7 @@ function settleAutoTraceRoot(context) {
5231
5394
  }
5232
5395
  warnOnce(
5233
5396
  "auto-trace-transform-missing",
5234
- `trace root "${context.traceFunctionKey}" recorded only its own span. No module in this build was compiled by @bitfab/transform, so calls beneath the root were not discovered. Install @bitfab/transform and add its adapter to the server build: ${SUBTREE_TRACING_DOCS_URL}`
5397
+ `trace root "${context.traceFunctionKey}" recorded only its own span. No module in this build was compiled by @bitfab/sdk/transform, so calls beneath the root were not discovered. Add the SDK's transform adapter to the server build: ${SUBTREE_TRACING_DOCS_URL}`
5235
5398
  );
5236
5399
  }
5237
5400
  function runWithAutoTraceRootContext(context, spanStack, fn) {