bitfab 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-6JQL37VC.js → chunk-A4UVO6BQ.js} +171 -48
  8. package/dist/chunk-A4UVO6BQ.js.map +1 -0
  9. package/dist/{chunk-5DNB7EN7.js → chunk-BMJNDIVA.js} +2 -2
  10. package/dist/chunk-BMJNDIVA.js.map +1 -0
  11. package/dist/{chunk-2M62EGYK.js → chunk-INA6W7OB.js} +42 -2
  12. package/dist/{chunk-2M62EGYK.js.map → chunk-INA6W7OB.js.map} +1 -1
  13. package/dist/{chunk-O52C6BRF.js → chunk-LUOCT4HG.js} +7 -7
  14. package/dist/{chunk-O52C6BRF.js.map → chunk-LUOCT4HG.js.map} +1 -1
  15. package/dist/{chunk-J54ZR6NF.js → chunk-MTK6PZHA.js} +122 -52
  16. package/dist/chunk-MTK6PZHA.js.map +1 -0
  17. package/dist/{chunk-3BTITSNA.js → chunk-ONZFMRRF.js} +42 -2
  18. package/dist/{chunk-3BTITSNA.js.map → chunk-ONZFMRRF.js.map} +1 -1
  19. package/dist/chunk-OXFZJP4E.js +30 -0
  20. package/dist/chunk-OXFZJP4E.js.map +1 -0
  21. package/dist/chunk-PACLPKDH.js +513 -0
  22. package/dist/chunk-PACLPKDH.js.map +1 -0
  23. package/dist/{http-2EZA7I4F.js → http-2R6MSRVA.js} +2 -2
  24. package/dist/{http-PKQBVZD6.js → http-KM6QWKAP.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-XC2YOK4X.js → replay-6UUBJBLK.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-6JQL37VC.js.map +0 -1
  138. package/dist/chunk-J54ZR6NF.js.map +0 -1
  139. /package/dist/{http-2EZA7I4F.js.map → http-2R6MSRVA.js.map} +0 -0
  140. /package/dist/{http-PKQBVZD6.js.map → http-KM6QWKAP.js.map} +0 -0
  141. /package/dist/{replay-XC2YOK4X.js.map → replay-6UUBJBLK.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
@@ -35,8 +35,8 @@ import {
35
35
  getCurrentTrace,
36
36
  reseedFromRegistry,
37
37
  seedFromRegistry
38
- } from "./chunk-O52C6BRF.js";
39
- import "./chunk-5DNB7EN7.js";
38
+ } from "./chunk-LUOCT4HG.js";
39
+ import "./chunk-BMJNDIVA.js";
40
40
  import {
41
41
  BITFAB_PROGRESS_PREFIX,
42
42
  DbBranchReplayError,
@@ -44,7 +44,7 @@ import {
44
44
  ReplayError,
45
45
  reportReplayProgress,
46
46
  serializeReplayResult
47
- } from "./chunk-6JQL37VC.js";
47
+ } from "./chunk-A4UVO6BQ.js";
48
48
  import {
49
49
  BitfabError,
50
50
  DEFAULT_SERVICE_URL,
@@ -52,7 +52,7 @@ import {
52
52
  MixedTracingError,
53
53
  __version__,
54
54
  flushTraces
55
- } from "./chunk-2M62EGYK.js";
55
+ } from "./chunk-INA6W7OB.js";
56
56
  import "./chunk-BAOIRE5T.js";
57
57
  export {
58
58
  AssertionCategoriesClient,
package/dist/node.cjs CHANGED
@@ -97,7 +97,7 @@ var __version__, __packageName__;
97
97
  var init_version_generated = __esm({
98
98
  "src/version.generated.ts"() {
99
99
  "use strict";
100
- __version__ = "0.61.0";
100
+ __version__ = "0.61.2";
101
101
  __packageName__ = "bitfab";
102
102
  }
103
103
  });
@@ -2967,6 +2967,46 @@ var init_http = __esm({
2967
2967
  }
2968
2968
  return { ...rest, experimentId, experimentUrl };
2969
2969
  }
2970
+ async resumeReplay(experimentId, traceFunctionKey, codeChangeFiles, force) {
2971
+ const payload = {
2972
+ experimentId,
2973
+ traceFunctionKey,
2974
+ lazyDbBranchLease: true
2975
+ };
2976
+ if (force === true) {
2977
+ payload.force = true;
2978
+ }
2979
+ if (codeChangeFiles !== void 0) {
2980
+ payload.codeChangeFiles = codeChangeFiles;
2981
+ }
2982
+ const git = await resolvedGitState();
2983
+ if (git && !isEmptyGitState(git)) {
2984
+ payload.git = git;
2985
+ }
2986
+ const response = await this.request(
2987
+ "/api/sdk/replay/resume",
2988
+ payload,
2989
+ { timeout: REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS }
2990
+ );
2991
+ const { testRunId, testRunUrl, ...rest } = response;
2992
+ const resumedExperimentId = response.experimentId ?? testRunId;
2993
+ const experimentUrl = response.experimentUrl ?? testRunUrl;
2994
+ if (resumedExperimentId === void 0 || experimentUrl === void 0) {
2995
+ throw new BitfabError(
2996
+ "Replay resume response is missing the experiment ID or URL."
2997
+ );
2998
+ }
2999
+ return {
3000
+ ...rest,
3001
+ experimentId: resumedExperimentId,
3002
+ experimentUrl,
3003
+ work: rest.work ?? [],
3004
+ finished: rest.finished ?? [],
3005
+ skippedOriginalTraceIds: rest.skippedOriginalTraceIds ?? [],
3006
+ includeDbBranchLease: rest.includeDbBranchLease ?? false,
3007
+ dbBranchSettings: rest.dbBranchSettings ?? null
3008
+ };
3009
+ }
2970
3010
  /**
2971
3011
  * Fetch an external span by ID.
2972
3012
  * Blocking GET request.
@@ -3602,6 +3642,88 @@ function expandReplayWork(serverItems, attempts) {
3602
3642
  (_, attempt) => serverItems.map((serverItem) => ({ serverItem, attempt }))
3603
3643
  ).flat();
3604
3644
  }
3645
+ function validateResume(resume, options) {
3646
+ if (resume.trim().length === 0) {
3647
+ throw new BitfabError("resume must be the ID of the experiment to resume.");
3648
+ }
3649
+ const conflicting = RESUME_CONFLICTING_OPTIONS.filter(
3650
+ (name) => options[name] !== void 0 && options[name] !== false
3651
+ );
3652
+ if (conflicting.length > 0) {
3653
+ throw new BitfabError(
3654
+ `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.`
3655
+ );
3656
+ }
3657
+ }
3658
+ async function resumeReplaySession(httpClient, experimentId, traceFunctionKey, codeChangeFiles, force, requestedDbBranch) {
3659
+ const response = await httpClient.resumeReplay(
3660
+ experimentId,
3661
+ traceFunctionKey,
3662
+ codeChangeFiles,
3663
+ force
3664
+ );
3665
+ const work = response.work.map(({ itemIndex, attempt }) => {
3666
+ const serverItem = response.items[itemIndex];
3667
+ if (serverItem === void 0) {
3668
+ throw new BitfabError(
3669
+ `Replay resume for experiment ${response.experimentId} named item ${itemIndex}, but the server returned only ${response.items.length} item(s).`
3670
+ );
3671
+ }
3672
+ return { serverItem, attempt };
3673
+ });
3674
+ if (response.skippedOriginalTraceIds.length > 0) {
3675
+ try {
3676
+ console.warn(
3677
+ `Bitfab: ${response.skippedOriginalTraceIds.length} trace(s) selected when experiment ${response.experimentId} started no longer exist, so resume skips them: ${response.skippedOriginalTraceIds.join(", ")}`
3678
+ );
3679
+ } catch {
3680
+ }
3681
+ }
3682
+ if (requestedDbBranch !== void 0 && dbBranchEnabled(requestedDbBranch) !== response.includeDbBranchLease) {
3683
+ try {
3684
+ console.warn(
3685
+ `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.`
3686
+ );
3687
+ } catch {
3688
+ }
3689
+ }
3690
+ return {
3691
+ experimentId: response.experimentId,
3692
+ experimentUrl: response.experimentUrl,
3693
+ attempts: response.attempts,
3694
+ work,
3695
+ finished: response.finished,
3696
+ includeDbBranchLease: response.includeDbBranchLease,
3697
+ dbBranchSettings: response.dbBranchSettings ?? void 0
3698
+ };
3699
+ }
3700
+ function carriedOverReplayItem(finished) {
3701
+ return {
3702
+ traceId: finished.traceId,
3703
+ originalTraceId: finished.originalTraceId,
3704
+ originalSpanId: "",
3705
+ sourceTraceId: finished.originalTraceId,
3706
+ sourceSpanId: "",
3707
+ attempt: finished.attempt,
3708
+ input: [],
3709
+ result: void 0,
3710
+ originalOutput: void 0,
3711
+ error: finished.hasError ? CARRIED_OVER_ERROR : null,
3712
+ traceError: null,
3713
+ replayError: null,
3714
+ durationMs: null,
3715
+ originalDurationMs: null,
3716
+ originalTokens: null,
3717
+ originalModel: null,
3718
+ tokens: null,
3719
+ model: null,
3720
+ dbSnapshotRef: null,
3721
+ dbBranchTimings: null,
3722
+ traceOutline: null,
3723
+ originalTraceOutline: null,
3724
+ carriedOver: true
3725
+ };
3726
+ }
3605
3727
  function resolveAttempts(attempts) {
3606
3728
  if (attempts === void 0) {
3607
3729
  return 1;
@@ -4054,6 +4176,13 @@ async function mapWithConcurrency2(tasks, maxConcurrency, onSettled, onStarted)
4054
4176
  return results;
4055
4177
  }
4056
4178
  async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, registeredOverrides = []) {
4179
+ if (options?.resume !== void 0) {
4180
+ validateResume(options.resume, options);
4181
+ } else if (options?.force === true) {
4182
+ throw new BitfabError(
4183
+ "force only applies when resuming an experiment. Pass it together with resume."
4184
+ );
4185
+ }
4057
4186
  if (options?.traceIds !== void 0) {
4058
4187
  if (options.traceIds.length === 0) {
4059
4188
  throw new BitfabError("traceIds must contain at least one trace ID.");
@@ -4073,7 +4202,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4073
4202
  } catch {
4074
4203
  }
4075
4204
  }
4076
- const attempts = resolveAttempts(options?.attempts);
4205
+ const requestedAttempts = resolveAttempts(options?.attempts);
4077
4206
  const maxConcurrency = options?.maxConcurrency ?? 10;
4078
4207
  if (!Number.isInteger(maxConcurrency) || maxConcurrency < 1) {
4079
4208
  throw new BitfabError(
@@ -4092,40 +4221,59 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4092
4221
  }
4093
4222
  }
4094
4223
  }
4095
- const {
4096
- experimentId,
4097
- experimentUrl,
4098
- items: serverItems
4099
- } = await httpClient.startReplay(
4100
- traceFunctionKey,
4101
- // limit is meaningless with explicit traceIds (the ID list determines
4102
- // the count), so it's omitted from the request entirely.
4103
- options?.traceIds ? void 0 : options?.limit ?? 5,
4104
- options?.traceIds,
4105
- options?.name,
4106
- codeChangeDescription,
4107
- codeChangeFiles,
4108
- // A dry run executes nothing, so a branch would be provisioned (and billed)
4109
- // for code that never runs, and a seeded source's refusal would fail the item
4110
- // before it could report its resolved inputs.
4111
- dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true,
4112
- options?.experimentGroupId,
4113
- datasetIds,
4114
- options?.graderIds,
4115
- resolveDbBranchSettings(options?.dbBranch),
4116
- attempts,
4117
- options?.adaptInputs !== void 0,
4118
- options?.onlyWithAssertions,
4119
- options?.judgeAssertions
4120
- );
4121
- if (serverItems.length === 0) {
4122
- try {
4123
- console.warn(
4124
- `Bitfab: no traces matched "${traceFunctionKey}", so this replay ran nothing. Capture a trace, or seed one with seedTrace, before replaying.`
4125
- );
4126
- } catch {
4224
+ const includeDbBranchLease = dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true;
4225
+ let session;
4226
+ if (options?.resume === void 0) {
4227
+ const started2 = await httpClient.startReplay(
4228
+ traceFunctionKey,
4229
+ // limit is meaningless with explicit traceIds (the ID list determines
4230
+ // the count), so it's omitted from the request entirely.
4231
+ options?.traceIds ? void 0 : options?.limit ?? 5,
4232
+ options?.traceIds,
4233
+ options?.name,
4234
+ codeChangeDescription,
4235
+ codeChangeFiles,
4236
+ // A dry run executes nothing, so a branch would be provisioned (and billed)
4237
+ // for code that never runs, and a seeded source's refusal would fail the item
4238
+ // before it could report its resolved inputs.
4239
+ includeDbBranchLease,
4240
+ options?.experimentGroupId,
4241
+ datasetIds,
4242
+ options?.graderIds,
4243
+ resolveDbBranchSettings(options?.dbBranch),
4244
+ requestedAttempts,
4245
+ options?.adaptInputs !== void 0,
4246
+ options?.onlyWithAssertions,
4247
+ options?.judgeAssertions
4248
+ );
4249
+ if (started2.items.length === 0) {
4250
+ try {
4251
+ console.warn(
4252
+ `Bitfab: no traces matched "${traceFunctionKey}", so this replay ran nothing. Capture a trace, or seed one with seedTrace, before replaying.`
4253
+ );
4254
+ } catch {
4255
+ }
4127
4256
  }
4257
+ session = {
4258
+ experimentId: started2.experimentId,
4259
+ experimentUrl: started2.experimentUrl,
4260
+ attempts: requestedAttempts,
4261
+ work: expandReplayWork(started2.items, requestedAttempts),
4262
+ finished: [],
4263
+ includeDbBranchLease,
4264
+ dbBranchSettings: resolveDbBranchSettings(options?.dbBranch)
4265
+ };
4266
+ } else {
4267
+ session = await resumeReplaySession(
4268
+ httpClient,
4269
+ options.resume,
4270
+ traceFunctionKey,
4271
+ codeChangeFiles,
4272
+ options.force,
4273
+ options.dbBranch
4274
+ );
4128
4275
  }
4276
+ const { experimentId, experimentUrl, attempts } = session;
4129
4277
  const mockStrategy = options?.mock ?? "marked";
4130
4278
  const fullExperimentUrl = `${serviceUrl}${experimentUrl}`;
4131
4279
  try {
@@ -4139,7 +4287,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4139
4287
  ...normalizeMockOverrides(options?.mockOverride),
4140
4288
  ...registeredOverrides
4141
4289
  ];
4142
- const workItems = expandReplayWork(serverItems, attempts);
4290
+ const workItems = session.work;
4291
+ const carriedOverItems = session.finished.map(
4292
+ (finished) => carriedOverReplayItem(finished)
4293
+ );
4143
4294
  const replayedTraceIds = workItems.map(() => randomUuid());
4144
4295
  httpClient.trackTraceDeliveries(replayedTraceIds);
4145
4296
  const tasks = workItems.map(
@@ -4152,18 +4303,18 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4152
4303
  resolvedOverrides,
4153
4304
  replayedTraceIds[index],
4154
4305
  attempt,
4155
- dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true,
4156
- resolveDbBranchSettings(options?.dbBranch),
4306
+ session.includeDbBranchLease,
4307
+ session.dbBranchSettings,
4157
4308
  options?.adaptInputs,
4158
4309
  options?.dryRun === true
4159
4310
  )
4160
4311
  );
4161
- const total = tasks.length;
4312
+ const total = tasks.length + carriedOverItems.length;
4162
4313
  const onItemFinish = options?.onItemFinish ?? options?.onProgress;
4163
- let completed = 0;
4164
- let started = 0;
4165
- let succeeded = 0;
4166
- let errored = 0;
4314
+ let completed = carriedOverItems.length;
4315
+ let started = carriedOverItems.length;
4316
+ let errored = carriedOverItems.filter((item) => item.error !== null).length;
4317
+ let succeeded = completed - errored;
4167
4318
  let flushInFlight = null;
4168
4319
  let flushPending = false;
4169
4320
  const flushFinishedItemTrace = () => {
@@ -4183,7 +4334,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4183
4334
  }
4184
4335
  return flushInFlight;
4185
4336
  };
4186
- const resultItems = await mapWithConcurrency2(
4337
+ const ranItems = await mapWithConcurrency2(
4187
4338
  tasks,
4188
4339
  maxConcurrency,
4189
4340
  async (item, index) => {
@@ -4270,6 +4421,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4270
4421
  }
4271
4422
  } : void 0
4272
4423
  );
4424
+ const resultItems = [...carriedOverItems, ...ranItems];
4273
4425
  if (options?.dryRun === true) {
4274
4426
  await httpClient.completeReplay(experimentId).catch(() => void 0);
4275
4427
  const dryResult = {
@@ -4289,11 +4441,11 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4289
4441
  experimentId,
4290
4442
  fullExperimentUrl
4291
4443
  );
4292
- for (let index = 0; index < resultItems.length; index += 1) {
4444
+ for (let index = 0; index < ranItems.length; index += 1) {
4293
4445
  const localId = replayedTraceIds[index];
4294
4446
  const readBack = localId ? deliveredTraceIds[localId] : void 0;
4295
4447
  if (readBack !== void 0) {
4296
- resultItems[index].traceId = readBack;
4448
+ ranItems[index].traceId = readBack;
4297
4449
  }
4298
4450
  }
4299
4451
  const completeResult = await preserveReplayFailure(
@@ -4307,8 +4459,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
4307
4459
  if (serverTraceIds !== void 0) {
4308
4460
  const missing = [];
4309
4461
  let completedCount = 0;
4310
- for (let index = 0; index < resultItems.length; index += 1) {
4311
- const item = resultItems[index];
4462
+ for (let index = 0; index < ranItems.length; index += 1) {
4463
+ const item = ranItems[index];
4312
4464
  const localId = replayedTraceIds[index];
4313
4465
  const mapped = localId ? serverTraceIds[localId] : void 0;
4314
4466
  item.traceId = item.traceId ?? mapped ?? null;
@@ -4394,7 +4546,7 @@ async function writeReplayResultFile(result) {
4394
4546
  }
4395
4547
  }
4396
4548
  }
4397
- var REPLAY_PERSISTENCE_TIMEOUT_MS, MAX_REPLAY_ATTEMPTS, BITFAB_PROGRESS_PREFIX, ReplayError, DbBranchReplayError;
4549
+ var REPLAY_PERSISTENCE_TIMEOUT_MS, MAX_REPLAY_ATTEMPTS, RESUME_CONFLICTING_OPTIONS, CARRIED_OVER_ERROR, BITFAB_PROGRESS_PREFIX, ReplayError, DbBranchReplayError;
4398
4550
  var init_replay = __esm({
4399
4551
  "src/replay.ts"() {
4400
4552
  "use strict";
@@ -4408,6 +4560,17 @@ var init_replay = __esm({
4408
4560
  init_serialize();
4409
4561
  REPLAY_PERSISTENCE_TIMEOUT_MS = 3e4;
4410
4562
  MAX_REPLAY_ATTEMPTS = 100;
4563
+ RESUME_CONFLICTING_OPTIONS = [
4564
+ "traceIds",
4565
+ "limit",
4566
+ "datasetId",
4567
+ "datasetIds",
4568
+ "attempts",
4569
+ "graderIds",
4570
+ "onlyWithAssertions",
4571
+ "dryRun"
4572
+ ];
4573
+ CARRIED_OVER_ERROR = "This item errored in an earlier run of this experiment, before it was resumed.";
4411
4574
  BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
4412
4575
  ReplayError = class extends BitfabError {
4413
4576
  constructor(message, items, experimentId, experimentUrl, cause) {
@@ -5240,7 +5403,7 @@ function settleAutoTraceRoot(context) {
5240
5403
  }
5241
5404
  warnOnce(
5242
5405
  "auto-trace-transform-missing",
5243
- `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}`
5406
+ `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}`
5244
5407
  );
5245
5408
  }
5246
5409
  function runWithAutoTraceRootContext(context, spanStack, fn) {