bitfab 0.11.6 → 0.12.1
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-NU52P7HA.js} +29 -3
- package/dist/chunk-NU52P7HA.js.map +1 -0
- package/dist/{chunk-VOSASRED.js → chunk-OOKZ6S64.js} +38 -2
- package/dist/chunk-OOKZ6S64.js.map +1 -0
- package/dist/index.cjs +95 -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 +95 -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-UQP2XXBZ.js} +35 -5
- package/dist/replay-UQP2XXBZ.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.1";
|
|
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.1";
|
|
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-NU52P7HA.js";
|
|
10
10
|
import {
|
|
11
11
|
BitfabError,
|
|
12
12
|
DEFAULT_SERVICE_URL,
|
|
13
13
|
__version__,
|
|
14
14
|
flushTraces
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-OOKZ6S64.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.1";
|
|
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,37 @@ 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
|
+
walk(rootNode);
|
|
489
|
+
return { spans };
|
|
490
|
+
}
|
|
491
|
+
async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy) {
|
|
435
492
|
const span = await httpClient.getExternalSpan(serverItem.externalSpanId);
|
|
436
493
|
const spanData = span.rawData?.span_data ?? {};
|
|
437
494
|
const inputs = deserializeInputs(spanData);
|
|
438
495
|
const originalOutput = deserializeOutput(spanData);
|
|
496
|
+
let mockTree;
|
|
497
|
+
if (mockStrategy === "all" || mockStrategy === "marked") {
|
|
498
|
+
const treeResponse = await httpClient.getSpanTree(serverItem.externalSpanId);
|
|
499
|
+
mockTree = buildMockTree(treeResponse.root);
|
|
500
|
+
}
|
|
439
501
|
let result;
|
|
440
502
|
let error = null;
|
|
441
503
|
try {
|
|
@@ -443,7 +505,10 @@ async function processItem(httpClient, serverItem, fn, testRunId) {
|
|
|
443
505
|
{
|
|
444
506
|
testRunId,
|
|
445
507
|
inputSourceSpanId: span.id,
|
|
446
|
-
inputSourceTraceId: span.externalTraceId
|
|
508
|
+
inputSourceTraceId: span.externalTraceId,
|
|
509
|
+
mockTree,
|
|
510
|
+
callCounters: mockTree ? /* @__PURE__ */ new Map() : void 0,
|
|
511
|
+
mockStrategy
|
|
447
512
|
},
|
|
448
513
|
() => fn(...inputs)
|
|
449
514
|
);
|
|
@@ -490,9 +555,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
|
|
|
490
555
|
options?.codeChangeDescription,
|
|
491
556
|
options?.codeChangeFiles
|
|
492
557
|
);
|
|
558
|
+
const mockStrategy = options?.mock ?? "none";
|
|
493
559
|
const maxConcurrency = options?.maxConcurrency ?? 10;
|
|
494
560
|
const tasks = serverItems.map(
|
|
495
|
-
(serverItem) => () => processItem(httpClient, serverItem, fn, testRunId)
|
|
561
|
+
(serverItem) => () => processItem(httpClient, serverItem, fn, testRunId, mockStrategy)
|
|
496
562
|
);
|
|
497
563
|
const resultItems = await mapWithConcurrency(tasks, maxConcurrency);
|
|
498
564
|
await flushTraces();
|
|
@@ -2639,6 +2705,31 @@ var Bitfab = class {
|
|
|
2639
2705
|
} catch {
|
|
2640
2706
|
}
|
|
2641
2707
|
};
|
|
2708
|
+
const replayCtxForMock = getReplayContext();
|
|
2709
|
+
if (replayCtxForMock?.mockTree && !isRootSpan) {
|
|
2710
|
+
const counters = replayCtxForMock.callCounters;
|
|
2711
|
+
const callIndex = counters.get(traceFunctionKey) ?? 0;
|
|
2712
|
+
counters.set(traceFunctionKey, callIndex + 1);
|
|
2713
|
+
const shouldMock = replayCtxForMock.mockStrategy === "all" || replayCtxForMock.mockStrategy === "marked" && options.mockOnReplay === true;
|
|
2714
|
+
if (shouldMock) {
|
|
2715
|
+
const mockKey = `${traceFunctionKey}:${callIndex}`;
|
|
2716
|
+
const mockSpan = replayCtxForMock.mockTree.spans.get(mockKey);
|
|
2717
|
+
if (mockSpan) {
|
|
2718
|
+
let output = mockSpan.output;
|
|
2719
|
+
if (mockSpan.outputMeta !== void 0 && mockSpan.outputMeta !== null) {
|
|
2720
|
+
output = deserializeValue({
|
|
2721
|
+
json: mockSpan.output,
|
|
2722
|
+
meta: mockSpan.outputMeta
|
|
2723
|
+
});
|
|
2724
|
+
}
|
|
2725
|
+
void sendSpan({ result: output });
|
|
2726
|
+
if (fn.constructor.name === "AsyncFunction") {
|
|
2727
|
+
return Promise.resolve(output);
|
|
2728
|
+
}
|
|
2729
|
+
return output;
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2642
2733
|
const executeWithContext = () => {
|
|
2643
2734
|
const result = fn(...args);
|
|
2644
2735
|
if (result instanceof Promise) {
|