@bitfab/sdk 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
|
@@ -42,7 +42,7 @@ var __version__;
|
|
|
42
42
|
var init_version_generated = __esm({
|
|
43
43
|
"src/version.generated.ts"() {
|
|
44
44
|
"use strict";
|
|
45
|
-
__version__ = "0.36.
|
|
45
|
+
__version__ = "0.36.3";
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
48
|
|
|
@@ -1521,9 +1521,11 @@ var init_http = __esm({
|
|
|
1521
1521
|
/**
|
|
1522
1522
|
* Fetch an external span by ID.
|
|
1523
1523
|
* Blocking GET request.
|
|
1524
|
+
* The replay view limits rawData to input/output serialization fields.
|
|
1524
1525
|
*/
|
|
1525
|
-
async getExternalSpan(spanId) {
|
|
1526
|
-
const
|
|
1526
|
+
async getExternalSpan(spanId, options) {
|
|
1527
|
+
const query = options?.view === "replay" ? "?view=replay" : "";
|
|
1528
|
+
const url = `${this.serviceUrl}/api/sdk/externalSpans/${spanId}${query}`;
|
|
1527
1529
|
const controller = new AbortController();
|
|
1528
1530
|
const timeoutId = setTimeout(() => controller.abort(), 3e4);
|
|
1529
1531
|
try {
|
|
@@ -1561,9 +1563,18 @@ var init_http = __esm({
|
|
|
1561
1563
|
* Pass `includeOutputs: false` for a payload-free tree (structure +
|
|
1562
1564
|
* `externalSpanId` only), so recorded outputs are fetched lazily per mocked
|
|
1563
1565
|
* span instead of all up front. Omit it (default eager) for `mock: "all"`.
|
|
1566
|
+
* Pass `includeRootOutput: false` when the root was already fetched.
|
|
1564
1567
|
*/
|
|
1565
1568
|
async getSpanTree(externalSpanId, options) {
|
|
1566
|
-
const
|
|
1569
|
+
const searchParams = new URLSearchParams();
|
|
1570
|
+
if (options?.includeOutputs === false) {
|
|
1571
|
+
searchParams.set("includeOutputs", "false");
|
|
1572
|
+
}
|
|
1573
|
+
if (options?.includeRootOutput === false) {
|
|
1574
|
+
searchParams.set("includeRootOutput", "false");
|
|
1575
|
+
}
|
|
1576
|
+
const encodedQuery = searchParams.toString();
|
|
1577
|
+
const query = encodedQuery ? `?${encodedQuery}` : "";
|
|
1567
1578
|
const url = `${this.serviceUrl}/api/sdk/replay/spanTree/${externalSpanId}${query}`;
|
|
1568
1579
|
const controller = new AbortController();
|
|
1569
1580
|
const timeoutId = setTimeout(() => controller.abort(), 3e4);
|
|
@@ -2042,8 +2053,11 @@ var init_codeChange = __esm({
|
|
|
2042
2053
|
var replay_exports = {};
|
|
2043
2054
|
__export(replay_exports, {
|
|
2044
2055
|
BITFAB_PROGRESS_PREFIX: () => BITFAB_PROGRESS_PREFIX,
|
|
2056
|
+
DbBranchReplayError: () => DbBranchReplayError,
|
|
2057
|
+
ReplayError: () => ReplayError,
|
|
2045
2058
|
replay: () => replay,
|
|
2046
|
-
reportReplayProgress: () => reportReplayProgress
|
|
2059
|
+
reportReplayProgress: () => reportReplayProgress,
|
|
2060
|
+
serializeReplayResult: () => serializeReplayResult
|
|
2047
2061
|
});
|
|
2048
2062
|
function dbBranchEnabled(dbBranch) {
|
|
2049
2063
|
return dbBranch !== void 0 && dbBranch !== false;
|
|
@@ -2066,11 +2080,59 @@ function reportReplayProgress(progress) {
|
|
|
2066
2080
|
return;
|
|
2067
2081
|
}
|
|
2068
2082
|
try {
|
|
2069
|
-
stderr.write(
|
|
2070
|
-
|
|
2083
|
+
stderr.write(
|
|
2084
|
+
`${BITFAB_PROGRESS_PREFIX}${JSON.stringify(progress, replayJsonReplacer)}
|
|
2085
|
+
`
|
|
2086
|
+
);
|
|
2071
2087
|
} catch {
|
|
2072
2088
|
}
|
|
2073
2089
|
}
|
|
2090
|
+
function errorMessage(error) {
|
|
2091
|
+
return error instanceof Error ? error.message : String(error);
|
|
2092
|
+
}
|
|
2093
|
+
function replayItemErrorMessage(error) {
|
|
2094
|
+
if (error instanceof DbBranchReplayError) {
|
|
2095
|
+
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.`;
|
|
2096
|
+
}
|
|
2097
|
+
return errorMessage(error);
|
|
2098
|
+
}
|
|
2099
|
+
function replayJsonReplacer(_key, value) {
|
|
2100
|
+
if (value instanceof Error) {
|
|
2101
|
+
const serialized = {
|
|
2102
|
+
name: value.name,
|
|
2103
|
+
message: value.message,
|
|
2104
|
+
stack: value.stack
|
|
2105
|
+
};
|
|
2106
|
+
if (value instanceof DbBranchReplayError) {
|
|
2107
|
+
serialized.code = value.code;
|
|
2108
|
+
serialized.originalTraceId = value.originalTraceId;
|
|
2109
|
+
if (value.cause !== void 0) {
|
|
2110
|
+
serialized.cause = value.cause;
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
return serialized;
|
|
2114
|
+
}
|
|
2115
|
+
return value;
|
|
2116
|
+
}
|
|
2117
|
+
function serializeReplayResult(result) {
|
|
2118
|
+
return JSON.stringify(result, replayJsonReplacer, 2);
|
|
2119
|
+
}
|
|
2120
|
+
async function preserveReplayFailure(operation, items, testRunId, testRunUrl) {
|
|
2121
|
+
try {
|
|
2122
|
+
return await operation();
|
|
2123
|
+
} catch (cause) {
|
|
2124
|
+
if (cause instanceof ReplayError) {
|
|
2125
|
+
throw cause;
|
|
2126
|
+
}
|
|
2127
|
+
throw new ReplayError(
|
|
2128
|
+
errorMessage(cause),
|
|
2129
|
+
items,
|
|
2130
|
+
testRunId,
|
|
2131
|
+
testRunUrl,
|
|
2132
|
+
cause
|
|
2133
|
+
);
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2074
2136
|
function deserializeInputs(spanData) {
|
|
2075
2137
|
const inputMeta = spanData.input_meta;
|
|
2076
2138
|
const rawInput = spanData.input;
|
|
@@ -2128,25 +2190,41 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
2128
2190
|
let originalOutput;
|
|
2129
2191
|
let result;
|
|
2130
2192
|
let error = null;
|
|
2193
|
+
let traceError = null;
|
|
2194
|
+
let replayError = null;
|
|
2131
2195
|
const originalTraceId = serverItem.originalTraceId ?? serverItem.sourceTraceId;
|
|
2132
2196
|
const originalSpanId = serverItem.originalSpanId ?? serverItem.sourceSpanId;
|
|
2133
2197
|
try {
|
|
2134
2198
|
if (includeDbBranchLease && !lease && !leaseError) {
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2199
|
+
let resolved;
|
|
2200
|
+
try {
|
|
2201
|
+
resolved = await httpClient.resolveDbBranchLease(
|
|
2202
|
+
testRunId,
|
|
2203
|
+
originalTraceId,
|
|
2204
|
+
dbBranchSettings
|
|
2205
|
+
);
|
|
2206
|
+
} catch (cause) {
|
|
2207
|
+
throw new DbBranchReplayError(
|
|
2208
|
+
"lease_request_failed",
|
|
2209
|
+
`Bitfab could not request the database branch: ${errorMessage(cause)}`,
|
|
2210
|
+
originalTraceId,
|
|
2211
|
+
cause
|
|
2212
|
+
);
|
|
2213
|
+
}
|
|
2140
2214
|
lease = resolved.lease ?? void 0;
|
|
2141
2215
|
leaseError = resolved.leaseError ?? void 0;
|
|
2142
2216
|
dbSnapshotRef = resolved.dbSnapshotRef ?? dbSnapshotRef;
|
|
2143
2217
|
}
|
|
2144
2218
|
if (leaseError) {
|
|
2145
|
-
throw new
|
|
2146
|
-
|
|
2219
|
+
throw new DbBranchReplayError(
|
|
2220
|
+
leaseError.code,
|
|
2221
|
+
leaseError.message,
|
|
2222
|
+
originalTraceId
|
|
2147
2223
|
);
|
|
2148
2224
|
}
|
|
2149
|
-
const span = await httpClient.getExternalSpan(originalSpanId
|
|
2225
|
+
const span = await httpClient.getExternalSpan(originalSpanId, {
|
|
2226
|
+
view: "replay"
|
|
2227
|
+
});
|
|
2150
2228
|
const spanData = span.rawData?.span_data ?? {};
|
|
2151
2229
|
inputs = deserializeInputs(spanData);
|
|
2152
2230
|
originalOutput = deserializeOutput(spanData);
|
|
@@ -2166,7 +2244,8 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
2166
2244
|
if (needTree) {
|
|
2167
2245
|
try {
|
|
2168
2246
|
const treeResponse = await httpClient.getSpanTree(originalSpanId, {
|
|
2169
|
-
includeOutputs
|
|
2247
|
+
includeOutputs,
|
|
2248
|
+
includeRootOutput: false
|
|
2170
2249
|
});
|
|
2171
2250
|
if (treeResponse.root) {
|
|
2172
2251
|
mockTree = buildMockTree(treeResponse.root);
|
|
@@ -2188,7 +2267,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
2188
2267
|
const fetchSpanOutput = mockTree && !includeOutputs ? (externalSpanId) => {
|
|
2189
2268
|
let pending = outputCache.get(externalSpanId);
|
|
2190
2269
|
if (!pending) {
|
|
2191
|
-
pending = httpClient.getExternalSpan(externalSpanId).then(
|
|
2270
|
+
pending = httpClient.getExternalSpan(externalSpanId, { view: "replay" }).then(
|
|
2192
2271
|
(s) => deserializeOutput(
|
|
2193
2272
|
s.rawData?.span_data ?? {}
|
|
2194
2273
|
)
|
|
@@ -2197,25 +2276,31 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
2197
2276
|
}
|
|
2198
2277
|
return pending;
|
|
2199
2278
|
} : void 0;
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2279
|
+
try {
|
|
2280
|
+
const maybePromise = runWithReplayContext(
|
|
2281
|
+
{
|
|
2282
|
+
testRunId,
|
|
2283
|
+
traceId: replayedTraceId,
|
|
2284
|
+
inputSourceSpanId: span.id,
|
|
2285
|
+
inputSourceTraceId: span.externalTraceId,
|
|
2286
|
+
sourceBitfabTraceId: originalTraceId,
|
|
2287
|
+
mockTree,
|
|
2288
|
+
callCounters: mockTree ? /* @__PURE__ */ new Map() : void 0,
|
|
2289
|
+
mockStrategy,
|
|
2290
|
+
mockOverrides: hasOverrides ? resolvedOverrides : void 0,
|
|
2291
|
+
fetchSpanOutput,
|
|
2292
|
+
dbBranchLease: lease
|
|
2293
|
+
},
|
|
2294
|
+
() => fn(...inputs)
|
|
2295
|
+
);
|
|
2296
|
+
result = maybePromise instanceof Promise ? await maybePromise : maybePromise;
|
|
2297
|
+
} catch (e) {
|
|
2298
|
+
traceError = e;
|
|
2299
|
+
error = errorMessage(e);
|
|
2300
|
+
}
|
|
2217
2301
|
} catch (e) {
|
|
2218
|
-
|
|
2302
|
+
replayError = e;
|
|
2303
|
+
error = replayItemErrorMessage(e);
|
|
2219
2304
|
} finally {
|
|
2220
2305
|
if (lease) {
|
|
2221
2306
|
try {
|
|
@@ -2244,6 +2329,8 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
2244
2329
|
result,
|
|
2245
2330
|
originalOutput,
|
|
2246
2331
|
error,
|
|
2332
|
+
traceError,
|
|
2333
|
+
replayError,
|
|
2247
2334
|
durationMs: serverItem.durationMs ?? null,
|
|
2248
2335
|
// Filled in by replay() from the complete-replay response once the
|
|
2249
2336
|
// replay traces are persisted and their spans aggregated server-side.
|
|
@@ -2368,6 +2455,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2368
2455
|
);
|
|
2369
2456
|
const mockStrategy = options?.mock ?? "marked";
|
|
2370
2457
|
const maxConcurrency = options?.maxConcurrency ?? 10;
|
|
2458
|
+
const fullTestRunUrl = `${serviceUrl}${testRunUrl}`;
|
|
2371
2459
|
const resolvedOverrides = [
|
|
2372
2460
|
...normalizeMockOverrides(options?.mockOverride),
|
|
2373
2461
|
...registeredOverrides
|
|
@@ -2424,6 +2512,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2424
2512
|
result: item.result,
|
|
2425
2513
|
originalOutput: item.originalOutput,
|
|
2426
2514
|
error: item.error,
|
|
2515
|
+
traceError: item.traceError,
|
|
2516
|
+
replayError: item.replayError,
|
|
2427
2517
|
durationMs: item.durationMs,
|
|
2428
2518
|
tokens: item.tokens,
|
|
2429
2519
|
model: item.model,
|
|
@@ -2434,8 +2524,18 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2434
2524
|
}
|
|
2435
2525
|
} : void 0
|
|
2436
2526
|
);
|
|
2437
|
-
await
|
|
2438
|
-
|
|
2527
|
+
await preserveReplayFailure(
|
|
2528
|
+
() => waitForReplayPersistence(httpClient, testRunId, replayedTraceIds),
|
|
2529
|
+
resultItems,
|
|
2530
|
+
testRunId,
|
|
2531
|
+
fullTestRunUrl
|
|
2532
|
+
);
|
|
2533
|
+
const completeResult = await preserveReplayFailure(
|
|
2534
|
+
() => httpClient.completeReplay(testRunId),
|
|
2535
|
+
resultItems,
|
|
2536
|
+
testRunId,
|
|
2537
|
+
fullTestRunUrl
|
|
2538
|
+
);
|
|
2439
2539
|
const serverTraceIds = completeResult.traceIds;
|
|
2440
2540
|
const replayTokens = completeResult.tokens;
|
|
2441
2541
|
if (serverTraceIds !== void 0) {
|
|
@@ -2458,9 +2558,16 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2458
2558
|
}
|
|
2459
2559
|
if (completedCount > 0 && missing.length === completedCount) {
|
|
2460
2560
|
const serverCount = completeResult.traceCount !== void 0 ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.` : "";
|
|
2461
|
-
|
|
2561
|
+
const cause = new BitfabError(
|
|
2462
2562
|
`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.`
|
|
2463
2563
|
);
|
|
2564
|
+
throw new ReplayError(
|
|
2565
|
+
cause.message,
|
|
2566
|
+
resultItems,
|
|
2567
|
+
testRunId,
|
|
2568
|
+
fullTestRunUrl,
|
|
2569
|
+
cause
|
|
2570
|
+
);
|
|
2464
2571
|
}
|
|
2465
2572
|
if (missing.length > 0) {
|
|
2466
2573
|
try {
|
|
@@ -2474,7 +2581,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
2474
2581
|
const result = {
|
|
2475
2582
|
items: resultItems,
|
|
2476
2583
|
testRunId,
|
|
2477
|
-
testRunUrl:
|
|
2584
|
+
testRunUrl: fullTestRunUrl
|
|
2478
2585
|
};
|
|
2479
2586
|
await writeReplayResultFile(result);
|
|
2480
2587
|
try {
|
|
@@ -2502,7 +2609,7 @@ async function writeReplayResultFile(result) {
|
|
|
2502
2609
|
import("fs/promises")
|
|
2503
2610
|
]);
|
|
2504
2611
|
await mkdir(dirname(resultPath), { recursive: true });
|
|
2505
|
-
await writeFile(resultPath, `${
|
|
2612
|
+
await writeFile(resultPath, `${serializeReplayResult(result)}
|
|
2506
2613
|
`);
|
|
2507
2614
|
} catch (err) {
|
|
2508
2615
|
try {
|
|
@@ -2513,7 +2620,7 @@ async function writeReplayResultFile(result) {
|
|
|
2513
2620
|
}
|
|
2514
2621
|
}
|
|
2515
2622
|
}
|
|
2516
|
-
var REPLAY_PERSISTENCE_TIMEOUT_MS, BITFAB_PROGRESS_PREFIX;
|
|
2623
|
+
var REPLAY_PERSISTENCE_TIMEOUT_MS, BITFAB_PROGRESS_PREFIX, ReplayError, DbBranchReplayError;
|
|
2517
2624
|
var init_replay = __esm({
|
|
2518
2625
|
"src/replay.ts"() {
|
|
2519
2626
|
"use strict";
|
|
@@ -2528,6 +2635,25 @@ var init_replay = __esm({
|
|
|
2528
2635
|
init_unrefTimer();
|
|
2529
2636
|
REPLAY_PERSISTENCE_TIMEOUT_MS = 3e4;
|
|
2530
2637
|
BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
|
|
2638
|
+
ReplayError = class extends BitfabError {
|
|
2639
|
+
constructor(message, items, testRunId, testRunUrl, cause) {
|
|
2640
|
+
super(message, testRunUrl);
|
|
2641
|
+
this.items = items;
|
|
2642
|
+
this.testRunId = testRunId;
|
|
2643
|
+
this.testRunUrl = testRunUrl;
|
|
2644
|
+
this.cause = cause;
|
|
2645
|
+
this.name = "ReplayError";
|
|
2646
|
+
}
|
|
2647
|
+
};
|
|
2648
|
+
DbBranchReplayError = class extends BitfabError {
|
|
2649
|
+
constructor(code, message, originalTraceId, cause) {
|
|
2650
|
+
super(message);
|
|
2651
|
+
this.code = code;
|
|
2652
|
+
this.originalTraceId = originalTraceId;
|
|
2653
|
+
this.cause = cause;
|
|
2654
|
+
this.name = "DbBranchReplayError";
|
|
2655
|
+
}
|
|
2656
|
+
};
|
|
2531
2657
|
}
|
|
2532
2658
|
});
|
|
2533
2659
|
|
|
@@ -2545,7 +2671,9 @@ __export(index_exports, {
|
|
|
2545
2671
|
BitfabOpenAITracingProcessor: () => BitfabOpenAITracingProcessor,
|
|
2546
2672
|
BitfabVercelAiHandler: () => BitfabVercelAiHandler,
|
|
2547
2673
|
DEFAULT_SERVICE_URL: () => DEFAULT_SERVICE_URL,
|
|
2674
|
+
DbBranchReplayError: () => DbBranchReplayError,
|
|
2548
2675
|
HttpClient: () => HttpClient,
|
|
2676
|
+
ReplayError: () => ReplayError,
|
|
2549
2677
|
SUPPORTED_PROVIDERS: () => SUPPORTED_PROVIDERS,
|
|
2550
2678
|
__version__: () => __version__,
|
|
2551
2679
|
finalizers: () => finalizers,
|
|
@@ -2553,7 +2681,8 @@ __export(index_exports, {
|
|
|
2553
2681
|
getCurrentReplayBranch: () => getCurrentReplayBranch,
|
|
2554
2682
|
getCurrentSpan: () => getCurrentSpan,
|
|
2555
2683
|
getCurrentTrace: () => getCurrentTrace,
|
|
2556
|
-
reportReplayProgress: () => reportReplayProgress
|
|
2684
|
+
reportReplayProgress: () => reportReplayProgress,
|
|
2685
|
+
serializeReplayResult: () => serializeReplayResult
|
|
2557
2686
|
});
|
|
2558
2687
|
module.exports = __toCommonJS(index_exports);
|
|
2559
2688
|
|
|
@@ -6134,7 +6263,9 @@ init_replay();
|
|
|
6134
6263
|
BitfabOpenAITracingProcessor,
|
|
6135
6264
|
BitfabVercelAiHandler,
|
|
6136
6265
|
DEFAULT_SERVICE_URL,
|
|
6266
|
+
DbBranchReplayError,
|
|
6137
6267
|
HttpClient,
|
|
6268
|
+
ReplayError,
|
|
6138
6269
|
SUPPORTED_PROVIDERS,
|
|
6139
6270
|
__version__,
|
|
6140
6271
|
finalizers,
|
|
@@ -6142,6 +6273,7 @@ init_replay();
|
|
|
6142
6273
|
getCurrentReplayBranch,
|
|
6143
6274
|
getCurrentSpan,
|
|
6144
6275
|
getCurrentTrace,
|
|
6145
|
-
reportReplayProgress
|
|
6276
|
+
reportReplayProgress,
|
|
6277
|
+
serializeReplayResult
|
|
6146
6278
|
});
|
|
6147
6279
|
//# sourceMappingURL=index.cjs.map
|