@brainpilot/backend-core 0.0.9 → 0.0.11
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/app.d.ts.map +1 -1
- package/dist/app.js +200 -1
- package/dist/app.js.map +1 -1
- package/dist/config.d.ts +16 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +83 -2
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kb-builder.d.ts +120 -0
- package/dist/kb-builder.d.ts.map +1 -0
- package/dist/kb-builder.js +593 -0
- package/dist/kb-builder.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +13 -2
- package/dist/server.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-user knowledge-base build orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Spawns ``KnowledgeBase/scripts/build_kb.py --json`` and exposes:
|
|
5
|
+
* - POST /api/kb/build start a run (returns immediately)
|
|
6
|
+
* - GET /api/kb/status current run state
|
|
7
|
+
* - GET /api/kb/events SSE — live stream of NDJSON events from the child
|
|
8
|
+
* - POST /api/kb/cancel best-effort SIGTERM
|
|
9
|
+
*
|
|
10
|
+
* Only one build is allowed at a time across the whole process. A new POST
|
|
11
|
+
* while a run is active 409s — that's the right behaviour because every run
|
|
12
|
+
* mutates the same on-disk files and a second concurrent run would corrupt
|
|
13
|
+
* the OCRed_pdf.json ledger.
|
|
14
|
+
*
|
|
15
|
+
* The child's stdout is line-buffered and parsed as NDJSON. Anything that
|
|
16
|
+
* doesn't parse is forwarded as a `{event: "log", msg: <line>}` so stray
|
|
17
|
+
* prints from a dependency don't drop on the floor.
|
|
18
|
+
*/
|
|
19
|
+
import { spawn } from "node:child_process";
|
|
20
|
+
import { existsSync } from "node:fs";
|
|
21
|
+
import { resolve, join, dirname } from "node:path";
|
|
22
|
+
import { fileURLToPath } from "node:url";
|
|
23
|
+
const EVENT_BUFFER_CAP = 5_000; // last N events kept for the status panel
|
|
24
|
+
const SLOTS = { build: null, envSetup: null, modelSetup: null };
|
|
25
|
+
const BUS = { events: [], listeners: new Set() };
|
|
26
|
+
/** Back-compat re-export: some diagnostic code path may still consult a
|
|
27
|
+
* "primary" run. Prefer `slotByKey` in new code. */
|
|
28
|
+
function anyActiveSlot() {
|
|
29
|
+
return SLOTS.build ?? SLOTS.envSetup ?? SLOTS.modelSetup;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the Python interpreter the build pipeline subprocess will run as.
|
|
33
|
+
*
|
|
34
|
+
* Priority (kept in lock-step with packages/runtime/src/tools/kb/python.ts —
|
|
35
|
+
* we duplicate here rather than importing across packages, so backend-core
|
|
36
|
+
* stays free of a runtime dependency):
|
|
37
|
+
*
|
|
38
|
+
* 1. ``BP_KB_PYTHON`` — explicit override
|
|
39
|
+
* 2. ``<kbRoot>/.venv/bin/python`` — venv created by setup_env.sh
|
|
40
|
+
* (``<kbRoot>\.venv\Scripts\python.exe`` on Windows)
|
|
41
|
+
* 3. ``PYTHON`` env var
|
|
42
|
+
* 4. ``python3`` (Unix) / ``python`` (Windows) on PATH
|
|
43
|
+
*
|
|
44
|
+
* If `kbRoot` is undefined we still check `process.cwd()/KnowledgeBase/.venv`
|
|
45
|
+
* which catches the common "ran build_kb.py from the repo root" case.
|
|
46
|
+
*/
|
|
47
|
+
function pythonBin(kbRoot) {
|
|
48
|
+
const override = process.env.BP_KB_PYTHON?.trim();
|
|
49
|
+
if (override)
|
|
50
|
+
return override;
|
|
51
|
+
const rootCandidates = [];
|
|
52
|
+
if (kbRoot)
|
|
53
|
+
rootCandidates.push(kbRoot);
|
|
54
|
+
rootCandidates.push(join(process.cwd(), "KnowledgeBase"));
|
|
55
|
+
try {
|
|
56
|
+
rootCandidates.push(findKbRoot());
|
|
57
|
+
}
|
|
58
|
+
catch { /* findKbRoot fallback */ }
|
|
59
|
+
for (const root of rootCandidates) {
|
|
60
|
+
const venvPython = process.platform === "win32"
|
|
61
|
+
? join(root, ".venv", "Scripts", "python.exe")
|
|
62
|
+
: join(root, ".venv", "bin", "python");
|
|
63
|
+
if (existsSync(venvPython))
|
|
64
|
+
return venvPython;
|
|
65
|
+
}
|
|
66
|
+
const pyEnv = process.env.PYTHON?.trim();
|
|
67
|
+
if (pyEnv)
|
|
68
|
+
return pyEnv;
|
|
69
|
+
return process.platform === "win32" ? "python" : "python3";
|
|
70
|
+
}
|
|
71
|
+
function defaultBuildScript() {
|
|
72
|
+
if (process.env.BP_KB_BUILD_SCRIPT)
|
|
73
|
+
return process.env.BP_KB_BUILD_SCRIPT;
|
|
74
|
+
return join(findKbRoot(), "scripts", "build_kb.py");
|
|
75
|
+
}
|
|
76
|
+
function buildArgv(opts, script) {
|
|
77
|
+
const argv = [script, "--json"];
|
|
78
|
+
if (opts.kbRoot)
|
|
79
|
+
argv.push("--kb-root", opts.kbRoot);
|
|
80
|
+
if (opts.ocrApiKey)
|
|
81
|
+
argv.push("--ocr-api-key", opts.ocrApiKey);
|
|
82
|
+
if (opts.ocrConcurrency != null)
|
|
83
|
+
argv.push("--ocr-concurrency", String(opts.ocrConcurrency));
|
|
84
|
+
if (opts.ocrLimit != null)
|
|
85
|
+
argv.push("--ocr-limit", String(opts.ocrLimit));
|
|
86
|
+
if (opts.metaApiKey)
|
|
87
|
+
argv.push("--meta-api-key", opts.metaApiKey);
|
|
88
|
+
if (opts.metaBaseUrl)
|
|
89
|
+
argv.push("--meta-base-url", opts.metaBaseUrl);
|
|
90
|
+
if (opts.metaModel)
|
|
91
|
+
argv.push("--meta-model", opts.metaModel);
|
|
92
|
+
if (opts.hfMirror)
|
|
93
|
+
argv.push("--hf-mirror", opts.hfMirror);
|
|
94
|
+
if (opts.only && opts.only.length) {
|
|
95
|
+
argv.push("--only", ...opts.only);
|
|
96
|
+
}
|
|
97
|
+
else if (opts.skip && opts.skip.length) {
|
|
98
|
+
for (const s of opts.skip)
|
|
99
|
+
argv.push(`--skip-${s}`);
|
|
100
|
+
}
|
|
101
|
+
return argv;
|
|
102
|
+
}
|
|
103
|
+
function broadcast(ev) {
|
|
104
|
+
BUS.events.push(ev);
|
|
105
|
+
if (BUS.events.length > EVENT_BUFFER_CAP) {
|
|
106
|
+
BUS.events.splice(0, BUS.events.length - EVENT_BUFFER_CAP);
|
|
107
|
+
}
|
|
108
|
+
for (const l of BUS.listeners) {
|
|
109
|
+
try {
|
|
110
|
+
l(ev);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
/* one bad listener should not block the rest */
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function parseLine(line) {
|
|
118
|
+
const trimmed = line.trim();
|
|
119
|
+
if (!trimmed)
|
|
120
|
+
return null;
|
|
121
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
122
|
+
try {
|
|
123
|
+
const ev = JSON.parse(trimmed);
|
|
124
|
+
if (typeof ev.stage === "string" && typeof ev.event === "string")
|
|
125
|
+
return ev;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
/* fall through to log */
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
ts: new Date().toISOString(),
|
|
133
|
+
stage: "log",
|
|
134
|
+
event: "log",
|
|
135
|
+
msg: trimmed,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function pipeOutput(stream) {
|
|
139
|
+
let buf = "";
|
|
140
|
+
stream.setEncoding("utf8");
|
|
141
|
+
stream.on("data", (chunk) => {
|
|
142
|
+
buf += chunk;
|
|
143
|
+
let idx;
|
|
144
|
+
while ((idx = buf.indexOf("\n")) !== -1) {
|
|
145
|
+
const line = buf.slice(0, idx);
|
|
146
|
+
buf = buf.slice(idx + 1);
|
|
147
|
+
const ev = parseLine(line);
|
|
148
|
+
if (ev)
|
|
149
|
+
broadcast(ev);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
stream.on("end", () => {
|
|
153
|
+
if (buf.trim()) {
|
|
154
|
+
const ev = parseLine(buf);
|
|
155
|
+
if (ev)
|
|
156
|
+
broadcast(ev);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Bootstrap the KnowledgeBase Python venv via ``scripts/setup_env.py``.
|
|
162
|
+
*
|
|
163
|
+
* Owns SLOTS.envSetup. Can run concurrently with startKbModelSetup (they
|
|
164
|
+
* don't touch the same files); guarded against a second env-setup only.
|
|
165
|
+
* Build refuses to start while env-setup is running via its own check
|
|
166
|
+
* inside startKbBuild.
|
|
167
|
+
*
|
|
168
|
+
* The setup script is **pure stdlib Python**, so we deliberately do NOT
|
|
169
|
+
* resolve via the venv (which doesn't exist yet). Priority for the
|
|
170
|
+
* bootstrap interpreter:
|
|
171
|
+
* 1. ``opts.python`` — explicit override from the UI
|
|
172
|
+
* 2. ``BP_KB_PYTHON`` — env var (probably wrong here, but honour it)
|
|
173
|
+
* 3. ``python3`` / ``python`` on PATH
|
|
174
|
+
*/
|
|
175
|
+
export function startKbEnvSetup(opts = {}) {
|
|
176
|
+
if (SLOTS.envSetup && SLOTS.envSetup.doneAt == null) {
|
|
177
|
+
return { ok: false, message: "Python environment setup is already running" };
|
|
178
|
+
}
|
|
179
|
+
const root = opts.kbRoot ? resolve(opts.kbRoot) : findKbRoot();
|
|
180
|
+
const script = join(root, "scripts", "setup_env.py");
|
|
181
|
+
if (!existsSync(script)) {
|
|
182
|
+
return {
|
|
183
|
+
ok: false,
|
|
184
|
+
message: `setup_env.py not found at ${script}; is the KnowledgeBase tree intact?`,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const bootstrapPython = opts.python?.trim() ||
|
|
188
|
+
process.env.BP_KB_PYTHON?.trim() ||
|
|
189
|
+
(process.platform === "win32" ? "python" : "python3");
|
|
190
|
+
const argv = [script, "--kb-root", root, "--json"];
|
|
191
|
+
if (opts.reinstall)
|
|
192
|
+
argv.push("--reinstall");
|
|
193
|
+
if (opts.python)
|
|
194
|
+
argv.push("--python", opts.python);
|
|
195
|
+
let proc;
|
|
196
|
+
try {
|
|
197
|
+
proc = spawn(bootstrapPython, argv, {
|
|
198
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
199
|
+
env: { ...process.env, BP_KB_ROOT: root },
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
return {
|
|
204
|
+
ok: false,
|
|
205
|
+
message: `failed to spawn ${bootstrapPython}: ${err.message}`,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const slot = { startedAt: Date.now(), proc };
|
|
209
|
+
SLOTS.envSetup = slot;
|
|
210
|
+
broadcast({
|
|
211
|
+
ts: new Date().toISOString(),
|
|
212
|
+
stage: "setup-env",
|
|
213
|
+
event: "info",
|
|
214
|
+
msg: `spawned ${bootstrapPython} ${argv.join(" ")}`,
|
|
215
|
+
});
|
|
216
|
+
pipeOutput(proc.stdout);
|
|
217
|
+
pipeOutput(proc.stderr);
|
|
218
|
+
proc.on("error", (err) => {
|
|
219
|
+
broadcast({
|
|
220
|
+
ts: new Date().toISOString(),
|
|
221
|
+
stage: "setup-env",
|
|
222
|
+
event: "error",
|
|
223
|
+
msg: `failed to spawn: ${err.message}`,
|
|
224
|
+
});
|
|
225
|
+
slot.doneAt = Date.now();
|
|
226
|
+
slot.exitCode = null;
|
|
227
|
+
slot.error = err.message;
|
|
228
|
+
});
|
|
229
|
+
proc.on("exit", (code, signal) => {
|
|
230
|
+
broadcast({
|
|
231
|
+
ts: new Date().toISOString(),
|
|
232
|
+
stage: "setup-env",
|
|
233
|
+
event: code === 0 ? "done" : "error",
|
|
234
|
+
msg: code === 0
|
|
235
|
+
? "venv ready"
|
|
236
|
+
: `setup-env exited code=${code} signal=${signal ?? ""}`,
|
|
237
|
+
exit_code: code,
|
|
238
|
+
signal,
|
|
239
|
+
});
|
|
240
|
+
slot.doneAt = Date.now();
|
|
241
|
+
slot.exitCode = code;
|
|
242
|
+
});
|
|
243
|
+
return { ok: true, startedAt: slot.startedAt };
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Download the bge-m3 + bge-reranker-v2-m3 weights (~2.5 GB) via
|
|
247
|
+
* ``scripts/setup_models.py``. Runs in its own SLOTS.modelSetup slot so it
|
|
248
|
+
* can execute concurrently with setup_env — the two don't touch the same
|
|
249
|
+
* files. Reuses the venv's Python if present (needed for huggingface_hub);
|
|
250
|
+
* falls back to system Python otherwise (which will fail loudly if the
|
|
251
|
+
* package isn't there, letting the operator know to run env setup first).
|
|
252
|
+
*/
|
|
253
|
+
export function startKbModelSetup(opts = {}) {
|
|
254
|
+
if (SLOTS.modelSetup && SLOTS.modelSetup.doneAt == null) {
|
|
255
|
+
return { ok: false, message: "model download is already running" };
|
|
256
|
+
}
|
|
257
|
+
const root = opts.kbRoot ? resolve(opts.kbRoot) : findKbRoot();
|
|
258
|
+
const script = join(root, "scripts", "setup_models.py");
|
|
259
|
+
if (!existsSync(script)) {
|
|
260
|
+
return {
|
|
261
|
+
ok: false,
|
|
262
|
+
message: `setup_models.py not found at ${script}; is the KnowledgeBase tree intact?`,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
const py = pythonBin(root);
|
|
266
|
+
const argv = [script, "--kb-root", root, "--json"];
|
|
267
|
+
if (opts.hfMirror)
|
|
268
|
+
argv.push("--hf-mirror", opts.hfMirror);
|
|
269
|
+
let proc;
|
|
270
|
+
try {
|
|
271
|
+
proc = spawn(py, argv, {
|
|
272
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
273
|
+
env: { ...process.env, BP_KB_ROOT: root, BP_KB_PYTHON: py },
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
return {
|
|
278
|
+
ok: false,
|
|
279
|
+
message: `failed to spawn ${py}: ${err.message}`,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
const slot = { startedAt: Date.now(), proc };
|
|
283
|
+
SLOTS.modelSetup = slot;
|
|
284
|
+
broadcast({
|
|
285
|
+
ts: new Date().toISOString(),
|
|
286
|
+
stage: "setup-models",
|
|
287
|
+
event: "info",
|
|
288
|
+
msg: `spawned ${py} ${argv.join(" ")}`,
|
|
289
|
+
});
|
|
290
|
+
pipeOutput(proc.stdout);
|
|
291
|
+
pipeOutput(proc.stderr);
|
|
292
|
+
proc.on("error", (err) => {
|
|
293
|
+
broadcast({
|
|
294
|
+
ts: new Date().toISOString(),
|
|
295
|
+
stage: "setup-models",
|
|
296
|
+
event: "error",
|
|
297
|
+
msg: `failed to spawn: ${err.message}`,
|
|
298
|
+
});
|
|
299
|
+
slot.doneAt = Date.now();
|
|
300
|
+
slot.exitCode = null;
|
|
301
|
+
slot.error = err.message;
|
|
302
|
+
});
|
|
303
|
+
proc.on("exit", (code, signal) => {
|
|
304
|
+
broadcast({
|
|
305
|
+
ts: new Date().toISOString(),
|
|
306
|
+
stage: "setup-models",
|
|
307
|
+
event: code === 0 ? "done" : "error",
|
|
308
|
+
msg: code === 0
|
|
309
|
+
? "models ready"
|
|
310
|
+
: `setup-models exited code=${code} signal=${signal ?? ""}`,
|
|
311
|
+
exit_code: code,
|
|
312
|
+
signal,
|
|
313
|
+
});
|
|
314
|
+
slot.doneAt = Date.now();
|
|
315
|
+
slot.exitCode = code;
|
|
316
|
+
});
|
|
317
|
+
return { ok: true, startedAt: slot.startedAt };
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* One-click orchestration: start venv setup, then chain model download when
|
|
321
|
+
* (and only when) the venv build exits 0. huggingface_hub lives inside the
|
|
322
|
+
* venv, so kicking off model download before it exists would fail — the
|
|
323
|
+
* chaining is required, not just a nice-to-have.
|
|
324
|
+
*
|
|
325
|
+
* Emits a synthetic ``setup-full`` info event so the frontend can display a
|
|
326
|
+
* single "combined setup" banner and know when the whole thing is done.
|
|
327
|
+
*/
|
|
328
|
+
export function startKbFullSetup(opts = {}) {
|
|
329
|
+
if (SLOTS.envSetup && SLOTS.envSetup.doneAt == null) {
|
|
330
|
+
return { ok: false, message: "Python environment setup is already running" };
|
|
331
|
+
}
|
|
332
|
+
if (SLOTS.modelSetup && SLOTS.modelSetup.doneAt == null) {
|
|
333
|
+
return { ok: false, message: "model download is already running" };
|
|
334
|
+
}
|
|
335
|
+
broadcast({
|
|
336
|
+
ts: new Date().toISOString(),
|
|
337
|
+
stage: "setup-full",
|
|
338
|
+
event: "info",
|
|
339
|
+
msg: "starting Python env + model download (venv first, models will chain automatically on venv success)",
|
|
340
|
+
});
|
|
341
|
+
const envResult = startKbEnvSetup({
|
|
342
|
+
python: opts.python,
|
|
343
|
+
reinstall: opts.reinstall,
|
|
344
|
+
kbRoot: opts.kbRoot,
|
|
345
|
+
});
|
|
346
|
+
if (!envResult.ok)
|
|
347
|
+
return envResult;
|
|
348
|
+
// Chain: when the venv slot completes with code 0, kick off model download.
|
|
349
|
+
// We install this listener now so it fires exactly once — subsequent
|
|
350
|
+
// manual setupModels calls won't retrigger, and a non-zero venv exit
|
|
351
|
+
// leaves modelSetup untouched (letting the operator retry after fixing
|
|
352
|
+
// whatever broke venv creation).
|
|
353
|
+
const chain = (ev) => {
|
|
354
|
+
if (ev.stage !== "setup-env")
|
|
355
|
+
return;
|
|
356
|
+
if (ev.event !== "done" && ev.event !== "error")
|
|
357
|
+
return;
|
|
358
|
+
BUS.listeners.delete(chain);
|
|
359
|
+
if (ev.event === "error") {
|
|
360
|
+
broadcast({
|
|
361
|
+
ts: new Date().toISOString(),
|
|
362
|
+
stage: "setup-full",
|
|
363
|
+
event: "error",
|
|
364
|
+
msg: "venv setup failed; skipping model download",
|
|
365
|
+
});
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const modelResult = startKbModelSetup({
|
|
369
|
+
hfMirror: opts.hfMirror,
|
|
370
|
+
kbRoot: opts.kbRoot,
|
|
371
|
+
});
|
|
372
|
+
if (!modelResult.ok) {
|
|
373
|
+
broadcast({
|
|
374
|
+
ts: new Date().toISOString(),
|
|
375
|
+
stage: "setup-full",
|
|
376
|
+
event: "error",
|
|
377
|
+
msg: `venv done, but model download refused to start: ${modelResult.message}`,
|
|
378
|
+
});
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
// Second listener: once model download finishes, emit the setup-full done.
|
|
382
|
+
const doneChain = (ev2) => {
|
|
383
|
+
if (ev2.stage !== "setup-models")
|
|
384
|
+
return;
|
|
385
|
+
if (ev2.event !== "done" && ev2.event !== "error")
|
|
386
|
+
return;
|
|
387
|
+
BUS.listeners.delete(doneChain);
|
|
388
|
+
broadcast({
|
|
389
|
+
ts: new Date().toISOString(),
|
|
390
|
+
stage: "setup-full",
|
|
391
|
+
event: ev2.event,
|
|
392
|
+
msg: ev2.event === "done"
|
|
393
|
+
? "venv + models ready — knowledge base is ready to build"
|
|
394
|
+
: "model download failed after venv completed",
|
|
395
|
+
});
|
|
396
|
+
};
|
|
397
|
+
BUS.listeners.add(doneChain);
|
|
398
|
+
};
|
|
399
|
+
BUS.listeners.add(chain);
|
|
400
|
+
return envResult;
|
|
401
|
+
}
|
|
402
|
+
export function startKbBuild(opts = {}) {
|
|
403
|
+
if (SLOTS.build && SLOTS.build.doneAt == null) {
|
|
404
|
+
return { ok: false, message: "a knowledge-base build is already running" };
|
|
405
|
+
}
|
|
406
|
+
const script = defaultBuildScript();
|
|
407
|
+
if (!existsSync(script)) {
|
|
408
|
+
return {
|
|
409
|
+
ok: false,
|
|
410
|
+
message: `build script not found at ${script}; set BP_KB_BUILD_SCRIPT or ensure KnowledgeBase/ ships with the install.`,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
// If neither BP_KB_PYTHON nor the bundled venv is available, refuse rather
|
|
414
|
+
// than spawning a "python3 not found" failure halfway through. PATH-only
|
|
415
|
+
// python3 can still work, but the user's pip-installed deps then need to
|
|
416
|
+
// be system-wide — almost certainly not what they want.
|
|
417
|
+
const env = describeKbEnvironment(opts.kbRoot);
|
|
418
|
+
if (!process.env.BP_KB_PYTHON && !env.venvExists) {
|
|
419
|
+
return {
|
|
420
|
+
ok: false,
|
|
421
|
+
message: `Python venv not found at ${env.expectedVenvPath}. ` +
|
|
422
|
+
`Run "bash ${join(env.kbRoot, "scripts", "setup_env.sh")}" first ` +
|
|
423
|
+
`(or set BP_KB_PYTHON to point at a Python with the requirements.txt deps installed).`,
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
const argv = buildArgv(opts, script);
|
|
427
|
+
const py = pythonBin(opts.kbRoot);
|
|
428
|
+
const proc = spawn(py, argv, {
|
|
429
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
430
|
+
env: {
|
|
431
|
+
...process.env,
|
|
432
|
+
...(opts.kbRoot ? { BP_KB_ROOT: resolve(opts.kbRoot) } : {}),
|
|
433
|
+
// Make sure the build_kb.py orchestrator AND every stage it spawns
|
|
434
|
+
// share the same interpreter — without this, each `subprocess.run`
|
|
435
|
+
// call in build_kb.py would re-resolve via PATH and could land on a
|
|
436
|
+
// different python (e.g. system python3 without our deps installed).
|
|
437
|
+
BP_KB_PYTHON: py,
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
const slot = { startedAt: Date.now(), proc };
|
|
441
|
+
SLOTS.build = slot;
|
|
442
|
+
// Banner so the SSE consumer sees something immediately.
|
|
443
|
+
broadcast({
|
|
444
|
+
ts: new Date().toISOString(),
|
|
445
|
+
stage: "build",
|
|
446
|
+
event: "info",
|
|
447
|
+
msg: `spawned ${py} ${argv.join(" ")}`,
|
|
448
|
+
});
|
|
449
|
+
pipeOutput(proc.stdout);
|
|
450
|
+
pipeOutput(proc.stderr);
|
|
451
|
+
proc.on("error", (err) => {
|
|
452
|
+
broadcast({
|
|
453
|
+
ts: new Date().toISOString(),
|
|
454
|
+
stage: "build",
|
|
455
|
+
event: "error",
|
|
456
|
+
msg: `failed to spawn: ${err.message}`,
|
|
457
|
+
});
|
|
458
|
+
slot.doneAt = Date.now();
|
|
459
|
+
slot.exitCode = null;
|
|
460
|
+
slot.error = err.message;
|
|
461
|
+
});
|
|
462
|
+
proc.on("exit", (code, signal) => {
|
|
463
|
+
broadcast({
|
|
464
|
+
ts: new Date().toISOString(),
|
|
465
|
+
stage: "build",
|
|
466
|
+
event: code === 0 ? "done" : "error",
|
|
467
|
+
msg: code === 0
|
|
468
|
+
? "build finished successfully"
|
|
469
|
+
: `build exited code=${code} signal=${signal ?? ""}`,
|
|
470
|
+
exit_code: code,
|
|
471
|
+
signal,
|
|
472
|
+
});
|
|
473
|
+
slot.doneAt = Date.now();
|
|
474
|
+
slot.exitCode = code;
|
|
475
|
+
});
|
|
476
|
+
return { ok: true, startedAt: slot.startedAt };
|
|
477
|
+
}
|
|
478
|
+
function describeKbEnvironment(kbRoot) {
|
|
479
|
+
// Mirror defaultBuildScript()'s walk-up to find KnowledgeBase/.
|
|
480
|
+
const root = kbRoot ?? findKbRoot();
|
|
481
|
+
const expectedVenv = process.platform === "win32"
|
|
482
|
+
? join(root, ".venv", "Scripts", "python.exe")
|
|
483
|
+
: join(root, ".venv", "bin", "python");
|
|
484
|
+
const venvExists = existsSync(expectedVenv);
|
|
485
|
+
const python = pythonBin(root);
|
|
486
|
+
return {
|
|
487
|
+
python,
|
|
488
|
+
pythonIsVenv: python === expectedVenv,
|
|
489
|
+
venvExists,
|
|
490
|
+
expectedVenvPath: expectedVenv,
|
|
491
|
+
scriptsPresent: existsSync(join(root, "scripts", "build_kb.py")),
|
|
492
|
+
kbRoot: root,
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
export function findKbRoot() {
|
|
496
|
+
if (process.env.BP_KB_ROOT?.trim())
|
|
497
|
+
return resolve(process.env.BP_KB_ROOT.trim());
|
|
498
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
499
|
+
for (let i = 0; i < 8; i++) {
|
|
500
|
+
const candidate = join(dir, "KnowledgeBase");
|
|
501
|
+
if (existsSync(join(candidate, "scripts", "build_kb.py")))
|
|
502
|
+
return candidate;
|
|
503
|
+
const parent = dirname(dir);
|
|
504
|
+
if (parent === dir)
|
|
505
|
+
break;
|
|
506
|
+
dir = parent;
|
|
507
|
+
}
|
|
508
|
+
return join(process.cwd(), "KnowledgeBase");
|
|
509
|
+
}
|
|
510
|
+
export function getKbBuildStatus() {
|
|
511
|
+
const environment = describeKbEnvironment();
|
|
512
|
+
// "Active" now means "any slot is running" — build, env-setup, or model-
|
|
513
|
+
// download. The frontend already fans out on ev.stage for UI display, so
|
|
514
|
+
// this rollup is just used for the "reopened the panel mid-run" banner.
|
|
515
|
+
const active = anyActiveSlot();
|
|
516
|
+
const primary = SLOTS.build ?? SLOTS.envSetup ?? SLOTS.modelSetup;
|
|
517
|
+
if (!primary) {
|
|
518
|
+
return {
|
|
519
|
+
active: false,
|
|
520
|
+
startedAt: null,
|
|
521
|
+
finishedAt: null,
|
|
522
|
+
exitCode: undefined,
|
|
523
|
+
recentEvents: BUS.events.slice(-200),
|
|
524
|
+
environment,
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
return {
|
|
528
|
+
active: active !== null && active.doneAt == null,
|
|
529
|
+
startedAt: primary.startedAt,
|
|
530
|
+
finishedAt: primary.doneAt ?? null,
|
|
531
|
+
exitCode: primary.exitCode,
|
|
532
|
+
error: primary.error,
|
|
533
|
+
// Last ~200 events across every slot — the SSE stream is the primary
|
|
534
|
+
// surface; this is for a panel that has just been opened and wants
|
|
535
|
+
// enough context to replay the recent progress.
|
|
536
|
+
recentEvents: BUS.events.slice(-200),
|
|
537
|
+
environment,
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
export function subscribeKbBuild(listener) {
|
|
541
|
+
BUS.listeners.add(listener);
|
|
542
|
+
const history = [...BUS.events];
|
|
543
|
+
const done = anyActiveSlot() == null
|
|
544
|
+
? Promise.resolve()
|
|
545
|
+
: new Promise((resolve) => {
|
|
546
|
+
const check = () => {
|
|
547
|
+
const slot = anyActiveSlot();
|
|
548
|
+
if (slot == null || slot.doneAt != null) {
|
|
549
|
+
// "All idle" — no need to keep polling.
|
|
550
|
+
const anyRunning = (SLOTS.build && SLOTS.build.doneAt == null) ||
|
|
551
|
+
(SLOTS.envSetup && SLOTS.envSetup.doneAt == null) ||
|
|
552
|
+
(SLOTS.modelSetup && SLOTS.modelSetup.doneAt == null);
|
|
553
|
+
if (!anyRunning) {
|
|
554
|
+
resolve();
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
setTimeout(check, 200);
|
|
559
|
+
};
|
|
560
|
+
check();
|
|
561
|
+
});
|
|
562
|
+
return {
|
|
563
|
+
unsubscribe: () => BUS.listeners.delete(listener),
|
|
564
|
+
history,
|
|
565
|
+
done,
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
export function cancelKbBuild() {
|
|
569
|
+
// Cancel every active slot — the user has one "Cancel" button in the UI
|
|
570
|
+
// and expects it to stop whatever's currently running. Order: build
|
|
571
|
+
// first (most likely target), then setup jobs.
|
|
572
|
+
const targets = [];
|
|
573
|
+
if (SLOTS.build && SLOTS.build.doneAt == null)
|
|
574
|
+
targets.push(SLOTS.build);
|
|
575
|
+
if (SLOTS.envSetup && SLOTS.envSetup.doneAt == null)
|
|
576
|
+
targets.push(SLOTS.envSetup);
|
|
577
|
+
if (SLOTS.modelSetup && SLOTS.modelSetup.doneAt == null)
|
|
578
|
+
targets.push(SLOTS.modelSetup);
|
|
579
|
+
if (!targets.length) {
|
|
580
|
+
return { ok: false, message: "no active job to cancel" };
|
|
581
|
+
}
|
|
582
|
+
const errs = [];
|
|
583
|
+
for (const t of targets) {
|
|
584
|
+
try {
|
|
585
|
+
t.proc.kill("SIGTERM");
|
|
586
|
+
}
|
|
587
|
+
catch (err) {
|
|
588
|
+
errs.push(err.message);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
return errs.length ? { ok: false, message: errs.join("; ") } : { ok: true };
|
|
592
|
+
}
|
|
593
|
+
//# sourceMappingURL=kb-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-builder.js","sourceRoot":"","sources":["../src/kb-builder.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAMA,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAG5D,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAExE,MAAM,WAAW,kBAAmB,SAAQ,OAAO,CAAC,gBAAgB,CAAC;IACnE,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yEAAyE;IACzE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,kBAAuB,GAC/B,YAAY,CAgBd;AAED,wBAAsB,WAAW,CAC/B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,aAAa,CAAC,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAMA,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAG5D,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAExE,MAAM,WAAW,kBAAmB,SAAQ,OAAO,CAAC,gBAAgB,CAAC;IACnE,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yEAAyE;IACzE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,kBAAuB,GAC/B,YAAY,CAgBd;AAED,wBAAsB,WAAW,CAC/B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,aAAa,CAAC,CA4DxB"}
|
package/dist/server.js
CHANGED
|
@@ -7,7 +7,7 @@ import { pathToFileURL } from "node:url";
|
|
|
7
7
|
import { serve } from "@hono/node-server";
|
|
8
8
|
import { createApp } from "./app.js";
|
|
9
9
|
import { createOrchestrator } from "./create-orchestrator.js";
|
|
10
|
-
import { bootstrapEnvProvider } from "./config.js";
|
|
10
|
+
import { bootstrapEnvProvider, migrateLegacySettings } from "./config.js";
|
|
11
11
|
/**
|
|
12
12
|
* Build the orchestrator for a server from its options. Exposed (and pure) so
|
|
13
13
|
* the dataDir wiring is unit-testable without binding a socket.
|
|
@@ -47,12 +47,23 @@ export async function startServer(options = {}) {
|
|
|
47
47
|
serveWeb: options.serveWeb,
|
|
48
48
|
env: options.env,
|
|
49
49
|
});
|
|
50
|
+
const providerDataDir = options.dataDir ?? process.env.BP_DATA_DIR ?? "./brainpilot";
|
|
51
|
+
// #202: migrate a legacy plaintext-key settings.json (pre-rewrite layout) into
|
|
52
|
+
// providers.json before the env fallback runs — settings.json was a user's
|
|
53
|
+
// explicit config, so it outranks env projection. No-op once providers.json
|
|
54
|
+
// has any profile. Best-effort: a failure must not block startup.
|
|
55
|
+
try {
|
|
56
|
+
await migrateLegacySettings(providerDataDir);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// ignore — legacy migration is a convenience, not a startup gate
|
|
60
|
+
}
|
|
50
61
|
// #51: seed a provider profile from env on first launch so an env-only
|
|
51
62
|
// quick-start (ANTHROPIC_API_KEY etc.) surfaces an active provider in the Web
|
|
52
63
|
// UI. No-op once providers.json has any profile. Best-effort: a failure here
|
|
53
64
|
// must not block the server from starting.
|
|
54
65
|
try {
|
|
55
|
-
await bootstrapEnvProvider(
|
|
66
|
+
await bootstrapEnvProvider(providerDataDir, options.env);
|
|
56
67
|
}
|
|
57
68
|
catch {
|
|
58
69
|
// ignore — env projection is a convenience, not a startup gate
|