@cerefox/memory 0.8.0 → 0.8.2
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 +410 -147
- package/docs/guides/connect-agents.md +20 -0
- package/docs/guides/quickstart.md +6 -2
- package/package.json +1 -1
package/dist/bin/cerefox.js
CHANGED
|
@@ -182,6 +182,10 @@ function printTable(rows, emptyMessage = "(no rows)") {
|
|
|
182
182
|
println(line(headers.map((h) => String(row[h] ?? ""))));
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
|
+
function localTimestamp(d = new Date) {
|
|
186
|
+
const p = (n, w = 2) => String(n).padStart(w, "0");
|
|
187
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ` + `${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}.${p(d.getMilliseconds(), 3)}`;
|
|
188
|
+
}
|
|
185
189
|
function eprintln(line = "") {
|
|
186
190
|
process.stderr.write(line + `
|
|
187
191
|
`);
|
|
@@ -5315,6 +5319,7 @@ __export(exports_cli_core, {
|
|
|
5315
5319
|
parseFloat01: () => parseFloat01,
|
|
5316
5320
|
ok: () => ok,
|
|
5317
5321
|
notFound: () => notFound,
|
|
5322
|
+
localTimestamp: () => localTimestamp,
|
|
5318
5323
|
info: () => info,
|
|
5319
5324
|
errorln: () => errorln,
|
|
5320
5325
|
eprintln: () => eprintln,
|
|
@@ -7179,7 +7184,7 @@ var exports_meta = {};
|
|
|
7179
7184
|
__export(exports_meta, {
|
|
7180
7185
|
PKG_VERSION: () => PKG_VERSION
|
|
7181
7186
|
});
|
|
7182
|
-
var PKG_VERSION = "0.8.
|
|
7187
|
+
var PKG_VERSION = "0.8.2";
|
|
7183
7188
|
var init_meta = () => {};
|
|
7184
7189
|
|
|
7185
7190
|
// ../../node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.js
|
|
@@ -24624,12 +24629,12 @@ var init_src = __esm(() => {
|
|
|
24624
24629
|
|
|
24625
24630
|
// src/cli/util/bundled-docs.ts
|
|
24626
24631
|
import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync5, statSync } from "node:fs";
|
|
24627
|
-
import { dirname as dirname3, join as
|
|
24632
|
+
import { dirname as dirname3, join as join6, resolve as resolve2 } from "node:path";
|
|
24628
24633
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
24629
24634
|
function findPackageRoot() {
|
|
24630
24635
|
let dir = dirname3(fileURLToPath2(import.meta.url));
|
|
24631
24636
|
for (let i = 0;i < 10; i++) {
|
|
24632
|
-
const pkgJson =
|
|
24637
|
+
const pkgJson = join6(dir, "package.json");
|
|
24633
24638
|
if (existsSync7(pkgJson)) {
|
|
24634
24639
|
try {
|
|
24635
24640
|
const parsed = JSON.parse(readFileSync5(pkgJson, "utf8"));
|
|
@@ -24645,14 +24650,14 @@ function findPackageRoot() {
|
|
|
24645
24650
|
return resolve2(dirname3(fileURLToPath2(import.meta.url)), "..", "..", "..");
|
|
24646
24651
|
}
|
|
24647
24652
|
function bundledDocsDir() {
|
|
24648
|
-
const inPackage =
|
|
24653
|
+
const inPackage = join6(PACKAGE_ROOT, "docs");
|
|
24649
24654
|
if (existsSync7(inPackage))
|
|
24650
24655
|
return inPackage;
|
|
24651
24656
|
return resolve2(PACKAGE_ROOT, "..", "..", "docs");
|
|
24652
24657
|
}
|
|
24653
24658
|
function agentGuidePath() {
|
|
24654
24659
|
const candidates = [
|
|
24655
|
-
|
|
24660
|
+
join6(PACKAGE_ROOT, "AGENT_GUIDE.md"),
|
|
24656
24661
|
resolve2(PACKAGE_ROOT, "..", "..", "AGENT_GUIDE.md")
|
|
24657
24662
|
];
|
|
24658
24663
|
for (const c2 of candidates)
|
|
@@ -24662,7 +24667,7 @@ function agentGuidePath() {
|
|
|
24662
24667
|
}
|
|
24663
24668
|
function agentQuickReferencePath() {
|
|
24664
24669
|
const candidates = [
|
|
24665
|
-
|
|
24670
|
+
join6(PACKAGE_ROOT, "AGENT_QUICK_REFERENCE.md"),
|
|
24666
24671
|
resolve2(PACKAGE_ROOT, "..", "..", "AGENT_QUICK_REFERENCE.md")
|
|
24667
24672
|
];
|
|
24668
24673
|
for (const c2 of candidates)
|
|
@@ -24673,12 +24678,12 @@ function agentQuickReferencePath() {
|
|
|
24673
24678
|
function listBundledDocs() {
|
|
24674
24679
|
const entries = [];
|
|
24675
24680
|
const docsDir = bundledDocsDir();
|
|
24676
|
-
const guidesDir =
|
|
24681
|
+
const guidesDir = join6(docsDir, "guides");
|
|
24677
24682
|
if (existsSync7(guidesDir) && statSync(guidesDir).isDirectory()) {
|
|
24678
24683
|
for (const name of readdirSync3(guidesDir)) {
|
|
24679
24684
|
if (!name.endsWith(".md"))
|
|
24680
24685
|
continue;
|
|
24681
|
-
const full =
|
|
24686
|
+
const full = join6(guidesDir, name);
|
|
24682
24687
|
entries.push({
|
|
24683
24688
|
topic: name.replace(/\.md$/, ""),
|
|
24684
24689
|
path: full,
|
|
@@ -26814,11 +26819,11 @@ async function runSyncSelfDocs(options = {}) {
|
|
|
26814
26819
|
printTable(outcomes.filter((o) => o.status === "error").map((o) => ({ topic: o.topic, error: o.detail.slice(0, 100) })));
|
|
26815
26820
|
}
|
|
26816
26821
|
}
|
|
26817
|
-
async function
|
|
26822
|
+
async function action15(options) {
|
|
26818
26823
|
await runSyncSelfDocs(options);
|
|
26819
26824
|
}
|
|
26820
26825
|
function registerSyncSelfDocs(program2) {
|
|
26821
|
-
program2.command("sync-self-docs").description("Ingest bundled Cerefox docs under the _cerefox-self-docs project.").option("--dry-run", "List what would be ingested without writing.").option("--project <name>", "Override the target project name.", "_cerefox-self-docs").action(
|
|
26826
|
+
program2.command("sync-self-docs").description("Ingest bundled Cerefox docs under the _cerefox-self-docs project.").option("--dry-run", "List what would be ingested without writing.").option("--project <name>", "Override the target project name.", "_cerefox-self-docs").action(action15);
|
|
26822
26827
|
}
|
|
26823
26828
|
var init_sync_self_docs = __esm(() => {
|
|
26824
26829
|
init_cli_core();
|
|
@@ -41528,6 +41533,49 @@ function registerDeleteDoc(program2) {
|
|
|
41528
41533
|
program2.command("delete-doc").description("Soft-delete a document (recoverable via the web UI trash).").argument("<document-id>", "UUID of the document to delete.").option("--reason <text>", "Optional reason recorded in the audit log.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").option("--yes", "Skip the confirmation prompt.").action(action6);
|
|
41529
41534
|
}
|
|
41530
41535
|
|
|
41536
|
+
// src/cli/commands/delete-project.ts
|
|
41537
|
+
init_cli_core();
|
|
41538
|
+
init_client();
|
|
41539
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
41540
|
+
async function action7(target, options) {
|
|
41541
|
+
const client = getClient();
|
|
41542
|
+
const isUuid = UUID_RE.test(target);
|
|
41543
|
+
const lookup = isUuid ? client.raw.from("cerefox_projects").select("id, name, description").eq("id", target).maybeSingle() : client.raw.from("cerefox_projects").select("id, name, description").eq("name", target).maybeSingle();
|
|
41544
|
+
const { data: project, error } = await lookup;
|
|
41545
|
+
if (error) {
|
|
41546
|
+
throw systemError(`Project lookup failed: ${error.message}`);
|
|
41547
|
+
}
|
|
41548
|
+
if (!project) {
|
|
41549
|
+
throw notFound(`Project "${target}" not found.`);
|
|
41550
|
+
}
|
|
41551
|
+
const { count, error: countErr } = await client.raw.from("cerefox_document_projects").select("*", { count: "exact", head: true }).eq("project_id", project.id);
|
|
41552
|
+
if (countErr) {
|
|
41553
|
+
throw systemError(`Could not count documents in project: ${countErr.message}`);
|
|
41554
|
+
}
|
|
41555
|
+
const docCount = count ?? 0;
|
|
41556
|
+
if (docCount > 0 && !options.force) {
|
|
41557
|
+
throw userError(`Project "${project.name}" still has ${docCount} document link(s).`, "Pass --force to delete the project anyway (documents remain; only the project row is removed).");
|
|
41558
|
+
}
|
|
41559
|
+
println(c.yellow("About to delete project:"));
|
|
41560
|
+
println(` ${project.name}`);
|
|
41561
|
+
println(c.dim(` ${project.id} · ${docCount} doc link(s)`));
|
|
41562
|
+
if (!options.yes) {
|
|
41563
|
+
const ok2 = await confirm("Continue?", true);
|
|
41564
|
+
if (!ok2) {
|
|
41565
|
+
println(c.dim("Aborted."));
|
|
41566
|
+
return;
|
|
41567
|
+
}
|
|
41568
|
+
}
|
|
41569
|
+
const { error: delErr } = await client.raw.from("cerefox_projects").delete().eq("id", project.id);
|
|
41570
|
+
if (delErr) {
|
|
41571
|
+
throw systemError(`Delete failed: ${delErr.message}`);
|
|
41572
|
+
}
|
|
41573
|
+
println(c.green(`✓ Deleted project "${project.name}" (id: ${project.id}).`));
|
|
41574
|
+
}
|
|
41575
|
+
function registerDeleteProject(program2) {
|
|
41576
|
+
program2.command("delete-project").description("Delete an empty project (use --force to remove a non-empty one).").argument("<name-or-id>", "Project name (exact match) or UUID.").option("--yes", "Skip the confirmation prompt.").option("--force", "Allow deletion when documents are still linked to the project.").action(action7);
|
|
41577
|
+
}
|
|
41578
|
+
|
|
41531
41579
|
// src/cli/commands/deploy-server.ts
|
|
41532
41580
|
init_cli_core();
|
|
41533
41581
|
init_config();
|
|
@@ -41584,8 +41632,9 @@ function resolveServerAssets(opts = {}) {
|
|
|
41584
41632
|
}
|
|
41585
41633
|
|
|
41586
41634
|
// ../../_shared/db-deploy/index.ts
|
|
41587
|
-
import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync } from "node:fs";
|
|
41588
41635
|
init_src();
|
|
41636
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync } from "node:fs";
|
|
41637
|
+
import { join as join5 } from "node:path";
|
|
41589
41638
|
var RESET_SQL = `
|
|
41590
41639
|
DROP TABLE IF EXISTS cerefox_chunks CASCADE;
|
|
41591
41640
|
DROP TABLE IF EXISTS cerefox_documents CASCADE;
|
|
@@ -41651,6 +41700,95 @@ async function runDbDeploy(opts) {
|
|
|
41651
41700
|
await sql.end({ timeout: 5 }).catch(() => {});
|
|
41652
41701
|
}
|
|
41653
41702
|
}
|
|
41703
|
+
var BOOTSTRAP_MIGRATIONS_SQL = `
|
|
41704
|
+
CREATE TABLE IF NOT EXISTS cerefox_migrations (
|
|
41705
|
+
id SERIAL PRIMARY KEY,
|
|
41706
|
+
filename TEXT NOT NULL UNIQUE,
|
|
41707
|
+
applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
41708
|
+
);
|
|
41709
|
+
`;
|
|
41710
|
+
async function detectExistingSchema(dbUrl) {
|
|
41711
|
+
const sql = src_default(dbUrl, { prepare: false, onnotice: () => {} });
|
|
41712
|
+
try {
|
|
41713
|
+
const rows = await sql`SELECT to_regclass('public.cerefox_documents') AS t`;
|
|
41714
|
+
return rows[0]?.t != null;
|
|
41715
|
+
} finally {
|
|
41716
|
+
await sql.end({ timeout: 5 }).catch(() => {});
|
|
41717
|
+
}
|
|
41718
|
+
}
|
|
41719
|
+
async function migrationStatus(opts) {
|
|
41720
|
+
const sql = src_default(opts.dbUrl, { prepare: false, onnotice: () => {} });
|
|
41721
|
+
try {
|
|
41722
|
+
await sql.unsafe(BOOTSTRAP_MIGRATIONS_SQL);
|
|
41723
|
+
const all = listMigrationFiles(opts.assets.migrationsDir);
|
|
41724
|
+
const appliedRows = await sql`SELECT filename FROM cerefox_migrations ORDER BY filename`;
|
|
41725
|
+
const appliedSet = new Set(appliedRows.map((r) => r.filename));
|
|
41726
|
+
return {
|
|
41727
|
+
all,
|
|
41728
|
+
applied: all.filter((f) => appliedSet.has(f)),
|
|
41729
|
+
pending: all.filter((f) => !appliedSet.has(f))
|
|
41730
|
+
};
|
|
41731
|
+
} finally {
|
|
41732
|
+
await sql.end({ timeout: 5 }).catch(() => {});
|
|
41733
|
+
}
|
|
41734
|
+
}
|
|
41735
|
+
async function runDbMigrate(opts) {
|
|
41736
|
+
const log = opts.log ?? (() => {});
|
|
41737
|
+
const sql = src_default(opts.dbUrl, { prepare: false, onnotice: () => {} });
|
|
41738
|
+
try {
|
|
41739
|
+
await sql.unsafe(BOOTSTRAP_MIGRATIONS_SQL);
|
|
41740
|
+
const allFiles = listMigrationFiles(opts.assets.migrationsDir);
|
|
41741
|
+
const appliedRows = await sql`SELECT filename FROM cerefox_migrations ORDER BY filename`;
|
|
41742
|
+
const appliedSet = new Set(appliedRows.map((r) => r.filename));
|
|
41743
|
+
const pending = allFiles.filter((f) => !appliedSet.has(f));
|
|
41744
|
+
if (pending.length === 0)
|
|
41745
|
+
return { ok: true, applied: [], pending: [] };
|
|
41746
|
+
if (opts.dryRun) {
|
|
41747
|
+
for (const f of pending)
|
|
41748
|
+
log(`Would apply ${f}`);
|
|
41749
|
+
return { ok: true, applied: [], pending };
|
|
41750
|
+
}
|
|
41751
|
+
const applied = [];
|
|
41752
|
+
for (const f of pending) {
|
|
41753
|
+
const body = readFileSync4(join5(opts.assets.migrationsDir, f), "utf8");
|
|
41754
|
+
log(`Applying ${f}…`);
|
|
41755
|
+
try {
|
|
41756
|
+
await sql.begin(async (tx) => {
|
|
41757
|
+
await tx.unsafe(body);
|
|
41758
|
+
await tx`INSERT INTO cerefox_migrations (filename) VALUES (${f}) ON CONFLICT DO NOTHING`;
|
|
41759
|
+
});
|
|
41760
|
+
applied.push(f);
|
|
41761
|
+
} catch (err) {
|
|
41762
|
+
return {
|
|
41763
|
+
ok: false,
|
|
41764
|
+
applied,
|
|
41765
|
+
pending,
|
|
41766
|
+
failedFile: f,
|
|
41767
|
+
error: err instanceof Error ? err.message : String(err)
|
|
41768
|
+
};
|
|
41769
|
+
}
|
|
41770
|
+
}
|
|
41771
|
+
return { ok: true, applied, pending };
|
|
41772
|
+
} finally {
|
|
41773
|
+
await sql.end({ timeout: 5 }).catch(() => {});
|
|
41774
|
+
}
|
|
41775
|
+
}
|
|
41776
|
+
async function applyRpcs(opts) {
|
|
41777
|
+
const log = opts.log ?? (() => {});
|
|
41778
|
+
log("Refresh RPCs (rpcs.sql)…");
|
|
41779
|
+
if (opts.dryRun)
|
|
41780
|
+
return { ok: true };
|
|
41781
|
+
const rpcsSql = readFileSync4(opts.assets.rpcsFile, "utf8");
|
|
41782
|
+
const sql = src_default(opts.dbUrl, { prepare: false, onnotice: () => {} });
|
|
41783
|
+
try {
|
|
41784
|
+
await sql.unsafe(rpcsSql);
|
|
41785
|
+
return { ok: true };
|
|
41786
|
+
} catch (err) {
|
|
41787
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
41788
|
+
} finally {
|
|
41789
|
+
await sql.end({ timeout: 5 }).catch(() => {});
|
|
41790
|
+
}
|
|
41791
|
+
}
|
|
41654
41792
|
|
|
41655
41793
|
// src/cli/commands/deploy-server.ts
|
|
41656
41794
|
function commandSucceeds(cmd, args) {
|
|
@@ -41661,16 +41799,28 @@ function commandSucceeds(cmd, args) {
|
|
|
41661
41799
|
return false;
|
|
41662
41800
|
}
|
|
41663
41801
|
}
|
|
41802
|
+
function parseProjectRef(supabaseUrl) {
|
|
41803
|
+
if (!supabaseUrl)
|
|
41804
|
+
return null;
|
|
41805
|
+
try {
|
|
41806
|
+
const host = new URL(supabaseUrl).hostname;
|
|
41807
|
+
const label = host.split(".")[0];
|
|
41808
|
+
return /^[a-z0-9]{20}$/.test(label) ? label : null;
|
|
41809
|
+
} catch {
|
|
41810
|
+
return null;
|
|
41811
|
+
}
|
|
41812
|
+
}
|
|
41664
41813
|
function listEdgeFunctions(functionsDir) {
|
|
41665
41814
|
if (!existsSync6(functionsDir))
|
|
41666
41815
|
return [];
|
|
41667
41816
|
return readdirSync2(functionsDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("cerefox-")).map((e) => e.name).sort();
|
|
41668
41817
|
}
|
|
41669
|
-
async function
|
|
41818
|
+
async function action8(options) {
|
|
41670
41819
|
const settings = loadSettings();
|
|
41671
41820
|
const assets = resolveServerAssets();
|
|
41672
41821
|
const doSchema = !options.functionsOnly;
|
|
41673
41822
|
const doFunctions = !options.schemaOnly;
|
|
41823
|
+
const projectRef = options.projectRef ?? parseProjectRef(settings.supabaseUrl);
|
|
41674
41824
|
const checks = [];
|
|
41675
41825
|
if (doSchema) {
|
|
41676
41826
|
checks.push({
|
|
@@ -41698,12 +41848,11 @@ async function action7(options) {
|
|
|
41698
41848
|
remediation: "Install Node 20+ (npx ships with it) from nodejs.org, then re-run. " + "`cerefox deploy-server` shells out to the Supabase CLI via npx."
|
|
41699
41849
|
});
|
|
41700
41850
|
checks.push({
|
|
41701
|
-
label: "Supabase project
|
|
41702
|
-
ok:
|
|
41703
|
-
remediation: `
|
|
41704
|
-
` + `
|
|
41705
|
-
` +
|
|
41706
|
-
` + " Your project ref is in the dashboard URL: " + "https://supabase.com/dashboard/project/<project-ref>"
|
|
41851
|
+
label: "Supabase project ref resolved (from CEREFOX_SUPABASE_URL)",
|
|
41852
|
+
ok: Boolean(projectRef),
|
|
41853
|
+
remediation: `Could not derive the project ref from CEREFOX_SUPABASE_URL.
|
|
41854
|
+
` + " Set CEREFOX_SUPABASE_URL to your project URL " + `(https://<project-ref>.supabase.co), or pass --project-ref <ref>.
|
|
41855
|
+
` + " Also make sure you're logged in once: npx supabase login"
|
|
41707
41856
|
});
|
|
41708
41857
|
}
|
|
41709
41858
|
const failed = checks.filter((ch) => !ch.ok);
|
|
@@ -41724,12 +41873,38 @@ async function action7(options) {
|
|
|
41724
41873
|
}
|
|
41725
41874
|
println(c.green(`
|
|
41726
41875
|
✓ All prerequisites satisfied.`));
|
|
41876
|
+
let schemaMode = "unknown";
|
|
41877
|
+
let pending = [];
|
|
41878
|
+
if (doSchema) {
|
|
41879
|
+
try {
|
|
41880
|
+
const exists = await detectExistingSchema(settings.databaseUrl);
|
|
41881
|
+
schemaMode = exists ? "existing" : "fresh";
|
|
41882
|
+
if (exists) {
|
|
41883
|
+
pending = (await migrationStatus({ dbUrl: settings.databaseUrl, assets })).pending;
|
|
41884
|
+
}
|
|
41885
|
+
} catch (err) {
|
|
41886
|
+
if (!options.dryRun) {
|
|
41887
|
+
eprintln(c.red(`
|
|
41888
|
+
✗ Could not connect to the database: ${err instanceof Error ? err.message : String(err)}`));
|
|
41889
|
+
eprintln(c.dim(" Verify CEREFOX_DATABASE_URL (Session Pooler, port 5432)."));
|
|
41890
|
+
process.exit(1);
|
|
41891
|
+
}
|
|
41892
|
+
}
|
|
41893
|
+
}
|
|
41727
41894
|
const planLines = [];
|
|
41728
41895
|
if (doSchema) {
|
|
41729
|
-
|
|
41896
|
+
if (schemaMode === "fresh") {
|
|
41897
|
+
planLines.push(` • Deploy fresh schema + RPCs to ${settings.supabaseUrl || "your Supabase database"}`);
|
|
41898
|
+
} else if (schemaMode === "existing") {
|
|
41899
|
+
planLines.push(` • Update existing schema: apply ${pending.length} pending migration(s) + refresh RPCs`);
|
|
41900
|
+
for (const f of pending)
|
|
41901
|
+
planLines.push(c.dim(` – ${f}`));
|
|
41902
|
+
} else {
|
|
41903
|
+
planLines.push(` • Schema + RPCs (fresh or update — couldn't probe the DB)`);
|
|
41904
|
+
}
|
|
41730
41905
|
}
|
|
41731
41906
|
if (doFunctions) {
|
|
41732
|
-
planLines.push(` • Deploy ${efNames.length} Edge Function(s): ${efNames.join(", ")}`);
|
|
41907
|
+
planLines.push(` • Deploy ${efNames.length} Edge Function(s) to project ${projectRef}: ${efNames.join(", ")}`);
|
|
41733
41908
|
}
|
|
41734
41909
|
println(c.bold(`
|
|
41735
41910
|
Plan:`));
|
|
@@ -41741,26 +41916,52 @@ Plan:`));
|
|
|
41741
41916
|
process.exit(0);
|
|
41742
41917
|
}
|
|
41743
41918
|
const proceed = await confirm(`
|
|
41744
|
-
Proceed with deployment to Supabase
|
|
41919
|
+
Proceed with deployment to Supabase?`, true);
|
|
41745
41920
|
if (!proceed) {
|
|
41746
41921
|
println(c.dim("Aborted."));
|
|
41747
41922
|
process.exit(0);
|
|
41748
41923
|
}
|
|
41749
41924
|
if (doSchema) {
|
|
41750
|
-
|
|
41751
|
-
|
|
41752
|
-
|
|
41753
|
-
|
|
41754
|
-
|
|
41755
|
-
|
|
41756
|
-
|
|
41757
|
-
|
|
41758
|
-
|
|
41759
|
-
|
|
41925
|
+
if (schemaMode === "fresh") {
|
|
41926
|
+
println(c.bold(`
|
|
41927
|
+
▶ Deploying fresh schema + RPCs…`));
|
|
41928
|
+
const result = await runDbDeploy({
|
|
41929
|
+
dbUrl: settings.databaseUrl,
|
|
41930
|
+
assets,
|
|
41931
|
+
log: (line) => println(c.dim(` ${line}`))
|
|
41932
|
+
});
|
|
41933
|
+
if (!result.ok) {
|
|
41934
|
+
eprintln(c.red(`
|
|
41760
41935
|
✗ Schema deploy failed at "${result.failedStep}": ${result.error}`));
|
|
41761
|
-
|
|
41936
|
+
process.exit(1);
|
|
41937
|
+
}
|
|
41938
|
+
println(c.green(` ✓ Fresh schema deployed (${result.stepsRun} steps).`));
|
|
41939
|
+
} else {
|
|
41940
|
+
println(c.bold(`
|
|
41941
|
+
▶ Updating existing schema (migrations + RPC refresh)…`));
|
|
41942
|
+
const mig = await runDbMigrate({
|
|
41943
|
+
dbUrl: settings.databaseUrl,
|
|
41944
|
+
assets,
|
|
41945
|
+
log: (line) => println(c.dim(` ${line}`))
|
|
41946
|
+
});
|
|
41947
|
+
if (!mig.ok) {
|
|
41948
|
+
eprintln(c.red(`
|
|
41949
|
+
✗ Migration "${mig.failedFile}" failed: ${mig.error}`));
|
|
41950
|
+
eprintln(c.dim(" Earlier migrations in this run were committed. Fix + re-run."));
|
|
41951
|
+
process.exit(1);
|
|
41952
|
+
}
|
|
41953
|
+
const rpcs = await applyRpcs({
|
|
41954
|
+
dbUrl: settings.databaseUrl,
|
|
41955
|
+
assets,
|
|
41956
|
+
log: (line) => println(c.dim(` ${line}`))
|
|
41957
|
+
});
|
|
41958
|
+
if (!rpcs.ok) {
|
|
41959
|
+
eprintln(c.red(`
|
|
41960
|
+
✗ RPC refresh failed: ${rpcs.error}`));
|
|
41961
|
+
process.exit(1);
|
|
41962
|
+
}
|
|
41963
|
+
println(c.green(` ✓ Applied ${mig.applied.length} migration(s); RPCs refreshed.`));
|
|
41762
41964
|
}
|
|
41763
|
-
println(c.green(` ✓ Schema deployed (${result.stepsRun} steps).`));
|
|
41764
41965
|
}
|
|
41765
41966
|
if (doFunctions) {
|
|
41766
41967
|
println(c.bold(`
|
|
@@ -41770,7 +41971,10 @@ Proceed with deployment to Supabase${options.reset ? " (--reset DROPS existing d
|
|
|
41770
41971
|
for (const ef of efNames) {
|
|
41771
41972
|
info(` deploying ${ef}…`);
|
|
41772
41973
|
const workdir = assets.functionsDir.replace(/\/functions$/, "").replace(/\/supabase$/, "");
|
|
41773
|
-
const
|
|
41974
|
+
const args = ["--yes", "supabase", "functions", "deploy", ef];
|
|
41975
|
+
if (projectRef)
|
|
41976
|
+
args.push("--project-ref", projectRef);
|
|
41977
|
+
const r = spawnSync2("npx", args, {
|
|
41774
41978
|
encoding: "utf8",
|
|
41775
41979
|
stdio: "inherit",
|
|
41776
41980
|
cwd: workdir,
|
|
@@ -41794,7 +41998,7 @@ Proceed with deployment to Supabase${options.reset ? " (--reset DROPS existing d
|
|
|
41794
41998
|
println(c.dim("Verify with: cerefox doctor"));
|
|
41795
41999
|
}
|
|
41796
42000
|
function registerDeployServer(program2) {
|
|
41797
|
-
program2.command("deploy-server").description("Deploy the Cerefox server side (schema + RPCs + Edge Functions)
|
|
42001
|
+
program2.command("deploy-server").description("Deploy/update the Cerefox server side (schema + RPCs + Edge Functions) on Supabase.").option("--dry-run", "Print the plan + pre-flight without deploying.").option("--schema-only", "Deploy/update only the schema + RPCs (skip Edge Functions).").option("--functions-only", "Deploy only the Edge Functions (skip the schema/RPCs).").option("--project-ref <ref>", "Supabase project ref for Edge Function deploys (default: derived from CEREFOX_SUPABASE_URL).").action(action8);
|
|
41798
42002
|
}
|
|
41799
42003
|
|
|
41800
42004
|
// src/cli/commands/docs.ts
|
|
@@ -41808,7 +42012,7 @@ function openInBrowser(path) {
|
|
|
41808
42012
|
println(c.dim(`(could not auto-open; the file is at: ${path})`));
|
|
41809
42013
|
}
|
|
41810
42014
|
}
|
|
41811
|
-
function
|
|
42015
|
+
function action9(topic, options) {
|
|
41812
42016
|
const docs = listBundledDocs();
|
|
41813
42017
|
if (options.list || !topic && !options.print) {
|
|
41814
42018
|
if (docs.length === 0) {
|
|
@@ -41837,7 +42041,7 @@ function action8(topic, options) {
|
|
|
41837
42041
|
openInBrowser(doc.path);
|
|
41838
42042
|
}
|
|
41839
42043
|
function registerDocs(program2) {
|
|
41840
|
-
program2.command("docs").description("Open bundled Cerefox docs in your browser (or print to stdout).").argument("[topic]", "Doc topic (e.g. quickstart, connect-agents). Omit for the index.").option("--print", "Print to stdout instead of opening a browser.").option("--list", "List available topics.").action(
|
|
42044
|
+
program2.command("docs").description("Open bundled Cerefox docs in your browser (or print to stdout).").argument("[topic]", "Doc topic (e.g. quickstart, connect-agents). Omit for the index.").option("--print", "Print to stdout instead of opening a browser.").option("--list", "List available topics.").action(action9);
|
|
41841
42045
|
}
|
|
41842
42046
|
|
|
41843
42047
|
// ../../node_modules/.bun/ora@9.4.0/node_modules/ora/index.js
|
|
@@ -45227,11 +45431,16 @@ init_cli_core();
|
|
|
45227
45431
|
|
|
45228
45432
|
// src/cli/util/checks.ts
|
|
45229
45433
|
init_meta();
|
|
45230
|
-
init_config();
|
|
45231
|
-
init_config();
|
|
45232
45434
|
import { existsSync as existsSync8, readFileSync as readFileSync6, realpathSync, statSync as statSync2 } from "node:fs";
|
|
45233
45435
|
import { homedir as homedir4 } from "node:os";
|
|
45234
|
-
import { join as
|
|
45436
|
+
import { join as join7 } from "node:path";
|
|
45437
|
+
|
|
45438
|
+
// ../../_shared/ef-meta/index.ts
|
|
45439
|
+
var EF_VERSION = "0.8.0";
|
|
45440
|
+
|
|
45441
|
+
// src/cli/util/checks.ts
|
|
45442
|
+
init_config();
|
|
45443
|
+
init_config();
|
|
45235
45444
|
|
|
45236
45445
|
// ../../_shared/compatibility/index.ts
|
|
45237
45446
|
var COMPATIBILITY = {
|
|
@@ -45502,11 +45711,24 @@ async function checkOpenAI() {
|
|
|
45502
45711
|
};
|
|
45503
45712
|
}
|
|
45504
45713
|
}
|
|
45714
|
+
var SCHEMA_VERSION_RE = /^--\s*@version:\s*(\S+)/m;
|
|
45715
|
+
function readBundledSchemaVersion() {
|
|
45716
|
+
try {
|
|
45717
|
+
const assets = resolveServerAssets();
|
|
45718
|
+
if (!existsSync8(assets.schemaFile))
|
|
45719
|
+
return null;
|
|
45720
|
+
const m = readFileSync6(assets.schemaFile, "utf8").match(SCHEMA_VERSION_RE);
|
|
45721
|
+
return m ? m[1] : null;
|
|
45722
|
+
} catch {
|
|
45723
|
+
return null;
|
|
45724
|
+
}
|
|
45725
|
+
}
|
|
45726
|
+
var SCHEMA_CHECK_NAME = "schema + RPCs";
|
|
45505
45727
|
async function checkSchemaVersion() {
|
|
45506
45728
|
const settings = loadSettings();
|
|
45507
45729
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
45508
45730
|
return {
|
|
45509
|
-
name:
|
|
45731
|
+
name: SCHEMA_CHECK_NAME,
|
|
45510
45732
|
status: "skipped",
|
|
45511
45733
|
detail: "Supabase config missing; skipped."
|
|
45512
45734
|
};
|
|
@@ -45524,21 +45746,40 @@ async function checkSchemaVersion() {
|
|
|
45524
45746
|
});
|
|
45525
45747
|
if (!resp.ok) {
|
|
45526
45748
|
return {
|
|
45527
|
-
name:
|
|
45749
|
+
name: SCHEMA_CHECK_NAME,
|
|
45528
45750
|
status: "error",
|
|
45529
|
-
detail: `cerefox_schema_version returned ${resp.status}
|
|
45530
|
-
hint: "Deploy the schema
|
|
45751
|
+
detail: `cerefox_schema_version returned ${resp.status} — schema not deployed.`,
|
|
45752
|
+
hint: "Deploy the schema + RPCs (see remediation below)."
|
|
45531
45753
|
};
|
|
45532
45754
|
}
|
|
45533
45755
|
const deployed = await resp.json();
|
|
45534
|
-
|
|
45535
|
-
|
|
45536
|
-
|
|
45537
|
-
|
|
45538
|
-
|
|
45756
|
+
const bundled = readBundledSchemaVersion();
|
|
45757
|
+
const level = classifyCompat(deployed, COMPATIBILITY.minSchema, bundled);
|
|
45758
|
+
switch (level) {
|
|
45759
|
+
case "below-min":
|
|
45760
|
+
return {
|
|
45761
|
+
name: SCHEMA_CHECK_NAME,
|
|
45762
|
+
status: "error",
|
|
45763
|
+
detail: `Deployed schema v${deployed} is below the required minimum v${COMPATIBILITY.minSchema}.`,
|
|
45764
|
+
hint: "Update the schema + RPCs (see remediation below)."
|
|
45765
|
+
};
|
|
45766
|
+
case "above-min-but-old":
|
|
45767
|
+
return {
|
|
45768
|
+
name: SCHEMA_CHECK_NAME,
|
|
45769
|
+
status: "warn",
|
|
45770
|
+
detail: `Deployed schema v${deployed} works but is older than this client's bundled v${bundled}.`,
|
|
45771
|
+
hint: "Update the schema + RPCs (see remediation below)."
|
|
45772
|
+
};
|
|
45773
|
+
default:
|
|
45774
|
+
return {
|
|
45775
|
+
name: SCHEMA_CHECK_NAME,
|
|
45776
|
+
status: "ok",
|
|
45777
|
+
detail: `cerefox_schema_version() → "${deployed}"${bundled ? ` (bundled v${bundled})` : ""}`
|
|
45778
|
+
};
|
|
45779
|
+
}
|
|
45539
45780
|
} catch (err) {
|
|
45540
45781
|
return {
|
|
45541
|
-
name:
|
|
45782
|
+
name: SCHEMA_CHECK_NAME,
|
|
45542
45783
|
status: "error",
|
|
45543
45784
|
detail: `Schema version probe failed: ${err instanceof Error ? err.message : String(err)}`
|
|
45544
45785
|
};
|
|
@@ -45557,9 +45798,9 @@ function hasCerefoxInJsonFile(path) {
|
|
|
45557
45798
|
}
|
|
45558
45799
|
function checkMcpConfigs() {
|
|
45559
45800
|
const home = homedir4();
|
|
45560
|
-
const claudeCodeUser =
|
|
45561
|
-
const claudeCodeProj =
|
|
45562
|
-
const claudeDesktop = process.platform === "darwin" ?
|
|
45801
|
+
const claudeCodeUser = join7(home, ".claude.json");
|
|
45802
|
+
const claudeCodeProj = join7(process.cwd(), ".mcp.json");
|
|
45803
|
+
const claudeDesktop = process.platform === "darwin" ? join7(home, "Library", "Application Support", "Claude", "claude_desktop_config.json") : process.platform === "win32" ? join7(process.env.APPDATA ?? "", "Claude", "claude_desktop_config.json") : join7(home, ".config", "Claude", "claude_desktop_config.json");
|
|
45563
45804
|
const found = [];
|
|
45564
45805
|
if (hasCerefoxInJsonFile(claudeCodeUser))
|
|
45565
45806
|
found.push("Claude Code (user)");
|
|
@@ -45583,8 +45824,8 @@ function checkMcpConfigs() {
|
|
|
45583
45824
|
}
|
|
45584
45825
|
function checkLegacyShadowEnv() {
|
|
45585
45826
|
const home = homedir4();
|
|
45586
|
-
const homeEnv =
|
|
45587
|
-
const cwdEnv =
|
|
45827
|
+
const homeEnv = join7(home, USER_STATE_DIR_NAME, ".env");
|
|
45828
|
+
const cwdEnv = join7(process.cwd(), ".env");
|
|
45588
45829
|
if (!existsSync8(homeEnv) || !existsSync8(cwdEnv))
|
|
45589
45830
|
return null;
|
|
45590
45831
|
try {
|
|
@@ -45666,7 +45907,7 @@ async function checkEdgeFunctionsCompat() {
|
|
|
45666
45907
|
compat = await checkServerCompatibility({
|
|
45667
45908
|
aggregatorUrl: aggregatorUrlFor(settings.supabaseUrl),
|
|
45668
45909
|
bearer: settings.supabaseAnonKey,
|
|
45669
|
-
bundledEf:
|
|
45910
|
+
bundledEf: EF_VERSION
|
|
45670
45911
|
});
|
|
45671
45912
|
} catch (err) {
|
|
45672
45913
|
return {
|
|
@@ -45689,14 +45930,14 @@ async function checkEdgeFunctionsCompat() {
|
|
|
45689
45930
|
name: "edge functions",
|
|
45690
45931
|
status: "error",
|
|
45691
45932
|
detail: `Deployed EF v${deployed} is below the required minimum v${compat.edgeFunctions.min}.`,
|
|
45692
|
-
hint: "
|
|
45933
|
+
hint: "Update the Edge Functions (see remediation below)."
|
|
45693
45934
|
};
|
|
45694
45935
|
case "above-min-but-old":
|
|
45695
45936
|
return {
|
|
45696
45937
|
name: "edge functions",
|
|
45697
45938
|
status: "warn",
|
|
45698
|
-
detail: `Deployed EF v${deployed} works but is older than
|
|
45699
|
-
hint: "
|
|
45939
|
+
detail: `Deployed EF v${deployed} works but is older than the bundled Edge Functions (v${EF_VERSION}).`,
|
|
45940
|
+
hint: "Update the Edge Functions (see remediation below)."
|
|
45700
45941
|
};
|
|
45701
45942
|
default:
|
|
45702
45943
|
return {
|
|
@@ -45731,7 +45972,7 @@ async function runAllChecks(opts = {}) {
|
|
|
45731
45972
|
{ name: "legacy env", phase: "Checking legacy env shadowing", run: () => checkLegacyShadowEnv() },
|
|
45732
45973
|
{ name: "supabase", phase: "Probing Supabase Data API", run: () => checkSupabase() },
|
|
45733
45974
|
{ name: "openai", phase: "Probing OpenAI embeddings", run: () => checkOpenAI() },
|
|
45734
|
-
{ name: "schema", phase: "Reading schema version", run: () => checkSchemaVersion() },
|
|
45975
|
+
{ name: "schema + RPCs", phase: "Reading schema + RPC version", run: () => checkSchemaVersion() },
|
|
45735
45976
|
{ name: "edge functions", phase: "Probing Edge Function versions", run: () => checkEdgeFunctionsCompat() },
|
|
45736
45977
|
{ name: "postgres", phase: "Probing Postgres DDL endpoint", run: () => checkPostgres() },
|
|
45737
45978
|
{ name: "mcp clients", phase: "Scanning MCP client configs", run: () => checkMcpConfigs() }
|
|
@@ -45760,7 +46001,7 @@ function symbol(status) {
|
|
|
45760
46001
|
return cErr.dim("ℹ");
|
|
45761
46002
|
}
|
|
45762
46003
|
}
|
|
45763
|
-
async function
|
|
46004
|
+
async function action10(options) {
|
|
45764
46005
|
const useSpinner = !options.json && process.stderr.isTTY;
|
|
45765
46006
|
const spinner = useSpinner ? ora({ text: "Starting checks…", spinner: "dots", stream: process.stderr }).start() : null;
|
|
45766
46007
|
const results = await runAllChecks({
|
|
@@ -45784,6 +46025,26 @@ async function action9(options) {
|
|
|
45784
46025
|
}
|
|
45785
46026
|
println("");
|
|
45786
46027
|
}
|
|
46028
|
+
if (!options.json) {
|
|
46029
|
+
const stale = (name) => {
|
|
46030
|
+
const r = results.find((x) => x.name === name);
|
|
46031
|
+
return r != null && (r.status === "error" || r.status === "warn");
|
|
46032
|
+
};
|
|
46033
|
+
const needsSchema = stale("schema + RPCs");
|
|
46034
|
+
const needsEf = stale("edge functions");
|
|
46035
|
+
let remediation = null;
|
|
46036
|
+
if (needsSchema && needsEf) {
|
|
46037
|
+
remediation = "Update the server (schema + RPCs + Edge Functions): cerefox deploy-server";
|
|
46038
|
+
} else if (needsSchema) {
|
|
46039
|
+
remediation = "Update the schema + RPCs: cerefox deploy-server --schema-only";
|
|
46040
|
+
} else if (needsEf) {
|
|
46041
|
+
remediation = "Update the Edge Functions: cerefox deploy-server --functions-only";
|
|
46042
|
+
}
|
|
46043
|
+
if (remediation) {
|
|
46044
|
+
println(cErr.yellow("→ " + remediation));
|
|
46045
|
+
println("");
|
|
46046
|
+
}
|
|
46047
|
+
}
|
|
45787
46048
|
const errCount = results.filter((r) => r.status === "error").length;
|
|
45788
46049
|
const warnCount = results.filter((r) => r.status === "warn").length;
|
|
45789
46050
|
if (errCount > 0) {
|
|
@@ -45797,13 +46058,13 @@ async function action9(options) {
|
|
|
45797
46058
|
}
|
|
45798
46059
|
}
|
|
45799
46060
|
function registerDoctor(program2) {
|
|
45800
|
-
program2.command("doctor").description("Run diagnostic checks against the installed Cerefox.").option("--json", "Emit machine-readable JSON (no colours, structured output).").action(
|
|
46061
|
+
program2.command("doctor").description("Run diagnostic checks against the installed Cerefox.").option("--json", "Emit machine-readable JSON (no colours, structured output).").action(action10);
|
|
45801
46062
|
}
|
|
45802
46063
|
|
|
45803
46064
|
// src/cli/commands/get-audit-log.ts
|
|
45804
46065
|
init_cli_core();
|
|
45805
46066
|
init_client();
|
|
45806
|
-
async function
|
|
46067
|
+
async function action11(options) {
|
|
45807
46068
|
const limit = parsePositiveInt(options.limit, "--limit", 50);
|
|
45808
46069
|
const client = getClient();
|
|
45809
46070
|
const data = await client.rpc("cerefox_list_audit_entries", {
|
|
@@ -45841,14 +46102,14 @@ async function action10(options) {
|
|
|
45841
46102
|
})));
|
|
45842
46103
|
}
|
|
45843
46104
|
function registerGetAuditLog(program2) {
|
|
45844
|
-
program2.command("get-audit-log").description("Query the audit log with optional filters.").option("-d, --document-id <uuid>", "Filter by document.").option("-a, --author <name>", "Filter by author.").option("-o, --operation <type>", "Filter by operation: create, update-content, update-metadata, delete, restore.").option("--since <iso>", "Lower-bound ISO timestamp.").option("--until <iso>", "Upper-bound ISO timestamp.").option("-l, --limit <n>", "Maximum entries (max 200).", "50").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
46105
|
+
program2.command("get-audit-log").description("Query the audit log with optional filters.").option("-d, --document-id <uuid>", "Filter by document.").option("-a, --author <name>", "Filter by author.").option("-o, --operation <type>", "Filter by operation: create, update-content, update-metadata, delete, restore.").option("--since <iso>", "Lower-bound ISO timestamp.").option("--until <iso>", "Upper-bound ISO timestamp.").option("-l, --limit <n>", "Maximum entries (max 200).", "50").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action11);
|
|
45845
46106
|
}
|
|
45846
46107
|
|
|
45847
46108
|
// src/cli/commands/get-doc.ts
|
|
45848
46109
|
init_cli_core();
|
|
45849
46110
|
init_cli_core();
|
|
45850
46111
|
init_client();
|
|
45851
|
-
async function
|
|
46112
|
+
async function action12(documentId, options) {
|
|
45852
46113
|
const client = getClient();
|
|
45853
46114
|
const rows = await client.rpc("cerefox_get_document", {
|
|
45854
46115
|
p_document_id: documentId,
|
|
@@ -45878,7 +46139,7 @@ async function action11(documentId, options) {
|
|
|
45878
46139
|
println(doc.full_content);
|
|
45879
46140
|
}
|
|
45880
46141
|
function registerGetDoc(program2) {
|
|
45881
|
-
program2.command("get-doc").description("Retrieve the full content of a document by ID.").argument("<document-id>", "UUID of the document.").option("--version-id <uuid>", "Specific archived version (default: current).").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
46142
|
+
program2.command("get-doc").description("Retrieve the full content of a document by ID.").argument("<document-id>", "UUID of the document.").option("--version-id <uuid>", "Specific archived version (default: current).").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action12);
|
|
45882
46143
|
}
|
|
45883
46144
|
|
|
45884
46145
|
// src/cli/commands/ingest.ts
|
|
@@ -46615,7 +46876,7 @@ async function readContent(path, paste) {
|
|
|
46615
46876
|
const titleFromPath = basename2(path, extname2(path));
|
|
46616
46877
|
return { content, titleFromPath };
|
|
46617
46878
|
}
|
|
46618
|
-
async function
|
|
46879
|
+
async function action13(path, options) {
|
|
46619
46880
|
const { content, titleFromPath } = await readContent(path, Boolean(options.paste));
|
|
46620
46881
|
const title = options.title ?? titleFromPath;
|
|
46621
46882
|
if (!title || title.trim() === "") {
|
|
@@ -46687,7 +46948,7 @@ async function action12(path, options) {
|
|
|
46687
46948
|
}
|
|
46688
46949
|
}
|
|
46689
46950
|
function registerIngest(program2) {
|
|
46690
|
-
program2.command("ingest").description("Ingest a file (or stdin paste) into the knowledge base.").argument("[path]", "Path to the file to ingest. Omit when using --paste.").option("--paste", "Read content from stdin instead of a file.").option("-t, --title <title>", "Document title (required with --paste; defaults to filename without extension).").option("-p, --project-name <name>", "Single project membership (non-destructive on update).").option("-P, --project-names <names>", "Comma-separated full project membership set (destructive replace on update).").option("-m, --metadata <json>", "JSON metadata object.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-i, --document-id <uuid>", "Update a specific document by UUID (overrides --update-if-exists).").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(
|
|
46951
|
+
program2.command("ingest").description("Ingest a file (or stdin paste) into the knowledge base.").argument("[path]", "Path to the file to ingest. Omit when using --paste.").option("--paste", "Read content from stdin instead of a file.").option("-t, --title <title>", "Document title (required with --paste; defaults to filename without extension).").option("-p, --project-name <name>", "Single project membership (non-destructive on update).").option("-P, --project-names <names>", "Comma-separated full project membership set (destructive replace on update).").option("-m, --metadata <json>", "JSON metadata object.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-i, --document-id <uuid>", "Update a specific document by UUID (overrides --update-if-exists).").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(action13);
|
|
46691
46952
|
}
|
|
46692
46953
|
|
|
46693
46954
|
// src/cli/commands/ingest-dir.ts
|
|
@@ -46696,7 +46957,7 @@ init_cli_core();
|
|
|
46696
46957
|
init_config();
|
|
46697
46958
|
var import_cli_progress = __toESM(require_cli_progress(), 1);
|
|
46698
46959
|
import { readdirSync as readdirSync4, statSync as statSync3 } from "node:fs";
|
|
46699
|
-
import { basename as basename3, extname as extname3, join as
|
|
46960
|
+
import { basename as basename3, extname as extname3, join as join8 } from "node:path";
|
|
46700
46961
|
function walk(dir, extensions) {
|
|
46701
46962
|
let entries;
|
|
46702
46963
|
try {
|
|
@@ -46706,7 +46967,7 @@ function walk(dir, extensions) {
|
|
|
46706
46967
|
}
|
|
46707
46968
|
const files = [];
|
|
46708
46969
|
for (const name of entries) {
|
|
46709
|
-
const full =
|
|
46970
|
+
const full = join8(dir, name);
|
|
46710
46971
|
let stat;
|
|
46711
46972
|
try {
|
|
46712
46973
|
stat = statSync3(full);
|
|
@@ -46723,7 +46984,7 @@ function walk(dir, extensions) {
|
|
|
46723
46984
|
}
|
|
46724
46985
|
return files;
|
|
46725
46986
|
}
|
|
46726
|
-
async function
|
|
46987
|
+
async function action14(dir, options) {
|
|
46727
46988
|
const extensions = new Set((options.extensions ?? ".md,.txt").split(",").map((e) => e.trim().toLowerCase()).map((e) => e.startsWith(".") ? e : "." + e).filter((e) => e.length > 0));
|
|
46728
46989
|
const files = walk(dir, extensions);
|
|
46729
46990
|
if (files.length === 0) {
|
|
@@ -46796,7 +47057,7 @@ async function action13(dir, options) {
|
|
|
46796
47057
|
}
|
|
46797
47058
|
}
|
|
46798
47059
|
function registerIngestDir(program2) {
|
|
46799
|
-
program2.command("ingest-dir").description("Recursively ingest a directory of markdown / text files.").argument("<dir>", "Root directory to walk.").option("-p, --project-name <name>", "Project membership for all ingested docs.").option("-m, --metadata <json>", "JSON metadata applied to every doc.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").option("-e, --extensions <list>", "Comma-separated file extensions to ingest.", ".md,.txt").action(
|
|
47060
|
+
program2.command("ingest-dir").description("Recursively ingest a directory of markdown / text files.").argument("<dir>", "Root directory to walk.").option("-p, --project-name <name>", "Project membership for all ingested docs.").option("-m, --metadata <json>", "JSON metadata applied to every doc.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").option("-e, --extensions <list>", "Comma-separated file extensions to ingest.", ".md,.txt").action(action14);
|
|
46800
47061
|
}
|
|
46801
47062
|
|
|
46802
47063
|
// src/cli/commands/init.ts
|
|
@@ -46812,7 +47073,7 @@ import {
|
|
|
46812
47073
|
writeFileSync as writeFileSync3
|
|
46813
47074
|
} from "node:fs";
|
|
46814
47075
|
import { homedir as homedir5 } from "node:os";
|
|
46815
|
-
import { dirname as dirname4, join as
|
|
47076
|
+
import { dirname as dirname4, join as join9 } from "node:path";
|
|
46816
47077
|
async function readConfigFile(path) {
|
|
46817
47078
|
if (!existsSync9(path)) {
|
|
46818
47079
|
throw userError(`--config file not found: ${path}`);
|
|
@@ -47062,11 +47323,11 @@ async function maybeOfferServerDeploy() {
|
|
|
47062
47323
|
if (compareSemver(deployed, COMPATIBILITY.minSchema) < 0) {
|
|
47063
47324
|
println(c.bold("Schema deploy"));
|
|
47064
47325
|
println(c.yellow(` Deployed schema v${deployed} is below the required v${COMPATIBILITY.minSchema}.`));
|
|
47065
|
-
const yes = await confirm("
|
|
47326
|
+
const yes = await confirm(" Update the server now (applies pending migrations, refreshes RPCs + EFs)?", true);
|
|
47066
47327
|
if (yes)
|
|
47067
|
-
launchDeployServer(
|
|
47328
|
+
launchDeployServer();
|
|
47068
47329
|
else
|
|
47069
|
-
println(c.dim(" Skipped. Run `cerefox deploy-server
|
|
47330
|
+
println(c.dim(" Skipped. Run `cerefox deploy-server` when ready."));
|
|
47070
47331
|
println("");
|
|
47071
47332
|
return;
|
|
47072
47333
|
}
|
|
@@ -47126,9 +47387,9 @@ function writeAnswersTo(target, answers) {
|
|
|
47126
47387
|
}
|
|
47127
47388
|
}
|
|
47128
47389
|
}
|
|
47129
|
-
async function
|
|
47130
|
-
const homeEnv =
|
|
47131
|
-
const cwdEnv =
|
|
47390
|
+
async function action16(options) {
|
|
47391
|
+
const homeEnv = join9(homedir5(), USER_STATE_DIR_NAME, ".env");
|
|
47392
|
+
const cwdEnv = join9(process.cwd(), ".env");
|
|
47132
47393
|
const explicitDir = (process.env.CEREFOX_CONFIG_DIR ?? "").trim();
|
|
47133
47394
|
if (explicitDir) {
|
|
47134
47395
|
const target2 = resolveEnvFile();
|
|
@@ -47235,13 +47496,13 @@ async function action15(options) {
|
|
|
47235
47496
|
await postWriteLifecycle(target, options);
|
|
47236
47497
|
}
|
|
47237
47498
|
function registerInit(program2) {
|
|
47238
|
-
program2.command("init").description("Interactive first-run setup (config, schema deploy stub, optional MCP wiring).").option("-c, --config <file>", "Non-interactive mode: read answers from a JSON file.").option("--force", "Overwrite existing configuration without prompting.").option("--skip-schema", "Skip the schema deploy step.").option("--skip-self-docs", "Skip the bundled self-doc ingest.").option("--skip-agent-config", "Skip the optional MCP agent wiring.").action(
|
|
47499
|
+
program2.command("init").description("Interactive first-run setup (config, schema deploy stub, optional MCP wiring).").option("-c, --config <file>", "Non-interactive mode: read answers from a JSON file.").option("--force", "Overwrite existing configuration without prompting.").option("--skip-schema", "Skip the schema deploy step.").option("--skip-self-docs", "Skip the bundled self-doc ingest.").option("--skip-agent-config", "Skip the optional MCP agent wiring.").action(action16);
|
|
47239
47500
|
}
|
|
47240
47501
|
|
|
47241
47502
|
// src/cli/commands/list-docs.ts
|
|
47242
47503
|
init_cli_core();
|
|
47243
47504
|
init_client();
|
|
47244
|
-
async function
|
|
47505
|
+
async function action17(options) {
|
|
47245
47506
|
const limit = parsePositiveInt(options.limit, "--limit", 100);
|
|
47246
47507
|
const client = getClient();
|
|
47247
47508
|
let projectId;
|
|
@@ -47296,13 +47557,13 @@ async function action16(options) {
|
|
|
47296
47557
|
})));
|
|
47297
47558
|
}
|
|
47298
47559
|
function registerListDocs(program2) {
|
|
47299
|
-
program2.command("list-docs").description("List documents in the knowledge base.").option("-p, --project <name>", "Filter to a specific project.").option("-l, --limit <n>", "Maximum docs to return.", "100").option("--json", "Emit machine-readable JSON.").action(
|
|
47560
|
+
program2.command("list-docs").description("List documents in the knowledge base.").option("-p, --project <name>", "Filter to a specific project.").option("-l, --limit <n>", "Maximum docs to return.", "100").option("--json", "Emit machine-readable JSON.").action(action17);
|
|
47300
47561
|
}
|
|
47301
47562
|
|
|
47302
47563
|
// src/cli/commands/list-metadata-keys.ts
|
|
47303
47564
|
init_cli_core();
|
|
47304
47565
|
init_client();
|
|
47305
|
-
async function
|
|
47566
|
+
async function action18(options) {
|
|
47306
47567
|
const client = getClient();
|
|
47307
47568
|
const data = await client.rpc("cerefox_list_metadata_keys");
|
|
47308
47569
|
if (data === null) {
|
|
@@ -47330,13 +47591,13 @@ async function action17(options) {
|
|
|
47330
47591
|
})));
|
|
47331
47592
|
}
|
|
47332
47593
|
function registerListMetadataKeys(program2) {
|
|
47333
|
-
program2.command("list-metadata-keys").description("List all metadata keys with document counts and example values.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
47594
|
+
program2.command("list-metadata-keys").description("List all metadata keys with document counts and example values.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action18);
|
|
47334
47595
|
}
|
|
47335
47596
|
|
|
47336
47597
|
// src/cli/commands/list-projects.ts
|
|
47337
47598
|
init_cli_core();
|
|
47338
47599
|
init_client();
|
|
47339
|
-
async function
|
|
47600
|
+
async function action19(options) {
|
|
47340
47601
|
const client = getClient();
|
|
47341
47602
|
const { data, error: error2 } = await client.raw.from("cerefox_projects").select("id, name, description, created_at").order("name", { ascending: true });
|
|
47342
47603
|
if (error2) {
|
|
@@ -47365,13 +47626,13 @@ async function action18(options) {
|
|
|
47365
47626
|
})), "(no projects)");
|
|
47366
47627
|
}
|
|
47367
47628
|
function registerListProjects(program2) {
|
|
47368
|
-
program2.command("list-projects").description("List all projects in the knowledge base.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
47629
|
+
program2.command("list-projects").description("List all projects in the knowledge base.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action19);
|
|
47369
47630
|
}
|
|
47370
47631
|
|
|
47371
47632
|
// src/cli/commands/list-versions.ts
|
|
47372
47633
|
init_cli_core();
|
|
47373
47634
|
init_client();
|
|
47374
|
-
async function
|
|
47635
|
+
async function action20(documentId, options) {
|
|
47375
47636
|
const client = getClient();
|
|
47376
47637
|
const data = await client.rpc("cerefox_list_document_versions", {
|
|
47377
47638
|
p_document_id: documentId
|
|
@@ -47412,7 +47673,7 @@ async function action19(documentId, options) {
|
|
|
47412
47673
|
})));
|
|
47413
47674
|
}
|
|
47414
47675
|
function registerListVersions(program2) {
|
|
47415
|
-
program2.command("list-versions").description("List archived versions of a document.").argument("<document-id>", "UUID of the document.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
47676
|
+
program2.command("list-versions").description("List archived versions of a document.").argument("<document-id>", "UUID of the document.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action20);
|
|
47416
47677
|
}
|
|
47417
47678
|
|
|
47418
47679
|
// src/cli/commands/mcp.ts
|
|
@@ -47427,7 +47688,7 @@ function registerMcp(program2) {
|
|
|
47427
47688
|
// src/cli/commands/metadata-search.ts
|
|
47428
47689
|
init_cli_core();
|
|
47429
47690
|
init_client();
|
|
47430
|
-
async function
|
|
47691
|
+
async function action21(options) {
|
|
47431
47692
|
const metadataFilter = parseJsonObjectArg(options.metadataFilter, "--metadata-filter");
|
|
47432
47693
|
if (!metadataFilter || Object.keys(metadataFilter).length === 0) {
|
|
47433
47694
|
throw userError("--metadata-filter is required and must be a non-empty JSON object.", `Example: --metadata-filter '{"type":"decision-log"}'.`);
|
|
@@ -47490,7 +47751,7 @@ async function action20(options) {
|
|
|
47490
47751
|
}
|
|
47491
47752
|
}
|
|
47492
47753
|
function registerMetadataSearch(program2) {
|
|
47493
|
-
program2.command("metadata-search").description("Find documents by metadata criteria (no text query).").requiredOption("-f, --metadata-filter <json>", "JSON object; only docs whose metadata contains ALL pairs are returned.").option("-p, --project-name <name>", "Filter to a specific project.").option("--updated-since <iso>", "Only docs updated on/after this ISO timestamp.").option("--created-since <iso>", "Only docs created on/after this ISO timestamp.").option("--include-content", "Include full document text in results.").option("-l, --limit <n>", "Maximum docs to return.", "10").option("--max-bytes <n>", "Response size budget in bytes (with --include-content).", "200000").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
47754
|
+
program2.command("metadata-search").description("Find documents by metadata criteria (no text query).").requiredOption("-f, --metadata-filter <json>", "JSON object; only docs whose metadata contains ALL pairs are returned.").option("-p, --project-name <name>", "Filter to a specific project.").option("--updated-since <iso>", "Only docs updated on/after this ISO timestamp.").option("--created-since <iso>", "Only docs created on/after this ISO timestamp.").option("--include-content", "Include full document text in results.").option("-l, --limit <n>", "Maximum docs to return.", "10").option("--max-bytes <n>", "Response size budget in bytes (with --include-content).", "200000").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action21);
|
|
47494
47755
|
}
|
|
47495
47756
|
|
|
47496
47757
|
// src/cli/commands/reindex.ts
|
|
@@ -47498,7 +47759,7 @@ init_dist4();
|
|
|
47498
47759
|
init_cli_core();
|
|
47499
47760
|
init_config();
|
|
47500
47761
|
var DEFAULT_MODEL = "text-embedding-3-small";
|
|
47501
|
-
async function
|
|
47762
|
+
async function action22(options) {
|
|
47502
47763
|
const settings = loadSettings();
|
|
47503
47764
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
47504
47765
|
throw userError("Supabase credentials not configured — run `cerefox init` first.");
|
|
@@ -47577,7 +47838,7 @@ ${c2.content}`;
|
|
|
47577
47838
|
}
|
|
47578
47839
|
}
|
|
47579
47840
|
function registerReindex(program2) {
|
|
47580
|
-
program2.command("reindex").description("Re-embed existing document chunks (v0.7+).").option("--all", "Reindex every chunk regardless of embedder.").option("--batch <n>", "Chunks per OpenAI batch call. Capped at 96 internally.", "32").option("--dry-run", "Show counts without re-embedding.").option("-i, --document-id <uuid>", "Limit reindex to a single document.").action(
|
|
47841
|
+
program2.command("reindex").description("Re-embed existing document chunks (v0.7+).").option("--all", "Reindex every chunk regardless of embedder.").option("--batch <n>", "Chunks per OpenAI batch call. Capped at 96 internally.", "32").option("--dry-run", "Show counts without re-embedding.").option("-i, --document-id <uuid>", "Limit reindex to a single document.").action(action22);
|
|
47581
47842
|
}
|
|
47582
47843
|
|
|
47583
47844
|
// src/cli/commands/restore.ts
|
|
@@ -47585,12 +47846,12 @@ init_cli_core();
|
|
|
47585
47846
|
init_client();
|
|
47586
47847
|
import { existsSync as existsSync10, readFileSync as readFileSync11, readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
|
|
47587
47848
|
import { homedir as homedir6 } from "node:os";
|
|
47588
|
-
import { join as
|
|
47849
|
+
import { join as join10, resolve as resolve4 } from "node:path";
|
|
47589
47850
|
function expandHome2(path) {
|
|
47590
47851
|
if (path === "~")
|
|
47591
47852
|
return homedir6();
|
|
47592
47853
|
if (path.startsWith("~/"))
|
|
47593
|
-
return
|
|
47854
|
+
return join10(homedir6(), path.slice(2));
|
|
47594
47855
|
return path;
|
|
47595
47856
|
}
|
|
47596
47857
|
function resolveBackupFile(target) {
|
|
@@ -47601,13 +47862,13 @@ function resolveBackupFile(target) {
|
|
|
47601
47862
|
const stat = statSync4(path);
|
|
47602
47863
|
if (stat.isFile())
|
|
47603
47864
|
return path;
|
|
47604
|
-
const candidates = readdirSync5(path).filter((n) => n.endsWith(".json") && n.startsWith("cerefox-")).map((n) => ({ name: n, mtime: statSync4(
|
|
47865
|
+
const candidates = readdirSync5(path).filter((n) => n.endsWith(".json") && n.startsWith("cerefox-")).map((n) => ({ name: n, mtime: statSync4(join10(path, n)).mtimeMs })).sort((a, b2) => b2.mtime - a.mtime);
|
|
47605
47866
|
if (candidates.length === 0) {
|
|
47606
47867
|
throw userError(`No cerefox-*.json files in ${path}`);
|
|
47607
47868
|
}
|
|
47608
|
-
return
|
|
47869
|
+
return join10(path, candidates[0].name);
|
|
47609
47870
|
}
|
|
47610
|
-
async function
|
|
47871
|
+
async function action23(target, options) {
|
|
47611
47872
|
const file = resolveBackupFile(target);
|
|
47612
47873
|
let payload;
|
|
47613
47874
|
try {
|
|
@@ -47663,7 +47924,7 @@ async function action22(target, options) {
|
|
|
47663
47924
|
}
|
|
47664
47925
|
}
|
|
47665
47926
|
function registerRestore(program2) {
|
|
47666
|
-
program2.command("restore").description("Restore a JSON-snapshot backup into the knowledge base.").argument("<snapshot>", "Backup file (or directory; most recent is picked) produced by `cerefox backup`.").option("--dry-run", "Print what would be restored without writing.").option("-p, --project-name <name>", "Reserved for future use; currently ignored (project memberships ride along with each doc's metadata).").action(
|
|
47927
|
+
program2.command("restore").description("Restore a JSON-snapshot backup into the knowledge base.").argument("<snapshot>", "Backup file (or directory; most recent is picked) produced by `cerefox backup`.").option("--dry-run", "Print what would be restored without writing.").option("-p, --project-name <name>", "Reserved for future use; currently ignored (project memberships ride along with each doc's metadata).").action(action23);
|
|
47667
47928
|
}
|
|
47668
47929
|
|
|
47669
47930
|
// src/cli/commands/search.ts
|
|
@@ -47688,7 +47949,7 @@ async function embedQuery(query) {
|
|
|
47688
47949
|
}
|
|
47689
47950
|
|
|
47690
47951
|
// src/cli/commands/search.ts
|
|
47691
|
-
async function
|
|
47952
|
+
async function action24(query, options) {
|
|
47692
47953
|
if (!query || query.trim() === "") {
|
|
47693
47954
|
throw userError("Empty query.");
|
|
47694
47955
|
}
|
|
@@ -47822,7 +48083,7 @@ async function action23(query, options) {
|
|
|
47822
48083
|
}
|
|
47823
48084
|
}
|
|
47824
48085
|
function registerSearch(program2) {
|
|
47825
|
-
program2.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: 0.7).", "0.7").option("--min-score <float>", "Minimum cosine similarity threshold.", "0.5").option("--max-bytes <n>", "Response size budget in bytes.", "200000").option("-r, --requestor <name>", "Agent / user name (recorded in usage log).").option("--json", "Emit machine-readable JSON instead of the default text.").action(
|
|
48086
|
+
program2.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: 0.7).", "0.7").option("--min-score <float>", "Minimum cosine similarity threshold.", "0.5").option("--max-bytes <n>", "Response size budget in bytes.", "200000").option("-r, --requestor <name>", "Agent / user name (recorded in usage log).").option("--json", "Emit machine-readable JSON instead of the default text.").action(action24);
|
|
47826
48087
|
}
|
|
47827
48088
|
|
|
47828
48089
|
// src/cli/commands/self-update.ts
|
|
@@ -47869,7 +48130,7 @@ async function fetchLatestVersion() {
|
|
|
47869
48130
|
}
|
|
47870
48131
|
return body.version;
|
|
47871
48132
|
}
|
|
47872
|
-
async function
|
|
48133
|
+
async function action25(options) {
|
|
47873
48134
|
let target;
|
|
47874
48135
|
try {
|
|
47875
48136
|
target = options.version ?? await fetchLatestVersion();
|
|
@@ -47921,7 +48182,7 @@ async function action24(options) {
|
|
|
47921
48182
|
}
|
|
47922
48183
|
function registerSelfUpdate(program2) {
|
|
47923
48184
|
const desc = "Upgrade Cerefox in place. Alias: `cerefox upgrade`.";
|
|
47924
|
-
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(
|
|
48185
|
+
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(action25);
|
|
47925
48186
|
declaration(program2.command("self-update"));
|
|
47926
48187
|
declaration(program2.command("upgrade"));
|
|
47927
48188
|
}
|
|
@@ -47940,7 +48201,7 @@ function symbol2(status) {
|
|
|
47940
48201
|
return cErr.dim("ℹ");
|
|
47941
48202
|
}
|
|
47942
48203
|
}
|
|
47943
|
-
async function
|
|
48204
|
+
async function action26(options) {
|
|
47944
48205
|
const useSpinner = !options.json && process.stderr.isTTY;
|
|
47945
48206
|
const spinner = useSpinner ? ora({ text: "Starting checks…", spinner: "dots", stream: process.stderr }).start() : null;
|
|
47946
48207
|
const results = await runFastChecks({
|
|
@@ -47961,7 +48222,7 @@ async function action25(options) {
|
|
|
47961
48222
|
}
|
|
47962
48223
|
}
|
|
47963
48224
|
function registerStatus(program2) {
|
|
47964
|
-
program2.command("status").description("Quick sanity check (fast subset of `cerefox doctor`).").option("--json", "Emit machine-readable JSON.").action(
|
|
48225
|
+
program2.command("status").description("Quick sanity check (fast subset of `cerefox doctor`).").option("--json", "Emit machine-readable JSON.").action(action26);
|
|
47965
48226
|
}
|
|
47966
48227
|
|
|
47967
48228
|
// src/cli/commands/sync-docs.ts
|
|
@@ -47975,14 +48236,14 @@ import {
|
|
|
47975
48236
|
readdirSync as readdirSync6,
|
|
47976
48237
|
statSync as statSync5
|
|
47977
48238
|
} from "node:fs";
|
|
47978
|
-
import { basename as basename5, extname as extname5, join as
|
|
48239
|
+
import { basename as basename5, extname as extname5, join as join11, relative } from "node:path";
|
|
47979
48240
|
var ROOT_LEVEL_DOCS = ["README.md", "AGENT_GUIDE.md", "AGENT_QUICK_REFERENCE.md"];
|
|
47980
48241
|
function walkMarkdown(dir) {
|
|
47981
48242
|
const out = [];
|
|
47982
48243
|
if (!existsSync11(dir))
|
|
47983
48244
|
return out;
|
|
47984
48245
|
for (const name of readdirSync6(dir)) {
|
|
47985
|
-
const full =
|
|
48246
|
+
const full = join11(dir, name);
|
|
47986
48247
|
let stat;
|
|
47987
48248
|
try {
|
|
47988
48249
|
stat = statSync5(full);
|
|
@@ -47997,16 +48258,16 @@ function walkMarkdown(dir) {
|
|
|
47997
48258
|
}
|
|
47998
48259
|
return out;
|
|
47999
48260
|
}
|
|
48000
|
-
async function
|
|
48261
|
+
async function action27(options) {
|
|
48001
48262
|
const cwd = process.cwd();
|
|
48002
48263
|
const project = options.project ?? "cerefox";
|
|
48003
48264
|
const targets = [];
|
|
48004
48265
|
for (const rel of ROOT_LEVEL_DOCS) {
|
|
48005
|
-
const abs =
|
|
48266
|
+
const abs = join11(cwd, rel);
|
|
48006
48267
|
if (existsSync11(abs))
|
|
48007
48268
|
targets.push({ abs, rel });
|
|
48008
48269
|
}
|
|
48009
|
-
for (const abs of walkMarkdown(
|
|
48270
|
+
for (const abs of walkMarkdown(join11(cwd, "docs"))) {
|
|
48010
48271
|
targets.push({ abs, rel: relative(cwd, abs) });
|
|
48011
48272
|
}
|
|
48012
48273
|
if (targets.length === 0) {
|
|
@@ -48059,7 +48320,7 @@ async function action26(options) {
|
|
|
48059
48320
|
}
|
|
48060
48321
|
}
|
|
48061
48322
|
function registerSyncDocs(program2) {
|
|
48062
|
-
program2.command("sync-docs").description("Sync repo docs (README, AGENT_*, docs/) into a Cerefox project.").option("--dry-run", "Print what would be synced without writing.").option("-p, --project <name>", "Target project for the sync.", "cerefox").action(
|
|
48323
|
+
program2.command("sync-docs").description("Sync repo docs (README, AGENT_*, docs/) into a Cerefox project.").option("--dry-run", "Print what would be synced without writing.").option("-p, --project <name>", "Target project for the sync.", "cerefox").action(action27);
|
|
48063
48324
|
}
|
|
48064
48325
|
|
|
48065
48326
|
// src/cli/program.ts
|
|
@@ -49395,7 +49656,7 @@ var baseMimes = _baseMimes;
|
|
|
49395
49656
|
|
|
49396
49657
|
// ../../node_modules/.bun/@hono+node-server@2.0.4+1bbe96acb4c5ebf1/node_modules/@hono/node-server/dist/serve-static.mjs
|
|
49397
49658
|
import { createReadStream, existsSync as existsSync12, statSync as statSync6 } from "node:fs";
|
|
49398
|
-
import { join as
|
|
49659
|
+
import { join as join12 } from "node:path";
|
|
49399
49660
|
var COMPRESSIBLE_CONTENT_TYPE_REGEX = /^\s*(?:text\/[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;
|
|
49400
49661
|
var ENCODINGS = {
|
|
49401
49662
|
br: ".br",
|
|
@@ -49444,11 +49705,11 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
49444
49705
|
await options.onNotFound?.(c2.req.path, c2);
|
|
49445
49706
|
return next();
|
|
49446
49707
|
}
|
|
49447
|
-
let path =
|
|
49708
|
+
let path = join12(root, !optionPath && options.rewriteRequestPath ? options.rewriteRequestPath(filename, c2) : filename);
|
|
49448
49709
|
let stats = getStats(path);
|
|
49449
49710
|
if (stats && stats.isDirectory()) {
|
|
49450
49711
|
const indexFile = options.index ?? "index.html";
|
|
49451
|
-
path =
|
|
49712
|
+
path = join12(path, indexFile);
|
|
49452
49713
|
stats = getStats(path);
|
|
49453
49714
|
}
|
|
49454
49715
|
if (!stats) {
|
|
@@ -49507,7 +49768,7 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
49507
49768
|
// src/web/server.ts
|
|
49508
49769
|
import { existsSync as existsSync15 } from "node:fs";
|
|
49509
49770
|
import { readFileSync as readFileSync14 } from "node:fs";
|
|
49510
|
-
import { join as
|
|
49771
|
+
import { join as join15 } from "node:path";
|
|
49511
49772
|
|
|
49512
49773
|
// ../../node_modules/.bun/hono@4.12.23/node_modules/hono/dist/compose.js
|
|
49513
49774
|
var compose = (middleware, onError, onNotFound) => {
|
|
@@ -51314,7 +51575,7 @@ function registerConfigRoutes(app, ctx) {
|
|
|
51314
51575
|
}
|
|
51315
51576
|
|
|
51316
51577
|
// src/web/routes/discovery.ts
|
|
51317
|
-
var
|
|
51578
|
+
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
51318
51579
|
var DOC_COLS = "id, title, source, source_path, content_hash, metadata, chunk_count, total_chars, review_status, created_at, updated_at, deleted_at";
|
|
51319
51580
|
function jsonByteLength(value) {
|
|
51320
51581
|
return Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
@@ -51760,7 +52021,7 @@ function registerDiscoveryRoutes(app, ctx) {
|
|
|
51760
52021
|
if (!path) {
|
|
51761
52022
|
return c2.json({ tried_path: "", anchor, matches: [] });
|
|
51762
52023
|
}
|
|
51763
|
-
if (
|
|
52024
|
+
if (UUID_RE2.test(path)) {
|
|
51764
52025
|
if (path === fromDocId) {
|
|
51765
52026
|
return c2.json({ tried_path: path, anchor, matches: [] });
|
|
51766
52027
|
}
|
|
@@ -52361,7 +52622,7 @@ import {
|
|
|
52361
52622
|
readdirSync as readdirSync7,
|
|
52362
52623
|
statSync as statSync7
|
|
52363
52624
|
} from "node:fs";
|
|
52364
|
-
import { basename as basename6, dirname as dirname5, join as
|
|
52625
|
+
import { basename as basename6, dirname as dirname5, join as join13, resolve as resolve5 } from "node:path";
|
|
52365
52626
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
52366
52627
|
var TOP_LEVEL_DOCS = [
|
|
52367
52628
|
{ filename: "README.md", path: "README.md", category: "readme" },
|
|
@@ -52382,27 +52643,27 @@ function moduleDir2() {
|
|
|
52382
52643
|
function resolveDocsRoots() {
|
|
52383
52644
|
const here = moduleDir2();
|
|
52384
52645
|
const pkgRootCandidates = [
|
|
52385
|
-
|
|
52386
|
-
|
|
52646
|
+
join13(here, "..", ".."),
|
|
52647
|
+
join13(here, "..", "..", "..", "..")
|
|
52387
52648
|
];
|
|
52388
52649
|
let pkgGuides = null;
|
|
52389
52650
|
let pkgTopLevel = null;
|
|
52390
52651
|
for (const pkg of pkgRootCandidates) {
|
|
52391
|
-
const guides =
|
|
52652
|
+
const guides = join13(pkg, "docs", "guides");
|
|
52392
52653
|
if (existsSync13(guides) && statSync7(guides).isDirectory()) {
|
|
52393
52654
|
pkgGuides = guides;
|
|
52394
52655
|
pkgTopLevel = pkg;
|
|
52395
52656
|
break;
|
|
52396
52657
|
}
|
|
52397
52658
|
}
|
|
52398
|
-
const repoCandidate =
|
|
52399
|
-
const repoGuides =
|
|
52659
|
+
const repoCandidate = join13(here, "..", "..", "..", "..");
|
|
52660
|
+
const repoGuides = join13(repoCandidate, "docs", "guides");
|
|
52400
52661
|
const repoTopLevel = repoCandidate;
|
|
52401
52662
|
return {
|
|
52402
52663
|
pkgGuides,
|
|
52403
52664
|
pkgTopLevel,
|
|
52404
52665
|
repoGuides: existsSync13(repoGuides) ? repoGuides : null,
|
|
52405
|
-
repoTopLevel: existsSync13(
|
|
52666
|
+
repoTopLevel: existsSync13(join13(repoTopLevel, "README.md")) ? repoTopLevel : null
|
|
52406
52667
|
};
|
|
52407
52668
|
}
|
|
52408
52669
|
function readH1(filePath) {
|
|
@@ -52427,7 +52688,7 @@ function listBundledDocs2() {
|
|
|
52427
52688
|
const topRoot = pkgTopLevel ?? repoTopLevel;
|
|
52428
52689
|
if (topRoot) {
|
|
52429
52690
|
for (const t of TOP_LEVEL_DOCS) {
|
|
52430
|
-
const abs =
|
|
52691
|
+
const abs = join13(topRoot, t.filename);
|
|
52431
52692
|
if (existsSync13(abs)) {
|
|
52432
52693
|
entries.push(entryForFile(abs, t.path, t.category));
|
|
52433
52694
|
}
|
|
@@ -52437,7 +52698,7 @@ function listBundledDocs2() {
|
|
|
52437
52698
|
if (guidesRoot) {
|
|
52438
52699
|
const names = readdirSync7(guidesRoot).filter((n) => n.endsWith(".md")).sort();
|
|
52439
52700
|
for (const name of names) {
|
|
52440
|
-
const abs =
|
|
52701
|
+
const abs = join13(guidesRoot, name);
|
|
52441
52702
|
entries.push(entryForFile(abs, `guides/${name}`, "guide"));
|
|
52442
52703
|
}
|
|
52443
52704
|
}
|
|
@@ -52482,7 +52743,7 @@ var VERSION_INFO = {
|
|
|
52482
52743
|
git_commit_short: resolveGitCommitShort(),
|
|
52483
52744
|
build_date: process.env.CEREFOX_BUILD_DATE ?? null
|
|
52484
52745
|
};
|
|
52485
|
-
var
|
|
52746
|
+
var SCHEMA_VERSION_RE2 = /^--\s*@version:\s*(\S+)/m;
|
|
52486
52747
|
function registerMetaRoutes(app, ctx) {
|
|
52487
52748
|
app.get("/api/v1/version", (c2) => c2.json(VERSION_INFO));
|
|
52488
52749
|
app.get("/api/v1/docs", (c2) => c2.json(listBundledDocs2()));
|
|
@@ -52501,16 +52762,16 @@ function registerMetaRoutes(app, ctx) {
|
|
|
52501
52762
|
try {
|
|
52502
52763
|
const { readFileSync: readFileSync14, existsSync: existsSync14 } = await import("node:fs");
|
|
52503
52764
|
const { fileURLToPath: fileURLToPath4 } = await import("node:url");
|
|
52504
|
-
const { dirname: dirname6, join:
|
|
52765
|
+
const { dirname: dirname6, join: join14 } = await import("node:path");
|
|
52505
52766
|
const here = dirname6(fileURLToPath4(import.meta.url));
|
|
52506
52767
|
const candidates = [
|
|
52507
|
-
|
|
52508
|
-
|
|
52768
|
+
join14(here, "..", "..", "..", "db", "schema.sql"),
|
|
52769
|
+
join14(here, "..", "..", "..", "..", "..", "src", "cerefox", "db", "schema.sql")
|
|
52509
52770
|
];
|
|
52510
52771
|
for (const path of candidates) {
|
|
52511
52772
|
if (existsSync14(path)) {
|
|
52512
52773
|
const sql = readFileSync14(path, "utf8");
|
|
52513
|
-
const match2 = sql.match(
|
|
52774
|
+
const match2 = sql.match(SCHEMA_VERSION_RE2);
|
|
52514
52775
|
bundled = match2 ? match2[1] : null;
|
|
52515
52776
|
break;
|
|
52516
52777
|
}
|
|
@@ -52620,20 +52881,20 @@ function registerProjectsRoutes(app, ctx) {
|
|
|
52620
52881
|
|
|
52621
52882
|
// src/web/static.ts
|
|
52622
52883
|
import { existsSync as existsSync14, statSync as statSync8 } from "node:fs";
|
|
52623
|
-
import { dirname as dirname6, join as
|
|
52884
|
+
import { dirname as dirname6, join as join14 } from "node:path";
|
|
52624
52885
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
52625
52886
|
function moduleDir3() {
|
|
52626
52887
|
return dirname6(fileURLToPath4(import.meta.url));
|
|
52627
52888
|
}
|
|
52628
52889
|
function isUsableSpaDir(dir) {
|
|
52629
|
-
return existsSync14(dir) && statSync8(dir).isDirectory() && existsSync14(
|
|
52890
|
+
return existsSync14(dir) && statSync8(dir).isDirectory() && existsSync14(join14(dir, "index.html"));
|
|
52630
52891
|
}
|
|
52631
52892
|
function resolveSpaDist() {
|
|
52632
52893
|
const here = moduleDir3();
|
|
52633
52894
|
const candidates = [
|
|
52634
|
-
|
|
52635
|
-
|
|
52636
|
-
|
|
52895
|
+
join14(here, "..", "frontend"),
|
|
52896
|
+
join14(here, "..", "..", "..", "..", "frontend", "dist"),
|
|
52897
|
+
join14(here, "..", "..", "dist", "frontend")
|
|
52637
52898
|
];
|
|
52638
52899
|
for (const c2 of candidates) {
|
|
52639
52900
|
if (isUsableSpaDir(c2))
|
|
@@ -52644,8 +52905,8 @@ function resolveSpaDist() {
|
|
|
52644
52905
|
function resolveStaticDir() {
|
|
52645
52906
|
const here = moduleDir3();
|
|
52646
52907
|
const candidates = [
|
|
52647
|
-
|
|
52648
|
-
|
|
52908
|
+
join14(here, "..", "static"),
|
|
52909
|
+
join14(here, "..", "..", "..", "..", "web", "static")
|
|
52649
52910
|
];
|
|
52650
52911
|
for (const c2 of candidates) {
|
|
52651
52912
|
if (existsSync14(c2) && statSync8(c2).isDirectory())
|
|
@@ -52691,11 +52952,12 @@ var ROOT_REDIRECT_HTML = `<!DOCTYPE html>
|
|
|
52691
52952
|
|
|
52692
52953
|
// src/web/server.ts
|
|
52693
52954
|
init_meta();
|
|
52955
|
+
init_cli_core();
|
|
52694
52956
|
init_config();
|
|
52695
52957
|
function buildApp(ctx = buildWebContext()) {
|
|
52696
52958
|
const app = new Hono2;
|
|
52697
52959
|
if (true) {
|
|
52698
|
-
app.use(logger());
|
|
52960
|
+
app.use(logger((message, ...rest) => console.log(`${localTimestamp()} ${message}`, ...rest)));
|
|
52699
52961
|
}
|
|
52700
52962
|
registerMetaRoutes(app, ctx);
|
|
52701
52963
|
if (ctx) {
|
|
@@ -52731,7 +52993,7 @@ function buildApp(ctx = buildWebContext()) {
|
|
|
52731
52993
|
root: spaDist,
|
|
52732
52994
|
rewriteRequestPath: (path) => path.replace(/^\/app/, "") || "/"
|
|
52733
52995
|
}));
|
|
52734
|
-
const indexPath =
|
|
52996
|
+
const indexPath = join15(spaDist, "index.html");
|
|
52735
52997
|
if (existsSync15(indexPath)) {
|
|
52736
52998
|
const indexHtml = readFileSync14(indexPath, "utf8");
|
|
52737
52999
|
app.get("/app/*", (c2) => c2.html(indexHtml));
|
|
@@ -52752,7 +53014,7 @@ async function assertServerCompatible() {
|
|
|
52752
53014
|
compat2 = await checkServerCompatibility({
|
|
52753
53015
|
aggregatorUrl: aggregatorUrlFor(settings.supabaseUrl),
|
|
52754
53016
|
bearer: settings.supabaseAnonKey,
|
|
52755
|
-
bundledEf:
|
|
53017
|
+
bundledEf: EF_VERSION
|
|
52756
53018
|
});
|
|
52757
53019
|
} catch {
|
|
52758
53020
|
return;
|
|
@@ -52799,10 +53061,10 @@ import {
|
|
|
52799
53061
|
writeFileSync as writeFileSync4
|
|
52800
53062
|
} from "node:fs";
|
|
52801
53063
|
import { homedir as homedir7 } from "node:os";
|
|
52802
|
-
import { join as
|
|
52803
|
-
var STATE_DIR =
|
|
52804
|
-
var PID_FILE =
|
|
52805
|
-
var LOG_FILE =
|
|
53064
|
+
import { join as join16 } from "node:path";
|
|
53065
|
+
var STATE_DIR = join16(homedir7(), ".cerefox");
|
|
53066
|
+
var PID_FILE = join16(STATE_DIR, "web.pid");
|
|
53067
|
+
var LOG_FILE = join16(STATE_DIR, "web.log");
|
|
52806
53068
|
var daemonPaths = { stateDir: STATE_DIR, pidFile: PID_FILE, logFile: LOG_FILE };
|
|
52807
53069
|
function ensureStateDir() {
|
|
52808
53070
|
if (!existsSync16(STATE_DIR))
|
|
@@ -52950,11 +53212,11 @@ async function runForeground(host, port, watch) {
|
|
|
52950
53212
|
}
|
|
52951
53213
|
try {
|
|
52952
53214
|
const handle = await buildWebServer({ host, port });
|
|
52953
|
-
|
|
53215
|
+
println(`${localTimestamp()} Cerefox web listening on http://${handle.host}:${handle.port}/`);
|
|
52954
53216
|
println(` Web UI: http://${handle.host}:${handle.port}/app/`);
|
|
52955
53217
|
println(` API: http://${handle.host}:${handle.port}/api/v1/`);
|
|
52956
53218
|
const shutdown = async (signal) => {
|
|
52957
|
-
|
|
53219
|
+
println(`${localTimestamp()} Received ${signal}; shutting down.`);
|
|
52958
53220
|
await handle.close().catch(() => {});
|
|
52959
53221
|
process.exit(0);
|
|
52960
53222
|
};
|
|
@@ -53056,7 +53318,7 @@ function buildProgram() {
|
|
|
53056
53318
|
Command groups (each row in the list above falls into one):
|
|
53057
53319
|
` + ` READS search · get-doc · list-docs · list-versions · list-projects
|
|
53058
53320
|
` + ` · list-metadata-keys · metadata-search · get-audit-log
|
|
53059
|
-
` + ` WRITES ingest · ingest-dir · delete-doc
|
|
53321
|
+
` + ` WRITES ingest · ingest-dir · delete-doc · delete-project
|
|
53060
53322
|
` + ` SERVERS mcp · web
|
|
53061
53323
|
` + ` LIFECYCLE init · doctor · status · configure-agent · self-update · upgrade · sync-self-docs · deploy-server
|
|
53062
53324
|
` + ` OPS backup · restore · sync-docs · docs · reindex · config-get · config-set · completion
|
|
@@ -53081,6 +53343,7 @@ Learn more:
|
|
|
53081
53343
|
registerIngest(program2);
|
|
53082
53344
|
registerIngestDir(program2);
|
|
53083
53345
|
registerDeleteDoc(program2);
|
|
53346
|
+
registerDeleteProject(program2);
|
|
53084
53347
|
registerMcp(program2);
|
|
53085
53348
|
registerWeb(program2);
|
|
53086
53349
|
registerInit(program2);
|