@bitfab/sdk 0.28.11 → 0.29.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-ZBWTCBVQ.js → chunk-RTPEBWVO.js} +102 -45
- package/dist/chunk-RTPEBWVO.js.map +1 -0
- package/dist/{chunk-5E4BUIYA.js → chunk-YZU6WFG2.js} +113 -55
- package/dist/chunk-YZU6WFG2.js.map +1 -0
- package/dist/index.cjs +218 -96
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +165 -15
- package/dist/index.d.ts +165 -15
- package/dist/index.js +2 -2
- package/dist/node.cjs +218 -96
- 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-IEE4RY57.js → replay-SKW5A7II.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-5E4BUIYA.js.map +0 -1
- package/dist/chunk-ZBWTCBVQ.js.map +0 -1
- /package/dist/{replay-IEE4RY57.js.map → replay-SKW5A7II.js.map} +0 -0
|
@@ -6,14 +6,15 @@ import {
|
|
|
6
6
|
getReplayContext,
|
|
7
7
|
isAsyncStorageInitDone,
|
|
8
8
|
randomUuid,
|
|
9
|
+
resolveMockValue,
|
|
9
10
|
serializeValue,
|
|
10
11
|
toJsonSafe,
|
|
11
12
|
toJsonSafeReport,
|
|
12
13
|
warnOnce
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-YZU6WFG2.js";
|
|
14
15
|
|
|
15
16
|
// src/version.generated.ts
|
|
16
|
-
var __version__ = "0.
|
|
17
|
+
var __version__ = "0.29.1";
|
|
17
18
|
|
|
18
19
|
// src/constants.ts
|
|
19
20
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -438,9 +439,14 @@ var HttpClient = class {
|
|
|
438
439
|
/**
|
|
439
440
|
* Fetch the span tree for a root span.
|
|
440
441
|
* Blocking GET request.
|
|
442
|
+
*
|
|
443
|
+
* Pass `includeOutputs: false` for a payload-free tree (structure +
|
|
444
|
+
* `externalSpanId` only), so recorded outputs are fetched lazily per mocked
|
|
445
|
+
* span instead of all up front. Omit it (default eager) for `mock: "all"`.
|
|
441
446
|
*/
|
|
442
|
-
async getSpanTree(externalSpanId) {
|
|
443
|
-
const
|
|
447
|
+
async getSpanTree(externalSpanId, options) {
|
|
448
|
+
const query = options?.includeOutputs === false ? "?includeOutputs=false" : "";
|
|
449
|
+
const url = `${this.serviceUrl}/api/sdk/replay/spanTree/${externalSpanId}${query}`;
|
|
444
450
|
const controller = new AbortController();
|
|
445
451
|
const timeoutId = setTimeout(() => controller.abort(), 3e4);
|
|
446
452
|
try {
|
|
@@ -2821,6 +2827,12 @@ var Bitfab = class {
|
|
|
2821
2827
|
constructor(config) {
|
|
2822
2828
|
/** Gate the empty-key warning to fire at most once. */
|
|
2823
2829
|
this.apiKeyWarned = false;
|
|
2830
|
+
/**
|
|
2831
|
+
* Mock overrides registered via {@link Bitfab.registerMockOverride}, applied
|
|
2832
|
+
* to every `replay` on this client (after any per-call `mockOverride`). In
|
|
2833
|
+
* registration order; first matcher wins within this list.
|
|
2834
|
+
*/
|
|
2835
|
+
this.mockOverrides = [];
|
|
2824
2836
|
this.apiKeyConfig = config.apiKey;
|
|
2825
2837
|
this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL;
|
|
2826
2838
|
this.timeout = config.timeout ?? 12e4;
|
|
@@ -3405,7 +3417,7 @@ var Bitfab = class {
|
|
|
3405
3417
|
dbSnapshotUsage: {
|
|
3406
3418
|
neonBranchId: replayCtx.dbBranchLease.neonBranchId,
|
|
3407
3419
|
snapshotTimestamp: replayCtx.dbBranchLease.snapshotTimestamp,
|
|
3408
|
-
|
|
3420
|
+
originalTraceId: replayCtx.sourceBitfabTraceId,
|
|
3409
3421
|
accessed: replayCtx.dbSnapshotAccessed === true
|
|
3410
3422
|
}
|
|
3411
3423
|
}
|
|
@@ -3433,25 +3445,78 @@ var Bitfab = class {
|
|
|
3433
3445
|
const counterKey = `${traceFunctionKey}:${baseSpanParams.spanName}`;
|
|
3434
3446
|
const callIndex = counters.get(counterKey) ?? 0;
|
|
3435
3447
|
counters.set(counterKey, callIndex + 1);
|
|
3436
|
-
const
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
if (
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
+
const mockKey = `${counterKey}:${callIndex}`;
|
|
3449
|
+
const mockSpan = replayCtxForMock.mockTree.spans.get(mockKey);
|
|
3450
|
+
const emitMock = (output) => {
|
|
3451
|
+
void sendSpan({ result: output, mocked: true });
|
|
3452
|
+
if (fnReturnsPromise) {
|
|
3453
|
+
return Promise.resolve(output);
|
|
3454
|
+
}
|
|
3455
|
+
return output;
|
|
3456
|
+
};
|
|
3457
|
+
const emitMockAsync = (pending) => {
|
|
3458
|
+
if (!fnReturnsPromise) {
|
|
3459
|
+
throw new BitfabError(
|
|
3460
|
+
`Cannot mock synchronous span "${traceFunctionKey}" with an asynchronously-resolved value (lazy recorded-output fetch or an async value function). Make the wrapped function async, or use mock: "all" so recorded outputs are fetched eagerly.`
|
|
3461
|
+
);
|
|
3462
|
+
}
|
|
3463
|
+
return (async () => {
|
|
3464
|
+
const output = await pending;
|
|
3448
3465
|
void sendSpan({ result: output, mocked: true });
|
|
3449
|
-
if (fnReturnsPromise) {
|
|
3450
|
-
return Promise.resolve(output);
|
|
3451
|
-
}
|
|
3452
3466
|
return output;
|
|
3467
|
+
})();
|
|
3468
|
+
};
|
|
3469
|
+
const resolveRecordedOutput = () => {
|
|
3470
|
+
const hasInlineOutput = mockSpan?.output !== void 0 || mockSpan?.outputMeta !== void 0;
|
|
3471
|
+
if (!hasInlineOutput && replayCtxForMock.fetchSpanOutput && mockSpan?.externalSpanId) {
|
|
3472
|
+
return replayCtxForMock.fetchSpanOutput(mockSpan.externalSpanId);
|
|
3473
|
+
}
|
|
3474
|
+
if (!mockSpan) {
|
|
3475
|
+
return Promise.reject(
|
|
3476
|
+
new BitfabError(
|
|
3477
|
+
`No recorded span to source output for "${traceFunctionKey}".`
|
|
3478
|
+
)
|
|
3479
|
+
);
|
|
3480
|
+
}
|
|
3481
|
+
let output = mockSpan.output;
|
|
3482
|
+
if (mockSpan.outputMeta !== void 0 && mockSpan.outputMeta !== null) {
|
|
3483
|
+
output = deserializeValue({
|
|
3484
|
+
json: mockSpan.output,
|
|
3485
|
+
meta: mockSpan.outputMeta
|
|
3486
|
+
});
|
|
3487
|
+
}
|
|
3488
|
+
return output;
|
|
3489
|
+
};
|
|
3490
|
+
if (replayCtxForMock.mockOverrides?.length) {
|
|
3491
|
+
const nodeMeta = {
|
|
3492
|
+
traceFunctionKey,
|
|
3493
|
+
spanName: baseSpanParams.spanName,
|
|
3494
|
+
type: options.type ?? "custom",
|
|
3495
|
+
originalSpanId: mockSpan?.sourceSpanId
|
|
3496
|
+
};
|
|
3497
|
+
const override = replayCtxForMock.mockOverrides.find(
|
|
3498
|
+
(o) => o.match(nodeMeta)
|
|
3499
|
+
);
|
|
3500
|
+
if (override) {
|
|
3501
|
+
const injected = resolveMockValue(override.value, {
|
|
3502
|
+
node: nodeMeta,
|
|
3503
|
+
inputs: args,
|
|
3504
|
+
getOriginalOutput: () => Promise.resolve(resolveRecordedOutput())
|
|
3505
|
+
});
|
|
3506
|
+
if (injected instanceof Promise) {
|
|
3507
|
+
return emitMockAsync(injected);
|
|
3508
|
+
}
|
|
3509
|
+
return emitMock(injected);
|
|
3453
3510
|
}
|
|
3454
3511
|
}
|
|
3512
|
+
const shouldMock = replayCtxForMock.mockStrategy === "all" || replayCtxForMock.mockStrategy === "marked" && options.mockOnReplay === true;
|
|
3513
|
+
if (shouldMock && mockSpan) {
|
|
3514
|
+
const recorded = resolveRecordedOutput();
|
|
3515
|
+
if (recorded instanceof Promise) {
|
|
3516
|
+
return emitMockAsync(recorded);
|
|
3517
|
+
}
|
|
3518
|
+
return emitMock(recorded);
|
|
3519
|
+
}
|
|
3455
3520
|
}
|
|
3456
3521
|
const recordSpan = (result) => {
|
|
3457
3522
|
if (options.finalize) {
|
|
@@ -3656,8 +3721,11 @@ var Bitfab = class {
|
|
|
3656
3721
|
...params.dbSnapshotUsage.snapshotTimestamp && {
|
|
3657
3722
|
snapshot_timestamp: params.dbSnapshotUsage.snapshotTimestamp
|
|
3658
3723
|
},
|
|
3659
|
-
...params.dbSnapshotUsage.
|
|
3660
|
-
|
|
3724
|
+
...params.dbSnapshotUsage.originalTraceId && {
|
|
3725
|
+
original_trace_id: params.dbSnapshotUsage.originalTraceId,
|
|
3726
|
+
// Deprecated wire alias, kept so this SDK still reports usage
|
|
3727
|
+
// against servers that predate the rename.
|
|
3728
|
+
source_trace_id: params.dbSnapshotUsage.originalTraceId
|
|
3661
3729
|
},
|
|
3662
3730
|
accessed: params.dbSnapshotUsage.accessed
|
|
3663
3731
|
};
|
|
@@ -3730,26 +3798,14 @@ var Bitfab = class {
|
|
|
3730
3798
|
...params.mocked && { mocked: true }
|
|
3731
3799
|
});
|
|
3732
3800
|
}
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
* invocation records a trace tied to the test run. The plain-callable form
|
|
3742
|
-
* is how handler-instrumented workflows (LangGraph/LangChain, Claude Agent
|
|
3743
|
-
* SDK) replay - those record traces under a key with no `withSpan`-wrapped
|
|
3744
|
-
* root in the app.
|
|
3745
|
-
*
|
|
3746
|
-
* @param traceFunctionKey - The trace function key to replay
|
|
3747
|
-
* @param fn - The function to run recorded inputs through
|
|
3748
|
-
* @param options - Optional replay options. When `traceIds` is passed,
|
|
3749
|
-
* `limit` is ignored (with a warning): an explicit ID list already
|
|
3750
|
-
* determines how many traces replay.
|
|
3751
|
-
* @returns ReplayResult with items, testRunId, and testRunUrl
|
|
3752
|
-
*/
|
|
3801
|
+
registerMockOverride(overrideOrMatch, value) {
|
|
3802
|
+
const override = typeof overrideOrMatch === "function" ? { match: overrideOrMatch, value } : overrideOrMatch;
|
|
3803
|
+
this.mockOverrides.push(override);
|
|
3804
|
+
}
|
|
3805
|
+
/** Remove all overrides registered via {@link registerMockOverride}. */
|
|
3806
|
+
clearMockOverrides() {
|
|
3807
|
+
this.mockOverrides.length = 0;
|
|
3808
|
+
}
|
|
3753
3809
|
async replay(traceFunctionKey, fn, options) {
|
|
3754
3810
|
const wrappedKey = fn._bitfabTraceFunctionKey;
|
|
3755
3811
|
let replayFn = fn;
|
|
@@ -3764,13 +3820,14 @@ var Bitfab = class {
|
|
|
3764
3820
|
`Function is wrapped with trace function key '${wrappedKey}' but replay was called with '${traceFunctionKey}'. Pass matching keys, or pass the unwrapped function to replay it under the explicit key.`
|
|
3765
3821
|
);
|
|
3766
3822
|
}
|
|
3767
|
-
const { replay: doReplay } = await import("./replay-
|
|
3823
|
+
const { replay: doReplay } = await import("./replay-SKW5A7II.js");
|
|
3768
3824
|
return doReplay(
|
|
3769
3825
|
this.httpClient,
|
|
3770
3826
|
this.serviceUrl,
|
|
3771
3827
|
traceFunctionKey,
|
|
3772
3828
|
replayFn,
|
|
3773
|
-
options
|
|
3829
|
+
options,
|
|
3830
|
+
this.mockOverrides
|
|
3774
3831
|
);
|
|
3775
3832
|
}
|
|
3776
3833
|
};
|
|
@@ -3989,4 +4046,4 @@ export {
|
|
|
3989
4046
|
BitfabFunction,
|
|
3990
4047
|
finalizers
|
|
3991
4048
|
};
|
|
3992
|
-
//# sourceMappingURL=chunk-
|
|
4049
|
+
//# sourceMappingURL=chunk-RTPEBWVO.js.map
|