@bitfab/sdk 0.16.2 → 0.18.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
@@ -433,7 +433,7 @@ __export(index_exports, {
433
433
  module.exports = __toCommonJS(index_exports);
434
434
 
435
435
  // src/version.generated.ts
436
- var __version__ = "0.16.2";
436
+ var __version__ = "0.18.0";
437
437
 
438
438
  // src/constants.ts
439
439
  var DEFAULT_SERVICE_URL = "https://bitfab.ai";
@@ -1548,8 +1548,8 @@ function validateDbSnapshotConfig(config) {
1548
1548
  }
1549
1549
  function buildSnapshotRef(config, sdkWallClockBeforeFn) {
1550
1550
  return {
1551
- provider: config.provider,
1552
- sdkWallClockBeforeFn
1551
+ sdkWallClockBeforeFn,
1552
+ ...config && { provider: config.provider }
1553
1553
  };
1554
1554
  }
1555
1555
 
@@ -2924,7 +2924,7 @@ var Bitfab = class {
2924
2924
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
2925
2925
  if (isRootSpan && !activeTraceStates.has(traceId)) {
2926
2926
  const replayCtxAtRoot = getReplayContext();
2927
- const dbSnapshotRef = self.dbSnapshot ? buildSnapshotRef(self.dbSnapshot, startedAt) : void 0;
2927
+ const dbSnapshotRef = buildSnapshotRef(self.dbSnapshot, startedAt);
2928
2928
  activeTraceStates.set(traceId, {
2929
2929
  traceId,
2930
2930
  startedAt,
@@ -2935,7 +2935,7 @@ var Bitfab = class {
2935
2935
  ...replayCtxAtRoot?.inputSourceTraceId && {
2936
2936
  inputSourceTraceId: replayCtxAtRoot.inputSourceTraceId
2937
2937
  },
2938
- ...dbSnapshotRef && { dbSnapshotRef }
2938
+ dbSnapshotRef
2939
2939
  });
2940
2940
  pendingSpanPromises.set(traceId, []);
2941
2941
  }
@@ -3065,6 +3065,9 @@ var Bitfab = class {
3065
3065
  };
3066
3066
  return runWithSpanStack(newStack, executeWithContext);
3067
3067
  };
3068
+ Object.defineProperty(wrappedFn, "_bitfabTraceFunctionKey", {
3069
+ value: traceFunctionKey
3070
+ });
3068
3071
  return wrappedFn;
3069
3072
  }
3070
3073
  /**
@@ -3236,23 +3239,40 @@ var Bitfab = class {
3236
3239
  * Fetches the last N traces for the given trace function key, re-runs each
3237
3240
  * through the provided function, and returns comparison data.
3238
3241
  *
3239
- * The function must have been wrapped with `withSpan` replay injects
3240
- * `testRunId` via async context so new spans are linked to the test run.
3242
+ * Accepts either a `withSpan`-wrapped function (under the same key) or any
3243
+ * plain callable: plain callables are wrapped internally so each replayed
3244
+ * invocation records a trace tied to the test run. The plain-callable form
3245
+ * is how handler-instrumented workflows (LangGraph/LangChain, Claude Agent
3246
+ * SDK) replay — those record traces under a key with no `withSpan`-wrapped
3247
+ * root in the app.
3241
3248
  *
3242
3249
  * @param traceFunctionKey - The trace function key to replay
3243
- * @param fn - The function to replay (must be the return value of `withSpan`)
3250
+ * @param fn - The function to run recorded inputs through
3244
3251
  * @param options - Optional replay options. When `traceIds` is passed,
3245
3252
  * `limit` is ignored (with a warning): an explicit ID list already
3246
3253
  * determines how many traces replay.
3247
3254
  * @returns ReplayResult with items, testRunId, and testRunUrl
3248
3255
  */
3249
3256
  async replay(traceFunctionKey, fn, options) {
3257
+ const wrappedKey = fn._bitfabTraceFunctionKey;
3258
+ let replayFn = fn;
3259
+ if (wrappedKey === void 0) {
3260
+ replayFn = this.withSpan(
3261
+ traceFunctionKey,
3262
+ { name: fn.name || "Replay", type: "agent" },
3263
+ fn
3264
+ );
3265
+ } else if (wrappedKey !== traceFunctionKey) {
3266
+ throw new BitfabError(
3267
+ `Function is wrapped with trace function key '${wrappedKey}' but replay was called with '${traceFunctionKey}'. Pass matching keys, or pass the unwrapped function to replay it under the explicit key.`
3268
+ );
3269
+ }
3250
3270
  const { replay: doReplay } = await Promise.resolve().then(() => (init_replay(), replay_exports));
3251
3271
  return doReplay(
3252
3272
  this.httpClient,
3253
3273
  this.serviceUrl,
3254
3274
  traceFunctionKey,
3255
- fn,
3275
+ replayFn,
3256
3276
  options
3257
3277
  );
3258
3278
  }