bitfab 0.11.5 → 0.12.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/{chunk-GWHHP5PL.js → chunk-QUCK3IU2.js} +34 -4
- package/dist/chunk-QUCK3IU2.js.map +1 -0
- package/dist/{chunk-KSUI74KL.js → chunk-VMJPNYAG.js} +38 -2
- package/dist/chunk-VMJPNYAG.js.map +1 -0
- package/dist/index.cjs +106 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -2
- package/dist/index.d.ts +21 -2
- package/dist/index.js +2 -2
- package/dist/node.cjs +106 -5
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +2 -2
- package/dist/{replay-RR4IVBXE.js → replay-6FKD2UEU.js} +41 -5
- package/dist/replay-6FKD2UEU.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-GWHHP5PL.js.map +0 -1
- package/dist/chunk-KSUI74KL.js.map +0 -1
- package/dist/replay-RR4IVBXE.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -258,6 +258,7 @@ declare class BitfabLangGraphCallbackHandler {
|
|
|
258
258
|
* 3. Complete — marks the test run as completed on the server
|
|
259
259
|
*/
|
|
260
260
|
|
|
261
|
+
type MockStrategy = "none" | "all" | "marked";
|
|
261
262
|
interface ReplayOptions {
|
|
262
263
|
/** Maximum number of traces to replay (1–100, default 5). */
|
|
263
264
|
limit?: number;
|
|
@@ -277,6 +278,13 @@ interface ReplayOptions {
|
|
|
277
278
|
* files (`before`) or deleted files (`after`).
|
|
278
279
|
*/
|
|
279
280
|
codeChangeFiles?: CodeChangeFile[];
|
|
281
|
+
/**
|
|
282
|
+
* Mock strategy for child spans during replay.
|
|
283
|
+
* - "none": everything runs real code (default)
|
|
284
|
+
* - "all": every child withSpan returns historical output
|
|
285
|
+
* - "marked": only spans tagged with { mockOnReplay: true } in SpanOptions are mocked
|
|
286
|
+
*/
|
|
287
|
+
mock?: MockStrategy;
|
|
280
288
|
}
|
|
281
289
|
interface ReplayItem<T> {
|
|
282
290
|
/** Deserialized inputs from the original trace. */
|
|
@@ -533,6 +541,16 @@ interface SpanOptions {
|
|
|
533
541
|
* The type of span. Defaults to "custom" if not specified.
|
|
534
542
|
*/
|
|
535
543
|
type?: SpanType;
|
|
544
|
+
/**
|
|
545
|
+
* When true, replay will reuse this span's historical output instead of
|
|
546
|
+
* executing the wrapped function. Read by the "marked" replay strategy;
|
|
547
|
+
* ignored outside replay and under the "all"/"none" strategies.
|
|
548
|
+
*
|
|
549
|
+
* Use this for child spans that are expensive (paid LLM/API calls),
|
|
550
|
+
* slow, or non-deterministic — the root function still runs real code,
|
|
551
|
+
* only the marked descendants return their recorded output.
|
|
552
|
+
*/
|
|
553
|
+
mockOnReplay?: boolean;
|
|
536
554
|
}
|
|
537
555
|
|
|
538
556
|
/**
|
|
@@ -740,6 +758,7 @@ declare class Bitfab {
|
|
|
740
758
|
maxConcurrency?: number;
|
|
741
759
|
codeChangeDescription?: string;
|
|
742
760
|
codeChangeFiles?: CodeChangeFile[];
|
|
761
|
+
mock?: "none" | "all" | "marked";
|
|
743
762
|
}): Promise<ReplayResult<TReturn>>;
|
|
744
763
|
}
|
|
745
764
|
/**
|
|
@@ -803,7 +822,7 @@ declare class BitfabFunction {
|
|
|
803
822
|
/**
|
|
804
823
|
* SDK version from package.json (injected at build time)
|
|
805
824
|
*/
|
|
806
|
-
declare const __version__ = "0.
|
|
825
|
+
declare const __version__ = "0.12.0";
|
|
807
826
|
|
|
808
827
|
/**
|
|
809
828
|
* Constants for the Bitfab SDK.
|
|
@@ -813,4 +832,4 @@ declare const __version__ = "0.11.5";
|
|
|
813
832
|
*/
|
|
814
833
|
declare const DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
815
834
|
|
|
816
|
-
export { type ActiveSpanContext, type AllowedEnvVars, type BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, type BitfabConfig, BitfabError, BitfabFunction, BitfabLangGraphCallbackHandler, BitfabOpenAITracingProcessor, type CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type ProviderDefinition, type ReplayItem, type ReplayOptions, type ReplayResult, type SpanOptions, type SpanType, type TokenUsage, type TraceResponse, type TracingProcessor, type WrapBAMLOptions, type WrappedBamlFn, __version__, flushTraces, getCurrentSpan, getCurrentTrace };
|
|
835
|
+
export { type ActiveSpanContext, type AllowedEnvVars, type BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, type BitfabConfig, BitfabError, BitfabFunction, BitfabLangGraphCallbackHandler, BitfabOpenAITracingProcessor, type CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type MockStrategy, type ProviderDefinition, type ReplayItem, type ReplayOptions, type ReplayResult, type SpanOptions, type SpanType, type TokenUsage, type TraceResponse, type TracingProcessor, type WrapBAMLOptions, type WrappedBamlFn, __version__, flushTraces, getCurrentSpan, getCurrentTrace };
|
package/dist/index.d.ts
CHANGED
|
@@ -258,6 +258,7 @@ declare class BitfabLangGraphCallbackHandler {
|
|
|
258
258
|
* 3. Complete — marks the test run as completed on the server
|
|
259
259
|
*/
|
|
260
260
|
|
|
261
|
+
type MockStrategy = "none" | "all" | "marked";
|
|
261
262
|
interface ReplayOptions {
|
|
262
263
|
/** Maximum number of traces to replay (1–100, default 5). */
|
|
263
264
|
limit?: number;
|
|
@@ -277,6 +278,13 @@ interface ReplayOptions {
|
|
|
277
278
|
* files (`before`) or deleted files (`after`).
|
|
278
279
|
*/
|
|
279
280
|
codeChangeFiles?: CodeChangeFile[];
|
|
281
|
+
/**
|
|
282
|
+
* Mock strategy for child spans during replay.
|
|
283
|
+
* - "none": everything runs real code (default)
|
|
284
|
+
* - "all": every child withSpan returns historical output
|
|
285
|
+
* - "marked": only spans tagged with { mockOnReplay: true } in SpanOptions are mocked
|
|
286
|
+
*/
|
|
287
|
+
mock?: MockStrategy;
|
|
280
288
|
}
|
|
281
289
|
interface ReplayItem<T> {
|
|
282
290
|
/** Deserialized inputs from the original trace. */
|
|
@@ -533,6 +541,16 @@ interface SpanOptions {
|
|
|
533
541
|
* The type of span. Defaults to "custom" if not specified.
|
|
534
542
|
*/
|
|
535
543
|
type?: SpanType;
|
|
544
|
+
/**
|
|
545
|
+
* When true, replay will reuse this span's historical output instead of
|
|
546
|
+
* executing the wrapped function. Read by the "marked" replay strategy;
|
|
547
|
+
* ignored outside replay and under the "all"/"none" strategies.
|
|
548
|
+
*
|
|
549
|
+
* Use this for child spans that are expensive (paid LLM/API calls),
|
|
550
|
+
* slow, or non-deterministic — the root function still runs real code,
|
|
551
|
+
* only the marked descendants return their recorded output.
|
|
552
|
+
*/
|
|
553
|
+
mockOnReplay?: boolean;
|
|
536
554
|
}
|
|
537
555
|
|
|
538
556
|
/**
|
|
@@ -740,6 +758,7 @@ declare class Bitfab {
|
|
|
740
758
|
maxConcurrency?: number;
|
|
741
759
|
codeChangeDescription?: string;
|
|
742
760
|
codeChangeFiles?: CodeChangeFile[];
|
|
761
|
+
mock?: "none" | "all" | "marked";
|
|
743
762
|
}): Promise<ReplayResult<TReturn>>;
|
|
744
763
|
}
|
|
745
764
|
/**
|
|
@@ -803,7 +822,7 @@ declare class BitfabFunction {
|
|
|
803
822
|
/**
|
|
804
823
|
* SDK version from package.json (injected at build time)
|
|
805
824
|
*/
|
|
806
|
-
declare const __version__ = "0.
|
|
825
|
+
declare const __version__ = "0.12.0";
|
|
807
826
|
|
|
808
827
|
/**
|
|
809
828
|
* Constants for the Bitfab SDK.
|
|
@@ -813,4 +832,4 @@ declare const __version__ = "0.11.5";
|
|
|
813
832
|
*/
|
|
814
833
|
declare const DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
815
834
|
|
|
816
|
-
export { type ActiveSpanContext, type AllowedEnvVars, type BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, type BitfabConfig, BitfabError, BitfabFunction, BitfabLangGraphCallbackHandler, BitfabOpenAITracingProcessor, type CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type ProviderDefinition, type ReplayItem, type ReplayOptions, type ReplayResult, type SpanOptions, type SpanType, type TokenUsage, type TraceResponse, type TracingProcessor, type WrapBAMLOptions, type WrappedBamlFn, __version__, flushTraces, getCurrentSpan, getCurrentTrace };
|
|
835
|
+
export { type ActiveSpanContext, type AllowedEnvVars, type BamlExecutionResult, Bitfab, BitfabClaudeAgentHandler, type BitfabConfig, BitfabError, BitfabFunction, BitfabLangGraphCallbackHandler, BitfabOpenAITracingProcessor, type CodeChangeFile, type CurrentSpan, type CurrentTrace, DEFAULT_SERVICE_URL, type MockStrategy, type ProviderDefinition, type ReplayItem, type ReplayOptions, type ReplayResult, type SpanOptions, type SpanType, type TokenUsage, type TraceResponse, type TracingProcessor, type WrapBAMLOptions, type WrappedBamlFn, __version__, flushTraces, getCurrentSpan, getCurrentTrace };
|
package/dist/index.js
CHANGED
|
@@ -6,13 +6,13 @@ import {
|
|
|
6
6
|
BitfabOpenAITracingProcessor,
|
|
7
7
|
getCurrentSpan,
|
|
8
8
|
getCurrentTrace
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-QUCK3IU2.js";
|
|
10
10
|
import {
|
|
11
11
|
BitfabError,
|
|
12
12
|
DEFAULT_SERVICE_URL,
|
|
13
13
|
__version__,
|
|
14
14
|
flushTraces
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-VMJPNYAG.js";
|
|
16
16
|
export {
|
|
17
17
|
Bitfab,
|
|
18
18
|
BitfabClaudeAgentHandler,
|
package/dist/node.cjs
CHANGED
|
@@ -81,7 +81,7 @@ var __version__;
|
|
|
81
81
|
var init_version_generated = __esm({
|
|
82
82
|
"src/version.generated.ts"() {
|
|
83
83
|
"use strict";
|
|
84
|
-
__version__ = "0.
|
|
84
|
+
__version__ = "0.12.0";
|
|
85
85
|
}
|
|
86
86
|
});
|
|
87
87
|
|
|
@@ -336,6 +336,42 @@ var init_http = __esm({
|
|
|
336
336
|
clearTimeout(timeoutId);
|
|
337
337
|
}
|
|
338
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* Fetch the span tree for a root span.
|
|
341
|
+
* Blocking GET request.
|
|
342
|
+
*/
|
|
343
|
+
async getSpanTree(externalSpanId) {
|
|
344
|
+
const url = `${this.serviceUrl}/api/sdk/replay/spanTree/${externalSpanId}`;
|
|
345
|
+
const controller = new AbortController();
|
|
346
|
+
const timeoutId = setTimeout(() => controller.abort(), 3e4);
|
|
347
|
+
try {
|
|
348
|
+
const response = await fetch(url, {
|
|
349
|
+
method: "GET",
|
|
350
|
+
headers: { Authorization: `Bearer ${this.apiKey}` },
|
|
351
|
+
signal: controller.signal
|
|
352
|
+
});
|
|
353
|
+
if (!response.ok) {
|
|
354
|
+
const errorText = await response.text();
|
|
355
|
+
throw new BitfabError(
|
|
356
|
+
`HTTP ${response.status}: ${errorText.slice(0, 500)}`
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
return await response.json();
|
|
360
|
+
} catch (error) {
|
|
361
|
+
if (error instanceof BitfabError) {
|
|
362
|
+
throw error;
|
|
363
|
+
}
|
|
364
|
+
if (error instanceof Error) {
|
|
365
|
+
if (error.name === "AbortError") {
|
|
366
|
+
throw new BitfabError("Request timed out after 30000ms");
|
|
367
|
+
}
|
|
368
|
+
throw new BitfabError(error.message);
|
|
369
|
+
}
|
|
370
|
+
throw new BitfabError("Unknown error occurred");
|
|
371
|
+
} finally {
|
|
372
|
+
clearTimeout(timeoutId);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
339
375
|
/**
|
|
340
376
|
* Mark a replay test run as completed.
|
|
341
377
|
* Blocking call.
|
|
@@ -431,16 +467,51 @@ function deserializeOutput(spanData) {
|
|
|
431
467
|
}
|
|
432
468
|
return rawOutput;
|
|
433
469
|
}
|
|
434
|
-
|
|
470
|
+
function buildMockTree(rootNode) {
|
|
471
|
+
const spans = /* @__PURE__ */ new Map();
|
|
472
|
+
const counters = /* @__PURE__ */ new Map();
|
|
473
|
+
function walk(node) {
|
|
474
|
+
const key = node.traceFunctionKey;
|
|
475
|
+
if (key) {
|
|
476
|
+
const index = counters.get(key) ?? 0;
|
|
477
|
+
counters.set(key, index + 1);
|
|
478
|
+
spans.set(`${key}:${index}`, {
|
|
479
|
+
sourceSpanId: node.sourceSpanId,
|
|
480
|
+
output: node.output,
|
|
481
|
+
outputMeta: node.outputMeta
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
for (const child of node.children) {
|
|
485
|
+
walk(child);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
for (const child of rootNode.children) {
|
|
489
|
+
walk(child);
|
|
490
|
+
}
|
|
491
|
+
return { spans };
|
|
492
|
+
}
|
|
493
|
+
async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy) {
|
|
435
494
|
const span = await httpClient.getExternalSpan(serverItem.externalSpanId);
|
|
436
495
|
const spanData = span.rawData?.span_data ?? {};
|
|
437
496
|
const inputs = deserializeInputs(spanData);
|
|
438
497
|
const originalOutput = deserializeOutput(spanData);
|
|
498
|
+
let mockTree;
|
|
499
|
+
if (mockStrategy === "all" || mockStrategy === "marked") {
|
|
500
|
+
const treeResponse = await httpClient.getSpanTree(serverItem.externalSpanId);
|
|
501
|
+
mockTree = buildMockTree(treeResponse.root);
|
|
502
|
+
}
|
|
439
503
|
let result;
|
|
440
504
|
let error = null;
|
|
441
505
|
try {
|
|
442
506
|
const maybePromise = runWithReplayContext(
|
|
443
|
-
{
|
|
507
|
+
{
|
|
508
|
+
testRunId,
|
|
509
|
+
inputSourceSpanId: span.id,
|
|
510
|
+
inputSourceTraceId: span.externalTraceId,
|
|
511
|
+
mockTree,
|
|
512
|
+
callCounters: mockTree ? /* @__PURE__ */ new Map() : void 0,
|
|
513
|
+
mockStrategy
|
|
514
|
+
},
|
|
444
515
|
() => fn(...inputs)
|
|
445
516
|
);
|
|
446
517
|
result = maybePromise instanceof Promise ? await maybePromise : maybePromise;
|
|
@@ -486,9 +557,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
|
|
|
486
557
|
options?.codeChangeDescription,
|
|
487
558
|
options?.codeChangeFiles
|
|
488
559
|
);
|
|
560
|
+
const mockStrategy = options?.mock ?? "none";
|
|
489
561
|
const maxConcurrency = options?.maxConcurrency ?? 10;
|
|
490
562
|
const tasks = serverItems.map(
|
|
491
|
-
(serverItem) => () => processItem(httpClient, serverItem, fn, testRunId)
|
|
563
|
+
(serverItem) => () => processItem(httpClient, serverItem, fn, testRunId, mockStrategy)
|
|
492
564
|
);
|
|
493
565
|
const resultItems = await mapWithConcurrency(tasks, maxConcurrency);
|
|
494
566
|
await flushTraces();
|
|
@@ -2569,6 +2641,9 @@ var Bitfab = class {
|
|
|
2569
2641
|
contexts: [],
|
|
2570
2642
|
...replayCtxAtRoot?.testRunId && {
|
|
2571
2643
|
testRunId: replayCtxAtRoot.testRunId
|
|
2644
|
+
},
|
|
2645
|
+
...replayCtxAtRoot?.inputSourceTraceId && {
|
|
2646
|
+
inputSourceTraceId: replayCtxAtRoot.inputSourceTraceId
|
|
2572
2647
|
}
|
|
2573
2648
|
});
|
|
2574
2649
|
pendingSpanPromises.set(traceId, []);
|
|
@@ -2617,7 +2692,8 @@ var Bitfab = class {
|
|
|
2617
2692
|
sessionId: traceState?.sessionId,
|
|
2618
2693
|
metadata: traceState?.metadata,
|
|
2619
2694
|
contexts: traceState?.contexts ?? [],
|
|
2620
|
-
testRunId: traceState?.testRunId
|
|
2695
|
+
testRunId: traceState?.testRunId,
|
|
2696
|
+
inputSourceTraceId: traceState?.inputSourceTraceId
|
|
2621
2697
|
});
|
|
2622
2698
|
activeTraceStates.delete(traceId);
|
|
2623
2699
|
} else {
|
|
@@ -2631,6 +2707,28 @@ var Bitfab = class {
|
|
|
2631
2707
|
} catch {
|
|
2632
2708
|
}
|
|
2633
2709
|
};
|
|
2710
|
+
const replayCtxForMock = getReplayContext();
|
|
2711
|
+
if (replayCtxForMock?.mockTree && !isRootSpan) {
|
|
2712
|
+
const counters = replayCtxForMock.callCounters;
|
|
2713
|
+
const callIndex = counters.get(traceFunctionKey) ?? 0;
|
|
2714
|
+
counters.set(traceFunctionKey, callIndex + 1);
|
|
2715
|
+
const shouldMock = replayCtxForMock.mockStrategy === "all" || replayCtxForMock.mockStrategy === "marked" && options.mockOnReplay === true;
|
|
2716
|
+
if (shouldMock) {
|
|
2717
|
+
const mockKey = `${traceFunctionKey}:${callIndex}`;
|
|
2718
|
+
const mockSpan = replayCtxForMock.mockTree.spans.get(mockKey);
|
|
2719
|
+
if (mockSpan) {
|
|
2720
|
+
let output = mockSpan.output;
|
|
2721
|
+
if (mockSpan.outputMeta !== void 0 && mockSpan.outputMeta !== null) {
|
|
2722
|
+
output = deserializeValue({
|
|
2723
|
+
json: mockSpan.output,
|
|
2724
|
+
meta: mockSpan.outputMeta
|
|
2725
|
+
});
|
|
2726
|
+
}
|
|
2727
|
+
void sendSpan({ result: output });
|
|
2728
|
+
return output;
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2634
2732
|
const executeWithContext = () => {
|
|
2635
2733
|
const result = fn(...args);
|
|
2636
2734
|
if (result instanceof Promise) {
|
|
@@ -2694,6 +2792,9 @@ var Bitfab = class {
|
|
|
2694
2792
|
if (params.contexts && params.contexts.length > 0) {
|
|
2695
2793
|
rawTrace.contexts = params.contexts;
|
|
2696
2794
|
}
|
|
2795
|
+
if (params.inputSourceTraceId) {
|
|
2796
|
+
rawTrace.input_source_trace_id = params.inputSourceTraceId;
|
|
2797
|
+
}
|
|
2697
2798
|
this.httpClient.sendExternalTrace({
|
|
2698
2799
|
type: "sdk-function",
|
|
2699
2800
|
source: "typescript-sdk-function",
|