@bitfab/sdk 0.31.1 → 0.33.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
@@ -143,6 +143,124 @@ interface MockOverride {
143
143
  value: MockValue;
144
144
  }
145
145
 
146
+ /**
147
+ * Replay context propagation via AsyncLocalStorage.
148
+ *
149
+ * When set, the withSpan wrapper injects testRunId into the span payload
150
+ * so that new spans created during replay are linked to the test run.
151
+ * Optionally carries a mock tree so child spans can return historical
152
+ * outputs instead of executing.
153
+ */
154
+
155
+ /**
156
+ * A single span entry in the mock tree.
157
+ *
158
+ * Under the eager path (`mock: "all"`) `output`/`outputMeta` are populated
159
+ * inline. Under the lazy path (`marked` / overrides) they are absent and the
160
+ * recorded output is fetched on demand via `externalSpanId` - see
161
+ * {@link ReplayContext.fetchSpanOutput}.
162
+ */
163
+ interface MockSpan {
164
+ sourceSpanId: string;
165
+ /** Row id accepted by `getExternalSpan`, for the lazy per-span output fetch. */
166
+ externalSpanId?: string;
167
+ output?: unknown;
168
+ outputMeta?: unknown;
169
+ }
170
+ /**
171
+ * Per-item DB branch resolved by the Bitfab service from the source
172
+ * trace's `dbSnapshotRef`. Carried on the replay context so that
173
+ * customer code reads `databaseUrl` through `getCurrentReplayBranch()`, and so
174
+ * the process-isolated replay runner can materialize it into a `.env`
175
+ * overlay file before customer code initializes its DB client.
176
+ *
177
+ * `neonBranchId` is the literal Neon branch id; passing it to
178
+ * `releaseDbBranchLease` deletes that branch.
179
+ */
180
+ interface DbBranchLease {
181
+ neonBranchId: string;
182
+ /** Env var name the customer's app reads, e.g. "DATABASE_URL". */
183
+ envKey: string;
184
+ databaseUrl: string;
185
+ expiresAt: string;
186
+ /**
187
+ * The instant the branch was pinned to (the source trace's wall clock).
188
+ * Echoed back in `db_snapshot_usage` on the replayed trace's completion.
189
+ */
190
+ snapshotTimestamp?: string;
191
+ providerConsoleUrl?: string;
192
+ readOnly?: boolean;
193
+ /**
194
+ * The branch's region, e.g. `aws-us-east-1`. A compute runs in its project's
195
+ * region, so a runner elsewhere pays that round trip on every query.
196
+ */
197
+ region?: string;
198
+ }
199
+ /**
200
+ * Pre-built lookup table of historical span outputs.
201
+ * Keys are `${traceFunctionKey}:${spanName}:${callIndex}` so that repeated
202
+ * calls with the same (key, name) are matched by call order, but spans
203
+ * sharing only the traceFunctionKey (different name) do not collide.
204
+ */
205
+ interface MockTree {
206
+ spans: Map<string, MockSpan>;
207
+ }
208
+ interface ReplayContext {
209
+ testRunId: string;
210
+ traceId?: string;
211
+ inputSourceSpanId?: string;
212
+ /**
213
+ * External trace ID from `external_traces.id`. Used for span-chain
214
+ * lookup against the source platform's trace tree (Braintrust, etc.).
215
+ * NOT the same as the Bitfab `traceId` - see `sourceBitfabTraceId`.
216
+ */
217
+ inputSourceTraceId?: string;
218
+ /**
219
+ * The Bitfab `traces.id` of the historical trace that produced this
220
+ * replay item's input. This is what customer-facing surfaces (e.g.
221
+ * `ReplayBranch.traceId`) should expose, since it's the ID the
222
+ * customer sees in the Bitfab dashboard.
223
+ */
224
+ sourceBitfabTraceId?: string;
225
+ mockTree?: MockTree;
226
+ callCounters?: Map<string, number>;
227
+ mockStrategy?: "none" | "all" | "marked";
228
+ /**
229
+ * Resolved override chain for this replay, per-call overrides first then
230
+ * registered ones (first matcher wins). Empty/absent when no overrides apply.
231
+ */
232
+ mockOverrides?: MockOverride[];
233
+ /**
234
+ * Memoized lazy fetch of a span's recorded output (deserialized), keyed by
235
+ * `externalSpanId`. Present ONLY on the lazy path (`marked` / overrides);
236
+ * absent under `mock: "all"`, where outputs are inline on the mock tree. Its
237
+ * presence is the signal that outputs must be fetched rather than read inline.
238
+ */
239
+ fetchSpanOutput?: (externalSpanId: string) => Promise<unknown>;
240
+ dbBranchLease?: DbBranchLease;
241
+ /**
242
+ * Set to true by `ReplayBranch` the first time customer code actually
243
+ * obtains `databaseUrl` for this item. Reported on the trace completion inside
244
+ * `db_snapshot_usage` so the server can distinguish "branch was
245
+ * provisioned and exposed" from "branch URL was actually consumed".
246
+ * Any future consumption path that hands the URL to customer code by
247
+ * other means (e.g. a process-isolated runner writing an env overlay)
248
+ * must also set this.
249
+ */
250
+ dbSnapshotAccessed?: boolean;
251
+ /**
252
+ * Collector for the replay item's trace-persistence work. When present,
253
+ * the root span's send path pushes a promise that resolves only after
254
+ * every span upload AND the trace completion have been sent (registered
255
+ * synchronously at send time, so the replay runner can await it after
256
+ * the wrapped fn resolves). This is what lets replay guarantee traces
257
+ * are persisted server-side before `completeReplay` builds the
258
+ * trace-ID mapping. Absent outside replay, where sends stay
259
+ * fire-and-forget.
260
+ */
261
+ pendingPersistence?: Promise<unknown>[];
262
+ }
263
+
146
264
  /**
147
265
  * HTTP client utilities for Bitfab API requests.
148
266
  *
@@ -621,73 +739,6 @@ declare class BitfabOpenAIAgentHandler {
621
739
  wrapRun(agent: AgentLike, input: RunInput, options?: RunOptions): Promise<RunResultLike>;
622
740
  }
623
741
 
624
- /**
625
- * Per-trace environment exposed to customer code during replay.
626
- *
627
- * The customer instantiates one `ReplayEnvironment` and passes it to
628
- * `bitfab.replay({ environment })`. Inside the replayed function they read
629
- * `env.databaseUrl` (and friends) to pick up the per-trace branch URL the
630
- * Bitfab service resolved from the source trace's snapshot reference.
631
- *
632
- * Outside replay, accessing `env.databaseUrl` throws. Customer code uses
633
- * the env only on the replay path; live request code keeps reading
634
- * `process.env.DATABASE_URL` the normal way.
635
- *
636
- * Concurrency-safe: getters resolve through the replay AsyncLocalStorage
637
- * context, so each in-flight replay item sees its own per-trace values
638
- * even when the SDK runs items in parallel.
639
- *
640
- * Internally, the resolved per-item state is a `DbBranchLease` (see
641
- * replayContext.ts) - that's the SDK ↔ server protocol term. We expose
642
- * its useful fields directly here so customer code never sees the word.
643
- */
644
- interface ReplayEnvironmentSnapshot {
645
- databaseUrl: string;
646
- expiresAt: string;
647
- providerConsoleUrl?: string;
648
- readOnly?: boolean;
649
- region?: string;
650
- traceId: string;
651
- }
652
- declare class ReplayEnvironment {
653
- /**
654
- * The per-trace branch URL for the item currently being replayed.
655
- * Throws if read outside a replay item.
656
- */
657
- get databaseUrl(): string;
658
- /** When the per-trace branch URL stops being valid. ISO-8601. */
659
- get expiresAt(): string;
660
- /** Deep link to the branch in the provider console, if available. */
661
- get providerConsoleUrl(): string | undefined;
662
- /**
663
- * True if the branch is read-only. Customer code can use this to skip
664
- * write operations during replay when the provider returned a read-only
665
- * lease.
666
- */
667
- get readOnly(): boolean | undefined;
668
- /**
669
- * The branch's region, e.g. `aws-us-east-1`. A compute runs in its project's
670
- * region, so a replay runner elsewhere pays that round trip on every query.
671
- */
672
- get region(): string | undefined;
673
- /** The historical trace ID that produced the input for this replay item. */
674
- get traceId(): string;
675
- /** True when read inside a replay item that has a resolved branch. */
676
- get active(): boolean;
677
- /** Non-throwing variant for callers that handle the inactive case. */
678
- snapshot(): ReplayEnvironmentSnapshot | null;
679
- /**
680
- * Record on the replay context that customer code obtained the branch
681
- * URL. Only `databaseUrl` and `snapshot()` count - `active`, `readOnly`
682
- * and friends inspect the lease without exposing the connection string,
683
- * so they don't prove the replayed code could have connected to the
684
- * branch.
685
- */
686
- private markAccessed;
687
- private read;
688
- private require;
689
- }
690
-
691
742
  /**
692
743
  * Replay historical traces through a function and create a test run.
693
744
  *
@@ -699,8 +750,10 @@ declare class ReplayEnvironment {
699
750
 
700
751
  type MockStrategy = "none" | "all" | "marked";
701
752
  /**
702
- * Per-lease settings for the DB-snapshot branch a replay item runs against.
703
- * Only read when `environment` is set, since that is what turns branching on.
753
+ * How the DB-snapshot branch each replay item runs against is sized and warmed.
754
+ *
755
+ * Passing this object at all is what turns database branching on, so `{}` means
756
+ * "branch every item, with the mirror project's own defaults".
704
757
  */
705
758
  interface DbBranchOptions {
706
759
  /**
@@ -719,9 +772,9 @@ interface DbBranchOptions {
719
772
  maxCu?: number;
720
773
  /**
721
774
  * SQL that warms the branch's cache. The server appends it to the branch's
722
- * readiness check, so it runs BEFORE your function sees the lease and its
723
- * time is not charged to the replayed call. Invalid SQL fails the lease
724
- * rather than silently leaving the branch cold.
775
+ * readiness check, so it runs BEFORE your function sees the branch and its
776
+ * time is not charged to the replayed call. Invalid SQL fails the branch
777
+ * rather than silently leaving it cold.
725
778
  */
726
779
  warmupSql?: string;
727
780
  }
@@ -767,13 +820,17 @@ interface ReplayOptions {
767
820
  */
768
821
  mockOverride?: MockOverride | MockOverride[];
769
822
  /**
770
- * Per-trace environment. When the source trace carries a DB branching
771
- * snapshot, the SDK populates `environment.databaseUrl` before invoking
772
- * `fn` for that item and resets it after. Customer code reads from the
773
- * environment to pick up the per-trace branch URL.
823
+ * Run each item against a database branch restored to the state its source
824
+ * trace saw. Passing this object at all turns branching on, so `{}` enables
825
+ * it with the mirror project's own sizing; the fields tune how each branch is
826
+ * sized and warmed. Inside `fn`, read the resolved branch with
827
+ * `getCurrentReplayBranch()`.
828
+ *
829
+ * Items whose source trace carried no DB snapshot reference get no branch and
830
+ * run against the live database. An item whose branch was requested but could
831
+ * not be resolved fails instead of running, so a replay never silently
832
+ * reports a result that did not use the historical data you asked for.
774
833
  */
775
- environment?: ReplayEnvironment;
776
- /** Compute size and cache warm-up for the per-item DB snapshot branch. */
777
834
  dbBranch?: DbBranchOptions;
778
835
  /** Group ID to associate this replay with an experiment group for live streaming in Studio. */
779
836
  experimentGroupId?: string;
@@ -990,6 +1047,58 @@ interface ReplayResult<T> {
990
1047
  testRunUrl: string;
991
1048
  }
992
1049
 
1050
+ /**
1051
+ * The database branch a single replay item runs against.
1052
+ *
1053
+ * `getCurrentReplayBranch()` hands you one inside a replayed function when the
1054
+ * source trace carried a DB snapshot reference and the Bitfab service resolved
1055
+ * a branch from it. Outside a replay item, or when no branch was resolved, that
1056
+ * accessor returns null and your code keeps reading `process.env.DATABASE_URL`
1057
+ * the normal way.
1058
+ *
1059
+ * Immutable and scoped to one item: the accessor builds it from the replay
1060
+ * AsyncLocalStorage context, so parallel replay items each see their own branch
1061
+ * and no lease state lives on a long-lived object.
1062
+ *
1063
+ * Internally the resolved per-item state is a `DbBranchLease` (see
1064
+ * replayContext.ts), the SDK/server protocol term. Its useful fields are
1065
+ * exposed directly here so customer code never sees the word.
1066
+ */
1067
+
1068
+ declare class ReplayBranch {
1069
+ #private;
1070
+ /** When this branch's URL stops being valid. ISO-8601. */
1071
+ readonly expiresAt: string;
1072
+ /** Deep link to the branch in the provider console, if available. */
1073
+ readonly providerConsoleUrl?: string;
1074
+ /**
1075
+ * True if the branch is read-only. Use it to skip write operations during
1076
+ * replay when the provider returned a read-only lease.
1077
+ */
1078
+ readonly readOnly?: boolean;
1079
+ /**
1080
+ * The branch's region, e.g. `aws-us-east-1`. A compute runs in its project's
1081
+ * region, so a replay runner elsewhere pays that round trip on every query.
1082
+ */
1083
+ readonly region?: string;
1084
+ /** The historical trace ID that produced the input for this replay item. */
1085
+ readonly traceId: string;
1086
+ /** @internal Built by `getCurrentReplayBranch()`; never constructed by callers. */
1087
+ constructor(lease: DbBranchLease, traceId: string, context: ReplayContext);
1088
+ /**
1089
+ * Connection string for this item's branch. Point your database client at it
1090
+ * instead of the live database for the duration of the replayed call.
1091
+ *
1092
+ * Reading it records on the trace that the replayed code obtained the branch
1093
+ * URL, which is what separates "a branch was provisioned" from "the branch
1094
+ * was actually used". The other fields inspect the lease without exposing the
1095
+ * connection string, so they deliberately do not record anything. That is
1096
+ * also why this is a getter and not a plain field: the URL is absent from
1097
+ * `JSON.stringify(branch)` and from logging the object.
1098
+ */
1099
+ get databaseUrl(): string;
1100
+ }
1101
+
993
1102
  /**
994
1103
  * Tracing utilities for external trace submission to Bitfab.
995
1104
  *
@@ -1229,6 +1338,23 @@ interface CurrentTrace {
1229
1338
  * Returns a no-op object if called outside of a span context (methods do nothing).
1230
1339
  */
1231
1340
  declare function getCurrentSpan(): CurrentSpan;
1341
+ /**
1342
+ * Get the database branch the current replay item is running against.
1343
+ *
1344
+ * Call this from inside a function being replayed with `replay({ dbBranch })`
1345
+ * and point your database client at `branch.databaseUrl` so the replay reads
1346
+ * the data as it was at trace time:
1347
+ *
1348
+ * ```ts
1349
+ * const branch = getCurrentReplayBranch()
1350
+ * const url = branch?.databaseUrl ?? process.env.DATABASE_URL
1351
+ * ```
1352
+ *
1353
+ * Returns null outside a replay item, and for an item whose source trace
1354
+ * carried no DB snapshot reference, so live request code takes the same path
1355
+ * it always did.
1356
+ */
1357
+ declare function getCurrentReplayBranch(): ReplayBranch | null;
1232
1358
  /**
1233
1359
  * Get a handle to the current active trace.
1234
1360
  *
@@ -1336,12 +1462,6 @@ interface SpanOptions {
1336
1462
  * Client for making provider-based API calls via BAML.
1337
1463
  */
1338
1464
  declare class Bitfab {
1339
- /**
1340
- * Per-trace environment for `replay({ environment })`. Construct one,
1341
- * pass it to replay, and read `env.databaseUrl` inside the replayed
1342
- * function to pick up the per-trace branch URL.
1343
- */
1344
- static readonly ReplayEnvironment: typeof ReplayEnvironment;
1345
1465
  private readonly apiKeyConfig;
1346
1466
  /** Cached only once a non-empty key is found, so an early resolve (before env loaded) can't poison a later one. */
1347
1467
  private resolvedApiKey;
@@ -1843,7 +1963,7 @@ declare class BitfabFunction {
1843
1963
  /**
1844
1964
  * SDK version from package.json (injected at build time)
1845
1965
  */
1846
- declare const __version__ = "0.31.1";
1966
+ declare const __version__ = "0.33.0";
1847
1967
 
1848
1968
  /**
1849
1969
  * Constants for the Bitfab SDK.
@@ -1911,4 +2031,4 @@ declare const finalizers: {
1911
2031
  readableStream: typeof readableStream;
1912
2032
  };
1913
2033
 
1914
- export { type ActiveSpanContext, type AdaptContext, type AdaptInputsFn, type AllowedEnvVars, BITFAB_PROGRESS_PREFIX, type BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, type BitfabConfig, BitfabError, BitfabFunction, BitfabLangGraphCallbackHandler as BitfabLangChainCallbackHandler, BitfabLangGraphCallbackHandler, type BitfabLanguageModelMiddleware, BitfabOpenAIAgentHandler, BitfabOpenAITracingProcessor, BitfabVercelAiHandler, type CapturedSpan, type CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type DbBranchOptions, type DbSnapshotConfig, type DbSnapshotProvider, type DbSnapshotRef, type DetachedTrace, type MockOverride, type MockOverrideCtx, type MockStrategy, type MockValue, type NodeMatcher, type ProviderDefinition, ReplayEnvironment, type ReplayEnvironmentSnapshot, type ReplayItem, type ReplayOptions, type ReplayProgress, type ReplayResult, SUPPORTED_PROVIDERS, type SpanLookup, type SpanNodeMeta, type SpanOccurrence, type SpanOptions, type SpanType, type TokenUsage, type TraceResponse, type TracingProcessor, type VercelCallParams, type VercelGenerateResult, type VercelStreamResult, type WrapBAMLOptions, type WrappedBamlFn, __version__, finalizers, flushTraces, getCurrentSpan, getCurrentTrace, reportReplayProgress };
2034
+ export { type ActiveSpanContext, type AdaptContext, type AdaptInputsFn, type AllowedEnvVars, BITFAB_PROGRESS_PREFIX, type BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, type BitfabConfig, BitfabError, BitfabFunction, BitfabLangGraphCallbackHandler as BitfabLangChainCallbackHandler, BitfabLangGraphCallbackHandler, type BitfabLanguageModelMiddleware, BitfabOpenAIAgentHandler, BitfabOpenAITracingProcessor, BitfabVercelAiHandler, type CapturedSpan, type CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type DbBranchOptions, type DbSnapshotConfig, type DbSnapshotProvider, type DbSnapshotRef, type DetachedTrace, type MockOverride, type MockOverrideCtx, type MockStrategy, type MockValue, type NodeMatcher, type ProviderDefinition, ReplayBranch, type ReplayItem, type ReplayOptions, type ReplayProgress, type ReplayResult, SUPPORTED_PROVIDERS, type SpanLookup, type SpanNodeMeta, type SpanOccurrence, type SpanOptions, type SpanType, type TokenUsage, type TraceResponse, type TracingProcessor, type VercelCallParams, type VercelGenerateResult, type VercelStreamResult, type WrapBAMLOptions, type WrappedBamlFn, __version__, finalizers, flushTraces, getCurrentReplayBranch, getCurrentSpan, getCurrentTrace, reportReplayProgress };