@bitfab/sdk 0.33.7 → 0.34.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/README.md +19 -0
- package/dist/chunk-4J36FZ4K.js +2299 -0
- package/dist/chunk-4J36FZ4K.js.map +1 -0
- package/dist/{chunk-DZJ5K75J.js → chunk-ESKBRHVG.js} +87 -604
- package/dist/chunk-ESKBRHVG.js.map +1 -0
- package/dist/index.cjs +2297 -1365
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +374 -28
- package/dist/index.d.ts +374 -28
- package/dist/index.js +5 -5
- package/dist/node.cjs +2287 -1355
- package/dist/node.cjs.map +1 -1
- package/dist/node.js +5 -5
- package/dist/{replay-SRQI4QMY.js → replay-QFNYP7EY.js} +2 -2
- package/package.json +6 -1
- package/dist/chunk-DPV6PBWE.js +0 -916
- package/dist/chunk-DPV6PBWE.js.map +0 -1
- package/dist/chunk-DZJ5K75J.js.map +0 -1
- /package/dist/{replay-SRQI4QMY.js.map → replay-QFNYP7EY.js.map} +0 -0
package/dist/chunk-DPV6PBWE.js
DELETED
|
@@ -1,916 +0,0 @@
|
|
|
1
|
-
var __typeError = (msg) => {
|
|
2
|
-
throw TypeError(msg);
|
|
3
|
-
};
|
|
4
|
-
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
-
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
|
-
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
|
-
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
8
|
-
|
|
9
|
-
// src/codeChange.ts
|
|
10
|
-
var MAX_FILES = 60;
|
|
11
|
-
var MAX_FILE_BYTES = 5e5;
|
|
12
|
-
var MAX_TOTAL_BYTES = 2e6;
|
|
13
|
-
var TRUNK_CANDIDATES = [
|
|
14
|
-
"origin/HEAD",
|
|
15
|
-
"origin/main",
|
|
16
|
-
"origin/master",
|
|
17
|
-
"main",
|
|
18
|
-
"master"
|
|
19
|
-
];
|
|
20
|
-
var NUL = String.fromCharCode(0);
|
|
21
|
-
async function resolveAutoCodeChange(label) {
|
|
22
|
-
if (typeof process === "undefined") {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
if (process.env?.BITFAB_DISABLE_CODE_CHANGE_CAPTURE) {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
const fromEnv = await readCodeChangeFile();
|
|
29
|
-
if (fromEnv) {
|
|
30
|
-
return fromEnv;
|
|
31
|
-
}
|
|
32
|
-
return captureCodeChangeFromGit(process.cwd?.() ?? ".", label);
|
|
33
|
-
}
|
|
34
|
-
async function readCodeChangeFile() {
|
|
35
|
-
const path = process.env?.BITFAB_CODE_CHANGE_PATH;
|
|
36
|
-
if (!path) {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
try {
|
|
40
|
-
const { readFile } = await import("fs/promises");
|
|
41
|
-
const parsed = JSON.parse(await readFile(path, "utf8"));
|
|
42
|
-
const files = Array.isArray(parsed?.files) && parsed.files.every(
|
|
43
|
-
(f) => typeof f === "object" && f !== null && !Array.isArray(f)
|
|
44
|
-
) ? parsed.files : void 0;
|
|
45
|
-
const description = typeof parsed?.description === "string" ? parsed.description : void 0;
|
|
46
|
-
if (!files && description === void 0) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
return { description, files };
|
|
50
|
-
} catch {
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
async function captureCodeChangeFromGit(cwd, label) {
|
|
55
|
-
let execFile;
|
|
56
|
-
let readFile;
|
|
57
|
-
try {
|
|
58
|
-
;
|
|
59
|
-
({ execFile } = await import("child_process"));
|
|
60
|
-
({ readFile } = await import("fs/promises"));
|
|
61
|
-
} catch {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
const git = (dir, args) => new Promise((resolve) => {
|
|
65
|
-
execFile(
|
|
66
|
-
"git",
|
|
67
|
-
args,
|
|
68
|
-
// 30s timeout so a hung git (e.g. a network-touching ref op) can't
|
|
69
|
-
// block the whole replay indefinitely.
|
|
70
|
-
{ cwd: dir, maxBuffer: 64 * 1024 * 1024, timeout: 3e4 },
|
|
71
|
-
(err, stdout) => resolve(err ? null : stdout)
|
|
72
|
-
);
|
|
73
|
-
});
|
|
74
|
-
try {
|
|
75
|
-
const root = (await git(cwd, ["rev-parse", "--show-toplevel"]))?.trim();
|
|
76
|
-
if (!root) {
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
const resolved = await resolveBase(git, root);
|
|
80
|
-
if (!resolved) {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
const { base, fromTrunk } = resolved;
|
|
84
|
-
const blobBytes = async (ref, path) => {
|
|
85
|
-
const out = await git(root, ["cat-file", "-s", `${ref}:${path}`]);
|
|
86
|
-
const n = out ? Number.parseInt(out.trim(), 10) : Number.NaN;
|
|
87
|
-
return Number.isFinite(n) ? n : 0;
|
|
88
|
-
};
|
|
89
|
-
const workingBytes = async (path) => {
|
|
90
|
-
try {
|
|
91
|
-
const { stat } = await import("fs/promises");
|
|
92
|
-
const { join } = await import("path");
|
|
93
|
-
return (await stat(join(root, path))).size;
|
|
94
|
-
} catch {
|
|
95
|
-
return 0;
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
const tracked = await git(root, [
|
|
99
|
-
"diff",
|
|
100
|
-
"--name-status",
|
|
101
|
-
"--no-renames",
|
|
102
|
-
"-z",
|
|
103
|
-
base,
|
|
104
|
-
"--",
|
|
105
|
-
":!.bitfab"
|
|
106
|
-
]);
|
|
107
|
-
const untracked = await git(root, [
|
|
108
|
-
"ls-files",
|
|
109
|
-
"--others",
|
|
110
|
-
"--exclude-standard",
|
|
111
|
-
"-z",
|
|
112
|
-
"--",
|
|
113
|
-
":!.bitfab"
|
|
114
|
-
]);
|
|
115
|
-
const entries = [
|
|
116
|
-
...parseNameStatusZ(tracked ?? ""),
|
|
117
|
-
...(untracked ?? "").split(NUL).filter((p) => p.length > 0).map((path) => ({ status: "A", path }))
|
|
118
|
-
];
|
|
119
|
-
if (entries.length === 0) {
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
const files = [];
|
|
123
|
-
let totalBytes = 0;
|
|
124
|
-
for (const { status, path } of entries) {
|
|
125
|
-
if (files.length >= MAX_FILES) {
|
|
126
|
-
break;
|
|
127
|
-
}
|
|
128
|
-
const beforeBytes = status === "A" ? 0 : await blobBytes(base, path);
|
|
129
|
-
const afterBytes = status === "D" ? 0 : await workingBytes(path);
|
|
130
|
-
if (beforeBytes > MAX_FILE_BYTES || afterBytes > MAX_FILE_BYTES) {
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
const before = (status === "A" ? "" : await git(root, ["show", `${base}:${path}`]) ?? "").replace(/\r\n/g, "\n");
|
|
134
|
-
const after = (status === "D" ? "" : await readWorkingFile(readFile, root, path)).replace(/\r\n/g, "\n");
|
|
135
|
-
if (before === after) {
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
const size = Buffer.byteLength(before, "utf8") + Buffer.byteLength(after, "utf8");
|
|
139
|
-
if (totalBytes + size > MAX_TOTAL_BYTES || looksBinary(before) || looksBinary(after)) {
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
totalBytes += size;
|
|
143
|
-
files.push({ path, before, after });
|
|
144
|
-
}
|
|
145
|
-
if (files.length === 0) {
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
const subject = (await git(root, ["log", "-1", "--format=%s", "HEAD"]))?.trim();
|
|
149
|
-
const fileWord = files.length === 1 ? "file" : "files";
|
|
150
|
-
const head = label?.trim() || subject || "Working-tree change";
|
|
151
|
-
const against = fromTrunk ? "vs trunk" : "uncommitted (vs HEAD)";
|
|
152
|
-
return {
|
|
153
|
-
description: `${head} (${files.length} ${fileWord} changed ${against})`,
|
|
154
|
-
files
|
|
155
|
-
};
|
|
156
|
-
} catch {
|
|
157
|
-
return null;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
async function resolveBase(git, root) {
|
|
161
|
-
const forced = process.env?.BITFAB_CODE_CHANGE_BASE;
|
|
162
|
-
if (forced && await refExists(git, root, forced)) {
|
|
163
|
-
const base = (await git(root, ["merge-base", "HEAD", forced]))?.trim() || (await git(root, ["rev-parse", "--verify", forced]))?.trim() || null;
|
|
164
|
-
return base ? { base, fromTrunk: true } : null;
|
|
165
|
-
}
|
|
166
|
-
for (const candidate of TRUNK_CANDIDATES) {
|
|
167
|
-
if (!await refExists(git, root, candidate)) {
|
|
168
|
-
continue;
|
|
169
|
-
}
|
|
170
|
-
const mb = (await git(root, ["merge-base", "HEAD", candidate]))?.trim();
|
|
171
|
-
if (mb) {
|
|
172
|
-
return { base: mb, fromTrunk: true };
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return await refExists(git, root, "HEAD") ? { base: "HEAD", fromTrunk: false } : null;
|
|
176
|
-
}
|
|
177
|
-
async function refExists(git, root, ref) {
|
|
178
|
-
return await git(root, ["rev-parse", "--verify", `${ref}^{object}`]) !== null;
|
|
179
|
-
}
|
|
180
|
-
async function readWorkingFile(readFile, root, path) {
|
|
181
|
-
try {
|
|
182
|
-
const { join } = await import("path");
|
|
183
|
-
return await readFile(join(root, path), "utf8");
|
|
184
|
-
} catch {
|
|
185
|
-
return "";
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
function parseNameStatusZ(raw) {
|
|
189
|
-
const parts = raw.split(NUL).filter((p) => p.length > 0);
|
|
190
|
-
const out = [];
|
|
191
|
-
for (let i = 0; i + 1 < parts.length; i += 2) {
|
|
192
|
-
out.push({ status: parts[i].charAt(0), path: parts[i + 1] });
|
|
193
|
-
}
|
|
194
|
-
return out;
|
|
195
|
-
}
|
|
196
|
-
function looksBinary(s) {
|
|
197
|
-
return s.slice(0, 8e3).includes(NUL);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// src/errors.ts
|
|
201
|
-
var BitfabError = class extends Error {
|
|
202
|
-
constructor(message, url) {
|
|
203
|
-
super(message);
|
|
204
|
-
this.url = url;
|
|
205
|
-
this.name = "BitfabError";
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
// src/mockOverride.ts
|
|
210
|
-
function resolveMockValue(value, ctx) {
|
|
211
|
-
return typeof value === "function" ? value(ctx) : value;
|
|
212
|
-
}
|
|
213
|
-
function normalizeMockOverrides(mockOverride) {
|
|
214
|
-
if (mockOverride === void 0) {
|
|
215
|
-
return [];
|
|
216
|
-
}
|
|
217
|
-
return Array.isArray(mockOverride) ? mockOverride : [mockOverride];
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// src/warnOnce.ts
|
|
221
|
-
var warned = /* @__PURE__ */ new Set();
|
|
222
|
-
function warnOnce(key, message) {
|
|
223
|
-
if (warned.has(key)) {
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
warned.add(key);
|
|
227
|
-
try {
|
|
228
|
-
console.warn(`[bitfab] ${message}`);
|
|
229
|
-
} catch {
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// src/randomUuid.ts
|
|
234
|
-
function randomUuid() {
|
|
235
|
-
const globalCrypto = globalThis.crypto;
|
|
236
|
-
if (typeof globalCrypto?.randomUUID === "function") {
|
|
237
|
-
try {
|
|
238
|
-
return globalCrypto.randomUUID();
|
|
239
|
-
} catch {
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
warnOnce(
|
|
243
|
-
"crypto-unavailable",
|
|
244
|
-
"global crypto.randomUUID is unavailable; using a non-cryptographic fallback for trace/span ids. Tracing works normally (ids are correlation-only, not security-sensitive)."
|
|
245
|
-
);
|
|
246
|
-
return fallbackUuidV4();
|
|
247
|
-
}
|
|
248
|
-
function fallbackUuidV4() {
|
|
249
|
-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
|
|
250
|
-
const rand = Math.random() * 16 | 0;
|
|
251
|
-
const value = char === "x" ? rand : rand & 3 | 8;
|
|
252
|
-
return value.toString(16);
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// src/asyncStorage.ts
|
|
257
|
-
var AsyncLocalStorageClass = null;
|
|
258
|
-
var initDone = false;
|
|
259
|
-
function registerAsyncLocalStorageClass(cls) {
|
|
260
|
-
if (!AsyncLocalStorageClass) {
|
|
261
|
-
AsyncLocalStorageClass = cls;
|
|
262
|
-
}
|
|
263
|
-
initDone = true;
|
|
264
|
-
}
|
|
265
|
-
function assertAsyncStorageRegistered() {
|
|
266
|
-
if (!AsyncLocalStorageClass) {
|
|
267
|
-
console.warn(
|
|
268
|
-
"Bitfab: AsyncLocalStorage not available - nested span context will not propagate."
|
|
269
|
-
);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
var asyncStorageReady = (typeof process !== "undefined" && process.versions?.node ? (
|
|
273
|
-
// The join trick hides "node:async_hooks" from static analysis so
|
|
274
|
-
// bundlers that ban Node.js built-ins don't fail at build time.
|
|
275
|
-
// webpackIgnore tells webpack/turbopack to emit a native import()
|
|
276
|
-
// so Node.js can resolve the module at runtime.
|
|
277
|
-
import(
|
|
278
|
-
/* webpackIgnore: true */
|
|
279
|
-
["node", "async_hooks"].join(":")
|
|
280
|
-
).then(
|
|
281
|
-
(mod) => {
|
|
282
|
-
registerAsyncLocalStorageClass(mod.AsyncLocalStorage);
|
|
283
|
-
}
|
|
284
|
-
).catch(() => {
|
|
285
|
-
})
|
|
286
|
-
) : Promise.resolve()).then(() => {
|
|
287
|
-
initDone = true;
|
|
288
|
-
});
|
|
289
|
-
function isAsyncStorageInitDone() {
|
|
290
|
-
return initDone;
|
|
291
|
-
}
|
|
292
|
-
function createAsyncLocalStorage() {
|
|
293
|
-
return AsyncLocalStorageClass ? new AsyncLocalStorageClass() : null;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// src/replayContext.ts
|
|
297
|
-
var replayContextStorage = null;
|
|
298
|
-
var REPLAY_CONTEXT_STORAGE_SYMBOL = /* @__PURE__ */ Symbol.for("bitfab.replayContextStorage");
|
|
299
|
-
var replayContextReady = asyncStorageReady.then(() => {
|
|
300
|
-
const shared = globalThis;
|
|
301
|
-
const existing = shared[REPLAY_CONTEXT_STORAGE_SYMBOL];
|
|
302
|
-
if (existing) {
|
|
303
|
-
replayContextStorage = existing;
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
const created = createAsyncLocalStorage();
|
|
307
|
-
if (created) {
|
|
308
|
-
shared[REPLAY_CONTEXT_STORAGE_SYMBOL] = created;
|
|
309
|
-
replayContextStorage = created;
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
function getReplayContext() {
|
|
313
|
-
return replayContextStorage?.getStore() ?? null;
|
|
314
|
-
}
|
|
315
|
-
function runWithReplayContext(ctx, fn) {
|
|
316
|
-
if (replayContextStorage) {
|
|
317
|
-
return replayContextStorage.run(ctx, fn);
|
|
318
|
-
}
|
|
319
|
-
return fn();
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// src/serialize.ts
|
|
323
|
-
import superjson from "superjson";
|
|
324
|
-
var MAX_SERIALIZED_BYTES = 512e3;
|
|
325
|
-
var MAX_FRAMEWORK_SERIALIZED_BYTES = 2e6;
|
|
326
|
-
function describeValue(value) {
|
|
327
|
-
try {
|
|
328
|
-
const ctorName = value?.constructor?.name;
|
|
329
|
-
if (ctorName && ctorName !== "Object") {
|
|
330
|
-
return ctorName;
|
|
331
|
-
}
|
|
332
|
-
} catch {
|
|
333
|
-
}
|
|
334
|
-
return typeof value;
|
|
335
|
-
}
|
|
336
|
-
function unserializableStub(value, reason) {
|
|
337
|
-
warnOnce(
|
|
338
|
-
`serialize:${reason.replace(/\d+/g, "N")}`,
|
|
339
|
-
`a value could not be fully serialized for a span (${reason}); it was replaced with a placeholder. The span still ships, but its captured input/output is incomplete.`
|
|
340
|
-
);
|
|
341
|
-
let summary;
|
|
342
|
-
try {
|
|
343
|
-
summary = `<unserializable: ${describeValue(value)} (${reason})>`;
|
|
344
|
-
} catch {
|
|
345
|
-
summary = `<unserializable (${reason})>`;
|
|
346
|
-
}
|
|
347
|
-
return { json: summary };
|
|
348
|
-
}
|
|
349
|
-
function serializeValue(value) {
|
|
350
|
-
try {
|
|
351
|
-
const { json, meta } = superjson.serialize(value);
|
|
352
|
-
let size;
|
|
353
|
-
try {
|
|
354
|
-
size = JSON.stringify(json).length;
|
|
355
|
-
} catch {
|
|
356
|
-
return unserializableStub(value, "stringify_failed_after_superjson");
|
|
357
|
-
}
|
|
358
|
-
if (size > MAX_SERIALIZED_BYTES) {
|
|
359
|
-
return unserializableStub(value, `too_large_${size}_bytes`);
|
|
360
|
-
}
|
|
361
|
-
return meta ? { json, meta } : { json };
|
|
362
|
-
} catch {
|
|
363
|
-
try {
|
|
364
|
-
return { json: JSON.parse(JSON.stringify(value)) };
|
|
365
|
-
} catch {
|
|
366
|
-
return unserializableStub(value, "json_stringify_failed");
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
function deserializeValue(serialized) {
|
|
371
|
-
if (serialized.meta === void 0) {
|
|
372
|
-
return serialized.json;
|
|
373
|
-
}
|
|
374
|
-
return superjson.deserialize({
|
|
375
|
-
json: serialized.json,
|
|
376
|
-
meta: serialized.meta
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
var MAX_SAFE_DEPTH = 6;
|
|
380
|
-
function toJsonSafe(value) {
|
|
381
|
-
return toJsonSafeReport(value).safe;
|
|
382
|
-
}
|
|
383
|
-
function toJsonSafeReport(value) {
|
|
384
|
-
const dropped = [];
|
|
385
|
-
const safe = toJsonSafeInner(value, 0, /* @__PURE__ */ new WeakSet(), dropped);
|
|
386
|
-
try {
|
|
387
|
-
const size = JSON.stringify(safe)?.length ?? 0;
|
|
388
|
-
if (size > MAX_FRAMEWORK_SERIALIZED_BYTES) {
|
|
389
|
-
warnOnce(
|
|
390
|
-
"toJsonSafe:too_large",
|
|
391
|
-
`a framework payload exceeded ${MAX_FRAMEWORK_SERIALIZED_BYTES} bytes and was replaced with a placeholder so the span still ships. The captured state for this span is incomplete.`
|
|
392
|
-
);
|
|
393
|
-
return {
|
|
394
|
-
safe: `<unserializable: too_large_${size}_bytes>`,
|
|
395
|
-
dropped: [...dropped, `too_large_${size}_bytes`]
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
} catch {
|
|
399
|
-
}
|
|
400
|
-
return { safe, dropped };
|
|
401
|
-
}
|
|
402
|
-
function toJsonSafeInner(value, depth, seen, dropped) {
|
|
403
|
-
if (value === null || value === void 0) {
|
|
404
|
-
return value;
|
|
405
|
-
}
|
|
406
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
407
|
-
return value;
|
|
408
|
-
}
|
|
409
|
-
const className = value?.constructor?.name ?? typeof value;
|
|
410
|
-
if (depth > MAX_SAFE_DEPTH) {
|
|
411
|
-
dropped.push(className);
|
|
412
|
-
return `<${className}>`;
|
|
413
|
-
}
|
|
414
|
-
if (typeof value !== "object") {
|
|
415
|
-
if (typeof value === "function" || typeof value === "symbol") {
|
|
416
|
-
dropped.push(className);
|
|
417
|
-
}
|
|
418
|
-
try {
|
|
419
|
-
return String(value);
|
|
420
|
-
} catch {
|
|
421
|
-
dropped.push(className);
|
|
422
|
-
return `<${className}>`;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
if (seen.has(value)) {
|
|
426
|
-
dropped.push(className);
|
|
427
|
-
return `<cycle ${className}>`;
|
|
428
|
-
}
|
|
429
|
-
seen.add(value);
|
|
430
|
-
let result;
|
|
431
|
-
if (Array.isArray(value)) {
|
|
432
|
-
result = value.map(
|
|
433
|
-
(item) => toJsonSafeInner(item, depth + 1, seen, dropped)
|
|
434
|
-
);
|
|
435
|
-
} else if (typeof value.toJSON === "function") {
|
|
436
|
-
try {
|
|
437
|
-
result = toJsonSafeInner(
|
|
438
|
-
value.toJSON(),
|
|
439
|
-
depth + 1,
|
|
440
|
-
seen,
|
|
441
|
-
dropped
|
|
442
|
-
);
|
|
443
|
-
} catch {
|
|
444
|
-
dropped.push(className);
|
|
445
|
-
result = `<${className}>`;
|
|
446
|
-
}
|
|
447
|
-
} else {
|
|
448
|
-
try {
|
|
449
|
-
const obj = {};
|
|
450
|
-
for (const [k, v] of Object.entries(value)) {
|
|
451
|
-
if (!k.startsWith("_")) {
|
|
452
|
-
obj[k] = toJsonSafeInner(v, depth + 1, seen, dropped);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
result = obj;
|
|
456
|
-
} catch {
|
|
457
|
-
dropped.push(className);
|
|
458
|
-
result = `<${className}>`;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
seen.delete(value);
|
|
462
|
-
return result;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// src/replay.ts
|
|
466
|
-
function dbBranchEnabled(dbBranch) {
|
|
467
|
-
return dbBranch !== void 0 && dbBranch !== false;
|
|
468
|
-
}
|
|
469
|
-
function resolveDbBranchSettings(dbBranch) {
|
|
470
|
-
if (!dbBranch || dbBranch === true) {
|
|
471
|
-
return void 0;
|
|
472
|
-
}
|
|
473
|
-
const { minCu, maxCu, warmupSql } = dbBranch;
|
|
474
|
-
const settings = {
|
|
475
|
-
...minCu === void 0 ? {} : { minCu },
|
|
476
|
-
...maxCu === void 0 ? {} : { maxCu },
|
|
477
|
-
...warmupSql === void 0 ? {} : { warmupSql }
|
|
478
|
-
};
|
|
479
|
-
return Object.keys(settings).length === 0 ? void 0 : settings;
|
|
480
|
-
}
|
|
481
|
-
var BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
|
|
482
|
-
function reportReplayProgress(progress) {
|
|
483
|
-
const stderr = typeof process !== "undefined" ? process.stderr : void 0;
|
|
484
|
-
if (!stderr) {
|
|
485
|
-
return;
|
|
486
|
-
}
|
|
487
|
-
try {
|
|
488
|
-
stderr.write(`${BITFAB_PROGRESS_PREFIX}${JSON.stringify(progress)}
|
|
489
|
-
`);
|
|
490
|
-
} catch {
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
function deserializeInputs(spanData) {
|
|
494
|
-
const inputMeta = spanData.input_meta;
|
|
495
|
-
const rawInput = spanData.input;
|
|
496
|
-
if (inputMeta !== void 0 && inputMeta !== null) {
|
|
497
|
-
const deserialized = deserializeValue({ json: rawInput, meta: inputMeta });
|
|
498
|
-
if (Array.isArray(deserialized)) {
|
|
499
|
-
return deserialized;
|
|
500
|
-
}
|
|
501
|
-
return deserialized !== void 0 && deserialized !== null ? [deserialized] : [];
|
|
502
|
-
}
|
|
503
|
-
if (Array.isArray(rawInput)) {
|
|
504
|
-
return rawInput;
|
|
505
|
-
}
|
|
506
|
-
return rawInput !== void 0 && rawInput !== null ? [rawInput] : [];
|
|
507
|
-
}
|
|
508
|
-
function deserializeOutput(spanData) {
|
|
509
|
-
const outputMeta = spanData.output_meta;
|
|
510
|
-
const rawOutput = spanData.output;
|
|
511
|
-
if (outputMeta !== void 0 && outputMeta !== null) {
|
|
512
|
-
return deserializeValue({ json: rawOutput, meta: outputMeta });
|
|
513
|
-
}
|
|
514
|
-
return rawOutput;
|
|
515
|
-
}
|
|
516
|
-
function buildMockTree(rootNode) {
|
|
517
|
-
const spans = /* @__PURE__ */ new Map();
|
|
518
|
-
const counters = /* @__PURE__ */ new Map();
|
|
519
|
-
function walk(node) {
|
|
520
|
-
const key = node.traceFunctionKey;
|
|
521
|
-
if (key) {
|
|
522
|
-
const name = node.spanName || key;
|
|
523
|
-
const counterKey = `${key}:${name}`;
|
|
524
|
-
const index = counters.get(counterKey) ?? 0;
|
|
525
|
-
counters.set(counterKey, index + 1);
|
|
526
|
-
spans.set(`${counterKey}:${index}`, {
|
|
527
|
-
sourceSpanId: node.sourceSpanId,
|
|
528
|
-
externalSpanId: node.externalSpanId,
|
|
529
|
-
output: node.output,
|
|
530
|
-
outputMeta: node.outputMeta
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
for (const child of node.children) {
|
|
534
|
-
walk(child);
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
for (const child of rootNode.children) {
|
|
538
|
-
walk(child);
|
|
539
|
-
}
|
|
540
|
-
return { spans };
|
|
541
|
-
}
|
|
542
|
-
async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy, resolvedOverrides, replayedTraceId, includeDbBranchLease, dbBranchSettings, adaptInputs) {
|
|
543
|
-
let lease = includeDbBranchLease ? serverItem.dbBranchLease : void 0;
|
|
544
|
-
let leaseError = includeDbBranchLease ? serverItem.dbBranchLeaseError : void 0;
|
|
545
|
-
let dbSnapshotRef = serverItem.dbSnapshotRef;
|
|
546
|
-
let inputs = [];
|
|
547
|
-
let originalOutput;
|
|
548
|
-
let result;
|
|
549
|
-
let error = null;
|
|
550
|
-
const pendingPersistence = [];
|
|
551
|
-
const originalTraceId = serverItem.originalTraceId ?? serverItem.sourceTraceId;
|
|
552
|
-
const originalSpanId = serverItem.originalSpanId ?? serverItem.sourceSpanId;
|
|
553
|
-
try {
|
|
554
|
-
if (includeDbBranchLease && !lease && !leaseError) {
|
|
555
|
-
const resolved = await httpClient.resolveDbBranchLease(
|
|
556
|
-
testRunId,
|
|
557
|
-
originalTraceId,
|
|
558
|
-
dbBranchSettings
|
|
559
|
-
);
|
|
560
|
-
lease = resolved.lease ?? void 0;
|
|
561
|
-
leaseError = resolved.leaseError ?? void 0;
|
|
562
|
-
dbSnapshotRef = resolved.dbSnapshotRef ?? dbSnapshotRef;
|
|
563
|
-
}
|
|
564
|
-
if (leaseError) {
|
|
565
|
-
throw new BitfabError(
|
|
566
|
-
`Replay requested a database branch for trace ${originalTraceId} but it could not be resolved (${leaseError.code}): ${leaseError.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.`
|
|
567
|
-
);
|
|
568
|
-
}
|
|
569
|
-
const span = await httpClient.getExternalSpan(originalSpanId);
|
|
570
|
-
const spanData = span.rawData?.span_data ?? {};
|
|
571
|
-
inputs = deserializeInputs(spanData);
|
|
572
|
-
originalOutput = deserializeOutput(spanData);
|
|
573
|
-
if (adaptInputs) {
|
|
574
|
-
inputs = adaptInputs(inputs, {
|
|
575
|
-
originalTraceId,
|
|
576
|
-
originalSpanId,
|
|
577
|
-
// Deprecated aliases for originalTraceId/originalSpanId.
|
|
578
|
-
sourceTraceId: originalTraceId,
|
|
579
|
-
sourceSpanId: originalSpanId
|
|
580
|
-
});
|
|
581
|
-
}
|
|
582
|
-
const hasOverrides = resolvedOverrides.length > 0;
|
|
583
|
-
const needTree = mockStrategy === "all" || mockStrategy === "marked" || hasOverrides;
|
|
584
|
-
const includeOutputs = mockStrategy === "all";
|
|
585
|
-
let mockTree;
|
|
586
|
-
if (needTree) {
|
|
587
|
-
try {
|
|
588
|
-
const treeResponse = await httpClient.getSpanTree(originalSpanId, {
|
|
589
|
-
includeOutputs
|
|
590
|
-
});
|
|
591
|
-
if (treeResponse.root) {
|
|
592
|
-
mockTree = buildMockTree(treeResponse.root);
|
|
593
|
-
} else if (mockStrategy === "all" || hasOverrides) {
|
|
594
|
-
throw new BitfabError(
|
|
595
|
-
`Replay mock strategy "${mockStrategy}"${hasOverrides ? " with overrides" : ""} requires a span tree root for original span ${originalSpanId}.`
|
|
596
|
-
);
|
|
597
|
-
} else {
|
|
598
|
-
mockTree = void 0;
|
|
599
|
-
}
|
|
600
|
-
} catch (e) {
|
|
601
|
-
if (mockStrategy === "all" || hasOverrides) {
|
|
602
|
-
throw e;
|
|
603
|
-
}
|
|
604
|
-
mockTree = void 0;
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
const outputCache = /* @__PURE__ */ new Map();
|
|
608
|
-
const fetchSpanOutput = mockTree && !includeOutputs ? (externalSpanId) => {
|
|
609
|
-
let pending = outputCache.get(externalSpanId);
|
|
610
|
-
if (!pending) {
|
|
611
|
-
pending = httpClient.getExternalSpan(externalSpanId).then(
|
|
612
|
-
(s) => deserializeOutput(
|
|
613
|
-
s.rawData?.span_data ?? {}
|
|
614
|
-
)
|
|
615
|
-
);
|
|
616
|
-
outputCache.set(externalSpanId, pending);
|
|
617
|
-
}
|
|
618
|
-
return pending;
|
|
619
|
-
} : void 0;
|
|
620
|
-
const maybePromise = runWithReplayContext(
|
|
621
|
-
{
|
|
622
|
-
testRunId,
|
|
623
|
-
traceId: replayedTraceId,
|
|
624
|
-
inputSourceSpanId: span.id,
|
|
625
|
-
inputSourceTraceId: span.externalTraceId,
|
|
626
|
-
sourceBitfabTraceId: originalTraceId,
|
|
627
|
-
mockTree,
|
|
628
|
-
callCounters: mockTree ? /* @__PURE__ */ new Map() : void 0,
|
|
629
|
-
mockStrategy,
|
|
630
|
-
mockOverrides: hasOverrides ? resolvedOverrides : void 0,
|
|
631
|
-
fetchSpanOutput,
|
|
632
|
-
dbBranchLease: lease,
|
|
633
|
-
pendingPersistence
|
|
634
|
-
},
|
|
635
|
-
() => fn(...inputs)
|
|
636
|
-
);
|
|
637
|
-
result = maybePromise instanceof Promise ? await maybePromise : maybePromise;
|
|
638
|
-
} catch (e) {
|
|
639
|
-
error = e instanceof Error ? e.message : String(e);
|
|
640
|
-
} finally {
|
|
641
|
-
await Promise.allSettled(pendingPersistence);
|
|
642
|
-
if (lease) {
|
|
643
|
-
try {
|
|
644
|
-
await httpClient.releaseDbBranchLease(lease.neonBranchId);
|
|
645
|
-
} catch (e) {
|
|
646
|
-
try {
|
|
647
|
-
console.warn(
|
|
648
|
-
`Bitfab: failed to release DB branch ${lease.neonBranchId} (TTL janitor will catch it): ${e instanceof Error ? e.message : String(e)}`
|
|
649
|
-
);
|
|
650
|
-
} catch {
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
return {
|
|
656
|
-
// Written in by replay() from the complete-replay response once the server
|
|
657
|
-
// has minted this replay trace's row. Null until then: the client-side
|
|
658
|
-
// correlation id (replayedTraceId) is never surfaced as the item's traceId.
|
|
659
|
-
traceId: null,
|
|
660
|
-
originalTraceId,
|
|
661
|
-
originalSpanId,
|
|
662
|
-
// Deprecated aliases for originalTraceId/originalSpanId.
|
|
663
|
-
sourceTraceId: originalTraceId,
|
|
664
|
-
sourceSpanId: originalSpanId,
|
|
665
|
-
input: inputs,
|
|
666
|
-
result,
|
|
667
|
-
originalOutput,
|
|
668
|
-
error,
|
|
669
|
-
durationMs: serverItem.durationMs ?? null,
|
|
670
|
-
// Filled in by replay() from the complete-replay response once the
|
|
671
|
-
// replay traces are persisted and their spans aggregated server-side.
|
|
672
|
-
// Null here (and on older servers) means "replay tokens not known".
|
|
673
|
-
tokens: null,
|
|
674
|
-
model: serverItem.model ?? null,
|
|
675
|
-
dbSnapshotRef: dbSnapshotRef ?? null
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
async function mapWithConcurrency(tasks, maxConcurrency, onSettled) {
|
|
679
|
-
const results = new Array(tasks.length);
|
|
680
|
-
let nextIndex = 0;
|
|
681
|
-
async function worker() {
|
|
682
|
-
while (nextIndex < tasks.length) {
|
|
683
|
-
const index = nextIndex++;
|
|
684
|
-
const result = await tasks[index]();
|
|
685
|
-
results[index] = result;
|
|
686
|
-
onSettled?.(result, index);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
const workers = Array.from(
|
|
690
|
-
{ length: Math.min(maxConcurrency, tasks.length) },
|
|
691
|
-
() => worker()
|
|
692
|
-
);
|
|
693
|
-
await Promise.all(workers);
|
|
694
|
-
return results;
|
|
695
|
-
}
|
|
696
|
-
async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, registeredOverrides = []) {
|
|
697
|
-
if (options?.traceIds !== void 0) {
|
|
698
|
-
if (options.traceIds.length === 0) {
|
|
699
|
-
throw new BitfabError("traceIds must contain at least one trace ID.");
|
|
700
|
-
}
|
|
701
|
-
if (options.traceIds.length > 100) {
|
|
702
|
-
throw new BitfabError(
|
|
703
|
-
`traceIds supports at most 100 trace IDs per replay (got ${options.traceIds.length}).`
|
|
704
|
-
);
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
if (options?.limit !== void 0 && options?.traceIds !== void 0) {
|
|
708
|
-
try {
|
|
709
|
-
console.warn(
|
|
710
|
-
"Bitfab: limit is ignored when traceIds is passed: the explicit trace ID list already determines how many traces replay."
|
|
711
|
-
);
|
|
712
|
-
} catch {
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
await replayContextReady;
|
|
716
|
-
let codeChangeDescription = options?.codeChangeDescription;
|
|
717
|
-
let codeChangeFiles = options?.codeChangeFiles;
|
|
718
|
-
if (codeChangeFiles === void 0) {
|
|
719
|
-
const captured = await resolveAutoCodeChange(options?.name);
|
|
720
|
-
if (captured) {
|
|
721
|
-
codeChangeFiles = captured.files;
|
|
722
|
-
if (codeChangeDescription === void 0) {
|
|
723
|
-
codeChangeDescription = captured.description;
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
const {
|
|
728
|
-
testRunId,
|
|
729
|
-
testRunUrl,
|
|
730
|
-
items: serverItems
|
|
731
|
-
} = await httpClient.startReplay(
|
|
732
|
-
traceFunctionKey,
|
|
733
|
-
// limit is meaningless with explicit traceIds (the ID list determines
|
|
734
|
-
// the count), so it's omitted from the request entirely.
|
|
735
|
-
options?.traceIds ? void 0 : options?.limit ?? 5,
|
|
736
|
-
options?.traceIds,
|
|
737
|
-
options?.name,
|
|
738
|
-
codeChangeDescription,
|
|
739
|
-
codeChangeFiles,
|
|
740
|
-
dbBranchEnabled(options?.dbBranch),
|
|
741
|
-
// includeDbBranchLease
|
|
742
|
-
options?.experimentGroupId,
|
|
743
|
-
options?.datasetId,
|
|
744
|
-
options?.graderIds,
|
|
745
|
-
resolveDbBranchSettings(options?.dbBranch)
|
|
746
|
-
);
|
|
747
|
-
const mockStrategy = options?.mock ?? "marked";
|
|
748
|
-
const maxConcurrency = options?.maxConcurrency ?? 10;
|
|
749
|
-
const resolvedOverrides = [
|
|
750
|
-
...normalizeMockOverrides(options?.mockOverride),
|
|
751
|
-
...registeredOverrides
|
|
752
|
-
];
|
|
753
|
-
const replayedTraceIds = serverItems.map(() => randomUuid());
|
|
754
|
-
const tasks = serverItems.map(
|
|
755
|
-
(serverItem, index) => () => processItem(
|
|
756
|
-
httpClient,
|
|
757
|
-
serverItem,
|
|
758
|
-
fn,
|
|
759
|
-
testRunId,
|
|
760
|
-
mockStrategy,
|
|
761
|
-
resolvedOverrides,
|
|
762
|
-
replayedTraceIds[index],
|
|
763
|
-
dbBranchEnabled(options?.dbBranch),
|
|
764
|
-
resolveDbBranchSettings(options?.dbBranch),
|
|
765
|
-
options?.adaptInputs
|
|
766
|
-
)
|
|
767
|
-
);
|
|
768
|
-
const total = tasks.length;
|
|
769
|
-
let completed = 0;
|
|
770
|
-
let succeeded = 0;
|
|
771
|
-
let errored = 0;
|
|
772
|
-
const resultItems = await mapWithConcurrency(
|
|
773
|
-
tasks,
|
|
774
|
-
maxConcurrency,
|
|
775
|
-
options?.onProgress ? (item) => {
|
|
776
|
-
completed += 1;
|
|
777
|
-
if (item.error === null) {
|
|
778
|
-
succeeded += 1;
|
|
779
|
-
} else {
|
|
780
|
-
errored += 1;
|
|
781
|
-
}
|
|
782
|
-
try {
|
|
783
|
-
options?.onProgress?.({
|
|
784
|
-
testRunId,
|
|
785
|
-
completed,
|
|
786
|
-
total,
|
|
787
|
-
succeeded,
|
|
788
|
-
errored,
|
|
789
|
-
item: {
|
|
790
|
-
// The server replay trace id isn't known until completeReplay
|
|
791
|
-
// runs (below), so it can't be reported mid-run and we never
|
|
792
|
-
// emit the client-side placeholder. originalTraceId (the
|
|
793
|
-
// historical trace) is known now and is what a UI keys on to
|
|
794
|
-
// identify what just settled.
|
|
795
|
-
traceId: null,
|
|
796
|
-
originalTraceId: item.originalTraceId ?? null,
|
|
797
|
-
originalSpanId: item.originalSpanId ?? null,
|
|
798
|
-
// Deprecated aliases for originalTraceId/originalSpanId.
|
|
799
|
-
sourceTraceId: item.originalTraceId ?? null,
|
|
800
|
-
sourceSpanId: item.originalSpanId ?? null,
|
|
801
|
-
input: item.input,
|
|
802
|
-
result: item.result,
|
|
803
|
-
originalOutput: item.originalOutput,
|
|
804
|
-
error: item.error,
|
|
805
|
-
durationMs: item.durationMs,
|
|
806
|
-
tokens: item.tokens,
|
|
807
|
-
model: item.model,
|
|
808
|
-
dbSnapshotRef: item.dbSnapshotRef
|
|
809
|
-
}
|
|
810
|
-
});
|
|
811
|
-
} catch {
|
|
812
|
-
}
|
|
813
|
-
} : void 0
|
|
814
|
-
);
|
|
815
|
-
const completeResult = await httpClient.completeReplay(testRunId);
|
|
816
|
-
const serverTraceIds = completeResult.traceIds;
|
|
817
|
-
const replayTokens = completeResult.tokens;
|
|
818
|
-
if (serverTraceIds !== void 0) {
|
|
819
|
-
const missing = [];
|
|
820
|
-
let completedCount = 0;
|
|
821
|
-
for (let index = 0; index < resultItems.length; index += 1) {
|
|
822
|
-
const item = resultItems[index];
|
|
823
|
-
const localId = replayedTraceIds[index];
|
|
824
|
-
const mapped = localId ? serverTraceIds[localId] : void 0;
|
|
825
|
-
item.traceId = mapped ?? null;
|
|
826
|
-
if (item.error === null) {
|
|
827
|
-
completedCount += 1;
|
|
828
|
-
if (mapped === void 0) {
|
|
829
|
-
missing.push(localId ?? item.originalTraceId);
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
if (mapped !== void 0) {
|
|
833
|
-
item.tokens = replayTokens?.[mapped] ?? null;
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
if (completedCount > 0 && missing.length === completedCount) {
|
|
837
|
-
const serverCount = completeResult.traceCount !== void 0 ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.` : "";
|
|
838
|
-
throw new BitfabError(
|
|
839
|
-
`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.`
|
|
840
|
-
);
|
|
841
|
-
}
|
|
842
|
-
if (missing.length > 0) {
|
|
843
|
-
try {
|
|
844
|
-
console.error(
|
|
845
|
-
`Bitfab: server has no persisted trace for ${missing.length} of ${completedCount} completed replay item(s) (testRunId ${testRunId}). Their replay token usage is unavailable and they cannot be labeled.`
|
|
846
|
-
);
|
|
847
|
-
} catch {
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
const result = {
|
|
852
|
-
items: resultItems,
|
|
853
|
-
testRunId,
|
|
854
|
-
testRunUrl: `${serviceUrl}${testRunUrl}`
|
|
855
|
-
};
|
|
856
|
-
await writeReplayResultFile(result);
|
|
857
|
-
try {
|
|
858
|
-
options?.onProgress?.({
|
|
859
|
-
type: "complete",
|
|
860
|
-
testRunId,
|
|
861
|
-
completed: total,
|
|
862
|
-
total,
|
|
863
|
-
succeeded,
|
|
864
|
-
errored,
|
|
865
|
-
result
|
|
866
|
-
});
|
|
867
|
-
} catch {
|
|
868
|
-
}
|
|
869
|
-
return result;
|
|
870
|
-
}
|
|
871
|
-
async function writeReplayResultFile(result) {
|
|
872
|
-
const resultPath = typeof process !== "undefined" ? process.env?.BITFAB_REPLAY_RESULT_PATH : void 0;
|
|
873
|
-
if (!resultPath) {
|
|
874
|
-
return;
|
|
875
|
-
}
|
|
876
|
-
try {
|
|
877
|
-
const [{ dirname }, { mkdir, writeFile }] = await Promise.all([
|
|
878
|
-
import("path"),
|
|
879
|
-
import("fs/promises")
|
|
880
|
-
]);
|
|
881
|
-
await mkdir(dirname(resultPath), { recursive: true });
|
|
882
|
-
await writeFile(resultPath, `${JSON.stringify(result, null, 2)}
|
|
883
|
-
`);
|
|
884
|
-
} catch (err) {
|
|
885
|
-
try {
|
|
886
|
-
console.warn(
|
|
887
|
-
`Bitfab: failed to write replay result to BITFAB_REPLAY_RESULT_PATH (${resultPath}): ${err instanceof Error ? err.message : String(err)}`
|
|
888
|
-
);
|
|
889
|
-
} catch {
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
export {
|
|
895
|
-
__privateGet,
|
|
896
|
-
__privateAdd,
|
|
897
|
-
__privateSet,
|
|
898
|
-
BitfabError,
|
|
899
|
-
warnOnce,
|
|
900
|
-
serializeValue,
|
|
901
|
-
deserializeValue,
|
|
902
|
-
toJsonSafe,
|
|
903
|
-
toJsonSafeReport,
|
|
904
|
-
randomUuid,
|
|
905
|
-
registerAsyncLocalStorageClass,
|
|
906
|
-
assertAsyncStorageRegistered,
|
|
907
|
-
asyncStorageReady,
|
|
908
|
-
isAsyncStorageInitDone,
|
|
909
|
-
createAsyncLocalStorage,
|
|
910
|
-
resolveMockValue,
|
|
911
|
-
getReplayContext,
|
|
912
|
-
BITFAB_PROGRESS_PREFIX,
|
|
913
|
-
reportReplayProgress,
|
|
914
|
-
replay
|
|
915
|
-
};
|
|
916
|
-
//# sourceMappingURL=chunk-DPV6PBWE.js.map
|