@cerefox/memory 1.0.0-beta.3 → 1.0.0-beta.4
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 +10 -9
- package/dist/bin/cerefox.js +688 -385
- package/dist/frontend/assets/{index-BZdKiyrT.js → index-6DS5ujj2.js} +30 -30
- package/dist/frontend/assets/{index-BZdKiyrT.js.map → index-6DS5ujj2.js.map} +1 -1
- package/dist/frontend/index.html +1 -1
- package/dist/server-assets/_shared/ef-meta/index.ts +1 -1
- package/dist/server-assets/_shared/embeddings/index.ts +51 -1
- package/dist/server-assets/_shared/embeddings/onnx-embedder.ts +229 -0
- package/dist/server-assets/_shared/mcp-tools/ingest.ts +16 -8
- package/dist/server-assets/_shared/mcp-tools/search.ts +3 -3
- package/dist/server-assets/db/rpcs.sql +5 -3
- package/dist/server-assets/db/schema.sql +1 -1
- package/dist/server-assets/supabase/functions/cerefox-ingest/index.ts +10 -0
- package/docs/guides/configuration.md +8 -3
- package/docs/guides/setup-local.md +34 -2
- package/package.json +6 -2
package/dist/bin/cerefox.js
CHANGED
|
@@ -7184,7 +7184,7 @@ var exports_meta = {};
|
|
|
7184
7184
|
__export(exports_meta, {
|
|
7185
7185
|
PKG_VERSION: () => PKG_VERSION
|
|
7186
7186
|
});
|
|
7187
|
-
var PKG_VERSION = "1.0.0-beta.
|
|
7187
|
+
var PKG_VERSION = "1.0.0-beta.4";
|
|
7188
7188
|
var init_meta = () => {};
|
|
7189
7189
|
|
|
7190
7190
|
// ../../node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.js
|
|
@@ -22959,6 +22959,55 @@ var init_client = __esm(() => {
|
|
|
22959
22959
|
init_cli_core();
|
|
22960
22960
|
});
|
|
22961
22961
|
|
|
22962
|
+
// ../../_shared/server-assets/index.ts
|
|
22963
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
22964
|
+
import { dirname as dirname2, join as join5 } from "node:path";
|
|
22965
|
+
import { fileURLToPath } from "node:url";
|
|
22966
|
+
import { cwd as processCwd2 } from "node:process";
|
|
22967
|
+
function moduleDir() {
|
|
22968
|
+
return dirname2(fileURLToPath(import.meta.url));
|
|
22969
|
+
}
|
|
22970
|
+
function bundledServerAssets(serverAssetsRoot) {
|
|
22971
|
+
return {
|
|
22972
|
+
schemaFile: join5(serverAssetsRoot, "db", "schema.sql"),
|
|
22973
|
+
rpcsFile: join5(serverAssetsRoot, "db", "rpcs.sql"),
|
|
22974
|
+
migrationsDir: join5(serverAssetsRoot, "db", "migrations"),
|
|
22975
|
+
functionsDir: join5(serverAssetsRoot, "supabase", "functions"),
|
|
22976
|
+
layout: "bundled"
|
|
22977
|
+
};
|
|
22978
|
+
}
|
|
22979
|
+
function sourceServerAssets(repoRoot) {
|
|
22980
|
+
const dbDir = join5(repoRoot, "src", "cerefox", "db");
|
|
22981
|
+
return {
|
|
22982
|
+
schemaFile: join5(dbDir, "schema.sql"),
|
|
22983
|
+
rpcsFile: join5(dbDir, "rpcs.sql"),
|
|
22984
|
+
migrationsDir: join5(dbDir, "migrations"),
|
|
22985
|
+
functionsDir: join5(repoRoot, "supabase", "functions"),
|
|
22986
|
+
layout: "source"
|
|
22987
|
+
};
|
|
22988
|
+
}
|
|
22989
|
+
function serverAssetsUsable(p) {
|
|
22990
|
+
return existsSync5(p.schemaFile) && existsSync5(p.rpcsFile);
|
|
22991
|
+
}
|
|
22992
|
+
function resolveServerAssets(opts = {}) {
|
|
22993
|
+
if (opts.assetsDir) {
|
|
22994
|
+
return { ...bundledServerAssets(opts.assetsDir), layout: "explicit" };
|
|
22995
|
+
}
|
|
22996
|
+
const here = opts.moduleDirOverride ?? moduleDir();
|
|
22997
|
+
const cwd = opts.cwd ?? processCwd2();
|
|
22998
|
+
const candidates = [
|
|
22999
|
+
bundledServerAssets(join5(here, "..", "server-assets")),
|
|
23000
|
+
sourceServerAssets(join5(here, "..", "..")),
|
|
23001
|
+
sourceServerAssets(cwd)
|
|
23002
|
+
];
|
|
23003
|
+
for (const candidate of candidates) {
|
|
23004
|
+
if (serverAssetsUsable(candidate))
|
|
23005
|
+
return candidate;
|
|
23006
|
+
}
|
|
23007
|
+
return sourceServerAssets(join5(here, "..", ".."));
|
|
23008
|
+
}
|
|
23009
|
+
var init_server_assets = () => {};
|
|
23010
|
+
|
|
22962
23011
|
// ../../node_modules/.bun/postgres@3.4.9/node_modules/postgres/src/query.js
|
|
22963
23012
|
function cachedError(xs) {
|
|
22964
23013
|
if (originCache.has(xs))
|
|
@@ -25193,127 +25242,296 @@ var init_bundled_docs = __esm(() => {
|
|
|
25193
25242
|
PACKAGE_ROOT = findPackageRoot();
|
|
25194
25243
|
});
|
|
25195
25244
|
|
|
25196
|
-
// ../../_shared/
|
|
25197
|
-
function
|
|
25198
|
-
|
|
25199
|
-
|
|
25200
|
-
|
|
25201
|
-
|
|
25245
|
+
// ../../_shared/compatibility/index.ts
|
|
25246
|
+
function compareSemver(a, b2) {
|
|
25247
|
+
const norm = (v) => v.split(/[.-]/).slice(0, 3).map((p) => Number.parseInt(p, 10)).map((n) => Number.isFinite(n) ? n : 0);
|
|
25248
|
+
const pa = norm(a);
|
|
25249
|
+
const pb = norm(b2);
|
|
25250
|
+
for (let i = 0;i < 3; i++) {
|
|
25251
|
+
const x = pa[i] ?? 0;
|
|
25252
|
+
const y = pb[i] ?? 0;
|
|
25253
|
+
if (x !== y)
|
|
25254
|
+
return x < y ? -1 : 1;
|
|
25255
|
+
}
|
|
25256
|
+
return 0;
|
|
25202
25257
|
}
|
|
25203
|
-
function
|
|
25204
|
-
|
|
25205
|
-
|
|
25206
|
-
|
|
25207
|
-
|
|
25258
|
+
function classifyCompat(deployed, min, bundled) {
|
|
25259
|
+
if (!deployed)
|
|
25260
|
+
return "unknown";
|
|
25261
|
+
if (compareSemver(deployed, min) < 0)
|
|
25262
|
+
return "below-min";
|
|
25263
|
+
if (bundled && compareSemver(deployed, bundled) < 0)
|
|
25264
|
+
return "above-min-but-old";
|
|
25265
|
+
return "ok";
|
|
25208
25266
|
}
|
|
25209
|
-
function
|
|
25210
|
-
const
|
|
25211
|
-
|
|
25212
|
-
let m;
|
|
25213
|
-
while ((m = re.exec(doc)) !== null) {
|
|
25214
|
-
out.push({ offset: m.index, level: m[1].length, text: rstripHash(m[2]).trim() });
|
|
25215
|
-
}
|
|
25216
|
-
return out;
|
|
25267
|
+
function aggregatorUrlFor(supabaseUrl) {
|
|
25268
|
+
const base = supabaseUrl.replace(/\/$/, "");
|
|
25269
|
+
return `${base}/functions/v1/cerefox-mcp/version?peers=true`;
|
|
25217
25270
|
}
|
|
25218
|
-
function
|
|
25219
|
-
const
|
|
25220
|
-
|
|
25221
|
-
|
|
25222
|
-
|
|
25223
|
-
|
|
25224
|
-
|
|
25225
|
-
|
|
25271
|
+
async function checkServerCompatibility(opts) {
|
|
25272
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
25273
|
+
const result = {
|
|
25274
|
+
schema: { deployed: null, min: COMPATIBILITY.minSchema, level: "unknown" },
|
|
25275
|
+
edgeFunctions: {
|
|
25276
|
+
deployed: null,
|
|
25277
|
+
min: COMPATIBILITY.minEdgeFunctions,
|
|
25278
|
+
level: "unknown",
|
|
25279
|
+
errors: []
|
|
25280
|
+
},
|
|
25281
|
+
blocking: false,
|
|
25282
|
+
efProbeSkipped: false
|
|
25283
|
+
};
|
|
25284
|
+
if (!opts.bearer) {
|
|
25285
|
+
result.efProbeSkipped = true;
|
|
25286
|
+
result.efSkipReason = "No CEREFOX_ACCESS_TOKEN configured; Edge Function version check skipped.";
|
|
25287
|
+
return result;
|
|
25226
25288
|
}
|
|
25227
|
-
|
|
25228
|
-
|
|
25229
|
-
|
|
25230
|
-
|
|
25231
|
-
|
|
25232
|
-
|
|
25233
|
-
|
|
25234
|
-
|
|
25235
|
-
|
|
25236
|
-
|
|
25237
|
-
|
|
25289
|
+
let agg = null;
|
|
25290
|
+
try {
|
|
25291
|
+
const ctrl = new AbortController;
|
|
25292
|
+
const timer2 = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 6000);
|
|
25293
|
+
try {
|
|
25294
|
+
const resp = await fetchImpl(opts.aggregatorUrl, {
|
|
25295
|
+
method: "GET",
|
|
25296
|
+
headers: { Authorization: `Bearer ${opts.bearer}`, apikey: opts.bearer },
|
|
25297
|
+
signal: ctrl.signal
|
|
25298
|
+
});
|
|
25299
|
+
if (resp.ok) {
|
|
25300
|
+
agg = await resp.json();
|
|
25301
|
+
} else {
|
|
25302
|
+
result.efProbeSkipped = true;
|
|
25303
|
+
result.efSkipReason = resp.status === 404 || resp.status === 405 ? "Edge Functions predate v0.8 (no /version route). Redeploy with `cerefox server deploy --functions-only` to enable version checks." : `Aggregator returned HTTP ${resp.status}; Edge Function version check skipped.`;
|
|
25304
|
+
}
|
|
25305
|
+
} finally {
|
|
25306
|
+
clearTimeout(timer2);
|
|
25238
25307
|
}
|
|
25239
|
-
|
|
25240
|
-
|
|
25308
|
+
} catch (err) {
|
|
25309
|
+
result.efProbeSkipped = true;
|
|
25310
|
+
result.efSkipReason = `Could not reach the version aggregator: ${err instanceof Error ? err.message : String(err)}`;
|
|
25241
25311
|
}
|
|
25242
|
-
if (
|
|
25243
|
-
|
|
25312
|
+
if (!agg)
|
|
25313
|
+
return result;
|
|
25314
|
+
result.schema.deployed = agg.schema ?? null;
|
|
25315
|
+
result.schema.level = classifyCompat(result.schema.deployed, COMPATIBILITY.minSchema, opts.bundledSchema);
|
|
25316
|
+
const versions = [];
|
|
25317
|
+
if (agg.version)
|
|
25318
|
+
versions.push(agg.version);
|
|
25319
|
+
for (const ef of agg.efs ?? [])
|
|
25320
|
+
versions.push(ef.version);
|
|
25321
|
+
result.edgeFunctions.errors = agg.errors ?? [];
|
|
25322
|
+
if (versions.length > 0) {
|
|
25323
|
+
const weakest = versions.reduce((lo, v) => compareSemver(v, lo) < 0 ? v : lo);
|
|
25324
|
+
result.edgeFunctions.deployed = weakest;
|
|
25325
|
+
result.edgeFunctions.level = classifyCompat(weakest, COMPATIBILITY.minEdgeFunctions, opts.bundledEf);
|
|
25326
|
+
} else {
|
|
25327
|
+
result.edgeFunctions.level = "unknown";
|
|
25328
|
+
result.efProbeSkipped = true;
|
|
25329
|
+
result.efSkipReason = "Aggregator reported no Edge Function versions; check skipped.";
|
|
25330
|
+
}
|
|
25331
|
+
result.blocking = result.schema.level === "below-min" || result.edgeFunctions.level === "below-min";
|
|
25332
|
+
return result;
|
|
25333
|
+
}
|
|
25334
|
+
var COMPATIBILITY;
|
|
25335
|
+
var init_compatibility = __esm(() => {
|
|
25336
|
+
COMPATIBILITY = {
|
|
25337
|
+
minSchema: "0.3.1",
|
|
25338
|
+
minEdgeFunctions: "0.6.0"
|
|
25339
|
+
};
|
|
25340
|
+
});
|
|
25341
|
+
|
|
25342
|
+
// ../../_shared/embeddings/onnx-embedder.ts
|
|
25343
|
+
var exports_onnx_embedder = {};
|
|
25344
|
+
__export(exports_onnx_embedder, {
|
|
25345
|
+
warmup: () => warmup,
|
|
25346
|
+
onnxEmbed: () => onnxEmbed,
|
|
25347
|
+
nomicPrefix: () => nomicPrefix,
|
|
25348
|
+
buildPrefixedInputs: () => buildPrefixedInputs,
|
|
25349
|
+
ONNX_MODEL_NAME: () => ONNX_MODEL_NAME,
|
|
25350
|
+
ONNX_MODEL_ID: () => ONNX_MODEL_ID,
|
|
25351
|
+
ONNX_MODEL_DTYPE: () => ONNX_MODEL_DTYPE,
|
|
25352
|
+
ONNX_MODEL_DIM: () => ONNX_MODEL_DIM,
|
|
25353
|
+
ONNX_MODEL_APPROX_MB: () => ONNX_MODEL_APPROX_MB
|
|
25354
|
+
});
|
|
25355
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync3 } from "node:fs";
|
|
25356
|
+
import { homedir as homedir5 } from "node:os";
|
|
25357
|
+
import { join as join8 } from "node:path";
|
|
25358
|
+
function nomicPrefix(role) {
|
|
25359
|
+
return role === "query" ? "search_query: " : "search_document: ";
|
|
25360
|
+
}
|
|
25361
|
+
function buildPrefixedInputs(texts, role) {
|
|
25362
|
+
const p = nomicPrefix(role);
|
|
25363
|
+
return texts.map((t) => p + t);
|
|
25364
|
+
}
|
|
25365
|
+
function getCacheDir() {
|
|
25366
|
+
const env4 = globalThis.process?.env ?? {};
|
|
25367
|
+
if (env4.CEREFOX_MODELS_DIR)
|
|
25368
|
+
return env4.CEREFOX_MODELS_DIR;
|
|
25369
|
+
return join8(homedir5(), ".cerefox", "models");
|
|
25370
|
+
}
|
|
25371
|
+
async function loadTransformers() {
|
|
25372
|
+
if (transformersModule)
|
|
25373
|
+
return transformersModule;
|
|
25374
|
+
const spec = "@huggingface/transformers";
|
|
25375
|
+
transformersModule = await import(spec);
|
|
25376
|
+
const dir = getCacheDir();
|
|
25377
|
+
if (!existsSync9(dir))
|
|
25378
|
+
mkdirSync3(dir, { recursive: true });
|
|
25379
|
+
transformersModule.env.cacheDir = dir;
|
|
25380
|
+
transformersModule.env.allowLocalModels = true;
|
|
25381
|
+
transformersModule.env.allowRemoteModels = true;
|
|
25382
|
+
return transformersModule;
|
|
25383
|
+
}
|
|
25384
|
+
function makeBar(pct, width = 20) {
|
|
25385
|
+
const clamped = Math.max(0, Math.min(100, pct));
|
|
25386
|
+
const filled = Math.round(clamped / 100 * width);
|
|
25387
|
+
return `[${"█".repeat(filled)}${"░".repeat(width - filled)}]`;
|
|
25388
|
+
}
|
|
25389
|
+
function l2Normalise(v) {
|
|
25390
|
+
let sum = 0;
|
|
25391
|
+
for (let i = 0;i < v.length; i++)
|
|
25392
|
+
sum += v[i] * v[i];
|
|
25393
|
+
const norm = Math.sqrt(sum);
|
|
25394
|
+
if (norm === 0)
|
|
25395
|
+
return v;
|
|
25396
|
+
const out = new Float32Array(v.length);
|
|
25397
|
+
for (let i = 0;i < v.length; i++)
|
|
25398
|
+
out[i] = v[i] / norm;
|
|
25244
25399
|
return out;
|
|
25245
25400
|
}
|
|
25246
|
-
function
|
|
25247
|
-
|
|
25248
|
-
|
|
25401
|
+
async function ensurePipeline() {
|
|
25402
|
+
if (pipelinePromise)
|
|
25403
|
+
return pipelinePromise;
|
|
25404
|
+
pipelinePromise = (async () => {
|
|
25405
|
+
const transformers = await loadTransformers();
|
|
25406
|
+
const mb = ONNX_MODEL_APPROX_MB;
|
|
25407
|
+
const fmt = (s) => s < 60 ? `${s}s` : `${Math.round(s / 60)}m`;
|
|
25408
|
+
process.stderr.write(`[cerefox-embed] loading "${ONNX_MODEL_NAME}" from HuggingFace (~${mb} MB; est. ${fmt(Math.round(mb * 8 / 50))}-${fmt(Math.round(mb * 8 / 10))} at 50-10 Mbps; first-run only)…
|
|
25409
|
+
`);
|
|
25410
|
+
const progressState = new Map;
|
|
25411
|
+
let activeFile = null;
|
|
25412
|
+
const isTty = !!process.stderr.isTTY;
|
|
25413
|
+
const RENDER_INTERVAL_MS = 250;
|
|
25414
|
+
const fmtMb = (n) => (n / 1024 / 1024).toFixed(1);
|
|
25415
|
+
const renderInPlace = (line) => {
|
|
25416
|
+
if (isTty)
|
|
25417
|
+
process.stderr.write(`\r\x1B[K${line}`);
|
|
25418
|
+
else
|
|
25419
|
+
process.stderr.write(`${line}
|
|
25420
|
+
`);
|
|
25421
|
+
};
|
|
25422
|
+
const finalizeLine = () => {
|
|
25423
|
+
if (isTty && activeFile !== null)
|
|
25424
|
+
process.stderr.write(`
|
|
25425
|
+
`);
|
|
25426
|
+
activeFile = null;
|
|
25427
|
+
};
|
|
25428
|
+
const progressCallback = (info3) => {
|
|
25429
|
+
const file = info3.file ?? info3.name ?? "(unknown)";
|
|
25430
|
+
const now = Date.now();
|
|
25431
|
+
if (info3.status === "progress") {
|
|
25432
|
+
const total = info3.total ?? 0;
|
|
25433
|
+
const loaded = info3.loaded ?? 0;
|
|
25434
|
+
if (total === 0 && loaded === 0)
|
|
25435
|
+
return;
|
|
25436
|
+
const prior = progressState.get(file) ?? {
|
|
25437
|
+
loaded: 0,
|
|
25438
|
+
total: 0,
|
|
25439
|
+
done: false,
|
|
25440
|
+
indeterminate: false,
|
|
25441
|
+
lastRenderAt: 0,
|
|
25442
|
+
lastRenderedPct: -1
|
|
25443
|
+
};
|
|
25444
|
+
const indeterminate = prior.indeterminate || prior.total > 0 && total > prior.total;
|
|
25445
|
+
const next = {
|
|
25446
|
+
loaded,
|
|
25447
|
+
total,
|
|
25448
|
+
done: false,
|
|
25449
|
+
indeterminate,
|
|
25450
|
+
lastRenderAt: prior.lastRenderAt,
|
|
25451
|
+
lastRenderedPct: prior.lastRenderedPct
|
|
25452
|
+
};
|
|
25453
|
+
if (activeFile !== file) {
|
|
25454
|
+
finalizeLine();
|
|
25455
|
+
activeFile = file;
|
|
25456
|
+
}
|
|
25457
|
+
if (indeterminate) {
|
|
25458
|
+
if (now - prior.lastRenderAt >= RENDER_INTERVAL_MS) {
|
|
25459
|
+
renderInPlace(`[cerefox-embed] [streaming...] ${fmtMb(loaded)} MB ${file}`);
|
|
25460
|
+
next.lastRenderAt = now;
|
|
25461
|
+
}
|
|
25462
|
+
} else if (total > 0) {
|
|
25463
|
+
const pct = Math.floor(loaded / total * 100);
|
|
25464
|
+
const stepBumped = pct >= prior.lastRenderedPct + 5;
|
|
25465
|
+
const timeBumped = isTty && now - prior.lastRenderAt >= RENDER_INTERVAL_MS && pct !== prior.lastRenderedPct;
|
|
25466
|
+
if (stepBumped || timeBumped) {
|
|
25467
|
+
renderInPlace(`[cerefox-embed] ${makeBar(pct)} ${pct.toString().padStart(3)}% ${fmtMb(loaded)}/${fmtMb(total)} MB ${file}`);
|
|
25468
|
+
next.lastRenderedPct = pct;
|
|
25469
|
+
next.lastRenderAt = now;
|
|
25470
|
+
}
|
|
25471
|
+
}
|
|
25472
|
+
progressState.set(file, next);
|
|
25473
|
+
} else if (info3.status === "done") {
|
|
25474
|
+
const prior = progressState.get(file);
|
|
25475
|
+
finalizeLine();
|
|
25476
|
+
const finalSize = prior && prior.loaded > 0 ? `${fmtMb(prior.loaded)} MB` : info3.total && info3.total > 0 ? `${fmtMb(info3.total)} MB` : "cached";
|
|
25477
|
+
process.stderr.write(`[cerefox-embed] ✓ ${file} (${finalSize})
|
|
25478
|
+
`);
|
|
25479
|
+
if (prior)
|
|
25480
|
+
progressState.set(file, { ...prior, done: true });
|
|
25481
|
+
}
|
|
25482
|
+
};
|
|
25483
|
+
const pipe = await transformers.pipeline("feature-extraction", ONNX_MODEL_ID, {
|
|
25484
|
+
dtype: ONNX_MODEL_DTYPE,
|
|
25485
|
+
progress_callback: progressCallback
|
|
25486
|
+
});
|
|
25487
|
+
process.stderr.write(`[cerefox-embed] embedder ready.
|
|
25488
|
+
`);
|
|
25489
|
+
return pipe;
|
|
25490
|
+
})();
|
|
25491
|
+
pipelinePromise.catch(() => {
|
|
25492
|
+
pipelinePromise = null;
|
|
25493
|
+
});
|
|
25494
|
+
return pipelinePromise;
|
|
25495
|
+
}
|
|
25496
|
+
async function warmup() {
|
|
25497
|
+
await ensurePipeline();
|
|
25498
|
+
}
|
|
25499
|
+
async function onnxEmbed(texts, role) {
|
|
25500
|
+
if (texts.length === 0)
|
|
25249
25501
|
return [];
|
|
25250
|
-
|
|
25251
|
-
|
|
25252
|
-
|
|
25253
|
-
|
|
25502
|
+
const pipeline = await ensurePipeline();
|
|
25503
|
+
const inputs = buildPrefixedInputs(texts, role);
|
|
25504
|
+
const out = await pipeline(inputs, { pooling: "mean", normalize: true });
|
|
25505
|
+
const dim2 = out.dims[out.dims.length - 1];
|
|
25506
|
+
if (dim2 !== ONNX_MODEL_DIM) {
|
|
25507
|
+
throw new Error(`OnnxEmbedder: expected dim=${ONNX_MODEL_DIM} (schema vector(768)), got ${dim2} from model`);
|
|
25254
25508
|
}
|
|
25255
|
-
const
|
|
25256
|
-
|
|
25257
|
-
|
|
25258
|
-
|
|
25259
|
-
const unit = (parts[i] ?? "") + (parts[i + 1] ?? "");
|
|
25260
|
-
if (unit === "")
|
|
25261
|
-
continue;
|
|
25262
|
-
if (cpLen(unit) > maxChunkChars)
|
|
25263
|
-
atoms.push(...hardSplitCp(unit, maxChunkChars));
|
|
25264
|
-
else
|
|
25265
|
-
atoms.push(unit);
|
|
25509
|
+
const vectors = [];
|
|
25510
|
+
for (let i = 0;i < inputs.length; i++) {
|
|
25511
|
+
const slice = out.data.slice(i * dim2, (i + 1) * dim2);
|
|
25512
|
+
vectors.push(Array.from(l2Normalise(slice)));
|
|
25266
25513
|
}
|
|
25267
|
-
|
|
25268
|
-
let buf = "";
|
|
25269
|
-
let bufCp = 0;
|
|
25270
|
-
let bufStart = 0;
|
|
25271
|
-
let offset = 0;
|
|
25272
|
-
const flush = () => {
|
|
25273
|
-
if (buf === "")
|
|
25274
|
-
return;
|
|
25275
|
-
const stack = activeHeadings(headings, bufStart);
|
|
25276
|
-
chunks.push({
|
|
25277
|
-
chunk_index: chunks.length,
|
|
25278
|
-
heading_path: stack.map((h) => h.text),
|
|
25279
|
-
heading_level: stack.length ? stack[stack.length - 1].level : 0,
|
|
25280
|
-
title: stack.length ? stack[stack.length - 1].text : "",
|
|
25281
|
-
content: buf,
|
|
25282
|
-
char_count: bufCp
|
|
25283
|
-
});
|
|
25284
|
-
buf = "";
|
|
25285
|
-
bufCp = 0;
|
|
25286
|
-
};
|
|
25287
|
-
for (const atom of atoms) {
|
|
25288
|
-
const cp = cpLen(atom);
|
|
25289
|
-
if (buf === "") {
|
|
25290
|
-
bufStart = offset;
|
|
25291
|
-
buf = atom;
|
|
25292
|
-
bufCp = cp;
|
|
25293
|
-
} else if (bufCp + cp <= maxChunkChars) {
|
|
25294
|
-
buf += atom;
|
|
25295
|
-
bufCp += cp;
|
|
25296
|
-
} else {
|
|
25297
|
-
flush();
|
|
25298
|
-
bufStart = offset;
|
|
25299
|
-
buf = atom;
|
|
25300
|
-
bufCp = cp;
|
|
25301
|
-
}
|
|
25302
|
-
offset += atom.length;
|
|
25303
|
-
}
|
|
25304
|
-
flush();
|
|
25305
|
-
return chunks;
|
|
25306
|
-
}
|
|
25307
|
-
function embeddingInputFor(docTitle, chunk) {
|
|
25308
|
-
const breadcrumb = chunk.heading_path.join(" > ");
|
|
25309
|
-
const head2 = breadcrumb ? `# ${docTitle}
|
|
25310
|
-
${breadcrumb}` : `# ${docTitle}`;
|
|
25311
|
-
return `${head2}
|
|
25312
|
-
${chunk.content}`;
|
|
25514
|
+
return vectors;
|
|
25313
25515
|
}
|
|
25314
|
-
var
|
|
25516
|
+
var ONNX_MODEL_ID = "nomic-ai/nomic-embed-text-v1.5", ONNX_MODEL_NAME = "nomic-embed-text-v1.5", ONNX_MODEL_DTYPE = "q8", ONNX_MODEL_DIM = 768, ONNX_MODEL_APPROX_MB = 130, transformersModule = null, pipelinePromise = null;
|
|
25517
|
+
var init_onnx_embedder = () => {};
|
|
25315
25518
|
|
|
25316
25519
|
// ../../_shared/embeddings/index.ts
|
|
25520
|
+
var exports_embeddings = {};
|
|
25521
|
+
__export(exports_embeddings, {
|
|
25522
|
+
resolveEmbedderKind: () => resolveEmbedderKind,
|
|
25523
|
+
openaiEmbeddingConfig: () => openaiEmbeddingConfig,
|
|
25524
|
+
getEmbedding: () => getEmbedding,
|
|
25525
|
+
embeddingMaxInputChars: () => embeddingMaxInputChars,
|
|
25526
|
+
embedBatch: () => embedBatch,
|
|
25527
|
+
capEmbeddingInput: () => capEmbeddingInput,
|
|
25528
|
+
activeEmbedderName: () => activeEmbedderName,
|
|
25529
|
+
OPENAI_MODEL: () => OPENAI_MODEL,
|
|
25530
|
+
OPENAI_EMBEDDING_URL: () => OPENAI_EMBEDDING_URL,
|
|
25531
|
+
EMBEDDING_DIMENSIONS: () => EMBEDDING_DIMENSIONS,
|
|
25532
|
+
EMBEDDING_BATCH_SIZE: () => EMBEDDING_BATCH_SIZE,
|
|
25533
|
+
DEFAULT_EMBED_MAX_INPUT_CHARS: () => DEFAULT_EMBED_MAX_INPUT_CHARS
|
|
25534
|
+
});
|
|
25317
25535
|
function openaiEmbeddingConfig() {
|
|
25318
25536
|
const env4 = globalThis.process?.env ?? {};
|
|
25319
25537
|
const base = env4.CEREFOX_OPENAI_BASE_URL?.replace(/\/+$/, "");
|
|
@@ -25340,7 +25558,22 @@ function capEmbeddingInput(text) {
|
|
|
25340
25558
|
console.warn(`[embeddings] truncated an embedding input: ${text.length} → ${cut.length} chars ` + `(cap CEREFOX_EMBED_MAX_INPUT_CHARS=${max}). The full content is stored and reconstructed ` + `untouched; only this chunk's embedding uses the prefix (degraded search for this chunk).`);
|
|
25341
25559
|
return cut;
|
|
25342
25560
|
}
|
|
25561
|
+
function resolveEmbedderKind() {
|
|
25562
|
+
const env4 = globalThis.process?.env ?? {};
|
|
25563
|
+
return env4.CEREFOX_EMBEDDER === "local" ? "local" : "openai";
|
|
25564
|
+
}
|
|
25565
|
+
function activeEmbedderName() {
|
|
25566
|
+
return resolveEmbedderKind() === "local" ? "nomic-embed-text-v1.5" : openaiEmbeddingConfig().model;
|
|
25567
|
+
}
|
|
25568
|
+
async function onnxModule() {
|
|
25569
|
+
return await Promise.resolve().then(() => (init_onnx_embedder(), exports_onnx_embedder));
|
|
25570
|
+
}
|
|
25343
25571
|
async function getEmbedding(text, apiKey) {
|
|
25572
|
+
if (resolveEmbedderKind() === "local") {
|
|
25573
|
+
const onnx = await onnxModule();
|
|
25574
|
+
const [vec] = await onnx.onnxEmbed([capEmbeddingInput(text)], "query");
|
|
25575
|
+
return vec;
|
|
25576
|
+
}
|
|
25344
25577
|
let lastError = null;
|
|
25345
25578
|
const cfg = openaiEmbeddingConfig();
|
|
25346
25579
|
const input = capEmbeddingInput(text);
|
|
@@ -25432,6 +25665,10 @@ async function embedBatchSingleCall(texts, apiKey) {
|
|
|
25432
25665
|
async function embedBatch(texts, apiKey, batchSize = EMBEDDING_BATCH_SIZE) {
|
|
25433
25666
|
if (texts.length === 0)
|
|
25434
25667
|
return [];
|
|
25668
|
+
if (resolveEmbedderKind() === "local") {
|
|
25669
|
+
const onnx = await onnxModule();
|
|
25670
|
+
return onnx.onnxEmbed(texts.map(capEmbeddingInput), "document");
|
|
25671
|
+
}
|
|
25435
25672
|
if (texts.length <= batchSize) {
|
|
25436
25673
|
return embedBatchSingleCall(texts, apiKey);
|
|
25437
25674
|
}
|
|
@@ -25446,6 +25683,126 @@ async function embedBatch(texts, apiKey, batchSize = EMBEDDING_BATCH_SIZE) {
|
|
|
25446
25683
|
}
|
|
25447
25684
|
var OPENAI_EMBEDDING_URL = "https://api.openai.com/v1/embeddings", OPENAI_MODEL = "text-embedding-3-small", EMBEDDING_DIMENSIONS = 768, DEFAULT_EMBED_MAX_INPUT_CHARS = 20000, EMBEDDING_MAX_RETRIES = 3, EMBEDDING_INITIAL_BACKOFF_MS = 500, EMBEDDING_BATCH_SIZE = 96;
|
|
25448
25685
|
|
|
25686
|
+
// ../../_shared/ingest/chunker.ts
|
|
25687
|
+
function cpLen(s) {
|
|
25688
|
+
let n = 0;
|
|
25689
|
+
for (const _ of s)
|
|
25690
|
+
n++;
|
|
25691
|
+
return n;
|
|
25692
|
+
}
|
|
25693
|
+
function rstripHash(s) {
|
|
25694
|
+
let i = s.length;
|
|
25695
|
+
while (i > 0 && s[i - 1] === "#")
|
|
25696
|
+
i--;
|
|
25697
|
+
return s.slice(0, i);
|
|
25698
|
+
}
|
|
25699
|
+
function findHeadings(doc) {
|
|
25700
|
+
const out = [];
|
|
25701
|
+
const re = /^(#{1,3})[ \t]+(.+)$/gm;
|
|
25702
|
+
let m;
|
|
25703
|
+
while ((m = re.exec(doc)) !== null) {
|
|
25704
|
+
out.push({ offset: m.index, level: m[1].length, text: rstripHash(m[2]).trim() });
|
|
25705
|
+
}
|
|
25706
|
+
return out;
|
|
25707
|
+
}
|
|
25708
|
+
function activeHeadings(headings, offset) {
|
|
25709
|
+
const stack = [];
|
|
25710
|
+
for (const h of headings) {
|
|
25711
|
+
if (h.offset > offset)
|
|
25712
|
+
break;
|
|
25713
|
+
while (stack.length && stack[stack.length - 1].level >= h.level)
|
|
25714
|
+
stack.pop();
|
|
25715
|
+
stack.push(h);
|
|
25716
|
+
}
|
|
25717
|
+
return stack;
|
|
25718
|
+
}
|
|
25719
|
+
function hardSplitCp(s, maxCp) {
|
|
25720
|
+
const out = [];
|
|
25721
|
+
let buf = "";
|
|
25722
|
+
let n = 0;
|
|
25723
|
+
for (const ch of s) {
|
|
25724
|
+
if (n >= maxCp) {
|
|
25725
|
+
out.push(buf);
|
|
25726
|
+
buf = "";
|
|
25727
|
+
n = 0;
|
|
25728
|
+
}
|
|
25729
|
+
buf += ch;
|
|
25730
|
+
n++;
|
|
25731
|
+
}
|
|
25732
|
+
if (buf)
|
|
25733
|
+
out.push(buf);
|
|
25734
|
+
return out;
|
|
25735
|
+
}
|
|
25736
|
+
function chunkMarkdown(text, maxChunkChars = 4000, _minChunkChars = 100) {
|
|
25737
|
+
const doc = text.trim();
|
|
25738
|
+
if (!doc)
|
|
25739
|
+
return [];
|
|
25740
|
+
if (cpLen(doc) <= maxChunkChars) {
|
|
25741
|
+
return [
|
|
25742
|
+
{ chunk_index: 0, heading_path: [], heading_level: 0, title: "", content: doc, char_count: cpLen(doc) }
|
|
25743
|
+
];
|
|
25744
|
+
}
|
|
25745
|
+
const headings = findHeadings(doc);
|
|
25746
|
+
const parts = doc.split(/(\n{2,})/);
|
|
25747
|
+
const atoms = [];
|
|
25748
|
+
for (let i = 0;i < parts.length; i += 2) {
|
|
25749
|
+
const unit = (parts[i] ?? "") + (parts[i + 1] ?? "");
|
|
25750
|
+
if (unit === "")
|
|
25751
|
+
continue;
|
|
25752
|
+
if (cpLen(unit) > maxChunkChars)
|
|
25753
|
+
atoms.push(...hardSplitCp(unit, maxChunkChars));
|
|
25754
|
+
else
|
|
25755
|
+
atoms.push(unit);
|
|
25756
|
+
}
|
|
25757
|
+
const chunks = [];
|
|
25758
|
+
let buf = "";
|
|
25759
|
+
let bufCp = 0;
|
|
25760
|
+
let bufStart = 0;
|
|
25761
|
+
let offset = 0;
|
|
25762
|
+
const flush = () => {
|
|
25763
|
+
if (buf === "")
|
|
25764
|
+
return;
|
|
25765
|
+
const stack = activeHeadings(headings, bufStart);
|
|
25766
|
+
chunks.push({
|
|
25767
|
+
chunk_index: chunks.length,
|
|
25768
|
+
heading_path: stack.map((h) => h.text),
|
|
25769
|
+
heading_level: stack.length ? stack[stack.length - 1].level : 0,
|
|
25770
|
+
title: stack.length ? stack[stack.length - 1].text : "",
|
|
25771
|
+
content: buf,
|
|
25772
|
+
char_count: bufCp
|
|
25773
|
+
});
|
|
25774
|
+
buf = "";
|
|
25775
|
+
bufCp = 0;
|
|
25776
|
+
};
|
|
25777
|
+
for (const atom of atoms) {
|
|
25778
|
+
const cp = cpLen(atom);
|
|
25779
|
+
if (buf === "") {
|
|
25780
|
+
bufStart = offset;
|
|
25781
|
+
buf = atom;
|
|
25782
|
+
bufCp = cp;
|
|
25783
|
+
} else if (bufCp + cp <= maxChunkChars) {
|
|
25784
|
+
buf += atom;
|
|
25785
|
+
bufCp += cp;
|
|
25786
|
+
} else {
|
|
25787
|
+
flush();
|
|
25788
|
+
bufStart = offset;
|
|
25789
|
+
buf = atom;
|
|
25790
|
+
bufCp = cp;
|
|
25791
|
+
}
|
|
25792
|
+
offset += atom.length;
|
|
25793
|
+
}
|
|
25794
|
+
flush();
|
|
25795
|
+
return chunks;
|
|
25796
|
+
}
|
|
25797
|
+
function embeddingInputFor(docTitle, chunk) {
|
|
25798
|
+
const breadcrumb = chunk.heading_path.join(" > ");
|
|
25799
|
+
const head2 = breadcrumb ? `# ${docTitle}
|
|
25800
|
+
${breadcrumb}` : `# ${docTitle}`;
|
|
25801
|
+
return `${head2}
|
|
25802
|
+
${chunk.content}`;
|
|
25803
|
+
}
|
|
25804
|
+
var CONTENT_FORMAT_BLIND_STITCH = 2;
|
|
25805
|
+
|
|
25449
25806
|
// ../../node_modules/.bun/underscore@1.13.8/node_modules/underscore/underscore-node-f.cjs
|
|
25450
25807
|
var require_underscore_node_f = __commonJS((exports) => {
|
|
25451
25808
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -32746,7 +33103,7 @@ var require_BufferList = __commonJS((exports, module) => {
|
|
|
32746
33103
|
this.head = this.tail = null;
|
|
32747
33104
|
this.length = 0;
|
|
32748
33105
|
};
|
|
32749
|
-
BufferList.prototype.join = function
|
|
33106
|
+
BufferList.prototype.join = function join10(s) {
|
|
32750
33107
|
if (this.length === 0)
|
|
32751
33108
|
return "";
|
|
32752
33109
|
var p = this.head;
|
|
@@ -54469,6 +54826,9 @@ async function handler4(supabase, args, ctx) {
|
|
|
54469
54826
|
const project_names_raw = args.project_names;
|
|
54470
54827
|
const source = args.source ?? "agent";
|
|
54471
54828
|
const metadata = args.metadata ?? null;
|
|
54829
|
+
if (metadata !== null && (typeof metadata !== "object" || Array.isArray(metadata))) {
|
|
54830
|
+
throw new McpInvalidParams('metadata must be a JSON object of key/value pairs, e.g. {"type":"note"} — not a string, number, or array');
|
|
54831
|
+
}
|
|
54472
54832
|
const update_if_exists = args.update_if_exists ?? false;
|
|
54473
54833
|
const author = args.author ?? "mcp-agent";
|
|
54474
54834
|
const author_type = "agent";
|
|
@@ -54481,7 +54841,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54481
54841
|
throw new McpInvalidParams("project_names must be a JSON array of strings; for a single project use project_name (string)");
|
|
54482
54842
|
}
|
|
54483
54843
|
const project_names = Array.isArray(project_names_raw) ? project_names_raw.filter((s) => typeof s === "string" && s.length > 0) : null;
|
|
54484
|
-
if (!ctx.openaiApiKey) {
|
|
54844
|
+
if (!ctx.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
54485
54845
|
throw new Error("OpenAI API key not configured. Set OPENAI_API_KEY (Edge Function) or CEREFOX_OPENAI_API_KEY (.env, local).");
|
|
54486
54846
|
}
|
|
54487
54847
|
const contentHash2 = await sha256hex(normalizeContent(content));
|
|
@@ -54503,7 +54863,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54503
54863
|
if (chunks2.length === 0)
|
|
54504
54864
|
throw new Error("Content produced no chunks");
|
|
54505
54865
|
const texts2 = chunks2.map((c2) => embeddingInputFor(title, c2));
|
|
54506
|
-
const embeddings2 = await embedBatch(texts2, ctx.openaiApiKey);
|
|
54866
|
+
const embeddings2 = await embedBatch(texts2, ctx.openaiApiKey ?? "");
|
|
54507
54867
|
const totalChars2 = chunks2.reduce((s, c2) => s + c2.char_count, 0);
|
|
54508
54868
|
const chunkData2 = chunks2.map((chunk, i) => ({
|
|
54509
54869
|
chunk_index: i,
|
|
@@ -54513,7 +54873,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54513
54873
|
content: chunk.content,
|
|
54514
54874
|
char_count: chunk.char_count,
|
|
54515
54875
|
embedding: embeddings2[i],
|
|
54516
|
-
embedder:
|
|
54876
|
+
embedder: activeEmbedderName()
|
|
54517
54877
|
}));
|
|
54518
54878
|
const { error: ingestErr2 } = await supabase.rpc("cerefox_ingest_document", {
|
|
54519
54879
|
p_document_id: existingDoc.id,
|
|
@@ -54561,7 +54921,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54561
54921
|
if (chunks2.length === 0)
|
|
54562
54922
|
throw new Error("Content produced no chunks");
|
|
54563
54923
|
const texts2 = chunks2.map((c2) => embeddingInputFor(title, c2));
|
|
54564
|
-
const embeddings2 = await embedBatch(texts2, ctx.openaiApiKey);
|
|
54924
|
+
const embeddings2 = await embedBatch(texts2, ctx.openaiApiKey ?? "");
|
|
54565
54925
|
const totalChars2 = chunks2.reduce((s, c2) => s + c2.char_count, 0);
|
|
54566
54926
|
const chunkData2 = chunks2.map((chunk, i) => ({
|
|
54567
54927
|
chunk_index: i,
|
|
@@ -54571,7 +54931,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54571
54931
|
content: chunk.content,
|
|
54572
54932
|
char_count: chunk.char_count,
|
|
54573
54933
|
embedding: embeddings2[i],
|
|
54574
|
-
embedder:
|
|
54934
|
+
embedder: activeEmbedderName()
|
|
54575
54935
|
}));
|
|
54576
54936
|
const { error: ingestErr2 } = await supabase.rpc("cerefox_ingest_document", {
|
|
54577
54937
|
p_document_id: existingDoc.id,
|
|
@@ -54613,7 +54973,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54613
54973
|
if (chunks.length === 0)
|
|
54614
54974
|
throw new Error("Content produced no chunks");
|
|
54615
54975
|
const texts = chunks.map((c2) => embeddingInputFor(title, c2));
|
|
54616
|
-
const embeddings = await embedBatch(texts, ctx.openaiApiKey);
|
|
54976
|
+
const embeddings = await embedBatch(texts, ctx.openaiApiKey ?? "");
|
|
54617
54977
|
const totalChars = chunks.reduce((s, c2) => s + c2.char_count, 0);
|
|
54618
54978
|
const chunkData = chunks.map((chunk, i) => ({
|
|
54619
54979
|
chunk_index: i,
|
|
@@ -54623,7 +54983,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54623
54983
|
content: chunk.content,
|
|
54624
54984
|
char_count: chunk.char_count,
|
|
54625
54985
|
embedding: embeddings[i],
|
|
54626
|
-
embedder:
|
|
54986
|
+
embedder: activeEmbedderName()
|
|
54627
54987
|
}));
|
|
54628
54988
|
const { data: ingestResult, error: ingestErr } = await supabase.rpc("cerefox_ingest_document", {
|
|
54629
54989
|
p_document_id: null,
|
|
@@ -54960,7 +55320,7 @@ async function handler9(supabase, args, ctx) {
|
|
|
54960
55320
|
}
|
|
54961
55321
|
if (!query?.trim())
|
|
54962
55322
|
throw new McpInvalidParams("query is required");
|
|
54963
|
-
if (mode !== "fts" && !ctx.openaiApiKey) {
|
|
55323
|
+
if (mode !== "fts" && !ctx.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
54964
55324
|
throw new Error("OpenAI API key not configured. Set OPENAI_API_KEY (Edge Function) or CEREFOX_OPENAI_API_KEY (.env, local).");
|
|
54965
55325
|
}
|
|
54966
55326
|
let projectId = null;
|
|
@@ -54971,7 +55331,7 @@ async function handler9(supabase, args, ctx) {
|
|
|
54971
55331
|
}
|
|
54972
55332
|
let embedding = null;
|
|
54973
55333
|
if (mode !== "fts") {
|
|
54974
|
-
embedding = await getEmbedding(query, ctx.openaiApiKey);
|
|
55334
|
+
embedding = await getEmbedding(query, ctx.openaiApiKey ?? "");
|
|
54975
55335
|
}
|
|
54976
55336
|
const metaFilterParam = metadata_filter && Object.keys(metadata_filter).length > 0 ? { p_metadata_filter: metadata_filter } : {};
|
|
54977
55337
|
let rpcName;
|
|
@@ -68266,6 +68626,7 @@ var exports_server = {};
|
|
|
68266
68626
|
__export(exports_server, {
|
|
68267
68627
|
buildServer: () => buildServer
|
|
68268
68628
|
});
|
|
68629
|
+
import { existsSync as existsSync12, readFileSync as readFileSync12 } from "node:fs";
|
|
68269
68630
|
function buildServer() {
|
|
68270
68631
|
const settings = loadSettings();
|
|
68271
68632
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
@@ -68314,21 +68675,36 @@ async function warnIfSchemaVersionMismatch(supabase) {
|
|
|
68314
68675
|
try {
|
|
68315
68676
|
const { data } = await supabase.rpc("cerefox_schema_version");
|
|
68316
68677
|
const deployed = typeof data === "string" ? data : null;
|
|
68317
|
-
if (deployed
|
|
68318
|
-
|
|
68678
|
+
if (!deployed)
|
|
68679
|
+
return;
|
|
68680
|
+
let bundled = null;
|
|
68681
|
+
try {
|
|
68682
|
+
const assets = resolveServerAssets();
|
|
68683
|
+
if (existsSync12(assets.schemaFile)) {
|
|
68684
|
+
const m = readFileSync12(assets.schemaFile, "utf8").match(SCHEMA_VERSION_RE2);
|
|
68685
|
+
bundled = m ? m[1] : null;
|
|
68686
|
+
}
|
|
68687
|
+
} catch {}
|
|
68688
|
+
if (!bundled)
|
|
68689
|
+
return;
|
|
68690
|
+
if (compareSemver(deployed, bundled) < 0) {
|
|
68691
|
+
process.stderr.write(`[cerefox-mcp] ⚠ schema version mismatch: this client bundles v${bundled} ` + `but the deployed schema is v${deployed}. Run \`cerefox server deploy\` ` + `to update it. Tools may behave unexpectedly until then.
|
|
68319
68692
|
`);
|
|
68320
68693
|
}
|
|
68321
68694
|
} catch {}
|
|
68322
68695
|
}
|
|
68323
|
-
var SERVER_NAME = "cerefox";
|
|
68696
|
+
var SERVER_NAME = "cerefox", SCHEMA_VERSION_RE2;
|
|
68324
68697
|
var init_server3 = __esm(() => {
|
|
68325
68698
|
init_server2();
|
|
68326
68699
|
init_stdio2();
|
|
68327
68700
|
init_types4();
|
|
68328
68701
|
init_dist4();
|
|
68702
|
+
init_compatibility();
|
|
68329
68703
|
init_config();
|
|
68704
|
+
init_server_assets();
|
|
68330
68705
|
init_mcp_tools();
|
|
68331
68706
|
init_meta();
|
|
68707
|
+
SCHEMA_VERSION_RE2 = /^--\s*@version:\s*(\S+)/m;
|
|
68332
68708
|
});
|
|
68333
68709
|
|
|
68334
68710
|
// src/bin/cerefox.ts
|
|
@@ -70166,58 +70542,11 @@ function registerDeleteProject(program2) {
|
|
|
70166
70542
|
// src/cli/commands/deploy-server.ts
|
|
70167
70543
|
init_cli_core();
|
|
70168
70544
|
init_config();
|
|
70545
|
+
init_server_assets();
|
|
70169
70546
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
70170
70547
|
import { existsSync as existsSync7 } from "node:fs";
|
|
70171
70548
|
import { readdirSync as readdirSync2 } from "node:fs";
|
|
70172
70549
|
|
|
70173
|
-
// ../../_shared/server-assets/index.ts
|
|
70174
|
-
import { existsSync as existsSync5 } from "node:fs";
|
|
70175
|
-
import { dirname as dirname2, join as join5 } from "node:path";
|
|
70176
|
-
import { fileURLToPath } from "node:url";
|
|
70177
|
-
import { cwd as processCwd2 } from "node:process";
|
|
70178
|
-
function moduleDir() {
|
|
70179
|
-
return dirname2(fileURLToPath(import.meta.url));
|
|
70180
|
-
}
|
|
70181
|
-
function bundledServerAssets(serverAssetsRoot) {
|
|
70182
|
-
return {
|
|
70183
|
-
schemaFile: join5(serverAssetsRoot, "db", "schema.sql"),
|
|
70184
|
-
rpcsFile: join5(serverAssetsRoot, "db", "rpcs.sql"),
|
|
70185
|
-
migrationsDir: join5(serverAssetsRoot, "db", "migrations"),
|
|
70186
|
-
functionsDir: join5(serverAssetsRoot, "supabase", "functions"),
|
|
70187
|
-
layout: "bundled"
|
|
70188
|
-
};
|
|
70189
|
-
}
|
|
70190
|
-
function sourceServerAssets(repoRoot) {
|
|
70191
|
-
const dbDir = join5(repoRoot, "src", "cerefox", "db");
|
|
70192
|
-
return {
|
|
70193
|
-
schemaFile: join5(dbDir, "schema.sql"),
|
|
70194
|
-
rpcsFile: join5(dbDir, "rpcs.sql"),
|
|
70195
|
-
migrationsDir: join5(dbDir, "migrations"),
|
|
70196
|
-
functionsDir: join5(repoRoot, "supabase", "functions"),
|
|
70197
|
-
layout: "source"
|
|
70198
|
-
};
|
|
70199
|
-
}
|
|
70200
|
-
function serverAssetsUsable(p) {
|
|
70201
|
-
return existsSync5(p.schemaFile) && existsSync5(p.rpcsFile);
|
|
70202
|
-
}
|
|
70203
|
-
function resolveServerAssets(opts = {}) {
|
|
70204
|
-
if (opts.assetsDir) {
|
|
70205
|
-
return { ...bundledServerAssets(opts.assetsDir), layout: "explicit" };
|
|
70206
|
-
}
|
|
70207
|
-
const here = opts.moduleDirOverride ?? moduleDir();
|
|
70208
|
-
const cwd = opts.cwd ?? processCwd2();
|
|
70209
|
-
const candidates = [
|
|
70210
|
-
bundledServerAssets(join5(here, "..", "server-assets")),
|
|
70211
|
-
sourceServerAssets(join5(here, "..", "..")),
|
|
70212
|
-
sourceServerAssets(cwd)
|
|
70213
|
-
];
|
|
70214
|
-
for (const candidate of candidates) {
|
|
70215
|
-
if (serverAssetsUsable(candidate))
|
|
70216
|
-
return candidate;
|
|
70217
|
-
}
|
|
70218
|
-
return sourceServerAssets(join5(here, "..", ".."));
|
|
70219
|
-
}
|
|
70220
|
-
|
|
70221
70550
|
// ../../_shared/db-deploy/index.ts
|
|
70222
70551
|
init_src();
|
|
70223
70552
|
import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync } from "node:fs";
|
|
@@ -74276,112 +74605,18 @@ init_cli_core();
|
|
|
74276
74605
|
|
|
74277
74606
|
// src/cli/util/checks.ts
|
|
74278
74607
|
init_meta();
|
|
74279
|
-
import { existsSync as
|
|
74280
|
-
import { homedir as
|
|
74281
|
-
import { join as
|
|
74608
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7, realpathSync, statSync as statSync2 } from "node:fs";
|
|
74609
|
+
import { homedir as homedir6 } from "node:os";
|
|
74610
|
+
import { join as join9 } from "node:path";
|
|
74282
74611
|
|
|
74283
74612
|
// ../../_shared/ef-meta/index.ts
|
|
74284
|
-
var EF_VERSION = "1.0.0-beta.
|
|
74613
|
+
var EF_VERSION = "1.0.0-beta.4";
|
|
74285
74614
|
|
|
74286
74615
|
// src/cli/util/checks.ts
|
|
74287
74616
|
init_config();
|
|
74288
74617
|
init_config();
|
|
74289
|
-
|
|
74290
|
-
|
|
74291
|
-
var COMPATIBILITY = {
|
|
74292
|
-
minSchema: "0.3.1",
|
|
74293
|
-
minEdgeFunctions: "0.6.0"
|
|
74294
|
-
};
|
|
74295
|
-
function compareSemver(a, b2) {
|
|
74296
|
-
const norm = (v) => v.split(/[.-]/).slice(0, 3).map((p) => Number.parseInt(p, 10)).map((n) => Number.isFinite(n) ? n : 0);
|
|
74297
|
-
const pa = norm(a);
|
|
74298
|
-
const pb = norm(b2);
|
|
74299
|
-
for (let i = 0;i < 3; i++) {
|
|
74300
|
-
const x = pa[i] ?? 0;
|
|
74301
|
-
const y = pb[i] ?? 0;
|
|
74302
|
-
if (x !== y)
|
|
74303
|
-
return x < y ? -1 : 1;
|
|
74304
|
-
}
|
|
74305
|
-
return 0;
|
|
74306
|
-
}
|
|
74307
|
-
function classifyCompat(deployed, min, bundled) {
|
|
74308
|
-
if (!deployed)
|
|
74309
|
-
return "unknown";
|
|
74310
|
-
if (compareSemver(deployed, min) < 0)
|
|
74311
|
-
return "below-min";
|
|
74312
|
-
if (bundled && compareSemver(deployed, bundled) < 0)
|
|
74313
|
-
return "above-min-but-old";
|
|
74314
|
-
return "ok";
|
|
74315
|
-
}
|
|
74316
|
-
function aggregatorUrlFor(supabaseUrl) {
|
|
74317
|
-
const base = supabaseUrl.replace(/\/$/, "");
|
|
74318
|
-
return `${base}/functions/v1/cerefox-mcp/version?peers=true`;
|
|
74319
|
-
}
|
|
74320
|
-
async function checkServerCompatibility(opts) {
|
|
74321
|
-
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
74322
|
-
const result = {
|
|
74323
|
-
schema: { deployed: null, min: COMPATIBILITY.minSchema, level: "unknown" },
|
|
74324
|
-
edgeFunctions: {
|
|
74325
|
-
deployed: null,
|
|
74326
|
-
min: COMPATIBILITY.minEdgeFunctions,
|
|
74327
|
-
level: "unknown",
|
|
74328
|
-
errors: []
|
|
74329
|
-
},
|
|
74330
|
-
blocking: false,
|
|
74331
|
-
efProbeSkipped: false
|
|
74332
|
-
};
|
|
74333
|
-
if (!opts.bearer) {
|
|
74334
|
-
result.efProbeSkipped = true;
|
|
74335
|
-
result.efSkipReason = "No CEREFOX_ACCESS_TOKEN configured; Edge Function version check skipped.";
|
|
74336
|
-
return result;
|
|
74337
|
-
}
|
|
74338
|
-
let agg = null;
|
|
74339
|
-
try {
|
|
74340
|
-
const ctrl = new AbortController;
|
|
74341
|
-
const timer2 = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 6000);
|
|
74342
|
-
try {
|
|
74343
|
-
const resp = await fetchImpl(opts.aggregatorUrl, {
|
|
74344
|
-
method: "GET",
|
|
74345
|
-
headers: { Authorization: `Bearer ${opts.bearer}`, apikey: opts.bearer },
|
|
74346
|
-
signal: ctrl.signal
|
|
74347
|
-
});
|
|
74348
|
-
if (resp.ok) {
|
|
74349
|
-
agg = await resp.json();
|
|
74350
|
-
} else {
|
|
74351
|
-
result.efProbeSkipped = true;
|
|
74352
|
-
result.efSkipReason = resp.status === 404 || resp.status === 405 ? "Edge Functions predate v0.8 (no /version route). Redeploy with `cerefox server deploy --functions-only` to enable version checks." : `Aggregator returned HTTP ${resp.status}; Edge Function version check skipped.`;
|
|
74353
|
-
}
|
|
74354
|
-
} finally {
|
|
74355
|
-
clearTimeout(timer2);
|
|
74356
|
-
}
|
|
74357
|
-
} catch (err) {
|
|
74358
|
-
result.efProbeSkipped = true;
|
|
74359
|
-
result.efSkipReason = `Could not reach the version aggregator: ${err instanceof Error ? err.message : String(err)}`;
|
|
74360
|
-
}
|
|
74361
|
-
if (!agg)
|
|
74362
|
-
return result;
|
|
74363
|
-
result.schema.deployed = agg.schema ?? null;
|
|
74364
|
-
result.schema.level = classifyCompat(result.schema.deployed, COMPATIBILITY.minSchema, opts.bundledSchema);
|
|
74365
|
-
const versions = [];
|
|
74366
|
-
if (agg.version)
|
|
74367
|
-
versions.push(agg.version);
|
|
74368
|
-
for (const ef of agg.efs ?? [])
|
|
74369
|
-
versions.push(ef.version);
|
|
74370
|
-
result.edgeFunctions.errors = agg.errors ?? [];
|
|
74371
|
-
if (versions.length > 0) {
|
|
74372
|
-
const weakest = versions.reduce((lo, v) => compareSemver(v, lo) < 0 ? v : lo);
|
|
74373
|
-
result.edgeFunctions.deployed = weakest;
|
|
74374
|
-
result.edgeFunctions.level = classifyCompat(weakest, COMPATIBILITY.minEdgeFunctions, opts.bundledEf);
|
|
74375
|
-
} else {
|
|
74376
|
-
result.edgeFunctions.level = "unknown";
|
|
74377
|
-
result.efProbeSkipped = true;
|
|
74378
|
-
result.efSkipReason = "Aggregator reported no Edge Function versions; check skipped.";
|
|
74379
|
-
}
|
|
74380
|
-
result.blocking = result.schema.level === "below-min" || result.edgeFunctions.level === "below-min";
|
|
74381
|
-
return result;
|
|
74382
|
-
}
|
|
74383
|
-
|
|
74384
|
-
// src/cli/util/checks.ts
|
|
74618
|
+
init_compatibility();
|
|
74619
|
+
init_server_assets();
|
|
74385
74620
|
function checkBinary() {
|
|
74386
74621
|
return {
|
|
74387
74622
|
name: "binary",
|
|
@@ -74432,7 +74667,7 @@ function checkConfig() {
|
|
|
74432
74667
|
hint: "Run `cerefox init` to bootstrap."
|
|
74433
74668
|
};
|
|
74434
74669
|
}
|
|
74435
|
-
if (!
|
|
74670
|
+
if (!existsSync10(envPath)) {
|
|
74436
74671
|
return {
|
|
74437
74672
|
name: "config",
|
|
74438
74673
|
status: "error",
|
|
@@ -74514,6 +74749,14 @@ async function checkSupabase() {
|
|
|
74514
74749
|
async function checkOpenAI() {
|
|
74515
74750
|
const settings = loadSettings();
|
|
74516
74751
|
if (!settings.openaiApiKey) {
|
|
74752
|
+
const { resolveEmbedderKind: resolveEmbedderKind2 } = await Promise.resolve().then(() => exports_embeddings);
|
|
74753
|
+
if (resolveEmbedderKind2() === "local") {
|
|
74754
|
+
return {
|
|
74755
|
+
name: "openai",
|
|
74756
|
+
status: "skipped",
|
|
74757
|
+
detail: "no key set — not needed (local embedder active; see the embedder check)."
|
|
74758
|
+
};
|
|
74759
|
+
}
|
|
74517
74760
|
return {
|
|
74518
74761
|
name: "openai",
|
|
74519
74762
|
status: "warn",
|
|
@@ -74560,7 +74803,7 @@ var SCHEMA_VERSION_RE = /^--\s*@version:\s*(\S+)/m;
|
|
|
74560
74803
|
function readBundledSchemaVersion() {
|
|
74561
74804
|
try {
|
|
74562
74805
|
const assets = resolveServerAssets();
|
|
74563
|
-
if (!
|
|
74806
|
+
if (!existsSync10(assets.schemaFile))
|
|
74564
74807
|
return null;
|
|
74565
74808
|
const m = readFileSync7(assets.schemaFile, "utf8").match(SCHEMA_VERSION_RE);
|
|
74566
74809
|
return m ? m[1] : null;
|
|
@@ -74630,6 +74873,46 @@ async function checkSchemaVersion() {
|
|
|
74630
74873
|
};
|
|
74631
74874
|
}
|
|
74632
74875
|
}
|
|
74876
|
+
var EMBEDDER_CHECK_NAME = "embedder";
|
|
74877
|
+
async function checkEmbedderMismatch() {
|
|
74878
|
+
const settings = loadSettings();
|
|
74879
|
+
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
74880
|
+
return { name: EMBEDDER_CHECK_NAME, status: "skipped", detail: "Supabase config missing; skipped." };
|
|
74881
|
+
}
|
|
74882
|
+
const { activeEmbedderName: activeEmbedderName2 } = await Promise.resolve().then(() => exports_embeddings);
|
|
74883
|
+
const active = activeEmbedderName2();
|
|
74884
|
+
try {
|
|
74885
|
+
const url = `${settings.supabaseUrl.replace(/\/$/, "")}/rest/v1/cerefox_chunks?version_id=is.null&embedder_primary=not.is.null&select=embedder_primary&limit=1000`;
|
|
74886
|
+
const resp = await fetch(url, {
|
|
74887
|
+
headers: { apikey: settings.supabaseKey, Authorization: `Bearer ${settings.supabaseKey}` }
|
|
74888
|
+
});
|
|
74889
|
+
if (!resp.ok) {
|
|
74890
|
+
return { name: EMBEDDER_CHECK_NAME, status: "skipped", detail: `chunk probe returned ${resp.status}; skipped.` };
|
|
74891
|
+
}
|
|
74892
|
+
const rows = await resp.json();
|
|
74893
|
+
const recorded = [...new Set(rows.map((r) => r.embedder_primary))];
|
|
74894
|
+
const stale = recorded.filter((r) => r !== active);
|
|
74895
|
+
if (stale.length === 0) {
|
|
74896
|
+
return {
|
|
74897
|
+
name: EMBEDDER_CHECK_NAME,
|
|
74898
|
+
status: "ok",
|
|
74899
|
+
detail: `configured "${active}"${recorded.length ? " — matches all existing chunks" : " (no embedded chunks yet)"}`
|
|
74900
|
+
};
|
|
74901
|
+
}
|
|
74902
|
+
return {
|
|
74903
|
+
name: EMBEDDER_CHECK_NAME,
|
|
74904
|
+
status: "warn",
|
|
74905
|
+
detail: `configured "${active}" but existing chunks were embedded with ${stale.map((r) => `"${r}"`).join(", ")} — semantic search across them is broken.`,
|
|
74906
|
+
hint: "Run `cerefox server reindex` to re-embed everything with the configured embedder."
|
|
74907
|
+
};
|
|
74908
|
+
} catch (err) {
|
|
74909
|
+
return {
|
|
74910
|
+
name: EMBEDDER_CHECK_NAME,
|
|
74911
|
+
status: "skipped",
|
|
74912
|
+
detail: `probe failed: ${err instanceof Error ? err.message : String(err)}`
|
|
74913
|
+
};
|
|
74914
|
+
}
|
|
74915
|
+
}
|
|
74633
74916
|
var CONTENT_FORMAT_CHECK_NAME = "content format";
|
|
74634
74917
|
async function checkContentFormat() {
|
|
74635
74918
|
const settings = loadSettings();
|
|
@@ -74679,7 +74962,7 @@ async function checkContentFormat() {
|
|
|
74679
74962
|
}
|
|
74680
74963
|
}
|
|
74681
74964
|
function hasCerefoxInJsonFile(path) {
|
|
74682
|
-
if (!
|
|
74965
|
+
if (!existsSync10(path))
|
|
74683
74966
|
return false;
|
|
74684
74967
|
try {
|
|
74685
74968
|
const parsed = JSON.parse(readFileSync7(path, "utf8"));
|
|
@@ -74690,10 +74973,10 @@ function hasCerefoxInJsonFile(path) {
|
|
|
74690
74973
|
}
|
|
74691
74974
|
}
|
|
74692
74975
|
function checkMcpConfigs() {
|
|
74693
|
-
const home =
|
|
74694
|
-
const claudeCodeUser =
|
|
74695
|
-
const claudeCodeProj =
|
|
74696
|
-
const claudeDesktop = process.platform === "darwin" ?
|
|
74976
|
+
const home = homedir6();
|
|
74977
|
+
const claudeCodeUser = join9(home, ".claude.json");
|
|
74978
|
+
const claudeCodeProj = join9(process.cwd(), ".mcp.json");
|
|
74979
|
+
const claudeDesktop = process.platform === "darwin" ? join9(home, "Library", "Application Support", "Claude", "claude_desktop_config.json") : process.platform === "win32" ? join9(process.env.APPDATA ?? "", "Claude", "claude_desktop_config.json") : join9(home, ".config", "Claude", "claude_desktop_config.json");
|
|
74697
74980
|
const found = [];
|
|
74698
74981
|
if (hasCerefoxInJsonFile(claudeCodeUser))
|
|
74699
74982
|
found.push("Claude Code (user)");
|
|
@@ -74716,10 +74999,10 @@ function checkMcpConfigs() {
|
|
|
74716
74999
|
};
|
|
74717
75000
|
}
|
|
74718
75001
|
function checkLegacyShadowEnv() {
|
|
74719
|
-
const home =
|
|
74720
|
-
const homeEnv =
|
|
74721
|
-
const cwdEnv =
|
|
74722
|
-
if (!
|
|
75002
|
+
const home = homedir6();
|
|
75003
|
+
const homeEnv = join9(home, USER_STATE_DIR_NAME, ".env");
|
|
75004
|
+
const cwdEnv = join9(process.cwd(), ".env");
|
|
75005
|
+
if (!existsSync10(homeEnv) || !existsSync10(cwdEnv))
|
|
74723
75006
|
return null;
|
|
74724
75007
|
try {
|
|
74725
75008
|
if (realpathSync(homeEnv) === realpathSync(cwdEnv))
|
|
@@ -74729,7 +75012,7 @@ function checkLegacyShadowEnv() {
|
|
|
74729
75012
|
name: "legacy env",
|
|
74730
75013
|
status: "skipped",
|
|
74731
75014
|
detail: `${cwdEnv} (shadowed by ~/.cerefox/.env)`,
|
|
74732
|
-
hint: "Shadowed by ~/.cerefox/.env and no longer read by anything (Python was removed at
|
|
75015
|
+
hint: "Shadowed by ~/.cerefox/.env and no longer read by anything (Python was removed at v1.0.0). Safe to delete."
|
|
74733
75016
|
};
|
|
74734
75017
|
}
|
|
74735
75018
|
async function checkPostgres() {
|
|
@@ -74866,6 +75149,7 @@ async function runAllChecks(opts = {}) {
|
|
|
74866
75149
|
{ name: "supabase", phase: "Probing Supabase Data API", run: () => checkSupabase() },
|
|
74867
75150
|
{ name: "openai", phase: "Probing OpenAI embeddings", run: () => checkOpenAI() },
|
|
74868
75151
|
{ name: "schema + RPCs", phase: "Reading schema + RPC version", run: () => checkSchemaVersion() },
|
|
75152
|
+
{ name: "embedder", phase: "Checking embedder consistency", run: () => checkEmbedderMismatch() },
|
|
74869
75153
|
{ name: "content format", phase: "Checking chunk reconstruction format", run: () => checkContentFormat() },
|
|
74870
75154
|
{ name: "edge functions", phase: "Probing Edge Function versions", run: () => checkEdgeFunctionsCompat() },
|
|
74871
75155
|
{ name: "postgres", phase: "Probing Postgres DDL endpoint", run: () => checkPostgres() },
|
|
@@ -75316,7 +75600,7 @@ class IngestionPipeline {
|
|
|
75316
75600
|
constructor(deps) {
|
|
75317
75601
|
this.db = new IngestionDbBridge(deps.supabase);
|
|
75318
75602
|
this.apiKey = deps.openAiApiKey;
|
|
75319
|
-
this.embedderModel = deps.embedderModel ??
|
|
75603
|
+
this.embedderModel = deps.embedderModel ?? activeEmbedderName();
|
|
75320
75604
|
this.settings = { ...loadPipelineSettings(), ...deps.settings ?? {} };
|
|
75321
75605
|
}
|
|
75322
75606
|
async ingestText(opts) {
|
|
@@ -75681,7 +75965,7 @@ async function action18(path, options) {
|
|
|
75681
75965
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
75682
75966
|
throw userError("Supabase credentials not configured — run `cerefox init` first.");
|
|
75683
75967
|
}
|
|
75684
|
-
if (!settings.openaiApiKey) {
|
|
75968
|
+
if (!settings.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
75685
75969
|
throw userError("OPENAI_API_KEY not set — required for embeddings during ingest.");
|
|
75686
75970
|
}
|
|
75687
75971
|
const supabase = createClient(settings.supabaseUrl, settings.supabaseKey, {
|
|
@@ -75744,7 +76028,7 @@ init_cli_core();
|
|
|
75744
76028
|
init_config();
|
|
75745
76029
|
var import_cli_progress = __toESM(require_cli_progress(), 1);
|
|
75746
76030
|
import { readdirSync as readdirSync4, statSync as statSync3 } from "node:fs";
|
|
75747
|
-
import { basename as basename3, extname as extname4, join as
|
|
76031
|
+
import { basename as basename3, extname as extname4, join as join10 } from "node:path";
|
|
75748
76032
|
function walk(dir, extensions) {
|
|
75749
76033
|
let entries;
|
|
75750
76034
|
try {
|
|
@@ -75754,7 +76038,7 @@ function walk(dir, extensions) {
|
|
|
75754
76038
|
}
|
|
75755
76039
|
const files = [];
|
|
75756
76040
|
for (const name of entries) {
|
|
75757
|
-
const full =
|
|
76041
|
+
const full = join10(dir, name);
|
|
75758
76042
|
let stat;
|
|
75759
76043
|
try {
|
|
75760
76044
|
stat = statSync3(full);
|
|
@@ -75788,7 +76072,7 @@ async function action19(dir, options) {
|
|
|
75788
76072
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
75789
76073
|
throw userError("Supabase credentials not configured — run `cerefox init` first.");
|
|
75790
76074
|
}
|
|
75791
|
-
if (!settings.openaiApiKey) {
|
|
76075
|
+
if (!settings.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
75792
76076
|
throw userError("OPENAI_API_KEY not set — required for embeddings during ingest.");
|
|
75793
76077
|
}
|
|
75794
76078
|
const supabase = createClient(settings.supabaseUrl, settings.supabaseKey, {
|
|
@@ -75851,19 +76135,20 @@ function registerIngestDir(program2) {
|
|
|
75851
76135
|
// src/cli/commands/init.ts
|
|
75852
76136
|
init_cli_core();
|
|
75853
76137
|
init_config();
|
|
76138
|
+
init_compatibility();
|
|
75854
76139
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
75855
76140
|
import {
|
|
75856
76141
|
chmodSync,
|
|
75857
76142
|
copyFileSync as copyFileSync2,
|
|
75858
|
-
existsSync as
|
|
75859
|
-
mkdirSync as
|
|
76143
|
+
existsSync as existsSync11,
|
|
76144
|
+
mkdirSync as mkdirSync4,
|
|
75860
76145
|
readFileSync as readFileSync11,
|
|
75861
76146
|
writeFileSync as writeFileSync4
|
|
75862
76147
|
} from "node:fs";
|
|
75863
|
-
import { homedir as
|
|
75864
|
-
import { dirname as dirname4, join as
|
|
76148
|
+
import { homedir as homedir7 } from "node:os";
|
|
76149
|
+
import { dirname as dirname4, join as join11 } from "node:path";
|
|
75865
76150
|
async function readConfigFile(path) {
|
|
75866
|
-
if (!
|
|
76151
|
+
if (!existsSync11(path)) {
|
|
75867
76152
|
throw userError(`--config file not found: ${path}`);
|
|
75868
76153
|
}
|
|
75869
76154
|
let parsed;
|
|
@@ -76165,7 +76450,7 @@ async function postWriteLifecycle(envPath, options) {
|
|
|
76165
76450
|
println(c.dim(` Config in effect: ${envPath}`));
|
|
76166
76451
|
}
|
|
76167
76452
|
function writeAnswersTo(target, answers) {
|
|
76168
|
-
|
|
76453
|
+
mkdirSync4(dirname4(target), { recursive: true });
|
|
76169
76454
|
writeFileSync4(target, buildEnvFile(answers), "utf8");
|
|
76170
76455
|
if (process.platform !== "win32") {
|
|
76171
76456
|
try {
|
|
@@ -76176,12 +76461,12 @@ function writeAnswersTo(target, answers) {
|
|
|
76176
76461
|
}
|
|
76177
76462
|
}
|
|
76178
76463
|
async function action21(options) {
|
|
76179
|
-
const homeEnv =
|
|
76180
|
-
const cwdEnv =
|
|
76464
|
+
const homeEnv = join11(homedir7(), USER_STATE_DIR_NAME, ".env");
|
|
76465
|
+
const cwdEnv = join11(process.cwd(), ".env");
|
|
76181
76466
|
const explicitDir = (process.env.CEREFOX_CONFIG_DIR ?? "").trim();
|
|
76182
76467
|
if (explicitDir) {
|
|
76183
76468
|
const target2 = resolveEnvFile();
|
|
76184
|
-
if (
|
|
76469
|
+
if (existsSync11(target2) && !options.force) {
|
|
76185
76470
|
println(c.yellow(`⚠ Config already exists at ${target2}.`));
|
|
76186
76471
|
const ok2 = await confirm("Overwrite?", true);
|
|
76187
76472
|
if (!ok2) {
|
|
@@ -76203,7 +76488,7 @@ async function action21(options) {
|
|
|
76203
76488
|
await postWriteLifecycle(target2, options);
|
|
76204
76489
|
return;
|
|
76205
76490
|
}
|
|
76206
|
-
if (
|
|
76491
|
+
if (existsSync11(homeEnv) && !options.force) {
|
|
76207
76492
|
println(c.yellow(`⚠ Config already exists at ${homeEnv}.`));
|
|
76208
76493
|
const ok2 = await confirm("Overwrite?", true);
|
|
76209
76494
|
if (!ok2) {
|
|
@@ -76224,12 +76509,12 @@ async function action21(options) {
|
|
|
76224
76509
|
await postWriteLifecycle(homeEnv, options);
|
|
76225
76510
|
return;
|
|
76226
76511
|
}
|
|
76227
|
-
if (
|
|
76512
|
+
if (existsSync11(cwdEnv) && !options.force && !options.config) {
|
|
76228
76513
|
printMigrationMenu(cwdEnv, homeEnv);
|
|
76229
76514
|
const ch = await promptMigrationChoice();
|
|
76230
76515
|
println("");
|
|
76231
76516
|
if (ch === "c") {
|
|
76232
|
-
|
|
76517
|
+
mkdirSync4(dirname4(homeEnv), { recursive: true });
|
|
76233
76518
|
copyFileSync2(cwdEnv, homeEnv);
|
|
76234
76519
|
if (process.platform !== "win32") {
|
|
76235
76520
|
try {
|
|
@@ -76478,6 +76763,23 @@ function registerMcp(program2) {
|
|
|
76478
76763
|
});
|
|
76479
76764
|
}
|
|
76480
76765
|
|
|
76766
|
+
// src/cli/commands/embedder-warmup.ts
|
|
76767
|
+
function registerEmbedderWarmup(program2) {
|
|
76768
|
+
program2.command("embedder-warmup", { hidden: true }).description("Download + warm the local ONNX embedding model (Cerefox Local).").action(async () => {
|
|
76769
|
+
if (process.env.CEREFOX_EMBEDDER !== "local") {
|
|
76770
|
+
process.stderr.write(`embedder-warmup: CEREFOX_EMBEDDER is not 'local' — nothing to warm (the OpenAI embedder has no local model).
|
|
76771
|
+
`);
|
|
76772
|
+
process.exitCode = 1;
|
|
76773
|
+
return;
|
|
76774
|
+
}
|
|
76775
|
+
const onnx = await Promise.resolve().then(() => (init_onnx_embedder(), exports_onnx_embedder));
|
|
76776
|
+
await onnx.warmup();
|
|
76777
|
+
const [vec] = await onnx.onnxEmbed(["warmup"], "query");
|
|
76778
|
+
process.stderr.write(`[cerefox-embed] warm — ${vec.length}-dim vectors ready.
|
|
76779
|
+
`);
|
|
76780
|
+
});
|
|
76781
|
+
}
|
|
76782
|
+
|
|
76481
76783
|
// src/cli/commands/metadata-search.ts
|
|
76482
76784
|
init_cli_core();
|
|
76483
76785
|
init_client();
|
|
@@ -76637,35 +76939,35 @@ function registerReindex(program2) {
|
|
|
76637
76939
|
// src/cli/commands/restore.ts
|
|
76638
76940
|
init_cli_core();
|
|
76639
76941
|
init_client();
|
|
76640
|
-
import { existsSync as
|
|
76641
|
-
import { homedir as
|
|
76642
|
-
import { join as
|
|
76942
|
+
import { existsSync as existsSync13, readFileSync as readFileSync13, readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
|
|
76943
|
+
import { homedir as homedir8 } from "node:os";
|
|
76944
|
+
import { join as join12, resolve as resolve4 } from "node:path";
|
|
76643
76945
|
function expandHome2(path) {
|
|
76644
76946
|
if (path === "~")
|
|
76645
|
-
return
|
|
76947
|
+
return homedir8();
|
|
76646
76948
|
if (path.startsWith("~/"))
|
|
76647
|
-
return
|
|
76949
|
+
return join12(homedir8(), path.slice(2));
|
|
76648
76950
|
return path;
|
|
76649
76951
|
}
|
|
76650
76952
|
function resolveBackupFile(target) {
|
|
76651
76953
|
const path = resolve4(expandHome2(target));
|
|
76652
|
-
if (!
|
|
76954
|
+
if (!existsSync13(path)) {
|
|
76653
76955
|
throw userError(`Backup path not found: ${target}`);
|
|
76654
76956
|
}
|
|
76655
76957
|
const stat = statSync4(path);
|
|
76656
76958
|
if (stat.isFile())
|
|
76657
76959
|
return path;
|
|
76658
|
-
const candidates = readdirSync5(path).filter((n) => n.endsWith(".json") && n.startsWith("cerefox-")).map((n) => ({ name: n, mtime: statSync4(
|
|
76960
|
+
const candidates = readdirSync5(path).filter((n) => n.endsWith(".json") && n.startsWith("cerefox-")).map((n) => ({ name: n, mtime: statSync4(join12(path, n)).mtimeMs })).sort((a, b2) => b2.mtime - a.mtime);
|
|
76659
76961
|
if (candidates.length === 0) {
|
|
76660
76962
|
throw userError(`No cerefox-*.json files in ${path}`);
|
|
76661
76963
|
}
|
|
76662
|
-
return
|
|
76964
|
+
return join12(path, candidates[0].name);
|
|
76663
76965
|
}
|
|
76664
76966
|
async function action28(target, options) {
|
|
76665
76967
|
const file = resolveBackupFile(target);
|
|
76666
76968
|
let payload;
|
|
76667
76969
|
try {
|
|
76668
|
-
payload = JSON.parse(
|
|
76970
|
+
payload = JSON.parse(readFileSync13(file, "utf8"));
|
|
76669
76971
|
} catch (err) {
|
|
76670
76972
|
throw userError(`Could not parse backup file ${file}: ${err instanceof Error ? err.message : String(err)}`);
|
|
76671
76973
|
}
|
|
@@ -76730,7 +77032,7 @@ init_config();
|
|
|
76730
77032
|
async function embedQuery(query) {
|
|
76731
77033
|
const settings = loadSettings();
|
|
76732
77034
|
const apiKey = settings.openaiApiKey;
|
|
76733
|
-
if (!apiKey) {
|
|
77035
|
+
if (!apiKey && resolveEmbedderKind() !== "local") {
|
|
76734
77036
|
throw userError("OPENAI_API_KEY (or CEREFOX_OPENAI_API_KEY) is required for search.", "Set the key in your .env, or run `cerefox init` to bootstrap.");
|
|
76735
77037
|
}
|
|
76736
77038
|
try {
|
|
@@ -77045,7 +77347,7 @@ import { randomBytes } from "node:crypto";
|
|
|
77045
77347
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
77046
77348
|
|
|
77047
77349
|
// src/cli/util/env-file.ts
|
|
77048
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
77350
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync14, readFileSync as readFileSync14, writeFileSync as writeFileSync5 } from "node:fs";
|
|
77049
77351
|
import { dirname as dirname5 } from "node:path";
|
|
77050
77352
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
77051
77353
|
function escapeRegExp(s) {
|
|
@@ -77055,12 +77357,12 @@ function upsertEnvVar(path, key, value, opts = {}) {
|
|
|
77055
77357
|
const line = `${key}=${value}`;
|
|
77056
77358
|
const header = opts.comment ? `# ${opts.comment}
|
|
77057
77359
|
` : "";
|
|
77058
|
-
if (!
|
|
77360
|
+
if (!existsSync14(path)) {
|
|
77059
77361
|
writeFileSync5(path, `${header}${line}
|
|
77060
77362
|
`, { mode: 384 });
|
|
77061
77363
|
return { path, action: "created" };
|
|
77062
77364
|
}
|
|
77063
|
-
const original =
|
|
77365
|
+
const original = readFileSync14(path, "utf8");
|
|
77064
77366
|
let backupPath;
|
|
77065
77367
|
if (!opts.noBackup) {
|
|
77066
77368
|
backupPath = `${path}.pre-cerefox.bak`;
|
|
@@ -77085,9 +77387,9 @@ ${header}${line}
|
|
|
77085
77387
|
return { path, action: action32, backupPath };
|
|
77086
77388
|
}
|
|
77087
77389
|
function readEnvVar(path, key) {
|
|
77088
|
-
if (!
|
|
77390
|
+
if (!existsSync14(path))
|
|
77089
77391
|
return null;
|
|
77090
|
-
const m =
|
|
77392
|
+
const m = readFileSync14(path, "utf8").match(new RegExp(`^\\s*${escapeRegExp(key)}=(.*)$`, "m"));
|
|
77091
77393
|
return m ? m[1].trim() : null;
|
|
77092
77394
|
}
|
|
77093
77395
|
function envGitignoreWarning(path) {
|
|
@@ -78555,8 +78857,8 @@ var _baseMimes = {
|
|
|
78555
78857
|
var baseMimes = _baseMimes;
|
|
78556
78858
|
|
|
78557
78859
|
// ../../node_modules/.bun/@hono+node-server@2.0.8+68404363cdc13251/node_modules/@hono/node-server/dist/serve-static.mjs
|
|
78558
|
-
import { createReadStream, existsSync as
|
|
78559
|
-
import { join as
|
|
78860
|
+
import { createReadStream, existsSync as existsSync15, statSync as statSync5 } from "node:fs";
|
|
78861
|
+
import { join as join13 } from "node:path";
|
|
78560
78862
|
var COMPRESSIBLE_CONTENT_TYPE_REGEX = /^\s*(?:text\/[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;
|
|
78561
78863
|
var ENCODINGS = {
|
|
78562
78864
|
br: ".br",
|
|
@@ -78588,7 +78890,7 @@ var tryDecodeURI = (str) => tryDecode(str, decodeURI);
|
|
|
78588
78890
|
var serveStatic = (options = { root: "" }) => {
|
|
78589
78891
|
const root = options.root || "";
|
|
78590
78892
|
const optionPath = options.path;
|
|
78591
|
-
if (root !== "" && !
|
|
78893
|
+
if (root !== "" && !existsSync15(root))
|
|
78592
78894
|
console.error(`serveStatic: root path '${root}' is not found, are you sure it's correct?`);
|
|
78593
78895
|
return async (c2, next) => {
|
|
78594
78896
|
if (c2.finalized)
|
|
@@ -78605,11 +78907,11 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
78605
78907
|
await options.onNotFound?.(c2.req.path, c2);
|
|
78606
78908
|
return next();
|
|
78607
78909
|
}
|
|
78608
|
-
let path =
|
|
78910
|
+
let path = join13(root, !optionPath && options.rewriteRequestPath ? options.rewriteRequestPath(filename, c2) : filename);
|
|
78609
78911
|
let stats = getStats(path);
|
|
78610
78912
|
if (stats && stats.isDirectory()) {
|
|
78611
78913
|
const indexFile = options.index ?? "index.html";
|
|
78612
|
-
path =
|
|
78914
|
+
path = join13(path, indexFile);
|
|
78613
78915
|
stats = getStats(path);
|
|
78614
78916
|
}
|
|
78615
78917
|
if (!stats) {
|
|
@@ -78666,9 +78968,9 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
78666
78968
|
};
|
|
78667
78969
|
|
|
78668
78970
|
// src/web/server.ts
|
|
78669
|
-
import { existsSync as
|
|
78670
|
-
import { readFileSync as
|
|
78671
|
-
import { join as
|
|
78971
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
78972
|
+
import { readFileSync as readFileSync17 } from "node:fs";
|
|
78973
|
+
import { join as join17 } from "node:path";
|
|
78672
78974
|
|
|
78673
78975
|
// ../../node_modules/.bun/hono@4.12.29/node_modules/hono/dist/compose.js
|
|
78674
78976
|
var compose = (middleware, onError, onNotFound) => {
|
|
@@ -80697,7 +80999,7 @@ async function runSearch(ctx, opts) {
|
|
|
80697
80999
|
throw error4;
|
|
80698
81000
|
return (data2 ?? []).map(projectChunkResult);
|
|
80699
81001
|
}
|
|
80700
|
-
if (!ctx.openAiApiKey) {
|
|
81002
|
+
if (!ctx.openAiApiKey && resolveEmbedderKind() !== "local") {
|
|
80701
81003
|
throw new HttpError(503, "Embedder not available");
|
|
80702
81004
|
}
|
|
80703
81005
|
const embedding = await getEmbedding(query, ctx.openAiApiKey);
|
|
@@ -81238,7 +81540,6 @@ function registerDocumentReadRoutes(app, ctx) {
|
|
|
81238
81540
|
return c2.json({ exists: false });
|
|
81239
81541
|
});
|
|
81240
81542
|
}
|
|
81241
|
-
|
|
81242
81543
|
// src/web/routes/documents-write.ts
|
|
81243
81544
|
async function createAuditEntry(ctx, args) {
|
|
81244
81545
|
try {
|
|
@@ -81289,7 +81590,7 @@ function registerDocumentWriteRoutes(app, ctx) {
|
|
|
81289
81590
|
const proposedHash = content.trim() ? contentHash(content) : null;
|
|
81290
81591
|
const contentChanged = proposedHash !== null && currentHash !== null && proposedHash !== currentHash;
|
|
81291
81592
|
if (contentChanged) {
|
|
81292
|
-
if (!ctx.openAiApiKey) {
|
|
81593
|
+
if (!ctx.openAiApiKey && resolveEmbedderKind() !== "local") {
|
|
81293
81594
|
return c2.json({
|
|
81294
81595
|
success: false,
|
|
81295
81596
|
error: "Embedder not available — set OPENAI_API_KEY in your config"
|
|
@@ -81445,14 +81746,13 @@ function registerDocumentWriteRoutes(app, ctx) {
|
|
|
81445
81746
|
return c2.json({ archived });
|
|
81446
81747
|
});
|
|
81447
81748
|
}
|
|
81448
|
-
|
|
81449
81749
|
// src/web/routes/ingest.ts
|
|
81450
81750
|
function notReady(error3) {
|
|
81451
81751
|
return { success: false, error: error3 };
|
|
81452
81752
|
}
|
|
81453
81753
|
function registerIngestRoutes(app, ctx) {
|
|
81454
81754
|
app.post("/api/v1/ingest", async (c2) => {
|
|
81455
|
-
if (!ctx.openAiApiKey) {
|
|
81755
|
+
if (!ctx.openAiApiKey && resolveEmbedderKind() !== "local") {
|
|
81456
81756
|
return c2.json(notReady("Embedder not available"), 503);
|
|
81457
81757
|
}
|
|
81458
81758
|
let body;
|
|
@@ -81500,7 +81800,7 @@ function registerIngestRoutes(app, ctx) {
|
|
|
81500
81800
|
}
|
|
81501
81801
|
});
|
|
81502
81802
|
app.post("/api/v1/ingest/file", async (c2) => {
|
|
81503
|
-
if (!ctx.openAiApiKey) {
|
|
81803
|
+
if (!ctx.openAiApiKey && resolveEmbedderKind() !== "local") {
|
|
81504
81804
|
return c2.json(notReady("Embedder not available"), 503);
|
|
81505
81805
|
}
|
|
81506
81806
|
let form;
|
|
@@ -81562,7 +81862,7 @@ function registerIngestRoutes(app, ctx) {
|
|
|
81562
81862
|
}
|
|
81563
81863
|
});
|
|
81564
81864
|
app.post("/api/v1/documents/:document_id/upload", async (c2) => {
|
|
81565
|
-
if (!ctx.openAiApiKey) {
|
|
81865
|
+
if (!ctx.openAiApiKey && resolveEmbedderKind() !== "local") {
|
|
81566
81866
|
return c2.json(notReady("Embedder not available"), 503);
|
|
81567
81867
|
}
|
|
81568
81868
|
const documentId = c2.req.param("document_id");
|
|
@@ -81617,12 +81917,12 @@ import { execFileSync } from "node:child_process";
|
|
|
81617
81917
|
|
|
81618
81918
|
// src/web/docs.ts
|
|
81619
81919
|
import {
|
|
81620
|
-
existsSync as
|
|
81621
|
-
readFileSync as
|
|
81920
|
+
existsSync as existsSync16,
|
|
81921
|
+
readFileSync as readFileSync15,
|
|
81622
81922
|
readdirSync as readdirSync6,
|
|
81623
81923
|
statSync as statSync6
|
|
81624
81924
|
} from "node:fs";
|
|
81625
|
-
import { basename as basename5, dirname as dirname6, join as
|
|
81925
|
+
import { basename as basename5, dirname as dirname6, join as join14, resolve as resolve5 } from "node:path";
|
|
81626
81926
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
81627
81927
|
var TOP_LEVEL_DOCS = [
|
|
81628
81928
|
{ filename: "README.md", path: "README.md", category: "readme" },
|
|
@@ -81643,32 +81943,32 @@ function moduleDir2() {
|
|
|
81643
81943
|
function resolveDocsRoots() {
|
|
81644
81944
|
const here = moduleDir2();
|
|
81645
81945
|
const pkgRootCandidates = [
|
|
81646
|
-
|
|
81647
|
-
|
|
81946
|
+
join14(here, "..", ".."),
|
|
81947
|
+
join14(here, "..", "..", "..", "..")
|
|
81648
81948
|
];
|
|
81649
81949
|
let pkgGuides = null;
|
|
81650
81950
|
let pkgTopLevel = null;
|
|
81651
81951
|
for (const pkg of pkgRootCandidates) {
|
|
81652
|
-
const guides =
|
|
81653
|
-
if (
|
|
81952
|
+
const guides = join14(pkg, "docs", "guides");
|
|
81953
|
+
if (existsSync16(guides) && statSync6(guides).isDirectory()) {
|
|
81654
81954
|
pkgGuides = guides;
|
|
81655
81955
|
pkgTopLevel = pkg;
|
|
81656
81956
|
break;
|
|
81657
81957
|
}
|
|
81658
81958
|
}
|
|
81659
|
-
const repoCandidate =
|
|
81660
|
-
const repoGuides =
|
|
81959
|
+
const repoCandidate = join14(here, "..", "..", "..", "..");
|
|
81960
|
+
const repoGuides = join14(repoCandidate, "docs", "guides");
|
|
81661
81961
|
const repoTopLevel = repoCandidate;
|
|
81662
81962
|
return {
|
|
81663
81963
|
pkgGuides,
|
|
81664
81964
|
pkgTopLevel,
|
|
81665
|
-
repoGuides:
|
|
81666
|
-
repoTopLevel:
|
|
81965
|
+
repoGuides: existsSync16(repoGuides) ? repoGuides : null,
|
|
81966
|
+
repoTopLevel: existsSync16(join14(repoTopLevel, "README.md")) ? repoTopLevel : null
|
|
81667
81967
|
};
|
|
81668
81968
|
}
|
|
81669
81969
|
function readH1(filePath) {
|
|
81670
81970
|
try {
|
|
81671
|
-
const content =
|
|
81971
|
+
const content = readFileSync15(filePath, "utf8");
|
|
81672
81972
|
const match2 = content.match(/^#\s+(.+?)\s*$/m);
|
|
81673
81973
|
return match2 ? match2[1] : null;
|
|
81674
81974
|
} catch {
|
|
@@ -81688,8 +81988,8 @@ function listBundledDocs2() {
|
|
|
81688
81988
|
const topRoot = pkgTopLevel ?? repoTopLevel;
|
|
81689
81989
|
if (topRoot) {
|
|
81690
81990
|
for (const t of TOP_LEVEL_DOCS) {
|
|
81691
|
-
const abs =
|
|
81692
|
-
if (
|
|
81991
|
+
const abs = join14(topRoot, t.filename);
|
|
81992
|
+
if (existsSync16(abs)) {
|
|
81693
81993
|
entries.push(entryForFile(abs, t.path, t.category));
|
|
81694
81994
|
}
|
|
81695
81995
|
}
|
|
@@ -81698,7 +81998,7 @@ function listBundledDocs2() {
|
|
|
81698
81998
|
if (guidesRoot) {
|
|
81699
81999
|
const names = readdirSync6(guidesRoot).filter((n) => n.endsWith(".md")).sort();
|
|
81700
82000
|
for (const name of names) {
|
|
81701
|
-
const abs =
|
|
82001
|
+
const abs = join14(guidesRoot, name);
|
|
81702
82002
|
entries.push(entryForFile(abs, `guides/${name}`, "guide"));
|
|
81703
82003
|
}
|
|
81704
82004
|
}
|
|
@@ -81716,9 +82016,9 @@ function readDoc(docPath) {
|
|
|
81716
82016
|
if (!candidate.startsWith(rootResolved + "/") && candidate !== rootResolved) {
|
|
81717
82017
|
return null;
|
|
81718
82018
|
}
|
|
81719
|
-
if (
|
|
82019
|
+
if (existsSync16(candidate) && statSync6(candidate).isFile()) {
|
|
81720
82020
|
try {
|
|
81721
|
-
return
|
|
82021
|
+
return readFileSync15(candidate, "utf8");
|
|
81722
82022
|
} catch {
|
|
81723
82023
|
return null;
|
|
81724
82024
|
}
|
|
@@ -81727,6 +82027,7 @@ function readDoc(docPath) {
|
|
|
81727
82027
|
}
|
|
81728
82028
|
|
|
81729
82029
|
// src/web/routes/meta.ts
|
|
82030
|
+
init_compatibility();
|
|
81730
82031
|
function resolveGitCommitShort() {
|
|
81731
82032
|
const env4 = process.env.CEREFOX_GIT_COMMIT;
|
|
81732
82033
|
if (env4)
|
|
@@ -81746,7 +82047,7 @@ var VERSION_INFO = {
|
|
|
81746
82047
|
git_commit_short: resolveGitCommitShort(),
|
|
81747
82048
|
build_date: process.env.CEREFOX_BUILD_DATE ?? null
|
|
81748
82049
|
};
|
|
81749
|
-
var
|
|
82050
|
+
var SCHEMA_VERSION_RE3 = /^--\s*@version:\s*(\S+)/m;
|
|
81750
82051
|
function registerMetaRoutes(app, ctx) {
|
|
81751
82052
|
app.get("/api/v1/version", (c2) => c2.json(VERSION_INFO));
|
|
81752
82053
|
app.get("/api/v1/docs", (c2) => c2.json(listBundledDocs2()));
|
|
@@ -81763,18 +82064,18 @@ function registerMetaRoutes(app, ctx) {
|
|
|
81763
82064
|
app.get("/api/v1/schema-version", async (c2) => {
|
|
81764
82065
|
let bundled = null;
|
|
81765
82066
|
try {
|
|
81766
|
-
const { readFileSync:
|
|
82067
|
+
const { readFileSync: readFileSync16, existsSync: existsSync17 } = await import("node:fs");
|
|
81767
82068
|
const { fileURLToPath: fileURLToPath4 } = await import("node:url");
|
|
81768
|
-
const { dirname: dirname7, join:
|
|
82069
|
+
const { dirname: dirname7, join: join15 } = await import("node:path");
|
|
81769
82070
|
const here = dirname7(fileURLToPath4(import.meta.url));
|
|
81770
82071
|
const candidates = [
|
|
81771
|
-
|
|
81772
|
-
|
|
82072
|
+
join15(here, "..", "..", "..", "db", "schema.sql"),
|
|
82073
|
+
join15(here, "..", "..", "..", "..", "..", "src", "cerefox", "db", "schema.sql")
|
|
81773
82074
|
];
|
|
81774
82075
|
for (const path of candidates) {
|
|
81775
|
-
if (
|
|
81776
|
-
const sql =
|
|
81777
|
-
const match2 = sql.match(
|
|
82076
|
+
if (existsSync17(path)) {
|
|
82077
|
+
const sql = readFileSync16(path, "utf8");
|
|
82078
|
+
const match2 = sql.match(SCHEMA_VERSION_RE3);
|
|
81778
82079
|
bundled = match2 ? match2[1] : null;
|
|
81779
82080
|
break;
|
|
81780
82081
|
}
|
|
@@ -81869,17 +82170,17 @@ function registerPostgrestProxy(app) {
|
|
|
81869
82170
|
|
|
81870
82171
|
// src/web/routes/preferences.ts
|
|
81871
82172
|
init_config();
|
|
81872
|
-
import { existsSync as
|
|
81873
|
-
import { join as
|
|
82173
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync5, readFileSync as readFileSync16, writeFileSync as writeFileSync6 } from "node:fs";
|
|
82174
|
+
import { join as join15 } from "node:path";
|
|
81874
82175
|
function isTheme(v) {
|
|
81875
82176
|
return v === "auto" || v === "light" || v === "dark";
|
|
81876
82177
|
}
|
|
81877
82178
|
function prefsFile() {
|
|
81878
|
-
return
|
|
82179
|
+
return join15(userStateDir(), "web-prefs.json");
|
|
81879
82180
|
}
|
|
81880
82181
|
function readPrefs() {
|
|
81881
82182
|
try {
|
|
81882
|
-
const raw2 = JSON.parse(
|
|
82183
|
+
const raw2 = JSON.parse(readFileSync16(prefsFile(), "utf8"));
|
|
81883
82184
|
if (isTheme(raw2.theme))
|
|
81884
82185
|
return { theme: raw2.theme };
|
|
81885
82186
|
} catch {}
|
|
@@ -81895,8 +82196,8 @@ function registerPreferencesRoutes(app) {
|
|
|
81895
82196
|
const next = { ...readPrefs(), theme: body.theme };
|
|
81896
82197
|
try {
|
|
81897
82198
|
const dir = userStateDir();
|
|
81898
|
-
if (!
|
|
81899
|
-
|
|
82199
|
+
if (!existsSync17(dir))
|
|
82200
|
+
mkdirSync5(dir, { recursive: true });
|
|
81900
82201
|
writeFileSync6(prefsFile(), `${JSON.stringify(next, null, 2)}
|
|
81901
82202
|
`);
|
|
81902
82203
|
} catch (err) {
|
|
@@ -81967,21 +82268,21 @@ function registerProjectsRoutes(app, ctx) {
|
|
|
81967
82268
|
}
|
|
81968
82269
|
|
|
81969
82270
|
// src/web/static.ts
|
|
81970
|
-
import { existsSync as
|
|
81971
|
-
import { dirname as dirname7, join as
|
|
82271
|
+
import { existsSync as existsSync18, statSync as statSync7 } from "node:fs";
|
|
82272
|
+
import { dirname as dirname7, join as join16 } from "node:path";
|
|
81972
82273
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
81973
82274
|
function moduleDir3() {
|
|
81974
82275
|
return dirname7(fileURLToPath4(import.meta.url));
|
|
81975
82276
|
}
|
|
81976
82277
|
function isUsableSpaDir(dir) {
|
|
81977
|
-
return
|
|
82278
|
+
return existsSync18(dir) && statSync7(dir).isDirectory() && existsSync18(join16(dir, "index.html"));
|
|
81978
82279
|
}
|
|
81979
82280
|
function resolveSpaDist() {
|
|
81980
82281
|
const here = moduleDir3();
|
|
81981
82282
|
const candidates = [
|
|
81982
|
-
|
|
81983
|
-
|
|
81984
|
-
|
|
82283
|
+
join16(here, "..", "frontend"),
|
|
82284
|
+
join16(here, "..", "..", "..", "..", "frontend", "dist"),
|
|
82285
|
+
join16(here, "..", "..", "dist", "frontend")
|
|
81985
82286
|
];
|
|
81986
82287
|
for (const c2 of candidates) {
|
|
81987
82288
|
if (isUsableSpaDir(c2))
|
|
@@ -81992,11 +82293,11 @@ function resolveSpaDist() {
|
|
|
81992
82293
|
function resolveStaticDir() {
|
|
81993
82294
|
const here = moduleDir3();
|
|
81994
82295
|
const candidates = [
|
|
81995
|
-
|
|
81996
|
-
|
|
82296
|
+
join16(here, "..", "static"),
|
|
82297
|
+
join16(here, "..", "..", "..", "..", "web", "static")
|
|
81997
82298
|
];
|
|
81998
82299
|
for (const c2 of candidates) {
|
|
81999
|
-
if (
|
|
82300
|
+
if (existsSync18(c2) && statSync7(c2).isDirectory())
|
|
82000
82301
|
return c2;
|
|
82001
82302
|
}
|
|
82002
82303
|
return null;
|
|
@@ -82041,6 +82342,7 @@ var ROOT_REDIRECT_HTML = `<!DOCTYPE html>
|
|
|
82041
82342
|
init_meta();
|
|
82042
82343
|
init_cli_core();
|
|
82043
82344
|
init_config();
|
|
82345
|
+
init_compatibility();
|
|
82044
82346
|
function buildApp(ctx = buildWebContext()) {
|
|
82045
82347
|
const app = new Hono2;
|
|
82046
82348
|
if (true) {
|
|
@@ -82082,9 +82384,9 @@ function buildApp(ctx = buildWebContext()) {
|
|
|
82082
82384
|
root: spaDist,
|
|
82083
82385
|
rewriteRequestPath: (path) => path.replace(/^\/app/, "") || "/"
|
|
82084
82386
|
}));
|
|
82085
|
-
const indexPath =
|
|
82086
|
-
if (
|
|
82087
|
-
const indexHtml =
|
|
82387
|
+
const indexPath = join17(spaDist, "index.html");
|
|
82388
|
+
if (existsSync19(indexPath)) {
|
|
82389
|
+
const indexHtml = readFileSync17(indexPath, "utf8");
|
|
82088
82390
|
app.get("/app/*", (c2) => c2.html(indexHtml));
|
|
82089
82391
|
}
|
|
82090
82392
|
}
|
|
@@ -82142,28 +82444,28 @@ async function buildWebServer(options = {}) {
|
|
|
82142
82444
|
// src/web/daemon.ts
|
|
82143
82445
|
import { spawn } from "node:child_process";
|
|
82144
82446
|
import {
|
|
82145
|
-
existsSync as
|
|
82146
|
-
mkdirSync as
|
|
82447
|
+
existsSync as existsSync20,
|
|
82448
|
+
mkdirSync as mkdirSync6,
|
|
82147
82449
|
openSync,
|
|
82148
|
-
readFileSync as
|
|
82450
|
+
readFileSync as readFileSync18,
|
|
82149
82451
|
rmSync,
|
|
82150
82452
|
writeFileSync as writeFileSync7
|
|
82151
82453
|
} from "node:fs";
|
|
82152
|
-
import { homedir as
|
|
82153
|
-
import { join as
|
|
82154
|
-
var STATE_DIR =
|
|
82155
|
-
var PID_FILE =
|
|
82156
|
-
var LOG_FILE =
|
|
82454
|
+
import { homedir as homedir9 } from "node:os";
|
|
82455
|
+
import { join as join18 } from "node:path";
|
|
82456
|
+
var STATE_DIR = join18(homedir9(), ".cerefox");
|
|
82457
|
+
var PID_FILE = join18(STATE_DIR, "web.pid");
|
|
82458
|
+
var LOG_FILE = join18(STATE_DIR, "web.log");
|
|
82157
82459
|
var daemonPaths = { stateDir: STATE_DIR, pidFile: PID_FILE, logFile: LOG_FILE };
|
|
82158
82460
|
function ensureStateDir() {
|
|
82159
|
-
if (!
|
|
82160
|
-
|
|
82461
|
+
if (!existsSync20(STATE_DIR))
|
|
82462
|
+
mkdirSync6(STATE_DIR, { recursive: true });
|
|
82161
82463
|
}
|
|
82162
82464
|
function readPidFile() {
|
|
82163
|
-
if (!
|
|
82465
|
+
if (!existsSync20(PID_FILE))
|
|
82164
82466
|
return null;
|
|
82165
82467
|
try {
|
|
82166
|
-
const parsed = JSON.parse(
|
|
82468
|
+
const parsed = JSON.parse(readFileSync18(PID_FILE, "utf8"));
|
|
82167
82469
|
if (typeof parsed.pid !== "number")
|
|
82168
82470
|
return null;
|
|
82169
82471
|
return {
|
|
@@ -82474,6 +82776,7 @@ Learn more:
|
|
|
82474
82776
|
registerConfigureAgent(program2);
|
|
82475
82777
|
registerSelfUpdate(program2);
|
|
82476
82778
|
registerMcp(program2);
|
|
82779
|
+
registerEmbedderWarmup(program2);
|
|
82477
82780
|
registerWeb(program2);
|
|
82478
82781
|
registerCompletion(program2);
|
|
82479
82782
|
registerToken(program2);
|
|
@@ -82527,7 +82830,7 @@ Learn more:
|
|
|
82527
82830
|
|
|
82528
82831
|
// src/bin/cerefox.ts
|
|
82529
82832
|
async function bareEntryPoint() {
|
|
82530
|
-
const { existsSync:
|
|
82833
|
+
const { existsSync: existsSync21 } = await import("node:fs");
|
|
82531
82834
|
const { resolveEnvFile: resolveEnvFile2 } = await Promise.resolve().then(() => (init_config(), exports_config));
|
|
82532
82835
|
const { c: c2, println: println2 } = await Promise.resolve().then(() => (init_cli_core(), exports_cli_core));
|
|
82533
82836
|
const { PKG_VERSION: PKG_VERSION2 } = await Promise.resolve().then(() => (init_meta(), exports_meta));
|
|
@@ -82536,7 +82839,7 @@ async function bareEntryPoint() {
|
|
|
82536
82839
|
println2("");
|
|
82537
82840
|
let configExists = false;
|
|
82538
82841
|
try {
|
|
82539
|
-
configExists =
|
|
82842
|
+
configExists = existsSync21(resolveEnvFile2());
|
|
82540
82843
|
} catch {}
|
|
82541
82844
|
if (!configExists) {
|
|
82542
82845
|
println2(c2.yellow("⚠ No config detected."));
|