bitfab 0.26.1 → 0.27.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
@@ -579,9 +579,9 @@ declare class ReplayEnvironment {
579
579
  * Replay historical traces through a function and create a test run.
580
580
  *
581
581
  * The replay flow has three phases:
582
- * 1. Start fetches historical traces from the server and creates a test run
583
- * 2. Execute re-runs each trace's inputs through the provided function locally
584
- * 3. Complete marks the test run as completed on the server
582
+ * 1. Start: fetches historical traces from the server and creates a test run
583
+ * 2. Execute: re-runs each trace's inputs through the provided function locally
584
+ * 3. Complete: marks the test run as completed on the server
585
585
  */
586
586
 
587
587
  type MockStrategy = "none" | "all" | "marked";
@@ -603,7 +603,7 @@ interface ReplayOptions {
603
603
  codeChangeDescription?: string;
604
604
  /**
605
605
  * Files edited as part of this code change. Each entry holds the file path
606
- * and the full `before`/`after` contents the agent reads each file before
606
+ * and the full `before`/`after` contents. The agent reads each file before
607
607
  * and after editing and passes the two strings. Use `""` for newly created
608
608
  * files (`before`) or deleted files (`after`).
609
609
  */
@@ -675,7 +675,44 @@ interface ReplayProgress {
675
675
  succeeded: number;
676
676
  /** Of the completed items, how many threw (their `item.error` is set). */
677
677
  errored: number;
678
+ /**
679
+ * The single item that just settled to produce this event. `traceId` is the
680
+ * source (historical) trace that was replayed (so a UI can identify or link
681
+ * it); `error` is its replay error, or null when it ran ok; `durationMs` is how
682
+ * long this one trace took to replay. Lets a progress UI show per-trace
683
+ * pass/fail and timing as the run streams, without waiting for the full
684
+ * {@link ReplayResult}.
685
+ */
686
+ item?: {
687
+ traceId: string | null;
688
+ error: string | null;
689
+ durationMs: number | null;
690
+ };
678
691
  }
692
+ /**
693
+ * Wire prefix the Bitfab plugin scans for. Each line {@link reportReplayProgress}
694
+ * writes is this prefix followed by the JSON of the running totals (plus the
695
+ * settled `item`). The plugin polls these lines to report live progress while a
696
+ * replay runs in the background; keep the SDK emitter and the plugin parser in
697
+ * sync.
698
+ */
699
+ declare const BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
700
+ /**
701
+ * A ready-made {@link ReplayOptions.onProgress} callback for replay scripts.
702
+ * Pass it straight in:
703
+ *
704
+ * ```ts
705
+ * await bitfab.replay("my-fn", fn, { limit, onProgress: reportReplayProgress })
706
+ * ```
707
+ *
708
+ * It writes one `@@bitfab:progress` line per trace to stderr, which the Bitfab
709
+ * plugin polls to report live progress while the replay runs in the background,
710
+ * so scripts never hand-format the wire protocol.
711
+ * stdout is left untouched for the ReplayResult JSON. Outside Node (no
712
+ * `process.stderr`, e.g. a browser) it is a no-op, and a write failure is
713
+ * swallowed so progress can never crash a run.
714
+ */
715
+ declare function reportReplayProgress(progress: ReplayProgress): void;
679
716
  /** Per-trace context passed to {@link ReplayOptions.adaptInputs}. */
680
717
  interface AdaptContext {
681
718
  /** Bitfab trace ID of the historical trace being replayed. */
@@ -1491,7 +1528,7 @@ declare class BitfabFunction {
1491
1528
  /**
1492
1529
  * SDK version from package.json (injected at build time)
1493
1530
  */
1494
- declare const __version__ = "0.26.1";
1531
+ declare const __version__ = "0.27.0";
1495
1532
 
1496
1533
  /**
1497
1534
  * Constants for the Bitfab SDK.
@@ -1559,4 +1596,4 @@ declare const finalizers: {
1559
1596
  readableStream: typeof readableStream;
1560
1597
  };
1561
1598
 
1562
- export { type ActiveSpanContext, type AdaptContext, type AdaptInputsFn, type AllowedEnvVars, type BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, type BitfabConfig, BitfabError, BitfabFunction, BitfabLangGraphCallbackHandler as BitfabLangChainCallbackHandler, BitfabLangGraphCallbackHandler, type BitfabLanguageModelMiddleware, BitfabOpenAIAgentHandler, BitfabOpenAITracingProcessor, BitfabVercelAiHandler, type CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type DbSnapshotConfig, type DbSnapshotProvider, type DbSnapshotRef, type DetachedTrace, type MockStrategy, type ProviderDefinition, ReplayEnvironment, type ReplayEnvironmentSnapshot, type ReplayItem, type ReplayOptions, type ReplayProgress, type ReplayResult, SUPPORTED_PROVIDERS, 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 };
1599
+ 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 CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type DbSnapshotConfig, type DbSnapshotProvider, type DbSnapshotRef, type DetachedTrace, type MockStrategy, type ProviderDefinition, ReplayEnvironment, type ReplayEnvironmentSnapshot, type ReplayItem, type ReplayOptions, type ReplayProgress, type ReplayResult, SUPPORTED_PROVIDERS, 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 };
package/dist/index.d.ts CHANGED
@@ -579,9 +579,9 @@ declare class ReplayEnvironment {
579
579
  * Replay historical traces through a function and create a test run.
580
580
  *
581
581
  * The replay flow has three phases:
582
- * 1. Start fetches historical traces from the server and creates a test run
583
- * 2. Execute re-runs each trace's inputs through the provided function locally
584
- * 3. Complete marks the test run as completed on the server
582
+ * 1. Start: fetches historical traces from the server and creates a test run
583
+ * 2. Execute: re-runs each trace's inputs through the provided function locally
584
+ * 3. Complete: marks the test run as completed on the server
585
585
  */
586
586
 
587
587
  type MockStrategy = "none" | "all" | "marked";
@@ -603,7 +603,7 @@ interface ReplayOptions {
603
603
  codeChangeDescription?: string;
604
604
  /**
605
605
  * Files edited as part of this code change. Each entry holds the file path
606
- * and the full `before`/`after` contents the agent reads each file before
606
+ * and the full `before`/`after` contents. The agent reads each file before
607
607
  * and after editing and passes the two strings. Use `""` for newly created
608
608
  * files (`before`) or deleted files (`after`).
609
609
  */
@@ -675,7 +675,44 @@ interface ReplayProgress {
675
675
  succeeded: number;
676
676
  /** Of the completed items, how many threw (their `item.error` is set). */
677
677
  errored: number;
678
+ /**
679
+ * The single item that just settled to produce this event. `traceId` is the
680
+ * source (historical) trace that was replayed (so a UI can identify or link
681
+ * it); `error` is its replay error, or null when it ran ok; `durationMs` is how
682
+ * long this one trace took to replay. Lets a progress UI show per-trace
683
+ * pass/fail and timing as the run streams, without waiting for the full
684
+ * {@link ReplayResult}.
685
+ */
686
+ item?: {
687
+ traceId: string | null;
688
+ error: string | null;
689
+ durationMs: number | null;
690
+ };
678
691
  }
692
+ /**
693
+ * Wire prefix the Bitfab plugin scans for. Each line {@link reportReplayProgress}
694
+ * writes is this prefix followed by the JSON of the running totals (plus the
695
+ * settled `item`). The plugin polls these lines to report live progress while a
696
+ * replay runs in the background; keep the SDK emitter and the plugin parser in
697
+ * sync.
698
+ */
699
+ declare const BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
700
+ /**
701
+ * A ready-made {@link ReplayOptions.onProgress} callback for replay scripts.
702
+ * Pass it straight in:
703
+ *
704
+ * ```ts
705
+ * await bitfab.replay("my-fn", fn, { limit, onProgress: reportReplayProgress })
706
+ * ```
707
+ *
708
+ * It writes one `@@bitfab:progress` line per trace to stderr, which the Bitfab
709
+ * plugin polls to report live progress while the replay runs in the background,
710
+ * so scripts never hand-format the wire protocol.
711
+ * stdout is left untouched for the ReplayResult JSON. Outside Node (no
712
+ * `process.stderr`, e.g. a browser) it is a no-op, and a write failure is
713
+ * swallowed so progress can never crash a run.
714
+ */
715
+ declare function reportReplayProgress(progress: ReplayProgress): void;
679
716
  /** Per-trace context passed to {@link ReplayOptions.adaptInputs}. */
680
717
  interface AdaptContext {
681
718
  /** Bitfab trace ID of the historical trace being replayed. */
@@ -1491,7 +1528,7 @@ declare class BitfabFunction {
1491
1528
  /**
1492
1529
  * SDK version from package.json (injected at build time)
1493
1530
  */
1494
- declare const __version__ = "0.26.1";
1531
+ declare const __version__ = "0.27.0";
1495
1532
 
1496
1533
  /**
1497
1534
  * Constants for the Bitfab SDK.
@@ -1559,4 +1596,4 @@ declare const finalizers: {
1559
1596
  readableStream: typeof readableStream;
1560
1597
  };
1561
1598
 
1562
- export { type ActiveSpanContext, type AdaptContext, type AdaptInputsFn, type AllowedEnvVars, type BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, type BitfabConfig, BitfabError, BitfabFunction, BitfabLangGraphCallbackHandler as BitfabLangChainCallbackHandler, BitfabLangGraphCallbackHandler, type BitfabLanguageModelMiddleware, BitfabOpenAIAgentHandler, BitfabOpenAITracingProcessor, BitfabVercelAiHandler, type CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type DbSnapshotConfig, type DbSnapshotProvider, type DbSnapshotRef, type DetachedTrace, type MockStrategy, type ProviderDefinition, ReplayEnvironment, type ReplayEnvironmentSnapshot, type ReplayItem, type ReplayOptions, type ReplayProgress, type ReplayResult, SUPPORTED_PROVIDERS, 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 };
1599
+ 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 CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type DbSnapshotConfig, type DbSnapshotProvider, type DbSnapshotRef, type DetachedTrace, type MockStrategy, type ProviderDefinition, ReplayEnvironment, type ReplayEnvironmentSnapshot, type ReplayItem, type ReplayOptions, type ReplayProgress, type ReplayResult, SUPPORTED_PROVIDERS, 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 };
package/dist/index.js CHANGED
@@ -23,11 +23,14 @@ import {
23
23
  flushTraces,
24
24
  getCurrentSpan,
25
25
  getCurrentTrace
26
- } from "./chunk-SJFOTDP3.js";
26
+ } from "./chunk-PFV4MPNS.js";
27
27
  import {
28
- BitfabError
29
- } from "./chunk-26MUT4IP.js";
28
+ BITFAB_PROGRESS_PREFIX,
29
+ BitfabError,
30
+ reportReplayProgress
31
+ } from "./chunk-RNTDM6WM.js";
30
32
  export {
33
+ BITFAB_PROGRESS_PREFIX,
31
34
  Bitfab,
32
35
  BitfabClaudeAgentHandler,
33
36
  BitfabError,
@@ -44,6 +47,7 @@ export {
44
47
  finalizers,
45
48
  flushTraces,
46
49
  getCurrentSpan,
47
- getCurrentTrace
50
+ getCurrentTrace,
51
+ reportReplayProgress
48
52
  };
49
53
  //# sourceMappingURL=index.js.map
package/dist/node.cjs CHANGED
@@ -119,35 +119,6 @@ var init_warnOnce = __esm({
119
119
  }
120
120
  });
121
121
 
122
- // src/randomUuid.ts
123
- function randomUuid() {
124
- const globalCrypto = globalThis.crypto;
125
- if (typeof globalCrypto?.randomUUID === "function") {
126
- try {
127
- return globalCrypto.randomUUID();
128
- } catch {
129
- }
130
- }
131
- warnOnce(
132
- "crypto-unavailable",
133
- "global crypto.randomUUID is unavailable; using a non-cryptographic fallback for trace/span ids. Tracing works normally (ids are correlation-only, not security-sensitive)."
134
- );
135
- return fallbackUuidV4();
136
- }
137
- function fallbackUuidV4() {
138
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
139
- const rand = Math.random() * 16 | 0;
140
- const value = char === "x" ? rand : rand & 3 | 8;
141
- return value.toString(16);
142
- });
143
- }
144
- var init_randomUuid = __esm({
145
- "src/randomUuid.ts"() {
146
- "use strict";
147
- init_warnOnce();
148
- }
149
- });
150
-
151
122
  // src/serialize.ts
152
123
  function describeValue(value) {
153
124
  try {
@@ -203,7 +174,11 @@ function deserializeValue(serialized) {
203
174
  });
204
175
  }
205
176
  function toJsonSafe(value) {
206
- const safe = toJsonSafeInner(value, 0, /* @__PURE__ */ new WeakSet());
177
+ return toJsonSafeReport(value).safe;
178
+ }
179
+ function toJsonSafeReport(value) {
180
+ const dropped = [];
181
+ const safe = toJsonSafeInner(value, 0, /* @__PURE__ */ new WeakSet(), dropped);
207
182
  try {
208
183
  const size = JSON.stringify(safe)?.length ?? 0;
209
184
  if (size > MAX_FRAMEWORK_SERIALIZED_BYTES) {
@@ -211,13 +186,16 @@ function toJsonSafe(value) {
211
186
  "toJsonSafe:too_large",
212
187
  `a framework payload exceeded ${MAX_FRAMEWORK_SERIALIZED_BYTES} bytes and was replaced with a placeholder so the span still ships. The captured state for this span is incomplete.`
213
188
  );
214
- return `<unserializable: too_large_${size}_bytes>`;
189
+ return {
190
+ safe: `<unserializable: too_large_${size}_bytes>`,
191
+ dropped: [...dropped, `too_large_${size}_bytes`]
192
+ };
215
193
  }
216
194
  } catch {
217
195
  }
218
- return safe;
196
+ return { safe, dropped };
219
197
  }
220
- function toJsonSafeInner(value, depth, seen) {
198
+ function toJsonSafeInner(value, depth, seen, dropped) {
221
199
  if (value === null || value === void 0) {
222
200
  return value;
223
201
  }
@@ -226,30 +204,40 @@ function toJsonSafeInner(value, depth, seen) {
226
204
  }
227
205
  const className = value?.constructor?.name ?? typeof value;
228
206
  if (depth > MAX_SAFE_DEPTH) {
207
+ dropped.push(className);
229
208
  return `<${className}>`;
230
209
  }
231
210
  if (typeof value !== "object") {
211
+ if (typeof value === "function" || typeof value === "symbol") {
212
+ dropped.push(className);
213
+ }
232
214
  try {
233
215
  return String(value);
234
216
  } catch {
217
+ dropped.push(className);
235
218
  return `<${className}>`;
236
219
  }
237
220
  }
238
221
  if (seen.has(value)) {
222
+ dropped.push(className);
239
223
  return `<cycle ${className}>`;
240
224
  }
241
225
  seen.add(value);
242
226
  let result;
243
227
  if (Array.isArray(value)) {
244
- result = value.map((item) => toJsonSafeInner(item, depth + 1, seen));
228
+ result = value.map(
229
+ (item) => toJsonSafeInner(item, depth + 1, seen, dropped)
230
+ );
245
231
  } else if (typeof value.toJSON === "function") {
246
232
  try {
247
233
  result = toJsonSafeInner(
248
234
  value.toJSON(),
249
235
  depth + 1,
250
- seen
236
+ seen,
237
+ dropped
251
238
  );
252
239
  } catch {
240
+ dropped.push(className);
253
241
  result = `<${className}>`;
254
242
  }
255
243
  } else {
@@ -257,11 +245,12 @@ function toJsonSafeInner(value, depth, seen) {
257
245
  const obj = {};
258
246
  for (const [k, v] of Object.entries(value)) {
259
247
  if (!k.startsWith("_")) {
260
- obj[k] = toJsonSafeInner(v, depth + 1, seen);
248
+ obj[k] = toJsonSafeInner(v, depth + 1, seen, dropped);
261
249
  }
262
250
  }
263
251
  result = obj;
264
252
  } catch {
253
+ dropped.push(className);
265
254
  result = `<${className}>`;
266
255
  }
267
256
  }
@@ -280,6 +269,35 @@ var init_serialize = __esm({
280
269
  }
281
270
  });
282
271
 
272
+ // src/randomUuid.ts
273
+ function randomUuid() {
274
+ const globalCrypto = globalThis.crypto;
275
+ if (typeof globalCrypto?.randomUUID === "function") {
276
+ try {
277
+ return globalCrypto.randomUUID();
278
+ } catch {
279
+ }
280
+ }
281
+ warnOnce(
282
+ "crypto-unavailable",
283
+ "global crypto.randomUUID is unavailable; using a non-cryptographic fallback for trace/span ids. Tracing works normally (ids are correlation-only, not security-sensitive)."
284
+ );
285
+ return fallbackUuidV4();
286
+ }
287
+ function fallbackUuidV4() {
288
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
289
+ const rand = Math.random() * 16 | 0;
290
+ const value = char === "x" ? rand : rand & 3 | 8;
291
+ return value.toString(16);
292
+ });
293
+ }
294
+ var init_randomUuid = __esm({
295
+ "src/randomUuid.ts"() {
296
+ "use strict";
297
+ init_warnOnce();
298
+ }
299
+ });
300
+
283
301
  // src/replayContext.ts
284
302
  function getReplayContext() {
285
303
  return replayContextStorage?.getStore() ?? null;
@@ -305,8 +323,21 @@ var init_replayContext = __esm({
305
323
  // src/replay.ts
306
324
  var replay_exports = {};
307
325
  __export(replay_exports, {
308
- replay: () => replay
326
+ BITFAB_PROGRESS_PREFIX: () => BITFAB_PROGRESS_PREFIX,
327
+ replay: () => replay,
328
+ reportReplayProgress: () => reportReplayProgress
309
329
  });
330
+ function reportReplayProgress(progress) {
331
+ const stderr = typeof process !== "undefined" ? process.stderr : void 0;
332
+ if (!stderr) {
333
+ return;
334
+ }
335
+ try {
336
+ stderr.write(`${BITFAB_PROGRESS_PREFIX}${JSON.stringify(progress)}
337
+ `);
338
+ } catch {
339
+ }
340
+ }
310
341
  function deserializeInputs(spanData) {
311
342
  const inputMeta = spanData.input_meta;
312
343
  const rawInput = spanData.input;
@@ -504,7 +535,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
504
535
  const resultItems = await mapWithConcurrency(
505
536
  tasks,
506
537
  maxConcurrency,
507
- options?.onProgress ? (item) => {
538
+ options?.onProgress ? (item, index) => {
508
539
  completed += 1;
509
540
  if (item.error === null) {
510
541
  succeeded += 1;
@@ -512,7 +543,20 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
512
543
  errored += 1;
513
544
  }
514
545
  try {
515
- options?.onProgress?.({ completed, total, succeeded, errored });
546
+ options?.onProgress?.({
547
+ completed,
548
+ total,
549
+ succeeded,
550
+ errored,
551
+ item: {
552
+ // Source (historical) trace id, so a UI can identify the trace
553
+ // that just settled. The item's own traceId is the new replay
554
+ // trace and is assigned later (below), so use the server item.
555
+ traceId: serverItems[index]?.traceId ?? null,
556
+ error: item.error,
557
+ durationMs: item.durationMs
558
+ }
559
+ });
516
560
  } catch {
517
561
  }
518
562
  } : void 0
@@ -569,6 +613,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
569
613
  testRunUrl: `${serviceUrl}${testRunUrl}`
570
614
  };
571
615
  }
616
+ var BITFAB_PROGRESS_PREFIX;
572
617
  var init_replay = __esm({
573
618
  "src/replay.ts"() {
574
619
  "use strict";
@@ -576,12 +621,14 @@ var init_replay = __esm({
576
621
  init_randomUuid();
577
622
  init_replayContext();
578
623
  init_serialize();
624
+ BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
579
625
  }
580
626
  });
581
627
 
582
628
  // src/node.ts
583
629
  var node_exports = {};
584
630
  __export(node_exports, {
631
+ BITFAB_PROGRESS_PREFIX: () => BITFAB_PROGRESS_PREFIX,
585
632
  Bitfab: () => Bitfab,
586
633
  BitfabClaudeAgentHandler: () => BitfabClaudeAgentHandler,
587
634
  BitfabError: () => BitfabError,
@@ -598,7 +645,8 @@ __export(node_exports, {
598
645
  finalizers: () => finalizers,
599
646
  flushTraces: () => flushTraces,
600
647
  getCurrentSpan: () => getCurrentSpan,
601
- getCurrentTrace: () => getCurrentTrace
648
+ getCurrentTrace: () => getCurrentTrace,
649
+ reportReplayProgress: () => reportReplayProgress
602
650
  });
603
651
  module.exports = __toCommonJS(node_exports);
604
652
 
@@ -610,7 +658,7 @@ registerAsyncLocalStorageClass(
610
658
  );
611
659
 
612
660
  // src/version.generated.ts
613
- var __version__ = "0.26.1";
661
+ var __version__ = "0.27.0";
614
662
 
615
663
  // src/constants.ts
616
664
  var DEFAULT_SERVICE_URL = "https://bitfab.ai";
@@ -1052,6 +1100,62 @@ var HttpClient = class {
1052
1100
  }
1053
1101
  };
1054
1102
 
1103
+ // src/processorPayload.ts
1104
+ init_serialize();
1105
+ init_warnOnce();
1106
+ var SERIALIZATION_DEGRADED_STEP = "serialization_degraded";
1107
+ function degradedError(dropped) {
1108
+ const names = [...new Set(dropped)].sort().join(", ");
1109
+ return {
1110
+ source: "sdk",
1111
+ step: SERIALIZATION_DEGRADED_STEP,
1112
+ error: `non-replayable: could not faithfully capture ${names}`
1113
+ };
1114
+ }
1115
+ var ENVELOPE_FIELDS = [
1116
+ "type",
1117
+ "source",
1118
+ "traceFunctionKey",
1119
+ "sourceTraceId",
1120
+ "completed"
1121
+ ];
1122
+ function rebuildEnvelope(payload, bodyKey, placeholder) {
1123
+ const rebuilt = {};
1124
+ for (const k of ENVELOPE_FIELDS) {
1125
+ if (k in payload) {
1126
+ rebuilt[k] = payload[k];
1127
+ }
1128
+ }
1129
+ rebuilt[bodyKey] = { serialized: placeholder };
1130
+ return rebuilt;
1131
+ }
1132
+ function finalizeSpanPayload(payload, extraDropped) {
1133
+ const { safe, dropped } = toJsonSafeReport(payload);
1134
+ const allDropped = [...extraDropped ?? [], ...dropped];
1135
+ const collapsed = safe === null || typeof safe !== "object" || Array.isArray(safe);
1136
+ const result = collapsed ? rebuildEnvelope(payload, "rawSpan", safe) : safe;
1137
+ if (allDropped.length > 0) {
1138
+ const existing = result.errors;
1139
+ const errors = Array.isArray(existing) ? existing : [];
1140
+ errors.push(degradedError(allDropped));
1141
+ result.errors = errors;
1142
+ }
1143
+ return result;
1144
+ }
1145
+ function finalizeTracePayload(payload) {
1146
+ const { safe, dropped } = toJsonSafeReport(payload);
1147
+ const collapsed = safe === null || typeof safe !== "object" || Array.isArray(safe);
1148
+ const result = collapsed ? rebuildEnvelope(payload, "externalTrace", safe) : safe;
1149
+ if (dropped.length > 0 || collapsed) {
1150
+ const names = dropped.length > 0 ? [...new Set(dropped)].sort().join(", ") : "trace";
1151
+ warnOnce(
1152
+ `finalizeTrace:${names.replace(/\d+/g, "N")}`,
1153
+ `a trace held non-serializable value(s) (${names}); they were captured as placeholders, so the trace may not be replayable.`
1154
+ );
1155
+ }
1156
+ return result;
1157
+ }
1158
+
1055
1159
  // src/claudeAgentSdk.ts
1056
1160
  init_randomUuid();
1057
1161
  init_serialize();
@@ -1181,6 +1285,7 @@ var BitfabClaudeAgentHandler = class {
1181
1285
  // ── span helpers ─────────────────────────────────────────────
1182
1286
  startSpan(spanId, name, spanType, inputData, parentId) {
1183
1287
  const traceId = this.ensureTrace();
1288
+ const { safe: safeInput, dropped: inputDropped } = toJsonSafeReport(inputData);
1184
1289
  const spanInfo = {
1185
1290
  spanId,
1186
1291
  traceId,
@@ -1188,9 +1293,12 @@ var BitfabClaudeAgentHandler = class {
1188
1293
  startedAt: nowIso(),
1189
1294
  name,
1190
1295
  type: spanType,
1191
- input: safeSerialize(inputData),
1296
+ input: safeInput,
1192
1297
  contexts: []
1193
1298
  };
1299
+ if (inputDropped.length > 0) {
1300
+ spanInfo.dropped = [...inputDropped];
1301
+ }
1194
1302
  this.runToSpan.set(spanId, spanInfo);
1195
1303
  return spanInfo;
1196
1304
  }
@@ -1201,7 +1309,11 @@ var BitfabClaudeAgentHandler = class {
1201
1309
  }
1202
1310
  this.runToSpan.delete(spanId);
1203
1311
  spanInfo.endedAt = nowIso();
1204
- spanInfo.output = safeSerialize(output);
1312
+ const { safe: safeOutput, dropped: outputDropped } = toJsonSafeReport(output);
1313
+ spanInfo.output = safeOutput;
1314
+ if (outputDropped.length > 0) {
1315
+ spanInfo.dropped = [...spanInfo.dropped ?? [], ...outputDropped];
1316
+ }
1205
1317
  if (error !== void 0) {
1206
1318
  spanInfo.error = error;
1207
1319
  }
@@ -1244,8 +1356,9 @@ var BitfabClaudeAgentHandler = class {
1244
1356
  sourceTraceId: spanInfo.traceId,
1245
1357
  rawSpan
1246
1358
  };
1359
+ const finalized = finalizeSpanPayload(payload, spanInfo.dropped);
1247
1360
  try {
1248
- this.httpClient.sendExternalSpan(payload);
1361
+ this.httpClient.sendExternalSpan(finalized);
1249
1362
  } catch {
1250
1363
  }
1251
1364
  }
@@ -1272,8 +1385,9 @@ var BitfabClaudeAgentHandler = class {
1272
1385
  externalTrace,
1273
1386
  completed
1274
1387
  };
1388
+ const finalized = finalizeTracePayload(traceData);
1275
1389
  try {
1276
- this.httpClient.sendExternalTrace(traceData);
1390
+ this.httpClient.sendExternalTrace(finalized);
1277
1391
  } catch {
1278
1392
  }
1279
1393
  }
@@ -1911,7 +2025,6 @@ var LANGGRAPH_METADATA_KEYS = [
1911
2025
  function nowIso2() {
1912
2026
  return (/* @__PURE__ */ new Date()).toISOString();
1913
2027
  }
1914
- var safeSerialize2 = toJsonSafe;
1915
2028
  function convertMessage(message) {
1916
2029
  if (typeof message !== "object" || message === null) {
1917
2030
  return { role: "unknown", content: String(message) };
@@ -2156,6 +2269,7 @@ var BitfabLangGraphCallbackHandler = class {
2156
2269
  }
2157
2270
  const lgMetadata = extractLangGraphMetadata(metadata);
2158
2271
  const contexts = Object.keys(lgMetadata).length > 0 ? [lgMetadata] : [];
2272
+ const { safe: safeInput, dropped: inputDropped } = toJsonSafeReport(inputData);
2159
2273
  const spanInfo = {
2160
2274
  spanId: runId,
2161
2275
  traceId: invocation.traceId,
@@ -2164,9 +2278,12 @@ var BitfabLangGraphCallbackHandler = class {
2164
2278
  startedAt: nowIso2(),
2165
2279
  name,
2166
2280
  type: spanType,
2167
- input: safeSerialize2(inputData),
2281
+ input: safeInput,
2168
2282
  contexts
2169
2283
  };
2284
+ if (inputDropped.length > 0) {
2285
+ spanInfo.dropped = [...inputDropped];
2286
+ }
2170
2287
  if (willHide) {
2171
2288
  spanInfo.hidden = true;
2172
2289
  }
@@ -2180,7 +2297,11 @@ var BitfabLangGraphCallbackHandler = class {
2180
2297
  }
2181
2298
  this.runToSpan.delete(runId);
2182
2299
  spanInfo.endedAt = nowIso2();
2183
- spanInfo.output = safeSerialize2(output);
2300
+ const { safe: safeOutput, dropped: outputDropped } = toJsonSafeReport(output);
2301
+ spanInfo.output = safeOutput;
2302
+ if (outputDropped.length > 0) {
2303
+ spanInfo.dropped = [...spanInfo.dropped ?? [], ...outputDropped];
2304
+ }
2184
2305
  if (error !== void 0) {
2185
2306
  spanInfo.error = error;
2186
2307
  }
@@ -2231,8 +2352,9 @@ var BitfabLangGraphCallbackHandler = class {
2231
2352
  sourceTraceId: spanInfo.traceId,
2232
2353
  rawSpan
2233
2354
  };
2355
+ const finalized = finalizeSpanPayload(payload, spanInfo.dropped);
2234
2356
  try {
2235
- this.httpClient.sendExternalSpan(payload);
2357
+ this.httpClient.sendExternalSpan(finalized);
2236
2358
  } catch {
2237
2359
  }
2238
2360
  }
@@ -2250,8 +2372,9 @@ var BitfabLangGraphCallbackHandler = class {
2250
2372
  },
2251
2373
  completed
2252
2374
  };
2375
+ const finalized = finalizeTracePayload(traceData);
2253
2376
  try {
2254
- this.httpClient.sendExternalTrace(traceData);
2377
+ this.httpClient.sendExternalTrace(finalized);
2255
2378
  } catch {
2256
2379
  }
2257
2380
  }
@@ -2766,7 +2889,7 @@ var BitfabOpenAITracingProcessor = class {
2766
2889
  if (errors.length > 0) {
2767
2890
  payload.errors = errors;
2768
2891
  }
2769
- return payload;
2892
+ return finalizeSpanPayload(payload);
2770
2893
  }
2771
2894
  /**
2772
2895
  * Send span to Bitfab API (fire-and-forget).
@@ -4277,11 +4400,15 @@ var finalizers = {
4277
4400
  readableStream
4278
4401
  };
4279
4402
 
4403
+ // src/index.ts
4404
+ init_replay();
4405
+
4280
4406
  // src/node.ts
4281
4407
  init_asyncStorage();
4282
4408
  assertAsyncStorageRegistered();
4283
4409
  // Annotate the CommonJS export names for ESM import in node:
4284
4410
  0 && (module.exports = {
4411
+ BITFAB_PROGRESS_PREFIX,
4285
4412
  Bitfab,
4286
4413
  BitfabClaudeAgentHandler,
4287
4414
  BitfabError,
@@ -4298,6 +4425,7 @@ assertAsyncStorageRegistered();
4298
4425
  finalizers,
4299
4426
  flushTraces,
4300
4427
  getCurrentSpan,
4301
- getCurrentTrace
4428
+ getCurrentTrace,
4429
+ reportReplayProgress
4302
4430
  });
4303
4431
  //# sourceMappingURL=node.cjs.map