@cerefox/memory 1.21.0 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cerefox.js +171 -119
- package/dist/frontend/assets/{docx-DeQjAnSd.js → docx-Ch26gbLd.js} +2 -2
- package/dist/frontend/assets/{docx-DeQjAnSd.js.map → docx-Ch26gbLd.js.map} +1 -1
- package/dist/frontend/assets/{index-Dd1nIOAB.js → index-Dhpoy6w3.js} +31 -31
- package/dist/frontend/assets/{index-Dd1nIOAB.js.map → index-Dhpoy6w3.js.map} +1 -1
- package/dist/frontend/assets/{markdown-CsTKTR78.js → markdown-YrYQtnOl.js} +2 -2
- package/dist/frontend/assets/{markdown-CsTKTR78.js.map → markdown-YrYQtnOl.js.map} +1 -1
- package/dist/frontend/assets/{pdf-CkRjSAWX.js → pdf-Bpjaodjd.js} +2 -2
- package/dist/frontend/assets/{pdf-CkRjSAWX.js.map → pdf-Bpjaodjd.js.map} +1 -1
- package/dist/frontend/index.html +1 -1
- package/dist/server-assets/_shared/ef-meta/index.ts +3 -3
- package/dist/server-assets/_shared/mcp-tools/_utils.ts +1 -0
- package/dist/server-assets/_shared/mcp-tools/audit-ops.ts +23 -2
- package/docs/guides/configuration.md +5 -2
- package/docs/guides/connect-agents.md +4 -0
- package/docs/guides/securing-local-access.md +17 -0
- package/docs/guides/setup-lan.md +160 -9
- package/docs/guides/staging-env.md +12 -2
- package/package.json +1 -1
package/dist/bin/cerefox.js
CHANGED
|
@@ -5318,7 +5318,7 @@ var init_cli_core = __esm(() => {
|
|
|
5318
5318
|
});
|
|
5319
5319
|
|
|
5320
5320
|
// src/meta.ts
|
|
5321
|
-
var PKG_VERSION = "1.
|
|
5321
|
+
var PKG_VERSION = "1.22.0";
|
|
5322
5322
|
var init_meta = () => {};
|
|
5323
5323
|
|
|
5324
5324
|
// ../../_shared/config/paths.ts
|
|
@@ -5405,7 +5405,7 @@ function loadEnv(opts = {}) {
|
|
|
5405
5405
|
for (const [k, v] of Object.entries(parseDotenv(content))) {
|
|
5406
5406
|
if (k === "CEREFOX_CONFIG_DIR")
|
|
5407
5407
|
continue;
|
|
5408
|
-
if (env2[k] === undefined || configDirNamed) {
|
|
5408
|
+
if (env2[k] === undefined || configDirNamed || k === "CEREFOX_PROG_NAME") {
|
|
5409
5409
|
env2[k] = v;
|
|
5410
5410
|
count++;
|
|
5411
5411
|
}
|
|
@@ -23699,17 +23699,28 @@ var init_db_client = __esm(() => {
|
|
|
23699
23699
|
});
|
|
23700
23700
|
});
|
|
23701
23701
|
|
|
23702
|
+
// src/cli/util/prog-name.ts
|
|
23703
|
+
function progName() {
|
|
23704
|
+
const name = (process.env.CEREFOX_PROG_NAME ?? "").trim();
|
|
23705
|
+
if (name)
|
|
23706
|
+
return name;
|
|
23707
|
+
const dir = (process.env.CEREFOX_CONFIG_DIR ?? "").trim();
|
|
23708
|
+
if (!dir)
|
|
23709
|
+
return "cerefox";
|
|
23710
|
+
return /^[A-Za-z0-9_\/.~+,:@%=-]+$/.test(dir) ? `CEREFOX_CONFIG_DIR=${dir} cerefox` : `CEREFOX_CONFIG_DIR='${dir.replace(/'/g, `'\\''`)}' cerefox`;
|
|
23711
|
+
}
|
|
23712
|
+
|
|
23702
23713
|
// src/cli/util/client.ts
|
|
23703
23714
|
function getClient() {
|
|
23704
23715
|
const settings = loadSettings();
|
|
23705
23716
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
23706
|
-
throw systemError("CEREFOX_SUPABASE_URL and CEREFOX_SUPABASE_KEY must be set in your .env file.",
|
|
23717
|
+
throw systemError("CEREFOX_SUPABASE_URL and CEREFOX_SUPABASE_KEY must be set in your .env file.", `Run \`${progName()} init\` to create a config, or see docs/guides/setup-supabase.md.`);
|
|
23707
23718
|
}
|
|
23708
23719
|
try {
|
|
23709
23720
|
return createClient2(settings);
|
|
23710
23721
|
} catch (err) {
|
|
23711
23722
|
const msg = err instanceof Error ? err.message : String(err);
|
|
23712
|
-
throw systemError(`Failed to initialize Supabase client: ${msg}`,
|
|
23723
|
+
throw systemError(`Failed to initialize Supabase client: ${msg}`, `Run \`${progName()} doctor\` to verify your credentials.`);
|
|
23713
23724
|
}
|
|
23714
23725
|
}
|
|
23715
23726
|
var init_client = __esm(() => {
|
|
@@ -23727,8 +23738,20 @@ function auditDocLabel(docTitle, documentId, operation) {
|
|
|
23727
23738
|
return docTitle;
|
|
23728
23739
|
if (documentId)
|
|
23729
23740
|
return documentId.slice(0, 8) + "…";
|
|
23741
|
+
if (operation === "config-change")
|
|
23742
|
+
return "(setting)";
|
|
23743
|
+
if (operation?.startsWith("project-"))
|
|
23744
|
+
return "(project)";
|
|
23730
23745
|
return isStoreLevelAuditOp(operation) ? "(store)" : "(deleted)";
|
|
23731
23746
|
}
|
|
23747
|
+
function storeChangeSummary(operation, description) {
|
|
23748
|
+
if (!isStoreLevelAuditOp(operation))
|
|
23749
|
+
return null;
|
|
23750
|
+
const d = (description ?? "").trim();
|
|
23751
|
+
if (!d)
|
|
23752
|
+
return null;
|
|
23753
|
+
return operation === "config-change" ? d.replace(/^config:\s*/, "") : d;
|
|
23754
|
+
}
|
|
23732
23755
|
function metadataChangeSummary(before, after) {
|
|
23733
23756
|
if (before == null && after == null)
|
|
23734
23757
|
return null;
|
|
@@ -26658,6 +26681,7 @@ function apiAuth(keys = () => process.env.CEREFOX_API_KEY ?? "") {
|
|
|
26658
26681
|
if (!guard.allow)
|
|
26659
26682
|
return c.json({ detail: guard.message }, 403);
|
|
26660
26683
|
}
|
|
26684
|
+
c.set("cerefoxAuthReason", decision.reason);
|
|
26661
26685
|
return next();
|
|
26662
26686
|
}
|
|
26663
26687
|
return c.json({ detail: decision.message }, 401, {
|
|
@@ -26768,7 +26792,7 @@ async function isResponding(host, port, timeoutMs = 1500) {
|
|
|
26768
26792
|
}
|
|
26769
26793
|
function assertUnix() {
|
|
26770
26794
|
if (process.platform === "win32") {
|
|
26771
|
-
throw new Error(
|
|
26795
|
+
throw new Error(`Daemon mode (\`${progName()} web start/stop/status\`) is not supported on Windows yet. ` + `Run \`${progName()} web\` in the foreground, or set up a Windows service manually.`);
|
|
26772
26796
|
}
|
|
26773
26797
|
}
|
|
26774
26798
|
async function startDaemon(opts) {
|
|
@@ -26834,7 +26858,8 @@ async function stopDaemon() {
|
|
|
26834
26858
|
}
|
|
26835
26859
|
function restartCommand(host, port) {
|
|
26836
26860
|
const flags = `${host === "127.0.0.1" ? "" : ` --host ${host}`}${port === 8000 ? "" : ` --port ${port}`}`;
|
|
26837
|
-
|
|
26861
|
+
const p = progName();
|
|
26862
|
+
return `${p} web stop && ${p} web start${flags}`;
|
|
26838
26863
|
}
|
|
26839
26864
|
async function statusDaemon() {
|
|
26840
26865
|
const info = readPidFile();
|
|
@@ -26918,7 +26943,7 @@ function startPeriodicRefresh() {
|
|
|
26918
26943
|
if (updateCheckDisabled())
|
|
26919
26944
|
return;
|
|
26920
26945
|
refreshLatest();
|
|
26921
|
-
const timer = setInterval(() => void refreshLatest(),
|
|
26946
|
+
const timer = setInterval(() => void refreshLatest(), REFRESH_TICK_MS);
|
|
26922
26947
|
timer.unref?.();
|
|
26923
26948
|
}
|
|
26924
26949
|
function newerRelease(latest, installed = PKG_VERSION) {
|
|
@@ -26946,19 +26971,21 @@ function takeCliNotice(opts = {}) {
|
|
|
26946
26971
|
writeCache({ ...cached, notifiedAt: now.toISOString() }, path);
|
|
26947
26972
|
return `Cerefox ${newer} is available (you have ${opts.installed ?? PKG_VERSION}). Run \`${upgradeCommand()}\`.`;
|
|
26948
26973
|
}
|
|
26949
|
-
var LATEST_URL = "https://registry.npmjs.org/@cerefox%2Fmemory/latest", DAY_MS, CACHE_TTL_MS, NOTIFY_INTERVAL_MS, releaseNotesUrl = (version) => `https://github.com/fstamatelopoulos/cerefox/releases/tag/v${version}`;
|
|
26974
|
+
var LATEST_URL = "https://registry.npmjs.org/@cerefox%2Fmemory/latest", DAY_MS, HOUR_MS, CACHE_TTL_MS, REFRESH_TICK_MS, NOTIFY_INTERVAL_MS, releaseNotesUrl = (version) => `https://github.com/fstamatelopoulos/cerefox/releases/tag/v${version}`;
|
|
26950
26975
|
var init_update_check = __esm(() => {
|
|
26951
26976
|
init_compatibility();
|
|
26952
26977
|
init_meta();
|
|
26953
26978
|
init_auth();
|
|
26954
26979
|
init_daemon();
|
|
26955
26980
|
DAY_MS = 24 * 60 * 60 * 1000;
|
|
26956
|
-
|
|
26981
|
+
HOUR_MS = 60 * 60 * 1000;
|
|
26982
|
+
CACHE_TTL_MS = HOUR_MS;
|
|
26983
|
+
REFRESH_TICK_MS = 15 * 60 * 1000;
|
|
26957
26984
|
NOTIFY_INTERVAL_MS = DAY_MS;
|
|
26958
26985
|
});
|
|
26959
26986
|
|
|
26960
26987
|
// ../../_shared/ef-meta/index.ts
|
|
26961
|
-
var EF_VERSION = "1.
|
|
26988
|
+
var EF_VERSION = "1.22.0", CEREFOX_VERSION = "1.22.0", EF_LAST_CHANGED = "1.22.0";
|
|
26962
26989
|
var init_ef_meta = () => {};
|
|
26963
26990
|
|
|
26964
26991
|
// ../../_shared/embeddings/onnx-embedder.ts
|
|
@@ -63952,7 +63979,7 @@ async function warnIfSchemaVersionMismatch(supabase) {
|
|
|
63952
63979
|
if (!bundled)
|
|
63953
63980
|
return;
|
|
63954
63981
|
if (compareSemver(deployed, bundled) < 0) {
|
|
63955
|
-
process.stderr.write(`[cerefox-mcp] ⚠ schema version mismatch: this client bundles v${bundled} but the deployed schema is v${deployed}. Run
|
|
63982
|
+
process.stderr.write(`[cerefox-mcp] ⚠ schema version mismatch: this client bundles v${bundled} but the deployed schema is v${deployed}. Run \`${progName()} server deploy\` to update it. Tools may behave unexpectedly until then.
|
|
63956
63983
|
`);
|
|
63957
63984
|
}
|
|
63958
63985
|
} catch {}
|
|
@@ -66357,7 +66384,7 @@ end
|
|
|
66357
66384
|
complete -c ${prog} -f -a '(__${fn}_complete)'
|
|
66358
66385
|
`;
|
|
66359
66386
|
}
|
|
66360
|
-
function
|
|
66387
|
+
function progName2() {
|
|
66361
66388
|
return buildProgram().name();
|
|
66362
66389
|
}
|
|
66363
66390
|
function fnId(prog) {
|
|
@@ -66365,7 +66392,7 @@ function fnId(prog) {
|
|
|
66365
66392
|
}
|
|
66366
66393
|
function scriptFor(shell) {
|
|
66367
66394
|
const nodes = collectNodes();
|
|
66368
|
-
const prog =
|
|
66395
|
+
const prog = progName2();
|
|
66369
66396
|
const fn = fnId(prog);
|
|
66370
66397
|
switch (shell) {
|
|
66371
66398
|
case "bash":
|
|
@@ -66397,7 +66424,7 @@ async function installMode(options) {
|
|
|
66397
66424
|
throw userError(`Unsupported --shell "${shell}". Use bash, zsh, or fish.`);
|
|
66398
66425
|
}
|
|
66399
66426
|
const home = homedir3();
|
|
66400
|
-
const prog =
|
|
66427
|
+
const prog = progName2();
|
|
66401
66428
|
const rcBegin = rcBeginFor(prog);
|
|
66402
66429
|
const rcEnd = rcEndFor(prog);
|
|
66403
66430
|
const scriptPath = join3(home, `.${prog}-completion.${shell}`);
|
|
@@ -66445,7 +66472,7 @@ async function action2(target, options) {
|
|
|
66445
66472
|
println(scriptFor(target));
|
|
66446
66473
|
if (process.stdout.isTTY) {
|
|
66447
66474
|
eprintln(c.dim(`
|
|
66448
|
-
# Tip:
|
|
66475
|
+
# Tip: \`${progName()} completion install\` writes this + wires your shell rc automatically.`));
|
|
66449
66476
|
}
|
|
66450
66477
|
}
|
|
66451
66478
|
function registerCompletion(program) {
|
|
@@ -66655,7 +66682,7 @@ function action4(options) {
|
|
|
66655
66682
|
});
|
|
66656
66683
|
return;
|
|
66657
66684
|
}
|
|
66658
|
-
println(c.bold(
|
|
66685
|
+
println(c.bold(`Runtime config keys (stored in cerefox_config; read with \`${progName()} config get <key>\`):`));
|
|
66659
66686
|
let group = null;
|
|
66660
66687
|
for (const spec of CONFIG_CATALOG) {
|
|
66661
66688
|
if (spec.group !== group) {
|
|
@@ -68052,7 +68079,7 @@ function delegatedWrite(writer, opts) {
|
|
|
68052
68079
|
if (result.error) {
|
|
68053
68080
|
const err = result.error;
|
|
68054
68081
|
if (err.code === "ENOENT") {
|
|
68055
|
-
throw new Error(`${writer.label}: \`${cmd}\` not found on PATH. ` + `Install ${writer.label} (https://docs.claude.com/en/docs/claude-code) ` + `and re-run
|
|
68082
|
+
throw new Error(`${writer.label}: \`${cmd}\` not found on PATH. ` + `Install ${writer.label} (https://docs.claude.com/en/docs/claude-code) ` + `and re-run \`${progName()} configure-agent --tool ${writer.id}\`.`);
|
|
68056
68083
|
}
|
|
68057
68084
|
throw new Error(`${writer.label}: failed to spawn \`${cmd}\`: ${err.message}`);
|
|
68058
68085
|
}
|
|
@@ -68169,18 +68196,18 @@ async function action7(documentId, options) {
|
|
|
68169
68196
|
} catch (e) {
|
|
68170
68197
|
const message = e instanceof Error ? e.message : String(e);
|
|
68171
68198
|
if (isMissingFunctionError(message, "cerefox_delete_document")) {
|
|
68172
|
-
throw systemError(options.reason ? `This server is behind: \`--reason\` needs schema 0.12.0 or newer. ` + `Run
|
|
68199
|
+
throw systemError(options.reason ? `This server is behind: \`--reason\` needs schema 0.12.0 or newer. ` + `Run \`${progName()} server deploy\` and retry, or retry without --reason.` : `The delete did not run: the server has no matching cerefox_delete_document ` + `(mid-deploy window, or an old schema). Run \`${progName()} server deploy\` and retry.`);
|
|
68173
68200
|
}
|
|
68174
68201
|
throw e;
|
|
68175
68202
|
}
|
|
68176
68203
|
if (result === null) {
|
|
68177
68204
|
const { data: check, error: checkError } = await client.raw.from("cerefox_documents").select("deleted_at").eq("id", documentId).maybeSingle();
|
|
68178
68205
|
if (checkError) {
|
|
68179
|
-
warn(`Delete submitted, but the follow-up verification read failed (${checkError.message}). ` + `Confirm with:
|
|
68206
|
+
warn(`Delete submitted, but the follow-up verification read failed (${checkError.message}). ` + `Confirm with: ${progName()} document get ${documentId}`);
|
|
68180
68207
|
return;
|
|
68181
68208
|
}
|
|
68182
68209
|
if (!check?.deleted_at) {
|
|
68183
|
-
throw systemError(`The delete did not take effect — the server has no matching ` + `cerefox_delete_document (mid-deploy window, or an old schema). ` + `Run
|
|
68210
|
+
throw systemError(`The delete did not take effect — the server has no matching ` + `cerefox_delete_document (mid-deploy window, or an old schema). ` + `Run \`${progName()} server deploy\` and retry.`);
|
|
68184
68211
|
}
|
|
68185
68212
|
}
|
|
68186
68213
|
if (result?.already_deleted) {
|
|
@@ -68203,7 +68230,7 @@ function registerDeleteDoc(program) {
|
|
|
68203
68230
|
init_cli_core();
|
|
68204
68231
|
init__utils();
|
|
68205
68232
|
init_client();
|
|
68206
|
-
var
|
|
68233
|
+
var serverBehind = () => "The sweep did not run: this server has no cerefox_find_dead_links (needs schema 0.12.2). " + `Run \`${progName()} server deploy\`, then retry.`;
|
|
68207
68234
|
async function action8(options) {
|
|
68208
68235
|
const client = getClient();
|
|
68209
68236
|
let rows;
|
|
@@ -68212,12 +68239,12 @@ async function action8(options) {
|
|
|
68212
68239
|
} catch (e) {
|
|
68213
68240
|
const message = e instanceof Error ? e.message : String(e);
|
|
68214
68241
|
if (isMissingFunctionError(message, "cerefox_find_dead_links")) {
|
|
68215
|
-
throw systemError(
|
|
68242
|
+
throw systemError(serverBehind());
|
|
68216
68243
|
}
|
|
68217
68244
|
throw e;
|
|
68218
68245
|
}
|
|
68219
68246
|
if (rows === null)
|
|
68220
|
-
throw systemError(
|
|
68247
|
+
throw systemError(serverBehind());
|
|
68221
68248
|
if (options.json) {
|
|
68222
68249
|
printJson(rows);
|
|
68223
68250
|
return;
|
|
@@ -68574,7 +68601,8 @@ async function action10(options) {
|
|
|
68574
68601
|
${c.red("✗")} ${ch.label}`);
|
|
68575
68602
|
eprintln(c.dim(` → ${ch.remediation}`));
|
|
68576
68603
|
}
|
|
68577
|
-
eprintln(
|
|
68604
|
+
eprintln(`
|
|
68605
|
+
Fix the above and re-run \`${progName()} server deploy\` (it's idempotent).`);
|
|
68578
68606
|
process.exit(1);
|
|
68579
68607
|
}
|
|
68580
68608
|
println(c.green(`
|
|
@@ -68724,9 +68752,9 @@ ${r.stderr ?? ""}`);
|
|
|
68724
68752
|
eprintln(c.dim(" published yet, and bundling fails."));
|
|
68725
68753
|
eprintln(c.dim(" Your deployed functions were NOT changed — the previous version is"));
|
|
68726
68754
|
eprintln(c.dim(" still serving, so nothing is down."));
|
|
68727
|
-
eprintln(c.cyan(
|
|
68755
|
+
eprintln(c.cyan(` → Wait a few minutes, then re-run: ${progName()} server deploy --functions-only`));
|
|
68728
68756
|
} else {
|
|
68729
|
-
eprintln(c.dim(
|
|
68757
|
+
eprintln(c.dim(` Re-run \`${progName()} server deploy --functions-only\` after fixing the cause.`));
|
|
68730
68758
|
}
|
|
68731
68759
|
process.exit(1);
|
|
68732
68760
|
}
|
|
@@ -68745,15 +68773,16 @@ ${r.stderr ?? ""}`);
|
|
|
68745
68773
|
println(c.cyan(`
|
|
68746
68774
|
ℹ The primitive Edge Functions now require the Cerefox access token.
|
|
68747
68775
|
` + ` If CEREFOX_ACCESS_TOKENS is unset they reject ALL callers (fail closed) —
|
|
68748
|
-
` +
|
|
68776
|
+
` + ` GPT Actions, remote HTTP, and \`${progName()} doctor\`. Generate it now:
|
|
68777
|
+
` + ` ${progName()} token generate
|
|
68749
68778
|
` + ` (or manually: supabase secrets set CEREFOX_ACCESS_TOKENS=<token> --project-ref ${ref})
|
|
68750
68779
|
` + " Migration + client cutover: docs/specs/ef-auth-migration-design.md §6."));
|
|
68751
68780
|
}
|
|
68752
68781
|
}
|
|
68753
68782
|
println(c.green(`
|
|
68754
68783
|
✓ Server deploy complete.`));
|
|
68755
|
-
println(c.dim(
|
|
68756
|
-
println(c.dim(
|
|
68784
|
+
println(c.dim(`Verify with: ${progName()} doctor`));
|
|
68785
|
+
println(c.dim(`Refresh the bundled guides: ${progName()} guides ingest`));
|
|
68757
68786
|
}
|
|
68758
68787
|
function efDeployArgs(ef, workdir, projectRef) {
|
|
68759
68788
|
const args = ["--yes", "supabase", "functions", "deploy", ef, "--use-api", "--workdir", workdir];
|
|
@@ -68804,7 +68833,7 @@ async function action11(documentId, options) {
|
|
|
68804
68833
|
if (!doc)
|
|
68805
68834
|
throw notFound(`Document ${documentId} not found.`);
|
|
68806
68835
|
if (doc.deleted_at) {
|
|
68807
|
-
throw userError(`Document ${documentId} is soft-deleted — restore it first (
|
|
68836
|
+
throw userError(`Document ${documentId} is soft-deleted — restore it first (${progName()} document restore).`);
|
|
68808
68837
|
}
|
|
68809
68838
|
const metaTouched = sets.length > 0 || unsets.length > 0;
|
|
68810
68839
|
const newTitle = hasTitle ? options.title.trim() : doc.title;
|
|
@@ -68831,7 +68860,7 @@ async function action11(documentId, options) {
|
|
|
68831
68860
|
});
|
|
68832
68861
|
if (metaErr) {
|
|
68833
68862
|
if (metaErr.message?.includes("CEREFOX_BAD_METADATA")) {
|
|
68834
|
-
throw userError(`Document ${documentId} has non-object metadata; a patch cannot repair it. ` + `Repair it first with:
|
|
68863
|
+
throw userError(`Document ${documentId} has non-object metadata; a patch cannot repair it. ` + `Repair it first with: ${progName()} document set-metadata ${documentId} --replace --json '<the intended object>'`);
|
|
68835
68864
|
}
|
|
68836
68865
|
throw systemError(`Metadata update failed: ${metaErr.message}`);
|
|
68837
68866
|
}
|
|
@@ -68850,7 +68879,7 @@ async function action11(documentId, options) {
|
|
|
68850
68879
|
}
|
|
68851
68880
|
println(c.green(`✓ Edited "${newTitle}" (id: ${documentId}).`));
|
|
68852
68881
|
if (titleChanged) {
|
|
68853
|
-
println(c.dim(
|
|
68882
|
+
println(c.dim(` Title changed: FTS refreshed; semantic embeddings update on next \`${progName()} server reindex\`.`));
|
|
68854
68883
|
}
|
|
68855
68884
|
}
|
|
68856
68885
|
function collect(value, prev) {
|
|
@@ -68891,21 +68920,21 @@ async function action12(documentId, options) {
|
|
|
68891
68920
|
} catch (e) {
|
|
68892
68921
|
const message = e instanceof Error ? e.message : String(e);
|
|
68893
68922
|
if (isMissingFunctionError(message, "cerefox_restore_document")) {
|
|
68894
|
-
throw systemError(options.reason ? `This server is behind: \`--reason\` needs schema 0.12.0 or newer. ` + `Run
|
|
68923
|
+
throw systemError(options.reason ? `This server is behind: \`--reason\` needs schema 0.12.0 or newer. ` + `Run \`${progName()} server deploy\` and retry, or retry without --reason.` : `The restore did not run: the server has no matching cerefox_restore_document ` + `(mid-deploy window, or an old schema). Run \`${progName()} server deploy\` and retry.`);
|
|
68895
68924
|
}
|
|
68896
68925
|
throw e;
|
|
68897
68926
|
}
|
|
68898
68927
|
if (result === null) {
|
|
68899
68928
|
const { data: check, error: checkError } = await client.raw.from("cerefox_documents").select("deleted_at").eq("id", documentId).maybeSingle();
|
|
68900
68929
|
if (checkError) {
|
|
68901
|
-
warn(`Restore submitted, but the follow-up verification read failed (${checkError.message}). ` + `Confirm with:
|
|
68930
|
+
warn(`Restore submitted, but the follow-up verification read failed (${checkError.message}). ` + `Confirm with: ${progName()} document get ${documentId}`);
|
|
68902
68931
|
return;
|
|
68903
68932
|
}
|
|
68904
68933
|
if (!check) {
|
|
68905
68934
|
throw systemError(`Document ${documentId} no longer exists — it may have been purged concurrently. Nothing was restored.`);
|
|
68906
68935
|
}
|
|
68907
68936
|
if (check.deleted_at) {
|
|
68908
|
-
throw systemError(`The restore did not take effect — the server has no matching ` + `cerefox_restore_document (mid-deploy window, or an old schema). ` + `Run
|
|
68937
|
+
throw systemError(`The restore did not take effect — the server has no matching ` + `cerefox_restore_document (mid-deploy window, or an old schema). ` + `Run \`${progName()} server deploy\` and retry.`);
|
|
68909
68938
|
}
|
|
68910
68939
|
}
|
|
68911
68940
|
if (result && result.restored === false) {
|
|
@@ -68986,15 +69015,15 @@ async function action13(documentId, options) {
|
|
|
68986
69015
|
if (/not found/i.test(msg))
|
|
68987
69016
|
throw notFound(`Document ${documentId} not found (or is deleted).`);
|
|
68988
69017
|
if (msg.includes("CEREFOX_METADATA_CONFLICT")) {
|
|
68989
|
-
throw userError(`The metadata of ${documentId} changed since you read it. Re-read it ` + `(
|
|
69018
|
+
throw userError(`The metadata of ${documentId} changed since you read it. Re-read it ` + `(${progName()} document get ${documentId} --outline), reapply your change, and retry ` + `with the new --expected-metadata-revision.`);
|
|
68990
69019
|
}
|
|
68991
69020
|
if (msg.includes("CEREFOX_METADATA_TOKEN_REQUIRED")) {
|
|
68992
|
-
throw userError(`--replace discards every key you do not list, so it needs --expected-metadata-revision ` + `(from
|
|
69021
|
+
throw userError(`--replace discards every key you do not list, so it needs --expected-metadata-revision ` + `(from ${progName()} document get ${documentId} --outline) or --last-write-wins.`);
|
|
68993
69022
|
}
|
|
68994
69023
|
throw systemError(`Could not set metadata: ${msg}`);
|
|
68995
69024
|
}
|
|
68996
69025
|
if (!rows || rows.length === 0) {
|
|
68997
|
-
throw systemError("cerefox_set_document_metadata returned no data.",
|
|
69026
|
+
throw systemError("cerefox_set_document_metadata returned no data.", `Verify the RPC is deployed: \`${progName()} server deploy\`.`);
|
|
68998
69027
|
}
|
|
68999
69028
|
const row = rows[0];
|
|
69000
69029
|
if (options.jsonOut) {
|
|
@@ -69067,7 +69096,7 @@ function openInBrowser(path) {
|
|
|
69067
69096
|
function resolveDoc(topic) {
|
|
69068
69097
|
const doc = readBundledDoc(topic);
|
|
69069
69098
|
if (!doc) {
|
|
69070
|
-
throw notFound(`No bundled guide named "${topic}".`,
|
|
69099
|
+
throw notFound(`No bundled guide named "${topic}".`, `Run \`${progName()} guides list\` to see available topics.`);
|
|
69071
69100
|
}
|
|
69072
69101
|
return doc;
|
|
69073
69102
|
}
|
|
@@ -69081,7 +69110,7 @@ function listAction() {
|
|
|
69081
69110
|
println("");
|
|
69082
69111
|
printTable(docs.map((d) => ({ topic: d.topic, size_kb: Math.round(d.size / 1024) + " KB" })));
|
|
69083
69112
|
println("");
|
|
69084
|
-
println(c.dim(
|
|
69113
|
+
println(c.dim(`Open with \`${progName()} guides open <topic>\` (browser) or \`${progName()} guides show <topic>\` (stdout).`));
|
|
69085
69114
|
}
|
|
69086
69115
|
function openAction(topic) {
|
|
69087
69116
|
const doc = resolveDoc(topic);
|
|
@@ -69204,8 +69233,8 @@ async function setArchived(versionId, archived, options) {
|
|
|
69204
69233
|
println(c.green(`✓ Version ${data.version_number} (${versionId}) ${op}d.`));
|
|
69205
69234
|
}
|
|
69206
69235
|
function registerVersionArchive(parent) {
|
|
69207
|
-
parent.command("archive").description("Archive a document version (protect it from version cleanup).").argument("<version-id>",
|
|
69208
|
-
parent.command("unarchive").description("Unarchive a document version (allow version cleanup again).").argument("<version-id>",
|
|
69236
|
+
parent.command("archive").description("Archive a document version (protect it from version cleanup).").argument("<version-id>", `UUID of the version (from \`${progName()} document version list\`).`).option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action((versionId, options) => setArchived(versionId, true, options));
|
|
69237
|
+
parent.command("unarchive").description("Unarchive a document version (allow version cleanup again).").argument("<version-id>", `UUID of the version (from \`${progName()} document version list\`).`).option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action((versionId, options) => setArchived(versionId, false, options));
|
|
69209
69238
|
}
|
|
69210
69239
|
|
|
69211
69240
|
// ../../node_modules/.bun/ora@9.4.1/node_modules/ora/index.js
|
|
@@ -72687,7 +72716,7 @@ function checkConfig() {
|
|
|
72687
72716
|
name: "config",
|
|
72688
72717
|
status: "error",
|
|
72689
72718
|
detail: `Could not resolve config dir: ${err instanceof Error ? err.message : String(err)}`,
|
|
72690
|
-
hint:
|
|
72719
|
+
hint: `Run \`${progName()} init\` to bootstrap.`
|
|
72691
72720
|
};
|
|
72692
72721
|
}
|
|
72693
72722
|
if (!existsSync12(envPath)) {
|
|
@@ -72703,7 +72732,7 @@ function checkConfig() {
|
|
|
72703
72732
|
name: "config",
|
|
72704
72733
|
status: "error",
|
|
72705
72734
|
detail: `No config file at ${envPath}`,
|
|
72706
|
-
hint:
|
|
72735
|
+
hint: `Run \`${progName()} init\` to create one.`
|
|
72707
72736
|
};
|
|
72708
72737
|
}
|
|
72709
72738
|
let modeDetail = "";
|
|
@@ -72781,7 +72810,7 @@ async function checkRetiredEnvVars() {
|
|
|
72781
72810
|
hint: "Safe to delete those lines; nothing reads them."
|
|
72782
72811
|
};
|
|
72783
72812
|
}
|
|
72784
|
-
const moves = pending.map((v) =>
|
|
72813
|
+
const moves = pending.map((v) => `${progName()} config set ${v.configKey} ${(process.env[v.name] ?? "").trim()}`).join(`
|
|
72785
72814
|
`);
|
|
72786
72815
|
const prunedWasDisabled = pending.some((v) => v.configKey.startsWith("version_"));
|
|
72787
72816
|
return {
|
|
@@ -72795,6 +72824,17 @@ async function checkRetiredEnvVars() {
|
|
|
72795
72824
|
Then delete those lines from your .env — nothing reads them.`
|
|
72796
72825
|
};
|
|
72797
72826
|
}
|
|
72827
|
+
function dataApiHint(status, body, key) {
|
|
72828
|
+
if (status !== 401)
|
|
72829
|
+
return "Verify CEREFOX_SUPABASE_URL.";
|
|
72830
|
+
if (key.trim().startsWith("cfx_lak_")) {
|
|
72831
|
+
if (/PGRST30\d|JWT/.test(body)) {
|
|
72832
|
+
return "This Cerefox Local container is older than 1.22.0 and cannot accept an API key here. " + "Upgrade the container image to 1.22.0 or later.";
|
|
72833
|
+
}
|
|
72834
|
+
return "The server does not accept this API key. Check CEREFOX_SUPABASE_KEY against the server's key.";
|
|
72835
|
+
}
|
|
72836
|
+
return "Verify CEREFOX_SUPABASE_KEY (use the service-role / sb_secret key).";
|
|
72837
|
+
}
|
|
72798
72838
|
async function checkSupabase() {
|
|
72799
72839
|
let settings;
|
|
72800
72840
|
try {
|
|
@@ -72804,7 +72844,7 @@ async function checkSupabase() {
|
|
|
72804
72844
|
name: "supabase",
|
|
72805
72845
|
status: "error",
|
|
72806
72846
|
detail: `Could not load settings: ${err instanceof Error ? err.message : String(err)}`,
|
|
72807
|
-
hint:
|
|
72847
|
+
hint: `Run \`${progName()} init\`.`
|
|
72808
72848
|
};
|
|
72809
72849
|
}
|
|
72810
72850
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
@@ -72812,7 +72852,7 @@ async function checkSupabase() {
|
|
|
72812
72852
|
name: "supabase",
|
|
72813
72853
|
status: "error",
|
|
72814
72854
|
detail: "CEREFOX_SUPABASE_URL or CEREFOX_SUPABASE_KEY is not set.",
|
|
72815
|
-
hint:
|
|
72855
|
+
hint: `Run \`${progName()} init\` to bootstrap.`
|
|
72816
72856
|
};
|
|
72817
72857
|
}
|
|
72818
72858
|
try {
|
|
@@ -72824,11 +72864,12 @@ async function checkSupabase() {
|
|
|
72824
72864
|
}
|
|
72825
72865
|
});
|
|
72826
72866
|
if (!resp.ok) {
|
|
72867
|
+
const body = await resp.text().catch(() => "");
|
|
72827
72868
|
return {
|
|
72828
72869
|
name: "supabase",
|
|
72829
72870
|
status: "error",
|
|
72830
72871
|
detail: `Data API returned ${resp.status} ${resp.statusText}`,
|
|
72831
|
-
hint: resp.status
|
|
72872
|
+
hint: dataApiHint(resp.status, body, settings.supabaseKey)
|
|
72832
72873
|
};
|
|
72833
72874
|
}
|
|
72834
72875
|
return {
|
|
@@ -72860,7 +72901,7 @@ async function checkOpenAI() {
|
|
|
72860
72901
|
name: "openai",
|
|
72861
72902
|
status: "warn",
|
|
72862
72903
|
detail: "No OPENAI_API_KEY / CEREFOX_OPENAI_API_KEY set.",
|
|
72863
|
-
hint:
|
|
72904
|
+
hint: `Required for \`${progName()} search\` (semantic mode) and ingest. Set in your .env.`
|
|
72864
72905
|
};
|
|
72865
72906
|
}
|
|
72866
72907
|
try {
|
|
@@ -72991,7 +73032,7 @@ async function checkReviewWorkflow() {
|
|
|
72991
73032
|
name,
|
|
72992
73033
|
status: "warn",
|
|
72993
73034
|
detail: "review_workflow_enabled is not set — treated as OFF until the schema is updated",
|
|
72994
|
-
hint:
|
|
73035
|
+
hint: `Run \`${progName()} server deploy --schema-only\` (v1.13.0+) to seed it.`
|
|
72995
73036
|
};
|
|
72996
73037
|
}
|
|
72997
73038
|
const on = raw.trim().toLowerCase() === "true";
|
|
@@ -72999,7 +73040,7 @@ async function checkReviewWorkflow() {
|
|
|
72999
73040
|
name,
|
|
73000
73041
|
status: "ok",
|
|
73001
73042
|
detail: on ? "ON — agent writes land pending_review; review_status is shown everywhere" : "OFF — review_status is hidden everywhere (still recorded from author_type)",
|
|
73002
|
-
hint: on ? undefined :
|
|
73043
|
+
hint: on ? undefined : `Turn it on with \`${progName()} config set review_workflow_enabled true\`.`
|
|
73003
73044
|
};
|
|
73004
73045
|
}
|
|
73005
73046
|
async function checkTrashAutoPurge() {
|
|
@@ -73038,7 +73079,7 @@ async function checkTrashAutoPurge() {
|
|
|
73038
73079
|
name,
|
|
73039
73080
|
status: "ok",
|
|
73040
73081
|
detail: "off — the trash is only emptied by hand",
|
|
73041
|
-
hint:
|
|
73082
|
+
hint: `Opt in with \`${progName()} config set trash_auto_purge_enabled true\` (period: trash_retention_days).`
|
|
73042
73083
|
};
|
|
73043
73084
|
}
|
|
73044
73085
|
return {
|
|
@@ -73073,7 +73114,7 @@ async function checkEmbedderMismatch() {
|
|
|
73073
73114
|
name: EMBEDDER_CHECK_NAME,
|
|
73074
73115
|
status: "warn",
|
|
73075
73116
|
detail: `configured "${active}", but the model is not downloaded yet; the first search or write will fetch it (~130 MB).`,
|
|
73076
|
-
hint:
|
|
73117
|
+
hint: `Fetch it now with \`${progName()} embedder-warmup\`${progName() === "cerefox" ? " (Cerefox Local: `cerefox-local embedder-warmup`)" : ""}; it resumes if the connection drops.`
|
|
73077
73118
|
};
|
|
73078
73119
|
}
|
|
73079
73120
|
}
|
|
@@ -73087,7 +73128,7 @@ async function checkEmbedderMismatch() {
|
|
|
73087
73128
|
name: EMBEDDER_CHECK_NAME,
|
|
73088
73129
|
status: "warn",
|
|
73089
73130
|
detail: `configured "${active}" but existing chunks were embedded with ${stale.map((r) => `"${r}"`).join(", ")} — semantic search across them is broken.`,
|
|
73090
|
-
hint:
|
|
73131
|
+
hint: `Run \`${progName()} server reindex\` to re-embed everything with the configured embedder.`
|
|
73091
73132
|
};
|
|
73092
73133
|
} catch (err) {
|
|
73093
73134
|
return {
|
|
@@ -73195,7 +73236,7 @@ async function checkContentFormat() {
|
|
|
73195
73236
|
name: CONTENT_FORMAT_CHECK_NAME,
|
|
73196
73237
|
status: "skipped",
|
|
73197
73238
|
detail: `${legacy} of ${total} document(s) use the legacy reconstruction format (format 1).`,
|
|
73198
|
-
hint:
|
|
73239
|
+
hint: `Harmless — they auto-convert on next edit. To convert them all now: \`${progName()} server migrate-format\` (re-embeds, so try \`--dry-run\` first). To read what chunk formats are: \`${progName()} guides show content-format\`.`
|
|
73199
73240
|
};
|
|
73200
73241
|
}
|
|
73201
73242
|
}
|
|
@@ -73228,7 +73269,7 @@ async function checkMetadataHealth() {
|
|
|
73228
73269
|
name: METADATA_HEALTH_CHECK_NAME,
|
|
73229
73270
|
status: "skipped",
|
|
73230
73271
|
detail: `${probe.rows.length} document(s) hold non-object metadata: ${sample}${probe.rows.length > 3 ? ", …" : ""}.`,
|
|
73231
|
-
hint:
|
|
73272
|
+
hint: `Writes that would merge onto these rows are refused (#212). Repair each with \`${progName()} document set-metadata <id> --replace --json '<the intended object>'\`.`
|
|
73232
73273
|
};
|
|
73233
73274
|
}
|
|
73234
73275
|
function hasCerefoxInJsonFile(path) {
|
|
@@ -73257,7 +73298,7 @@ async function checkWebDaemon() {
|
|
|
73257
73298
|
name: "web server",
|
|
73258
73299
|
status: "skipped",
|
|
73259
73300
|
detail: `no daemon running (stale pidfile for process ${status.info.pid}).`,
|
|
73260
|
-
hint:
|
|
73301
|
+
hint: `Clean it up: ${progName()} web stop`
|
|
73261
73302
|
};
|
|
73262
73303
|
}
|
|
73263
73304
|
if (!status.responding) {
|
|
@@ -73307,7 +73348,7 @@ function checkMcpConfigs() {
|
|
|
73307
73348
|
name: "mcp clients",
|
|
73308
73349
|
status: isLocalBackend() ? "skipped" : "warn",
|
|
73309
73350
|
detail: isLocalBackend() ? "checked from inside the container — host MCP configs are not visible here." : "No MCP client configs reference Cerefox.",
|
|
73310
|
-
hint: isLocalBackend() ? "Configure agents on the host with `cerefox-local configure-agent`." :
|
|
73351
|
+
hint: isLocalBackend() ? "Configure agents on the host with `cerefox-local configure-agent`." : `Run \`${progName()} configure-agent --tool claude-code\` (or \`--tool claude-desktop\`) to wire up a client.`
|
|
73311
73352
|
};
|
|
73312
73353
|
}
|
|
73313
73354
|
return {
|
|
@@ -73405,7 +73446,7 @@ async function checkEdgeFunctionsCompat() {
|
|
|
73405
73446
|
name: "edge functions",
|
|
73406
73447
|
status: "skipped",
|
|
73407
73448
|
detail: "No CEREFOX_ACCESS_TOKEN set; EF version check skipped.",
|
|
73408
|
-
hint:
|
|
73449
|
+
hint: `Run \`${progName()} token generate\` to enable client↔server version checks.`
|
|
73409
73450
|
};
|
|
73410
73451
|
}
|
|
73411
73452
|
let compat;
|
|
@@ -73557,11 +73598,11 @@ async function action17(options) {
|
|
|
73557
73598
|
const needsEf = stale("edge functions");
|
|
73558
73599
|
let remediation = null;
|
|
73559
73600
|
if (needsSchema && needsEf) {
|
|
73560
|
-
remediation =
|
|
73601
|
+
remediation = `This release needs a server update (schema + RPCs + Edge Functions): ${progName()} server deploy`;
|
|
73561
73602
|
} else if (needsSchema) {
|
|
73562
|
-
remediation =
|
|
73603
|
+
remediation = `This release needs a schema + RPC update: ${progName()} server deploy --schema-only`;
|
|
73563
73604
|
} else if (needsEf) {
|
|
73564
|
-
remediation =
|
|
73605
|
+
remediation = `This release needs an Edge Function update: ${progName()} server deploy --functions-only`;
|
|
73565
73606
|
}
|
|
73566
73607
|
if (remediation) {
|
|
73567
73608
|
println(cErr.yellow("→ " + remediation));
|
|
@@ -73649,7 +73690,7 @@ async function action18(options) {
|
|
|
73649
73690
|
doc: auditDocLabel(row.doc_title, row.document_id, row.operation).slice(0, 40),
|
|
73650
73691
|
author: (row.author ?? "") + (row.author_type ? `(${row.author_type})` : ""),
|
|
73651
73692
|
size_delta: row.size_before !== null && row.size_after !== null ? `${row.size_before} → ${row.size_after}` : "",
|
|
73652
|
-
change: (metadataChangeSummary(row.metadata_before, row.metadata_after) ?? "").slice(0, 60)
|
|
73693
|
+
change: (metadataChangeSummary(row.metadata_before, row.metadata_after) ?? storeChangeSummary(row.operation, row.description) ?? "").slice(0, 60)
|
|
73653
73694
|
})));
|
|
73654
73695
|
}
|
|
73655
73696
|
function registerGetAuditLog(program) {
|
|
@@ -74674,7 +74715,7 @@ async function readContent(path, paste) {
|
|
|
74674
74715
|
return { content, titleFromPath: undefined };
|
|
74675
74716
|
}
|
|
74676
74717
|
if (!path) {
|
|
74677
|
-
throw userError("Provide a file path or use --paste.",
|
|
74718
|
+
throw userError("Provide a file path or use --paste.", `Example: ${progName()} document ingest notes.md --title 'My Note'`);
|
|
74678
74719
|
}
|
|
74679
74720
|
let content;
|
|
74680
74721
|
try {
|
|
@@ -74716,7 +74757,7 @@ async function action20(path, options) {
|
|
|
74716
74757
|
}
|
|
74717
74758
|
const settings = loadSettings();
|
|
74718
74759
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
74719
|
-
throw userError(
|
|
74760
|
+
throw userError(`Supabase credentials not configured — run \`${progName()} init\` first.`);
|
|
74720
74761
|
}
|
|
74721
74762
|
if (!settings.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
74722
74763
|
throw userError("OPENAI_API_KEY not set — required for embeddings during ingest.");
|
|
@@ -74828,7 +74869,7 @@ async function runTool(toolName, args) {
|
|
|
74828
74869
|
}
|
|
74829
74870
|
}
|
|
74830
74871
|
function registerDocumentInsert(program) {
|
|
74831
|
-
program.command("insert <document-id>").description("Add text to a document without resending it (purely additive)").requiredOption("-t, --text <text>", "Markdown to insert. Use '-' for stdin or '@path' for a file.").option("-p, --position <position>", "end_of_document | end_of_section | after_heading | before_heading", "end_of_document").option("-a, --anchor-heading <heading>", "Heading line, or a ' > ' path. Required unless end_of_document.").option("--section-part <part>", "own_body | subtree — required when the target section has child sections").requiredOption("-e, --expected-content-hash <hash>",
|
|
74872
|
+
program.command("insert <document-id>").description("Add text to a document without resending it (purely additive)").requiredOption("-t, --text <text>", "Markdown to insert. Use '-' for stdin or '@path' for a file.").option("-p, --position <position>", "end_of_document | end_of_section | after_heading | before_heading", "end_of_document").option("-a, --anchor-heading <heading>", "Heading line, or a ' > ' path. Required unless end_of_document.").option("--section-part <part>", "own_body | subtree — required when the target section has child sections").requiredOption("-e, --expected-content-hash <hash>", `content_hash you are basing this on (${progName()} document get --outline shows it)`).addOption(authorOption("write", { short: false })).addOption(requestorAliasOption()).option("--author-type <type>", "user (default for the CLI) or agent, when scripting on an agent's behalf", "user").action(async (documentId, options) => {
|
|
74832
74873
|
await runTool("cerefox_insert", {
|
|
74833
74874
|
document_id: documentId,
|
|
74834
74875
|
text: resolveText(options.text, "--text"),
|
|
@@ -74909,7 +74950,7 @@ async function action21(dir, options) {
|
|
|
74909
74950
|
const metadata = parseJsonObjectArg(options.metadata, "--metadata");
|
|
74910
74951
|
const settings = loadSettings();
|
|
74911
74952
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
74912
|
-
throw userError(
|
|
74953
|
+
throw userError(`Supabase credentials not configured — run \`${progName()} init\` first.`);
|
|
74913
74954
|
}
|
|
74914
74955
|
if (!settings.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
74915
74956
|
throw userError("OPENAI_API_KEY not set — required for embeddings during ingest.");
|
|
@@ -75039,7 +75080,7 @@ function answersFromEnvFile(path) {
|
|
|
75039
75080
|
const required = ["CEREFOX_SUPABASE_URL", "CEREFOX_SUPABASE_KEY", "OPENAI_API_KEY"];
|
|
75040
75081
|
for (const key of required) {
|
|
75041
75082
|
if (!parsed[key] || parsed[key].trim() === "") {
|
|
75042
|
-
throw userError(`Existing .env at ${path} is missing required key "${key}".`, `Fix it manually or run
|
|
75083
|
+
throw userError(`Existing .env at ${path} is missing required key "${key}".`, `Fix it manually or run \`${progName()} init --force\` to start fresh.`);
|
|
75043
75084
|
}
|
|
75044
75085
|
}
|
|
75045
75086
|
return {
|
|
@@ -75084,7 +75125,8 @@ async function promptForAnswers() {
|
|
|
75084
75125
|
});
|
|
75085
75126
|
println("");
|
|
75086
75127
|
println(c.cyan("▶ Step 4/5 — Direct Postgres connection (optional for npm-installed users)"));
|
|
75087
|
-
println(c.dim(
|
|
75128
|
+
println(c.dim(` Only needed for \`${progName()} server deploy\` (schema deploy + migrations).
|
|
75129
|
+
` + ` You can skip this and set CEREFOX_DATABASE_URL later — press Enter.
|
|
75088
75130
|
` + " Format: postgresql://postgres.<project-ref>:<pw>@…:5432/postgres?sslmode=require"));
|
|
75089
75131
|
const databaseUrl = await ask({
|
|
75090
75132
|
type: "text",
|
|
@@ -75229,7 +75271,7 @@ async function maybeOfferServerDeploy() {
|
|
|
75229
75271
|
if (yes)
|
|
75230
75272
|
launchDeployServer();
|
|
75231
75273
|
else
|
|
75232
|
-
println(c.dim(
|
|
75274
|
+
println(c.dim(` Skipped. Run \`${progName()} server deploy\` later (or \`${progName()} doctor\` to recheck).`));
|
|
75233
75275
|
println("");
|
|
75234
75276
|
return;
|
|
75235
75277
|
}
|
|
@@ -75240,7 +75282,7 @@ async function maybeOfferServerDeploy() {
|
|
|
75240
75282
|
if (yes)
|
|
75241
75283
|
launchDeployServer();
|
|
75242
75284
|
else
|
|
75243
|
-
println(c.dim(
|
|
75285
|
+
println(c.dim(` Skipped. Run \`${progName()} server deploy\` when ready.`));
|
|
75244
75286
|
println("");
|
|
75245
75287
|
return;
|
|
75246
75288
|
}
|
|
@@ -75259,7 +75301,7 @@ async function postWriteLifecycle(envPath, options) {
|
|
|
75259
75301
|
await Promise.resolve().then(() => init_sync_self_docs());
|
|
75260
75302
|
await runSyncSelfDocs({});
|
|
75261
75303
|
} catch (err) {
|
|
75262
|
-
warn(`Self-doc ingest failed: ${err instanceof Error ? err.message : String(err)}. Run
|
|
75304
|
+
warn(`Self-doc ingest failed: ${err instanceof Error ? err.message : String(err)}. Run \`${progName()} guides ingest\` manually after init.`);
|
|
75263
75305
|
}
|
|
75264
75306
|
println("");
|
|
75265
75307
|
}
|
|
@@ -75283,9 +75325,9 @@ async function postWriteLifecycle(envPath, options) {
|
|
|
75283
75325
|
}
|
|
75284
75326
|
println("");
|
|
75285
75327
|
println(c.green("Done. Try:"));
|
|
75286
|
-
println(c.dim(
|
|
75287
|
-
println(c.dim(
|
|
75288
|
-
println(c.dim(
|
|
75328
|
+
println(c.dim(` ${progName()} doctor # verify everything`));
|
|
75329
|
+
println(c.dim(` ${progName()} search "…" # search the KB`));
|
|
75330
|
+
println(c.dim(` ${progName()} document ingest <file> # add a doc`));
|
|
75289
75331
|
println("");
|
|
75290
75332
|
println(c.dim(` Config in effect: ${envPath}`));
|
|
75291
75333
|
}
|
|
@@ -75386,7 +75428,7 @@ async function action23(options) {
|
|
|
75386
75428
|
println("");
|
|
75387
75429
|
println(c.green(`✓ Using existing config at ${cwdEnv}`));
|
|
75388
75430
|
println(c.dim(` TS reads it via the legacy dev-mode fallback (~/.cerefox/.env not present).`));
|
|
75389
|
-
println(c.dim(` Run
|
|
75431
|
+
println(c.dim(` Run \`${progName()} init\` again later to migrate to the new home.`));
|
|
75390
75432
|
println("");
|
|
75391
75433
|
await postWriteLifecycle(cwdEnv, options);
|
|
75392
75434
|
return;
|
|
@@ -75427,7 +75469,7 @@ async function action24(options) {
|
|
|
75427
75469
|
throw systemError(`Project lookup failed: ${projectError.message}`);
|
|
75428
75470
|
}
|
|
75429
75471
|
if (!project) {
|
|
75430
|
-
throw userError(`Project "${options.project}" not found.`,
|
|
75472
|
+
throw userError(`Project "${options.project}" not found.`, `Run \`${progName()} project list\` to see available names.`);
|
|
75431
75473
|
}
|
|
75432
75474
|
projectId = project.id;
|
|
75433
75475
|
}
|
|
@@ -75743,7 +75785,7 @@ function warnLargeBulkWrite(opts) {
|
|
|
75743
75785
|
async function action29(options) {
|
|
75744
75786
|
const settings = loadSettings();
|
|
75745
75787
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
75746
|
-
throw userError(
|
|
75788
|
+
throw userError(`Supabase credentials not configured — run \`${progName()} init\` first.`);
|
|
75747
75789
|
}
|
|
75748
75790
|
if (!settings.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
75749
75791
|
throw userError("OPENAI_API_KEY not set — required for embeddings.");
|
|
@@ -76014,7 +76056,7 @@ async function action31(target, options) {
|
|
|
76014
76056
|
}
|
|
76015
76057
|
const trashedInFile = payload.documents.filter((d) => d.deleted_at != null).length;
|
|
76016
76058
|
if (trashedInFile > 0) {
|
|
76017
|
-
println(c.dim(` trashed documents in file: ${trashedInFile} — restored as trash ` +
|
|
76059
|
+
println(c.dim(` trashed documents in file: ${trashedInFile} — restored as trash ` + `(still deleted; recover with \`${progName()} document restore\`)`));
|
|
76018
76060
|
}
|
|
76019
76061
|
println("");
|
|
76020
76062
|
const client = getClient();
|
|
@@ -76133,7 +76175,7 @@ async function action31(target, options) {
|
|
|
76133
76175
|
}
|
|
76134
76176
|
}
|
|
76135
76177
|
function registerRestore(program) {
|
|
76136
|
-
program.command("restore").description("Restore a JSON-snapshot backup into the knowledge base.").argument("<snapshot>",
|
|
76178
|
+
program.command("restore").description("Restore a JSON-snapshot backup into the knowledge base.").argument("<snapshot>", `Backup file (or directory; most recent is picked) produced by \`${progName()} backup\`.`).option("--dry-run", "Print what would be restored without writing.").option("-p, --project-name <name>", "Reserved for future use; currently ignored. Project memberships are restored from the backup itself (format 2+).").action(action31);
|
|
76137
76179
|
}
|
|
76138
76180
|
|
|
76139
76181
|
// src/cli/commands/search.ts
|
|
@@ -76148,13 +76190,13 @@ async function embedQuery(query) {
|
|
|
76148
76190
|
const settings = loadSettings();
|
|
76149
76191
|
const apiKey = settings.openaiApiKey;
|
|
76150
76192
|
if (!apiKey && resolveEmbedderKind() !== "local") {
|
|
76151
|
-
throw userError("OPENAI_API_KEY (or CEREFOX_OPENAI_API_KEY) is required for search.",
|
|
76193
|
+
throw userError("OPENAI_API_KEY (or CEREFOX_OPENAI_API_KEY) is required for search.", `Set the key in your .env, or run \`${progName()} init\` to bootstrap.`);
|
|
76152
76194
|
}
|
|
76153
76195
|
try {
|
|
76154
76196
|
return await getEmbedding(query, apiKey);
|
|
76155
76197
|
} catch (err) {
|
|
76156
76198
|
const msg = err instanceof Error ? err.message : String(err);
|
|
76157
|
-
throw systemError(`Failed to embed query: ${msg}`,
|
|
76199
|
+
throw systemError(`Failed to embed query: ${msg}`, `Run \`${progName()} doctor\` to verify the OpenAI API path.`);
|
|
76158
76200
|
}
|
|
76159
76201
|
}
|
|
76160
76202
|
|
|
@@ -76326,7 +76368,7 @@ async function action32(query, options) {
|
|
|
76326
76368
|
}
|
|
76327
76369
|
}
|
|
76328
76370
|
function registerSearch(program) {
|
|
76329
|
-
program.command("search").description("Search the knowledge base (hybrid FTS + semantic).").argument("<query>", "Natural-language search query.").option("-c, --match-count <n>", "Maximum number of documents to return.", "5").option("-p, --project-name <name>", "Filter results to a specific project.").option("-f, --metadata-filter <json>", "JSON containment filter; only docs whose metadata contains ALL pairs are returned.").option("--mode <mode>", "Search mode: docs (default), hybrid, fts.", "docs").option("--alpha <float>", "Semantic weight 0..1 (default: CEREFOX_SEARCH_ALPHA; else 0.7).").option("--min-score <float>", "Minimum cosine similarity threshold (default: the store's min_search_score; else 0.5, or 0.6 on a local-embedder store).").option("--min-term-coverage <float>", "OR-fallback keyword matches must cover at least this fraction of the query's meaningful terms to count as confident hits (default: the store's min_term_coverage; else 0.66; needs schema ≥ 0.9.1).").option("--max-bytes <n>", "Response size budget in bytes (default: CEREFOX_MAX_RESPONSE_BYTES or 200000).").addOption(authorOption("read")).addOption(requestorAliasOption()).option("--json", "Emit machine-readable JSON instead of the default text.").option("--only-metadata",
|
|
76371
|
+
program.command("search").description("Search the knowledge base (hybrid FTS + semantic).").argument("<query>", "Natural-language search query.").option("-c, --match-count <n>", "Maximum number of documents to return.", "5").option("-p, --project-name <name>", "Filter results to a specific project.").option("-f, --metadata-filter <json>", "JSON containment filter; only docs whose metadata contains ALL pairs are returned.").option("--mode <mode>", "Search mode: docs (default), hybrid, fts.", "docs").option("--alpha <float>", "Semantic weight 0..1 (default: CEREFOX_SEARCH_ALPHA; else 0.7).").option("--min-score <float>", "Minimum cosine similarity threshold (default: the store's min_search_score; else 0.5, or 0.6 on a local-embedder store).").option("--min-term-coverage <float>", "OR-fallback keyword matches must cover at least this fraction of the query's meaningful terms to count as confident hits (default: the store's min_term_coverage; else 0.66; needs schema ≥ 0.9.1).").option("--max-bytes <n>", "Response size budget in bytes (default: CEREFOX_MAX_RESPONSE_BYTES or 200000).").addOption(authorOption("read")).addOption(requestorAliasOption()).option("--json", "Emit machine-readable JSON instead of the default text.").option("--only-metadata", `List matching docs (id, score, chunks, chars, partial/full) WITHOUT their content — like the web UI's collapsed result list. Grab a [id:…] then \`${progName()} document get <id>\`.`).action(action32);
|
|
76330
76372
|
}
|
|
76331
76373
|
|
|
76332
76374
|
// src/cli/commands/self-update.ts
|
|
@@ -76391,7 +76433,7 @@ async function action33(options) {
|
|
|
76391
76433
|
if (options.check) {
|
|
76392
76434
|
if (newerRelease(target)) {
|
|
76393
76435
|
println(c.yellow(`Update available: ${PKG_VERSION} → ${target}`));
|
|
76394
|
-
println(c.dim(
|
|
76436
|
+
println(c.dim(`Run \`${progName()} self-update\` to upgrade.`));
|
|
76395
76437
|
}
|
|
76396
76438
|
return;
|
|
76397
76439
|
}
|
|
@@ -76422,12 +76464,12 @@ async function action33(options) {
|
|
|
76422
76464
|
}
|
|
76423
76465
|
println("");
|
|
76424
76466
|
println("Next steps:");
|
|
76425
|
-
println(" 1. " + c.bold(
|
|
76426
|
-
println(" 2. " + c.bold(
|
|
76467
|
+
println(" 1. " + c.bold(`${progName()} server deploy`) + " apply this release's schema/RPC/EF updates");
|
|
76468
|
+
println(" 2. " + c.bold(`${progName()} guides ingest`) + " re-sync the bundled guides into your KB");
|
|
76427
76469
|
println(c.dim(" (order matters: the new client may require the new schema — run the deploy first)"));
|
|
76428
76470
|
}
|
|
76429
76471
|
function registerSelfUpdate(program) {
|
|
76430
|
-
const desc =
|
|
76472
|
+
const desc = `Upgrade Cerefox in place. Alias: \`${progName()} upgrade\`.`;
|
|
76431
76473
|
const declaration = (cmd) => cmd.description(desc).option("--check", "Print current vs latest; do nothing.").option("--yes", "Non-interactive (skip confirmation).").option("--version <version>", "Pin a specific version (e.g. 0.5.1 or 0.6.0-rc.1).").action(action33);
|
|
76432
76474
|
declaration(program.command("self-update"));
|
|
76433
76475
|
declaration(program.command("upgrade"));
|
|
@@ -76468,7 +76510,7 @@ async function action34(options) {
|
|
|
76468
76510
|
}
|
|
76469
76511
|
}
|
|
76470
76512
|
function registerStatus(program) {
|
|
76471
|
-
program.command("status").description(
|
|
76513
|
+
program.command("status").description(`Quick sanity check (fast subset of \`${progName()} doctor\`).`).option("--json", "Emit machine-readable JSON.").action(action34);
|
|
76472
76514
|
}
|
|
76473
76515
|
|
|
76474
76516
|
// src/cli/commands/api-key.ts
|
|
@@ -76581,7 +76623,7 @@ function generateAction(opts) {
|
|
|
76581
76623
|
const envPath = resolveEnvFile();
|
|
76582
76624
|
const existing = readEnvVar(envPath, ENV_NAME);
|
|
76583
76625
|
if (existing) {
|
|
76584
|
-
throw userError(`${ENV_NAME} is already set in ${envPath} (${mask(existing)}).`,
|
|
76626
|
+
throw userError(`${ENV_NAME} is already set in ${envPath} (${mask(existing)}).`, `Use \`${progName()} api-key show\` to see it, or \`${progName()} api-key rotate\` to replace it. ` + "Refusing to overwrite silently: any client already configured with the old key " + "would start getting 401s with no indication why.");
|
|
76585
76627
|
}
|
|
76586
76628
|
println(c.bold("Minting a local API key"));
|
|
76587
76629
|
writeKey(mint(), opts, "write");
|
|
@@ -76591,13 +76633,13 @@ function rotateAction(opts) {
|
|
|
76591
76633
|
const envPath = resolveEnvFile();
|
|
76592
76634
|
const existing = readEnvVar(envPath, ENV_NAME);
|
|
76593
76635
|
if (!existing) {
|
|
76594
|
-
throw userError(`No ${ENV_NAME} in ${envPath} — nothing to rotate.`,
|
|
76636
|
+
throw userError(`No ${ENV_NAME} in ${envPath} — nothing to rotate.`, `Run \`${progName()} api-key generate\` first.`);
|
|
76595
76637
|
}
|
|
76596
76638
|
println(c.bold("Rotating the local API key"));
|
|
76597
76639
|
println(c.dim(` replacing ${mask(existing)}`));
|
|
76598
76640
|
writeKey(mint(), opts, "replace");
|
|
76599
76641
|
println(c.yellow(` The previous key stops working as soon as the server restarts.
|
|
76600
|
-
` +
|
|
76642
|
+
` + ` Update every remote client, then: ${progName()} web restart`));
|
|
76601
76643
|
}
|
|
76602
76644
|
function showAction2() {
|
|
76603
76645
|
const envPath = resolveEnvFile();
|
|
@@ -76607,7 +76649,7 @@ function showAction2() {
|
|
|
76607
76649
|
println(c.dim(` none set in ${envPath}`));
|
|
76608
76650
|
println(c.dim(` The server is not gated: callers from any interface it is bound to can
|
|
76609
76651
|
` + ` reach it without a credential. That is fine while it binds 127.0.0.1.
|
|
76610
|
-
` +
|
|
76652
|
+
` + ` Mint one with: ${progName()} api-key generate`));
|
|
76611
76653
|
containerHint();
|
|
76612
76654
|
return;
|
|
76613
76655
|
}
|
|
@@ -76688,7 +76730,7 @@ function printTokenOnce(token) {
|
|
|
76688
76730
|
println(c.dim(" • Custom GPT → Configure → Actions → Authentication → API Key (Bearer)"));
|
|
76689
76731
|
println(c.dim(" • Remote HTTP MCP → the Authorization: Bearer header"));
|
|
76690
76732
|
println(c.dim(" If the GPT Actions schema changed this release, re-paste it too"));
|
|
76691
|
-
println(c.dim(
|
|
76733
|
+
println(c.dim(` (see docs/guides/connect-agents.md). Lose the token → \`${progName()} token rotate\`.`));
|
|
76692
76734
|
}
|
|
76693
76735
|
function generateAction2(opts) {
|
|
76694
76736
|
const projectRef = opts.projectRef ?? parseProjectRef2(loadSettings().supabaseUrl);
|
|
@@ -76705,7 +76747,7 @@ function rotateAction2(opts) {
|
|
|
76705
76747
|
const current = readEnvVar(envPath, LOCAL_NAME);
|
|
76706
76748
|
if (opts.finalize) {
|
|
76707
76749
|
if (!current) {
|
|
76708
|
-
throw userError(`No ${LOCAL_NAME} in ${envPath} to finalize to.`,
|
|
76750
|
+
throw userError(`No ${LOCAL_NAME} in ${envPath} to finalize to.`, `Run \`${progName()} token generate\` or \`${progName()} token rotate\` first.`);
|
|
76709
76751
|
}
|
|
76710
76752
|
println(c.bold("Finalizing rotation (dropping the previous token)…"));
|
|
76711
76753
|
setSecret(current, projectRef, opts.dryRun);
|
|
@@ -76722,14 +76764,15 @@ function rotateAction2(opts) {
|
|
|
76722
76764
|
printTokenOnce(token);
|
|
76723
76765
|
println("");
|
|
76724
76766
|
println(c.yellow(` Both the new and previous tokens are accepted right now. Update every
|
|
76725
|
-
` +
|
|
76767
|
+
` + ` client to the new token, then run \`${progName()} token rotate --finalize\`
|
|
76768
|
+
` + " to stop accepting the old one."));
|
|
76726
76769
|
}
|
|
76727
76770
|
}
|
|
76728
76771
|
function listAction2() {
|
|
76729
76772
|
const envPath = resolveEnvFile();
|
|
76730
76773
|
const local = readEnvVar(envPath, LOCAL_NAME);
|
|
76731
76774
|
println(c.bold("Cerefox access token"));
|
|
76732
|
-
println(local ? ` local (${LOCAL_NAME} in ${envPath}): ${c.green(mask2(local))}` : c.dim(` no ${LOCAL_NAME} in ${envPath} — run
|
|
76775
|
+
println(local ? ` local (${LOCAL_NAME} in ${envPath}): ${c.green(mask2(local))}` : c.dim(` no ${LOCAL_NAME} in ${envPath} — run \`${progName()} token generate\``));
|
|
76733
76776
|
println(c.dim(` The server-side accepted set (${SECRET_NAME}) is write-only; list names/digests
|
|
76734
76777
|
` + " with: npx supabase secrets list"));
|
|
76735
76778
|
}
|
|
@@ -81964,6 +82007,14 @@ var STRIP_RESPONSE_HEADERS = [
|
|
|
81964
82007
|
"proxy-authenticate",
|
|
81965
82008
|
"proxy-authorization"
|
|
81966
82009
|
];
|
|
82010
|
+
function upstreamCredentials(headers, reason, internalJwt) {
|
|
82011
|
+
const jwt = internalJwt.trim();
|
|
82012
|
+
if (reason !== "valid_key" || !jwt)
|
|
82013
|
+
return false;
|
|
82014
|
+
headers.set("authorization", `Bearer ${jwt}`);
|
|
82015
|
+
headers.set("apikey", jwt);
|
|
82016
|
+
return true;
|
|
82017
|
+
}
|
|
81967
82018
|
function registerPostgrestProxy(app) {
|
|
81968
82019
|
const upstream = (process.env.CEREFOX_POSTGREST_UPSTREAM ?? "").trim().replace(/\/+$/, "");
|
|
81969
82020
|
if (!upstream)
|
|
@@ -81975,6 +82026,7 @@ function registerPostgrestProxy(app) {
|
|
|
81975
82026
|
const headers = new Headers(c.req.raw.headers);
|
|
81976
82027
|
headers.delete("host");
|
|
81977
82028
|
headers.delete("accept-encoding");
|
|
82029
|
+
upstreamCredentials(headers, c.get("cerefoxAuthReason"), process.env.CEREFOX_SUPABASE_KEY ?? "");
|
|
81978
82030
|
const method = c.req.method;
|
|
81979
82031
|
const init = { method, headers };
|
|
81980
82032
|
if (method !== "GET" && method !== "HEAD") {
|
|
@@ -82342,7 +82394,7 @@ async function assertServerCompatible() {
|
|
|
82342
82394
|
` + parts.join(`
|
|
82343
82395
|
`) + `
|
|
82344
82396
|
|
|
82345
|
-
Redeploy your server:
|
|
82397
|
+
Redeploy your server: ${progName()} server deploy
|
|
82346
82398
|
` + `(or downgrade the client to match the deployed server).`);
|
|
82347
82399
|
}
|
|
82348
82400
|
async function buildWebServer(options = {}) {
|
|
@@ -82357,7 +82409,7 @@ async function buildWebServer(options = {}) {
|
|
|
82357
82409
|
⚠ Binding ${host} with NO API key configured.
|
|
82358
82410
|
` + ` Every read, write, delete and purge on this server is reachable by
|
|
82359
82411
|
` + ` anything that can connect to port ${port}, with no credential.
|
|
82360
|
-
` + ` Mint one:
|
|
82412
|
+
` + ` Mint one: ${progName()} api-key generate
|
|
82361
82413
|
`);
|
|
82362
82414
|
}
|
|
82363
82415
|
const app = buildApp();
|
|
@@ -82439,7 +82491,7 @@ function registerWeb(program) {
|
|
|
82439
82491
|
break;
|
|
82440
82492
|
case "port-conflict":
|
|
82441
82493
|
eprintln(`A Cerefox web daemon is already running on :${outcome.info.port} (pid ${outcome.info.pid}).
|
|
82442
|
-
` + `Stop it first (
|
|
82494
|
+
` + `Stop it first (\`${progName()} web stop\`) or start on its port.`);
|
|
82443
82495
|
process.exit(1);
|
|
82444
82496
|
break;
|
|
82445
82497
|
case "started":
|
|
@@ -82447,7 +82499,7 @@ function registerWeb(program) {
|
|
|
82447
82499
|
info(`Cerefox web started (pid ${outcome.pid}) on http://${rawOpts.host}:${port}/`);
|
|
82448
82500
|
println(` Web UI: http://${rawOpts.host}:${port}/app/`);
|
|
82449
82501
|
println(c.dim(` Logs: ${daemonPaths.logFile}`));
|
|
82450
|
-
println(c.dim(` Stop:
|
|
82502
|
+
println(c.dim(` Stop: ${progName()} web stop`));
|
|
82451
82503
|
} else {
|
|
82452
82504
|
const refusal = readStartupRefusal();
|
|
82453
82505
|
if (refusal) {
|
|
@@ -82489,7 +82541,7 @@ Full log: ${daemonPaths.logFile}`);
|
|
|
82489
82541
|
break;
|
|
82490
82542
|
case "stale":
|
|
82491
82543
|
println(c.yellow(`Cerefox web: stale pidfile — process ${status.info.pid} is not running.`));
|
|
82492
|
-
println(c.dim(` Clean up:
|
|
82544
|
+
println(c.dim(` Clean up: ${progName()} web stop (removes ${daemonPaths.pidFile})`));
|
|
82493
82545
|
break;
|
|
82494
82546
|
case "running":
|
|
82495
82547
|
if (status.responding) {
|
|
@@ -82541,16 +82593,16 @@ var RENAMED_VERBS = [
|
|
|
82541
82593
|
function registerRenameHusks(program) {
|
|
82542
82594
|
for (const [oldName, newForm] of RENAMED_VERBS) {
|
|
82543
82595
|
program.command(oldName, { hidden: true }).allowUnknownOption(true).allowExcessArguments(true).argument("[args...]", "(renamed)").action(() => {
|
|
82544
|
-
eprintln(c.yellow(`✗
|
|
82545
|
-
eprintln(` Use
|
|
82596
|
+
eprintln(c.yellow(`✗ \`${progName()} ${oldName}\` was renamed.`));
|
|
82597
|
+
eprintln(` Use \`${progName()} ${newForm}\` instead (run \`${progName()} ${newForm.split(" ")[0]} --help\`).`);
|
|
82546
82598
|
process.exit(1);
|
|
82547
82599
|
});
|
|
82548
82600
|
}
|
|
82549
82601
|
}
|
|
82550
82602
|
function buildProgram() {
|
|
82551
|
-
const
|
|
82552
|
-
const program = new Command(
|
|
82553
|
-
Resource groups (run \`${
|
|
82603
|
+
const progName2 = process.env.CEREFOX_PROG_NAME || "cerefox";
|
|
82604
|
+
const program = new Command(progName2).description("Cerefox — user-owned shared memory for AI agents.").version(PKG_VERSION, "-v, --version", `Print the ${progName2} version and exit.`).addOption(new Option("--json", "Emit machine-readable JSON on stdout instead of the default human text. " + "Available on read commands; ignored on commands without a JSON shape.").hideHelp()).showHelpAfterError(`(run \`${progName2} --help\` for usage)`).enablePositionalOptions().addHelpText("after", `
|
|
82605
|
+
Resource groups (run \`${progName2} <group> --help\`):
|
|
82554
82606
|
` + ` document get · list · edit · delete · restore · ingest · ingest-dir · version {list·archive·unarchive}
|
|
82555
82607
|
` + ` project list · create · edit · delete
|
|
82556
82608
|
` + ` metadata keys · search
|
|
@@ -82573,8 +82625,8 @@ Exit codes:
|
|
|
82573
82625
|
` + ` 1 user error 3 not found (document / version / project)
|
|
82574
82626
|
` + `
|
|
82575
82627
|
Learn more:
|
|
82576
|
-
` + ` ${
|
|
82577
|
-
` + ` ${
|
|
82628
|
+
` + ` ${progName2} guides list # bundled docs (offline)
|
|
82629
|
+
` + ` ${progName2} doctor # diagnose your install
|
|
82578
82630
|
` + ` https://github.com/fstamatelopoulos/cerefox
|
|
82579
82631
|
`);
|
|
82580
82632
|
registerSearch(program);
|
|
@@ -82625,8 +82677,8 @@ Learn more:
|
|
|
82625
82677
|
moveInto(config, registerConfigGet, "get");
|
|
82626
82678
|
moveInto(config, registerConfigSet, "set");
|
|
82627
82679
|
const backup = program.command("backup").description("Backup + restore the knowledge base: create, restore.").action(() => {
|
|
82628
|
-
eprintln(c.yellow(
|
|
82629
|
-
eprintln(
|
|
82680
|
+
eprintln(c.yellow(`\`${progName()} backup\` needs a subcommand.`));
|
|
82681
|
+
eprintln(` Use \`${progName()} backup create\` or \`${progName()} backup restore\`.`);
|
|
82630
82682
|
process.exit(1);
|
|
82631
82683
|
});
|
|
82632
82684
|
moveInto(backup, registerBackup, "create");
|
|
@@ -82663,22 +82715,22 @@ async function bareEntryPoint() {
|
|
|
82663
82715
|
if (!configExists) {
|
|
82664
82716
|
println(c.yellow("⚠ No config detected."));
|
|
82665
82717
|
println("Next step:");
|
|
82666
|
-
println(" " + c.bold(
|
|
82718
|
+
println(" " + c.bold(`${progName()} init`) + " # interactive first-run setup (~2 min)");
|
|
82667
82719
|
println("");
|
|
82668
82720
|
println(c.dim("Once configured, try:"));
|
|
82669
|
-
println(c.dim(
|
|
82670
|
-
println(c.dim(
|
|
82671
|
-
println(c.dim(
|
|
82721
|
+
println(c.dim(` ${progName()} doctor # verify your install`));
|
|
82722
|
+
println(c.dim(` ${progName()} search "…" # search the KB`));
|
|
82723
|
+
println(c.dim(` ${progName()} document ingest <file> # add a doc`));
|
|
82672
82724
|
} else {
|
|
82673
82725
|
println(c.green("✓ Config detected. You're good to go."));
|
|
82674
82726
|
println("");
|
|
82675
82727
|
println("Common commands:");
|
|
82676
|
-
println(c.dim(
|
|
82677
|
-
println(c.dim(
|
|
82678
|
-
println(c.dim(
|
|
82679
|
-
println(c.dim(
|
|
82728
|
+
println(c.dim(` ${progName()} doctor # diagnose your install`));
|
|
82729
|
+
println(c.dim(` ${progName()} search "…" # search the KB`));
|
|
82730
|
+
println(c.dim(` ${progName()} document ingest <file> # add a doc`));
|
|
82731
|
+
println(c.dim(` ${progName()} configure-agent # wire up an MCP client`));
|
|
82680
82732
|
println("");
|
|
82681
|
-
println(c.dim(
|
|
82733
|
+
println(c.dim(`Run \`${progName()} --help\` for the full command list.`));
|
|
82682
82734
|
}
|
|
82683
82735
|
}
|
|
82684
82736
|
async function main() {
|