bitfab 0.36.12 → 0.38.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.
package/dist/index.cjs CHANGED
@@ -51,7 +51,7 @@ var __version__;
51
51
  var init_version_generated = __esm({
52
52
  "src/version.generated.ts"() {
53
53
  "use strict";
54
- __version__ = "0.36.12";
54
+ __version__ = "0.38.0";
55
55
  }
56
56
  });
57
57
 
@@ -2534,12 +2534,15 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2534
2534
  let lease = includeDbBranchLease ? serverItem.dbBranchLease : void 0;
2535
2535
  let leaseError = includeDbBranchLease ? serverItem.dbBranchLeaseError : void 0;
2536
2536
  let dbSnapshotRef = serverItem.dbSnapshotRef;
2537
+ let dbBranchTimings = includeDbBranchLease ? serverItem.dbBranchTimings : void 0;
2537
2538
  let inputs = [];
2538
2539
  let originalOutput;
2539
2540
  let result;
2540
2541
  let error = null;
2541
2542
  let traceError = null;
2542
2543
  let replayError = null;
2544
+ let replayDurationMs = null;
2545
+ let replayStarted = null;
2543
2546
  const originalTraceId = serverItem.originalTraceId ?? serverItem.sourceTraceId;
2544
2547
  const originalSpanId = serverItem.originalSpanId ?? serverItem.sourceSpanId;
2545
2548
  try {
@@ -2562,6 +2565,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2562
2565
  lease = resolved.lease ?? void 0;
2563
2566
  leaseError = resolved.leaseError ?? void 0;
2564
2567
  dbSnapshotRef = resolved.dbSnapshotRef ?? dbSnapshotRef;
2568
+ dbBranchTimings = resolved.timings ?? dbBranchTimings;
2565
2569
  }
2566
2570
  if (leaseError) {
2567
2571
  throw new DbBranchReplayError(
@@ -2595,20 +2599,17 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2595
2599
  includeOutputs,
2596
2600
  includeRootOutput: false
2597
2601
  });
2598
- if (treeResponse.root) {
2599
- mockTree = buildMockTree(treeResponse.root);
2600
- } else if (mockStrategy === "all" || hasOverrides) {
2602
+ if (!treeResponse.root) {
2601
2603
  throw new BitfabError(
2602
2604
  `Replay mock strategy "${mockStrategy}"${hasOverrides ? " with overrides" : ""} requires a span tree root for original span ${originalSpanId}.`
2603
2605
  );
2604
- } else {
2605
- mockTree = void 0;
2606
2606
  }
2607
- } catch (e) {
2608
- if (mockStrategy === "all" || hasOverrides) {
2609
- throw e;
2607
+ mockTree = buildMockTree(treeResponse.root);
2608
+ } catch (error2) {
2609
+ if (mockStrategy !== "marked" || hasOverrides) {
2610
+ throw error2;
2610
2611
  }
2611
- mockTree = void 0;
2612
+ mockTree = { spans: /* @__PURE__ */ new Map() };
2612
2613
  }
2613
2614
  }
2614
2615
  const outputCache = /* @__PURE__ */ new Map();
@@ -2625,6 +2626,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2625
2626
  return pending;
2626
2627
  } : void 0;
2627
2628
  try {
2629
+ replayStarted = performance.now();
2628
2630
  const maybePromise = runWithReplayContext(
2629
2631
  {
2630
2632
  testRunId,
@@ -2637,16 +2639,24 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2637
2639
  mockStrategy,
2638
2640
  mockOverrides: hasOverrides ? resolvedOverrides : void 0,
2639
2641
  fetchSpanOutput,
2640
- dbBranchLease: lease
2642
+ dbBranchLease: lease,
2643
+ dbBranchTimings
2641
2644
  },
2642
2645
  () => fn(...inputs)
2643
2646
  );
2644
2647
  result = maybePromise instanceof Promise ? await maybePromise : maybePromise;
2648
+ replayDurationMs = Math.round(performance.now() - replayStarted);
2645
2649
  } catch (e) {
2650
+ if (replayStarted !== null) {
2651
+ replayDurationMs = Math.round(performance.now() - replayStarted);
2652
+ }
2646
2653
  traceError = e;
2647
2654
  error = errorMessage(e);
2648
2655
  }
2649
2656
  } catch (e) {
2657
+ if (replayStarted !== null) {
2658
+ replayDurationMs = Math.round(performance.now() - replayStarted);
2659
+ }
2650
2660
  replayError = e;
2651
2661
  error = replayItemErrorMessage(e);
2652
2662
  } finally {
@@ -2663,6 +2673,8 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2663
2673
  }
2664
2674
  }
2665
2675
  }
2676
+ const originalDurationMs = serverItem.originalDurationMs ?? serverItem.durationMs ?? null;
2677
+ const originalModel = serverItem.originalModel ?? serverItem.model ?? null;
2666
2678
  return {
2667
2679
  // Written in by replay() from the complete-replay response once the server
2668
2680
  // has minted this replay trace's row. Null until then: the client-side
@@ -2679,13 +2691,17 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
2679
2691
  error,
2680
2692
  traceError,
2681
2693
  replayError,
2682
- durationMs: serverItem.durationMs ?? null,
2694
+ durationMs: replayDurationMs,
2695
+ originalDurationMs,
2696
+ originalTokens: serverItem.originalTokens ?? serverItem.tokens ?? null,
2697
+ originalModel,
2683
2698
  // Filled in by replay() from the complete-replay response once the
2684
2699
  // replay traces are persisted and their spans aggregated server-side.
2685
2700
  // Null here (and on older servers) means "replay tokens not known".
2686
2701
  tokens: null,
2687
- model: serverItem.model ?? null,
2688
- dbSnapshotRef: dbSnapshotRef ?? null
2702
+ model: originalModel,
2703
+ dbSnapshotRef: dbSnapshotRef ?? null,
2704
+ dbBranchTimings: dbBranchTimings ?? null
2689
2705
  };
2690
2706
  }
2691
2707
  async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds) {
@@ -2912,9 +2928,13 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2912
2928
  traceError: item.traceError,
2913
2929
  replayError: item.replayError,
2914
2930
  durationMs: item.durationMs,
2931
+ originalDurationMs: item.originalDurationMs,
2932
+ originalTokens: item.originalTokens,
2933
+ originalModel: item.originalModel,
2915
2934
  tokens: item.tokens,
2916
2935
  model: item.model,
2917
- dbSnapshotRef: item.dbSnapshotRef
2936
+ dbSnapshotRef: item.dbSnapshotRef,
2937
+ dbBranchTimings: item.dbBranchTimings
2918
2938
  }
2919
2939
  });
2920
2940
  } catch {
@@ -6093,7 +6113,8 @@ var Bitfab = class {
6093
6113
  snapshotTimestamp: replayCtx.dbBranchLease.snapshotTimestamp,
6094
6114
  region: replayCtx.dbBranchLease.region,
6095
6115
  originalTraceId: replayCtx.sourceBitfabTraceId,
6096
- accessed: replayCtx.dbSnapshotAccessed === true
6116
+ accessed: replayCtx.dbSnapshotAccessed === true,
6117
+ timings: replayCtx.dbBranchTimings
6097
6118
  }
6098
6119
  }
6099
6120
  });
@@ -6183,7 +6204,12 @@ var Bitfab = class {
6183
6204
  }
6184
6205
  }
6185
6206
  const shouldMock = replayCtxForMock.mockStrategy === "all" || replayCtxForMock.mockStrategy === "marked" && options.mockOnReplay === true;
6186
- if (shouldMock && mockSpan) {
6207
+ if (shouldMock && !mockSpan) {
6208
+ throw new BitfabError(
6209
+ `Replay selected span "${traceFunctionKey}:${baseSpanParams.spanName}" for mocking, but recorded occurrence ${callIndex + 1} is unavailable. The real span was not executed.`
6210
+ );
6211
+ }
6212
+ if (shouldMock) {
6187
6213
  const recorded = resolveRecordedOutput();
6188
6214
  if (recorded instanceof Promise) {
6189
6215
  return emitMockAsync(recorded, "recorded");
@@ -6420,7 +6446,13 @@ var Bitfab = class {
6420
6446
  // against servers that predate the rename.
6421
6447
  source_trace_id: params.dbSnapshotUsage.originalTraceId
6422
6448
  },
6423
- accessed: params.dbSnapshotUsage.accessed
6449
+ accessed: params.dbSnapshotUsage.accessed,
6450
+ // Echoed verbatim (camelCase inside) rather than re-cased into this
6451
+ // record's snake_case: it is the server's own object coming back, and
6452
+ // a translation layer here is one more thing to drift.
6453
+ ...params.dbSnapshotUsage.timings && {
6454
+ timings: params.dbSnapshotUsage.timings
6455
+ }
6424
6456
  };
6425
6457
  }
6426
6458
  this.httpClient.sendExternalTrace({