@cerefox/memory 1.0.0-beta.3 → 1.0.0-rc.1
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 +724 -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-
|
|
7187
|
+
var PKG_VERSION = "1.0.0-rc.1";
|
|
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,332 @@ 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 split = (v) => {
|
|
25248
|
+
const [core, ...preParts] = v.split("-");
|
|
25249
|
+
return {
|
|
25250
|
+
core: core.split(".").slice(0, 3).map((p) => {
|
|
25251
|
+
const n = Number.parseInt(p, 10);
|
|
25252
|
+
return Number.isFinite(n) ? n : 0;
|
|
25253
|
+
}),
|
|
25254
|
+
pre: preParts.length ? preParts.join("-").split(".") : []
|
|
25255
|
+
};
|
|
25256
|
+
};
|
|
25257
|
+
const pa = split(a);
|
|
25258
|
+
const pb = split(b2);
|
|
25259
|
+
for (let i = 0;i < 3; i++) {
|
|
25260
|
+
const x = pa.core[i] ?? 0;
|
|
25261
|
+
const y = pb.core[i] ?? 0;
|
|
25262
|
+
if (x !== y)
|
|
25263
|
+
return x < y ? -1 : 1;
|
|
25264
|
+
}
|
|
25265
|
+
if (pa.pre.length === 0 && pb.pre.length === 0)
|
|
25266
|
+
return 0;
|
|
25267
|
+
if (pa.pre.length === 0)
|
|
25268
|
+
return 1;
|
|
25269
|
+
if (pb.pre.length === 0)
|
|
25270
|
+
return -1;
|
|
25271
|
+
const len = Math.max(pa.pre.length, pb.pre.length);
|
|
25272
|
+
for (let i = 0;i < len; i++) {
|
|
25273
|
+
const x = pa.pre[i];
|
|
25274
|
+
const y = pb.pre[i];
|
|
25275
|
+
if (x === undefined)
|
|
25276
|
+
return -1;
|
|
25277
|
+
if (y === undefined)
|
|
25278
|
+
return 1;
|
|
25279
|
+
const xn = /^\d+$/.test(x) ? Number.parseInt(x, 10) : null;
|
|
25280
|
+
const yn = /^\d+$/.test(y) ? Number.parseInt(y, 10) : null;
|
|
25281
|
+
if (xn !== null && yn !== null) {
|
|
25282
|
+
if (xn !== yn)
|
|
25283
|
+
return xn < yn ? -1 : 1;
|
|
25284
|
+
} else if (xn !== null) {
|
|
25285
|
+
return -1;
|
|
25286
|
+
} else if (yn !== null) {
|
|
25287
|
+
return 1;
|
|
25288
|
+
} else if (x !== y) {
|
|
25289
|
+
return x < y ? -1 : 1;
|
|
25290
|
+
}
|
|
25291
|
+
}
|
|
25292
|
+
return 0;
|
|
25202
25293
|
}
|
|
25203
|
-
function
|
|
25204
|
-
|
|
25205
|
-
|
|
25206
|
-
|
|
25207
|
-
|
|
25294
|
+
function classifyCompat(deployed, min, bundled) {
|
|
25295
|
+
if (!deployed)
|
|
25296
|
+
return "unknown";
|
|
25297
|
+
if (compareSemver(deployed, min) < 0)
|
|
25298
|
+
return "below-min";
|
|
25299
|
+
if (bundled && compareSemver(deployed, bundled) < 0)
|
|
25300
|
+
return "above-min-but-old";
|
|
25301
|
+
return "ok";
|
|
25208
25302
|
}
|
|
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;
|
|
25303
|
+
function aggregatorUrlFor(supabaseUrl) {
|
|
25304
|
+
const base = supabaseUrl.replace(/\/$/, "");
|
|
25305
|
+
return `${base}/functions/v1/cerefox-mcp/version?peers=true`;
|
|
25217
25306
|
}
|
|
25218
|
-
function
|
|
25219
|
-
const
|
|
25220
|
-
|
|
25221
|
-
|
|
25222
|
-
|
|
25223
|
-
|
|
25224
|
-
|
|
25225
|
-
|
|
25307
|
+
async function checkServerCompatibility(opts) {
|
|
25308
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
25309
|
+
const result = {
|
|
25310
|
+
schema: { deployed: null, min: COMPATIBILITY.minSchema, level: "unknown" },
|
|
25311
|
+
edgeFunctions: {
|
|
25312
|
+
deployed: null,
|
|
25313
|
+
min: COMPATIBILITY.minEdgeFunctions,
|
|
25314
|
+
level: "unknown",
|
|
25315
|
+
errors: []
|
|
25316
|
+
},
|
|
25317
|
+
blocking: false,
|
|
25318
|
+
efProbeSkipped: false
|
|
25319
|
+
};
|
|
25320
|
+
if (!opts.bearer) {
|
|
25321
|
+
result.efProbeSkipped = true;
|
|
25322
|
+
result.efSkipReason = "No CEREFOX_ACCESS_TOKEN configured; Edge Function version check skipped.";
|
|
25323
|
+
return result;
|
|
25226
25324
|
}
|
|
25227
|
-
|
|
25228
|
-
|
|
25229
|
-
|
|
25230
|
-
|
|
25231
|
-
|
|
25232
|
-
|
|
25233
|
-
|
|
25234
|
-
|
|
25235
|
-
|
|
25236
|
-
|
|
25237
|
-
|
|
25325
|
+
let agg = null;
|
|
25326
|
+
try {
|
|
25327
|
+
const ctrl = new AbortController;
|
|
25328
|
+
const timer2 = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 6000);
|
|
25329
|
+
try {
|
|
25330
|
+
const resp = await fetchImpl(opts.aggregatorUrl, {
|
|
25331
|
+
method: "GET",
|
|
25332
|
+
headers: { Authorization: `Bearer ${opts.bearer}`, apikey: opts.bearer },
|
|
25333
|
+
signal: ctrl.signal
|
|
25334
|
+
});
|
|
25335
|
+
if (resp.ok) {
|
|
25336
|
+
agg = await resp.json();
|
|
25337
|
+
} else {
|
|
25338
|
+
result.efProbeSkipped = true;
|
|
25339
|
+
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.`;
|
|
25340
|
+
}
|
|
25341
|
+
} finally {
|
|
25342
|
+
clearTimeout(timer2);
|
|
25238
25343
|
}
|
|
25239
|
-
|
|
25240
|
-
|
|
25344
|
+
} catch (err) {
|
|
25345
|
+
result.efProbeSkipped = true;
|
|
25346
|
+
result.efSkipReason = `Could not reach the version aggregator: ${err instanceof Error ? err.message : String(err)}`;
|
|
25241
25347
|
}
|
|
25242
|
-
if (
|
|
25243
|
-
|
|
25348
|
+
if (!agg)
|
|
25349
|
+
return result;
|
|
25350
|
+
result.schema.deployed = agg.schema ?? null;
|
|
25351
|
+
result.schema.level = classifyCompat(result.schema.deployed, COMPATIBILITY.minSchema, opts.bundledSchema);
|
|
25352
|
+
const versions = [];
|
|
25353
|
+
if (agg.version)
|
|
25354
|
+
versions.push(agg.version);
|
|
25355
|
+
for (const ef of agg.efs ?? [])
|
|
25356
|
+
versions.push(ef.version);
|
|
25357
|
+
result.edgeFunctions.errors = agg.errors ?? [];
|
|
25358
|
+
if (versions.length > 0) {
|
|
25359
|
+
const weakest = versions.reduce((lo, v) => compareSemver(v, lo) < 0 ? v : lo);
|
|
25360
|
+
result.edgeFunctions.deployed = weakest;
|
|
25361
|
+
result.edgeFunctions.level = classifyCompat(weakest, COMPATIBILITY.minEdgeFunctions, opts.bundledEf);
|
|
25362
|
+
} else {
|
|
25363
|
+
result.edgeFunctions.level = "unknown";
|
|
25364
|
+
result.efProbeSkipped = true;
|
|
25365
|
+
result.efSkipReason = "Aggregator reported no Edge Function versions; check skipped.";
|
|
25366
|
+
}
|
|
25367
|
+
result.blocking = result.schema.level === "below-min" || result.edgeFunctions.level === "below-min";
|
|
25368
|
+
return result;
|
|
25369
|
+
}
|
|
25370
|
+
var COMPATIBILITY;
|
|
25371
|
+
var init_compatibility = __esm(() => {
|
|
25372
|
+
COMPATIBILITY = {
|
|
25373
|
+
minSchema: "0.3.1",
|
|
25374
|
+
minEdgeFunctions: "0.6.0"
|
|
25375
|
+
};
|
|
25376
|
+
});
|
|
25377
|
+
|
|
25378
|
+
// ../../_shared/embeddings/onnx-embedder.ts
|
|
25379
|
+
var exports_onnx_embedder = {};
|
|
25380
|
+
__export(exports_onnx_embedder, {
|
|
25381
|
+
warmup: () => warmup,
|
|
25382
|
+
onnxEmbed: () => onnxEmbed,
|
|
25383
|
+
nomicPrefix: () => nomicPrefix,
|
|
25384
|
+
buildPrefixedInputs: () => buildPrefixedInputs,
|
|
25385
|
+
ONNX_MODEL_NAME: () => ONNX_MODEL_NAME,
|
|
25386
|
+
ONNX_MODEL_ID: () => ONNX_MODEL_ID,
|
|
25387
|
+
ONNX_MODEL_DTYPE: () => ONNX_MODEL_DTYPE,
|
|
25388
|
+
ONNX_MODEL_DIM: () => ONNX_MODEL_DIM,
|
|
25389
|
+
ONNX_MODEL_APPROX_MB: () => ONNX_MODEL_APPROX_MB
|
|
25390
|
+
});
|
|
25391
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync3 } from "node:fs";
|
|
25392
|
+
import { homedir as homedir5 } from "node:os";
|
|
25393
|
+
import { join as join8 } from "node:path";
|
|
25394
|
+
function nomicPrefix(role) {
|
|
25395
|
+
return role === "query" ? "search_query: " : "search_document: ";
|
|
25396
|
+
}
|
|
25397
|
+
function buildPrefixedInputs(texts, role) {
|
|
25398
|
+
const p = nomicPrefix(role);
|
|
25399
|
+
return texts.map((t) => p + t);
|
|
25400
|
+
}
|
|
25401
|
+
function getCacheDir() {
|
|
25402
|
+
const env4 = globalThis.process?.env ?? {};
|
|
25403
|
+
if (env4.CEREFOX_MODELS_DIR)
|
|
25404
|
+
return env4.CEREFOX_MODELS_DIR;
|
|
25405
|
+
return join8(homedir5(), ".cerefox", "models");
|
|
25406
|
+
}
|
|
25407
|
+
async function loadTransformers() {
|
|
25408
|
+
if (transformersModule)
|
|
25409
|
+
return transformersModule;
|
|
25410
|
+
const spec = "@huggingface/transformers";
|
|
25411
|
+
transformersModule = await import(spec);
|
|
25412
|
+
const dir = getCacheDir();
|
|
25413
|
+
if (!existsSync9(dir))
|
|
25414
|
+
mkdirSync3(dir, { recursive: true });
|
|
25415
|
+
transformersModule.env.cacheDir = dir;
|
|
25416
|
+
transformersModule.env.allowLocalModels = true;
|
|
25417
|
+
transformersModule.env.allowRemoteModels = true;
|
|
25418
|
+
return transformersModule;
|
|
25419
|
+
}
|
|
25420
|
+
function makeBar(pct, width = 20) {
|
|
25421
|
+
const clamped = Math.max(0, Math.min(100, pct));
|
|
25422
|
+
const filled = Math.round(clamped / 100 * width);
|
|
25423
|
+
return `[${"█".repeat(filled)}${"░".repeat(width - filled)}]`;
|
|
25424
|
+
}
|
|
25425
|
+
function l2Normalise(v) {
|
|
25426
|
+
let sum = 0;
|
|
25427
|
+
for (let i = 0;i < v.length; i++)
|
|
25428
|
+
sum += v[i] * v[i];
|
|
25429
|
+
const norm = Math.sqrt(sum);
|
|
25430
|
+
if (norm === 0)
|
|
25431
|
+
return v;
|
|
25432
|
+
const out = new Float32Array(v.length);
|
|
25433
|
+
for (let i = 0;i < v.length; i++)
|
|
25434
|
+
out[i] = v[i] / norm;
|
|
25244
25435
|
return out;
|
|
25245
25436
|
}
|
|
25246
|
-
function
|
|
25247
|
-
|
|
25248
|
-
|
|
25437
|
+
async function ensurePipeline() {
|
|
25438
|
+
if (pipelinePromise)
|
|
25439
|
+
return pipelinePromise;
|
|
25440
|
+
pipelinePromise = (async () => {
|
|
25441
|
+
const transformers = await loadTransformers();
|
|
25442
|
+
const mb = ONNX_MODEL_APPROX_MB;
|
|
25443
|
+
const fmt = (s) => s < 60 ? `${s}s` : `${Math.round(s / 60)}m`;
|
|
25444
|
+
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)…
|
|
25445
|
+
`);
|
|
25446
|
+
const progressState = new Map;
|
|
25447
|
+
let activeFile = null;
|
|
25448
|
+
const isTty = !!process.stderr.isTTY;
|
|
25449
|
+
const RENDER_INTERVAL_MS = 250;
|
|
25450
|
+
const fmtMb = (n) => (n / 1024 / 1024).toFixed(1);
|
|
25451
|
+
const renderInPlace = (line) => {
|
|
25452
|
+
if (isTty)
|
|
25453
|
+
process.stderr.write(`\r\x1B[K${line}`);
|
|
25454
|
+
else
|
|
25455
|
+
process.stderr.write(`${line}
|
|
25456
|
+
`);
|
|
25457
|
+
};
|
|
25458
|
+
const finalizeLine = () => {
|
|
25459
|
+
if (isTty && activeFile !== null)
|
|
25460
|
+
process.stderr.write(`
|
|
25461
|
+
`);
|
|
25462
|
+
activeFile = null;
|
|
25463
|
+
};
|
|
25464
|
+
const progressCallback = (info3) => {
|
|
25465
|
+
const file = info3.file ?? info3.name ?? "(unknown)";
|
|
25466
|
+
const now = Date.now();
|
|
25467
|
+
if (info3.status === "progress") {
|
|
25468
|
+
const total = info3.total ?? 0;
|
|
25469
|
+
const loaded = info3.loaded ?? 0;
|
|
25470
|
+
if (total === 0 && loaded === 0)
|
|
25471
|
+
return;
|
|
25472
|
+
const prior = progressState.get(file) ?? {
|
|
25473
|
+
loaded: 0,
|
|
25474
|
+
total: 0,
|
|
25475
|
+
done: false,
|
|
25476
|
+
indeterminate: false,
|
|
25477
|
+
lastRenderAt: 0,
|
|
25478
|
+
lastRenderedPct: -1
|
|
25479
|
+
};
|
|
25480
|
+
const indeterminate = prior.indeterminate || prior.total > 0 && total > prior.total;
|
|
25481
|
+
const next = {
|
|
25482
|
+
loaded,
|
|
25483
|
+
total,
|
|
25484
|
+
done: false,
|
|
25485
|
+
indeterminate,
|
|
25486
|
+
lastRenderAt: prior.lastRenderAt,
|
|
25487
|
+
lastRenderedPct: prior.lastRenderedPct
|
|
25488
|
+
};
|
|
25489
|
+
if (activeFile !== file) {
|
|
25490
|
+
finalizeLine();
|
|
25491
|
+
activeFile = file;
|
|
25492
|
+
}
|
|
25493
|
+
if (indeterminate) {
|
|
25494
|
+
if (now - prior.lastRenderAt >= RENDER_INTERVAL_MS) {
|
|
25495
|
+
renderInPlace(`[cerefox-embed] [streaming...] ${fmtMb(loaded)} MB ${file}`);
|
|
25496
|
+
next.lastRenderAt = now;
|
|
25497
|
+
}
|
|
25498
|
+
} else if (total > 0) {
|
|
25499
|
+
const pct = Math.floor(loaded / total * 100);
|
|
25500
|
+
const stepBumped = pct >= prior.lastRenderedPct + 5;
|
|
25501
|
+
const timeBumped = isTty && now - prior.lastRenderAt >= RENDER_INTERVAL_MS && pct !== prior.lastRenderedPct;
|
|
25502
|
+
if (stepBumped || timeBumped) {
|
|
25503
|
+
renderInPlace(`[cerefox-embed] ${makeBar(pct)} ${pct.toString().padStart(3)}% ${fmtMb(loaded)}/${fmtMb(total)} MB ${file}`);
|
|
25504
|
+
next.lastRenderedPct = pct;
|
|
25505
|
+
next.lastRenderAt = now;
|
|
25506
|
+
}
|
|
25507
|
+
}
|
|
25508
|
+
progressState.set(file, next);
|
|
25509
|
+
} else if (info3.status === "done") {
|
|
25510
|
+
const prior = progressState.get(file);
|
|
25511
|
+
finalizeLine();
|
|
25512
|
+
const finalSize = prior && prior.loaded > 0 ? `${fmtMb(prior.loaded)} MB` : info3.total && info3.total > 0 ? `${fmtMb(info3.total)} MB` : "cached";
|
|
25513
|
+
process.stderr.write(`[cerefox-embed] ✓ ${file} (${finalSize})
|
|
25514
|
+
`);
|
|
25515
|
+
if (prior)
|
|
25516
|
+
progressState.set(file, { ...prior, done: true });
|
|
25517
|
+
}
|
|
25518
|
+
};
|
|
25519
|
+
const pipe = await transformers.pipeline("feature-extraction", ONNX_MODEL_ID, {
|
|
25520
|
+
dtype: ONNX_MODEL_DTYPE,
|
|
25521
|
+
progress_callback: progressCallback
|
|
25522
|
+
});
|
|
25523
|
+
process.stderr.write(`[cerefox-embed] embedder ready.
|
|
25524
|
+
`);
|
|
25525
|
+
return pipe;
|
|
25526
|
+
})();
|
|
25527
|
+
pipelinePromise.catch(() => {
|
|
25528
|
+
pipelinePromise = null;
|
|
25529
|
+
});
|
|
25530
|
+
return pipelinePromise;
|
|
25531
|
+
}
|
|
25532
|
+
async function warmup() {
|
|
25533
|
+
await ensurePipeline();
|
|
25534
|
+
}
|
|
25535
|
+
async function onnxEmbed(texts, role) {
|
|
25536
|
+
if (texts.length === 0)
|
|
25249
25537
|
return [];
|
|
25250
|
-
|
|
25251
|
-
|
|
25252
|
-
|
|
25253
|
-
|
|
25538
|
+
const pipeline = await ensurePipeline();
|
|
25539
|
+
const inputs = buildPrefixedInputs(texts, role);
|
|
25540
|
+
const out = await pipeline(inputs, { pooling: "mean", normalize: true });
|
|
25541
|
+
const dim2 = out.dims[out.dims.length - 1];
|
|
25542
|
+
if (dim2 !== ONNX_MODEL_DIM) {
|
|
25543
|
+
throw new Error(`OnnxEmbedder: expected dim=${ONNX_MODEL_DIM} (schema vector(768)), got ${dim2} from model`);
|
|
25254
25544
|
}
|
|
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);
|
|
25545
|
+
const vectors = [];
|
|
25546
|
+
for (let i = 0;i < inputs.length; i++) {
|
|
25547
|
+
const slice = out.data.slice(i * dim2, (i + 1) * dim2);
|
|
25548
|
+
vectors.push(Array.from(l2Normalise(slice)));
|
|
25266
25549
|
}
|
|
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;
|
|
25550
|
+
return vectors;
|
|
25306
25551
|
}
|
|
25307
|
-
|
|
25308
|
-
|
|
25309
|
-
const head2 = breadcrumb ? `# ${docTitle}
|
|
25310
|
-
${breadcrumb}` : `# ${docTitle}`;
|
|
25311
|
-
return `${head2}
|
|
25312
|
-
${chunk.content}`;
|
|
25313
|
-
}
|
|
25314
|
-
var CONTENT_FORMAT_BLIND_STITCH = 2;
|
|
25552
|
+
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;
|
|
25553
|
+
var init_onnx_embedder = () => {};
|
|
25315
25554
|
|
|
25316
25555
|
// ../../_shared/embeddings/index.ts
|
|
25556
|
+
var exports_embeddings = {};
|
|
25557
|
+
__export(exports_embeddings, {
|
|
25558
|
+
resolveEmbedderKind: () => resolveEmbedderKind,
|
|
25559
|
+
openaiEmbeddingConfig: () => openaiEmbeddingConfig,
|
|
25560
|
+
getEmbedding: () => getEmbedding,
|
|
25561
|
+
embeddingMaxInputChars: () => embeddingMaxInputChars,
|
|
25562
|
+
embedBatch: () => embedBatch,
|
|
25563
|
+
capEmbeddingInput: () => capEmbeddingInput,
|
|
25564
|
+
activeEmbedderName: () => activeEmbedderName,
|
|
25565
|
+
OPENAI_MODEL: () => OPENAI_MODEL,
|
|
25566
|
+
OPENAI_EMBEDDING_URL: () => OPENAI_EMBEDDING_URL,
|
|
25567
|
+
EMBEDDING_DIMENSIONS: () => EMBEDDING_DIMENSIONS,
|
|
25568
|
+
EMBEDDING_BATCH_SIZE: () => EMBEDDING_BATCH_SIZE,
|
|
25569
|
+
DEFAULT_EMBED_MAX_INPUT_CHARS: () => DEFAULT_EMBED_MAX_INPUT_CHARS
|
|
25570
|
+
});
|
|
25317
25571
|
function openaiEmbeddingConfig() {
|
|
25318
25572
|
const env4 = globalThis.process?.env ?? {};
|
|
25319
25573
|
const base = env4.CEREFOX_OPENAI_BASE_URL?.replace(/\/+$/, "");
|
|
@@ -25340,7 +25594,22 @@ function capEmbeddingInput(text) {
|
|
|
25340
25594
|
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
25595
|
return cut;
|
|
25342
25596
|
}
|
|
25597
|
+
function resolveEmbedderKind() {
|
|
25598
|
+
const env4 = globalThis.process?.env ?? {};
|
|
25599
|
+
return env4.CEREFOX_EMBEDDER === "local" ? "local" : "openai";
|
|
25600
|
+
}
|
|
25601
|
+
function activeEmbedderName() {
|
|
25602
|
+
return resolveEmbedderKind() === "local" ? "nomic-embed-text-v1.5" : openaiEmbeddingConfig().model;
|
|
25603
|
+
}
|
|
25604
|
+
async function onnxModule() {
|
|
25605
|
+
return await Promise.resolve().then(() => (init_onnx_embedder(), exports_onnx_embedder));
|
|
25606
|
+
}
|
|
25343
25607
|
async function getEmbedding(text, apiKey) {
|
|
25608
|
+
if (resolveEmbedderKind() === "local") {
|
|
25609
|
+
const onnx = await onnxModule();
|
|
25610
|
+
const [vec] = await onnx.onnxEmbed([capEmbeddingInput(text)], "query");
|
|
25611
|
+
return vec;
|
|
25612
|
+
}
|
|
25344
25613
|
let lastError = null;
|
|
25345
25614
|
const cfg = openaiEmbeddingConfig();
|
|
25346
25615
|
const input = capEmbeddingInput(text);
|
|
@@ -25432,6 +25701,10 @@ async function embedBatchSingleCall(texts, apiKey) {
|
|
|
25432
25701
|
async function embedBatch(texts, apiKey, batchSize = EMBEDDING_BATCH_SIZE) {
|
|
25433
25702
|
if (texts.length === 0)
|
|
25434
25703
|
return [];
|
|
25704
|
+
if (resolveEmbedderKind() === "local") {
|
|
25705
|
+
const onnx = await onnxModule();
|
|
25706
|
+
return onnx.onnxEmbed(texts.map(capEmbeddingInput), "document");
|
|
25707
|
+
}
|
|
25435
25708
|
if (texts.length <= batchSize) {
|
|
25436
25709
|
return embedBatchSingleCall(texts, apiKey);
|
|
25437
25710
|
}
|
|
@@ -25446,6 +25719,126 @@ async function embedBatch(texts, apiKey, batchSize = EMBEDDING_BATCH_SIZE) {
|
|
|
25446
25719
|
}
|
|
25447
25720
|
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
25721
|
|
|
25722
|
+
// ../../_shared/ingest/chunker.ts
|
|
25723
|
+
function cpLen(s) {
|
|
25724
|
+
let n = 0;
|
|
25725
|
+
for (const _ of s)
|
|
25726
|
+
n++;
|
|
25727
|
+
return n;
|
|
25728
|
+
}
|
|
25729
|
+
function rstripHash(s) {
|
|
25730
|
+
let i = s.length;
|
|
25731
|
+
while (i > 0 && s[i - 1] === "#")
|
|
25732
|
+
i--;
|
|
25733
|
+
return s.slice(0, i);
|
|
25734
|
+
}
|
|
25735
|
+
function findHeadings(doc) {
|
|
25736
|
+
const out = [];
|
|
25737
|
+
const re = /^(#{1,3})[ \t]+(.+)$/gm;
|
|
25738
|
+
let m;
|
|
25739
|
+
while ((m = re.exec(doc)) !== null) {
|
|
25740
|
+
out.push({ offset: m.index, level: m[1].length, text: rstripHash(m[2]).trim() });
|
|
25741
|
+
}
|
|
25742
|
+
return out;
|
|
25743
|
+
}
|
|
25744
|
+
function activeHeadings(headings, offset) {
|
|
25745
|
+
const stack = [];
|
|
25746
|
+
for (const h of headings) {
|
|
25747
|
+
if (h.offset > offset)
|
|
25748
|
+
break;
|
|
25749
|
+
while (stack.length && stack[stack.length - 1].level >= h.level)
|
|
25750
|
+
stack.pop();
|
|
25751
|
+
stack.push(h);
|
|
25752
|
+
}
|
|
25753
|
+
return stack;
|
|
25754
|
+
}
|
|
25755
|
+
function hardSplitCp(s, maxCp) {
|
|
25756
|
+
const out = [];
|
|
25757
|
+
let buf = "";
|
|
25758
|
+
let n = 0;
|
|
25759
|
+
for (const ch of s) {
|
|
25760
|
+
if (n >= maxCp) {
|
|
25761
|
+
out.push(buf);
|
|
25762
|
+
buf = "";
|
|
25763
|
+
n = 0;
|
|
25764
|
+
}
|
|
25765
|
+
buf += ch;
|
|
25766
|
+
n++;
|
|
25767
|
+
}
|
|
25768
|
+
if (buf)
|
|
25769
|
+
out.push(buf);
|
|
25770
|
+
return out;
|
|
25771
|
+
}
|
|
25772
|
+
function chunkMarkdown(text, maxChunkChars = 4000, _minChunkChars = 100) {
|
|
25773
|
+
const doc = text.trim();
|
|
25774
|
+
if (!doc)
|
|
25775
|
+
return [];
|
|
25776
|
+
if (cpLen(doc) <= maxChunkChars) {
|
|
25777
|
+
return [
|
|
25778
|
+
{ chunk_index: 0, heading_path: [], heading_level: 0, title: "", content: doc, char_count: cpLen(doc) }
|
|
25779
|
+
];
|
|
25780
|
+
}
|
|
25781
|
+
const headings = findHeadings(doc);
|
|
25782
|
+
const parts = doc.split(/(\n{2,})/);
|
|
25783
|
+
const atoms = [];
|
|
25784
|
+
for (let i = 0;i < parts.length; i += 2) {
|
|
25785
|
+
const unit = (parts[i] ?? "") + (parts[i + 1] ?? "");
|
|
25786
|
+
if (unit === "")
|
|
25787
|
+
continue;
|
|
25788
|
+
if (cpLen(unit) > maxChunkChars)
|
|
25789
|
+
atoms.push(...hardSplitCp(unit, maxChunkChars));
|
|
25790
|
+
else
|
|
25791
|
+
atoms.push(unit);
|
|
25792
|
+
}
|
|
25793
|
+
const chunks = [];
|
|
25794
|
+
let buf = "";
|
|
25795
|
+
let bufCp = 0;
|
|
25796
|
+
let bufStart = 0;
|
|
25797
|
+
let offset = 0;
|
|
25798
|
+
const flush = () => {
|
|
25799
|
+
if (buf === "")
|
|
25800
|
+
return;
|
|
25801
|
+
const stack = activeHeadings(headings, bufStart);
|
|
25802
|
+
chunks.push({
|
|
25803
|
+
chunk_index: chunks.length,
|
|
25804
|
+
heading_path: stack.map((h) => h.text),
|
|
25805
|
+
heading_level: stack.length ? stack[stack.length - 1].level : 0,
|
|
25806
|
+
title: stack.length ? stack[stack.length - 1].text : "",
|
|
25807
|
+
content: buf,
|
|
25808
|
+
char_count: bufCp
|
|
25809
|
+
});
|
|
25810
|
+
buf = "";
|
|
25811
|
+
bufCp = 0;
|
|
25812
|
+
};
|
|
25813
|
+
for (const atom of atoms) {
|
|
25814
|
+
const cp = cpLen(atom);
|
|
25815
|
+
if (buf === "") {
|
|
25816
|
+
bufStart = offset;
|
|
25817
|
+
buf = atom;
|
|
25818
|
+
bufCp = cp;
|
|
25819
|
+
} else if (bufCp + cp <= maxChunkChars) {
|
|
25820
|
+
buf += atom;
|
|
25821
|
+
bufCp += cp;
|
|
25822
|
+
} else {
|
|
25823
|
+
flush();
|
|
25824
|
+
bufStart = offset;
|
|
25825
|
+
buf = atom;
|
|
25826
|
+
bufCp = cp;
|
|
25827
|
+
}
|
|
25828
|
+
offset += atom.length;
|
|
25829
|
+
}
|
|
25830
|
+
flush();
|
|
25831
|
+
return chunks;
|
|
25832
|
+
}
|
|
25833
|
+
function embeddingInputFor(docTitle, chunk) {
|
|
25834
|
+
const breadcrumb = chunk.heading_path.join(" > ");
|
|
25835
|
+
const head2 = breadcrumb ? `# ${docTitle}
|
|
25836
|
+
${breadcrumb}` : `# ${docTitle}`;
|
|
25837
|
+
return `${head2}
|
|
25838
|
+
${chunk.content}`;
|
|
25839
|
+
}
|
|
25840
|
+
var CONTENT_FORMAT_BLIND_STITCH = 2;
|
|
25841
|
+
|
|
25449
25842
|
// ../../node_modules/.bun/underscore@1.13.8/node_modules/underscore/underscore-node-f.cjs
|
|
25450
25843
|
var require_underscore_node_f = __commonJS((exports) => {
|
|
25451
25844
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -32746,7 +33139,7 @@ var require_BufferList = __commonJS((exports, module) => {
|
|
|
32746
33139
|
this.head = this.tail = null;
|
|
32747
33140
|
this.length = 0;
|
|
32748
33141
|
};
|
|
32749
|
-
BufferList.prototype.join = function
|
|
33142
|
+
BufferList.prototype.join = function join10(s) {
|
|
32750
33143
|
if (this.length === 0)
|
|
32751
33144
|
return "";
|
|
32752
33145
|
var p = this.head;
|
|
@@ -54469,6 +54862,9 @@ async function handler4(supabase, args, ctx) {
|
|
|
54469
54862
|
const project_names_raw = args.project_names;
|
|
54470
54863
|
const source = args.source ?? "agent";
|
|
54471
54864
|
const metadata = args.metadata ?? null;
|
|
54865
|
+
if (metadata !== null && (typeof metadata !== "object" || Array.isArray(metadata))) {
|
|
54866
|
+
throw new McpInvalidParams('metadata must be a JSON object of key/value pairs, e.g. {"type":"note"} — not a string, number, or array');
|
|
54867
|
+
}
|
|
54472
54868
|
const update_if_exists = args.update_if_exists ?? false;
|
|
54473
54869
|
const author = args.author ?? "mcp-agent";
|
|
54474
54870
|
const author_type = "agent";
|
|
@@ -54481,7 +54877,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54481
54877
|
throw new McpInvalidParams("project_names must be a JSON array of strings; for a single project use project_name (string)");
|
|
54482
54878
|
}
|
|
54483
54879
|
const project_names = Array.isArray(project_names_raw) ? project_names_raw.filter((s) => typeof s === "string" && s.length > 0) : null;
|
|
54484
|
-
if (!ctx.openaiApiKey) {
|
|
54880
|
+
if (!ctx.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
54485
54881
|
throw new Error("OpenAI API key not configured. Set OPENAI_API_KEY (Edge Function) or CEREFOX_OPENAI_API_KEY (.env, local).");
|
|
54486
54882
|
}
|
|
54487
54883
|
const contentHash2 = await sha256hex(normalizeContent(content));
|
|
@@ -54503,7 +54899,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54503
54899
|
if (chunks2.length === 0)
|
|
54504
54900
|
throw new Error("Content produced no chunks");
|
|
54505
54901
|
const texts2 = chunks2.map((c2) => embeddingInputFor(title, c2));
|
|
54506
|
-
const embeddings2 = await embedBatch(texts2, ctx.openaiApiKey);
|
|
54902
|
+
const embeddings2 = await embedBatch(texts2, ctx.openaiApiKey ?? "");
|
|
54507
54903
|
const totalChars2 = chunks2.reduce((s, c2) => s + c2.char_count, 0);
|
|
54508
54904
|
const chunkData2 = chunks2.map((chunk, i) => ({
|
|
54509
54905
|
chunk_index: i,
|
|
@@ -54513,7 +54909,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54513
54909
|
content: chunk.content,
|
|
54514
54910
|
char_count: chunk.char_count,
|
|
54515
54911
|
embedding: embeddings2[i],
|
|
54516
|
-
embedder:
|
|
54912
|
+
embedder: activeEmbedderName()
|
|
54517
54913
|
}));
|
|
54518
54914
|
const { error: ingestErr2 } = await supabase.rpc("cerefox_ingest_document", {
|
|
54519
54915
|
p_document_id: existingDoc.id,
|
|
@@ -54561,7 +54957,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54561
54957
|
if (chunks2.length === 0)
|
|
54562
54958
|
throw new Error("Content produced no chunks");
|
|
54563
54959
|
const texts2 = chunks2.map((c2) => embeddingInputFor(title, c2));
|
|
54564
|
-
const embeddings2 = await embedBatch(texts2, ctx.openaiApiKey);
|
|
54960
|
+
const embeddings2 = await embedBatch(texts2, ctx.openaiApiKey ?? "");
|
|
54565
54961
|
const totalChars2 = chunks2.reduce((s, c2) => s + c2.char_count, 0);
|
|
54566
54962
|
const chunkData2 = chunks2.map((chunk, i) => ({
|
|
54567
54963
|
chunk_index: i,
|
|
@@ -54571,7 +54967,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54571
54967
|
content: chunk.content,
|
|
54572
54968
|
char_count: chunk.char_count,
|
|
54573
54969
|
embedding: embeddings2[i],
|
|
54574
|
-
embedder:
|
|
54970
|
+
embedder: activeEmbedderName()
|
|
54575
54971
|
}));
|
|
54576
54972
|
const { error: ingestErr2 } = await supabase.rpc("cerefox_ingest_document", {
|
|
54577
54973
|
p_document_id: existingDoc.id,
|
|
@@ -54613,7 +55009,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54613
55009
|
if (chunks.length === 0)
|
|
54614
55010
|
throw new Error("Content produced no chunks");
|
|
54615
55011
|
const texts = chunks.map((c2) => embeddingInputFor(title, c2));
|
|
54616
|
-
const embeddings = await embedBatch(texts, ctx.openaiApiKey);
|
|
55012
|
+
const embeddings = await embedBatch(texts, ctx.openaiApiKey ?? "");
|
|
54617
55013
|
const totalChars = chunks.reduce((s, c2) => s + c2.char_count, 0);
|
|
54618
55014
|
const chunkData = chunks.map((chunk, i) => ({
|
|
54619
55015
|
chunk_index: i,
|
|
@@ -54623,7 +55019,7 @@ async function handler4(supabase, args, ctx) {
|
|
|
54623
55019
|
content: chunk.content,
|
|
54624
55020
|
char_count: chunk.char_count,
|
|
54625
55021
|
embedding: embeddings[i],
|
|
54626
|
-
embedder:
|
|
55022
|
+
embedder: activeEmbedderName()
|
|
54627
55023
|
}));
|
|
54628
55024
|
const { data: ingestResult, error: ingestErr } = await supabase.rpc("cerefox_ingest_document", {
|
|
54629
55025
|
p_document_id: null,
|
|
@@ -54960,7 +55356,7 @@ async function handler9(supabase, args, ctx) {
|
|
|
54960
55356
|
}
|
|
54961
55357
|
if (!query?.trim())
|
|
54962
55358
|
throw new McpInvalidParams("query is required");
|
|
54963
|
-
if (mode !== "fts" && !ctx.openaiApiKey) {
|
|
55359
|
+
if (mode !== "fts" && !ctx.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
54964
55360
|
throw new Error("OpenAI API key not configured. Set OPENAI_API_KEY (Edge Function) or CEREFOX_OPENAI_API_KEY (.env, local).");
|
|
54965
55361
|
}
|
|
54966
55362
|
let projectId = null;
|
|
@@ -54971,7 +55367,7 @@ async function handler9(supabase, args, ctx) {
|
|
|
54971
55367
|
}
|
|
54972
55368
|
let embedding = null;
|
|
54973
55369
|
if (mode !== "fts") {
|
|
54974
|
-
embedding = await getEmbedding(query, ctx.openaiApiKey);
|
|
55370
|
+
embedding = await getEmbedding(query, ctx.openaiApiKey ?? "");
|
|
54975
55371
|
}
|
|
54976
55372
|
const metaFilterParam = metadata_filter && Object.keys(metadata_filter).length > 0 ? { p_metadata_filter: metadata_filter } : {};
|
|
54977
55373
|
let rpcName;
|
|
@@ -68266,6 +68662,7 @@ var exports_server = {};
|
|
|
68266
68662
|
__export(exports_server, {
|
|
68267
68663
|
buildServer: () => buildServer
|
|
68268
68664
|
});
|
|
68665
|
+
import { existsSync as existsSync12, readFileSync as readFileSync12 } from "node:fs";
|
|
68269
68666
|
function buildServer() {
|
|
68270
68667
|
const settings = loadSettings();
|
|
68271
68668
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
@@ -68314,21 +68711,36 @@ async function warnIfSchemaVersionMismatch(supabase) {
|
|
|
68314
68711
|
try {
|
|
68315
68712
|
const { data } = await supabase.rpc("cerefox_schema_version");
|
|
68316
68713
|
const deployed = typeof data === "string" ? data : null;
|
|
68317
|
-
if (deployed
|
|
68318
|
-
|
|
68714
|
+
if (!deployed)
|
|
68715
|
+
return;
|
|
68716
|
+
let bundled = null;
|
|
68717
|
+
try {
|
|
68718
|
+
const assets = resolveServerAssets();
|
|
68719
|
+
if (existsSync12(assets.schemaFile)) {
|
|
68720
|
+
const m = readFileSync12(assets.schemaFile, "utf8").match(SCHEMA_VERSION_RE2);
|
|
68721
|
+
bundled = m ? m[1] : null;
|
|
68722
|
+
}
|
|
68723
|
+
} catch {}
|
|
68724
|
+
if (!bundled)
|
|
68725
|
+
return;
|
|
68726
|
+
if (compareSemver(deployed, bundled) < 0) {
|
|
68727
|
+
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
68728
|
`);
|
|
68320
68729
|
}
|
|
68321
68730
|
} catch {}
|
|
68322
68731
|
}
|
|
68323
|
-
var SERVER_NAME = "cerefox";
|
|
68732
|
+
var SERVER_NAME = "cerefox", SCHEMA_VERSION_RE2;
|
|
68324
68733
|
var init_server3 = __esm(() => {
|
|
68325
68734
|
init_server2();
|
|
68326
68735
|
init_stdio2();
|
|
68327
68736
|
init_types4();
|
|
68328
68737
|
init_dist4();
|
|
68738
|
+
init_compatibility();
|
|
68329
68739
|
init_config();
|
|
68740
|
+
init_server_assets();
|
|
68330
68741
|
init_mcp_tools();
|
|
68331
68742
|
init_meta();
|
|
68743
|
+
SCHEMA_VERSION_RE2 = /^--\s*@version:\s*(\S+)/m;
|
|
68332
68744
|
});
|
|
68333
68745
|
|
|
68334
68746
|
// src/bin/cerefox.ts
|
|
@@ -70166,58 +70578,11 @@ function registerDeleteProject(program2) {
|
|
|
70166
70578
|
// src/cli/commands/deploy-server.ts
|
|
70167
70579
|
init_cli_core();
|
|
70168
70580
|
init_config();
|
|
70581
|
+
init_server_assets();
|
|
70169
70582
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
70170
70583
|
import { existsSync as existsSync7 } from "node:fs";
|
|
70171
70584
|
import { readdirSync as readdirSync2 } from "node:fs";
|
|
70172
70585
|
|
|
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
70586
|
// ../../_shared/db-deploy/index.ts
|
|
70222
70587
|
init_src();
|
|
70223
70588
|
import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync } from "node:fs";
|
|
@@ -74276,112 +74641,18 @@ init_cli_core();
|
|
|
74276
74641
|
|
|
74277
74642
|
// src/cli/util/checks.ts
|
|
74278
74643
|
init_meta();
|
|
74279
|
-
import { existsSync as
|
|
74280
|
-
import { homedir as
|
|
74281
|
-
import { join as
|
|
74644
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7, realpathSync, statSync as statSync2 } from "node:fs";
|
|
74645
|
+
import { homedir as homedir6 } from "node:os";
|
|
74646
|
+
import { join as join9 } from "node:path";
|
|
74282
74647
|
|
|
74283
74648
|
// ../../_shared/ef-meta/index.ts
|
|
74284
|
-
var EF_VERSION = "1.0.0-beta.
|
|
74649
|
+
var EF_VERSION = "1.0.0-beta.4";
|
|
74285
74650
|
|
|
74286
74651
|
// src/cli/util/checks.ts
|
|
74287
74652
|
init_config();
|
|
74288
74653
|
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
|
|
74654
|
+
init_compatibility();
|
|
74655
|
+
init_server_assets();
|
|
74385
74656
|
function checkBinary() {
|
|
74386
74657
|
return {
|
|
74387
74658
|
name: "binary",
|
|
@@ -74432,7 +74703,7 @@ function checkConfig() {
|
|
|
74432
74703
|
hint: "Run `cerefox init` to bootstrap."
|
|
74433
74704
|
};
|
|
74434
74705
|
}
|
|
74435
|
-
if (!
|
|
74706
|
+
if (!existsSync10(envPath)) {
|
|
74436
74707
|
return {
|
|
74437
74708
|
name: "config",
|
|
74438
74709
|
status: "error",
|
|
@@ -74514,6 +74785,14 @@ async function checkSupabase() {
|
|
|
74514
74785
|
async function checkOpenAI() {
|
|
74515
74786
|
const settings = loadSettings();
|
|
74516
74787
|
if (!settings.openaiApiKey) {
|
|
74788
|
+
const { resolveEmbedderKind: resolveEmbedderKind2 } = await Promise.resolve().then(() => exports_embeddings);
|
|
74789
|
+
if (resolveEmbedderKind2() === "local") {
|
|
74790
|
+
return {
|
|
74791
|
+
name: "openai",
|
|
74792
|
+
status: "skipped",
|
|
74793
|
+
detail: "no key set — not needed (local embedder active; see the embedder check)."
|
|
74794
|
+
};
|
|
74795
|
+
}
|
|
74517
74796
|
return {
|
|
74518
74797
|
name: "openai",
|
|
74519
74798
|
status: "warn",
|
|
@@ -74560,7 +74839,7 @@ var SCHEMA_VERSION_RE = /^--\s*@version:\s*(\S+)/m;
|
|
|
74560
74839
|
function readBundledSchemaVersion() {
|
|
74561
74840
|
try {
|
|
74562
74841
|
const assets = resolveServerAssets();
|
|
74563
|
-
if (!
|
|
74842
|
+
if (!existsSync10(assets.schemaFile))
|
|
74564
74843
|
return null;
|
|
74565
74844
|
const m = readFileSync7(assets.schemaFile, "utf8").match(SCHEMA_VERSION_RE);
|
|
74566
74845
|
return m ? m[1] : null;
|
|
@@ -74630,6 +74909,46 @@ async function checkSchemaVersion() {
|
|
|
74630
74909
|
};
|
|
74631
74910
|
}
|
|
74632
74911
|
}
|
|
74912
|
+
var EMBEDDER_CHECK_NAME = "embedder";
|
|
74913
|
+
async function checkEmbedderMismatch() {
|
|
74914
|
+
const settings = loadSettings();
|
|
74915
|
+
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
74916
|
+
return { name: EMBEDDER_CHECK_NAME, status: "skipped", detail: "Supabase config missing; skipped." };
|
|
74917
|
+
}
|
|
74918
|
+
const { activeEmbedderName: activeEmbedderName2 } = await Promise.resolve().then(() => exports_embeddings);
|
|
74919
|
+
const active = activeEmbedderName2();
|
|
74920
|
+
try {
|
|
74921
|
+
const url = `${settings.supabaseUrl.replace(/\/$/, "")}/rest/v1/cerefox_chunks?version_id=is.null&embedder_primary=not.is.null&select=embedder_primary&limit=1000`;
|
|
74922
|
+
const resp = await fetch(url, {
|
|
74923
|
+
headers: { apikey: settings.supabaseKey, Authorization: `Bearer ${settings.supabaseKey}` }
|
|
74924
|
+
});
|
|
74925
|
+
if (!resp.ok) {
|
|
74926
|
+
return { name: EMBEDDER_CHECK_NAME, status: "skipped", detail: `chunk probe returned ${resp.status}; skipped.` };
|
|
74927
|
+
}
|
|
74928
|
+
const rows = await resp.json();
|
|
74929
|
+
const recorded = [...new Set(rows.map((r) => r.embedder_primary))];
|
|
74930
|
+
const stale = recorded.filter((r) => r !== active);
|
|
74931
|
+
if (stale.length === 0) {
|
|
74932
|
+
return {
|
|
74933
|
+
name: EMBEDDER_CHECK_NAME,
|
|
74934
|
+
status: "ok",
|
|
74935
|
+
detail: `configured "${active}"${recorded.length ? " — matches all existing chunks" : " (no embedded chunks yet)"}`
|
|
74936
|
+
};
|
|
74937
|
+
}
|
|
74938
|
+
return {
|
|
74939
|
+
name: EMBEDDER_CHECK_NAME,
|
|
74940
|
+
status: "warn",
|
|
74941
|
+
detail: `configured "${active}" but existing chunks were embedded with ${stale.map((r) => `"${r}"`).join(", ")} — semantic search across them is broken.`,
|
|
74942
|
+
hint: "Run `cerefox server reindex` to re-embed everything with the configured embedder."
|
|
74943
|
+
};
|
|
74944
|
+
} catch (err) {
|
|
74945
|
+
return {
|
|
74946
|
+
name: EMBEDDER_CHECK_NAME,
|
|
74947
|
+
status: "skipped",
|
|
74948
|
+
detail: `probe failed: ${err instanceof Error ? err.message : String(err)}`
|
|
74949
|
+
};
|
|
74950
|
+
}
|
|
74951
|
+
}
|
|
74633
74952
|
var CONTENT_FORMAT_CHECK_NAME = "content format";
|
|
74634
74953
|
async function checkContentFormat() {
|
|
74635
74954
|
const settings = loadSettings();
|
|
@@ -74679,7 +74998,7 @@ async function checkContentFormat() {
|
|
|
74679
74998
|
}
|
|
74680
74999
|
}
|
|
74681
75000
|
function hasCerefoxInJsonFile(path) {
|
|
74682
|
-
if (!
|
|
75001
|
+
if (!existsSync10(path))
|
|
74683
75002
|
return false;
|
|
74684
75003
|
try {
|
|
74685
75004
|
const parsed = JSON.parse(readFileSync7(path, "utf8"));
|
|
@@ -74690,10 +75009,10 @@ function hasCerefoxInJsonFile(path) {
|
|
|
74690
75009
|
}
|
|
74691
75010
|
}
|
|
74692
75011
|
function checkMcpConfigs() {
|
|
74693
|
-
const home =
|
|
74694
|
-
const claudeCodeUser =
|
|
74695
|
-
const claudeCodeProj =
|
|
74696
|
-
const claudeDesktop = process.platform === "darwin" ?
|
|
75012
|
+
const home = homedir6();
|
|
75013
|
+
const claudeCodeUser = join9(home, ".claude.json");
|
|
75014
|
+
const claudeCodeProj = join9(process.cwd(), ".mcp.json");
|
|
75015
|
+
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
75016
|
const found = [];
|
|
74698
75017
|
if (hasCerefoxInJsonFile(claudeCodeUser))
|
|
74699
75018
|
found.push("Claude Code (user)");
|
|
@@ -74716,10 +75035,10 @@ function checkMcpConfigs() {
|
|
|
74716
75035
|
};
|
|
74717
75036
|
}
|
|
74718
75037
|
function checkLegacyShadowEnv() {
|
|
74719
|
-
const home =
|
|
74720
|
-
const homeEnv =
|
|
74721
|
-
const cwdEnv =
|
|
74722
|
-
if (!
|
|
75038
|
+
const home = homedir6();
|
|
75039
|
+
const homeEnv = join9(home, USER_STATE_DIR_NAME, ".env");
|
|
75040
|
+
const cwdEnv = join9(process.cwd(), ".env");
|
|
75041
|
+
if (!existsSync10(homeEnv) || !existsSync10(cwdEnv))
|
|
74723
75042
|
return null;
|
|
74724
75043
|
try {
|
|
74725
75044
|
if (realpathSync(homeEnv) === realpathSync(cwdEnv))
|
|
@@ -74729,7 +75048,7 @@ function checkLegacyShadowEnv() {
|
|
|
74729
75048
|
name: "legacy env",
|
|
74730
75049
|
status: "skipped",
|
|
74731
75050
|
detail: `${cwdEnv} (shadowed by ~/.cerefox/.env)`,
|
|
74732
|
-
hint: "Shadowed by ~/.cerefox/.env and no longer read by anything (Python was removed at
|
|
75051
|
+
hint: "Shadowed by ~/.cerefox/.env and no longer read by anything (Python was removed at v1.0.0). Safe to delete."
|
|
74733
75052
|
};
|
|
74734
75053
|
}
|
|
74735
75054
|
async function checkPostgres() {
|
|
@@ -74866,6 +75185,7 @@ async function runAllChecks(opts = {}) {
|
|
|
74866
75185
|
{ name: "supabase", phase: "Probing Supabase Data API", run: () => checkSupabase() },
|
|
74867
75186
|
{ name: "openai", phase: "Probing OpenAI embeddings", run: () => checkOpenAI() },
|
|
74868
75187
|
{ name: "schema + RPCs", phase: "Reading schema + RPC version", run: () => checkSchemaVersion() },
|
|
75188
|
+
{ name: "embedder", phase: "Checking embedder consistency", run: () => checkEmbedderMismatch() },
|
|
74869
75189
|
{ name: "content format", phase: "Checking chunk reconstruction format", run: () => checkContentFormat() },
|
|
74870
75190
|
{ name: "edge functions", phase: "Probing Edge Function versions", run: () => checkEdgeFunctionsCompat() },
|
|
74871
75191
|
{ name: "postgres", phase: "Probing Postgres DDL endpoint", run: () => checkPostgres() },
|
|
@@ -75316,7 +75636,7 @@ class IngestionPipeline {
|
|
|
75316
75636
|
constructor(deps) {
|
|
75317
75637
|
this.db = new IngestionDbBridge(deps.supabase);
|
|
75318
75638
|
this.apiKey = deps.openAiApiKey;
|
|
75319
|
-
this.embedderModel = deps.embedderModel ??
|
|
75639
|
+
this.embedderModel = deps.embedderModel ?? activeEmbedderName();
|
|
75320
75640
|
this.settings = { ...loadPipelineSettings(), ...deps.settings ?? {} };
|
|
75321
75641
|
}
|
|
75322
75642
|
async ingestText(opts) {
|
|
@@ -75681,7 +76001,7 @@ async function action18(path, options) {
|
|
|
75681
76001
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
75682
76002
|
throw userError("Supabase credentials not configured — run `cerefox init` first.");
|
|
75683
76003
|
}
|
|
75684
|
-
if (!settings.openaiApiKey) {
|
|
76004
|
+
if (!settings.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
75685
76005
|
throw userError("OPENAI_API_KEY not set — required for embeddings during ingest.");
|
|
75686
76006
|
}
|
|
75687
76007
|
const supabase = createClient(settings.supabaseUrl, settings.supabaseKey, {
|
|
@@ -75744,7 +76064,7 @@ init_cli_core();
|
|
|
75744
76064
|
init_config();
|
|
75745
76065
|
var import_cli_progress = __toESM(require_cli_progress(), 1);
|
|
75746
76066
|
import { readdirSync as readdirSync4, statSync as statSync3 } from "node:fs";
|
|
75747
|
-
import { basename as basename3, extname as extname4, join as
|
|
76067
|
+
import { basename as basename3, extname as extname4, join as join10 } from "node:path";
|
|
75748
76068
|
function walk(dir, extensions) {
|
|
75749
76069
|
let entries;
|
|
75750
76070
|
try {
|
|
@@ -75754,7 +76074,7 @@ function walk(dir, extensions) {
|
|
|
75754
76074
|
}
|
|
75755
76075
|
const files = [];
|
|
75756
76076
|
for (const name of entries) {
|
|
75757
|
-
const full =
|
|
76077
|
+
const full = join10(dir, name);
|
|
75758
76078
|
let stat;
|
|
75759
76079
|
try {
|
|
75760
76080
|
stat = statSync3(full);
|
|
@@ -75788,7 +76108,7 @@ async function action19(dir, options) {
|
|
|
75788
76108
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
75789
76109
|
throw userError("Supabase credentials not configured — run `cerefox init` first.");
|
|
75790
76110
|
}
|
|
75791
|
-
if (!settings.openaiApiKey) {
|
|
76111
|
+
if (!settings.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
75792
76112
|
throw userError("OPENAI_API_KEY not set — required for embeddings during ingest.");
|
|
75793
76113
|
}
|
|
75794
76114
|
const supabase = createClient(settings.supabaseUrl, settings.supabaseKey, {
|
|
@@ -75851,19 +76171,20 @@ function registerIngestDir(program2) {
|
|
|
75851
76171
|
// src/cli/commands/init.ts
|
|
75852
76172
|
init_cli_core();
|
|
75853
76173
|
init_config();
|
|
76174
|
+
init_compatibility();
|
|
75854
76175
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
75855
76176
|
import {
|
|
75856
76177
|
chmodSync,
|
|
75857
76178
|
copyFileSync as copyFileSync2,
|
|
75858
|
-
existsSync as
|
|
75859
|
-
mkdirSync as
|
|
76179
|
+
existsSync as existsSync11,
|
|
76180
|
+
mkdirSync as mkdirSync4,
|
|
75860
76181
|
readFileSync as readFileSync11,
|
|
75861
76182
|
writeFileSync as writeFileSync4
|
|
75862
76183
|
} from "node:fs";
|
|
75863
|
-
import { homedir as
|
|
75864
|
-
import { dirname as dirname4, join as
|
|
76184
|
+
import { homedir as homedir7 } from "node:os";
|
|
76185
|
+
import { dirname as dirname4, join as join11 } from "node:path";
|
|
75865
76186
|
async function readConfigFile(path) {
|
|
75866
|
-
if (!
|
|
76187
|
+
if (!existsSync11(path)) {
|
|
75867
76188
|
throw userError(`--config file not found: ${path}`);
|
|
75868
76189
|
}
|
|
75869
76190
|
let parsed;
|
|
@@ -76165,7 +76486,7 @@ async function postWriteLifecycle(envPath, options) {
|
|
|
76165
76486
|
println(c.dim(` Config in effect: ${envPath}`));
|
|
76166
76487
|
}
|
|
76167
76488
|
function writeAnswersTo(target, answers) {
|
|
76168
|
-
|
|
76489
|
+
mkdirSync4(dirname4(target), { recursive: true });
|
|
76169
76490
|
writeFileSync4(target, buildEnvFile(answers), "utf8");
|
|
76170
76491
|
if (process.platform !== "win32") {
|
|
76171
76492
|
try {
|
|
@@ -76176,12 +76497,12 @@ function writeAnswersTo(target, answers) {
|
|
|
76176
76497
|
}
|
|
76177
76498
|
}
|
|
76178
76499
|
async function action21(options) {
|
|
76179
|
-
const homeEnv =
|
|
76180
|
-
const cwdEnv =
|
|
76500
|
+
const homeEnv = join11(homedir7(), USER_STATE_DIR_NAME, ".env");
|
|
76501
|
+
const cwdEnv = join11(process.cwd(), ".env");
|
|
76181
76502
|
const explicitDir = (process.env.CEREFOX_CONFIG_DIR ?? "").trim();
|
|
76182
76503
|
if (explicitDir) {
|
|
76183
76504
|
const target2 = resolveEnvFile();
|
|
76184
|
-
if (
|
|
76505
|
+
if (existsSync11(target2) && !options.force) {
|
|
76185
76506
|
println(c.yellow(`⚠ Config already exists at ${target2}.`));
|
|
76186
76507
|
const ok2 = await confirm("Overwrite?", true);
|
|
76187
76508
|
if (!ok2) {
|
|
@@ -76203,7 +76524,7 @@ async function action21(options) {
|
|
|
76203
76524
|
await postWriteLifecycle(target2, options);
|
|
76204
76525
|
return;
|
|
76205
76526
|
}
|
|
76206
|
-
if (
|
|
76527
|
+
if (existsSync11(homeEnv) && !options.force) {
|
|
76207
76528
|
println(c.yellow(`⚠ Config already exists at ${homeEnv}.`));
|
|
76208
76529
|
const ok2 = await confirm("Overwrite?", true);
|
|
76209
76530
|
if (!ok2) {
|
|
@@ -76224,12 +76545,12 @@ async function action21(options) {
|
|
|
76224
76545
|
await postWriteLifecycle(homeEnv, options);
|
|
76225
76546
|
return;
|
|
76226
76547
|
}
|
|
76227
|
-
if (
|
|
76548
|
+
if (existsSync11(cwdEnv) && !options.force && !options.config) {
|
|
76228
76549
|
printMigrationMenu(cwdEnv, homeEnv);
|
|
76229
76550
|
const ch = await promptMigrationChoice();
|
|
76230
76551
|
println("");
|
|
76231
76552
|
if (ch === "c") {
|
|
76232
|
-
|
|
76553
|
+
mkdirSync4(dirname4(homeEnv), { recursive: true });
|
|
76233
76554
|
copyFileSync2(cwdEnv, homeEnv);
|
|
76234
76555
|
if (process.platform !== "win32") {
|
|
76235
76556
|
try {
|
|
@@ -76478,6 +76799,23 @@ function registerMcp(program2) {
|
|
|
76478
76799
|
});
|
|
76479
76800
|
}
|
|
76480
76801
|
|
|
76802
|
+
// src/cli/commands/embedder-warmup.ts
|
|
76803
|
+
function registerEmbedderWarmup(program2) {
|
|
76804
|
+
program2.command("embedder-warmup", { hidden: true }).description("Download + warm the local ONNX embedding model (Cerefox Local).").action(async () => {
|
|
76805
|
+
if (process.env.CEREFOX_EMBEDDER !== "local") {
|
|
76806
|
+
process.stderr.write(`embedder-warmup: CEREFOX_EMBEDDER is not 'local' — nothing to warm (the OpenAI embedder has no local model).
|
|
76807
|
+
`);
|
|
76808
|
+
process.exitCode = 1;
|
|
76809
|
+
return;
|
|
76810
|
+
}
|
|
76811
|
+
const onnx = await Promise.resolve().then(() => (init_onnx_embedder(), exports_onnx_embedder));
|
|
76812
|
+
await onnx.warmup();
|
|
76813
|
+
const [vec] = await onnx.onnxEmbed(["warmup"], "query");
|
|
76814
|
+
process.stderr.write(`[cerefox-embed] warm — ${vec.length}-dim vectors ready.
|
|
76815
|
+
`);
|
|
76816
|
+
});
|
|
76817
|
+
}
|
|
76818
|
+
|
|
76481
76819
|
// src/cli/commands/metadata-search.ts
|
|
76482
76820
|
init_cli_core();
|
|
76483
76821
|
init_client();
|
|
@@ -76637,35 +76975,35 @@ function registerReindex(program2) {
|
|
|
76637
76975
|
// src/cli/commands/restore.ts
|
|
76638
76976
|
init_cli_core();
|
|
76639
76977
|
init_client();
|
|
76640
|
-
import { existsSync as
|
|
76641
|
-
import { homedir as
|
|
76642
|
-
import { join as
|
|
76978
|
+
import { existsSync as existsSync13, readFileSync as readFileSync13, readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
|
|
76979
|
+
import { homedir as homedir8 } from "node:os";
|
|
76980
|
+
import { join as join12, resolve as resolve4 } from "node:path";
|
|
76643
76981
|
function expandHome2(path) {
|
|
76644
76982
|
if (path === "~")
|
|
76645
|
-
return
|
|
76983
|
+
return homedir8();
|
|
76646
76984
|
if (path.startsWith("~/"))
|
|
76647
|
-
return
|
|
76985
|
+
return join12(homedir8(), path.slice(2));
|
|
76648
76986
|
return path;
|
|
76649
76987
|
}
|
|
76650
76988
|
function resolveBackupFile(target) {
|
|
76651
76989
|
const path = resolve4(expandHome2(target));
|
|
76652
|
-
if (!
|
|
76990
|
+
if (!existsSync13(path)) {
|
|
76653
76991
|
throw userError(`Backup path not found: ${target}`);
|
|
76654
76992
|
}
|
|
76655
76993
|
const stat = statSync4(path);
|
|
76656
76994
|
if (stat.isFile())
|
|
76657
76995
|
return path;
|
|
76658
|
-
const candidates = readdirSync5(path).filter((n) => n.endsWith(".json") && n.startsWith("cerefox-")).map((n) => ({ name: n, mtime: statSync4(
|
|
76996
|
+
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
76997
|
if (candidates.length === 0) {
|
|
76660
76998
|
throw userError(`No cerefox-*.json files in ${path}`);
|
|
76661
76999
|
}
|
|
76662
|
-
return
|
|
77000
|
+
return join12(path, candidates[0].name);
|
|
76663
77001
|
}
|
|
76664
77002
|
async function action28(target, options) {
|
|
76665
77003
|
const file = resolveBackupFile(target);
|
|
76666
77004
|
let payload;
|
|
76667
77005
|
try {
|
|
76668
|
-
payload = JSON.parse(
|
|
77006
|
+
payload = JSON.parse(readFileSync13(file, "utf8"));
|
|
76669
77007
|
} catch (err) {
|
|
76670
77008
|
throw userError(`Could not parse backup file ${file}: ${err instanceof Error ? err.message : String(err)}`);
|
|
76671
77009
|
}
|
|
@@ -76730,7 +77068,7 @@ init_config();
|
|
|
76730
77068
|
async function embedQuery(query) {
|
|
76731
77069
|
const settings = loadSettings();
|
|
76732
77070
|
const apiKey = settings.openaiApiKey;
|
|
76733
|
-
if (!apiKey) {
|
|
77071
|
+
if (!apiKey && resolveEmbedderKind() !== "local") {
|
|
76734
77072
|
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
77073
|
}
|
|
76736
77074
|
try {
|
|
@@ -77045,7 +77383,7 @@ import { randomBytes } from "node:crypto";
|
|
|
77045
77383
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
77046
77384
|
|
|
77047
77385
|
// src/cli/util/env-file.ts
|
|
77048
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
77386
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync14, readFileSync as readFileSync14, writeFileSync as writeFileSync5 } from "node:fs";
|
|
77049
77387
|
import { dirname as dirname5 } from "node:path";
|
|
77050
77388
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
77051
77389
|
function escapeRegExp(s) {
|
|
@@ -77055,12 +77393,12 @@ function upsertEnvVar(path, key, value, opts = {}) {
|
|
|
77055
77393
|
const line = `${key}=${value}`;
|
|
77056
77394
|
const header = opts.comment ? `# ${opts.comment}
|
|
77057
77395
|
` : "";
|
|
77058
|
-
if (!
|
|
77396
|
+
if (!existsSync14(path)) {
|
|
77059
77397
|
writeFileSync5(path, `${header}${line}
|
|
77060
77398
|
`, { mode: 384 });
|
|
77061
77399
|
return { path, action: "created" };
|
|
77062
77400
|
}
|
|
77063
|
-
const original =
|
|
77401
|
+
const original = readFileSync14(path, "utf8");
|
|
77064
77402
|
let backupPath;
|
|
77065
77403
|
if (!opts.noBackup) {
|
|
77066
77404
|
backupPath = `${path}.pre-cerefox.bak`;
|
|
@@ -77085,9 +77423,9 @@ ${header}${line}
|
|
|
77085
77423
|
return { path, action: action32, backupPath };
|
|
77086
77424
|
}
|
|
77087
77425
|
function readEnvVar(path, key) {
|
|
77088
|
-
if (!
|
|
77426
|
+
if (!existsSync14(path))
|
|
77089
77427
|
return null;
|
|
77090
|
-
const m =
|
|
77428
|
+
const m = readFileSync14(path, "utf8").match(new RegExp(`^\\s*${escapeRegExp(key)}=(.*)$`, "m"));
|
|
77091
77429
|
return m ? m[1].trim() : null;
|
|
77092
77430
|
}
|
|
77093
77431
|
function envGitignoreWarning(path) {
|
|
@@ -78555,8 +78893,8 @@ var _baseMimes = {
|
|
|
78555
78893
|
var baseMimes = _baseMimes;
|
|
78556
78894
|
|
|
78557
78895
|
// ../../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
|
|
78896
|
+
import { createReadStream, existsSync as existsSync15, statSync as statSync5 } from "node:fs";
|
|
78897
|
+
import { join as join13 } from "node:path";
|
|
78560
78898
|
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
78899
|
var ENCODINGS = {
|
|
78562
78900
|
br: ".br",
|
|
@@ -78588,7 +78926,7 @@ var tryDecodeURI = (str) => tryDecode(str, decodeURI);
|
|
|
78588
78926
|
var serveStatic = (options = { root: "" }) => {
|
|
78589
78927
|
const root = options.root || "";
|
|
78590
78928
|
const optionPath = options.path;
|
|
78591
|
-
if (root !== "" && !
|
|
78929
|
+
if (root !== "" && !existsSync15(root))
|
|
78592
78930
|
console.error(`serveStatic: root path '${root}' is not found, are you sure it's correct?`);
|
|
78593
78931
|
return async (c2, next) => {
|
|
78594
78932
|
if (c2.finalized)
|
|
@@ -78605,11 +78943,11 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
78605
78943
|
await options.onNotFound?.(c2.req.path, c2);
|
|
78606
78944
|
return next();
|
|
78607
78945
|
}
|
|
78608
|
-
let path =
|
|
78946
|
+
let path = join13(root, !optionPath && options.rewriteRequestPath ? options.rewriteRequestPath(filename, c2) : filename);
|
|
78609
78947
|
let stats = getStats(path);
|
|
78610
78948
|
if (stats && stats.isDirectory()) {
|
|
78611
78949
|
const indexFile = options.index ?? "index.html";
|
|
78612
|
-
path =
|
|
78950
|
+
path = join13(path, indexFile);
|
|
78613
78951
|
stats = getStats(path);
|
|
78614
78952
|
}
|
|
78615
78953
|
if (!stats) {
|
|
@@ -78666,9 +79004,9 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
78666
79004
|
};
|
|
78667
79005
|
|
|
78668
79006
|
// src/web/server.ts
|
|
78669
|
-
import { existsSync as
|
|
78670
|
-
import { readFileSync as
|
|
78671
|
-
import { join as
|
|
79007
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
79008
|
+
import { readFileSync as readFileSync17 } from "node:fs";
|
|
79009
|
+
import { join as join17 } from "node:path";
|
|
78672
79010
|
|
|
78673
79011
|
// ../../node_modules/.bun/hono@4.12.29/node_modules/hono/dist/compose.js
|
|
78674
79012
|
var compose = (middleware, onError, onNotFound) => {
|
|
@@ -80697,7 +81035,7 @@ async function runSearch(ctx, opts) {
|
|
|
80697
81035
|
throw error4;
|
|
80698
81036
|
return (data2 ?? []).map(projectChunkResult);
|
|
80699
81037
|
}
|
|
80700
|
-
if (!ctx.openAiApiKey) {
|
|
81038
|
+
if (!ctx.openAiApiKey && resolveEmbedderKind() !== "local") {
|
|
80701
81039
|
throw new HttpError(503, "Embedder not available");
|
|
80702
81040
|
}
|
|
80703
81041
|
const embedding = await getEmbedding(query, ctx.openAiApiKey);
|
|
@@ -81238,7 +81576,6 @@ function registerDocumentReadRoutes(app, ctx) {
|
|
|
81238
81576
|
return c2.json({ exists: false });
|
|
81239
81577
|
});
|
|
81240
81578
|
}
|
|
81241
|
-
|
|
81242
81579
|
// src/web/routes/documents-write.ts
|
|
81243
81580
|
async function createAuditEntry(ctx, args) {
|
|
81244
81581
|
try {
|
|
@@ -81289,7 +81626,7 @@ function registerDocumentWriteRoutes(app, ctx) {
|
|
|
81289
81626
|
const proposedHash = content.trim() ? contentHash(content) : null;
|
|
81290
81627
|
const contentChanged = proposedHash !== null && currentHash !== null && proposedHash !== currentHash;
|
|
81291
81628
|
if (contentChanged) {
|
|
81292
|
-
if (!ctx.openAiApiKey) {
|
|
81629
|
+
if (!ctx.openAiApiKey && resolveEmbedderKind() !== "local") {
|
|
81293
81630
|
return c2.json({
|
|
81294
81631
|
success: false,
|
|
81295
81632
|
error: "Embedder not available — set OPENAI_API_KEY in your config"
|
|
@@ -81445,14 +81782,13 @@ function registerDocumentWriteRoutes(app, ctx) {
|
|
|
81445
81782
|
return c2.json({ archived });
|
|
81446
81783
|
});
|
|
81447
81784
|
}
|
|
81448
|
-
|
|
81449
81785
|
// src/web/routes/ingest.ts
|
|
81450
81786
|
function notReady(error3) {
|
|
81451
81787
|
return { success: false, error: error3 };
|
|
81452
81788
|
}
|
|
81453
81789
|
function registerIngestRoutes(app, ctx) {
|
|
81454
81790
|
app.post("/api/v1/ingest", async (c2) => {
|
|
81455
|
-
if (!ctx.openAiApiKey) {
|
|
81791
|
+
if (!ctx.openAiApiKey && resolveEmbedderKind() !== "local") {
|
|
81456
81792
|
return c2.json(notReady("Embedder not available"), 503);
|
|
81457
81793
|
}
|
|
81458
81794
|
let body;
|
|
@@ -81500,7 +81836,7 @@ function registerIngestRoutes(app, ctx) {
|
|
|
81500
81836
|
}
|
|
81501
81837
|
});
|
|
81502
81838
|
app.post("/api/v1/ingest/file", async (c2) => {
|
|
81503
|
-
if (!ctx.openAiApiKey) {
|
|
81839
|
+
if (!ctx.openAiApiKey && resolveEmbedderKind() !== "local") {
|
|
81504
81840
|
return c2.json(notReady("Embedder not available"), 503);
|
|
81505
81841
|
}
|
|
81506
81842
|
let form;
|
|
@@ -81562,7 +81898,7 @@ function registerIngestRoutes(app, ctx) {
|
|
|
81562
81898
|
}
|
|
81563
81899
|
});
|
|
81564
81900
|
app.post("/api/v1/documents/:document_id/upload", async (c2) => {
|
|
81565
|
-
if (!ctx.openAiApiKey) {
|
|
81901
|
+
if (!ctx.openAiApiKey && resolveEmbedderKind() !== "local") {
|
|
81566
81902
|
return c2.json(notReady("Embedder not available"), 503);
|
|
81567
81903
|
}
|
|
81568
81904
|
const documentId = c2.req.param("document_id");
|
|
@@ -81617,12 +81953,12 @@ import { execFileSync } from "node:child_process";
|
|
|
81617
81953
|
|
|
81618
81954
|
// src/web/docs.ts
|
|
81619
81955
|
import {
|
|
81620
|
-
existsSync as
|
|
81621
|
-
readFileSync as
|
|
81956
|
+
existsSync as existsSync16,
|
|
81957
|
+
readFileSync as readFileSync15,
|
|
81622
81958
|
readdirSync as readdirSync6,
|
|
81623
81959
|
statSync as statSync6
|
|
81624
81960
|
} from "node:fs";
|
|
81625
|
-
import { basename as basename5, dirname as dirname6, join as
|
|
81961
|
+
import { basename as basename5, dirname as dirname6, join as join14, resolve as resolve5 } from "node:path";
|
|
81626
81962
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
81627
81963
|
var TOP_LEVEL_DOCS = [
|
|
81628
81964
|
{ filename: "README.md", path: "README.md", category: "readme" },
|
|
@@ -81643,32 +81979,32 @@ function moduleDir2() {
|
|
|
81643
81979
|
function resolveDocsRoots() {
|
|
81644
81980
|
const here = moduleDir2();
|
|
81645
81981
|
const pkgRootCandidates = [
|
|
81646
|
-
|
|
81647
|
-
|
|
81982
|
+
join14(here, "..", ".."),
|
|
81983
|
+
join14(here, "..", "..", "..", "..")
|
|
81648
81984
|
];
|
|
81649
81985
|
let pkgGuides = null;
|
|
81650
81986
|
let pkgTopLevel = null;
|
|
81651
81987
|
for (const pkg of pkgRootCandidates) {
|
|
81652
|
-
const guides =
|
|
81653
|
-
if (
|
|
81988
|
+
const guides = join14(pkg, "docs", "guides");
|
|
81989
|
+
if (existsSync16(guides) && statSync6(guides).isDirectory()) {
|
|
81654
81990
|
pkgGuides = guides;
|
|
81655
81991
|
pkgTopLevel = pkg;
|
|
81656
81992
|
break;
|
|
81657
81993
|
}
|
|
81658
81994
|
}
|
|
81659
|
-
const repoCandidate =
|
|
81660
|
-
const repoGuides =
|
|
81995
|
+
const repoCandidate = join14(here, "..", "..", "..", "..");
|
|
81996
|
+
const repoGuides = join14(repoCandidate, "docs", "guides");
|
|
81661
81997
|
const repoTopLevel = repoCandidate;
|
|
81662
81998
|
return {
|
|
81663
81999
|
pkgGuides,
|
|
81664
82000
|
pkgTopLevel,
|
|
81665
|
-
repoGuides:
|
|
81666
|
-
repoTopLevel:
|
|
82001
|
+
repoGuides: existsSync16(repoGuides) ? repoGuides : null,
|
|
82002
|
+
repoTopLevel: existsSync16(join14(repoTopLevel, "README.md")) ? repoTopLevel : null
|
|
81667
82003
|
};
|
|
81668
82004
|
}
|
|
81669
82005
|
function readH1(filePath) {
|
|
81670
82006
|
try {
|
|
81671
|
-
const content =
|
|
82007
|
+
const content = readFileSync15(filePath, "utf8");
|
|
81672
82008
|
const match2 = content.match(/^#\s+(.+?)\s*$/m);
|
|
81673
82009
|
return match2 ? match2[1] : null;
|
|
81674
82010
|
} catch {
|
|
@@ -81688,8 +82024,8 @@ function listBundledDocs2() {
|
|
|
81688
82024
|
const topRoot = pkgTopLevel ?? repoTopLevel;
|
|
81689
82025
|
if (topRoot) {
|
|
81690
82026
|
for (const t of TOP_LEVEL_DOCS) {
|
|
81691
|
-
const abs =
|
|
81692
|
-
if (
|
|
82027
|
+
const abs = join14(topRoot, t.filename);
|
|
82028
|
+
if (existsSync16(abs)) {
|
|
81693
82029
|
entries.push(entryForFile(abs, t.path, t.category));
|
|
81694
82030
|
}
|
|
81695
82031
|
}
|
|
@@ -81698,7 +82034,7 @@ function listBundledDocs2() {
|
|
|
81698
82034
|
if (guidesRoot) {
|
|
81699
82035
|
const names = readdirSync6(guidesRoot).filter((n) => n.endsWith(".md")).sort();
|
|
81700
82036
|
for (const name of names) {
|
|
81701
|
-
const abs =
|
|
82037
|
+
const abs = join14(guidesRoot, name);
|
|
81702
82038
|
entries.push(entryForFile(abs, `guides/${name}`, "guide"));
|
|
81703
82039
|
}
|
|
81704
82040
|
}
|
|
@@ -81716,9 +82052,9 @@ function readDoc(docPath) {
|
|
|
81716
82052
|
if (!candidate.startsWith(rootResolved + "/") && candidate !== rootResolved) {
|
|
81717
82053
|
return null;
|
|
81718
82054
|
}
|
|
81719
|
-
if (
|
|
82055
|
+
if (existsSync16(candidate) && statSync6(candidate).isFile()) {
|
|
81720
82056
|
try {
|
|
81721
|
-
return
|
|
82057
|
+
return readFileSync15(candidate, "utf8");
|
|
81722
82058
|
} catch {
|
|
81723
82059
|
return null;
|
|
81724
82060
|
}
|
|
@@ -81727,6 +82063,7 @@ function readDoc(docPath) {
|
|
|
81727
82063
|
}
|
|
81728
82064
|
|
|
81729
82065
|
// src/web/routes/meta.ts
|
|
82066
|
+
init_compatibility();
|
|
81730
82067
|
function resolveGitCommitShort() {
|
|
81731
82068
|
const env4 = process.env.CEREFOX_GIT_COMMIT;
|
|
81732
82069
|
if (env4)
|
|
@@ -81746,7 +82083,7 @@ var VERSION_INFO = {
|
|
|
81746
82083
|
git_commit_short: resolveGitCommitShort(),
|
|
81747
82084
|
build_date: process.env.CEREFOX_BUILD_DATE ?? null
|
|
81748
82085
|
};
|
|
81749
|
-
var
|
|
82086
|
+
var SCHEMA_VERSION_RE3 = /^--\s*@version:\s*(\S+)/m;
|
|
81750
82087
|
function registerMetaRoutes(app, ctx) {
|
|
81751
82088
|
app.get("/api/v1/version", (c2) => c2.json(VERSION_INFO));
|
|
81752
82089
|
app.get("/api/v1/docs", (c2) => c2.json(listBundledDocs2()));
|
|
@@ -81763,18 +82100,18 @@ function registerMetaRoutes(app, ctx) {
|
|
|
81763
82100
|
app.get("/api/v1/schema-version", async (c2) => {
|
|
81764
82101
|
let bundled = null;
|
|
81765
82102
|
try {
|
|
81766
|
-
const { readFileSync:
|
|
82103
|
+
const { readFileSync: readFileSync16, existsSync: existsSync17 } = await import("node:fs");
|
|
81767
82104
|
const { fileURLToPath: fileURLToPath4 } = await import("node:url");
|
|
81768
|
-
const { dirname: dirname7, join:
|
|
82105
|
+
const { dirname: dirname7, join: join15 } = await import("node:path");
|
|
81769
82106
|
const here = dirname7(fileURLToPath4(import.meta.url));
|
|
81770
82107
|
const candidates = [
|
|
81771
|
-
|
|
81772
|
-
|
|
82108
|
+
join15(here, "..", "..", "..", "db", "schema.sql"),
|
|
82109
|
+
join15(here, "..", "..", "..", "..", "..", "src", "cerefox", "db", "schema.sql")
|
|
81773
82110
|
];
|
|
81774
82111
|
for (const path of candidates) {
|
|
81775
|
-
if (
|
|
81776
|
-
const sql =
|
|
81777
|
-
const match2 = sql.match(
|
|
82112
|
+
if (existsSync17(path)) {
|
|
82113
|
+
const sql = readFileSync16(path, "utf8");
|
|
82114
|
+
const match2 = sql.match(SCHEMA_VERSION_RE3);
|
|
81778
82115
|
bundled = match2 ? match2[1] : null;
|
|
81779
82116
|
break;
|
|
81780
82117
|
}
|
|
@@ -81869,17 +82206,17 @@ function registerPostgrestProxy(app) {
|
|
|
81869
82206
|
|
|
81870
82207
|
// src/web/routes/preferences.ts
|
|
81871
82208
|
init_config();
|
|
81872
|
-
import { existsSync as
|
|
81873
|
-
import { join as
|
|
82209
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync5, readFileSync as readFileSync16, writeFileSync as writeFileSync6 } from "node:fs";
|
|
82210
|
+
import { join as join15 } from "node:path";
|
|
81874
82211
|
function isTheme(v) {
|
|
81875
82212
|
return v === "auto" || v === "light" || v === "dark";
|
|
81876
82213
|
}
|
|
81877
82214
|
function prefsFile() {
|
|
81878
|
-
return
|
|
82215
|
+
return join15(userStateDir(), "web-prefs.json");
|
|
81879
82216
|
}
|
|
81880
82217
|
function readPrefs() {
|
|
81881
82218
|
try {
|
|
81882
|
-
const raw2 = JSON.parse(
|
|
82219
|
+
const raw2 = JSON.parse(readFileSync16(prefsFile(), "utf8"));
|
|
81883
82220
|
if (isTheme(raw2.theme))
|
|
81884
82221
|
return { theme: raw2.theme };
|
|
81885
82222
|
} catch {}
|
|
@@ -81895,8 +82232,8 @@ function registerPreferencesRoutes(app) {
|
|
|
81895
82232
|
const next = { ...readPrefs(), theme: body.theme };
|
|
81896
82233
|
try {
|
|
81897
82234
|
const dir = userStateDir();
|
|
81898
|
-
if (!
|
|
81899
|
-
|
|
82235
|
+
if (!existsSync17(dir))
|
|
82236
|
+
mkdirSync5(dir, { recursive: true });
|
|
81900
82237
|
writeFileSync6(prefsFile(), `${JSON.stringify(next, null, 2)}
|
|
81901
82238
|
`);
|
|
81902
82239
|
} catch (err) {
|
|
@@ -81967,21 +82304,21 @@ function registerProjectsRoutes(app, ctx) {
|
|
|
81967
82304
|
}
|
|
81968
82305
|
|
|
81969
82306
|
// src/web/static.ts
|
|
81970
|
-
import { existsSync as
|
|
81971
|
-
import { dirname as dirname7, join as
|
|
82307
|
+
import { existsSync as existsSync18, statSync as statSync7 } from "node:fs";
|
|
82308
|
+
import { dirname as dirname7, join as join16 } from "node:path";
|
|
81972
82309
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
81973
82310
|
function moduleDir3() {
|
|
81974
82311
|
return dirname7(fileURLToPath4(import.meta.url));
|
|
81975
82312
|
}
|
|
81976
82313
|
function isUsableSpaDir(dir) {
|
|
81977
|
-
return
|
|
82314
|
+
return existsSync18(dir) && statSync7(dir).isDirectory() && existsSync18(join16(dir, "index.html"));
|
|
81978
82315
|
}
|
|
81979
82316
|
function resolveSpaDist() {
|
|
81980
82317
|
const here = moduleDir3();
|
|
81981
82318
|
const candidates = [
|
|
81982
|
-
|
|
81983
|
-
|
|
81984
|
-
|
|
82319
|
+
join16(here, "..", "frontend"),
|
|
82320
|
+
join16(here, "..", "..", "..", "..", "frontend", "dist"),
|
|
82321
|
+
join16(here, "..", "..", "dist", "frontend")
|
|
81985
82322
|
];
|
|
81986
82323
|
for (const c2 of candidates) {
|
|
81987
82324
|
if (isUsableSpaDir(c2))
|
|
@@ -81992,11 +82329,11 @@ function resolveSpaDist() {
|
|
|
81992
82329
|
function resolveStaticDir() {
|
|
81993
82330
|
const here = moduleDir3();
|
|
81994
82331
|
const candidates = [
|
|
81995
|
-
|
|
81996
|
-
|
|
82332
|
+
join16(here, "..", "static"),
|
|
82333
|
+
join16(here, "..", "..", "..", "..", "web", "static")
|
|
81997
82334
|
];
|
|
81998
82335
|
for (const c2 of candidates) {
|
|
81999
|
-
if (
|
|
82336
|
+
if (existsSync18(c2) && statSync7(c2).isDirectory())
|
|
82000
82337
|
return c2;
|
|
82001
82338
|
}
|
|
82002
82339
|
return null;
|
|
@@ -82041,6 +82378,7 @@ var ROOT_REDIRECT_HTML = `<!DOCTYPE html>
|
|
|
82041
82378
|
init_meta();
|
|
82042
82379
|
init_cli_core();
|
|
82043
82380
|
init_config();
|
|
82381
|
+
init_compatibility();
|
|
82044
82382
|
function buildApp(ctx = buildWebContext()) {
|
|
82045
82383
|
const app = new Hono2;
|
|
82046
82384
|
if (true) {
|
|
@@ -82082,9 +82420,9 @@ function buildApp(ctx = buildWebContext()) {
|
|
|
82082
82420
|
root: spaDist,
|
|
82083
82421
|
rewriteRequestPath: (path) => path.replace(/^\/app/, "") || "/"
|
|
82084
82422
|
}));
|
|
82085
|
-
const indexPath =
|
|
82086
|
-
if (
|
|
82087
|
-
const indexHtml =
|
|
82423
|
+
const indexPath = join17(spaDist, "index.html");
|
|
82424
|
+
if (existsSync19(indexPath)) {
|
|
82425
|
+
const indexHtml = readFileSync17(indexPath, "utf8");
|
|
82088
82426
|
app.get("/app/*", (c2) => c2.html(indexHtml));
|
|
82089
82427
|
}
|
|
82090
82428
|
}
|
|
@@ -82142,28 +82480,28 @@ async function buildWebServer(options = {}) {
|
|
|
82142
82480
|
// src/web/daemon.ts
|
|
82143
82481
|
import { spawn } from "node:child_process";
|
|
82144
82482
|
import {
|
|
82145
|
-
existsSync as
|
|
82146
|
-
mkdirSync as
|
|
82483
|
+
existsSync as existsSync20,
|
|
82484
|
+
mkdirSync as mkdirSync6,
|
|
82147
82485
|
openSync,
|
|
82148
|
-
readFileSync as
|
|
82486
|
+
readFileSync as readFileSync18,
|
|
82149
82487
|
rmSync,
|
|
82150
82488
|
writeFileSync as writeFileSync7
|
|
82151
82489
|
} from "node:fs";
|
|
82152
|
-
import { homedir as
|
|
82153
|
-
import { join as
|
|
82154
|
-
var STATE_DIR =
|
|
82155
|
-
var PID_FILE =
|
|
82156
|
-
var LOG_FILE =
|
|
82490
|
+
import { homedir as homedir9 } from "node:os";
|
|
82491
|
+
import { join as join18 } from "node:path";
|
|
82492
|
+
var STATE_DIR = join18(homedir9(), ".cerefox");
|
|
82493
|
+
var PID_FILE = join18(STATE_DIR, "web.pid");
|
|
82494
|
+
var LOG_FILE = join18(STATE_DIR, "web.log");
|
|
82157
82495
|
var daemonPaths = { stateDir: STATE_DIR, pidFile: PID_FILE, logFile: LOG_FILE };
|
|
82158
82496
|
function ensureStateDir() {
|
|
82159
|
-
if (!
|
|
82160
|
-
|
|
82497
|
+
if (!existsSync20(STATE_DIR))
|
|
82498
|
+
mkdirSync6(STATE_DIR, { recursive: true });
|
|
82161
82499
|
}
|
|
82162
82500
|
function readPidFile() {
|
|
82163
|
-
if (!
|
|
82501
|
+
if (!existsSync20(PID_FILE))
|
|
82164
82502
|
return null;
|
|
82165
82503
|
try {
|
|
82166
|
-
const parsed = JSON.parse(
|
|
82504
|
+
const parsed = JSON.parse(readFileSync18(PID_FILE, "utf8"));
|
|
82167
82505
|
if (typeof parsed.pid !== "number")
|
|
82168
82506
|
return null;
|
|
82169
82507
|
return {
|
|
@@ -82474,6 +82812,7 @@ Learn more:
|
|
|
82474
82812
|
registerConfigureAgent(program2);
|
|
82475
82813
|
registerSelfUpdate(program2);
|
|
82476
82814
|
registerMcp(program2);
|
|
82815
|
+
registerEmbedderWarmup(program2);
|
|
82477
82816
|
registerWeb(program2);
|
|
82478
82817
|
registerCompletion(program2);
|
|
82479
82818
|
registerToken(program2);
|
|
@@ -82527,7 +82866,7 @@ Learn more:
|
|
|
82527
82866
|
|
|
82528
82867
|
// src/bin/cerefox.ts
|
|
82529
82868
|
async function bareEntryPoint() {
|
|
82530
|
-
const { existsSync:
|
|
82869
|
+
const { existsSync: existsSync21 } = await import("node:fs");
|
|
82531
82870
|
const { resolveEnvFile: resolveEnvFile2 } = await Promise.resolve().then(() => (init_config(), exports_config));
|
|
82532
82871
|
const { c: c2, println: println2 } = await Promise.resolve().then(() => (init_cli_core(), exports_cli_core));
|
|
82533
82872
|
const { PKG_VERSION: PKG_VERSION2 } = await Promise.resolve().then(() => (init_meta(), exports_meta));
|
|
@@ -82536,7 +82875,7 @@ async function bareEntryPoint() {
|
|
|
82536
82875
|
println2("");
|
|
82537
82876
|
let configExists = false;
|
|
82538
82877
|
try {
|
|
82539
|
-
configExists =
|
|
82878
|
+
configExists = existsSync21(resolveEnvFile2());
|
|
82540
82879
|
} catch {}
|
|
82541
82880
|
if (!configExists) {
|
|
82542
82881
|
println2(c2.yellow("⚠ No config detected."));
|