bitfab 0.36.1 → 0.36.3
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-HD4DRDRE.js → chunk-4CTDZMG5.js} +3 -3
- package/dist/{chunk-6ZBZBR5K.js → chunk-M2GISXGV.js} +166 -40
- package/dist/chunk-M2GISXGV.js.map +1 -0
- package/dist/index.cjs +175 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -6
- package/dist/index.d.ts +57 -6
- package/dist/index.js +10 -4
- package/dist/node.cjs +175 -43
- 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 +10 -4
- package/dist/node.js.map +1 -1
- package/dist/replay-ZH25RPKH.js +17 -0
- package/package.json +1 -1
- package/dist/chunk-6ZBZBR5K.js.map +0 -1
- package/dist/replay-ZR4KIZIB.js +0 -11
- /package/dist/{chunk-HD4DRDRE.js.map → chunk-4CTDZMG5.js.map} +0 -0
- /package/dist/{replay-ZR4KIZIB.js.map → replay-ZH25RPKH.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -51,7 +51,7 @@ var __version__;
|
|
|
51
51
|
var init_version_generated = __esm({
|
|
52
52
|
"src/version.generated.ts"() {
|
|
53
53
|
"use strict";
|
|
54
|
-
__version__ = "0.36.
|
|
54
|
+
__version__ = "0.36.3";
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
57
|
|
|
@@ -1530,9 +1530,11 @@ var init_http = __esm({
|
|
|
1530
1530
|
/**
|
|
1531
1531
|
* Fetch an external span by ID.
|
|
1532
1532
|
* Blocking GET request.
|
|
1533
|
+
* The replay view limits rawData to input/output serialization fields.
|
|
1533
1534
|
*/
|
|
1534
|
-
async getExternalSpan(spanId) {
|
|
1535
|
-
const
|
|
1535
|
+
async getExternalSpan(spanId, options) {
|
|
1536
|
+
const query = options?.view === "replay" ? "?view=replay" : "";
|
|
1537
|
+
const url = `${this.serviceUrl}/api/sdk/externalSpans/${spanId}${query}`;
|
|
1536
1538
|
const controller = new AbortController();
|
|
1537
1539
|
const timeoutId = setTimeout(() => controller.abort(), 3e4);
|
|
1538
1540
|
try {
|
|
@@ -1570,9 +1572,18 @@ var init_http = __esm({
|
|
|
1570
1572
|
* Pass `includeOutputs: false` for a payload-free tree (structure +
|
|
1571
1573
|
* `externalSpanId` only), so recorded outputs are fetched lazily per mocked
|
|
1572
1574
|
* span instead of all up front. Omit it (default eager) for `mock: "all"`.
|
|
1575
|
+
* Pass `includeRootOutput: false` when the root was already fetched.
|
|
1573
1576
|
*/
|
|
1574
1577
|
async getSpanTree(externalSpanId, options) {
|
|
1575
|
-
const
|
|
1578
|
+
const searchParams = new URLSearchParams();
|
|
1579
|
+
if (options?.includeOutputs === false) {
|
|
1580
|
+
searchParams.set("includeOutputs", "false");
|
|
1581
|
+
}
|
|
1582
|
+
if (options?.includeRootOutput === false) {
|
|
1583
|
+
searchParams.set("includeRootOutput", "false");
|
|
1584
|
+
}
|
|
1585
|
+
const encodedQuery = searchParams.toString();
|
|
1586
|
+
const query = encodedQuery ? `?${encodedQuery}` : "";
|
|
1576
1587
|
const url = `${this.serviceUrl}/api/sdk/replay/spanTree/${externalSpanId}${query}`;
|
|
1577
1588
|
const controller = new AbortController();
|
|
1578
1589
|
const timeoutId = setTimeout(() => controller.abort(), 3e4);
|
|
@@ -2051,8 +2062,11 @@ var init_codeChange = __esm({
|
|
|
2051
2062
|
var replay_exports = {};
|
|
2052
2063
|
__export(replay_exports, {
|
|
2053
2064
|
BITFAB_PROGRESS_PREFIX: () => BITFAB_PROGRESS_PREFIX,
|
|
2065
|
+
DbBranchReplayError: () => DbBranchReplayError,
|
|
2066
|
+
ReplayError: () => ReplayError,
|
|
2054
2067
|
replay: () => replay,
|
|
2055
|
-
reportReplayProgress: () => reportReplayProgress
|
|
2068
|
+
reportReplayProgress: () => reportReplayProgress,
|
|
2069
|
+
serializeReplayResult: () => serializeReplayResult
|
|
2056
2070
|
});
|
|
2057
2071
|
function dbBranchEnabled(dbBranch) {
|
|
2058
2072
|
return dbBranch !== void 0 && dbBranch !== false;
|
|
@@ -2075,11 +2089,59 @@ function reportReplayProgress(progress) {
|
|
|
2075
2089
|
return;
|
|
2076
2090
|
}
|
|
2077
2091
|
try {
|
|
2078
|
-
stderr.write(
|
|
2079
|
-
|
|
2092
|
+
stderr.write(
|
|
2093
|
+
`${BITFAB_PROGRESS_PREFIX}${JSON.stringify(progress, replayJsonReplacer)}
|
|
2094
|
+
`
|
|
2095
|
+
);
|
|
2080
2096
|
} catch {
|
|
2081
2097
|
}
|
|
2082
2098
|
}
|
|
2099
|
+
function errorMessage(error) {
|
|
2100
|
+
return error instanceof Error ? error.message : String(error);
|
|
2101
|
+
}
|
|
2102
|
+
function replayItemErrorMessage(error) {
|
|
2103
|
+
if (error instanceof DbBranchReplayError) {
|
|
2104
|
+
return `Replay requested a database branch for trace ${error.originalTraceId} but it could not be resolved (${error.code}): ${error.message}. The function was not run, because replaying it against the live database would produce a result that looks valid but did not use the historical data you asked for.`;
|
|
2105
|
+
}
|
|
2106
|
+
return errorMessage(error);
|
|
2107
|
+
}
|
|
2108
|
+
function replayJsonReplacer(_key, value) {
|
|
2109
|
+
if (value instanceof Error) {
|
|
2110
|
+
const serialized = {
|
|
2111
|
+
name: value.name,
|
|
2112
|
+
message: value.message,
|
|
2113
|
+
stack: value.stack
|
|
2114
|
+
};
|
|
2115
|
+
if (value instanceof DbBranchReplayError) {
|
|
2116
|
+
serialized.code = value.code;
|
|
2117
|
+
serialized.originalTraceId = value.originalTraceId;
|
|
2118
|
+
if (value.cause !== void 0) {
|
|
2119
|
+
serialized.cause = value.cause;
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
return serialized;
|
|
2123
|
+
}
|
|
2124
|
+
return value;
|
|
2125
|
+
}
|
|
2126
|
+
function serializeReplayResult(result) {
|
|
2127
|
+
return JSON.stringify(result, replayJsonReplacer, 2);
|
|
2128
|
+
}
|
|
2129
|
+
async function preserveReplayFailure(operation, items, testRunId, testRunUrl) {
|
|
2130
|
+
try {
|
|
2131
|
+
return await operation();
|
|
2132
|
+
} catch (cause) {
|
|
2133
|
+
if (cause instanceof ReplayError) {
|
|
2134
|
+
throw cause;
|
|
2135
|
+
}
|
|
2136
|
+
throw new ReplayError(
|
|
2137
|
+
errorMessage(cause),
|
|
2138
|
+
items,
|
|
2139
|
+
testRunId,
|
|
2140
|
+
testRunUrl,
|
|
2141
|
+
cause
|
|
2142
|
+
);
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2083
2145
|
function deserializeInputs(spanData) {
|
|
2084
2146
|
const inputMeta = spanData.input_meta;
|
|
2085
2147
|
const rawInput = spanData.input;
|
|
@@ -2137,25 +2199,41 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
2137
2199
|
let originalOutput;
|
|
2138
2200
|
let result;
|
|
2139
2201
|
let error = null;
|
|
2202
|
+
let traceError = null;
|
|
2203
|
+
let replayError = null;
|
|
2140
2204
|
const originalTraceId = serverItem.originalTraceId ?? serverItem.sourceTraceId;
|
|
2141
2205
|
const originalSpanId = serverItem.originalSpanId ?? serverItem.sourceSpanId;
|
|
2142
2206
|
try {
|
|
2143
2207
|
if (includeDbBranchLease && !lease && !leaseError) {
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2208
|
+
let resolved;
|
|
2209
|
+
try {
|
|
2210
|
+
resolved = await httpClient.resolveDbBranchLease(
|
|
2211
|
+
testRunId,
|
|
2212
|
+
originalTraceId,
|
|
2213
|
+
dbBranchSettings
|
|
2214
|
+
);
|
|
2215
|
+
} catch (cause) {
|
|
2216
|
+
throw new DbBranchReplayError(
|
|
2217
|
+
"lease_request_failed",
|
|
2218
|
+
`Bitfab could not request the database branch: ${errorMessage(cause)}`,
|
|
2219
|
+
originalTraceId,
|
|
2220
|
+
cause
|
|
2221
|
+
);
|
|
2222
|
+
}
|
|
2149
2223
|
lease = resolved.lease ?? void 0;
|
|
2150
2224
|
leaseError = resolved.leaseError ?? void 0;
|
|
2151
2225
|
dbSnapshotRef = resolved.dbSnapshotRef ?? dbSnapshotRef;
|
|
2152
2226
|
}
|
|
2153
2227
|
if (leaseError) {
|
|
2154
|
-
throw new
|
|
2155
|
-
|
|
2228
|
+
throw new DbBranchReplayError(
|
|
2229
|
+
leaseError.code,
|
|
2230
|
+
leaseError.message,
|
|
2231
|
+
originalTraceId
|
|
2156
2232
|
);
|
|
2157
2233
|
}
|
|
2158
|
-
const span = await httpClient.getExternalSpan(originalSpanId
|
|
2234
|
+
const span = await httpClient.getExternalSpan(originalSpanId, {
|
|
2235
|
+
view: "replay"
|
|
2236
|
+
});
|
|
2159
2237
|
const spanData = span.rawData?.span_data ?? {};
|
|
2160
2238
|
inputs = deserializeInputs(spanData);
|
|
2161
2239
|
originalOutput = deserializeOutput(spanData);
|
|
@@ -2175,7 +2253,8 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
2175
2253
|
if (needTree) {
|
|
2176
2254
|
try {
|
|
2177
2255
|
const treeResponse = await httpClient.getSpanTree(originalSpanId, {
|
|
2178
|
-
includeOutputs
|
|
2256
|
+
includeOutputs,
|
|
2257
|
+
includeRootOutput: false
|
|
2179
2258
|
});
|
|
2180
2259
|
if (treeResponse.root) {
|
|
2181
2260
|
mockTree = buildMockTree(treeResponse.root);
|
|
@@ -2197,7 +2276,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
2197
2276
|
const fetchSpanOutput = mockTree && !includeOutputs ? (externalSpanId) => {
|
|
2198
2277
|
let pending = outputCache.get(externalSpanId);
|
|
2199
2278
|
if (!pending) {
|
|
2200
|
-
pending = httpClient.getExternalSpan(externalSpanId).then(
|
|
2279
|
+
pending = httpClient.getExternalSpan(externalSpanId, { view: "replay" }).then(
|
|
2201
2280
|
(s) => deserializeOutput(
|
|
2202
2281
|
s.rawData?.span_data ?? {}
|
|
2203
2282
|
)
|
|
@@ -2206,25 +2285,31 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
2206
2285
|
}
|
|
2207
2286
|
return pending;
|
|
2208
2287
|
} : void 0;
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2288
|
+
try {
|
|
2289
|
+
const maybePromise = runWithReplayContext(
|
|
2290
|
+
{
|
|
2291
|
+
testRunId,
|
|
2292
|
+
traceId: replayedTraceId,
|
|
2293
|
+
inputSourceSpanId: span.id,
|
|
2294
|
+
inputSourceTraceId: span.externalTraceId,
|
|
2295
|
+
sourceBitfabTraceId: originalTraceId,
|
|
2296
|
+
mockTree,
|
|
2297
|
+
callCounters: mockTree ? /* @__PURE__ */ new Map() : void 0,
|
|
2298
|
+
mockStrategy,
|
|
2299
|
+
mockOverrides: hasOverrides ? resolvedOverrides : void 0,
|
|
2300
|
+
fetchSpanOutput,
|
|
2301
|
+
dbBranchLease: lease
|
|
2302
|
+
},
|
|
2303
|
+
() => fn(...inputs)
|
|
2304
|
+
);
|
|
2305
|
+
result = maybePromise instanceof Promise ? await maybePromise : maybePromise;
|
|
2306
|
+
} catch (e) {
|
|
2307
|
+
traceError = e;
|
|
2308
|
+
error = errorMessage(e);
|
|
2309
|
+
}
|
|
2226
2310
|
} catch (e) {
|
|
2227
|
-
|
|
2311
|
+
replayError = e;
|
|
2312
|
+
error = replayItemErrorMessage(e);
|
|
2228
2313
|
} finally {
|
|
2229
2314
|
if (lease) {
|
|
2230
2315
|
try {
|
|
@@ -2253,6 +2338,8 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
2253
2338
|
result,
|
|
2254
2339
|
originalOutput,
|
|
2255
2340
|
error,
|
|
2341
|
+
traceError,
|
|
2342
|
+
replayError,
|
|
2256
2343
|
durationMs: serverItem.durationMs ?? null,
|
|
2257
2344
|
// Filled in by replay() from the complete-replay response once the
|
|
2258
2345
|
// replay traces are persisted and their spans aggregated server-side.
|
|
@@ -2377,6 +2464,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2377
2464
|
);
|
|
2378
2465
|
const mockStrategy = options?.mock ?? "marked";
|
|
2379
2466
|
const maxConcurrency = options?.maxConcurrency ?? 10;
|
|
2467
|
+
const fullTestRunUrl = `${serviceUrl}${testRunUrl}`;
|
|
2380
2468
|
const resolvedOverrides = [
|
|
2381
2469
|
...normalizeMockOverrides(options?.mockOverride),
|
|
2382
2470
|
...registeredOverrides
|
|
@@ -2433,6 +2521,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2433
2521
|
result: item.result,
|
|
2434
2522
|
originalOutput: item.originalOutput,
|
|
2435
2523
|
error: item.error,
|
|
2524
|
+
traceError: item.traceError,
|
|
2525
|
+
replayError: item.replayError,
|
|
2436
2526
|
durationMs: item.durationMs,
|
|
2437
2527
|
tokens: item.tokens,
|
|
2438
2528
|
model: item.model,
|
|
@@ -2443,8 +2533,18 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2443
2533
|
}
|
|
2444
2534
|
} : void 0
|
|
2445
2535
|
);
|
|
2446
|
-
await
|
|
2447
|
-
|
|
2536
|
+
await preserveReplayFailure(
|
|
2537
|
+
() => waitForReplayPersistence(httpClient, testRunId, replayedTraceIds),
|
|
2538
|
+
resultItems,
|
|
2539
|
+
testRunId,
|
|
2540
|
+
fullTestRunUrl
|
|
2541
|
+
);
|
|
2542
|
+
const completeResult = await preserveReplayFailure(
|
|
2543
|
+
() => httpClient.completeReplay(testRunId),
|
|
2544
|
+
resultItems,
|
|
2545
|
+
testRunId,
|
|
2546
|
+
fullTestRunUrl
|
|
2547
|
+
);
|
|
2448
2548
|
const serverTraceIds = completeResult.traceIds;
|
|
2449
2549
|
const replayTokens = completeResult.tokens;
|
|
2450
2550
|
if (serverTraceIds !== void 0) {
|
|
@@ -2467,9 +2567,16 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2467
2567
|
}
|
|
2468
2568
|
if (completedCount > 0 && missing.length === completedCount) {
|
|
2469
2569
|
const serverCount = completeResult.traceCount !== void 0 ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.` : "";
|
|
2470
|
-
|
|
2570
|
+
const cause = new BitfabError(
|
|
2471
2571
|
`Replay completed but the server has no persisted trace for any of the ${completedCount} completed item(s) (testRunId ${testRunId}).${serverCount} Trace uploads were awaited, so either the uploads failed (check for "Bitfab: Failed to create" errors above) or the replayed function is not wrapped with withSpan.`
|
|
2472
2572
|
);
|
|
2573
|
+
throw new ReplayError(
|
|
2574
|
+
cause.message,
|
|
2575
|
+
resultItems,
|
|
2576
|
+
testRunId,
|
|
2577
|
+
fullTestRunUrl,
|
|
2578
|
+
cause
|
|
2579
|
+
);
|
|
2473
2580
|
}
|
|
2474
2581
|
if (missing.length > 0) {
|
|
2475
2582
|
try {
|
|
@@ -2483,7 +2590,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2483
2590
|
const result = {
|
|
2484
2591
|
items: resultItems,
|
|
2485
2592
|
testRunId,
|
|
2486
|
-
testRunUrl:
|
|
2593
|
+
testRunUrl: fullTestRunUrl
|
|
2487
2594
|
};
|
|
2488
2595
|
await writeReplayResultFile(result);
|
|
2489
2596
|
try {
|
|
@@ -2511,7 +2618,7 @@ async function writeReplayResultFile(result) {
|
|
|
2511
2618
|
import("fs/promises")
|
|
2512
2619
|
]);
|
|
2513
2620
|
await mkdir(dirname(resultPath), { recursive: true });
|
|
2514
|
-
await writeFile(resultPath, `${
|
|
2621
|
+
await writeFile(resultPath, `${serializeReplayResult(result)}
|
|
2515
2622
|
`);
|
|
2516
2623
|
} catch (err) {
|
|
2517
2624
|
try {
|
|
@@ -2522,7 +2629,7 @@ async function writeReplayResultFile(result) {
|
|
|
2522
2629
|
}
|
|
2523
2630
|
}
|
|
2524
2631
|
}
|
|
2525
|
-
var REPLAY_PERSISTENCE_TIMEOUT_MS, BITFAB_PROGRESS_PREFIX;
|
|
2632
|
+
var REPLAY_PERSISTENCE_TIMEOUT_MS, BITFAB_PROGRESS_PREFIX, ReplayError, DbBranchReplayError;
|
|
2526
2633
|
var init_replay = __esm({
|
|
2527
2634
|
"src/replay.ts"() {
|
|
2528
2635
|
"use strict";
|
|
@@ -2537,6 +2644,25 @@ var init_replay = __esm({
|
|
|
2537
2644
|
init_unrefTimer();
|
|
2538
2645
|
REPLAY_PERSISTENCE_TIMEOUT_MS = 3e4;
|
|
2539
2646
|
BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
|
|
2647
|
+
ReplayError = class extends BitfabError {
|
|
2648
|
+
constructor(message, items, testRunId, testRunUrl, cause) {
|
|
2649
|
+
super(message, testRunUrl);
|
|
2650
|
+
this.items = items;
|
|
2651
|
+
this.testRunId = testRunId;
|
|
2652
|
+
this.testRunUrl = testRunUrl;
|
|
2653
|
+
this.cause = cause;
|
|
2654
|
+
this.name = "ReplayError";
|
|
2655
|
+
}
|
|
2656
|
+
};
|
|
2657
|
+
DbBranchReplayError = class extends BitfabError {
|
|
2658
|
+
constructor(code, message, originalTraceId, cause) {
|
|
2659
|
+
super(message);
|
|
2660
|
+
this.code = code;
|
|
2661
|
+
this.originalTraceId = originalTraceId;
|
|
2662
|
+
this.cause = cause;
|
|
2663
|
+
this.name = "DbBranchReplayError";
|
|
2664
|
+
}
|
|
2665
|
+
};
|
|
2540
2666
|
}
|
|
2541
2667
|
});
|
|
2542
2668
|
|
|
@@ -2554,7 +2680,9 @@ __export(index_exports, {
|
|
|
2554
2680
|
BitfabOpenAITracingProcessor: () => BitfabOpenAITracingProcessor,
|
|
2555
2681
|
BitfabVercelAiHandler: () => BitfabVercelAiHandler,
|
|
2556
2682
|
DEFAULT_SERVICE_URL: () => DEFAULT_SERVICE_URL,
|
|
2683
|
+
DbBranchReplayError: () => DbBranchReplayError,
|
|
2557
2684
|
HttpClient: () => HttpClient,
|
|
2685
|
+
ReplayError: () => ReplayError,
|
|
2558
2686
|
SUPPORTED_PROVIDERS: () => SUPPORTED_PROVIDERS,
|
|
2559
2687
|
__version__: () => __version__,
|
|
2560
2688
|
finalizers: () => finalizers,
|
|
@@ -2562,7 +2690,8 @@ __export(index_exports, {
|
|
|
2562
2690
|
getCurrentReplayBranch: () => getCurrentReplayBranch,
|
|
2563
2691
|
getCurrentSpan: () => getCurrentSpan,
|
|
2564
2692
|
getCurrentTrace: () => getCurrentTrace,
|
|
2565
|
-
reportReplayProgress: () => reportReplayProgress
|
|
2693
|
+
reportReplayProgress: () => reportReplayProgress,
|
|
2694
|
+
serializeReplayResult: () => serializeReplayResult
|
|
2566
2695
|
});
|
|
2567
2696
|
module.exports = __toCommonJS(index_exports);
|
|
2568
2697
|
|
|
@@ -6143,7 +6272,9 @@ init_replay();
|
|
|
6143
6272
|
BitfabOpenAITracingProcessor,
|
|
6144
6273
|
BitfabVercelAiHandler,
|
|
6145
6274
|
DEFAULT_SERVICE_URL,
|
|
6275
|
+
DbBranchReplayError,
|
|
6146
6276
|
HttpClient,
|
|
6277
|
+
ReplayError,
|
|
6147
6278
|
SUPPORTED_PROVIDERS,
|
|
6148
6279
|
__version__,
|
|
6149
6280
|
finalizers,
|
|
@@ -6151,6 +6282,7 @@ init_replay();
|
|
|
6151
6282
|
getCurrentReplayBranch,
|
|
6152
6283
|
getCurrentSpan,
|
|
6153
6284
|
getCurrentTrace,
|
|
6154
|
-
reportReplayProgress
|
|
6285
|
+
reportReplayProgress,
|
|
6286
|
+
serializeReplayResult
|
|
6155
6287
|
});
|
|
6156
6288
|
//# sourceMappingURL=index.cjs.map
|