@bitfab/sdk 0.38.10 → 0.39.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-BNOVHUQB.js → chunk-2JQSYJJR.js} +21 -1102
- package/dist/chunk-2JQSYJJR.js.map +1 -0
- package/dist/chunk-FW7PZ3EP.js +1150 -0
- package/dist/chunk-FW7PZ3EP.js.map +1 -0
- package/dist/chunk-RH4K4RSS.js +1856 -0
- package/dist/chunk-RH4K4RSS.js.map +1 -0
- package/dist/{chunk-UE4GGPM6.js → chunk-SHJ3ABUG.js} +110 -9
- package/dist/chunk-SHJ3ABUG.js.map +1 -0
- package/dist/http-GJZJKNZZ.js +19 -0
- package/dist/http-PRCLI43J.js +20 -0
- package/dist/http-PRCLI43J.js.map +1 -0
- package/dist/index.cjs +166 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +92 -3
- package/dist/index.d.ts +92 -3
- package/dist/index.js +12 -8
- package/dist/node.cjs +166 -6
- 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 +12 -8
- package/dist/node.js.map +1 -1
- package/dist/{replay-SMUBBMNK.js → replay-MZYX4IFV.js} +3 -2
- package/dist/replay-MZYX4IFV.js.map +1 -0
- package/dist/replayCli.js +132 -146
- package/dist/replayCli.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-BNOVHUQB.js.map +0 -1
- package/dist/chunk-UE4GGPM6.js.map +0 -1
- /package/dist/{replay-SMUBBMNK.js.map → http-GJZJKNZZ.js.map} +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BitfabError,
|
|
3
|
+
HttpClient,
|
|
4
|
+
awaitOnExit,
|
|
5
|
+
awaitPendingRequests,
|
|
6
|
+
flushTraces,
|
|
7
|
+
parseRetryAfterMs,
|
|
8
|
+
serializePayloadBody
|
|
9
|
+
} from "./chunk-RH4K4RSS.js";
|
|
10
|
+
export {
|
|
11
|
+
BitfabError,
|
|
12
|
+
HttpClient,
|
|
13
|
+
awaitOnExit,
|
|
14
|
+
awaitPendingRequests,
|
|
15
|
+
flushTraces,
|
|
16
|
+
parseRetryAfterMs,
|
|
17
|
+
serializePayloadBody
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=http-GJZJKNZZ.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BitfabError,
|
|
3
|
+
HttpClient,
|
|
4
|
+
awaitOnExit,
|
|
5
|
+
awaitPendingRequests,
|
|
6
|
+
flushTraces,
|
|
7
|
+
parseRetryAfterMs,
|
|
8
|
+
serializePayloadBody
|
|
9
|
+
} from "./chunk-2JQSYJJR.js";
|
|
10
|
+
import "./chunk-H6LZRFMN.js";
|
|
11
|
+
export {
|
|
12
|
+
BitfabError,
|
|
13
|
+
HttpClient,
|
|
14
|
+
awaitOnExit,
|
|
15
|
+
awaitPendingRequests,
|
|
16
|
+
flushTraces,
|
|
17
|
+
parseRetryAfterMs,
|
|
18
|
+
serializePayloadBody
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=http-PRCLI43J.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -42,7 +42,7 @@ var __version__, __packageName__;
|
|
|
42
42
|
var init_version_generated = __esm({
|
|
43
43
|
"src/version.generated.ts"() {
|
|
44
44
|
"use strict";
|
|
45
|
-
__version__ = "0.
|
|
45
|
+
__version__ = "0.39.0";
|
|
46
46
|
__packageName__ = "@bitfab/sdk";
|
|
47
47
|
}
|
|
48
48
|
});
|
|
@@ -1198,6 +1198,16 @@ var init_transport = __esm({
|
|
|
1198
1198
|
});
|
|
1199
1199
|
|
|
1200
1200
|
// src/http.ts
|
|
1201
|
+
var http_exports = {};
|
|
1202
|
+
__export(http_exports, {
|
|
1203
|
+
BitfabError: () => BitfabError,
|
|
1204
|
+
HttpClient: () => HttpClient,
|
|
1205
|
+
awaitOnExit: () => awaitOnExit,
|
|
1206
|
+
awaitPendingRequests: () => awaitPendingRequests,
|
|
1207
|
+
flushTraces: () => flushTraces,
|
|
1208
|
+
parseRetryAfterMs: () => parseRetryAfterMs,
|
|
1209
|
+
serializePayloadBody: () => serializePayloadBody
|
|
1210
|
+
});
|
|
1201
1211
|
function awaitOnExit(promise) {
|
|
1202
1212
|
pendingTracePromises.add(promise);
|
|
1203
1213
|
void promise.finally(() => {
|
|
@@ -2542,7 +2552,7 @@ function buildMockTree(rootNode) {
|
|
|
2542
2552
|
}
|
|
2543
2553
|
return { spans };
|
|
2544
2554
|
}
|
|
2545
|
-
async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy, resolvedOverrides, replayedTraceId, includeDbBranchLease, dbBranchSettings, adaptInputs) {
|
|
2555
|
+
async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy, resolvedOverrides, replayedTraceId, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
|
|
2546
2556
|
let lease = includeDbBranchLease ? serverItem.dbBranchLease : void 0;
|
|
2547
2557
|
let leaseError = includeDbBranchLease ? serverItem.dbBranchLeaseError : void 0;
|
|
2548
2558
|
let dbSnapshotRef = serverItem.dbSnapshotRef;
|
|
@@ -2637,6 +2647,32 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
2637
2647
|
}
|
|
2638
2648
|
return pending;
|
|
2639
2649
|
} : void 0;
|
|
2650
|
+
if (dryRun) {
|
|
2651
|
+
return {
|
|
2652
|
+
traceId: null,
|
|
2653
|
+
originalTraceId,
|
|
2654
|
+
originalSpanId,
|
|
2655
|
+
sourceTraceId: originalTraceId,
|
|
2656
|
+
sourceSpanId: originalSpanId,
|
|
2657
|
+
input: inputs,
|
|
2658
|
+
result: void 0,
|
|
2659
|
+
originalOutput,
|
|
2660
|
+
...serverItem.ingestionType && {
|
|
2661
|
+
ingestionType: serverItem.ingestionType
|
|
2662
|
+
},
|
|
2663
|
+
error: null,
|
|
2664
|
+
traceError: null,
|
|
2665
|
+
replayError: null,
|
|
2666
|
+
durationMs: null,
|
|
2667
|
+
originalDurationMs: serverItem.originalDurationMs ?? serverItem.durationMs ?? null,
|
|
2668
|
+
originalTokens: serverItem.originalTokens ?? serverItem.tokens ?? null,
|
|
2669
|
+
originalModel: serverItem.originalModel ?? serverItem.model ?? null,
|
|
2670
|
+
tokens: null,
|
|
2671
|
+
model: serverItem.originalModel ?? serverItem.model ?? null,
|
|
2672
|
+
dbSnapshotRef: dbSnapshotRef ?? null,
|
|
2673
|
+
dbBranchTimings: dbBranchTimings ?? null
|
|
2674
|
+
};
|
|
2675
|
+
}
|
|
2640
2676
|
try {
|
|
2641
2677
|
replayStarted = performance.now();
|
|
2642
2678
|
const maybePromise = runWithReplayContext(
|
|
@@ -2700,6 +2736,9 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
2700
2736
|
input: inputs,
|
|
2701
2737
|
result,
|
|
2702
2738
|
originalOutput,
|
|
2739
|
+
...serverItem.ingestionType && {
|
|
2740
|
+
ingestionType: serverItem.ingestionType
|
|
2741
|
+
},
|
|
2703
2742
|
error,
|
|
2704
2743
|
traceError,
|
|
2705
2744
|
replayError,
|
|
@@ -2847,13 +2886,23 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2847
2886
|
options?.name,
|
|
2848
2887
|
codeChangeDescription,
|
|
2849
2888
|
codeChangeFiles,
|
|
2850
|
-
|
|
2851
|
-
//
|
|
2889
|
+
// A dry run executes nothing, so a branch would be provisioned (and billed)
|
|
2890
|
+
// for code that never runs, and a seeded source's refusal would fail the item
|
|
2891
|
+
// before it could report its resolved inputs.
|
|
2892
|
+
dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true,
|
|
2852
2893
|
options?.experimentGroupId,
|
|
2853
2894
|
options?.datasetId,
|
|
2854
2895
|
options?.graderIds,
|
|
2855
2896
|
resolveDbBranchSettings(options?.dbBranch)
|
|
2856
2897
|
);
|
|
2898
|
+
if (serverItems.length === 0) {
|
|
2899
|
+
try {
|
|
2900
|
+
console.warn(
|
|
2901
|
+
`Bitfab: no traces matched "${traceFunctionKey}", so this replay ran nothing. Capture a trace, or seed one with seedTrace, before replaying.`
|
|
2902
|
+
);
|
|
2903
|
+
} catch {
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2857
2906
|
const mockStrategy = options?.mock ?? "marked";
|
|
2858
2907
|
const maxConcurrency = options?.maxConcurrency ?? 10;
|
|
2859
2908
|
const fullTestRunUrl = `${serviceUrl}${testRunUrl}`;
|
|
@@ -2872,9 +2921,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2872
2921
|
mockStrategy,
|
|
2873
2922
|
resolvedOverrides,
|
|
2874
2923
|
replayedTraceIds[index],
|
|
2875
|
-
dbBranchEnabled(options?.dbBranch),
|
|
2924
|
+
dbBranchEnabled(options?.dbBranch) && options?.dryRun !== true,
|
|
2876
2925
|
resolveDbBranchSettings(options?.dbBranch),
|
|
2877
|
-
options?.adaptInputs
|
|
2926
|
+
options?.adaptInputs,
|
|
2927
|
+
options?.dryRun === true
|
|
2878
2928
|
)
|
|
2879
2929
|
);
|
|
2880
2930
|
const total = tasks.length;
|
|
@@ -2982,6 +3032,16 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2982
3032
|
}
|
|
2983
3033
|
} : void 0
|
|
2984
3034
|
);
|
|
3035
|
+
if (options?.dryRun === true) {
|
|
3036
|
+
await httpClient.completeReplay(testRunId).catch(() => void 0);
|
|
3037
|
+
const dryResult = {
|
|
3038
|
+
items: resultItems,
|
|
3039
|
+
testRunId,
|
|
3040
|
+
testRunUrl: fullTestRunUrl
|
|
3041
|
+
};
|
|
3042
|
+
await writeReplayResultFile(dryResult);
|
|
3043
|
+
return dryResult;
|
|
3044
|
+
}
|
|
2985
3045
|
const deliveredTraceIds = await preserveReplayFailure(
|
|
2986
3046
|
() => waitForReplayPersistence(httpClient, testRunId, replayedTraceIds),
|
|
2987
3047
|
resultItems,
|
|
@@ -3150,6 +3210,7 @@ __export(index_exports, {
|
|
|
3150
3210
|
getCurrentSpan: () => getCurrentSpan,
|
|
3151
3211
|
getCurrentTrace: () => getCurrentTrace,
|
|
3152
3212
|
reportReplayProgress: () => reportReplayProgress,
|
|
3213
|
+
seedFromRegistry: () => seedFromRegistry,
|
|
3153
3214
|
serializeReplayResult: () => serializeReplayResult
|
|
3154
3215
|
});
|
|
3155
3216
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -6860,6 +6921,7 @@ var Bitfab = class {
|
|
|
6860
6921
|
inputSourceTraceId: traceState?.inputSourceTraceId,
|
|
6861
6922
|
dbSnapshotRef: traceState?.dbSnapshotRef,
|
|
6862
6923
|
dropped: traceState?.dropped,
|
|
6924
|
+
ingestionType: traceState?.ingestionType,
|
|
6863
6925
|
// Built AFTER the wrapped fn finished, so `accessed` reflects
|
|
6864
6926
|
// whether customer code obtained the branch URL during this
|
|
6865
6927
|
// item. Omitted entirely when no lease was attached, so the
|
|
@@ -7083,6 +7145,7 @@ var Bitfab = class {
|
|
|
7083
7145
|
Object.defineProperty(wrappedFn, "_bitfabTraceFunctionKey", {
|
|
7084
7146
|
value: traceFunctionKey
|
|
7085
7147
|
});
|
|
7148
|
+
Object.defineProperty(wrappedFn, "_bitfabWrappedFn", { value: fn });
|
|
7086
7149
|
return wrappedFn;
|
|
7087
7150
|
}
|
|
7088
7151
|
/**
|
|
@@ -7245,6 +7308,9 @@ var Bitfab = class {
|
|
|
7245
7308
|
if (params.dbSnapshotRef) {
|
|
7246
7309
|
rawTrace.db_snapshot_ref = params.dbSnapshotRef;
|
|
7247
7310
|
}
|
|
7311
|
+
if (params.ingestionType) {
|
|
7312
|
+
rawTrace.ingestion_type = params.ingestionType;
|
|
7313
|
+
}
|
|
7248
7314
|
if (params.dbSnapshotUsage) {
|
|
7249
7315
|
rawTrace.db_snapshot_usage = {
|
|
7250
7316
|
neon_branch_id: params.dbSnapshotUsage.neonBranchId,
|
|
@@ -7391,6 +7457,68 @@ var Bitfab = class {
|
|
|
7391
7457
|
clearMockOverrides() {
|
|
7392
7458
|
this.mockOverrides.length = 0;
|
|
7393
7459
|
}
|
|
7460
|
+
/**
|
|
7461
|
+
* Write a replayable trace from a case, without running anything.
|
|
7462
|
+
*
|
|
7463
|
+
* Use this to turn a corpus you already hold (a Braintrust dataset, a
|
|
7464
|
+
* spreadsheet, hand-written cases) into traces that {@link replay} can
|
|
7465
|
+
* select. The recorded root span carries `input` as its input and `expected`
|
|
7466
|
+
* as its output, so replay reports each item against the value you expected
|
|
7467
|
+
* rather than against a previous run.
|
|
7468
|
+
*
|
|
7469
|
+
* A seeded trace has no child spans and no database pin, so replay mocking
|
|
7470
|
+
* has nothing recorded to substitute and `dbBranch` refuses it. Pass
|
|
7471
|
+
* `mockOverride` at replay time for calls that must not run.
|
|
7472
|
+
*
|
|
7473
|
+
* @returns The trace ID, usable with `replay({ traceIds: [...] })`.
|
|
7474
|
+
*/
|
|
7475
|
+
seedTrace(traceFunctionKey, options) {
|
|
7476
|
+
const { input } = options;
|
|
7477
|
+
const fn = options.fn?._bitfabWrappedFn ?? options.fn;
|
|
7478
|
+
if (fn && input.length < fn.length) {
|
|
7479
|
+
throw new BitfabError(
|
|
7480
|
+
`Seeded case supplies ${input.length} argument(s) but ${fn.name === "" ? "the function" : fn.name} requires ${fn.length}. Fix the case, or omit fn to seed it anyway.`
|
|
7481
|
+
);
|
|
7482
|
+
}
|
|
7483
|
+
const traceId = randomUuid();
|
|
7484
|
+
const startedAt = nowIsoTimestamp();
|
|
7485
|
+
activeTraceStates.set(traceId, {
|
|
7486
|
+
traceId,
|
|
7487
|
+
startedAt,
|
|
7488
|
+
contexts: [],
|
|
7489
|
+
ingestionType: "seeded",
|
|
7490
|
+
...options.sessionId !== void 0 && { sessionId: options.sessionId },
|
|
7491
|
+
...options.metadata !== void 0 && { metadata: options.metadata }
|
|
7492
|
+
});
|
|
7493
|
+
try {
|
|
7494
|
+
this.sendWrapperSpan({
|
|
7495
|
+
traceFunctionKey,
|
|
7496
|
+
spanName: options.spanName ?? traceFunctionKey,
|
|
7497
|
+
traceId,
|
|
7498
|
+
spanId: randomUuid(),
|
|
7499
|
+
parentSpanId: null,
|
|
7500
|
+
inputs: input,
|
|
7501
|
+
result: options.expected,
|
|
7502
|
+
startedAt,
|
|
7503
|
+
endedAt: startedAt,
|
|
7504
|
+
spanType: options.spanType ?? "agent",
|
|
7505
|
+
captureContent: true
|
|
7506
|
+
});
|
|
7507
|
+
this.sendTraceCompletion({
|
|
7508
|
+
traceFunctionKey,
|
|
7509
|
+
traceId,
|
|
7510
|
+
startedAt,
|
|
7511
|
+
endedAt: startedAt,
|
|
7512
|
+
sessionId: options.sessionId,
|
|
7513
|
+
metadata: options.metadata,
|
|
7514
|
+
contexts: [],
|
|
7515
|
+
ingestionType: "seeded"
|
|
7516
|
+
});
|
|
7517
|
+
} finally {
|
|
7518
|
+
activeTraceStates.delete(traceId);
|
|
7519
|
+
}
|
|
7520
|
+
return traceId;
|
|
7521
|
+
}
|
|
7394
7522
|
async replay(traceFunctionKey, fn, options) {
|
|
7395
7523
|
const wrappedKey = fn._bitfabTraceFunctionKey;
|
|
7396
7524
|
let replayFn = fn;
|
|
@@ -7651,6 +7779,37 @@ init_replay();
|
|
|
7651
7779
|
function defineReplayRegistry(registry) {
|
|
7652
7780
|
return registry;
|
|
7653
7781
|
}
|
|
7782
|
+
async function seedFromRegistry(registry, pipeline, cases) {
|
|
7783
|
+
const registration = registry[pipeline];
|
|
7784
|
+
if (registration === void 0) {
|
|
7785
|
+
throw new BitfabError(
|
|
7786
|
+
`Unknown pipeline '${pipeline}'. Registered: ${Object.keys(registry).join(", ")}`
|
|
7787
|
+
);
|
|
7788
|
+
}
|
|
7789
|
+
const traceFunctionKey = resolveTraceFunctionKey(registration);
|
|
7790
|
+
const traceIds = cases.map(
|
|
7791
|
+
(seedCase) => registration.client.seedTrace(traceFunctionKey, {
|
|
7792
|
+
input: seedCase.input,
|
|
7793
|
+
expected: seedCase.expected,
|
|
7794
|
+
fn: registration.fn,
|
|
7795
|
+
metadata: seedCase.metadata,
|
|
7796
|
+
sessionId: seedCase.sessionId
|
|
7797
|
+
})
|
|
7798
|
+
);
|
|
7799
|
+
const { flushTraces: flushTraces2 } = await Promise.resolve().then(() => (init_http(), http_exports));
|
|
7800
|
+
await flushTraces2(3e4);
|
|
7801
|
+
return { pipeline, traceFunctionKey, traceIds };
|
|
7802
|
+
}
|
|
7803
|
+
function resolveTraceFunctionKey(registration) {
|
|
7804
|
+
const wrappedKey = registration.fn._bitfabTraceFunctionKey;
|
|
7805
|
+
const key = registration.traceFunctionKey ?? wrappedKey;
|
|
7806
|
+
if (key === void 0) {
|
|
7807
|
+
throw new BitfabError(
|
|
7808
|
+
"Replay registry entry uses a plain function. Set traceFunctionKey to the key its production handler records."
|
|
7809
|
+
);
|
|
7810
|
+
}
|
|
7811
|
+
return key;
|
|
7812
|
+
}
|
|
7654
7813
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7655
7814
|
0 && (module.exports = {
|
|
7656
7815
|
BITFAB_PROGRESS_PREFIX,
|
|
@@ -7678,6 +7837,7 @@ function defineReplayRegistry(registry) {
|
|
|
7678
7837
|
getCurrentSpan,
|
|
7679
7838
|
getCurrentTrace,
|
|
7680
7839
|
reportReplayProgress,
|
|
7840
|
+
seedFromRegistry,
|
|
7681
7841
|
serializeReplayResult
|
|
7682
7842
|
});
|
|
7683
7843
|
//# sourceMappingURL=index.cjs.map
|