bitfab 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.d.cts CHANGED
@@ -147,9 +147,12 @@ declare class BitfabClaudeAgentHandler {
147
147
  /**
148
148
  * Per-trace database snapshot ref capture.
149
149
  *
150
- * When the customer configures `dbSnapshot`, every root span carries a
151
- * `DbSnapshotRef` that pins the DB state at trace open by wall-clock
152
- * timestamp. The Bitfab service uses that timestamp at replay time to
150
+ * Every root span carries a `DbSnapshotRef` that pins the DB state at trace
151
+ * open by wall-clock timestamp. Capturing the timestamp is free (no IO) and
152
+ * harmless, so it happens on every trace regardless of configuration: that
153
+ * lets any trace be replayed against a historical branch later. A `provider`
154
+ * is attached only when the customer configured `dbSnapshot`; when absent it
155
+ * is resolved at replay time. The Bitfab service uses the timestamp to
153
156
  * materialize an ephemeral branch from `customer-main`.
154
157
  */
155
158
  declare const SUPPORTED_PROVIDERS: readonly ["neon"];
@@ -159,14 +162,19 @@ interface DbSnapshotConfig {
159
162
  provider: DbSnapshotProvider;
160
163
  }
161
164
  interface DbSnapshotRef {
162
- provider: DbSnapshotProvider;
163
165
  /**
164
166
  * The wall-clock ISO timestamp the SDK observed immediately before
165
167
  * invoking the wrapped function. The name encodes its provenance:
166
168
  * SDK-observed, wall clock (not monotonic), captured before user code
167
- * began executing.
169
+ * began executing. Always present.
168
170
  */
169
171
  sdkWallClockBeforeFn: string;
172
+ /**
173
+ * The configured provider for server-side branch resolution. Only set when
174
+ * the customer configured `dbSnapshot`; otherwise the provider is resolved
175
+ * at replay time.
176
+ */
177
+ provider?: DbSnapshotProvider;
170
178
  }
171
179
 
172
180
  /**
@@ -970,11 +978,15 @@ declare class Bitfab {
970
978
  * Fetches the last N traces for the given trace function key, re-runs each
971
979
  * through the provided function, and returns comparison data.
972
980
  *
973
- * The function must have been wrapped with `withSpan` replay injects
974
- * `testRunId` via async context so new spans are linked to the test run.
981
+ * Accepts either a `withSpan`-wrapped function (under the same key) or any
982
+ * plain callable: plain callables are wrapped internally so each replayed
983
+ * invocation records a trace tied to the test run. The plain-callable form
984
+ * is how handler-instrumented workflows (LangGraph/LangChain, Claude Agent
985
+ * SDK) replay — those record traces under a key with no `withSpan`-wrapped
986
+ * root in the app.
975
987
  *
976
988
  * @param traceFunctionKey - The trace function key to replay
977
- * @param fn - The function to replay (must be the return value of `withSpan`)
989
+ * @param fn - The function to run recorded inputs through
978
990
  * @param options - Optional replay options. When `traceIds` is passed,
979
991
  * `limit` is ignored (with a warning): an explicit ID list already
980
992
  * determines how many traces replay.
@@ -1043,7 +1055,7 @@ declare class BitfabFunction {
1043
1055
  /**
1044
1056
  * SDK version from package.json (injected at build time)
1045
1057
  */
1046
- declare const __version__ = "0.16.2";
1058
+ declare const __version__ = "0.18.0";
1047
1059
 
1048
1060
  /**
1049
1061
  * Constants for the Bitfab SDK.
package/dist/index.d.ts CHANGED
@@ -147,9 +147,12 @@ declare class BitfabClaudeAgentHandler {
147
147
  /**
148
148
  * Per-trace database snapshot ref capture.
149
149
  *
150
- * When the customer configures `dbSnapshot`, every root span carries a
151
- * `DbSnapshotRef` that pins the DB state at trace open by wall-clock
152
- * timestamp. The Bitfab service uses that timestamp at replay time to
150
+ * Every root span carries a `DbSnapshotRef` that pins the DB state at trace
151
+ * open by wall-clock timestamp. Capturing the timestamp is free (no IO) and
152
+ * harmless, so it happens on every trace regardless of configuration: that
153
+ * lets any trace be replayed against a historical branch later. A `provider`
154
+ * is attached only when the customer configured `dbSnapshot`; when absent it
155
+ * is resolved at replay time. The Bitfab service uses the timestamp to
153
156
  * materialize an ephemeral branch from `customer-main`.
154
157
  */
155
158
  declare const SUPPORTED_PROVIDERS: readonly ["neon"];
@@ -159,14 +162,19 @@ interface DbSnapshotConfig {
159
162
  provider: DbSnapshotProvider;
160
163
  }
161
164
  interface DbSnapshotRef {
162
- provider: DbSnapshotProvider;
163
165
  /**
164
166
  * The wall-clock ISO timestamp the SDK observed immediately before
165
167
  * invoking the wrapped function. The name encodes its provenance:
166
168
  * SDK-observed, wall clock (not monotonic), captured before user code
167
- * began executing.
169
+ * began executing. Always present.
168
170
  */
169
171
  sdkWallClockBeforeFn: string;
172
+ /**
173
+ * The configured provider for server-side branch resolution. Only set when
174
+ * the customer configured `dbSnapshot`; otherwise the provider is resolved
175
+ * at replay time.
176
+ */
177
+ provider?: DbSnapshotProvider;
170
178
  }
171
179
 
172
180
  /**
@@ -970,11 +978,15 @@ declare class Bitfab {
970
978
  * Fetches the last N traces for the given trace function key, re-runs each
971
979
  * through the provided function, and returns comparison data.
972
980
  *
973
- * The function must have been wrapped with `withSpan` replay injects
974
- * `testRunId` via async context so new spans are linked to the test run.
981
+ * Accepts either a `withSpan`-wrapped function (under the same key) or any
982
+ * plain callable: plain callables are wrapped internally so each replayed
983
+ * invocation records a trace tied to the test run. The plain-callable form
984
+ * is how handler-instrumented workflows (LangGraph/LangChain, Claude Agent
985
+ * SDK) replay — those record traces under a key with no `withSpan`-wrapped
986
+ * root in the app.
975
987
  *
976
988
  * @param traceFunctionKey - The trace function key to replay
977
- * @param fn - The function to replay (must be the return value of `withSpan`)
989
+ * @param fn - The function to run recorded inputs through
978
990
  * @param options - Optional replay options. When `traceIds` is passed,
979
991
  * `limit` is ignored (with a warning): an explicit ID list already
980
992
  * determines how many traces replay.
@@ -1043,7 +1055,7 @@ declare class BitfabFunction {
1043
1055
  /**
1044
1056
  * SDK version from package.json (injected at build time)
1045
1057
  */
1046
- declare const __version__ = "0.16.2";
1058
+ declare const __version__ = "0.18.0";
1047
1059
 
1048
1060
  /**
1049
1061
  * Constants for the Bitfab SDK.
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  flushTraces,
21
21
  getCurrentSpan,
22
22
  getCurrentTrace
23
- } from "./chunk-4WJPQT2X.js";
23
+ } from "./chunk-S3YLZ47O.js";
24
24
  import {
25
25
  BitfabError
26
26
  } from "./chunk-QT7HWOKU.js";
package/dist/node.cjs CHANGED
@@ -456,7 +456,7 @@ registerAsyncLocalStorageClass(
456
456
  );
457
457
 
458
458
  // src/version.generated.ts
459
- var __version__ = "0.16.2";
459
+ var __version__ = "0.18.0";
460
460
 
461
461
  // src/constants.ts
462
462
  var DEFAULT_SERVICE_URL = "https://bitfab.ai";
@@ -1571,8 +1571,8 @@ function validateDbSnapshotConfig(config) {
1571
1571
  }
1572
1572
  function buildSnapshotRef(config, sdkWallClockBeforeFn) {
1573
1573
  return {
1574
- provider: config.provider,
1575
- sdkWallClockBeforeFn
1574
+ sdkWallClockBeforeFn,
1575
+ ...config && { provider: config.provider }
1576
1576
  };
1577
1577
  }
1578
1578
 
@@ -2947,7 +2947,7 @@ var Bitfab = class {
2947
2947
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
2948
2948
  if (isRootSpan && !activeTraceStates.has(traceId)) {
2949
2949
  const replayCtxAtRoot = getReplayContext();
2950
- const dbSnapshotRef = self.dbSnapshot ? buildSnapshotRef(self.dbSnapshot, startedAt) : void 0;
2950
+ const dbSnapshotRef = buildSnapshotRef(self.dbSnapshot, startedAt);
2951
2951
  activeTraceStates.set(traceId, {
2952
2952
  traceId,
2953
2953
  startedAt,
@@ -2958,7 +2958,7 @@ var Bitfab = class {
2958
2958
  ...replayCtxAtRoot?.inputSourceTraceId && {
2959
2959
  inputSourceTraceId: replayCtxAtRoot.inputSourceTraceId
2960
2960
  },
2961
- ...dbSnapshotRef && { dbSnapshotRef }
2961
+ dbSnapshotRef
2962
2962
  });
2963
2963
  pendingSpanPromises.set(traceId, []);
2964
2964
  }
@@ -3088,6 +3088,9 @@ var Bitfab = class {
3088
3088
  };
3089
3089
  return runWithSpanStack(newStack, executeWithContext);
3090
3090
  };
3091
+ Object.defineProperty(wrappedFn, "_bitfabTraceFunctionKey", {
3092
+ value: traceFunctionKey
3093
+ });
3091
3094
  return wrappedFn;
3092
3095
  }
3093
3096
  /**
@@ -3259,23 +3262,40 @@ var Bitfab = class {
3259
3262
  * Fetches the last N traces for the given trace function key, re-runs each
3260
3263
  * through the provided function, and returns comparison data.
3261
3264
  *
3262
- * The function must have been wrapped with `withSpan` replay injects
3263
- * `testRunId` via async context so new spans are linked to the test run.
3265
+ * Accepts either a `withSpan`-wrapped function (under the same key) or any
3266
+ * plain callable: plain callables are wrapped internally so each replayed
3267
+ * invocation records a trace tied to the test run. The plain-callable form
3268
+ * is how handler-instrumented workflows (LangGraph/LangChain, Claude Agent
3269
+ * SDK) replay — those record traces under a key with no `withSpan`-wrapped
3270
+ * root in the app.
3264
3271
  *
3265
3272
  * @param traceFunctionKey - The trace function key to replay
3266
- * @param fn - The function to replay (must be the return value of `withSpan`)
3273
+ * @param fn - The function to run recorded inputs through
3267
3274
  * @param options - Optional replay options. When `traceIds` is passed,
3268
3275
  * `limit` is ignored (with a warning): an explicit ID list already
3269
3276
  * determines how many traces replay.
3270
3277
  * @returns ReplayResult with items, testRunId, and testRunUrl
3271
3278
  */
3272
3279
  async replay(traceFunctionKey, fn, options) {
3280
+ const wrappedKey = fn._bitfabTraceFunctionKey;
3281
+ let replayFn = fn;
3282
+ if (wrappedKey === void 0) {
3283
+ replayFn = this.withSpan(
3284
+ traceFunctionKey,
3285
+ { name: fn.name || "Replay", type: "agent" },
3286
+ fn
3287
+ );
3288
+ } else if (wrappedKey !== traceFunctionKey) {
3289
+ throw new BitfabError(
3290
+ `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.`
3291
+ );
3292
+ }
3273
3293
  const { replay: doReplay } = await Promise.resolve().then(() => (init_replay(), replay_exports));
3274
3294
  return doReplay(
3275
3295
  this.httpClient,
3276
3296
  this.serviceUrl,
3277
3297
  traceFunctionKey,
3278
- fn,
3298
+ replayFn,
3279
3299
  options
3280
3300
  );
3281
3301
  }