bitfab 0.11.6 → 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-MTHBHBOD.js → chunk-QUCK3IU2.js} +26 -3
- package/dist/chunk-QUCK3IU2.js.map +1 -0
- package/dist/{chunk-VOSASRED.js → chunk-VMJPNYAG.js} +38 -2
- package/dist/chunk-VMJPNYAG.js.map +1 -0
- package/dist/index.cjs +94 -4
- 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 +94 -4
- 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-DSVTUTGT.js → replay-6FKD2UEU.js} +37 -5
- package/dist/replay-6FKD2UEU.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-MTHBHBOD.js.map +0 -1
- package/dist/chunk-VOSASRED.js.map +0 -1
- package/dist/replay-DSVTUTGT.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.6";
|
|
|
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.6";
|
|
|
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,11 +467,39 @@ 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 {
|
|
@@ -443,7 +507,10 @@ async function processItem(httpClient, serverItem, fn, testRunId) {
|
|
|
443
507
|
{
|
|
444
508
|
testRunId,
|
|
445
509
|
inputSourceSpanId: span.id,
|
|
446
|
-
inputSourceTraceId: span.externalTraceId
|
|
510
|
+
inputSourceTraceId: span.externalTraceId,
|
|
511
|
+
mockTree,
|
|
512
|
+
callCounters: mockTree ? /* @__PURE__ */ new Map() : void 0,
|
|
513
|
+
mockStrategy
|
|
447
514
|
},
|
|
448
515
|
() => fn(...inputs)
|
|
449
516
|
);
|
|
@@ -490,9 +557,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
|
|
|
490
557
|
options?.codeChangeDescription,
|
|
491
558
|
options?.codeChangeFiles
|
|
492
559
|
);
|
|
560
|
+
const mockStrategy = options?.mock ?? "none";
|
|
493
561
|
const maxConcurrency = options?.maxConcurrency ?? 10;
|
|
494
562
|
const tasks = serverItems.map(
|
|
495
|
-
(serverItem) => () => processItem(httpClient, serverItem, fn, testRunId)
|
|
563
|
+
(serverItem) => () => processItem(httpClient, serverItem, fn, testRunId, mockStrategy)
|
|
496
564
|
);
|
|
497
565
|
const resultItems = await mapWithConcurrency(tasks, maxConcurrency);
|
|
498
566
|
await flushTraces();
|
|
@@ -2639,6 +2707,28 @@ var Bitfab = class {
|
|
|
2639
2707
|
} catch {
|
|
2640
2708
|
}
|
|
2641
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
|
+
}
|
|
2642
2732
|
const executeWithContext = () => {
|
|
2643
2733
|
const result = fn(...args);
|
|
2644
2734
|
if (result instanceof Promise) {
|