@bitfab/sdk 0.65.3 → 0.65.5
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/autoTrace-CZu0BXhG.js +270 -0
- package/dist/autoTrace-CZu0BXhG.js.map +1 -0
- package/dist/autoTrace-KM9pYqk9.cjs +395 -0
- package/dist/autoTrace-KM9pYqk9.cjs.map +1 -0
- package/dist/autoTrace.cjs +15 -353
- package/dist/autoTrace.d.cts +44 -44
- package/dist/autoTrace.d.ts +44 -44
- package/dist/autoTrace.js +1 -28
- package/dist/babelPlugin-C70OxrqA.js +209 -0
- package/dist/babelPlugin-C70OxrqA.js.map +1 -0
- package/dist/babelPlugin-Nta4-VcL.cjs +232 -0
- package/dist/babelPlugin-Nta4-VcL.cjs.map +1 -0
- package/dist/http-CG1Irqxx.js +2154 -0
- package/dist/http-CG1Irqxx.js.map +1 -0
- package/dist/index-BFkAwvuc.d.cts +4410 -0
- package/dist/index-BFkAwvuc.d.ts +4410 -0
- package/dist/index.cjs +48 -12501
- package/dist/index.d.cts +2 -4426
- package/dist/index.d.ts +2 -4426
- package/dist/index.js +3 -96
- package/dist/loaderRuntime-0huddOOP.d.ts +12 -0
- package/dist/loaderRuntime-CslfDFO7.d.cts +12 -0
- package/dist/node.cjs +56 -12517
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +2 -1
- package/dist/node.d.ts +2 -1
- package/dist/node.js +10 -105
- package/dist/node.js.map +1 -1
- package/dist/registryCommand-Di8x0YoJ.js +1111 -0
- package/dist/registryCommand-Di8x0YoJ.js.map +1 -0
- package/dist/replayCli.js +49 -87
- package/dist/replayCli.js.map +1 -1
- package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/seedCli.js +10 -24
- package/dist/seedCli.js.map +1 -1
- package/dist/src-BRKm0P_S.cjs +8434 -0
- package/dist/src-BRKm0P_S.cjs.map +1 -0
- package/dist/src-CfFkki5l.js +6011 -0
- package/dist/src-CfFkki5l.js.map +1 -0
- package/dist/transform/babel.cjs +5 -422
- package/dist/transform/babel.d.cts +16 -16
- package/dist/transform/babel.d.ts +16 -16
- package/dist/transform/babel.js +1 -7
- package/dist/transform/bun.cjs +9 -478
- package/dist/transform/bun.cjs.map +1 -1
- package/dist/transform/bun.d.cts +5 -7
- package/dist/transform/bun.d.ts +5 -7
- package/dist/transform/bun.js +6 -11
- package/dist/transform/bun.js.map +1 -1
- package/dist/transform/esbuild.cjs +9 -478
- package/dist/transform/esbuild.cjs.map +1 -1
- package/dist/transform/esbuild.d.cts +5 -7
- package/dist/transform/esbuild.d.ts +5 -7
- package/dist/transform/esbuild.js +6 -11
- package/dist/transform/esbuild.js.map +1 -1
- package/dist/transform/loaderRuntime.cjs +85 -532
- package/dist/transform/loaderRuntime.cjs.map +1 -1
- package/dist/transform/loaderRuntime.d.cts +2 -12
- package/dist/transform/loaderRuntime.d.ts +2 -12
- package/dist/transform/loaderRuntime.js +56 -98
- package/dist/transform/loaderRuntime.js.map +1 -1
- package/dist/transform/nest.cjs +12 -481
- package/dist/transform/nest.cjs.map +1 -1
- package/dist/transform/nest.d.cts +8 -9
- package/dist/transform/nest.d.ts +8 -9
- package/dist/transform/nest.js +9 -14
- package/dist/transform/nest.js.map +1 -1
- package/dist/transform/next.cjs +56 -528
- package/dist/transform/next.cjs.map +1 -1
- package/dist/transform/next.d.cts +25 -25
- package/dist/transform/next.d.ts +24 -24
- package/dist/transform/next.js +52 -60
- package/dist/transform/next.js.map +1 -1
- package/dist/transform/nodeLoader.js +260 -506
- package/dist/transform/nodeLoader.js.map +1 -1
- package/dist/transform/register.js +4 -1
- package/dist/transform/register.js.map +1 -1
- package/dist/transform/rolldown.cjs +9 -478
- package/dist/transform/rolldown.cjs.map +1 -1
- package/dist/transform/rolldown.d.cts +5 -7
- package/dist/transform/rolldown.d.ts +5 -7
- package/dist/transform/rolldown.js +6 -11
- package/dist/transform/rolldown.js.map +1 -1
- package/dist/transform/rollup.cjs +9 -478
- package/dist/transform/rollup.cjs.map +1 -1
- package/dist/transform/rollup.d.cts +5 -7
- package/dist/transform/rollup.d.ts +5 -7
- package/dist/transform/rollup.js +6 -11
- package/dist/transform/rollup.js.map +1 -1
- package/dist/transform/rsbuild.cjs +9 -478
- package/dist/transform/rsbuild.cjs.map +1 -1
- package/dist/transform/rsbuild.d.cts +5 -7
- package/dist/transform/rsbuild.d.ts +5 -7
- package/dist/transform/rsbuild.js +6 -11
- package/dist/transform/rsbuild.js.map +1 -1
- package/dist/transform/rspack.cjs +9 -478
- package/dist/transform/rspack.cjs.map +1 -1
- package/dist/transform/rspack.d.cts +5 -7
- package/dist/transform/rspack.d.ts +5 -7
- package/dist/transform/rspack.js +6 -11
- package/dist/transform/rspack.js.map +1 -1
- package/dist/transform/swc.cjs +18 -486
- package/dist/transform/swc.cjs.map +1 -1
- package/dist/transform/swc.d.cts +15 -14
- package/dist/transform/swc.d.ts +15 -14
- package/dist/transform/swc.js +14 -32
- package/dist/transform/swc.js.map +1 -1
- package/dist/transform/unplugin.cjs +20 -476
- package/dist/transform/unplugin.cjs.map +1 -1
- package/dist/transform/unplugin.d.cts +4 -6
- package/dist/transform/unplugin.d.ts +4 -6
- package/dist/transform/unplugin.js +19 -8
- package/dist/transform/unplugin.js.map +1 -1
- package/dist/transform/vite.cjs +9 -478
- package/dist/transform/vite.cjs.map +1 -1
- package/dist/transform/vite.d.cts +5 -7
- package/dist/transform/vite.d.ts +5 -7
- package/dist/transform/vite.js +6 -11
- package/dist/transform/vite.js.map +1 -1
- package/dist/transform/webpack.cjs +9 -478
- package/dist/transform/webpack.cjs.map +1 -1
- package/dist/transform/webpack.d.cts +5 -7
- package/dist/transform/webpack.d.ts +5 -7
- package/dist/transform/webpack.js +6 -11
- package/dist/transform/webpack.js.map +1 -1
- package/dist/transform-BcyUocwm.js +36 -0
- package/dist/transform-BcyUocwm.js.map +1 -0
- package/dist/transform-BjxHGGKc.cjs +47 -0
- package/dist/transform-BjxHGGKc.cjs.map +1 -0
- package/dist/transformOptions-BsjCELkh.d.cts +11 -0
- package/dist/transformOptions-BsjCELkh.d.ts +11 -0
- package/package.json +5 -5
- package/dist/autoTrace.cjs.map +0 -1
- package/dist/autoTrace.js.map +0 -1
- package/dist/chunk-BRMGNMDO.js +0 -1176
- package/dist/chunk-BRMGNMDO.js.map +0 -1
- package/dist/chunk-CLP2L5PU.js +0 -2547
- package/dist/chunk-CLP2L5PU.js.map +0 -1
- package/dist/chunk-HLH7TN2A.js +0 -2060
- package/dist/chunk-HLH7TN2A.js.map +0 -1
- package/dist/chunk-LCV2JYXL.js +0 -2979
- package/dist/chunk-LCV2JYXL.js.map +0 -1
- package/dist/chunk-MT36GJMW.js +0 -106
- package/dist/chunk-MT36GJMW.js.map +0 -1
- package/dist/chunk-NRE5CJPR.js +0 -6874
- package/dist/chunk-NRE5CJPR.js.map +0 -1
- package/dist/chunk-PTCLRG4E.js +0 -28
- package/dist/chunk-PTCLRG4E.js.map +0 -1
- package/dist/chunk-QRNHRY7F.js +0 -270
- package/dist/chunk-QRNHRY7F.js.map +0 -1
- package/dist/chunk-YVJAOGHE.js +0 -45
- package/dist/chunk-YVJAOGHE.js.map +0 -1
- package/dist/chunk-Z26K57WZ.js +0 -1912
- package/dist/chunk-Z26K57WZ.js.map +0 -1
- package/dist/chunk-ZG6SHKEF.js +0 -404
- package/dist/chunk-ZG6SHKEF.js.map +0 -1
- package/dist/http-VN52X47M.js +0 -24
- package/dist/http-VN52X47M.js.map +0 -1
- package/dist/http-WP4YPPKC.js +0 -23
- package/dist/http-WP4YPPKC.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/replay-463SEV53.js +0 -28
- package/dist/replay-463SEV53.js.map +0 -1
- package/dist/replay-OT4A4HVF.js +0 -29
- package/dist/replay-OT4A4HVF.js.map +0 -1
- package/dist/transform/babel.cjs.map +0 -1
- package/dist/transform/babel.js.map +0 -1
- package/dist/transformOptions-Df2_Chtc.d.cts +0 -10
- package/dist/transformOptions-Df2_Chtc.d.ts +0 -10
package/dist/chunk-BRMGNMDO.js
DELETED
|
@@ -1,1176 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ReplayError,
|
|
3
|
-
canonicalCliFlag,
|
|
4
|
-
describeReplayInterrupt,
|
|
5
|
-
reportReplayProgress,
|
|
6
|
-
serializeReplayResult,
|
|
7
|
-
warnJudgeAssertionsDeprecated,
|
|
8
|
-
withCliFlags
|
|
9
|
-
} from "./chunk-Z26K57WZ.js";
|
|
10
|
-
import {
|
|
11
|
-
BitfabError,
|
|
12
|
-
asyncStorageReady,
|
|
13
|
-
createAsyncLocalStorage,
|
|
14
|
-
warnOnce
|
|
15
|
-
} from "./chunk-CLP2L5PU.js";
|
|
16
|
-
|
|
17
|
-
// src/autoTrace.ts
|
|
18
|
-
var autoTraceGlobal = globalThis;
|
|
19
|
-
var autoTraceState = autoTraceGlobal.__bitfabAutoTraceStateV4 ?? {
|
|
20
|
-
storage: null,
|
|
21
|
-
browserScope: void 0,
|
|
22
|
-
capturePolicies: /* @__PURE__ */ new WeakMap(),
|
|
23
|
-
activeRoots: 0
|
|
24
|
-
};
|
|
25
|
-
autoTraceGlobal.__bitfabAutoTraceStateV4 = autoTraceState;
|
|
26
|
-
|
|
27
|
-
// src/commitRef.ts
|
|
28
|
-
var EXPLICIT_SHA_ENV = "BITFAB_COMMIT_SHA";
|
|
29
|
-
var DISABLE_ENV = "BITFAB_DISABLE_COMMIT_REF";
|
|
30
|
-
var GIT_MAX_BUFFER = 1024 * 1024;
|
|
31
|
-
var VERCEL_PROVIDER_HOSTS = {
|
|
32
|
-
github: "github.com",
|
|
33
|
-
gitlab: "gitlab.com",
|
|
34
|
-
bitbucket: "bitbucket.org"
|
|
35
|
-
};
|
|
36
|
-
function read(env, name) {
|
|
37
|
-
if (name === null) {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
const value = env(name)?.trim();
|
|
41
|
-
return value ? value : null;
|
|
42
|
-
}
|
|
43
|
-
function remoteFrom(...names) {
|
|
44
|
-
return (env) => {
|
|
45
|
-
const parts = names.map((name) => read(env, name));
|
|
46
|
-
if (parts.some((part) => part === null)) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
return normalizeRemote(parts.join("/"));
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
function vercelRemote(env) {
|
|
53
|
-
const provider = read(env, "VERCEL_GIT_PROVIDER")?.toLowerCase() ?? "";
|
|
54
|
-
const host = VERCEL_PROVIDER_HOSTS[provider];
|
|
55
|
-
const owner = read(env, "VERCEL_GIT_REPO_OWNER");
|
|
56
|
-
const slug = read(env, "VERCEL_GIT_REPO_SLUG");
|
|
57
|
-
if (!host || !owner || !slug) {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
return `${host}/${owner}/${slug}`;
|
|
61
|
-
}
|
|
62
|
-
function noRemote() {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
var PLATFORM_ENVS = [
|
|
66
|
-
["VERCEL_GIT_COMMIT_SHA", "VERCEL_GIT_COMMIT_REF", vercelRemote],
|
|
67
|
-
[
|
|
68
|
-
"GITHUB_SHA",
|
|
69
|
-
"GITHUB_REF_NAME",
|
|
70
|
-
remoteFrom("GITHUB_SERVER_URL", "GITHUB_REPOSITORY")
|
|
71
|
-
],
|
|
72
|
-
["RAILWAY_GIT_COMMIT_SHA", "RAILWAY_GIT_BRANCH", noRemote],
|
|
73
|
-
["RENDER_GIT_COMMIT", "RENDER_GIT_BRANCH", noRemote],
|
|
74
|
-
["SOURCE_VERSION", null, noRemote],
|
|
75
|
-
["CF_PAGES_COMMIT_SHA", "CF_PAGES_BRANCH", noRemote],
|
|
76
|
-
["CI_COMMIT_SHA", "CI_COMMIT_REF_NAME", remoteFrom("CI_REPOSITORY_URL")],
|
|
77
|
-
[
|
|
78
|
-
"BUILD_SOURCEVERSION",
|
|
79
|
-
"BUILD_SOURCEBRANCHNAME",
|
|
80
|
-
remoteFrom("BUILD_REPOSITORY_URI")
|
|
81
|
-
],
|
|
82
|
-
["CIRCLE_SHA1", "CIRCLE_BRANCH", remoteFrom("CIRCLE_REPOSITORY_URL")]
|
|
83
|
-
];
|
|
84
|
-
var COMMIT_REF_ENV_NAMES = [
|
|
85
|
-
EXPLICIT_SHA_ENV,
|
|
86
|
-
DISABLE_ENV,
|
|
87
|
-
...PLATFORM_ENVS.flatMap(
|
|
88
|
-
([sha, branch]) => branch === null ? [sha] : [sha, branch]
|
|
89
|
-
),
|
|
90
|
-
"GITHUB_SERVER_URL",
|
|
91
|
-
"GITHUB_REPOSITORY",
|
|
92
|
-
"CI_REPOSITORY_URL",
|
|
93
|
-
"BUILD_REPOSITORY_URI",
|
|
94
|
-
"CIRCLE_REPOSITORY_URL",
|
|
95
|
-
"VERCEL_GIT_PROVIDER",
|
|
96
|
-
"VERCEL_GIT_REPO_OWNER",
|
|
97
|
-
"VERCEL_GIT_REPO_SLUG"
|
|
98
|
-
];
|
|
99
|
-
function normalizeRemote(raw) {
|
|
100
|
-
const value = raw?.trim();
|
|
101
|
-
if (!value) {
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
let host = "";
|
|
105
|
-
let path = value;
|
|
106
|
-
if (value.includes("://")) {
|
|
107
|
-
try {
|
|
108
|
-
const parsed = new URL(value);
|
|
109
|
-
host = parsed.hostname;
|
|
110
|
-
path = parsed.pathname;
|
|
111
|
-
} catch {
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
const separator = value.indexOf(":");
|
|
116
|
-
if (separator !== -1) {
|
|
117
|
-
const head = value.slice(0, separator);
|
|
118
|
-
host = head.slice(head.lastIndexOf("@") + 1);
|
|
119
|
-
path = value.slice(separator + 1);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
path = path.replace(/^\/+|\/+$/g, "");
|
|
123
|
-
if (path.endsWith(".git")) {
|
|
124
|
-
path = path.slice(0, -".git".length).replace(/\/+$/, "");
|
|
125
|
-
}
|
|
126
|
-
if (!host) {
|
|
127
|
-
return path || null;
|
|
128
|
-
}
|
|
129
|
-
return path ? `${host}/${path}` : host;
|
|
130
|
-
}
|
|
131
|
-
var settled = Promise.resolve();
|
|
132
|
-
|
|
133
|
-
// src/openaiAgentsSpanContext.ts
|
|
134
|
-
var spanGlobal = globalThis;
|
|
135
|
-
var state = spanGlobal.__bitfabOpenAiAgentsSpansV1 ?? {
|
|
136
|
-
bitfabTraceIds: /* @__PURE__ */ new Map(),
|
|
137
|
-
endedSpanIds: /* @__PURE__ */ new Map()
|
|
138
|
-
};
|
|
139
|
-
spanGlobal.__bitfabOpenAiAgentsSpansV1 = state;
|
|
140
|
-
|
|
141
|
-
// src/rivetContext.ts
|
|
142
|
-
var storage = null;
|
|
143
|
-
var STORAGE_SYMBOL = /* @__PURE__ */ Symbol.for("bitfab.rivetContextStorage");
|
|
144
|
-
function initializeStorage() {
|
|
145
|
-
if (storage) {
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
const shared = globalThis;
|
|
149
|
-
const existing = shared[STORAGE_SYMBOL];
|
|
150
|
-
if (existing) {
|
|
151
|
-
storage = existing;
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
const created = createAsyncLocalStorage();
|
|
155
|
-
if (created) {
|
|
156
|
-
shared[STORAGE_SYMBOL] = created;
|
|
157
|
-
storage = created;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
var rivetContextReady = asyncStorageReady.then(() => {
|
|
161
|
-
initializeStorage();
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
// src/seedContext.ts
|
|
165
|
-
var seedContextStorage = null;
|
|
166
|
-
var SEED_CONTEXT_STORAGE_SYMBOL = /* @__PURE__ */ Symbol.for("bitfab.seedContextStorage");
|
|
167
|
-
var seedContextReady = asyncStorageReady.then(() => {
|
|
168
|
-
const shared = globalThis;
|
|
169
|
-
const existing = shared[SEED_CONTEXT_STORAGE_SYMBOL];
|
|
170
|
-
if (existing) {
|
|
171
|
-
seedContextStorage = existing;
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
const created = createAsyncLocalStorage();
|
|
175
|
-
if (created) {
|
|
176
|
-
shared[SEED_CONTEXT_STORAGE_SYMBOL] = created;
|
|
177
|
-
seedContextStorage = created;
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
// src/client.ts
|
|
182
|
-
var asyncLocalStorage = null;
|
|
183
|
-
var SPAN_CONTEXT_STORAGE_SYMBOL = /* @__PURE__ */ Symbol.for("bitfab.spanContextStorage");
|
|
184
|
-
var initializeAsyncContext = () => {
|
|
185
|
-
if (asyncLocalStorage) {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
const shared = globalThis;
|
|
189
|
-
const existing = shared[SPAN_CONTEXT_STORAGE_SYMBOL];
|
|
190
|
-
if (existing) {
|
|
191
|
-
asyncLocalStorage = existing;
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
const created = createAsyncLocalStorage();
|
|
195
|
-
if (created) {
|
|
196
|
-
shared[SPAN_CONTEXT_STORAGE_SYMBOL] = created;
|
|
197
|
-
asyncLocalStorage = created;
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
var asyncLocalStorageReady = asyncStorageReady.then(() => {
|
|
201
|
-
initializeAsyncContext();
|
|
202
|
-
});
|
|
203
|
-
function _resolvedApiKey(client) {
|
|
204
|
-
const keyed = client;
|
|
205
|
-
return keyed.findApiKey(true) ?? null;
|
|
206
|
-
}
|
|
207
|
-
function _serviceUrl(client) {
|
|
208
|
-
return client.serviceUrl;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// src/replayRegistry.ts
|
|
212
|
-
var REGISTRATION_FIELDS = /* @__PURE__ */ new Set([
|
|
213
|
-
"client",
|
|
214
|
-
"fn",
|
|
215
|
-
"traceFunctionKey",
|
|
216
|
-
"options",
|
|
217
|
-
"optionsFactory"
|
|
218
|
-
]);
|
|
219
|
-
function validateReplayRegistry(registry) {
|
|
220
|
-
for (const [pipeline, registration] of Object.entries(registry)) {
|
|
221
|
-
if (typeof registration !== "object" || registration === null) {
|
|
222
|
-
throw new BitfabError(
|
|
223
|
-
`Replay registry entry '${pipeline}' must be an object with client and fn.`
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
const unknownFields = Object.keys(registration).filter(
|
|
227
|
-
(field) => !REGISTRATION_FIELDS.has(field)
|
|
228
|
-
);
|
|
229
|
-
if (unknownFields.length > 0) {
|
|
230
|
-
warnOnce(
|
|
231
|
-
`replay-registry-unknown-fields:${pipeline}:${unknownFields.join(",")}`,
|
|
232
|
-
`Replay registry entry '${pipeline}' has unknown field(s): ${unknownFields.join(", ")}. They are ignored. An entry takes client, fn, traceFunctionKey, options, and optionsFactory. Put replay options such as adaptInputs, mock, and mockOverride inside options. A later SDK release will reject unknown fields.`
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
var VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
238
|
-
"--limit",
|
|
239
|
-
"--attempts",
|
|
240
|
-
"--trace-ids",
|
|
241
|
-
"--name",
|
|
242
|
-
"--notes",
|
|
243
|
-
"--metadata",
|
|
244
|
-
"--concurrency",
|
|
245
|
-
"--max-concurrency",
|
|
246
|
-
"--code-change",
|
|
247
|
-
"--experiment-group-id",
|
|
248
|
-
"--experiment-group-name",
|
|
249
|
-
"--dataset-id",
|
|
250
|
-
"--dataset-ids",
|
|
251
|
-
"--grader-ids",
|
|
252
|
-
"--mock",
|
|
253
|
-
"--param",
|
|
254
|
-
"--params",
|
|
255
|
-
"--resume"
|
|
256
|
-
]);
|
|
257
|
-
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
258
|
-
"--only-with-assertions",
|
|
259
|
-
"--skip-assertion-judging",
|
|
260
|
-
"--judge-assertions",
|
|
261
|
-
"--db-branch",
|
|
262
|
-
"--no-db-branch",
|
|
263
|
-
"--no-code-change",
|
|
264
|
-
"--dry-run",
|
|
265
|
-
"--fail-on-error",
|
|
266
|
-
"--force"
|
|
267
|
-
]);
|
|
268
|
-
var HELP_FLAGS = /* @__PURE__ */ new Set(["--help", "-h"]);
|
|
269
|
-
var REPEATABLE_FLAGS = /* @__PURE__ */ new Set(["--metadata", "--param"]);
|
|
270
|
-
function recordFlag(flags, flag, raw) {
|
|
271
|
-
const name = canonicalCliFlag(flag.slice(2));
|
|
272
|
-
if (raw === void 0) {
|
|
273
|
-
flags[name] = true;
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
const value = flag === "--param" ? raw.split("=")[0] : raw;
|
|
277
|
-
if (REPEATABLE_FLAGS.has(flag)) {
|
|
278
|
-
const previous = flags[name];
|
|
279
|
-
flags[name] = [...Array.isArray(previous) ? previous : [], value];
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
flags[name] = value;
|
|
283
|
-
}
|
|
284
|
-
var MAX_ATTEMPTS = 100;
|
|
285
|
-
var MAX_PINNED_TRACE_IDS = 100;
|
|
286
|
-
var INTERRUPT_EXIT_CODES = {
|
|
287
|
-
SIGINT: 130,
|
|
288
|
-
SIGTERM: 143
|
|
289
|
-
};
|
|
290
|
-
var RESUME_CONFLICTING_FLAGS = [
|
|
291
|
-
["traceIds", "--trace-ids"],
|
|
292
|
-
["datasetIds", "--dataset-ids"],
|
|
293
|
-
["limit", "--limit"],
|
|
294
|
-
["attempts", "--attempts"],
|
|
295
|
-
["graderIds", "--grader-ids"],
|
|
296
|
-
["onlyWithAssertions", "--only-with-assertions"],
|
|
297
|
-
["dryRun", "--dry-run"]
|
|
298
|
-
];
|
|
299
|
-
var RESUME_CLEARED_OPTIONS = {
|
|
300
|
-
traceIds: void 0,
|
|
301
|
-
limit: void 0,
|
|
302
|
-
datasetId: void 0,
|
|
303
|
-
datasetIds: void 0,
|
|
304
|
-
attempts: void 0,
|
|
305
|
-
graderIds: void 0,
|
|
306
|
-
onlyWithAssertions: void 0,
|
|
307
|
-
dryRun: void 0
|
|
308
|
-
};
|
|
309
|
-
function hasApprovedAssertion(assertions) {
|
|
310
|
-
return assertions.some((assertion) => assertion.approvalState === "approved");
|
|
311
|
-
}
|
|
312
|
-
async function boundTraceIds(client, traceIds, limit, onlyWithAssertions) {
|
|
313
|
-
if (!Number.isInteger(limit) || limit < 1) {
|
|
314
|
-
throw new BitfabError("Replay limit must be a positive integer.");
|
|
315
|
-
}
|
|
316
|
-
if (!onlyWithAssertions || limit >= traceIds.length) {
|
|
317
|
-
return traceIds.slice(0, limit);
|
|
318
|
-
}
|
|
319
|
-
const selected = [];
|
|
320
|
-
for (const traceId of traceIds) {
|
|
321
|
-
const { assertions, inheritedFrom } = await client.traces.getAssertions(traceId);
|
|
322
|
-
if (inheritedFrom === null && hasApprovedAssertion(assertions)) {
|
|
323
|
-
selected.push(traceId);
|
|
324
|
-
if (selected.length === limit) {
|
|
325
|
-
break;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
if (selected.length === 0) {
|
|
330
|
-
throw new BitfabError(
|
|
331
|
-
"No traces with approved assertions matched this replay selection."
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
return selected;
|
|
335
|
-
}
|
|
336
|
-
async function pinnedDatasetMembers(client, datasetIds, limit, onlyWithAssertions = false) {
|
|
337
|
-
const members = /* @__PURE__ */ new Set();
|
|
338
|
-
for (const datasetId of datasetIds) {
|
|
339
|
-
const { traceIds } = await client.datasets.listTraces(datasetId);
|
|
340
|
-
for (const traceId of traceIds) {
|
|
341
|
-
members.add(traceId);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
const ordered = [...members].sort();
|
|
345
|
-
if (limit >= ordered.length) {
|
|
346
|
-
return void 0;
|
|
347
|
-
}
|
|
348
|
-
if (limit > MAX_PINNED_TRACE_IDS) {
|
|
349
|
-
throw new BitfabError(
|
|
350
|
-
`Bounding a dataset replay to ${limit} names one trace ID per replayed item, and a replay accepts at most ${MAX_PINNED_TRACE_IDS}. Drop the limit to replay every selected dataset in full.`
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
return boundTraceIds(client, ordered, limit, onlyWithAssertions);
|
|
354
|
-
}
|
|
355
|
-
function usage(registry) {
|
|
356
|
-
const pipelines = registry === void 0 ? "pipeline" : Object.keys(registry).join("|");
|
|
357
|
-
return `Usage: bitfab-replay --registry <path> <${pipelines}> [options]
|
|
358
|
-
|
|
359
|
-
Options:
|
|
360
|
-
--limit N (bounds a trace ID or dataset selection instead of replacing it)
|
|
361
|
-
--attempts N (replay each trace N times in this run, max ${MAX_ATTEMPTS})
|
|
362
|
-
--trace-ids id1,id2
|
|
363
|
-
--name NAME (what this run is testing, such as "baseline"; Bitfab already records the commit, branch, and datasets)
|
|
364
|
-
--notes TEXT (run conditions Bitfab cannot see, such as a forced feature flag)
|
|
365
|
-
--metadata key=value (repeatable; tags kept on the experiment, such as which schedule launched it, and filterable through client.experiments.list)
|
|
366
|
-
--concurrency N, --max-concurrency N
|
|
367
|
-
--code-change PATH, --no-code-change
|
|
368
|
-
--experiment-group-id UUID (join this experiment group; a new UUID creates the group)
|
|
369
|
-
--experiment-group-name NAME (name the group when this run creates it or it has no name yet; requires --experiment-group-id)
|
|
370
|
-
--dataset-ids uuid1,uuid2 (--dataset-id is the same flag)
|
|
371
|
-
--grader-ids id1,id2
|
|
372
|
-
--only-with-assertions (replay only traces carrying an approved assertion)
|
|
373
|
-
--skip-assertion-judging (don't judge approved assertions on each replay; judging is on by default and costs model calls)
|
|
374
|
-
--judge-assertions (deprecated: judging is on by default)
|
|
375
|
-
--mock none|all|marked
|
|
376
|
-
--db-branch, --no-db-branch
|
|
377
|
-
--dry-run (resolve inputs, run nothing)
|
|
378
|
-
--fail-on-error (exit 1 after printing the result when any replayed item errored; under --dry-run, items whose inputs failed to resolve count)
|
|
379
|
-
--resume EXPERIMENT_ID (finish an experiment that stopped partway, running only the items it did not finish, with the traces, attempts, and graders it started with)
|
|
380
|
-
--force (with --resume, resume even when the experiment may still be running or the code changed since it started)
|
|
381
|
-
--params PATH
|
|
382
|
-
--param name=value (repeatable)
|
|
383
|
-
-h, --help`;
|
|
384
|
-
}
|
|
385
|
-
var ReplayCliHelp = class extends Error {
|
|
386
|
-
};
|
|
387
|
-
async function reseedFromRegistry(registry, pipeline, traceIds) {
|
|
388
|
-
const registration = registry[pipeline];
|
|
389
|
-
if (registration === void 0) {
|
|
390
|
-
throw new BitfabError(
|
|
391
|
-
`Unknown pipeline '${pipeline}'. Registered: ${Object.keys(registry).join(", ")}`
|
|
392
|
-
);
|
|
393
|
-
}
|
|
394
|
-
const traceFunctionKey = resolveTraceFunctionKey(registration);
|
|
395
|
-
const reseeded = [];
|
|
396
|
-
for (const traceId of traceIds) {
|
|
397
|
-
reseeded.push(
|
|
398
|
-
await registration.client.reseedTrace(traceFunctionKey, registration.fn, {
|
|
399
|
-
traceId
|
|
400
|
-
})
|
|
401
|
-
);
|
|
402
|
-
}
|
|
403
|
-
return { pipeline, traceFunctionKey, reseeded };
|
|
404
|
-
}
|
|
405
|
-
function parseSeedCases(raw, path, run) {
|
|
406
|
-
const trimmed = raw.trim();
|
|
407
|
-
if (trimmed.length === 0) {
|
|
408
|
-
throw new BitfabError(`Seed file '${path}' is empty.`);
|
|
409
|
-
}
|
|
410
|
-
const values = trimmed.startsWith("[") ? JSON.parse(trimmed) : trimmed.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => JSON.parse(line));
|
|
411
|
-
return values.map((value, index) => {
|
|
412
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
413
|
-
throw new BitfabError(
|
|
414
|
-
`Seed case ${index} in '${path}' must be an object with an "input" array.`
|
|
415
|
-
);
|
|
416
|
-
}
|
|
417
|
-
const { input } = value;
|
|
418
|
-
if (!Array.isArray(input)) {
|
|
419
|
-
throw new BitfabError(
|
|
420
|
-
`Seed case ${index} in '${path}' is missing an "input" array. Wrap a single argument as [arg].`
|
|
421
|
-
);
|
|
422
|
-
}
|
|
423
|
-
if (run && "expected" in value) {
|
|
424
|
-
throw new BitfabError(
|
|
425
|
-
`Seed case ${index} in '${path}' carries "expected", which --run does not record: the case is run once and its output is what the run produced. Remove the field, or drop --run to record the case without running it.`
|
|
426
|
-
);
|
|
427
|
-
}
|
|
428
|
-
return value;
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
async function seedFromRegistry(registry, pipeline, cases, options = {}) {
|
|
432
|
-
const registration = registry[pipeline];
|
|
433
|
-
if (registration === void 0) {
|
|
434
|
-
throw new BitfabError(
|
|
435
|
-
`Unknown pipeline '${pipeline}'. Registered: ${Object.keys(registry).join(", ")}`
|
|
436
|
-
);
|
|
437
|
-
}
|
|
438
|
-
const traceFunctionKey = resolveTraceFunctionKey(registration);
|
|
439
|
-
if (options.run === true) {
|
|
440
|
-
const traceIds2 = [];
|
|
441
|
-
for (const seedCase of cases) {
|
|
442
|
-
traceIds2.push(
|
|
443
|
-
await registration.client.seedTrace(traceFunctionKey, registration.fn, {
|
|
444
|
-
args: seedCase.input,
|
|
445
|
-
metadata: seedCase.metadata,
|
|
446
|
-
sessionId: seedCase.sessionId
|
|
447
|
-
})
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
return { pipeline, traceFunctionKey, traceIds: traceIds2 };
|
|
451
|
-
}
|
|
452
|
-
const traceIds = cases.map(
|
|
453
|
-
(seedCase) => registration.client.seedTrace(traceFunctionKey, {
|
|
454
|
-
input: seedCase.input,
|
|
455
|
-
expected: seedCase.expected,
|
|
456
|
-
fn: registration.fn,
|
|
457
|
-
metadata: seedCase.metadata,
|
|
458
|
-
sessionId: seedCase.sessionId
|
|
459
|
-
})
|
|
460
|
-
);
|
|
461
|
-
const { flushTraces } = await import("./http-WP4YPPKC.js");
|
|
462
|
-
await flushTraces(3e4);
|
|
463
|
-
return { pipeline, traceFunctionKey, traceIds };
|
|
464
|
-
}
|
|
465
|
-
var SEED_USAGE = `Usage: bitfab-seed --registry <path> <pipeline> --from-trace <id>[,<id>...]
|
|
466
|
-
bitfab-seed --registry <path> <pipeline> --cases <cases.jsonl> [--run]
|
|
467
|
-
|
|
468
|
-
--from-trace re-seeds each trace: the registered function runs once on the trace's recorded inputs and the result is recorded under the same trace id, with the previous run kept as history under a new id. Nothing is mocked and no experiment is created. Labels, assertions, and dataset membership stay on the trace.
|
|
469
|
-
|
|
470
|
-
--cases seeds new cases. Each case is a JSON object with an "input" array, plus optional "expected", "metadata", and "sessionId"; a JSON array of those objects works too. Without --run, each case is written as a trace directly ("input" becomes the root span input and "expected" its output) and nothing executes. With --run, each case runs once through the registered function with capture off and the execution is recorded, so the output is what the run produced; cases carrying "expected" are rejected.
|
|
471
|
-
|
|
472
|
-
bitfab-replay --registry <path> <pipeline> --seed <cases.jsonl> [--run] is the older spelling of --cases.`;
|
|
473
|
-
async function runSeedCli(registry, argv, io = {}) {
|
|
474
|
-
const stdout = io.stdout ?? console.log;
|
|
475
|
-
const stderr = io.stderr ?? console.error;
|
|
476
|
-
if (argv.some((value) => HELP_FLAGS.has(value))) {
|
|
477
|
-
throw new ReplayCliHelp(SEED_USAGE);
|
|
478
|
-
}
|
|
479
|
-
const pipeline = argv[0];
|
|
480
|
-
if (pipeline === void 0 || registry[pipeline] === void 0) {
|
|
481
|
-
throw new BitfabError(SEED_USAGE);
|
|
482
|
-
}
|
|
483
|
-
const fromTraceIndex = argv.indexOf("--from-trace");
|
|
484
|
-
if (fromTraceIndex !== -1) {
|
|
485
|
-
const raw = argv[fromTraceIndex + 1];
|
|
486
|
-
if (raw === void 0 || raw.startsWith("--")) {
|
|
487
|
-
throw new BitfabError("--from-trace requires one or more trace ids.");
|
|
488
|
-
}
|
|
489
|
-
const traceIds = commaSeparated("--from-trace", raw);
|
|
490
|
-
stderr(
|
|
491
|
-
`[seed] Re-seeding ${traceIds.length} trace(s) through "${pipeline}"...`
|
|
492
|
-
);
|
|
493
|
-
const result2 = await reseedFromRegistry(registry, pipeline, traceIds);
|
|
494
|
-
for (const entry of result2.reseeded) {
|
|
495
|
-
stderr(
|
|
496
|
-
`[seed] ${entry.traceId} now holds the fresh run; the previous run is kept as ${entry.previousRunTraceId}`
|
|
497
|
-
);
|
|
498
|
-
}
|
|
499
|
-
stdout(JSON.stringify(result2, null, 2));
|
|
500
|
-
return result2;
|
|
501
|
-
}
|
|
502
|
-
const casesFlagIndex = argv.indexOf("--cases");
|
|
503
|
-
const seedIndex = casesFlagIndex === -1 ? argv.indexOf("--seed") : casesFlagIndex;
|
|
504
|
-
if (seedIndex === -1) {
|
|
505
|
-
throw new BitfabError(SEED_USAGE);
|
|
506
|
-
}
|
|
507
|
-
const casesPath = argv[seedIndex + 1];
|
|
508
|
-
if (casesPath === void 0 || casesPath.startsWith("--")) {
|
|
509
|
-
throw new BitfabError(`${argv[seedIndex]} requires a path to a cases file.`);
|
|
510
|
-
}
|
|
511
|
-
const run = argv.includes("--run");
|
|
512
|
-
const readFile = io.readFile ?? defaultReadFile;
|
|
513
|
-
const cases = parseSeedCases(await readFile(casesPath), casesPath, run);
|
|
514
|
-
stderr(
|
|
515
|
-
run ? `[seed] Running ${cases.length} case(s) through "${pipeline}"...` : `[seed] Seeding ${cases.length} case(s) into "${pipeline}"...`
|
|
516
|
-
);
|
|
517
|
-
const result = await seedFromRegistry(registry, pipeline, cases, { run });
|
|
518
|
-
stderr(
|
|
519
|
-
`[seed] ${run ? "Recorded" : "Wrote"} ${result.traceIds.length} trace(s) for "${result.traceFunctionKey}". Replay them with --trace-ids ${result.traceIds.slice(0, 3).join(",")}${result.traceIds.length > 3 ? ",..." : ""}`
|
|
520
|
-
);
|
|
521
|
-
stdout(JSON.stringify(result, null, 2));
|
|
522
|
-
return result;
|
|
523
|
-
}
|
|
524
|
-
function requirePositiveInteger(flag, raw, max) {
|
|
525
|
-
const value = Number(raw);
|
|
526
|
-
if (!Number.isInteger(value) || value < 1) {
|
|
527
|
-
throw new BitfabError(
|
|
528
|
-
`${flag} must be a positive integer (received '${raw}').`
|
|
529
|
-
);
|
|
530
|
-
}
|
|
531
|
-
if (max !== void 0 && value > max) {
|
|
532
|
-
throw new BitfabError(`${flag} must be at most ${max} (received '${raw}').`);
|
|
533
|
-
}
|
|
534
|
-
return value;
|
|
535
|
-
}
|
|
536
|
-
function commaSeparated(flag, raw) {
|
|
537
|
-
const values = raw.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
|
|
538
|
-
if (values.length === 0) {
|
|
539
|
-
throw new BitfabError(`${flag} must contain at least one value.`);
|
|
540
|
-
}
|
|
541
|
-
return values;
|
|
542
|
-
}
|
|
543
|
-
function checkReplayCliArgs(argv) {
|
|
544
|
-
parseReplayCliArgs(void 0, argv);
|
|
545
|
-
}
|
|
546
|
-
function parseReplayCliArgs(registry, argv) {
|
|
547
|
-
if (argv.some((value) => HELP_FLAGS.has(value))) {
|
|
548
|
-
throw new ReplayCliHelp(usage(registry));
|
|
549
|
-
}
|
|
550
|
-
const pipeline = argv[0];
|
|
551
|
-
if (pipeline === void 0 || registry !== void 0 && registry[pipeline] === void 0) {
|
|
552
|
-
throw new BitfabError(usage(registry));
|
|
553
|
-
}
|
|
554
|
-
const parsed = { pipeline, params: [], flags: {} };
|
|
555
|
-
for (let index = 1; index < argv.length; index += 1) {
|
|
556
|
-
const flag = argv[index];
|
|
557
|
-
if (BOOLEAN_FLAGS.has(flag)) {
|
|
558
|
-
recordFlag(parsed.flags, flag);
|
|
559
|
-
switch (flag) {
|
|
560
|
-
case "--db-branch":
|
|
561
|
-
if (parsed.dbBranch === false) {
|
|
562
|
-
throw new BitfabError(
|
|
563
|
-
"--db-branch and --no-db-branch cannot be used together."
|
|
564
|
-
);
|
|
565
|
-
}
|
|
566
|
-
parsed.dbBranch = true;
|
|
567
|
-
break;
|
|
568
|
-
case "--no-db-branch":
|
|
569
|
-
if (parsed.dbBranch === true) {
|
|
570
|
-
throw new BitfabError(
|
|
571
|
-
"--db-branch and --no-db-branch cannot be used together."
|
|
572
|
-
);
|
|
573
|
-
}
|
|
574
|
-
parsed.dbBranch = false;
|
|
575
|
-
break;
|
|
576
|
-
case "--only-with-assertions":
|
|
577
|
-
parsed.onlyWithAssertions = true;
|
|
578
|
-
break;
|
|
579
|
-
case "--skip-assertion-judging":
|
|
580
|
-
parsed.skipAssertionJudging = true;
|
|
581
|
-
break;
|
|
582
|
-
case "--judge-assertions":
|
|
583
|
-
parsed.judgeAssertionsFlag = true;
|
|
584
|
-
break;
|
|
585
|
-
case "--no-code-change":
|
|
586
|
-
parsed.noCodeChange = true;
|
|
587
|
-
break;
|
|
588
|
-
case "--dry-run":
|
|
589
|
-
parsed.dryRun = true;
|
|
590
|
-
break;
|
|
591
|
-
case "--fail-on-error":
|
|
592
|
-
parsed.failOnError = true;
|
|
593
|
-
break;
|
|
594
|
-
case "--force":
|
|
595
|
-
parsed.force = true;
|
|
596
|
-
break;
|
|
597
|
-
}
|
|
598
|
-
continue;
|
|
599
|
-
}
|
|
600
|
-
if (!VALUE_FLAGS.has(flag)) {
|
|
601
|
-
throw new BitfabError(
|
|
602
|
-
`Unknown replay option '${flag}'.
|
|
603
|
-
${usage(registry)}`
|
|
604
|
-
);
|
|
605
|
-
}
|
|
606
|
-
const raw = argv[index + 1];
|
|
607
|
-
if (raw === void 0 || raw.startsWith("--")) {
|
|
608
|
-
throw new BitfabError(`${flag} requires a value.`);
|
|
609
|
-
}
|
|
610
|
-
index += 1;
|
|
611
|
-
recordFlag(parsed.flags, flag, raw);
|
|
612
|
-
switch (flag) {
|
|
613
|
-
case "--limit":
|
|
614
|
-
parsed.limit = requirePositiveInteger(flag, raw);
|
|
615
|
-
break;
|
|
616
|
-
case "--attempts":
|
|
617
|
-
parsed.attempts = requirePositiveInteger(flag, raw, MAX_ATTEMPTS);
|
|
618
|
-
break;
|
|
619
|
-
case "--trace-ids":
|
|
620
|
-
parsed.traceIds = commaSeparated(flag, raw);
|
|
621
|
-
break;
|
|
622
|
-
case "--name":
|
|
623
|
-
parsed.name = raw;
|
|
624
|
-
break;
|
|
625
|
-
case "--notes":
|
|
626
|
-
parsed.notes = raw;
|
|
627
|
-
break;
|
|
628
|
-
case "--metadata": {
|
|
629
|
-
const [key, value] = parseMetadataTag(raw);
|
|
630
|
-
parsed.metadata = { ...parsed.metadata, [key]: value };
|
|
631
|
-
break;
|
|
632
|
-
}
|
|
633
|
-
case "--concurrency":
|
|
634
|
-
case "--max-concurrency":
|
|
635
|
-
parsed.maxConcurrency = requirePositiveInteger(flag, raw);
|
|
636
|
-
break;
|
|
637
|
-
case "--code-change":
|
|
638
|
-
parsed.codeChangePath = raw;
|
|
639
|
-
break;
|
|
640
|
-
case "--experiment-group-id":
|
|
641
|
-
parsed.experimentGroupId = raw;
|
|
642
|
-
break;
|
|
643
|
-
case "--experiment-group-name":
|
|
644
|
-
parsed.experimentGroupName = raw;
|
|
645
|
-
break;
|
|
646
|
-
case "--dataset-id":
|
|
647
|
-
case "--dataset-ids":
|
|
648
|
-
parsed.datasetIds = commaSeparated(flag, raw);
|
|
649
|
-
break;
|
|
650
|
-
case "--grader-ids":
|
|
651
|
-
parsed.graderIds = commaSeparated(flag, raw);
|
|
652
|
-
break;
|
|
653
|
-
case "--mock":
|
|
654
|
-
if (raw !== "none" && raw !== "all" && raw !== "marked") {
|
|
655
|
-
throw new BitfabError(
|
|
656
|
-
`--mock must be one of: none, all, marked (received '${raw}').`
|
|
657
|
-
);
|
|
658
|
-
}
|
|
659
|
-
parsed.mock = raw;
|
|
660
|
-
break;
|
|
661
|
-
case "--params":
|
|
662
|
-
parsed.paramsPath = raw;
|
|
663
|
-
break;
|
|
664
|
-
case "--param":
|
|
665
|
-
parsed.params.push(raw);
|
|
666
|
-
break;
|
|
667
|
-
case "--resume":
|
|
668
|
-
parsed.resume = raw;
|
|
669
|
-
break;
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
if (parsed.force === true && parsed.resume === void 0) {
|
|
673
|
-
throw new BitfabError("--force only applies with --resume <experimentId>.");
|
|
674
|
-
}
|
|
675
|
-
if (parsed.resume !== void 0) {
|
|
676
|
-
const conflicting = RESUME_CONFLICTING_FLAGS.filter(
|
|
677
|
-
([key]) => parsed[key] !== void 0
|
|
678
|
-
).map(([, flag]) => flag);
|
|
679
|
-
if (conflicting.length > 0) {
|
|
680
|
-
throw new BitfabError(
|
|
681
|
-
`--resume reuses the traces, attempts, and graders experiment ${parsed.resume} started with, so it cannot be combined with ${conflicting.join(", ")}.`
|
|
682
|
-
);
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
if (parsed.traceIds !== void 0 && parsed.datasetIds !== void 0) {
|
|
686
|
-
throw new BitfabError(
|
|
687
|
-
"--trace-ids and --dataset-ids select different replay sources and cannot be used together."
|
|
688
|
-
);
|
|
689
|
-
}
|
|
690
|
-
if (parsed.codeChangePath !== void 0 && parsed.noCodeChange === true) {
|
|
691
|
-
throw new BitfabError(
|
|
692
|
-
"--code-change and --no-code-change cannot be used together."
|
|
693
|
-
);
|
|
694
|
-
}
|
|
695
|
-
return parsed;
|
|
696
|
-
}
|
|
697
|
-
function resolveRegistrationDatasetIds(options) {
|
|
698
|
-
if (options.datasetId !== void 0 && options.datasetIds !== void 0) {
|
|
699
|
-
throw new BitfabError(
|
|
700
|
-
"Replay registry options datasetId and datasetIds are the same selector: set one of them."
|
|
701
|
-
);
|
|
702
|
-
}
|
|
703
|
-
if (options.datasetId !== void 0) {
|
|
704
|
-
return [options.datasetId];
|
|
705
|
-
}
|
|
706
|
-
return options.datasetIds;
|
|
707
|
-
}
|
|
708
|
-
function describeSelection(options) {
|
|
709
|
-
if (options.traceIds !== void 0) {
|
|
710
|
-
return `${options.traceIds.length} traces`;
|
|
711
|
-
}
|
|
712
|
-
if (options.limit !== void 0) {
|
|
713
|
-
return `${options.limit} traces`;
|
|
714
|
-
}
|
|
715
|
-
const datasetCount = options.datasetIds?.length ?? 1;
|
|
716
|
-
return datasetCount > 1 ? `${datasetCount} datasets' traces` : "dataset traces";
|
|
717
|
-
}
|
|
718
|
-
function resolveTraceFunctionKey(registration) {
|
|
719
|
-
const wrappedKey = registration.fn._bitfabTraceFunctionKey;
|
|
720
|
-
const key = registration.traceFunctionKey ?? wrappedKey;
|
|
721
|
-
if (key === void 0) {
|
|
722
|
-
throw new BitfabError(
|
|
723
|
-
"Replay registry entry uses a plain function. Set traceFunctionKey to the key its production handler records."
|
|
724
|
-
);
|
|
725
|
-
}
|
|
726
|
-
return key;
|
|
727
|
-
}
|
|
728
|
-
async function defaultReadFile(path) {
|
|
729
|
-
const fs = await import("fs/promises").catch(() => null);
|
|
730
|
-
if (fs === null) {
|
|
731
|
-
throw new BitfabError(
|
|
732
|
-
"--code-change requires a runtime that can read local files."
|
|
733
|
-
);
|
|
734
|
-
}
|
|
735
|
-
return fs.readFile(path, "utf8");
|
|
736
|
-
}
|
|
737
|
-
async function loadCodeChange(path, readFile) {
|
|
738
|
-
if (path === void 0) {
|
|
739
|
-
return void 0;
|
|
740
|
-
}
|
|
741
|
-
const value = JSON.parse(await readFile(path));
|
|
742
|
-
if (typeof value.description !== "string" || !Array.isArray(value.files)) {
|
|
743
|
-
throw new BitfabError(
|
|
744
|
-
`Invalid --code-change file '${path}': expected { description, files }.`
|
|
745
|
-
);
|
|
746
|
-
}
|
|
747
|
-
return { description: value.description, files: value.files };
|
|
748
|
-
}
|
|
749
|
-
function parseMetadataTag(raw) {
|
|
750
|
-
const separator = raw.indexOf("=");
|
|
751
|
-
const key = raw.slice(0, separator).trim();
|
|
752
|
-
if (separator < 1 || key.length === 0) {
|
|
753
|
-
throw new BitfabError(
|
|
754
|
-
`Invalid --metadata '${raw}': expected a non-empty key=value pair.`
|
|
755
|
-
);
|
|
756
|
-
}
|
|
757
|
-
return [key, raw.slice(separator + 1)];
|
|
758
|
-
}
|
|
759
|
-
function parseParameter(raw) {
|
|
760
|
-
const separator = raw.indexOf("=");
|
|
761
|
-
const key = raw.slice(0, separator).trim();
|
|
762
|
-
if (separator < 1 || key.length === 0) {
|
|
763
|
-
throw new BitfabError(
|
|
764
|
-
`Invalid --param '${raw}': expected a non-empty name=value pair.`
|
|
765
|
-
);
|
|
766
|
-
}
|
|
767
|
-
const value = raw.slice(separator + 1);
|
|
768
|
-
try {
|
|
769
|
-
return [key, JSON.parse(value)];
|
|
770
|
-
} catch {
|
|
771
|
-
return [key, value];
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
async function loadParameters(path, rawParameters, readFile) {
|
|
775
|
-
let params = {};
|
|
776
|
-
if (path !== void 0) {
|
|
777
|
-
const value = JSON.parse(await readFile(path));
|
|
778
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
779
|
-
throw new BitfabError(
|
|
780
|
-
`Invalid --params file '${path}': expected a JSON object.`
|
|
781
|
-
);
|
|
782
|
-
}
|
|
783
|
-
params = { ...value };
|
|
784
|
-
}
|
|
785
|
-
for (const raw of rawParameters) {
|
|
786
|
-
const [key, value] = parseParameter(raw);
|
|
787
|
-
params[key] = value;
|
|
788
|
-
}
|
|
789
|
-
return params;
|
|
790
|
-
}
|
|
791
|
-
function valuesEqual(left, right) {
|
|
792
|
-
try {
|
|
793
|
-
return JSON.stringify(left) === JSON.stringify(right);
|
|
794
|
-
} catch {
|
|
795
|
-
return Object.is(left, right);
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
function renderSummary(pipeline, result, stderr) {
|
|
799
|
-
let same = 0;
|
|
800
|
-
let changed = 0;
|
|
801
|
-
let matched = 0;
|
|
802
|
-
let missed = 0;
|
|
803
|
-
let errors = 0;
|
|
804
|
-
let carriedOver = 0;
|
|
805
|
-
for (const item of result.items) {
|
|
806
|
-
if (item.carriedOver === true) {
|
|
807
|
-
carriedOver += 1;
|
|
808
|
-
continue;
|
|
809
|
-
}
|
|
810
|
-
if (item.error !== null) {
|
|
811
|
-
errors += 1;
|
|
812
|
-
continue;
|
|
813
|
-
}
|
|
814
|
-
const equal = valuesEqual(item.result, item.originalOutput);
|
|
815
|
-
if (item.ingestionType === "seeded") {
|
|
816
|
-
if (equal) {
|
|
817
|
-
matched += 1;
|
|
818
|
-
} else {
|
|
819
|
-
missed += 1;
|
|
820
|
-
}
|
|
821
|
-
} else if (equal) {
|
|
822
|
-
same += 1;
|
|
823
|
-
} else {
|
|
824
|
-
changed += 1;
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
stderr("\n\u2500\u2500\u2500 Summary \u2500\u2500\u2500");
|
|
828
|
-
stderr(` Pipeline: ${pipeline}`);
|
|
829
|
-
stderr(` Replayed: ${result.items.length - carriedOver}`);
|
|
830
|
-
if (carriedOver > 0) {
|
|
831
|
-
stderr(` Carried over from the earlier run: ${carriedOver}`);
|
|
832
|
-
}
|
|
833
|
-
if (result.attempts > 1) {
|
|
834
|
-
stderr(` Attempts: ${result.attempts}`);
|
|
835
|
-
}
|
|
836
|
-
if (same > 0 || changed > 0 || matched + missed === 0) {
|
|
837
|
-
stderr(` Same: ${same}`);
|
|
838
|
-
stderr(` Changed: ${changed}`);
|
|
839
|
-
}
|
|
840
|
-
if (matched > 0 || missed > 0) {
|
|
841
|
-
stderr(` Matched expected: ${matched}`);
|
|
842
|
-
stderr(` Missed expected: ${missed}`);
|
|
843
|
-
}
|
|
844
|
-
if (errors > 0) {
|
|
845
|
-
stderr(` Errors: ${errors}`);
|
|
846
|
-
}
|
|
847
|
-
stderr(`
|
|
848
|
-
${result.experimentUrl}`);
|
|
849
|
-
}
|
|
850
|
-
function countErroredItems(result) {
|
|
851
|
-
const replayed = result.items.filter((item) => item.carriedOver !== true);
|
|
852
|
-
return {
|
|
853
|
-
errored: replayed.filter((item) => item.error !== null).length,
|
|
854
|
-
replayed: replayed.length
|
|
855
|
-
};
|
|
856
|
-
}
|
|
857
|
-
function renderDryRun(pipeline, result, stderr) {
|
|
858
|
-
stderr("\n\u2500\u2500\u2500 Dry run \u2500\u2500\u2500");
|
|
859
|
-
stderr(` Pipeline: ${pipeline}`);
|
|
860
|
-
stderr(` Resolved: ${result.items.length} (nothing was executed)`);
|
|
861
|
-
for (const item of result.items) {
|
|
862
|
-
stderr(`
|
|
863
|
-
${item.originalTraceId}`);
|
|
864
|
-
stderr(` args: ${safeJson(item.input)}`);
|
|
865
|
-
}
|
|
866
|
-
if (result.experimentUrl !== null) {
|
|
867
|
-
stderr(`
|
|
868
|
-
${result.experimentUrl}`);
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
function safeJson(value) {
|
|
872
|
-
try {
|
|
873
|
-
return JSON.stringify(value) ?? String(value);
|
|
874
|
-
} catch {
|
|
875
|
-
return String(value);
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
function shellQuote(value) {
|
|
879
|
-
return /^[\w@%+=:,./-]+$/.test(value) ? value : `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
880
|
-
}
|
|
881
|
-
function resumeCommand(registryPath, args, experimentId) {
|
|
882
|
-
const carried = [
|
|
883
|
-
...args.mock === void 0 ? [] : ["--mock", args.mock],
|
|
884
|
-
...args.paramsPath === void 0 ? [] : ["--params", args.paramsPath],
|
|
885
|
-
...args.params.flatMap((param) => ["--param", param])
|
|
886
|
-
];
|
|
887
|
-
return [
|
|
888
|
-
"Resume with: bitfab-replay --registry",
|
|
889
|
-
registryPath === void 0 ? "<path>" : shellQuote(registryPath),
|
|
890
|
-
...[args.pipeline, ...carried, "--resume", experimentId].map(shellQuote)
|
|
891
|
-
].join(" ");
|
|
892
|
-
}
|
|
893
|
-
function reportReplayError(error, stderr) {
|
|
894
|
-
for (const item of error.items) {
|
|
895
|
-
stderr(
|
|
896
|
-
`${item.originalTraceId}: ${String(item.traceError ?? item.replayError ?? item.error)}`
|
|
897
|
-
);
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
var API_KEY_LINE_PREFIX = "@@bitfab:api-key ";
|
|
901
|
-
var PRINT_API_KEY_FLAG = "--print-api-key";
|
|
902
|
-
async function runReplayCli(registry, argv = typeof process === "undefined" ? [] : process.argv.slice(2), io = {}, registryPath) {
|
|
903
|
-
const stdout = io.stdout ?? console.log;
|
|
904
|
-
const stderr = io.stderr ?? console.error;
|
|
905
|
-
const printApiKey = argv.includes(PRINT_API_KEY_FLAG);
|
|
906
|
-
const args = parseReplayCliArgs(
|
|
907
|
-
registry,
|
|
908
|
-
argv.filter((arg) => arg !== PRINT_API_KEY_FLAG)
|
|
909
|
-
);
|
|
910
|
-
if (printApiKey) {
|
|
911
|
-
const client = registry[args.pipeline].client;
|
|
912
|
-
const apiKey = _resolvedApiKey(client);
|
|
913
|
-
const serviceUrl = _serviceUrl(client);
|
|
914
|
-
stdout(`${API_KEY_LINE_PREFIX}${JSON.stringify({ apiKey, serviceUrl })}`);
|
|
915
|
-
return null;
|
|
916
|
-
}
|
|
917
|
-
if (args.judgeAssertionsFlag) {
|
|
918
|
-
warnJudgeAssertionsDeprecated(stderr);
|
|
919
|
-
}
|
|
920
|
-
const registration = registry[args.pipeline];
|
|
921
|
-
const traceFunctionKey = resolveTraceFunctionKey(registration);
|
|
922
|
-
const readFile = io.readFile ?? defaultReadFile;
|
|
923
|
-
const params = await loadParameters(args.paramsPath, args.params, readFile);
|
|
924
|
-
const dynamicOptions = await registration.optionsFactory?.({ params });
|
|
925
|
-
const registrationOptions = {
|
|
926
|
-
...registration.options,
|
|
927
|
-
...dynamicOptions
|
|
928
|
-
};
|
|
929
|
-
const registrationDatasetIds = resolveRegistrationDatasetIds(registrationOptions);
|
|
930
|
-
if (registrationOptions.traceIds !== void 0 && registrationDatasetIds !== void 0) {
|
|
931
|
-
throw new BitfabError(
|
|
932
|
-
"Replay registry options traceIds and datasetIds select different sources and cannot be used together."
|
|
933
|
-
);
|
|
934
|
-
}
|
|
935
|
-
const selectedDatasetIds = args.datasetIds ?? registrationDatasetIds;
|
|
936
|
-
const codeChange = await loadCodeChange(args.codeChangePath, readFile);
|
|
937
|
-
let startedExperimentId;
|
|
938
|
-
const options = {
|
|
939
|
-
...registrationOptions,
|
|
940
|
-
...args.name === void 0 ? {} : { name: args.name },
|
|
941
|
-
...args.notes === void 0 ? {} : { notes: args.notes },
|
|
942
|
-
...args.metadata === void 0 ? {} : { metadata: args.metadata },
|
|
943
|
-
...args.attempts === void 0 ? {} : { attempts: args.attempts },
|
|
944
|
-
...args.maxConcurrency === void 0 ? {} : { maxConcurrency: args.maxConcurrency },
|
|
945
|
-
...args.experimentGroupId === void 0 ? {} : { experimentGroupId: args.experimentGroupId },
|
|
946
|
-
...args.experimentGroupName === void 0 ? {} : { experimentGroupName: args.experimentGroupName },
|
|
947
|
-
datasetId: void 0,
|
|
948
|
-
datasetIds: selectedDatasetIds,
|
|
949
|
-
...args.graderIds === void 0 ? {} : { graderIds: args.graderIds },
|
|
950
|
-
...args.onlyWithAssertions === void 0 ? {} : { onlyWithAssertions: args.onlyWithAssertions },
|
|
951
|
-
...args.skipAssertionJudging === void 0 ? {} : { skipAssertionJudging: args.skipAssertionJudging },
|
|
952
|
-
...args.mock === void 0 ? {} : { mock: args.mock },
|
|
953
|
-
...args.dbBranch === void 0 ? {} : {
|
|
954
|
-
dbBranch: args.dbBranch && registrationOptions.dbBranch !== void 0 && registrationOptions.dbBranch !== false ? registrationOptions.dbBranch : args.dbBranch
|
|
955
|
-
},
|
|
956
|
-
...args.noCodeChange === true ? { codeChangeDescription: null, codeChangeFiles: null } : {},
|
|
957
|
-
...args.dryRun === true ? { dryRun: true } : {},
|
|
958
|
-
...codeChange === void 0 ? {} : {
|
|
959
|
-
codeChangeDescription: codeChange.description,
|
|
960
|
-
codeChangeFiles: codeChange.files
|
|
961
|
-
},
|
|
962
|
-
onItemStart: reportReplayProgress,
|
|
963
|
-
onItemFinish: reportReplayProgress,
|
|
964
|
-
onExperimentStart: ({ experimentId, experimentUrl }) => {
|
|
965
|
-
startedExperimentId = experimentId;
|
|
966
|
-
stderr(`[replay] Experiment ${experimentId}: ${experimentUrl}`);
|
|
967
|
-
},
|
|
968
|
-
onInterrupt: ({ experimentId, signal, markedInterrupted }) => {
|
|
969
|
-
stderr(
|
|
970
|
-
`${describeReplayInterrupt(experimentId, markedInterrupted)} ${resumeCommand(registryPath, args, experimentId)}`
|
|
971
|
-
);
|
|
972
|
-
process.exit(INTERRUPT_EXIT_CODES[signal]);
|
|
973
|
-
}
|
|
974
|
-
};
|
|
975
|
-
withCliFlags(options, args.flags);
|
|
976
|
-
if (args.resume !== void 0) {
|
|
977
|
-
Object.assign(options, RESUME_CLEARED_OPTIONS, {
|
|
978
|
-
resume: args.resume,
|
|
979
|
-
...args.force === true ? { force: true } : {}
|
|
980
|
-
});
|
|
981
|
-
stderr(
|
|
982
|
-
`[replay] Resuming experiment ${args.resume} of "${traceFunctionKey}"...`
|
|
983
|
-
);
|
|
984
|
-
} else {
|
|
985
|
-
if (args.traceIds !== void 0) {
|
|
986
|
-
options.traceIds = args.traceIds;
|
|
987
|
-
options.datasetIds = void 0;
|
|
988
|
-
} else if (args.datasetIds !== void 0) {
|
|
989
|
-
options.traceIds = void 0;
|
|
990
|
-
}
|
|
991
|
-
const bound = args.limit ?? registrationOptions.limit;
|
|
992
|
-
options.limit = void 0;
|
|
993
|
-
if (options.traceIds !== void 0) {
|
|
994
|
-
if (bound !== void 0) {
|
|
995
|
-
options.traceIds = await boundTraceIds(
|
|
996
|
-
registration.client,
|
|
997
|
-
options.traceIds,
|
|
998
|
-
bound,
|
|
999
|
-
options.onlyWithAssertions === true
|
|
1000
|
-
);
|
|
1001
|
-
}
|
|
1002
|
-
} else if (options.datasetIds !== void 0) {
|
|
1003
|
-
if (bound !== void 0) {
|
|
1004
|
-
const pinned = await pinnedDatasetMembers(
|
|
1005
|
-
registration.client,
|
|
1006
|
-
options.datasetIds,
|
|
1007
|
-
bound,
|
|
1008
|
-
options.onlyWithAssertions === true
|
|
1009
|
-
);
|
|
1010
|
-
if (pinned !== void 0) {
|
|
1011
|
-
options.traceIds = pinned;
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
} else {
|
|
1015
|
-
options.limit = bound ?? 10;
|
|
1016
|
-
}
|
|
1017
|
-
const attemptsSuffix = options.attempts !== void 0 && options.attempts > 1 ? ` (${options.attempts} attempts each)` : "";
|
|
1018
|
-
stderr(
|
|
1019
|
-
`[replay] ${args.dryRun === true ? "Resolving inputs for" : "Replaying"} ${describeSelection(options)} from "${traceFunctionKey}"${attemptsSuffix}...`
|
|
1020
|
-
);
|
|
1021
|
-
}
|
|
1022
|
-
let result;
|
|
1023
|
-
try {
|
|
1024
|
-
result = await registration.client.replay(
|
|
1025
|
-
traceFunctionKey,
|
|
1026
|
-
registration.fn,
|
|
1027
|
-
options
|
|
1028
|
-
);
|
|
1029
|
-
} catch (error) {
|
|
1030
|
-
if (error instanceof ReplayError) {
|
|
1031
|
-
reportReplayError(error, stderr);
|
|
1032
|
-
}
|
|
1033
|
-
const experimentId = error instanceof ReplayError ? error.experimentId : startedExperimentId;
|
|
1034
|
-
if (experimentId !== void 0) {
|
|
1035
|
-
stderr(resumeCommand(registryPath, args, experimentId));
|
|
1036
|
-
}
|
|
1037
|
-
throw error;
|
|
1038
|
-
}
|
|
1039
|
-
if (args.dryRun === true) {
|
|
1040
|
-
renderDryRun(args.pipeline, result, stderr);
|
|
1041
|
-
} else {
|
|
1042
|
-
renderSummary(args.pipeline, result, stderr);
|
|
1043
|
-
}
|
|
1044
|
-
stdout(serializeReplayResult(result));
|
|
1045
|
-
if (result.items.length === 0) {
|
|
1046
|
-
throw new BitfabError(
|
|
1047
|
-
`No traces matched "${traceFunctionKey}", so nothing was replayed. Seed cases with --seed, or capture a trace first.`
|
|
1048
|
-
);
|
|
1049
|
-
}
|
|
1050
|
-
if (args.failOnError === true) {
|
|
1051
|
-
const { errored, replayed } = countErroredItems(result);
|
|
1052
|
-
if (errored > 0) {
|
|
1053
|
-
throw new BitfabError(
|
|
1054
|
-
`[replay] ${errored} of ${replayed} ${args.dryRun === true ? "resolved" : "replayed"} items errored; exiting 1 because of --fail-on-error`
|
|
1055
|
-
);
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
return result;
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
|
-
// src/registryCommand.ts
|
|
1062
|
-
import { register } from "tsx/esm/api";
|
|
1063
|
-
var isTypeScriptLoaderRegistered = false;
|
|
1064
|
-
async function parseRegistryCommandArgs(argv, usage2) {
|
|
1065
|
-
if (argv.some((value) => value === "--help" || value === "-h") && !argv.includes("--registry")) {
|
|
1066
|
-
throw new ReplayCliHelp(usage2);
|
|
1067
|
-
}
|
|
1068
|
-
const registryFlagIndex = argv.indexOf("--registry");
|
|
1069
|
-
const registryPath = argv[registryFlagIndex + 1];
|
|
1070
|
-
if (registryFlagIndex === -1 || registryPath === void 0 || registryPath.startsWith("--")) {
|
|
1071
|
-
throw new BitfabError(usage2);
|
|
1072
|
-
}
|
|
1073
|
-
const commandArgs = argv.filter(
|
|
1074
|
-
(_value, index) => index !== registryFlagIndex && index !== registryFlagIndex + 1
|
|
1075
|
-
);
|
|
1076
|
-
if (commandArgs.length === 0) {
|
|
1077
|
-
throw new BitfabError(usage2);
|
|
1078
|
-
}
|
|
1079
|
-
const { resolve } = await import("path");
|
|
1080
|
-
return { registryPath: resolve(registryPath), commandArgs };
|
|
1081
|
-
}
|
|
1082
|
-
async function importRegistry(path) {
|
|
1083
|
-
const { pathToFileURL } = await import("url");
|
|
1084
|
-
if (!isTypeScriptLoaderRegistered) {
|
|
1085
|
-
register();
|
|
1086
|
-
isTypeScriptLoaderRegistered = true;
|
|
1087
|
-
}
|
|
1088
|
-
try {
|
|
1089
|
-
return await import(pathToFileURL(path).href);
|
|
1090
|
-
} catch (error) {
|
|
1091
|
-
if (isModuleNotFoundError(error)) {
|
|
1092
|
-
throw new BitfabError(`${error.message}
|
|
1093
|
-
|
|
1094
|
-
${registryImportHint(path)}`);
|
|
1095
|
-
}
|
|
1096
|
-
throw error;
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
function isModuleNotFoundError(error) {
|
|
1100
|
-
const code = error?.code;
|
|
1101
|
-
return error instanceof Error && (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND");
|
|
1102
|
-
}
|
|
1103
|
-
function registryImportHint(path) {
|
|
1104
|
-
return [
|
|
1105
|
-
`The replay registry '${path}' could not load one of its imports.`,
|
|
1106
|
-
"A registry belongs in the package that builds the traced function's call and already depends on everything it imports (its tools, clients, and config), and bitfab-replay runs from that package's directory.",
|
|
1107
|
-
"When the traced function lives in a lower-level library that an app package calls, put the registry in the app package and add @bitfab/sdk to it. Copying the app's dependencies into the library is the wrong fix.",
|
|
1108
|
-
`See "When the traced function needs the app's dependencies" at https://docs.bitfab.ai/typescript-sdk.`
|
|
1109
|
-
].join("\n");
|
|
1110
|
-
}
|
|
1111
|
-
function resolveRegistry(moduleValue, path) {
|
|
1112
|
-
if (typeof moduleValue !== "object" || moduleValue === null) {
|
|
1113
|
-
throw new BitfabError(
|
|
1114
|
-
`Replay registry '${path}' must export a default registry.`
|
|
1115
|
-
);
|
|
1116
|
-
}
|
|
1117
|
-
const registry = moduleValue.default;
|
|
1118
|
-
if (typeof registry !== "object" || registry === null) {
|
|
1119
|
-
throw new BitfabError(
|
|
1120
|
-
`Replay registry '${path}' must export a default registry.`
|
|
1121
|
-
);
|
|
1122
|
-
}
|
|
1123
|
-
validateReplayRegistry(registry);
|
|
1124
|
-
return registry;
|
|
1125
|
-
}
|
|
1126
|
-
async function runRegistryMain(run, io = {}) {
|
|
1127
|
-
const stdout = io.stdout ?? console.log;
|
|
1128
|
-
const stderr = io.stderr ?? console.error;
|
|
1129
|
-
try {
|
|
1130
|
-
await run();
|
|
1131
|
-
return 0;
|
|
1132
|
-
} catch (error) {
|
|
1133
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1134
|
-
if (error instanceof ReplayCliHelp) {
|
|
1135
|
-
stdout(message);
|
|
1136
|
-
return 0;
|
|
1137
|
-
}
|
|
1138
|
-
if (error instanceof ReplayError) {
|
|
1139
|
-
stderr(`Experiment ${error.experimentId}: ${error.experimentUrl}`);
|
|
1140
|
-
}
|
|
1141
|
-
stderr(message);
|
|
1142
|
-
return 1;
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
async function isEntrypoint(moduleUrl) {
|
|
1146
|
-
const executablePath = process.argv[1];
|
|
1147
|
-
if (executablePath === void 0) {
|
|
1148
|
-
return false;
|
|
1149
|
-
}
|
|
1150
|
-
const [{ realpath }, { fileURLToPath }] = await Promise.all([
|
|
1151
|
-
import("fs/promises"),
|
|
1152
|
-
import("url")
|
|
1153
|
-
]);
|
|
1154
|
-
return await realpath(executablePath) === await realpath(fileURLToPath(moduleUrl));
|
|
1155
|
-
}
|
|
1156
|
-
function runIfEntrypoint(moduleUrl, main) {
|
|
1157
|
-
void isEntrypoint(moduleUrl).then((entrypoint) => {
|
|
1158
|
-
if (entrypoint) {
|
|
1159
|
-
void main().then((exitCode) => {
|
|
1160
|
-
process.exitCode = exitCode;
|
|
1161
|
-
});
|
|
1162
|
-
}
|
|
1163
|
-
});
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
export {
|
|
1167
|
-
runSeedCli,
|
|
1168
|
-
checkReplayCliArgs,
|
|
1169
|
-
runReplayCli,
|
|
1170
|
-
parseRegistryCommandArgs,
|
|
1171
|
-
importRegistry,
|
|
1172
|
-
resolveRegistry,
|
|
1173
|
-
runRegistryMain,
|
|
1174
|
-
runIfEntrypoint
|
|
1175
|
-
};
|
|
1176
|
-
//# sourceMappingURL=chunk-BRMGNMDO.js.map
|