@bitfab/sdk 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
@@ -14,11 +14,14 @@ import {
14
14
  flushTraces,
15
15
  getCurrentSpan,
16
16
  getCurrentTrace
17
- } from "./chunk-SJFOTDP3.js";
17
+ } from "./chunk-PFV4MPNS.js";
18
18
  import {
19
- BitfabError
20
- } from "./chunk-26MUT4IP.js";
19
+ BITFAB_PROGRESS_PREFIX,
20
+ BitfabError,
21
+ reportReplayProgress
22
+ } from "./chunk-RNTDM6WM.js";
21
23
  export {
24
+ BITFAB_PROGRESS_PREFIX,
22
25
  Bitfab,
23
26
  BitfabClaudeAgentHandler,
24
27
  BitfabError,
@@ -35,6 +38,7 @@ export {
35
38
  finalizers,
36
39
  flushTraces,
37
40
  getCurrentSpan,
38
- getCurrentTrace
41
+ getCurrentTrace,
42
+ reportReplayProgress
39
43
  };
40
44
  //# sourceMappingURL=index.js.map
package/dist/node.cjs CHANGED
@@ -110,35 +110,6 @@ var init_warnOnce = __esm({
110
110
  }
111
111
  });
112
112
 
113
- // src/randomUuid.ts
114
- function randomUuid() {
115
- const globalCrypto = globalThis.crypto;
116
- if (typeof globalCrypto?.randomUUID === "function") {
117
- try {
118
- return globalCrypto.randomUUID();
119
- } catch {
120
- }
121
- }
122
- warnOnce(
123
- "crypto-unavailable",
124
- "global crypto.randomUUID is unavailable; using a non-cryptographic fallback for trace/span ids. Tracing works normally (ids are correlation-only, not security-sensitive)."
125
- );
126
- return fallbackUuidV4();
127
- }
128
- function fallbackUuidV4() {
129
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
130
- const rand = Math.random() * 16 | 0;
131
- const value = char === "x" ? rand : rand & 3 | 8;
132
- return value.toString(16);
133
- });
134
- }
135
- var init_randomUuid = __esm({
136
- "src/randomUuid.ts"() {
137
- "use strict";
138
- init_warnOnce();
139
- }
140
- });
141
-
142
113
  // src/serialize.ts
143
114
  function describeValue(value) {
144
115
  try {
@@ -194,7 +165,11 @@ function deserializeValue(serialized) {
194
165
  });
195
166
  }
196
167
  function toJsonSafe(value) {
197
- const safe = toJsonSafeInner(value, 0, /* @__PURE__ */ new WeakSet());
168
+ return toJsonSafeReport(value).safe;
169
+ }
170
+ function toJsonSafeReport(value) {
171
+ const dropped = [];
172
+ const safe = toJsonSafeInner(value, 0, /* @__PURE__ */ new WeakSet(), dropped);
198
173
  try {
199
174
  const size = JSON.stringify(safe)?.length ?? 0;
200
175
  if (size > MAX_FRAMEWORK_SERIALIZED_BYTES) {
@@ -202,13 +177,16 @@ function toJsonSafe(value) {
202
177
  "toJsonSafe:too_large",
203
178
  `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.`
204
179
  );
205
- return `<unserializable: too_large_${size}_bytes>`;
180
+ return {
181
+ safe: `<unserializable: too_large_${size}_bytes>`,
182
+ dropped: [...dropped, `too_large_${size}_bytes`]
183
+ };
206
184
  }
207
185
  } catch {
208
186
  }
209
- return safe;
187
+ return { safe, dropped };
210
188
  }
211
- function toJsonSafeInner(value, depth, seen) {
189
+ function toJsonSafeInner(value, depth, seen, dropped) {
212
190
  if (value === null || value === void 0) {
213
191
  return value;
214
192
  }
@@ -217,30 +195,40 @@ function toJsonSafeInner(value, depth, seen) {
217
195
  }
218
196
  const className = value?.constructor?.name ?? typeof value;
219
197
  if (depth > MAX_SAFE_DEPTH) {
198
+ dropped.push(className);
220
199
  return `<${className}>`;
221
200
  }
222
201
  if (typeof value !== "object") {
202
+ if (typeof value === "function" || typeof value === "symbol") {
203
+ dropped.push(className);
204
+ }
223
205
  try {
224
206
  return String(value);
225
207
  } catch {
208
+ dropped.push(className);
226
209
  return `<${className}>`;
227
210
  }
228
211
  }
229
212
  if (seen.has(value)) {
213
+ dropped.push(className);
230
214
  return `<cycle ${className}>`;
231
215
  }
232
216
  seen.add(value);
233
217
  let result;
234
218
  if (Array.isArray(value)) {
235
- result = value.map((item) => toJsonSafeInner(item, depth + 1, seen));
219
+ result = value.map(
220
+ (item) => toJsonSafeInner(item, depth + 1, seen, dropped)
221
+ );
236
222
  } else if (typeof value.toJSON === "function") {
237
223
  try {
238
224
  result = toJsonSafeInner(
239
225
  value.toJSON(),
240
226
  depth + 1,
241
- seen
227
+ seen,
228
+ dropped
242
229
  );
243
230
  } catch {
231
+ dropped.push(className);
244
232
  result = `<${className}>`;
245
233
  }
246
234
  } else {
@@ -248,11 +236,12 @@ function toJsonSafeInner(value, depth, seen) {
248
236
  const obj = {};
249
237
  for (const [k, v] of Object.entries(value)) {
250
238
  if (!k.startsWith("_")) {
251
- obj[k] = toJsonSafeInner(v, depth + 1, seen);
239
+ obj[k] = toJsonSafeInner(v, depth + 1, seen, dropped);
252
240
  }
253
241
  }
254
242
  result = obj;
255
243
  } catch {
244
+ dropped.push(className);
256
245
  result = `<${className}>`;
257
246
  }
258
247
  }
@@ -271,6 +260,35 @@ var init_serialize = __esm({
271
260
  }
272
261
  });
273
262
 
263
+ // src/randomUuid.ts
264
+ function randomUuid() {
265
+ const globalCrypto = globalThis.crypto;
266
+ if (typeof globalCrypto?.randomUUID === "function") {
267
+ try {
268
+ return globalCrypto.randomUUID();
269
+ } catch {
270
+ }
271
+ }
272
+ warnOnce(
273
+ "crypto-unavailable",
274
+ "global crypto.randomUUID is unavailable; using a non-cryptographic fallback for trace/span ids. Tracing works normally (ids are correlation-only, not security-sensitive)."
275
+ );
276
+ return fallbackUuidV4();
277
+ }
278
+ function fallbackUuidV4() {
279
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
280
+ const rand = Math.random() * 16 | 0;
281
+ const value = char === "x" ? rand : rand & 3 | 8;
282
+ return value.toString(16);
283
+ });
284
+ }
285
+ var init_randomUuid = __esm({
286
+ "src/randomUuid.ts"() {
287
+ "use strict";
288
+ init_warnOnce();
289
+ }
290
+ });
291
+
274
292
  // src/replayContext.ts
275
293
  function getReplayContext() {
276
294
  return replayContextStorage?.getStore() ?? null;
@@ -296,8 +314,21 @@ var init_replayContext = __esm({
296
314
  // src/replay.ts
297
315
  var replay_exports = {};
298
316
  __export(replay_exports, {
299
- replay: () => replay
317
+ BITFAB_PROGRESS_PREFIX: () => BITFAB_PROGRESS_PREFIX,
318
+ replay: () => replay,
319
+ reportReplayProgress: () => reportReplayProgress
300
320
  });
321
+ function reportReplayProgress(progress) {
322
+ const stderr = typeof process !== "undefined" ? process.stderr : void 0;
323
+ if (!stderr) {
324
+ return;
325
+ }
326
+ try {
327
+ stderr.write(`${BITFAB_PROGRESS_PREFIX}${JSON.stringify(progress)}
328
+ `);
329
+ } catch {
330
+ }
331
+ }
301
332
  function deserializeInputs(spanData) {
302
333
  const inputMeta = spanData.input_meta;
303
334
  const rawInput = spanData.input;
@@ -495,7 +526,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
495
526
  const resultItems = await mapWithConcurrency(
496
527
  tasks,
497
528
  maxConcurrency,
498
- options?.onProgress ? (item) => {
529
+ options?.onProgress ? (item, index) => {
499
530
  completed += 1;
500
531
  if (item.error === null) {
501
532
  succeeded += 1;
@@ -503,7 +534,20 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
503
534
  errored += 1;
504
535
  }
505
536
  try {
506
- options?.onProgress?.({ completed, total, succeeded, errored });
537
+ options?.onProgress?.({
538
+ completed,
539
+ total,
540
+ succeeded,
541
+ errored,
542
+ item: {
543
+ // Source (historical) trace id, so a UI can identify the trace
544
+ // that just settled. The item's own traceId is the new replay
545
+ // trace and is assigned later (below), so use the server item.
546
+ traceId: serverItems[index]?.traceId ?? null,
547
+ error: item.error,
548
+ durationMs: item.durationMs
549
+ }
550
+ });
507
551
  } catch {
508
552
  }
509
553
  } : void 0
@@ -560,6 +604,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
560
604
  testRunUrl: `${serviceUrl}${testRunUrl}`
561
605
  };
562
606
  }
607
+ var BITFAB_PROGRESS_PREFIX;
563
608
  var init_replay = __esm({
564
609
  "src/replay.ts"() {
565
610
  "use strict";
@@ -567,12 +612,14 @@ var init_replay = __esm({
567
612
  init_randomUuid();
568
613
  init_replayContext();
569
614
  init_serialize();
615
+ BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
570
616
  }
571
617
  });
572
618
 
573
619
  // src/node.ts
574
620
  var node_exports = {};
575
621
  __export(node_exports, {
622
+ BITFAB_PROGRESS_PREFIX: () => BITFAB_PROGRESS_PREFIX,
576
623
  Bitfab: () => Bitfab,
577
624
  BitfabClaudeAgentHandler: () => BitfabClaudeAgentHandler,
578
625
  BitfabError: () => BitfabError,
@@ -589,7 +636,8 @@ __export(node_exports, {
589
636
  finalizers: () => finalizers,
590
637
  flushTraces: () => flushTraces,
591
638
  getCurrentSpan: () => getCurrentSpan,
592
- getCurrentTrace: () => getCurrentTrace
639
+ getCurrentTrace: () => getCurrentTrace,
640
+ reportReplayProgress: () => reportReplayProgress
593
641
  });
594
642
  module.exports = __toCommonJS(node_exports);
595
643
 
@@ -601,7 +649,7 @@ registerAsyncLocalStorageClass(
601
649
  );
602
650
 
603
651
  // src/version.generated.ts
604
- var __version__ = "0.26.1";
652
+ var __version__ = "0.27.0";
605
653
 
606
654
  // src/constants.ts
607
655
  var DEFAULT_SERVICE_URL = "https://bitfab.ai";
@@ -1043,6 +1091,62 @@ var HttpClient = class {
1043
1091
  }
1044
1092
  };
1045
1093
 
1094
+ // src/processorPayload.ts
1095
+ init_serialize();
1096
+ init_warnOnce();
1097
+ var SERIALIZATION_DEGRADED_STEP = "serialization_degraded";
1098
+ function degradedError(dropped) {
1099
+ const names = [...new Set(dropped)].sort().join(", ");
1100
+ return {
1101
+ source: "sdk",
1102
+ step: SERIALIZATION_DEGRADED_STEP,
1103
+ error: `non-replayable: could not faithfully capture ${names}`
1104
+ };
1105
+ }
1106
+ var ENVELOPE_FIELDS = [
1107
+ "type",
1108
+ "source",
1109
+ "traceFunctionKey",
1110
+ "sourceTraceId",
1111
+ "completed"
1112
+ ];
1113
+ function rebuildEnvelope(payload, bodyKey, placeholder) {
1114
+ const rebuilt = {};
1115
+ for (const k of ENVELOPE_FIELDS) {
1116
+ if (k in payload) {
1117
+ rebuilt[k] = payload[k];
1118
+ }
1119
+ }
1120
+ rebuilt[bodyKey] = { serialized: placeholder };
1121
+ return rebuilt;
1122
+ }
1123
+ function finalizeSpanPayload(payload, extraDropped) {
1124
+ const { safe, dropped } = toJsonSafeReport(payload);
1125
+ const allDropped = [...extraDropped ?? [], ...dropped];
1126
+ const collapsed = safe === null || typeof safe !== "object" || Array.isArray(safe);
1127
+ const result = collapsed ? rebuildEnvelope(payload, "rawSpan", safe) : safe;
1128
+ if (allDropped.length > 0) {
1129
+ const existing = result.errors;
1130
+ const errors = Array.isArray(existing) ? existing : [];
1131
+ errors.push(degradedError(allDropped));
1132
+ result.errors = errors;
1133
+ }
1134
+ return result;
1135
+ }
1136
+ function finalizeTracePayload(payload) {
1137
+ const { safe, dropped } = toJsonSafeReport(payload);
1138
+ const collapsed = safe === null || typeof safe !== "object" || Array.isArray(safe);
1139
+ const result = collapsed ? rebuildEnvelope(payload, "externalTrace", safe) : safe;
1140
+ if (dropped.length > 0 || collapsed) {
1141
+ const names = dropped.length > 0 ? [...new Set(dropped)].sort().join(", ") : "trace";
1142
+ warnOnce(
1143
+ `finalizeTrace:${names.replace(/\d+/g, "N")}`,
1144
+ `a trace held non-serializable value(s) (${names}); they were captured as placeholders, so the trace may not be replayable.`
1145
+ );
1146
+ }
1147
+ return result;
1148
+ }
1149
+
1046
1150
  // src/claudeAgentSdk.ts
1047
1151
  init_randomUuid();
1048
1152
  init_serialize();
@@ -1172,6 +1276,7 @@ var BitfabClaudeAgentHandler = class {
1172
1276
  // ── span helpers ─────────────────────────────────────────────
1173
1277
  startSpan(spanId, name, spanType, inputData, parentId) {
1174
1278
  const traceId = this.ensureTrace();
1279
+ const { safe: safeInput, dropped: inputDropped } = toJsonSafeReport(inputData);
1175
1280
  const spanInfo = {
1176
1281
  spanId,
1177
1282
  traceId,
@@ -1179,9 +1284,12 @@ var BitfabClaudeAgentHandler = class {
1179
1284
  startedAt: nowIso(),
1180
1285
  name,
1181
1286
  type: spanType,
1182
- input: safeSerialize(inputData),
1287
+ input: safeInput,
1183
1288
  contexts: []
1184
1289
  };
1290
+ if (inputDropped.length > 0) {
1291
+ spanInfo.dropped = [...inputDropped];
1292
+ }
1185
1293
  this.runToSpan.set(spanId, spanInfo);
1186
1294
  return spanInfo;
1187
1295
  }
@@ -1192,7 +1300,11 @@ var BitfabClaudeAgentHandler = class {
1192
1300
  }
1193
1301
  this.runToSpan.delete(spanId);
1194
1302
  spanInfo.endedAt = nowIso();
1195
- spanInfo.output = safeSerialize(output);
1303
+ const { safe: safeOutput, dropped: outputDropped } = toJsonSafeReport(output);
1304
+ spanInfo.output = safeOutput;
1305
+ if (outputDropped.length > 0) {
1306
+ spanInfo.dropped = [...spanInfo.dropped ?? [], ...outputDropped];
1307
+ }
1196
1308
  if (error !== void 0) {
1197
1309
  spanInfo.error = error;
1198
1310
  }
@@ -1235,8 +1347,9 @@ var BitfabClaudeAgentHandler = class {
1235
1347
  sourceTraceId: spanInfo.traceId,
1236
1348
  rawSpan
1237
1349
  };
1350
+ const finalized = finalizeSpanPayload(payload, spanInfo.dropped);
1238
1351
  try {
1239
- this.httpClient.sendExternalSpan(payload);
1352
+ this.httpClient.sendExternalSpan(finalized);
1240
1353
  } catch {
1241
1354
  }
1242
1355
  }
@@ -1263,8 +1376,9 @@ var BitfabClaudeAgentHandler = class {
1263
1376
  externalTrace,
1264
1377
  completed
1265
1378
  };
1379
+ const finalized = finalizeTracePayload(traceData);
1266
1380
  try {
1267
- this.httpClient.sendExternalTrace(traceData);
1381
+ this.httpClient.sendExternalTrace(finalized);
1268
1382
  } catch {
1269
1383
  }
1270
1384
  }
@@ -1902,7 +2016,6 @@ var LANGGRAPH_METADATA_KEYS = [
1902
2016
  function nowIso2() {
1903
2017
  return (/* @__PURE__ */ new Date()).toISOString();
1904
2018
  }
1905
- var safeSerialize2 = toJsonSafe;
1906
2019
  function convertMessage(message) {
1907
2020
  if (typeof message !== "object" || message === null) {
1908
2021
  return { role: "unknown", content: String(message) };
@@ -2147,6 +2260,7 @@ var BitfabLangGraphCallbackHandler = class {
2147
2260
  }
2148
2261
  const lgMetadata = extractLangGraphMetadata(metadata);
2149
2262
  const contexts = Object.keys(lgMetadata).length > 0 ? [lgMetadata] : [];
2263
+ const { safe: safeInput, dropped: inputDropped } = toJsonSafeReport(inputData);
2150
2264
  const spanInfo = {
2151
2265
  spanId: runId,
2152
2266
  traceId: invocation.traceId,
@@ -2155,9 +2269,12 @@ var BitfabLangGraphCallbackHandler = class {
2155
2269
  startedAt: nowIso2(),
2156
2270
  name,
2157
2271
  type: spanType,
2158
- input: safeSerialize2(inputData),
2272
+ input: safeInput,
2159
2273
  contexts
2160
2274
  };
2275
+ if (inputDropped.length > 0) {
2276
+ spanInfo.dropped = [...inputDropped];
2277
+ }
2161
2278
  if (willHide) {
2162
2279
  spanInfo.hidden = true;
2163
2280
  }
@@ -2171,7 +2288,11 @@ var BitfabLangGraphCallbackHandler = class {
2171
2288
  }
2172
2289
  this.runToSpan.delete(runId);
2173
2290
  spanInfo.endedAt = nowIso2();
2174
- spanInfo.output = safeSerialize2(output);
2291
+ const { safe: safeOutput, dropped: outputDropped } = toJsonSafeReport(output);
2292
+ spanInfo.output = safeOutput;
2293
+ if (outputDropped.length > 0) {
2294
+ spanInfo.dropped = [...spanInfo.dropped ?? [], ...outputDropped];
2295
+ }
2175
2296
  if (error !== void 0) {
2176
2297
  spanInfo.error = error;
2177
2298
  }
@@ -2222,8 +2343,9 @@ var BitfabLangGraphCallbackHandler = class {
2222
2343
  sourceTraceId: spanInfo.traceId,
2223
2344
  rawSpan
2224
2345
  };
2346
+ const finalized = finalizeSpanPayload(payload, spanInfo.dropped);
2225
2347
  try {
2226
- this.httpClient.sendExternalSpan(payload);
2348
+ this.httpClient.sendExternalSpan(finalized);
2227
2349
  } catch {
2228
2350
  }
2229
2351
  }
@@ -2241,8 +2363,9 @@ var BitfabLangGraphCallbackHandler = class {
2241
2363
  },
2242
2364
  completed
2243
2365
  };
2366
+ const finalized = finalizeTracePayload(traceData);
2244
2367
  try {
2245
- this.httpClient.sendExternalTrace(traceData);
2368
+ this.httpClient.sendExternalTrace(finalized);
2246
2369
  } catch {
2247
2370
  }
2248
2371
  }
@@ -2757,7 +2880,7 @@ var BitfabOpenAITracingProcessor = class {
2757
2880
  if (errors.length > 0) {
2758
2881
  payload.errors = errors;
2759
2882
  }
2760
- return payload;
2883
+ return finalizeSpanPayload(payload);
2761
2884
  }
2762
2885
  /**
2763
2886
  * Send span to Bitfab API (fire-and-forget).
@@ -4268,11 +4391,15 @@ var finalizers = {
4268
4391
  readableStream
4269
4392
  };
4270
4393
 
4394
+ // src/index.ts
4395
+ init_replay();
4396
+
4271
4397
  // src/node.ts
4272
4398
  init_asyncStorage();
4273
4399
  assertAsyncStorageRegistered();
4274
4400
  // Annotate the CommonJS export names for ESM import in node:
4275
4401
  0 && (module.exports = {
4402
+ BITFAB_PROGRESS_PREFIX,
4276
4403
  Bitfab,
4277
4404
  BitfabClaudeAgentHandler,
4278
4405
  BitfabError,
@@ -4289,6 +4416,7 @@ assertAsyncStorageRegistered();
4289
4416
  finalizers,
4290
4417
  flushTraces,
4291
4418
  getCurrentSpan,
4292
- getCurrentTrace
4419
+ getCurrentTrace,
4420
+ reportReplayProgress
4293
4421
  });
4294
4422
  //# sourceMappingURL=node.cjs.map