@cerefox/memory 1.21.0 → 1.22.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/dist/bin/cerefox.js +180 -123
- package/dist/frontend/assets/{docx-DeQjAnSd.js → docx-BvP4Jo4k.js} +2 -2
- package/dist/frontend/assets/{docx-DeQjAnSd.js.map → docx-BvP4Jo4k.js.map} +1 -1
- package/dist/frontend/assets/{index-Dd1nIOAB.js → index-nwj65c23.js} +31 -31
- package/dist/frontend/assets/{index-Dd1nIOAB.js.map → index-nwj65c23.js.map} +1 -1
- package/dist/frontend/assets/{markdown-CsTKTR78.js → markdown-C3Pl9aLl.js} +2 -2
- package/dist/frontend/assets/{markdown-CsTKTR78.js.map → markdown-C3Pl9aLl.js.map} +1 -1
- package/dist/frontend/assets/{pdf-CkRjSAWX.js → pdf-nplQ05zY.js} +2 -2
- package/dist/frontend/assets/{pdf-CkRjSAWX.js.map → pdf-nplQ05zY.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/api/openapi.json +5 -1
- package/docs/guides/api.md +1 -1
- 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 +165 -9
- package/docs/guides/setup-local.md +11 -0
- 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.1";
|
|
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) {
|
|
@@ -26926,8 +26951,10 @@ function newerRelease(latest, installed = PKG_VERSION) {
|
|
|
26926
26951
|
return null;
|
|
26927
26952
|
return compareSemver(latest, installed) > 0 ? latest : null;
|
|
26928
26953
|
}
|
|
26929
|
-
function upgradeCommand() {
|
|
26930
|
-
|
|
26954
|
+
function upgradeCommand(env = process.env, containerised = isContainerised()) {
|
|
26955
|
+
if (!containerised)
|
|
26956
|
+
return "cerefox self-update";
|
|
26957
|
+
return env.CEREFOX_PROG_NAME === "cerefox-local" ? "cerefox-local upgrade" : null;
|
|
26931
26958
|
}
|
|
26932
26959
|
function takeCliNotice(opts = {}) {
|
|
26933
26960
|
if (updateCheckDisabled(opts.env))
|
|
@@ -26944,21 +26971,24 @@ function takeCliNotice(opts = {}) {
|
|
|
26944
26971
|
return null;
|
|
26945
26972
|
}
|
|
26946
26973
|
writeCache({ ...cached, notifiedAt: now.toISOString() }, path);
|
|
26947
|
-
|
|
26974
|
+
const cmd = upgradeCommand(opts.env);
|
|
26975
|
+
return `Cerefox ${newer} is available (you have ${opts.installed ?? PKG_VERSION}).` + (cmd ? ` Run \`${cmd}\`.` : "");
|
|
26948
26976
|
}
|
|
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}`;
|
|
26977
|
+
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
26978
|
var init_update_check = __esm(() => {
|
|
26951
26979
|
init_compatibility();
|
|
26952
26980
|
init_meta();
|
|
26953
26981
|
init_auth();
|
|
26954
26982
|
init_daemon();
|
|
26955
26983
|
DAY_MS = 24 * 60 * 60 * 1000;
|
|
26956
|
-
|
|
26984
|
+
HOUR_MS = 60 * 60 * 1000;
|
|
26985
|
+
CACHE_TTL_MS = HOUR_MS;
|
|
26986
|
+
REFRESH_TICK_MS = 15 * 60 * 1000;
|
|
26957
26987
|
NOTIFY_INTERVAL_MS = DAY_MS;
|
|
26958
26988
|
});
|
|
26959
26989
|
|
|
26960
26990
|
// ../../_shared/ef-meta/index.ts
|
|
26961
|
-
var EF_VERSION = "1.
|
|
26991
|
+
var EF_VERSION = "1.22.1", CEREFOX_VERSION = "1.22.1", EF_LAST_CHANGED = "1.22.0";
|
|
26962
26992
|
var init_ef_meta = () => {};
|
|
26963
26993
|
|
|
26964
26994
|
// ../../_shared/embeddings/onnx-embedder.ts
|
|
@@ -63952,7 +63982,7 @@ async function warnIfSchemaVersionMismatch(supabase) {
|
|
|
63952
63982
|
if (!bundled)
|
|
63953
63983
|
return;
|
|
63954
63984
|
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
|
|
63985
|
+
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
63986
|
`);
|
|
63957
63987
|
}
|
|
63958
63988
|
} catch {}
|
|
@@ -66357,7 +66387,7 @@ end
|
|
|
66357
66387
|
complete -c ${prog} -f -a '(__${fn}_complete)'
|
|
66358
66388
|
`;
|
|
66359
66389
|
}
|
|
66360
|
-
function
|
|
66390
|
+
function progName2() {
|
|
66361
66391
|
return buildProgram().name();
|
|
66362
66392
|
}
|
|
66363
66393
|
function fnId(prog) {
|
|
@@ -66365,7 +66395,7 @@ function fnId(prog) {
|
|
|
66365
66395
|
}
|
|
66366
66396
|
function scriptFor(shell) {
|
|
66367
66397
|
const nodes = collectNodes();
|
|
66368
|
-
const prog =
|
|
66398
|
+
const prog = progName2();
|
|
66369
66399
|
const fn = fnId(prog);
|
|
66370
66400
|
switch (shell) {
|
|
66371
66401
|
case "bash":
|
|
@@ -66397,7 +66427,7 @@ async function installMode(options) {
|
|
|
66397
66427
|
throw userError(`Unsupported --shell "${shell}". Use bash, zsh, or fish.`);
|
|
66398
66428
|
}
|
|
66399
66429
|
const home = homedir3();
|
|
66400
|
-
const prog =
|
|
66430
|
+
const prog = progName2();
|
|
66401
66431
|
const rcBegin = rcBeginFor(prog);
|
|
66402
66432
|
const rcEnd = rcEndFor(prog);
|
|
66403
66433
|
const scriptPath = join3(home, `.${prog}-completion.${shell}`);
|
|
@@ -66445,7 +66475,7 @@ async function action2(target, options) {
|
|
|
66445
66475
|
println(scriptFor(target));
|
|
66446
66476
|
if (process.stdout.isTTY) {
|
|
66447
66477
|
eprintln(c.dim(`
|
|
66448
|
-
# Tip:
|
|
66478
|
+
# Tip: \`${progName()} completion install\` writes this + wires your shell rc automatically.`));
|
|
66449
66479
|
}
|
|
66450
66480
|
}
|
|
66451
66481
|
function registerCompletion(program) {
|
|
@@ -66655,7 +66685,7 @@ function action4(options) {
|
|
|
66655
66685
|
});
|
|
66656
66686
|
return;
|
|
66657
66687
|
}
|
|
66658
|
-
println(c.bold(
|
|
66688
|
+
println(c.bold(`Runtime config keys (stored in cerefox_config; read with \`${progName()} config get <key>\`):`));
|
|
66659
66689
|
let group = null;
|
|
66660
66690
|
for (const spec of CONFIG_CATALOG) {
|
|
66661
66691
|
if (spec.group !== group) {
|
|
@@ -68052,7 +68082,7 @@ function delegatedWrite(writer, opts) {
|
|
|
68052
68082
|
if (result.error) {
|
|
68053
68083
|
const err = result.error;
|
|
68054
68084
|
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
|
|
68085
|
+
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
68086
|
}
|
|
68057
68087
|
throw new Error(`${writer.label}: failed to spawn \`${cmd}\`: ${err.message}`);
|
|
68058
68088
|
}
|
|
@@ -68169,18 +68199,18 @@ async function action7(documentId, options) {
|
|
|
68169
68199
|
} catch (e) {
|
|
68170
68200
|
const message = e instanceof Error ? e.message : String(e);
|
|
68171
68201
|
if (isMissingFunctionError(message, "cerefox_delete_document")) {
|
|
68172
|
-
throw systemError(options.reason ? `This server is behind: \`--reason\` needs schema 0.12.0 or newer. ` + `Run
|
|
68202
|
+
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
68203
|
}
|
|
68174
68204
|
throw e;
|
|
68175
68205
|
}
|
|
68176
68206
|
if (result === null) {
|
|
68177
68207
|
const { data: check, error: checkError } = await client.raw.from("cerefox_documents").select("deleted_at").eq("id", documentId).maybeSingle();
|
|
68178
68208
|
if (checkError) {
|
|
68179
|
-
warn(`Delete submitted, but the follow-up verification read failed (${checkError.message}). ` + `Confirm with:
|
|
68209
|
+
warn(`Delete submitted, but the follow-up verification read failed (${checkError.message}). ` + `Confirm with: ${progName()} document get ${documentId}`);
|
|
68180
68210
|
return;
|
|
68181
68211
|
}
|
|
68182
68212
|
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
|
|
68213
|
+
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
68214
|
}
|
|
68185
68215
|
}
|
|
68186
68216
|
if (result?.already_deleted) {
|
|
@@ -68203,7 +68233,7 @@ function registerDeleteDoc(program) {
|
|
|
68203
68233
|
init_cli_core();
|
|
68204
68234
|
init__utils();
|
|
68205
68235
|
init_client();
|
|
68206
|
-
var
|
|
68236
|
+
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
68237
|
async function action8(options) {
|
|
68208
68238
|
const client = getClient();
|
|
68209
68239
|
let rows;
|
|
@@ -68212,12 +68242,12 @@ async function action8(options) {
|
|
|
68212
68242
|
} catch (e) {
|
|
68213
68243
|
const message = e instanceof Error ? e.message : String(e);
|
|
68214
68244
|
if (isMissingFunctionError(message, "cerefox_find_dead_links")) {
|
|
68215
|
-
throw systemError(
|
|
68245
|
+
throw systemError(serverBehind());
|
|
68216
68246
|
}
|
|
68217
68247
|
throw e;
|
|
68218
68248
|
}
|
|
68219
68249
|
if (rows === null)
|
|
68220
|
-
throw systemError(
|
|
68250
|
+
throw systemError(serverBehind());
|
|
68221
68251
|
if (options.json) {
|
|
68222
68252
|
printJson(rows);
|
|
68223
68253
|
return;
|
|
@@ -68574,7 +68604,8 @@ async function action10(options) {
|
|
|
68574
68604
|
${c.red("✗")} ${ch.label}`);
|
|
68575
68605
|
eprintln(c.dim(` → ${ch.remediation}`));
|
|
68576
68606
|
}
|
|
68577
|
-
eprintln(
|
|
68607
|
+
eprintln(`
|
|
68608
|
+
Fix the above and re-run \`${progName()} server deploy\` (it's idempotent).`);
|
|
68578
68609
|
process.exit(1);
|
|
68579
68610
|
}
|
|
68580
68611
|
println(c.green(`
|
|
@@ -68724,9 +68755,9 @@ ${r.stderr ?? ""}`);
|
|
|
68724
68755
|
eprintln(c.dim(" published yet, and bundling fails."));
|
|
68725
68756
|
eprintln(c.dim(" Your deployed functions were NOT changed — the previous version is"));
|
|
68726
68757
|
eprintln(c.dim(" still serving, so nothing is down."));
|
|
68727
|
-
eprintln(c.cyan(
|
|
68758
|
+
eprintln(c.cyan(` → Wait a few minutes, then re-run: ${progName()} server deploy --functions-only`));
|
|
68728
68759
|
} else {
|
|
68729
|
-
eprintln(c.dim(
|
|
68760
|
+
eprintln(c.dim(` Re-run \`${progName()} server deploy --functions-only\` after fixing the cause.`));
|
|
68730
68761
|
}
|
|
68731
68762
|
process.exit(1);
|
|
68732
68763
|
}
|
|
@@ -68745,15 +68776,16 @@ ${r.stderr ?? ""}`);
|
|
|
68745
68776
|
println(c.cyan(`
|
|
68746
68777
|
ℹ The primitive Edge Functions now require the Cerefox access token.
|
|
68747
68778
|
` + ` If CEREFOX_ACCESS_TOKENS is unset they reject ALL callers (fail closed) —
|
|
68748
|
-
` +
|
|
68779
|
+
` + ` GPT Actions, remote HTTP, and \`${progName()} doctor\`. Generate it now:
|
|
68780
|
+
` + ` ${progName()} token generate
|
|
68749
68781
|
` + ` (or manually: supabase secrets set CEREFOX_ACCESS_TOKENS=<token> --project-ref ${ref})
|
|
68750
68782
|
` + " Migration + client cutover: docs/specs/ef-auth-migration-design.md §6."));
|
|
68751
68783
|
}
|
|
68752
68784
|
}
|
|
68753
68785
|
println(c.green(`
|
|
68754
68786
|
✓ Server deploy complete.`));
|
|
68755
|
-
println(c.dim(
|
|
68756
|
-
println(c.dim(
|
|
68787
|
+
println(c.dim(`Verify with: ${progName()} doctor`));
|
|
68788
|
+
println(c.dim(`Refresh the bundled guides: ${progName()} guides ingest`));
|
|
68757
68789
|
}
|
|
68758
68790
|
function efDeployArgs(ef, workdir, projectRef) {
|
|
68759
68791
|
const args = ["--yes", "supabase", "functions", "deploy", ef, "--use-api", "--workdir", workdir];
|
|
@@ -68804,7 +68836,7 @@ async function action11(documentId, options) {
|
|
|
68804
68836
|
if (!doc)
|
|
68805
68837
|
throw notFound(`Document ${documentId} not found.`);
|
|
68806
68838
|
if (doc.deleted_at) {
|
|
68807
|
-
throw userError(`Document ${documentId} is soft-deleted — restore it first (
|
|
68839
|
+
throw userError(`Document ${documentId} is soft-deleted — restore it first (${progName()} document restore).`);
|
|
68808
68840
|
}
|
|
68809
68841
|
const metaTouched = sets.length > 0 || unsets.length > 0;
|
|
68810
68842
|
const newTitle = hasTitle ? options.title.trim() : doc.title;
|
|
@@ -68831,7 +68863,7 @@ async function action11(documentId, options) {
|
|
|
68831
68863
|
});
|
|
68832
68864
|
if (metaErr) {
|
|
68833
68865
|
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:
|
|
68866
|
+
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
68867
|
}
|
|
68836
68868
|
throw systemError(`Metadata update failed: ${metaErr.message}`);
|
|
68837
68869
|
}
|
|
@@ -68850,7 +68882,7 @@ async function action11(documentId, options) {
|
|
|
68850
68882
|
}
|
|
68851
68883
|
println(c.green(`✓ Edited "${newTitle}" (id: ${documentId}).`));
|
|
68852
68884
|
if (titleChanged) {
|
|
68853
|
-
println(c.dim(
|
|
68885
|
+
println(c.dim(` Title changed: FTS refreshed; semantic embeddings update on next \`${progName()} server reindex\`.`));
|
|
68854
68886
|
}
|
|
68855
68887
|
}
|
|
68856
68888
|
function collect(value, prev) {
|
|
@@ -68891,21 +68923,21 @@ async function action12(documentId, options) {
|
|
|
68891
68923
|
} catch (e) {
|
|
68892
68924
|
const message = e instanceof Error ? e.message : String(e);
|
|
68893
68925
|
if (isMissingFunctionError(message, "cerefox_restore_document")) {
|
|
68894
|
-
throw systemError(options.reason ? `This server is behind: \`--reason\` needs schema 0.12.0 or newer. ` + `Run
|
|
68926
|
+
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
68927
|
}
|
|
68896
68928
|
throw e;
|
|
68897
68929
|
}
|
|
68898
68930
|
if (result === null) {
|
|
68899
68931
|
const { data: check, error: checkError } = await client.raw.from("cerefox_documents").select("deleted_at").eq("id", documentId).maybeSingle();
|
|
68900
68932
|
if (checkError) {
|
|
68901
|
-
warn(`Restore submitted, but the follow-up verification read failed (${checkError.message}). ` + `Confirm with:
|
|
68933
|
+
warn(`Restore submitted, but the follow-up verification read failed (${checkError.message}). ` + `Confirm with: ${progName()} document get ${documentId}`);
|
|
68902
68934
|
return;
|
|
68903
68935
|
}
|
|
68904
68936
|
if (!check) {
|
|
68905
68937
|
throw systemError(`Document ${documentId} no longer exists — it may have been purged concurrently. Nothing was restored.`);
|
|
68906
68938
|
}
|
|
68907
68939
|
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
|
|
68940
|
+
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
68941
|
}
|
|
68910
68942
|
}
|
|
68911
68943
|
if (result && result.restored === false) {
|
|
@@ -68986,15 +69018,15 @@ async function action13(documentId, options) {
|
|
|
68986
69018
|
if (/not found/i.test(msg))
|
|
68987
69019
|
throw notFound(`Document ${documentId} not found (or is deleted).`);
|
|
68988
69020
|
if (msg.includes("CEREFOX_METADATA_CONFLICT")) {
|
|
68989
|
-
throw userError(`The metadata of ${documentId} changed since you read it. Re-read it ` + `(
|
|
69021
|
+
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
69022
|
}
|
|
68991
69023
|
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
|
|
69024
|
+
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
69025
|
}
|
|
68994
69026
|
throw systemError(`Could not set metadata: ${msg}`);
|
|
68995
69027
|
}
|
|
68996
69028
|
if (!rows || rows.length === 0) {
|
|
68997
|
-
throw systemError("cerefox_set_document_metadata returned no data.",
|
|
69029
|
+
throw systemError("cerefox_set_document_metadata returned no data.", `Verify the RPC is deployed: \`${progName()} server deploy\`.`);
|
|
68998
69030
|
}
|
|
68999
69031
|
const row = rows[0];
|
|
69000
69032
|
if (options.jsonOut) {
|
|
@@ -69067,7 +69099,7 @@ function openInBrowser(path) {
|
|
|
69067
69099
|
function resolveDoc(topic) {
|
|
69068
69100
|
const doc = readBundledDoc(topic);
|
|
69069
69101
|
if (!doc) {
|
|
69070
|
-
throw notFound(`No bundled guide named "${topic}".`,
|
|
69102
|
+
throw notFound(`No bundled guide named "${topic}".`, `Run \`${progName()} guides list\` to see available topics.`);
|
|
69071
69103
|
}
|
|
69072
69104
|
return doc;
|
|
69073
69105
|
}
|
|
@@ -69081,7 +69113,7 @@ function listAction() {
|
|
|
69081
69113
|
println("");
|
|
69082
69114
|
printTable(docs.map((d) => ({ topic: d.topic, size_kb: Math.round(d.size / 1024) + " KB" })));
|
|
69083
69115
|
println("");
|
|
69084
|
-
println(c.dim(
|
|
69116
|
+
println(c.dim(`Open with \`${progName()} guides open <topic>\` (browser) or \`${progName()} guides show <topic>\` (stdout).`));
|
|
69085
69117
|
}
|
|
69086
69118
|
function openAction(topic) {
|
|
69087
69119
|
const doc = resolveDoc(topic);
|
|
@@ -69204,8 +69236,8 @@ async function setArchived(versionId, archived, options) {
|
|
|
69204
69236
|
println(c.green(`✓ Version ${data.version_number} (${versionId}) ${op}d.`));
|
|
69205
69237
|
}
|
|
69206
69238
|
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>",
|
|
69239
|
+
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));
|
|
69240
|
+
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
69241
|
}
|
|
69210
69242
|
|
|
69211
69243
|
// ../../node_modules/.bun/ora@9.4.1/node_modules/ora/index.js
|
|
@@ -72671,11 +72703,12 @@ async function checkUpdates() {
|
|
|
72671
72703
|
const newer = newerRelease(latest);
|
|
72672
72704
|
if (!newer)
|
|
72673
72705
|
return { name, status: "ok", detail: `up to date (latest release: v${latest})` };
|
|
72706
|
+
const cmd = upgradeCommand();
|
|
72674
72707
|
return {
|
|
72675
72708
|
name,
|
|
72676
72709
|
status: "skipped",
|
|
72677
72710
|
detail: `v${newer} is available (installed: v${PKG_VERSION})`,
|
|
72678
|
-
hint: `Run \`${
|
|
72711
|
+
hint: `${cmd ? `Run \`${cmd}\`. ` : ""}Release notes: ${releaseNotesUrl(newer)}`
|
|
72679
72712
|
};
|
|
72680
72713
|
}
|
|
72681
72714
|
function checkConfig() {
|
|
@@ -72687,7 +72720,7 @@ function checkConfig() {
|
|
|
72687
72720
|
name: "config",
|
|
72688
72721
|
status: "error",
|
|
72689
72722
|
detail: `Could not resolve config dir: ${err instanceof Error ? err.message : String(err)}`,
|
|
72690
|
-
hint:
|
|
72723
|
+
hint: `Run \`${progName()} init\` to bootstrap.`
|
|
72691
72724
|
};
|
|
72692
72725
|
}
|
|
72693
72726
|
if (!existsSync12(envPath)) {
|
|
@@ -72703,7 +72736,7 @@ function checkConfig() {
|
|
|
72703
72736
|
name: "config",
|
|
72704
72737
|
status: "error",
|
|
72705
72738
|
detail: `No config file at ${envPath}`,
|
|
72706
|
-
hint:
|
|
72739
|
+
hint: `Run \`${progName()} init\` to create one.`
|
|
72707
72740
|
};
|
|
72708
72741
|
}
|
|
72709
72742
|
let modeDetail = "";
|
|
@@ -72781,7 +72814,7 @@ async function checkRetiredEnvVars() {
|
|
|
72781
72814
|
hint: "Safe to delete those lines; nothing reads them."
|
|
72782
72815
|
};
|
|
72783
72816
|
}
|
|
72784
|
-
const moves = pending.map((v) =>
|
|
72817
|
+
const moves = pending.map((v) => `${progName()} config set ${v.configKey} ${(process.env[v.name] ?? "").trim()}`).join(`
|
|
72785
72818
|
`);
|
|
72786
72819
|
const prunedWasDisabled = pending.some((v) => v.configKey.startsWith("version_"));
|
|
72787
72820
|
return {
|
|
@@ -72795,6 +72828,17 @@ async function checkRetiredEnvVars() {
|
|
|
72795
72828
|
Then delete those lines from your .env — nothing reads them.`
|
|
72796
72829
|
};
|
|
72797
72830
|
}
|
|
72831
|
+
function dataApiHint(status, body, key) {
|
|
72832
|
+
if (status !== 401)
|
|
72833
|
+
return "Verify CEREFOX_SUPABASE_URL.";
|
|
72834
|
+
if (key.trim().startsWith("cfx_lak_")) {
|
|
72835
|
+
if (/PGRST30\d|JWT/.test(body)) {
|
|
72836
|
+
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.";
|
|
72837
|
+
}
|
|
72838
|
+
return "The server does not accept this API key. Check CEREFOX_SUPABASE_KEY against the server's key.";
|
|
72839
|
+
}
|
|
72840
|
+
return "Verify CEREFOX_SUPABASE_KEY (use the service-role / sb_secret key).";
|
|
72841
|
+
}
|
|
72798
72842
|
async function checkSupabase() {
|
|
72799
72843
|
let settings;
|
|
72800
72844
|
try {
|
|
@@ -72804,7 +72848,7 @@ async function checkSupabase() {
|
|
|
72804
72848
|
name: "supabase",
|
|
72805
72849
|
status: "error",
|
|
72806
72850
|
detail: `Could not load settings: ${err instanceof Error ? err.message : String(err)}`,
|
|
72807
|
-
hint:
|
|
72851
|
+
hint: `Run \`${progName()} init\`.`
|
|
72808
72852
|
};
|
|
72809
72853
|
}
|
|
72810
72854
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
@@ -72812,7 +72856,7 @@ async function checkSupabase() {
|
|
|
72812
72856
|
name: "supabase",
|
|
72813
72857
|
status: "error",
|
|
72814
72858
|
detail: "CEREFOX_SUPABASE_URL or CEREFOX_SUPABASE_KEY is not set.",
|
|
72815
|
-
hint:
|
|
72859
|
+
hint: `Run \`${progName()} init\` to bootstrap.`
|
|
72816
72860
|
};
|
|
72817
72861
|
}
|
|
72818
72862
|
try {
|
|
@@ -72824,11 +72868,12 @@ async function checkSupabase() {
|
|
|
72824
72868
|
}
|
|
72825
72869
|
});
|
|
72826
72870
|
if (!resp.ok) {
|
|
72871
|
+
const body = await resp.text().catch(() => "");
|
|
72827
72872
|
return {
|
|
72828
72873
|
name: "supabase",
|
|
72829
72874
|
status: "error",
|
|
72830
72875
|
detail: `Data API returned ${resp.status} ${resp.statusText}`,
|
|
72831
|
-
hint: resp.status
|
|
72876
|
+
hint: dataApiHint(resp.status, body, settings.supabaseKey)
|
|
72832
72877
|
};
|
|
72833
72878
|
}
|
|
72834
72879
|
return {
|
|
@@ -72860,7 +72905,7 @@ async function checkOpenAI() {
|
|
|
72860
72905
|
name: "openai",
|
|
72861
72906
|
status: "warn",
|
|
72862
72907
|
detail: "No OPENAI_API_KEY / CEREFOX_OPENAI_API_KEY set.",
|
|
72863
|
-
hint:
|
|
72908
|
+
hint: `Required for \`${progName()} search\` (semantic mode) and ingest. Set in your .env.`
|
|
72864
72909
|
};
|
|
72865
72910
|
}
|
|
72866
72911
|
try {
|
|
@@ -72991,7 +73036,7 @@ async function checkReviewWorkflow() {
|
|
|
72991
73036
|
name,
|
|
72992
73037
|
status: "warn",
|
|
72993
73038
|
detail: "review_workflow_enabled is not set — treated as OFF until the schema is updated",
|
|
72994
|
-
hint:
|
|
73039
|
+
hint: `Run \`${progName()} server deploy --schema-only\` (v1.13.0+) to seed it.`
|
|
72995
73040
|
};
|
|
72996
73041
|
}
|
|
72997
73042
|
const on = raw.trim().toLowerCase() === "true";
|
|
@@ -72999,7 +73044,7 @@ async function checkReviewWorkflow() {
|
|
|
72999
73044
|
name,
|
|
73000
73045
|
status: "ok",
|
|
73001
73046
|
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 :
|
|
73047
|
+
hint: on ? undefined : `Turn it on with \`${progName()} config set review_workflow_enabled true\`.`
|
|
73003
73048
|
};
|
|
73004
73049
|
}
|
|
73005
73050
|
async function checkTrashAutoPurge() {
|
|
@@ -73038,7 +73083,7 @@ async function checkTrashAutoPurge() {
|
|
|
73038
73083
|
name,
|
|
73039
73084
|
status: "ok",
|
|
73040
73085
|
detail: "off — the trash is only emptied by hand",
|
|
73041
|
-
hint:
|
|
73086
|
+
hint: `Opt in with \`${progName()} config set trash_auto_purge_enabled true\` (period: trash_retention_days).`
|
|
73042
73087
|
};
|
|
73043
73088
|
}
|
|
73044
73089
|
return {
|
|
@@ -73073,7 +73118,7 @@ async function checkEmbedderMismatch() {
|
|
|
73073
73118
|
name: EMBEDDER_CHECK_NAME,
|
|
73074
73119
|
status: "warn",
|
|
73075
73120
|
detail: `configured "${active}", but the model is not downloaded yet; the first search or write will fetch it (~130 MB).`,
|
|
73076
|
-
hint:
|
|
73121
|
+
hint: `Fetch it now with \`${progName()} embedder-warmup\`${progName() === "cerefox" ? " (Cerefox Local: `cerefox-local embedder-warmup`)" : ""}; it resumes if the connection drops.`
|
|
73077
73122
|
};
|
|
73078
73123
|
}
|
|
73079
73124
|
}
|
|
@@ -73087,7 +73132,7 @@ async function checkEmbedderMismatch() {
|
|
|
73087
73132
|
name: EMBEDDER_CHECK_NAME,
|
|
73088
73133
|
status: "warn",
|
|
73089
73134
|
detail: `configured "${active}" but existing chunks were embedded with ${stale.map((r) => `"${r}"`).join(", ")} — semantic search across them is broken.`,
|
|
73090
|
-
hint:
|
|
73135
|
+
hint: `Run \`${progName()} server reindex\` to re-embed everything with the configured embedder.`
|
|
73091
73136
|
};
|
|
73092
73137
|
} catch (err) {
|
|
73093
73138
|
return {
|
|
@@ -73195,7 +73240,7 @@ async function checkContentFormat() {
|
|
|
73195
73240
|
name: CONTENT_FORMAT_CHECK_NAME,
|
|
73196
73241
|
status: "skipped",
|
|
73197
73242
|
detail: `${legacy} of ${total} document(s) use the legacy reconstruction format (format 1).`,
|
|
73198
|
-
hint:
|
|
73243
|
+
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
73244
|
};
|
|
73200
73245
|
}
|
|
73201
73246
|
}
|
|
@@ -73228,7 +73273,7 @@ async function checkMetadataHealth() {
|
|
|
73228
73273
|
name: METADATA_HEALTH_CHECK_NAME,
|
|
73229
73274
|
status: "skipped",
|
|
73230
73275
|
detail: `${probe.rows.length} document(s) hold non-object metadata: ${sample}${probe.rows.length > 3 ? ", …" : ""}.`,
|
|
73231
|
-
hint:
|
|
73276
|
+
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
73277
|
};
|
|
73233
73278
|
}
|
|
73234
73279
|
function hasCerefoxInJsonFile(path) {
|
|
@@ -73257,7 +73302,7 @@ async function checkWebDaemon() {
|
|
|
73257
73302
|
name: "web server",
|
|
73258
73303
|
status: "skipped",
|
|
73259
73304
|
detail: `no daemon running (stale pidfile for process ${status.info.pid}).`,
|
|
73260
|
-
hint:
|
|
73305
|
+
hint: `Clean it up: ${progName()} web stop`
|
|
73261
73306
|
};
|
|
73262
73307
|
}
|
|
73263
73308
|
if (!status.responding) {
|
|
@@ -73307,7 +73352,7 @@ function checkMcpConfigs() {
|
|
|
73307
73352
|
name: "mcp clients",
|
|
73308
73353
|
status: isLocalBackend() ? "skipped" : "warn",
|
|
73309
73354
|
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`." :
|
|
73355
|
+
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
73356
|
};
|
|
73312
73357
|
}
|
|
73313
73358
|
return {
|
|
@@ -73405,7 +73450,7 @@ async function checkEdgeFunctionsCompat() {
|
|
|
73405
73450
|
name: "edge functions",
|
|
73406
73451
|
status: "skipped",
|
|
73407
73452
|
detail: "No CEREFOX_ACCESS_TOKEN set; EF version check skipped.",
|
|
73408
|
-
hint:
|
|
73453
|
+
hint: `Run \`${progName()} token generate\` to enable client↔server version checks.`
|
|
73409
73454
|
};
|
|
73410
73455
|
}
|
|
73411
73456
|
let compat;
|
|
@@ -73557,11 +73602,11 @@ async function action17(options) {
|
|
|
73557
73602
|
const needsEf = stale("edge functions");
|
|
73558
73603
|
let remediation = null;
|
|
73559
73604
|
if (needsSchema && needsEf) {
|
|
73560
|
-
remediation =
|
|
73605
|
+
remediation = `This release needs a server update (schema + RPCs + Edge Functions): ${progName()} server deploy`;
|
|
73561
73606
|
} else if (needsSchema) {
|
|
73562
|
-
remediation =
|
|
73607
|
+
remediation = `This release needs a schema + RPC update: ${progName()} server deploy --schema-only`;
|
|
73563
73608
|
} else if (needsEf) {
|
|
73564
|
-
remediation =
|
|
73609
|
+
remediation = `This release needs an Edge Function update: ${progName()} server deploy --functions-only`;
|
|
73565
73610
|
}
|
|
73566
73611
|
if (remediation) {
|
|
73567
73612
|
println(cErr.yellow("→ " + remediation));
|
|
@@ -73649,7 +73694,7 @@ async function action18(options) {
|
|
|
73649
73694
|
doc: auditDocLabel(row.doc_title, row.document_id, row.operation).slice(0, 40),
|
|
73650
73695
|
author: (row.author ?? "") + (row.author_type ? `(${row.author_type})` : ""),
|
|
73651
73696
|
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)
|
|
73697
|
+
change: (metadataChangeSummary(row.metadata_before, row.metadata_after) ?? storeChangeSummary(row.operation, row.description) ?? "").slice(0, 60)
|
|
73653
73698
|
})));
|
|
73654
73699
|
}
|
|
73655
73700
|
function registerGetAuditLog(program) {
|
|
@@ -74674,7 +74719,7 @@ async function readContent(path, paste) {
|
|
|
74674
74719
|
return { content, titleFromPath: undefined };
|
|
74675
74720
|
}
|
|
74676
74721
|
if (!path) {
|
|
74677
|
-
throw userError("Provide a file path or use --paste.",
|
|
74722
|
+
throw userError("Provide a file path or use --paste.", `Example: ${progName()} document ingest notes.md --title 'My Note'`);
|
|
74678
74723
|
}
|
|
74679
74724
|
let content;
|
|
74680
74725
|
try {
|
|
@@ -74716,7 +74761,7 @@ async function action20(path, options) {
|
|
|
74716
74761
|
}
|
|
74717
74762
|
const settings = loadSettings();
|
|
74718
74763
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
74719
|
-
throw userError(
|
|
74764
|
+
throw userError(`Supabase credentials not configured — run \`${progName()} init\` first.`);
|
|
74720
74765
|
}
|
|
74721
74766
|
if (!settings.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
74722
74767
|
throw userError("OPENAI_API_KEY not set — required for embeddings during ingest.");
|
|
@@ -74828,7 +74873,7 @@ async function runTool(toolName, args) {
|
|
|
74828
74873
|
}
|
|
74829
74874
|
}
|
|
74830
74875
|
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>",
|
|
74876
|
+
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
74877
|
await runTool("cerefox_insert", {
|
|
74833
74878
|
document_id: documentId,
|
|
74834
74879
|
text: resolveText(options.text, "--text"),
|
|
@@ -74909,7 +74954,7 @@ async function action21(dir, options) {
|
|
|
74909
74954
|
const metadata = parseJsonObjectArg(options.metadata, "--metadata");
|
|
74910
74955
|
const settings = loadSettings();
|
|
74911
74956
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
74912
|
-
throw userError(
|
|
74957
|
+
throw userError(`Supabase credentials not configured — run \`${progName()} init\` first.`);
|
|
74913
74958
|
}
|
|
74914
74959
|
if (!settings.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
74915
74960
|
throw userError("OPENAI_API_KEY not set — required for embeddings during ingest.");
|
|
@@ -75039,7 +75084,7 @@ function answersFromEnvFile(path) {
|
|
|
75039
75084
|
const required = ["CEREFOX_SUPABASE_URL", "CEREFOX_SUPABASE_KEY", "OPENAI_API_KEY"];
|
|
75040
75085
|
for (const key of required) {
|
|
75041
75086
|
if (!parsed[key] || parsed[key].trim() === "") {
|
|
75042
|
-
throw userError(`Existing .env at ${path} is missing required key "${key}".`, `Fix it manually or run
|
|
75087
|
+
throw userError(`Existing .env at ${path} is missing required key "${key}".`, `Fix it manually or run \`${progName()} init --force\` to start fresh.`);
|
|
75043
75088
|
}
|
|
75044
75089
|
}
|
|
75045
75090
|
return {
|
|
@@ -75084,7 +75129,8 @@ async function promptForAnswers() {
|
|
|
75084
75129
|
});
|
|
75085
75130
|
println("");
|
|
75086
75131
|
println(c.cyan("▶ Step 4/5 — Direct Postgres connection (optional for npm-installed users)"));
|
|
75087
|
-
println(c.dim(
|
|
75132
|
+
println(c.dim(` Only needed for \`${progName()} server deploy\` (schema deploy + migrations).
|
|
75133
|
+
` + ` You can skip this and set CEREFOX_DATABASE_URL later — press Enter.
|
|
75088
75134
|
` + " Format: postgresql://postgres.<project-ref>:<pw>@…:5432/postgres?sslmode=require"));
|
|
75089
75135
|
const databaseUrl = await ask({
|
|
75090
75136
|
type: "text",
|
|
@@ -75229,7 +75275,7 @@ async function maybeOfferServerDeploy() {
|
|
|
75229
75275
|
if (yes)
|
|
75230
75276
|
launchDeployServer();
|
|
75231
75277
|
else
|
|
75232
|
-
println(c.dim(
|
|
75278
|
+
println(c.dim(` Skipped. Run \`${progName()} server deploy\` later (or \`${progName()} doctor\` to recheck).`));
|
|
75233
75279
|
println("");
|
|
75234
75280
|
return;
|
|
75235
75281
|
}
|
|
@@ -75240,7 +75286,7 @@ async function maybeOfferServerDeploy() {
|
|
|
75240
75286
|
if (yes)
|
|
75241
75287
|
launchDeployServer();
|
|
75242
75288
|
else
|
|
75243
|
-
println(c.dim(
|
|
75289
|
+
println(c.dim(` Skipped. Run \`${progName()} server deploy\` when ready.`));
|
|
75244
75290
|
println("");
|
|
75245
75291
|
return;
|
|
75246
75292
|
}
|
|
@@ -75259,7 +75305,7 @@ async function postWriteLifecycle(envPath, options) {
|
|
|
75259
75305
|
await Promise.resolve().then(() => init_sync_self_docs());
|
|
75260
75306
|
await runSyncSelfDocs({});
|
|
75261
75307
|
} catch (err) {
|
|
75262
|
-
warn(`Self-doc ingest failed: ${err instanceof Error ? err.message : String(err)}. Run
|
|
75308
|
+
warn(`Self-doc ingest failed: ${err instanceof Error ? err.message : String(err)}. Run \`${progName()} guides ingest\` manually after init.`);
|
|
75263
75309
|
}
|
|
75264
75310
|
println("");
|
|
75265
75311
|
}
|
|
@@ -75283,9 +75329,9 @@ async function postWriteLifecycle(envPath, options) {
|
|
|
75283
75329
|
}
|
|
75284
75330
|
println("");
|
|
75285
75331
|
println(c.green("Done. Try:"));
|
|
75286
|
-
println(c.dim(
|
|
75287
|
-
println(c.dim(
|
|
75288
|
-
println(c.dim(
|
|
75332
|
+
println(c.dim(` ${progName()} doctor # verify everything`));
|
|
75333
|
+
println(c.dim(` ${progName()} search "…" # search the KB`));
|
|
75334
|
+
println(c.dim(` ${progName()} document ingest <file> # add a doc`));
|
|
75289
75335
|
println("");
|
|
75290
75336
|
println(c.dim(` Config in effect: ${envPath}`));
|
|
75291
75337
|
}
|
|
@@ -75386,7 +75432,7 @@ async function action23(options) {
|
|
|
75386
75432
|
println("");
|
|
75387
75433
|
println(c.green(`✓ Using existing config at ${cwdEnv}`));
|
|
75388
75434
|
println(c.dim(` TS reads it via the legacy dev-mode fallback (~/.cerefox/.env not present).`));
|
|
75389
|
-
println(c.dim(` Run
|
|
75435
|
+
println(c.dim(` Run \`${progName()} init\` again later to migrate to the new home.`));
|
|
75390
75436
|
println("");
|
|
75391
75437
|
await postWriteLifecycle(cwdEnv, options);
|
|
75392
75438
|
return;
|
|
@@ -75427,7 +75473,7 @@ async function action24(options) {
|
|
|
75427
75473
|
throw systemError(`Project lookup failed: ${projectError.message}`);
|
|
75428
75474
|
}
|
|
75429
75475
|
if (!project) {
|
|
75430
|
-
throw userError(`Project "${options.project}" not found.`,
|
|
75476
|
+
throw userError(`Project "${options.project}" not found.`, `Run \`${progName()} project list\` to see available names.`);
|
|
75431
75477
|
}
|
|
75432
75478
|
projectId = project.id;
|
|
75433
75479
|
}
|
|
@@ -75743,7 +75789,7 @@ function warnLargeBulkWrite(opts) {
|
|
|
75743
75789
|
async function action29(options) {
|
|
75744
75790
|
const settings = loadSettings();
|
|
75745
75791
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
75746
|
-
throw userError(
|
|
75792
|
+
throw userError(`Supabase credentials not configured — run \`${progName()} init\` first.`);
|
|
75747
75793
|
}
|
|
75748
75794
|
if (!settings.openaiApiKey && resolveEmbedderKind() !== "local") {
|
|
75749
75795
|
throw userError("OPENAI_API_KEY not set — required for embeddings.");
|
|
@@ -76014,7 +76060,7 @@ async function action31(target, options) {
|
|
|
76014
76060
|
}
|
|
76015
76061
|
const trashedInFile = payload.documents.filter((d) => d.deleted_at != null).length;
|
|
76016
76062
|
if (trashedInFile > 0) {
|
|
76017
|
-
println(c.dim(` trashed documents in file: ${trashedInFile} — restored as trash ` +
|
|
76063
|
+
println(c.dim(` trashed documents in file: ${trashedInFile} — restored as trash ` + `(still deleted; recover with \`${progName()} document restore\`)`));
|
|
76018
76064
|
}
|
|
76019
76065
|
println("");
|
|
76020
76066
|
const client = getClient();
|
|
@@ -76133,7 +76179,7 @@ async function action31(target, options) {
|
|
|
76133
76179
|
}
|
|
76134
76180
|
}
|
|
76135
76181
|
function registerRestore(program) {
|
|
76136
|
-
program.command("restore").description("Restore a JSON-snapshot backup into the knowledge base.").argument("<snapshot>",
|
|
76182
|
+
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
76183
|
}
|
|
76138
76184
|
|
|
76139
76185
|
// src/cli/commands/search.ts
|
|
@@ -76148,13 +76194,13 @@ async function embedQuery(query) {
|
|
|
76148
76194
|
const settings = loadSettings();
|
|
76149
76195
|
const apiKey = settings.openaiApiKey;
|
|
76150
76196
|
if (!apiKey && resolveEmbedderKind() !== "local") {
|
|
76151
|
-
throw userError("OPENAI_API_KEY (or CEREFOX_OPENAI_API_KEY) is required for search.",
|
|
76197
|
+
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
76198
|
}
|
|
76153
76199
|
try {
|
|
76154
76200
|
return await getEmbedding(query, apiKey);
|
|
76155
76201
|
} catch (err) {
|
|
76156
76202
|
const msg = err instanceof Error ? err.message : String(err);
|
|
76157
|
-
throw systemError(`Failed to embed query: ${msg}`,
|
|
76203
|
+
throw systemError(`Failed to embed query: ${msg}`, `Run \`${progName()} doctor\` to verify the OpenAI API path.`);
|
|
76158
76204
|
}
|
|
76159
76205
|
}
|
|
76160
76206
|
|
|
@@ -76326,7 +76372,7 @@ async function action32(query, options) {
|
|
|
76326
76372
|
}
|
|
76327
76373
|
}
|
|
76328
76374
|
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",
|
|
76375
|
+
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
76376
|
}
|
|
76331
76377
|
|
|
76332
76378
|
// src/cli/commands/self-update.ts
|
|
@@ -76391,7 +76437,7 @@ async function action33(options) {
|
|
|
76391
76437
|
if (options.check) {
|
|
76392
76438
|
if (newerRelease(target)) {
|
|
76393
76439
|
println(c.yellow(`Update available: ${PKG_VERSION} → ${target}`));
|
|
76394
|
-
println(c.dim(
|
|
76440
|
+
println(c.dim(`Run \`${progName()} self-update\` to upgrade.`));
|
|
76395
76441
|
}
|
|
76396
76442
|
return;
|
|
76397
76443
|
}
|
|
@@ -76422,12 +76468,12 @@ async function action33(options) {
|
|
|
76422
76468
|
}
|
|
76423
76469
|
println("");
|
|
76424
76470
|
println("Next steps:");
|
|
76425
|
-
println(" 1. " + c.bold(
|
|
76426
|
-
println(" 2. " + c.bold(
|
|
76471
|
+
println(" 1. " + c.bold(`${progName()} server deploy`) + " apply this release's schema/RPC/EF updates");
|
|
76472
|
+
println(" 2. " + c.bold(`${progName()} guides ingest`) + " re-sync the bundled guides into your KB");
|
|
76427
76473
|
println(c.dim(" (order matters: the new client may require the new schema — run the deploy first)"));
|
|
76428
76474
|
}
|
|
76429
76475
|
function registerSelfUpdate(program) {
|
|
76430
|
-
const desc =
|
|
76476
|
+
const desc = `Upgrade Cerefox in place. Alias: \`${progName()} upgrade\`.`;
|
|
76431
76477
|
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
76478
|
declaration(program.command("self-update"));
|
|
76433
76479
|
declaration(program.command("upgrade"));
|
|
@@ -76468,7 +76514,7 @@ async function action34(options) {
|
|
|
76468
76514
|
}
|
|
76469
76515
|
}
|
|
76470
76516
|
function registerStatus(program) {
|
|
76471
|
-
program.command("status").description(
|
|
76517
|
+
program.command("status").description(`Quick sanity check (fast subset of \`${progName()} doctor\`).`).option("--json", "Emit machine-readable JSON.").action(action34);
|
|
76472
76518
|
}
|
|
76473
76519
|
|
|
76474
76520
|
// src/cli/commands/api-key.ts
|
|
@@ -76581,7 +76627,7 @@ function generateAction(opts) {
|
|
|
76581
76627
|
const envPath = resolveEnvFile();
|
|
76582
76628
|
const existing = readEnvVar(envPath, ENV_NAME);
|
|
76583
76629
|
if (existing) {
|
|
76584
|
-
throw userError(`${ENV_NAME} is already set in ${envPath} (${mask(existing)}).`,
|
|
76630
|
+
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
76631
|
}
|
|
76586
76632
|
println(c.bold("Minting a local API key"));
|
|
76587
76633
|
writeKey(mint(), opts, "write");
|
|
@@ -76591,13 +76637,13 @@ function rotateAction(opts) {
|
|
|
76591
76637
|
const envPath = resolveEnvFile();
|
|
76592
76638
|
const existing = readEnvVar(envPath, ENV_NAME);
|
|
76593
76639
|
if (!existing) {
|
|
76594
|
-
throw userError(`No ${ENV_NAME} in ${envPath} — nothing to rotate.`,
|
|
76640
|
+
throw userError(`No ${ENV_NAME} in ${envPath} — nothing to rotate.`, `Run \`${progName()} api-key generate\` first.`);
|
|
76595
76641
|
}
|
|
76596
76642
|
println(c.bold("Rotating the local API key"));
|
|
76597
76643
|
println(c.dim(` replacing ${mask(existing)}`));
|
|
76598
76644
|
writeKey(mint(), opts, "replace");
|
|
76599
76645
|
println(c.yellow(` The previous key stops working as soon as the server restarts.
|
|
76600
|
-
` +
|
|
76646
|
+
` + ` Update every remote client, then: ${progName()} web restart`));
|
|
76601
76647
|
}
|
|
76602
76648
|
function showAction2() {
|
|
76603
76649
|
const envPath = resolveEnvFile();
|
|
@@ -76607,7 +76653,7 @@ function showAction2() {
|
|
|
76607
76653
|
println(c.dim(` none set in ${envPath}`));
|
|
76608
76654
|
println(c.dim(` The server is not gated: callers from any interface it is bound to can
|
|
76609
76655
|
` + ` reach it without a credential. That is fine while it binds 127.0.0.1.
|
|
76610
|
-
` +
|
|
76656
|
+
` + ` Mint one with: ${progName()} api-key generate`));
|
|
76611
76657
|
containerHint();
|
|
76612
76658
|
return;
|
|
76613
76659
|
}
|
|
@@ -76688,7 +76734,7 @@ function printTokenOnce(token) {
|
|
|
76688
76734
|
println(c.dim(" • Custom GPT → Configure → Actions → Authentication → API Key (Bearer)"));
|
|
76689
76735
|
println(c.dim(" • Remote HTTP MCP → the Authorization: Bearer header"));
|
|
76690
76736
|
println(c.dim(" If the GPT Actions schema changed this release, re-paste it too"));
|
|
76691
|
-
println(c.dim(
|
|
76737
|
+
println(c.dim(` (see docs/guides/connect-agents.md). Lose the token → \`${progName()} token rotate\`.`));
|
|
76692
76738
|
}
|
|
76693
76739
|
function generateAction2(opts) {
|
|
76694
76740
|
const projectRef = opts.projectRef ?? parseProjectRef2(loadSettings().supabaseUrl);
|
|
@@ -76705,7 +76751,7 @@ function rotateAction2(opts) {
|
|
|
76705
76751
|
const current = readEnvVar(envPath, LOCAL_NAME);
|
|
76706
76752
|
if (opts.finalize) {
|
|
76707
76753
|
if (!current) {
|
|
76708
|
-
throw userError(`No ${LOCAL_NAME} in ${envPath} to finalize to.`,
|
|
76754
|
+
throw userError(`No ${LOCAL_NAME} in ${envPath} to finalize to.`, `Run \`${progName()} token generate\` or \`${progName()} token rotate\` first.`);
|
|
76709
76755
|
}
|
|
76710
76756
|
println(c.bold("Finalizing rotation (dropping the previous token)…"));
|
|
76711
76757
|
setSecret(current, projectRef, opts.dryRun);
|
|
@@ -76722,14 +76768,15 @@ function rotateAction2(opts) {
|
|
|
76722
76768
|
printTokenOnce(token);
|
|
76723
76769
|
println("");
|
|
76724
76770
|
println(c.yellow(` Both the new and previous tokens are accepted right now. Update every
|
|
76725
|
-
` +
|
|
76771
|
+
` + ` client to the new token, then run \`${progName()} token rotate --finalize\`
|
|
76772
|
+
` + " to stop accepting the old one."));
|
|
76726
76773
|
}
|
|
76727
76774
|
}
|
|
76728
76775
|
function listAction2() {
|
|
76729
76776
|
const envPath = resolveEnvFile();
|
|
76730
76777
|
const local = readEnvVar(envPath, LOCAL_NAME);
|
|
76731
76778
|
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
|
|
76779
|
+
println(local ? ` local (${LOCAL_NAME} in ${envPath}): ${c.green(mask2(local))}` : c.dim(` no ${LOCAL_NAME} in ${envPath} — run \`${progName()} token generate\``));
|
|
76733
76780
|
println(c.dim(` The server-side accepted set (${SECRET_NAME}) is write-only; list names/digests
|
|
76734
76781
|
` + " with: npx supabase secrets list"));
|
|
76735
76782
|
}
|
|
@@ -81888,6 +81935,7 @@ function registerMetaRoutes(app, ctx) {
|
|
|
81888
81935
|
...VERSION_INFO,
|
|
81889
81936
|
env_label: label.length > 0 ? label : null,
|
|
81890
81937
|
latest,
|
|
81938
|
+
update_available: newerRelease(latest) !== null,
|
|
81891
81939
|
update_command: newerRelease(latest) ? upgradeCommand() : null
|
|
81892
81940
|
});
|
|
81893
81941
|
});
|
|
@@ -81964,6 +82012,14 @@ var STRIP_RESPONSE_HEADERS = [
|
|
|
81964
82012
|
"proxy-authenticate",
|
|
81965
82013
|
"proxy-authorization"
|
|
81966
82014
|
];
|
|
82015
|
+
function upstreamCredentials(headers, reason, internalJwt) {
|
|
82016
|
+
const jwt = internalJwt.trim();
|
|
82017
|
+
if (reason !== "valid_key" || !jwt)
|
|
82018
|
+
return false;
|
|
82019
|
+
headers.set("authorization", `Bearer ${jwt}`);
|
|
82020
|
+
headers.set("apikey", jwt);
|
|
82021
|
+
return true;
|
|
82022
|
+
}
|
|
81967
82023
|
function registerPostgrestProxy(app) {
|
|
81968
82024
|
const upstream = (process.env.CEREFOX_POSTGREST_UPSTREAM ?? "").trim().replace(/\/+$/, "");
|
|
81969
82025
|
if (!upstream)
|
|
@@ -81975,6 +82031,7 @@ function registerPostgrestProxy(app) {
|
|
|
81975
82031
|
const headers = new Headers(c.req.raw.headers);
|
|
81976
82032
|
headers.delete("host");
|
|
81977
82033
|
headers.delete("accept-encoding");
|
|
82034
|
+
upstreamCredentials(headers, c.get("cerefoxAuthReason"), process.env.CEREFOX_SUPABASE_KEY ?? "");
|
|
81978
82035
|
const method = c.req.method;
|
|
81979
82036
|
const init = { method, headers };
|
|
81980
82037
|
if (method !== "GET" && method !== "HEAD") {
|
|
@@ -82342,7 +82399,7 @@ async function assertServerCompatible() {
|
|
|
82342
82399
|
` + parts.join(`
|
|
82343
82400
|
`) + `
|
|
82344
82401
|
|
|
82345
|
-
Redeploy your server:
|
|
82402
|
+
Redeploy your server: ${progName()} server deploy
|
|
82346
82403
|
` + `(or downgrade the client to match the deployed server).`);
|
|
82347
82404
|
}
|
|
82348
82405
|
async function buildWebServer(options = {}) {
|
|
@@ -82357,7 +82414,7 @@ async function buildWebServer(options = {}) {
|
|
|
82357
82414
|
⚠ Binding ${host} with NO API key configured.
|
|
82358
82415
|
` + ` Every read, write, delete and purge on this server is reachable by
|
|
82359
82416
|
` + ` anything that can connect to port ${port}, with no credential.
|
|
82360
|
-
` + ` Mint one:
|
|
82417
|
+
` + ` Mint one: ${progName()} api-key generate
|
|
82361
82418
|
`);
|
|
82362
82419
|
}
|
|
82363
82420
|
const app = buildApp();
|
|
@@ -82439,7 +82496,7 @@ function registerWeb(program) {
|
|
|
82439
82496
|
break;
|
|
82440
82497
|
case "port-conflict":
|
|
82441
82498
|
eprintln(`A Cerefox web daemon is already running on :${outcome.info.port} (pid ${outcome.info.pid}).
|
|
82442
|
-
` + `Stop it first (
|
|
82499
|
+
` + `Stop it first (\`${progName()} web stop\`) or start on its port.`);
|
|
82443
82500
|
process.exit(1);
|
|
82444
82501
|
break;
|
|
82445
82502
|
case "started":
|
|
@@ -82447,7 +82504,7 @@ function registerWeb(program) {
|
|
|
82447
82504
|
info(`Cerefox web started (pid ${outcome.pid}) on http://${rawOpts.host}:${port}/`);
|
|
82448
82505
|
println(` Web UI: http://${rawOpts.host}:${port}/app/`);
|
|
82449
82506
|
println(c.dim(` Logs: ${daemonPaths.logFile}`));
|
|
82450
|
-
println(c.dim(` Stop:
|
|
82507
|
+
println(c.dim(` Stop: ${progName()} web stop`));
|
|
82451
82508
|
} else {
|
|
82452
82509
|
const refusal = readStartupRefusal();
|
|
82453
82510
|
if (refusal) {
|
|
@@ -82489,7 +82546,7 @@ Full log: ${daemonPaths.logFile}`);
|
|
|
82489
82546
|
break;
|
|
82490
82547
|
case "stale":
|
|
82491
82548
|
println(c.yellow(`Cerefox web: stale pidfile — process ${status.info.pid} is not running.`));
|
|
82492
|
-
println(c.dim(` Clean up:
|
|
82549
|
+
println(c.dim(` Clean up: ${progName()} web stop (removes ${daemonPaths.pidFile})`));
|
|
82493
82550
|
break;
|
|
82494
82551
|
case "running":
|
|
82495
82552
|
if (status.responding) {
|
|
@@ -82541,16 +82598,16 @@ var RENAMED_VERBS = [
|
|
|
82541
82598
|
function registerRenameHusks(program) {
|
|
82542
82599
|
for (const [oldName, newForm] of RENAMED_VERBS) {
|
|
82543
82600
|
program.command(oldName, { hidden: true }).allowUnknownOption(true).allowExcessArguments(true).argument("[args...]", "(renamed)").action(() => {
|
|
82544
|
-
eprintln(c.yellow(`✗
|
|
82545
|
-
eprintln(` Use
|
|
82601
|
+
eprintln(c.yellow(`✗ \`${progName()} ${oldName}\` was renamed.`));
|
|
82602
|
+
eprintln(` Use \`${progName()} ${newForm}\` instead (run \`${progName()} ${newForm.split(" ")[0]} --help\`).`);
|
|
82546
82603
|
process.exit(1);
|
|
82547
82604
|
});
|
|
82548
82605
|
}
|
|
82549
82606
|
}
|
|
82550
82607
|
function buildProgram() {
|
|
82551
|
-
const
|
|
82552
|
-
const program = new Command(
|
|
82553
|
-
Resource groups (run \`${
|
|
82608
|
+
const progName2 = process.env.CEREFOX_PROG_NAME || "cerefox";
|
|
82609
|
+
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", `
|
|
82610
|
+
Resource groups (run \`${progName2} <group> --help\`):
|
|
82554
82611
|
` + ` document get · list · edit · delete · restore · ingest · ingest-dir · version {list·archive·unarchive}
|
|
82555
82612
|
` + ` project list · create · edit · delete
|
|
82556
82613
|
` + ` metadata keys · search
|
|
@@ -82573,8 +82630,8 @@ Exit codes:
|
|
|
82573
82630
|
` + ` 1 user error 3 not found (document / version / project)
|
|
82574
82631
|
` + `
|
|
82575
82632
|
Learn more:
|
|
82576
|
-
` + ` ${
|
|
82577
|
-
` + ` ${
|
|
82633
|
+
` + ` ${progName2} guides list # bundled docs (offline)
|
|
82634
|
+
` + ` ${progName2} doctor # diagnose your install
|
|
82578
82635
|
` + ` https://github.com/fstamatelopoulos/cerefox
|
|
82579
82636
|
`);
|
|
82580
82637
|
registerSearch(program);
|
|
@@ -82625,8 +82682,8 @@ Learn more:
|
|
|
82625
82682
|
moveInto(config, registerConfigGet, "get");
|
|
82626
82683
|
moveInto(config, registerConfigSet, "set");
|
|
82627
82684
|
const backup = program.command("backup").description("Backup + restore the knowledge base: create, restore.").action(() => {
|
|
82628
|
-
eprintln(c.yellow(
|
|
82629
|
-
eprintln(
|
|
82685
|
+
eprintln(c.yellow(`\`${progName()} backup\` needs a subcommand.`));
|
|
82686
|
+
eprintln(` Use \`${progName()} backup create\` or \`${progName()} backup restore\`.`);
|
|
82630
82687
|
process.exit(1);
|
|
82631
82688
|
});
|
|
82632
82689
|
moveInto(backup, registerBackup, "create");
|
|
@@ -82663,22 +82720,22 @@ async function bareEntryPoint() {
|
|
|
82663
82720
|
if (!configExists) {
|
|
82664
82721
|
println(c.yellow("⚠ No config detected."));
|
|
82665
82722
|
println("Next step:");
|
|
82666
|
-
println(" " + c.bold(
|
|
82723
|
+
println(" " + c.bold(`${progName()} init`) + " # interactive first-run setup (~2 min)");
|
|
82667
82724
|
println("");
|
|
82668
82725
|
println(c.dim("Once configured, try:"));
|
|
82669
|
-
println(c.dim(
|
|
82670
|
-
println(c.dim(
|
|
82671
|
-
println(c.dim(
|
|
82726
|
+
println(c.dim(` ${progName()} doctor # verify your install`));
|
|
82727
|
+
println(c.dim(` ${progName()} search "…" # search the KB`));
|
|
82728
|
+
println(c.dim(` ${progName()} document ingest <file> # add a doc`));
|
|
82672
82729
|
} else {
|
|
82673
82730
|
println(c.green("✓ Config detected. You're good to go."));
|
|
82674
82731
|
println("");
|
|
82675
82732
|
println("Common commands:");
|
|
82676
|
-
println(c.dim(
|
|
82677
|
-
println(c.dim(
|
|
82678
|
-
println(c.dim(
|
|
82679
|
-
println(c.dim(
|
|
82733
|
+
println(c.dim(` ${progName()} doctor # diagnose your install`));
|
|
82734
|
+
println(c.dim(` ${progName()} search "…" # search the KB`));
|
|
82735
|
+
println(c.dim(` ${progName()} document ingest <file> # add a doc`));
|
|
82736
|
+
println(c.dim(` ${progName()} configure-agent # wire up an MCP client`));
|
|
82680
82737
|
println("");
|
|
82681
|
-
println(c.dim(
|
|
82738
|
+
println(c.dim(`Run \`${progName()} --help\` for the full command list.`));
|
|
82682
82739
|
}
|
|
82683
82740
|
}
|
|
82684
82741
|
async function main() {
|