@cerefox/memory 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -25
- package/dist/bin/cerefox.js +1163 -344
- package/dist/frontend/assets/{index-HNlMcvli.js → index-CAp2_lFX.js} +2 -2
- package/dist/frontend/assets/index-CAp2_lFX.js.map +1 -0
- package/dist/frontend/index.html +1 -1
- package/dist/server-assets/_shared/ef-meta/index.ts +97 -0
- package/dist/server-assets/_shared/embeddings/index.ts +175 -0
- package/dist/server-assets/_shared/mcp-tools/_chunker.ts +187 -0
- package/dist/server-assets/_shared/mcp-tools/_projects.ts +121 -0
- package/dist/server-assets/_shared/mcp-tools/_utils.ts +73 -0
- package/dist/server-assets/_shared/mcp-tools/audit-log.ts +95 -0
- package/dist/server-assets/_shared/mcp-tools/get-document.ts +73 -0
- package/dist/server-assets/_shared/mcp-tools/get-help-content.ts +26 -0
- package/dist/server-assets/_shared/mcp-tools/get-help.ts +90 -0
- package/dist/server-assets/_shared/mcp-tools/index.ts +67 -0
- package/dist/server-assets/_shared/mcp-tools/ingest.ts +315 -0
- package/dist/server-assets/_shared/mcp-tools/list-metadata-keys.ts +55 -0
- package/dist/server-assets/_shared/mcp-tools/list-projects.ts +59 -0
- package/dist/server-assets/_shared/mcp-tools/list-versions.ts +72 -0
- package/dist/server-assets/_shared/mcp-tools/metadata-search.ts +154 -0
- package/dist/server-assets/_shared/mcp-tools/search.ts +193 -0
- package/dist/server-assets/_shared/mcp-tools/set-document-projects.ts +163 -0
- package/dist/server-assets/_shared/mcp-tools/types.ts +92 -0
- package/dist/server-assets/db/migrations/0003_add_document_versions.sql +91 -0
- package/dist/server-assets/db/migrations/0004_add_audit_log_review_status_archived.sql +71 -0
- package/dist/server-assets/db/migrations/0005_metadata_search.sql +628 -0
- package/dist/server-assets/db/migrations/0006_usage_log.sql +255 -0
- package/dist/server-assets/db/migrations/0007_usage_log_requestor.sql +178 -0
- package/dist/server-assets/db/migrations/0008_soft_delete.sql +130 -0
- package/dist/server-assets/db/migrations/0009_audit_log_restore_operation.sql +20 -0
- package/dist/server-assets/db/migrations/0010_requestor_enforcement_config.sql +12 -0
- package/dist/server-assets/db/migrations/0011_title_boosting.sql +48 -0
- package/dist/server-assets/db/rpcs.sql +1723 -0
- package/dist/server-assets/db/schema.sql +380 -0
- package/dist/server-assets/supabase/functions/cerefox-get-audit-log/index.ts +117 -0
- package/dist/server-assets/supabase/functions/cerefox-get-document/index.ts +138 -0
- package/dist/server-assets/supabase/functions/cerefox-ingest/index.ts +819 -0
- package/dist/server-assets/supabase/functions/cerefox-list-projects/index.ts +96 -0
- package/dist/server-assets/supabase/functions/cerefox-list-versions/index.ts +113 -0
- package/dist/server-assets/supabase/functions/cerefox-mcp/index.ts +294 -0
- package/dist/server-assets/supabase/functions/cerefox-mcp/shared.ts +42 -0
- package/dist/server-assets/supabase/functions/cerefox-metadata/index.ts +99 -0
- package/dist/server-assets/supabase/functions/cerefox-metadata-search/index.ts +146 -0
- package/dist/server-assets/supabase/functions/cerefox-search/index.ts +382 -0
- package/docs/guides/connect-agents.md +58 -3
- package/docs/guides/migration-v0.5.md +50 -0
- package/package.json +3 -2
- package/dist/frontend/assets/index-HNlMcvli.js.map +0 -1
package/dist/bin/cerefox.js
CHANGED
|
@@ -7179,7 +7179,7 @@ var exports_meta = {};
|
|
|
7179
7179
|
__export(exports_meta, {
|
|
7180
7180
|
PKG_VERSION: () => PKG_VERSION
|
|
7181
7181
|
});
|
|
7182
|
-
var PKG_VERSION = "0.
|
|
7182
|
+
var PKG_VERSION = "0.8.0";
|
|
7183
7183
|
var init_meta = () => {};
|
|
7184
7184
|
|
|
7185
7185
|
// ../../node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.js
|
|
@@ -22585,6 +22585,7 @@ function loadSettings(opts = {}) {
|
|
|
22585
22585
|
return {
|
|
22586
22586
|
supabaseUrl: env2.CEREFOX_SUPABASE_URL ?? "",
|
|
22587
22587
|
supabaseKey: env2.CEREFOX_SUPABASE_KEY ?? "",
|
|
22588
|
+
supabaseAnonKey: env2.CEREFOX_SUPABASE_ANON_KEY ?? "",
|
|
22588
22589
|
databaseUrl: env2.CEREFOX_DATABASE_URL ?? "",
|
|
22589
22590
|
openaiApiKey: env2.CEREFOX_OPENAI_API_KEY ?? env2.OPENAI_API_KEY ?? "",
|
|
22590
22591
|
fireworksApiKey: env2.CEREFOX_FIREWORKS_API_KEY ?? ""
|
|
@@ -22631,99 +22632,6 @@ var init_client = __esm(() => {
|
|
|
22631
22632
|
init_cli_core();
|
|
22632
22633
|
});
|
|
22633
22634
|
|
|
22634
|
-
// src/cli/util/bundled-docs.ts
|
|
22635
|
-
import { existsSync as existsSync4, readdirSync, readFileSync as readFileSync4, statSync } from "node:fs";
|
|
22636
|
-
import { dirname as dirname2, join as join4, resolve as resolve2 } from "node:path";
|
|
22637
|
-
import { fileURLToPath } from "node:url";
|
|
22638
|
-
function findPackageRoot() {
|
|
22639
|
-
let dir = dirname2(fileURLToPath(import.meta.url));
|
|
22640
|
-
for (let i = 0;i < 10; i++) {
|
|
22641
|
-
const pkgJson = join4(dir, "package.json");
|
|
22642
|
-
if (existsSync4(pkgJson)) {
|
|
22643
|
-
try {
|
|
22644
|
-
const parsed = JSON.parse(readFileSync4(pkgJson, "utf8"));
|
|
22645
|
-
if (parsed.name === "@cerefox/memory")
|
|
22646
|
-
return dir;
|
|
22647
|
-
} catch {}
|
|
22648
|
-
}
|
|
22649
|
-
const parent = dirname2(dir);
|
|
22650
|
-
if (parent === dir)
|
|
22651
|
-
break;
|
|
22652
|
-
dir = parent;
|
|
22653
|
-
}
|
|
22654
|
-
return resolve2(dirname2(fileURLToPath(import.meta.url)), "..", "..", "..");
|
|
22655
|
-
}
|
|
22656
|
-
function bundledDocsDir() {
|
|
22657
|
-
const inPackage = join4(PACKAGE_ROOT, "docs");
|
|
22658
|
-
if (existsSync4(inPackage))
|
|
22659
|
-
return inPackage;
|
|
22660
|
-
return resolve2(PACKAGE_ROOT, "..", "..", "docs");
|
|
22661
|
-
}
|
|
22662
|
-
function agentGuidePath() {
|
|
22663
|
-
const candidates = [
|
|
22664
|
-
join4(PACKAGE_ROOT, "AGENT_GUIDE.md"),
|
|
22665
|
-
resolve2(PACKAGE_ROOT, "..", "..", "AGENT_GUIDE.md")
|
|
22666
|
-
];
|
|
22667
|
-
for (const c2 of candidates)
|
|
22668
|
-
if (existsSync4(c2))
|
|
22669
|
-
return c2;
|
|
22670
|
-
return null;
|
|
22671
|
-
}
|
|
22672
|
-
function agentQuickReferencePath() {
|
|
22673
|
-
const candidates = [
|
|
22674
|
-
join4(PACKAGE_ROOT, "AGENT_QUICK_REFERENCE.md"),
|
|
22675
|
-
resolve2(PACKAGE_ROOT, "..", "..", "AGENT_QUICK_REFERENCE.md")
|
|
22676
|
-
];
|
|
22677
|
-
for (const c2 of candidates)
|
|
22678
|
-
if (existsSync4(c2))
|
|
22679
|
-
return c2;
|
|
22680
|
-
return null;
|
|
22681
|
-
}
|
|
22682
|
-
function listBundledDocs() {
|
|
22683
|
-
const entries = [];
|
|
22684
|
-
const docsDir = bundledDocsDir();
|
|
22685
|
-
const guidesDir = join4(docsDir, "guides");
|
|
22686
|
-
if (existsSync4(guidesDir) && statSync(guidesDir).isDirectory()) {
|
|
22687
|
-
for (const name of readdirSync(guidesDir)) {
|
|
22688
|
-
if (!name.endsWith(".md"))
|
|
22689
|
-
continue;
|
|
22690
|
-
const full = join4(guidesDir, name);
|
|
22691
|
-
entries.push({
|
|
22692
|
-
topic: name.replace(/\.md$/, ""),
|
|
22693
|
-
path: full,
|
|
22694
|
-
size: statSync(full).size
|
|
22695
|
-
});
|
|
22696
|
-
}
|
|
22697
|
-
}
|
|
22698
|
-
const ag = agentGuidePath();
|
|
22699
|
-
if (ag)
|
|
22700
|
-
entries.push({ topic: "agent-guide", path: ag, size: statSync(ag).size });
|
|
22701
|
-
const aqr = agentQuickReferencePath();
|
|
22702
|
-
if (aqr) {
|
|
22703
|
-
entries.push({
|
|
22704
|
-
topic: "agent-quick-reference",
|
|
22705
|
-
path: aqr,
|
|
22706
|
-
size: statSync(aqr).size
|
|
22707
|
-
});
|
|
22708
|
-
}
|
|
22709
|
-
entries.sort((a, b) => a.topic.localeCompare(b.topic));
|
|
22710
|
-
return entries;
|
|
22711
|
-
}
|
|
22712
|
-
function readBundledDoc(topic) {
|
|
22713
|
-
const entry = listBundledDocs().find((d) => d.topic === topic);
|
|
22714
|
-
if (!entry)
|
|
22715
|
-
return null;
|
|
22716
|
-
return {
|
|
22717
|
-
topic: entry.topic,
|
|
22718
|
-
path: entry.path,
|
|
22719
|
-
content: readFileSync4(entry.path, "utf8")
|
|
22720
|
-
};
|
|
22721
|
-
}
|
|
22722
|
-
var PACKAGE_ROOT;
|
|
22723
|
-
var init_bundled_docs = __esm(() => {
|
|
22724
|
-
PACKAGE_ROOT = findPackageRoot();
|
|
22725
|
-
});
|
|
22726
|
-
|
|
22727
22635
|
// ../../node_modules/.bun/postgres@3.4.9/node_modules/postgres/src/query.js
|
|
22728
22636
|
function cachedError(xs) {
|
|
22729
22637
|
if (originCache.has(xs))
|
|
@@ -22742,9 +22650,9 @@ var init_query = __esm(() => {
|
|
|
22742
22650
|
CLOSE = {};
|
|
22743
22651
|
Query = class Query extends Promise {
|
|
22744
22652
|
constructor(strings, args, handler, canceller, options = {}) {
|
|
22745
|
-
let
|
|
22653
|
+
let resolve2, reject;
|
|
22746
22654
|
super((a, b) => {
|
|
22747
|
-
|
|
22655
|
+
resolve2 = a;
|
|
22748
22656
|
reject = b;
|
|
22749
22657
|
});
|
|
22750
22658
|
this.tagged = Array.isArray(strings.raw);
|
|
@@ -22755,7 +22663,7 @@ var init_query = __esm(() => {
|
|
|
22755
22663
|
this.options = options;
|
|
22756
22664
|
this.state = null;
|
|
22757
22665
|
this.statement = null;
|
|
22758
|
-
this.resolve = (x) => (this.active = false,
|
|
22666
|
+
this.resolve = (x) => (this.active = false, resolve2(x));
|
|
22759
22667
|
this.reject = (x) => (this.active = false, reject(x));
|
|
22760
22668
|
this.active = false;
|
|
22761
22669
|
this.cancelled = null;
|
|
@@ -22803,12 +22711,12 @@ var init_query = __esm(() => {
|
|
|
22803
22711
|
if (this.executed && !this.active)
|
|
22804
22712
|
return { done: true };
|
|
22805
22713
|
prev && prev();
|
|
22806
|
-
const promise = new Promise((
|
|
22714
|
+
const promise = new Promise((resolve2, reject) => {
|
|
22807
22715
|
this.cursorFn = (value) => {
|
|
22808
|
-
|
|
22716
|
+
resolve2({ value, done: false });
|
|
22809
22717
|
return new Promise((r) => prev = r);
|
|
22810
22718
|
};
|
|
22811
|
-
this.resolve = () => (this.active = false,
|
|
22719
|
+
this.resolve = () => (this.active = false, resolve2({ done: true }));
|
|
22812
22720
|
this.reject = (x) => (this.active = false, reject(x));
|
|
22813
22721
|
});
|
|
22814
22722
|
this.execute();
|
|
@@ -22867,31 +22775,31 @@ var init_query = __esm(() => {
|
|
|
22867
22775
|
// ../../node_modules/.bun/postgres@3.4.9/node_modules/postgres/src/errors.js
|
|
22868
22776
|
function connection(x, options, socket) {
|
|
22869
22777
|
const { host, port } = socket || options;
|
|
22870
|
-
const
|
|
22778
|
+
const error = Object.assign(new Error("write " + x + " " + (options.path || host + ":" + port)), {
|
|
22871
22779
|
code: x,
|
|
22872
22780
|
errno: x,
|
|
22873
22781
|
address: options.path || host
|
|
22874
22782
|
}, options.path ? {} : { port });
|
|
22875
|
-
Error.captureStackTrace(
|
|
22876
|
-
return
|
|
22783
|
+
Error.captureStackTrace(error, connection);
|
|
22784
|
+
return error;
|
|
22877
22785
|
}
|
|
22878
22786
|
function postgres(x) {
|
|
22879
|
-
const
|
|
22880
|
-
Error.captureStackTrace(
|
|
22881
|
-
return
|
|
22787
|
+
const error = new PostgresError(x);
|
|
22788
|
+
Error.captureStackTrace(error, postgres);
|
|
22789
|
+
return error;
|
|
22882
22790
|
}
|
|
22883
22791
|
function generic(code, message) {
|
|
22884
|
-
const
|
|
22885
|
-
Error.captureStackTrace(
|
|
22886
|
-
return
|
|
22792
|
+
const error = Object.assign(new Error(code + ": " + message), { code });
|
|
22793
|
+
Error.captureStackTrace(error, generic);
|
|
22794
|
+
return error;
|
|
22887
22795
|
}
|
|
22888
22796
|
function notSupported(x) {
|
|
22889
|
-
const
|
|
22797
|
+
const error = Object.assign(new Error(x + " (B) is not supported"), {
|
|
22890
22798
|
code: "MESSAGE_NOT_SUPPORTED",
|
|
22891
22799
|
name: x
|
|
22892
22800
|
});
|
|
22893
|
-
Error.captureStackTrace(
|
|
22894
|
-
return
|
|
22801
|
+
Error.captureStackTrace(error, notSupported);
|
|
22802
|
+
return error;
|
|
22895
22803
|
}
|
|
22896
22804
|
var PostgresError, Errors;
|
|
22897
22805
|
var init_errors2 = __esm(() => {
|
|
@@ -23239,7 +23147,7 @@ function fit(x) {
|
|
|
23239
23147
|
prev.copy(buffer);
|
|
23240
23148
|
}
|
|
23241
23149
|
}
|
|
23242
|
-
function
|
|
23150
|
+
function reset() {
|
|
23243
23151
|
b.i = 0;
|
|
23244
23152
|
return b;
|
|
23245
23153
|
}
|
|
@@ -23255,7 +23163,7 @@ var init_bytes = __esm(() => {
|
|
|
23255
23163
|
};
|
|
23256
23164
|
return acc;
|
|
23257
23165
|
}, {});
|
|
23258
|
-
b = Object.assign(
|
|
23166
|
+
b = Object.assign(reset, messages, {
|
|
23259
23167
|
N: String.fromCharCode(0),
|
|
23260
23168
|
i: 0,
|
|
23261
23169
|
inc(x) {
|
|
@@ -23354,22 +23262,22 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
23354
23262
|
try {
|
|
23355
23263
|
x = options.socket ? await Promise.resolve(options.socket(options)) : new net.Socket;
|
|
23356
23264
|
} catch (e) {
|
|
23357
|
-
|
|
23265
|
+
error(e);
|
|
23358
23266
|
return;
|
|
23359
23267
|
}
|
|
23360
|
-
x.on("error",
|
|
23268
|
+
x.on("error", error);
|
|
23361
23269
|
x.on("close", closed);
|
|
23362
23270
|
x.on("drain", drain);
|
|
23363
23271
|
return x;
|
|
23364
23272
|
}
|
|
23365
|
-
async function cancel({ pid, secret },
|
|
23273
|
+
async function cancel({ pid, secret }, resolve2, reject) {
|
|
23366
23274
|
try {
|
|
23367
23275
|
cancelMessage = bytes_default().i32(16).i32(80877102).i32(pid).i32(secret).end(16);
|
|
23368
23276
|
await connect();
|
|
23369
23277
|
socket.once("error", reject);
|
|
23370
|
-
socket.once("close",
|
|
23371
|
-
} catch (
|
|
23372
|
-
reject(
|
|
23278
|
+
socket.once("close", resolve2);
|
|
23279
|
+
} catch (error2) {
|
|
23280
|
+
reject(error2);
|
|
23373
23281
|
}
|
|
23374
23282
|
}
|
|
23375
23283
|
function execute(q) {
|
|
@@ -23384,9 +23292,9 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
23384
23292
|
query ? sent.push(q) : (query = q, query.active = true);
|
|
23385
23293
|
build(q);
|
|
23386
23294
|
return write(toBuffer(q)) && !q.describeFirst && !q.cursorFn && sent.length < max_pipeline && (!q.options.onexecute || q.options.onexecute(connection2));
|
|
23387
|
-
} catch (
|
|
23295
|
+
} catch (error2) {
|
|
23388
23296
|
sent.length === 0 && write(Sync);
|
|
23389
|
-
errored(
|
|
23297
|
+
errored(error2);
|
|
23390
23298
|
return true;
|
|
23391
23299
|
}
|
|
23392
23300
|
}
|
|
@@ -23465,7 +23373,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
23465
23373
|
socket.removeAllListeners();
|
|
23466
23374
|
socket = tls.connect(options2);
|
|
23467
23375
|
socket.on("secureConnect", connected);
|
|
23468
|
-
socket.on("error",
|
|
23376
|
+
socket.on("error", error);
|
|
23469
23377
|
socket.on("close", closed);
|
|
23470
23378
|
socket.on("drain", drain);
|
|
23471
23379
|
}
|
|
@@ -23531,10 +23439,10 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
23531
23439
|
const s = StartupMessage();
|
|
23532
23440
|
write(s);
|
|
23533
23441
|
} catch (err) {
|
|
23534
|
-
|
|
23442
|
+
error(err);
|
|
23535
23443
|
}
|
|
23536
23444
|
}
|
|
23537
|
-
function
|
|
23445
|
+
function error(err) {
|
|
23538
23446
|
if (connection2.queue === queues.connecting && options.host[retries + 1])
|
|
23539
23447
|
return;
|
|
23540
23448
|
errored(err);
|
|
@@ -23567,7 +23475,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
23567
23475
|
function terminate() {
|
|
23568
23476
|
terminated = true;
|
|
23569
23477
|
if (stream || query || initial || sent.length)
|
|
23570
|
-
|
|
23478
|
+
error(Errors.connection("CONNECTION_DESTROYED", options));
|
|
23571
23479
|
clearImmediate(nextWriteTimer);
|
|
23572
23480
|
if (socket) {
|
|
23573
23481
|
socket.removeListener("data", data);
|
|
@@ -23590,7 +23498,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
23590
23498
|
socket = null;
|
|
23591
23499
|
if (initial)
|
|
23592
23500
|
return reconnect();
|
|
23593
|
-
!hadError && (query || sent.length) &&
|
|
23501
|
+
!hadError && (query || sent.length) && error(Errors.connection("CONNECTION_CLOSED", options, socket));
|
|
23594
23502
|
closedTime = performance.now();
|
|
23595
23503
|
hadError && options.shared.retries++;
|
|
23596
23504
|
delay = (typeof backoff === "function" ? backoff(options.shared.retries) : backoff) * 1000;
|
|
@@ -23814,9 +23722,9 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
23814
23722
|
errored(Errors.postgres(parseError(x)));
|
|
23815
23723
|
}
|
|
23816
23724
|
}
|
|
23817
|
-
function retry(q,
|
|
23725
|
+
function retry(q, error2) {
|
|
23818
23726
|
delete statements[q.signature];
|
|
23819
|
-
q.retried =
|
|
23727
|
+
q.retried = error2;
|
|
23820
23728
|
execute(q);
|
|
23821
23729
|
}
|
|
23822
23730
|
function NotificationResponse(x) {
|
|
@@ -23847,9 +23755,9 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
23847
23755
|
write(chunk2, encoding, callback) {
|
|
23848
23756
|
socket.write(bytes_default().d().raw(chunk2).end(), callback);
|
|
23849
23757
|
},
|
|
23850
|
-
destroy(
|
|
23851
|
-
callback(
|
|
23852
|
-
socket.write(bytes_default().f().str(
|
|
23758
|
+
destroy(error2, callback) {
|
|
23759
|
+
callback(error2);
|
|
23760
|
+
socket.write(bytes_default().f().str(error2 + bytes_default.N).end());
|
|
23853
23761
|
stream = null;
|
|
23854
23762
|
},
|
|
23855
23763
|
final(callback) {
|
|
@@ -23877,9 +23785,9 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
23877
23785
|
write(chunk2, encoding, callback) {
|
|
23878
23786
|
socket.write(bytes_default().d().raw(chunk2).end(), callback);
|
|
23879
23787
|
},
|
|
23880
|
-
destroy(
|
|
23881
|
-
callback(
|
|
23882
|
-
socket.write(bytes_default().f().str(
|
|
23788
|
+
destroy(error2, callback) {
|
|
23789
|
+
callback(error2);
|
|
23790
|
+
socket.write(bytes_default().f().str(error2 + bytes_default.N).end());
|
|
23883
23791
|
stream = null;
|
|
23884
23792
|
},
|
|
23885
23793
|
final(callback) {
|
|
@@ -23955,15 +23863,15 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
23955
23863
|
}
|
|
23956
23864
|
}
|
|
23957
23865
|
function parseError(x) {
|
|
23958
|
-
const
|
|
23866
|
+
const error = {};
|
|
23959
23867
|
let start = 5;
|
|
23960
23868
|
for (let i = 5;i < x.length - 1; i++) {
|
|
23961
23869
|
if (x[i] === 0) {
|
|
23962
|
-
|
|
23870
|
+
error[errorFields[x[start]]] = x.toString("utf8", start + 1, i);
|
|
23963
23871
|
start = i + 1;
|
|
23964
23872
|
}
|
|
23965
23873
|
}
|
|
23966
|
-
return
|
|
23874
|
+
return error;
|
|
23967
23875
|
}
|
|
23968
23876
|
function md5(x) {
|
|
23969
23877
|
return crypto2.createHash("md5").update(x).digest("hex");
|
|
@@ -24109,10 +24017,10 @@ function Subscribe(postgres2, options) {
|
|
|
24109
24017
|
lsn: Buffer.concat(x.consistent_point.split("/").map((x2) => Buffer.from(("00000000" + x2).slice(-8), "hex")))
|
|
24110
24018
|
};
|
|
24111
24019
|
stream2.on("data", data);
|
|
24112
|
-
stream2.on("error",
|
|
24020
|
+
stream2.on("error", error);
|
|
24113
24021
|
stream2.on("close", sql2.close);
|
|
24114
24022
|
return { stream: stream2, state: xs.state };
|
|
24115
|
-
function
|
|
24023
|
+
function error(e) {
|
|
24116
24024
|
console.error("Unexpected error during logical streaming - reconnecting", e);
|
|
24117
24025
|
}
|
|
24118
24026
|
function data(x2) {
|
|
@@ -24240,7 +24148,7 @@ var noop2 = () => {};
|
|
|
24240
24148
|
// ../../node_modules/.bun/postgres@3.4.9/node_modules/postgres/src/large.js
|
|
24241
24149
|
import Stream2 from "stream";
|
|
24242
24150
|
function largeObject(sql, oid, mode = 131072 | 262144) {
|
|
24243
|
-
return new Promise(async (
|
|
24151
|
+
return new Promise(async (resolve2, reject) => {
|
|
24244
24152
|
await sql.begin(async (sql2) => {
|
|
24245
24153
|
let finish;
|
|
24246
24154
|
!oid && ([{ oid }] = await sql2`select lo_creat(-1) as oid`);
|
|
@@ -24266,7 +24174,7 @@ function largeObject(sql, oid, mode = 131072 | 262144) {
|
|
|
24266
24174
|
) seek
|
|
24267
24175
|
`
|
|
24268
24176
|
};
|
|
24269
|
-
|
|
24177
|
+
resolve2(lo);
|
|
24270
24178
|
return new Promise(async (r) => finish = r);
|
|
24271
24179
|
async function readable({
|
|
24272
24180
|
highWaterMark = 2048 * 8,
|
|
@@ -24309,7 +24217,7 @@ var exports_src = {};
|
|
|
24309
24217
|
__export(exports_src, {
|
|
24310
24218
|
default: () => src_default
|
|
24311
24219
|
});
|
|
24312
|
-
import
|
|
24220
|
+
import os from "os";
|
|
24313
24221
|
import fs from "fs";
|
|
24314
24222
|
function Postgres(a, b2) {
|
|
24315
24223
|
const options = parseOptions(a, b2), subscribe = options.no_subscribe || Subscribe(Postgres, { ...options });
|
|
@@ -24426,8 +24334,8 @@ function Postgres(a, b2) {
|
|
|
24426
24334
|
}
|
|
24427
24335
|
async function reserve() {
|
|
24428
24336
|
const queue = queue_default();
|
|
24429
|
-
const c2 = open.length ? open.shift() : await new Promise((
|
|
24430
|
-
const query = { reserve:
|
|
24337
|
+
const c2 = open.length ? open.shift() : await new Promise((resolve2, reject) => {
|
|
24338
|
+
const query = { reserve: resolve2, reject };
|
|
24431
24339
|
queries.push(query);
|
|
24432
24340
|
closed.length && connect(closed.shift(), query);
|
|
24433
24341
|
});
|
|
@@ -24454,8 +24362,8 @@ function Postgres(a, b2) {
|
|
|
24454
24362
|
scope(connection2, fn),
|
|
24455
24363
|
new Promise((_, reject) => connection2.onclose = reject)
|
|
24456
24364
|
]);
|
|
24457
|
-
} catch (
|
|
24458
|
-
throw
|
|
24365
|
+
} catch (error) {
|
|
24366
|
+
throw error;
|
|
24459
24367
|
}
|
|
24460
24368
|
async function scope(c2, fn2, name) {
|
|
24461
24369
|
const sql2 = Sql(handler2);
|
|
@@ -24464,9 +24372,9 @@ function Postgres(a, b2) {
|
|
|
24464
24372
|
let uncaughtError, result;
|
|
24465
24373
|
name && await sql2`savepoint ${sql2(name)}`;
|
|
24466
24374
|
try {
|
|
24467
|
-
result = await new Promise((
|
|
24375
|
+
result = await new Promise((resolve2, reject) => {
|
|
24468
24376
|
const x = fn2(sql2);
|
|
24469
|
-
Promise.resolve(Array.isArray(x) ? Promise.all(x) : x).then(
|
|
24377
|
+
Promise.resolve(Array.isArray(x) ? Promise.all(x) : x).then(resolve2, reject);
|
|
24470
24378
|
});
|
|
24471
24379
|
if (uncaughtError)
|
|
24472
24380
|
throw uncaughtError;
|
|
@@ -24523,8 +24431,8 @@ function Postgres(a, b2) {
|
|
|
24523
24431
|
return c2.execute(query) ? move(c2, busy) : move(c2, full);
|
|
24524
24432
|
}
|
|
24525
24433
|
function cancel(query) {
|
|
24526
|
-
return new Promise((
|
|
24527
|
-
query.state ? query.active ? connection_default(options).cancel(query.state,
|
|
24434
|
+
return new Promise((resolve2, reject) => {
|
|
24435
|
+
query.state ? query.active ? connection_default(options).cancel(query.state, resolve2, reject) : query.cancelled = { resolve: resolve2, reject } : (queries.remove(query), query.cancelled = true, query.reject(Errors.generic("57014", "canceling statement due to user request")), resolve2());
|
|
24528
24436
|
});
|
|
24529
24437
|
}
|
|
24530
24438
|
async function end({ timeout = null } = {}) {
|
|
@@ -24540,11 +24448,11 @@ function Postgres(a, b2) {
|
|
|
24540
24448
|
async function close() {
|
|
24541
24449
|
await Promise.all(connections.map((c2) => c2.end()));
|
|
24542
24450
|
}
|
|
24543
|
-
async function destroy(
|
|
24451
|
+
async function destroy(resolve2) {
|
|
24544
24452
|
await Promise.all(connections.map((c2) => c2.terminate()));
|
|
24545
24453
|
while (queries.length)
|
|
24546
24454
|
queries.shift().reject(Errors.connection("CONNECTION_DESTROYED", options));
|
|
24547
|
-
|
|
24455
|
+
resolve2();
|
|
24548
24456
|
}
|
|
24549
24457
|
function connect(c2, query) {
|
|
24550
24458
|
move(c2, connecting);
|
|
@@ -24577,7 +24485,7 @@ function Postgres(a, b2) {
|
|
|
24577
24485
|
function parseOptions(a, b2) {
|
|
24578
24486
|
if (a && a.shared)
|
|
24579
24487
|
return a;
|
|
24580
|
-
const
|
|
24488
|
+
const env3 = process.env, o = (!a || typeof a === "string" ? b2 : a) || {}, { url, multihost } = parseUrl(a), query = [...url.searchParams].reduce((a2, [b3, c2]) => (a2[b3] = c2, a2), {}), host = o.hostname || o.host || multihost || url.hostname || env3.PGHOST || "localhost", port = o.port || url.port || env3.PGPORT || 5432, user = o.user || o.username || url.username || env3.PGUSERNAME || env3.PGUSER || osUsername();
|
|
24581
24489
|
o.no_prepare && (o.prepare = false);
|
|
24582
24490
|
query.sslmode && (query.ssl = query.sslmode, delete query.sslmode);
|
|
24583
24491
|
"timeout" in o && (console.log("The timeout option is deprecated, use idle_timeout instead"), o.idle_timeout = o.timeout);
|
|
@@ -24603,21 +24511,21 @@ function parseOptions(a, b2) {
|
|
|
24603
24511
|
host: Array.isArray(host) ? host : host.split(",").map((x) => x.split(":")[0]),
|
|
24604
24512
|
port: Array.isArray(port) ? port : host.split(",").map((x) => parseInt(x.split(":")[1] || port)),
|
|
24605
24513
|
path: o.path || host.indexOf("/") > -1 && host + "/.s.PGSQL." + port,
|
|
24606
|
-
database: o.database || o.db || (url.pathname || "").slice(1) ||
|
|
24514
|
+
database: o.database || o.db || (url.pathname || "").slice(1) || env3.PGDATABASE || user,
|
|
24607
24515
|
user,
|
|
24608
|
-
pass: o.pass || o.password || url.password ||
|
|
24516
|
+
pass: o.pass || o.password || url.password || env3.PGPASSWORD || "",
|
|
24609
24517
|
...Object.entries(defaults).reduce((acc, [k, d]) => {
|
|
24610
|
-
const value = k in o ? o[k] : (k in query) ? query[k] === "disable" || query[k] === "false" ? false : query[k] :
|
|
24518
|
+
const value = k in o ? o[k] : (k in query) ? query[k] === "disable" || query[k] === "false" ? false : query[k] : env3["PG" + k.toUpperCase()] || d;
|
|
24611
24519
|
acc[k] = typeof value === "string" && ints.includes(k) ? +value : value;
|
|
24612
24520
|
return acc;
|
|
24613
24521
|
}, {}),
|
|
24614
24522
|
connection: {
|
|
24615
|
-
application_name:
|
|
24523
|
+
application_name: env3.PGAPPNAME || "postgres.js",
|
|
24616
24524
|
...o.connection,
|
|
24617
24525
|
...Object.entries(query).reduce((acc, [k, v]) => ((k in defaults) || (acc[k] = v), acc), {})
|
|
24618
24526
|
},
|
|
24619
24527
|
types: o.types || {},
|
|
24620
|
-
target_session_attrs: tsa(o, url,
|
|
24528
|
+
target_session_attrs: tsa(o, url, env3),
|
|
24621
24529
|
onnotice: o.onnotice,
|
|
24622
24530
|
onnotify: o.onnotify,
|
|
24623
24531
|
onclose: o.onclose,
|
|
@@ -24629,8 +24537,8 @@ function parseOptions(a, b2) {
|
|
|
24629
24537
|
...mergeUserTypes(o.types)
|
|
24630
24538
|
};
|
|
24631
24539
|
}
|
|
24632
|
-
function tsa(o, url,
|
|
24633
|
-
const x = o.target_session_attrs || url.searchParams.get("target_session_attrs") ||
|
|
24540
|
+
function tsa(o, url, env3) {
|
|
24541
|
+
const x = o.target_session_attrs || url.searchParams.get("target_session_attrs") || env3.PGTARGETSESSIONATTRS;
|
|
24634
24542
|
if (!x || ["read-write", "read-only", "primary", "standby", "prefer-standby"].includes(x))
|
|
24635
24543
|
return x;
|
|
24636
24544
|
throw new Error("target_session_attrs " + x + " is not supported");
|
|
@@ -24680,7 +24588,7 @@ function parseUrl(url) {
|
|
|
24680
24588
|
}
|
|
24681
24589
|
function osUsername() {
|
|
24682
24590
|
try {
|
|
24683
|
-
return
|
|
24591
|
+
return os.userInfo().username;
|
|
24684
24592
|
} catch (_) {
|
|
24685
24593
|
return process.env.USERNAME || process.env.USER || process.env.LOGNAME;
|
|
24686
24594
|
}
|
|
@@ -24714,6 +24622,99 @@ var init_src = __esm(() => {
|
|
|
24714
24622
|
src_default = Postgres;
|
|
24715
24623
|
});
|
|
24716
24624
|
|
|
24625
|
+
// src/cli/util/bundled-docs.ts
|
|
24626
|
+
import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync5, statSync } from "node:fs";
|
|
24627
|
+
import { dirname as dirname3, join as join5, resolve as resolve2 } from "node:path";
|
|
24628
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
24629
|
+
function findPackageRoot() {
|
|
24630
|
+
let dir = dirname3(fileURLToPath2(import.meta.url));
|
|
24631
|
+
for (let i = 0;i < 10; i++) {
|
|
24632
|
+
const pkgJson = join5(dir, "package.json");
|
|
24633
|
+
if (existsSync7(pkgJson)) {
|
|
24634
|
+
try {
|
|
24635
|
+
const parsed = JSON.parse(readFileSync5(pkgJson, "utf8"));
|
|
24636
|
+
if (parsed.name === "@cerefox/memory")
|
|
24637
|
+
return dir;
|
|
24638
|
+
} catch {}
|
|
24639
|
+
}
|
|
24640
|
+
const parent = dirname3(dir);
|
|
24641
|
+
if (parent === dir)
|
|
24642
|
+
break;
|
|
24643
|
+
dir = parent;
|
|
24644
|
+
}
|
|
24645
|
+
return resolve2(dirname3(fileURLToPath2(import.meta.url)), "..", "..", "..");
|
|
24646
|
+
}
|
|
24647
|
+
function bundledDocsDir() {
|
|
24648
|
+
const inPackage = join5(PACKAGE_ROOT, "docs");
|
|
24649
|
+
if (existsSync7(inPackage))
|
|
24650
|
+
return inPackage;
|
|
24651
|
+
return resolve2(PACKAGE_ROOT, "..", "..", "docs");
|
|
24652
|
+
}
|
|
24653
|
+
function agentGuidePath() {
|
|
24654
|
+
const candidates = [
|
|
24655
|
+
join5(PACKAGE_ROOT, "AGENT_GUIDE.md"),
|
|
24656
|
+
resolve2(PACKAGE_ROOT, "..", "..", "AGENT_GUIDE.md")
|
|
24657
|
+
];
|
|
24658
|
+
for (const c2 of candidates)
|
|
24659
|
+
if (existsSync7(c2))
|
|
24660
|
+
return c2;
|
|
24661
|
+
return null;
|
|
24662
|
+
}
|
|
24663
|
+
function agentQuickReferencePath() {
|
|
24664
|
+
const candidates = [
|
|
24665
|
+
join5(PACKAGE_ROOT, "AGENT_QUICK_REFERENCE.md"),
|
|
24666
|
+
resolve2(PACKAGE_ROOT, "..", "..", "AGENT_QUICK_REFERENCE.md")
|
|
24667
|
+
];
|
|
24668
|
+
for (const c2 of candidates)
|
|
24669
|
+
if (existsSync7(c2))
|
|
24670
|
+
return c2;
|
|
24671
|
+
return null;
|
|
24672
|
+
}
|
|
24673
|
+
function listBundledDocs() {
|
|
24674
|
+
const entries = [];
|
|
24675
|
+
const docsDir = bundledDocsDir();
|
|
24676
|
+
const guidesDir = join5(docsDir, "guides");
|
|
24677
|
+
if (existsSync7(guidesDir) && statSync(guidesDir).isDirectory()) {
|
|
24678
|
+
for (const name of readdirSync3(guidesDir)) {
|
|
24679
|
+
if (!name.endsWith(".md"))
|
|
24680
|
+
continue;
|
|
24681
|
+
const full = join5(guidesDir, name);
|
|
24682
|
+
entries.push({
|
|
24683
|
+
topic: name.replace(/\.md$/, ""),
|
|
24684
|
+
path: full,
|
|
24685
|
+
size: statSync(full).size
|
|
24686
|
+
});
|
|
24687
|
+
}
|
|
24688
|
+
}
|
|
24689
|
+
const ag = agentGuidePath();
|
|
24690
|
+
if (ag)
|
|
24691
|
+
entries.push({ topic: "agent-guide", path: ag, size: statSync(ag).size });
|
|
24692
|
+
const aqr = agentQuickReferencePath();
|
|
24693
|
+
if (aqr) {
|
|
24694
|
+
entries.push({
|
|
24695
|
+
topic: "agent-quick-reference",
|
|
24696
|
+
path: aqr,
|
|
24697
|
+
size: statSync(aqr).size
|
|
24698
|
+
});
|
|
24699
|
+
}
|
|
24700
|
+
entries.sort((a, b2) => a.topic.localeCompare(b2.topic));
|
|
24701
|
+
return entries;
|
|
24702
|
+
}
|
|
24703
|
+
function readBundledDoc(topic) {
|
|
24704
|
+
const entry = listBundledDocs().find((d) => d.topic === topic);
|
|
24705
|
+
if (!entry)
|
|
24706
|
+
return null;
|
|
24707
|
+
return {
|
|
24708
|
+
topic: entry.topic,
|
|
24709
|
+
path: entry.path,
|
|
24710
|
+
content: readFileSync5(entry.path, "utf8")
|
|
24711
|
+
};
|
|
24712
|
+
}
|
|
24713
|
+
var PACKAGE_ROOT;
|
|
24714
|
+
var init_bundled_docs = __esm(() => {
|
|
24715
|
+
PACKAGE_ROOT = findPackageRoot();
|
|
24716
|
+
});
|
|
24717
|
+
|
|
24717
24718
|
// ../../_shared/embeddings/index.ts
|
|
24718
24719
|
async function getEmbedding(text, apiKey) {
|
|
24719
24720
|
let lastError = null;
|
|
@@ -26752,7 +26753,7 @@ __export(exports_sync_self_docs, {
|
|
|
26752
26753
|
runSyncSelfDocs: () => runSyncSelfDocs,
|
|
26753
26754
|
registerSyncSelfDocs: () => registerSyncSelfDocs
|
|
26754
26755
|
});
|
|
26755
|
-
import { readFileSync as
|
|
26756
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
26756
26757
|
import { basename as basename4, extname as extname4 } from "node:path";
|
|
26757
26758
|
async function runSyncSelfDocs(options = {}) {
|
|
26758
26759
|
const project = options.project ?? "_cerefox-self-docs";
|
|
@@ -26779,7 +26780,7 @@ async function runSyncSelfDocs(options = {}) {
|
|
|
26779
26780
|
const authorType = resolveAuthorType("agent");
|
|
26780
26781
|
const outcomes = [];
|
|
26781
26782
|
for (const doc of docs) {
|
|
26782
|
-
const content =
|
|
26783
|
+
const content = readFileSync9(doc.path, "utf8");
|
|
26783
26784
|
const m = content.match(/^#\s+(.+)$/m);
|
|
26784
26785
|
const title = m ? m[1].trim() : basename4(doc.path, extname4(doc.path));
|
|
26785
26786
|
try {
|
|
@@ -26813,11 +26814,11 @@ async function runSyncSelfDocs(options = {}) {
|
|
|
26813
26814
|
printTable(outcomes.filter((o) => o.status === "error").map((o) => ({ topic: o.topic, error: o.detail.slice(0, 100) })));
|
|
26814
26815
|
}
|
|
26815
26816
|
}
|
|
26816
|
-
async function
|
|
26817
|
+
async function action14(options) {
|
|
26817
26818
|
await runSyncSelfDocs(options);
|
|
26818
26819
|
}
|
|
26819
26820
|
function registerSyncSelfDocs(program2) {
|
|
26820
|
-
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(
|
|
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(action14);
|
|
26821
26822
|
}
|
|
26822
26823
|
var init_sync_self_docs = __esm(() => {
|
|
26823
26824
|
init_cli_core();
|
|
@@ -41527,18 +41528,287 @@ function registerDeleteDoc(program2) {
|
|
|
41527
41528
|
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);
|
|
41528
41529
|
}
|
|
41529
41530
|
|
|
41531
|
+
// src/cli/commands/deploy-server.ts
|
|
41532
|
+
init_cli_core();
|
|
41533
|
+
init_config();
|
|
41534
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
41535
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
41536
|
+
import { readdirSync as readdirSync2 } from "node:fs";
|
|
41537
|
+
|
|
41538
|
+
// ../../_shared/server-assets/index.ts
|
|
41539
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
41540
|
+
import { dirname as dirname2, join as join4 } from "node:path";
|
|
41541
|
+
import { fileURLToPath } from "node:url";
|
|
41542
|
+
import { cwd as processCwd2 } from "node:process";
|
|
41543
|
+
function moduleDir() {
|
|
41544
|
+
return dirname2(fileURLToPath(import.meta.url));
|
|
41545
|
+
}
|
|
41546
|
+
function bundledServerAssets(serverAssetsRoot) {
|
|
41547
|
+
return {
|
|
41548
|
+
schemaFile: join4(serverAssetsRoot, "db", "schema.sql"),
|
|
41549
|
+
rpcsFile: join4(serverAssetsRoot, "db", "rpcs.sql"),
|
|
41550
|
+
migrationsDir: join4(serverAssetsRoot, "db", "migrations"),
|
|
41551
|
+
functionsDir: join4(serverAssetsRoot, "supabase", "functions"),
|
|
41552
|
+
layout: "bundled"
|
|
41553
|
+
};
|
|
41554
|
+
}
|
|
41555
|
+
function sourceServerAssets(repoRoot) {
|
|
41556
|
+
const dbDir = join4(repoRoot, "src", "cerefox", "db");
|
|
41557
|
+
return {
|
|
41558
|
+
schemaFile: join4(dbDir, "schema.sql"),
|
|
41559
|
+
rpcsFile: join4(dbDir, "rpcs.sql"),
|
|
41560
|
+
migrationsDir: join4(dbDir, "migrations"),
|
|
41561
|
+
functionsDir: join4(repoRoot, "supabase", "functions"),
|
|
41562
|
+
layout: "source"
|
|
41563
|
+
};
|
|
41564
|
+
}
|
|
41565
|
+
function serverAssetsUsable(p) {
|
|
41566
|
+
return existsSync4(p.schemaFile) && existsSync4(p.rpcsFile);
|
|
41567
|
+
}
|
|
41568
|
+
function resolveServerAssets(opts = {}) {
|
|
41569
|
+
if (opts.assetsDir) {
|
|
41570
|
+
return { ...bundledServerAssets(opts.assetsDir), layout: "explicit" };
|
|
41571
|
+
}
|
|
41572
|
+
const here = opts.moduleDirOverride ?? moduleDir();
|
|
41573
|
+
const cwd = opts.cwd ?? processCwd2();
|
|
41574
|
+
const candidates = [
|
|
41575
|
+
bundledServerAssets(join4(here, "..", "server-assets")),
|
|
41576
|
+
sourceServerAssets(join4(here, "..", "..")),
|
|
41577
|
+
sourceServerAssets(cwd)
|
|
41578
|
+
];
|
|
41579
|
+
for (const candidate of candidates) {
|
|
41580
|
+
if (serverAssetsUsable(candidate))
|
|
41581
|
+
return candidate;
|
|
41582
|
+
}
|
|
41583
|
+
return sourceServerAssets(join4(here, "..", ".."));
|
|
41584
|
+
}
|
|
41585
|
+
|
|
41586
|
+
// ../../_shared/db-deploy/index.ts
|
|
41587
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync } from "node:fs";
|
|
41588
|
+
init_src();
|
|
41589
|
+
var RESET_SQL = `
|
|
41590
|
+
DROP TABLE IF EXISTS cerefox_chunks CASCADE;
|
|
41591
|
+
DROP TABLE IF EXISTS cerefox_documents CASCADE;
|
|
41592
|
+
DROP TABLE IF EXISTS cerefox_projects CASCADE;
|
|
41593
|
+
DROP TABLE IF EXISTS cerefox_migrations CASCADE;
|
|
41594
|
+
DROP FUNCTION IF EXISTS cerefox_set_updated_at CASCADE;
|
|
41595
|
+
DROP FUNCTION IF EXISTS cerefox_hybrid_search CASCADE;
|
|
41596
|
+
DROP FUNCTION IF EXISTS cerefox_fts_search CASCADE;
|
|
41597
|
+
DROP FUNCTION IF EXISTS cerefox_semantic_search CASCADE;
|
|
41598
|
+
DROP FUNCTION IF EXISTS cerefox_reconstruct_doc CASCADE;
|
|
41599
|
+
`;
|
|
41600
|
+
var EXTENSIONS_SQL = `
|
|
41601
|
+
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
41602
|
+
CREATE EXTENSION IF NOT EXISTS "vector";
|
|
41603
|
+
`;
|
|
41604
|
+
function listMigrationFiles(migrationsDir) {
|
|
41605
|
+
if (!existsSync5(migrationsDir))
|
|
41606
|
+
return [];
|
|
41607
|
+
return readdirSync(migrationsDir).filter((n) => n.endsWith(".sql")).sort();
|
|
41608
|
+
}
|
|
41609
|
+
function buildDeploySteps(assets, opts = {}) {
|
|
41610
|
+
const schemaSql = readFileSync4(assets.schemaFile, "utf8");
|
|
41611
|
+
const rpcsSql = readFileSync4(assets.rpcsFile, "utf8");
|
|
41612
|
+
const steps = [];
|
|
41613
|
+
if (opts.reset) {
|
|
41614
|
+
steps.push({ label: "Reset: drop existing Cerefox objects", sql: RESET_SQL });
|
|
41615
|
+
}
|
|
41616
|
+
steps.push({ label: "Enable extensions (uuid-ossp, vector/pgvector)", sql: EXTENSIONS_SQL }, { label: "Apply schema (tables, indexes, triggers)", sql: schemaSql }, { label: "Apply RPCs (search functions)", sql: rpcsSql });
|
|
41617
|
+
const migrationFiles = listMigrationFiles(assets.migrationsDir);
|
|
41618
|
+
if (migrationFiles.length > 0) {
|
|
41619
|
+
const values2 = migrationFiles.map((n) => `('${n.replace(/'/g, "''")}')`).join(", ");
|
|
41620
|
+
steps.push({
|
|
41621
|
+
label: "Stamp migration files as already applied",
|
|
41622
|
+
sql: `INSERT INTO cerefox_migrations (filename) VALUES ${values2} ON CONFLICT (filename) DO NOTHING;`
|
|
41623
|
+
});
|
|
41624
|
+
}
|
|
41625
|
+
return steps;
|
|
41626
|
+
}
|
|
41627
|
+
async function runDbDeploy(opts) {
|
|
41628
|
+
const log = opts.log ?? (() => {});
|
|
41629
|
+
const steps = buildDeploySteps(opts.assets, { reset: opts.reset });
|
|
41630
|
+
if (opts.dryRun) {
|
|
41631
|
+
for (const step of steps) {
|
|
41632
|
+
log(`▶ ${step.label}… (dry-run, not executed)`);
|
|
41633
|
+
}
|
|
41634
|
+
return { ok: true, stepsRun: steps.length };
|
|
41635
|
+
}
|
|
41636
|
+
const sql = src_default(opts.dbUrl, { prepare: false, onnotice: () => {} });
|
|
41637
|
+
let stepsRun = 0;
|
|
41638
|
+
try {
|
|
41639
|
+
for (const step of steps) {
|
|
41640
|
+
log(`▶ ${step.label}…`);
|
|
41641
|
+
try {
|
|
41642
|
+
await sql.unsafe(step.sql);
|
|
41643
|
+
stepsRun++;
|
|
41644
|
+
} catch (err) {
|
|
41645
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
41646
|
+
return { ok: false, stepsRun, failedStep: step.label, error: message };
|
|
41647
|
+
}
|
|
41648
|
+
}
|
|
41649
|
+
return { ok: true, stepsRun };
|
|
41650
|
+
} finally {
|
|
41651
|
+
await sql.end({ timeout: 5 }).catch(() => {});
|
|
41652
|
+
}
|
|
41653
|
+
}
|
|
41654
|
+
|
|
41655
|
+
// src/cli/commands/deploy-server.ts
|
|
41656
|
+
function commandSucceeds(cmd, args) {
|
|
41657
|
+
try {
|
|
41658
|
+
const r = spawnSync2(cmd, args, { encoding: "utf8", timeout: 15000 });
|
|
41659
|
+
return r.status === 0;
|
|
41660
|
+
} catch {
|
|
41661
|
+
return false;
|
|
41662
|
+
}
|
|
41663
|
+
}
|
|
41664
|
+
function listEdgeFunctions(functionsDir) {
|
|
41665
|
+
if (!existsSync6(functionsDir))
|
|
41666
|
+
return [];
|
|
41667
|
+
return readdirSync2(functionsDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("cerefox-")).map((e) => e.name).sort();
|
|
41668
|
+
}
|
|
41669
|
+
async function action7(options) {
|
|
41670
|
+
const settings = loadSettings();
|
|
41671
|
+
const assets = resolveServerAssets();
|
|
41672
|
+
const doSchema = !options.functionsOnly;
|
|
41673
|
+
const doFunctions = !options.schemaOnly;
|
|
41674
|
+
const checks = [];
|
|
41675
|
+
if (doSchema) {
|
|
41676
|
+
checks.push({
|
|
41677
|
+
label: "CEREFOX_DATABASE_URL is set (Session Pooler, port 5432)",
|
|
41678
|
+
ok: Boolean(settings.databaseUrl),
|
|
41679
|
+
remediation: "Set CEREFOX_DATABASE_URL in your .env. Use the Session Pooler URI " + "(port 5432, username postgres.<project-ref>, ?sslmode=require). " + "See docs/guides/setup-supabase.md → Connection pooling."
|
|
41680
|
+
});
|
|
41681
|
+
checks.push({
|
|
41682
|
+
label: "Bundled schema assets present",
|
|
41683
|
+
ok: existsSync6(assets.schemaFile) && existsSync6(assets.rpcsFile),
|
|
41684
|
+
remediation: "Schema files not found. Reinstall the package, or run from a repo " + "clone (src/cerefox/db/)."
|
|
41685
|
+
});
|
|
41686
|
+
}
|
|
41687
|
+
let efNames = [];
|
|
41688
|
+
if (doFunctions) {
|
|
41689
|
+
efNames = listEdgeFunctions(assets.functionsDir);
|
|
41690
|
+
checks.push({
|
|
41691
|
+
label: "Bundled Edge Function sources present",
|
|
41692
|
+
ok: efNames.length > 0,
|
|
41693
|
+
remediation: "Edge Function sources not found under the bundled assets. Reinstall " + "the package, or run from a repo clone (supabase/functions/)."
|
|
41694
|
+
});
|
|
41695
|
+
checks.push({
|
|
41696
|
+
label: "Supabase CLI reachable (`npx supabase --version`)",
|
|
41697
|
+
ok: commandSucceeds("npx", ["--yes", "supabase", "--version"]),
|
|
41698
|
+
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
|
+
});
|
|
41700
|
+
checks.push({
|
|
41701
|
+
label: "Supabase project linked (`npx supabase link`)",
|
|
41702
|
+
ok: existsSync6("supabase/config.toml") || existsSync6(".supabase/config.toml"),
|
|
41703
|
+
remediation: `Authenticate + link your project (one-time, from any working dir):
|
|
41704
|
+
` + ` npx supabase login
|
|
41705
|
+
` + ` npx supabase link --project-ref <your-project-ref>
|
|
41706
|
+
` + " Your project ref is in the dashboard URL: " + "https://supabase.com/dashboard/project/<project-ref>"
|
|
41707
|
+
});
|
|
41708
|
+
}
|
|
41709
|
+
const failed = checks.filter((ch) => !ch.ok);
|
|
41710
|
+
println(c.bold("Cerefox deploy-server — pre-flight"));
|
|
41711
|
+
for (const ch of checks) {
|
|
41712
|
+
println(` ${ch.ok ? c.green("✓") : c.red("✗")} ${ch.label}`);
|
|
41713
|
+
}
|
|
41714
|
+
if (failed.length > 0) {
|
|
41715
|
+
eprintln("");
|
|
41716
|
+
eprintln(c.red(`Cannot deploy yet — ${failed.length} prerequisite(s) missing:`));
|
|
41717
|
+
for (const ch of failed) {
|
|
41718
|
+
eprintln(`
|
|
41719
|
+
${c.red("✗")} ${ch.label}`);
|
|
41720
|
+
eprintln(c.dim(` → ${ch.remediation}`));
|
|
41721
|
+
}
|
|
41722
|
+
eprintln("\nFix the above and re-run `cerefox deploy-server` (it's idempotent).");
|
|
41723
|
+
process.exit(1);
|
|
41724
|
+
}
|
|
41725
|
+
println(c.green(`
|
|
41726
|
+
✓ All prerequisites satisfied.`));
|
|
41727
|
+
const planLines = [];
|
|
41728
|
+
if (doSchema) {
|
|
41729
|
+
planLines.push(` • ${options.reset ? "RESET + redeploy" : "Deploy"} schema + RPCs to ${settings.supabaseUrl || "your Supabase database"}`);
|
|
41730
|
+
}
|
|
41731
|
+
if (doFunctions) {
|
|
41732
|
+
planLines.push(` • Deploy ${efNames.length} Edge Function(s): ${efNames.join(", ")}`);
|
|
41733
|
+
}
|
|
41734
|
+
println(c.bold(`
|
|
41735
|
+
Plan:`));
|
|
41736
|
+
for (const line of planLines)
|
|
41737
|
+
println(line);
|
|
41738
|
+
if (options.dryRun) {
|
|
41739
|
+
println(c.yellow(`
|
|
41740
|
+
⚠ --dry-run: nothing was deployed.`));
|
|
41741
|
+
process.exit(0);
|
|
41742
|
+
}
|
|
41743
|
+
const proceed = await confirm(`
|
|
41744
|
+
Proceed with deployment to Supabase${options.reset ? " (--reset DROPS existing data!)" : ""}?`, true);
|
|
41745
|
+
if (!proceed) {
|
|
41746
|
+
println(c.dim("Aborted."));
|
|
41747
|
+
process.exit(0);
|
|
41748
|
+
}
|
|
41749
|
+
if (doSchema) {
|
|
41750
|
+
println(c.bold(`
|
|
41751
|
+
▶ Deploying schema + RPCs…`));
|
|
41752
|
+
const result = await runDbDeploy({
|
|
41753
|
+
dbUrl: settings.databaseUrl,
|
|
41754
|
+
assets,
|
|
41755
|
+
reset: options.reset,
|
|
41756
|
+
log: (line) => println(c.dim(` ${line}`))
|
|
41757
|
+
});
|
|
41758
|
+
if (!result.ok) {
|
|
41759
|
+
eprintln(c.red(`
|
|
41760
|
+
✗ Schema deploy failed at "${result.failedStep}": ${result.error}`));
|
|
41761
|
+
process.exit(1);
|
|
41762
|
+
}
|
|
41763
|
+
println(c.green(` ✓ Schema deployed (${result.stepsRun} steps).`));
|
|
41764
|
+
}
|
|
41765
|
+
if (doFunctions) {
|
|
41766
|
+
println(c.bold(`
|
|
41767
|
+
▶ Deploying ${efNames.length} Edge Function(s)…`));
|
|
41768
|
+
let efOk = 0;
|
|
41769
|
+
const efFailed = [];
|
|
41770
|
+
for (const ef of efNames) {
|
|
41771
|
+
info(` deploying ${ef}…`);
|
|
41772
|
+
const workdir = assets.functionsDir.replace(/\/functions$/, "").replace(/\/supabase$/, "");
|
|
41773
|
+
const r = spawnSync2("npx", ["--yes", "supabase", "functions", "deploy", ef], {
|
|
41774
|
+
encoding: "utf8",
|
|
41775
|
+
stdio: "inherit",
|
|
41776
|
+
cwd: workdir,
|
|
41777
|
+
timeout: 120000
|
|
41778
|
+
});
|
|
41779
|
+
if (r.status === 0)
|
|
41780
|
+
efOk++;
|
|
41781
|
+
else
|
|
41782
|
+
efFailed.push(ef);
|
|
41783
|
+
}
|
|
41784
|
+
if (efFailed.length > 0) {
|
|
41785
|
+
eprintln(c.red(`
|
|
41786
|
+
✗ ${efFailed.length} Edge Function(s) failed: ${efFailed.join(", ")}`));
|
|
41787
|
+
eprintln(c.dim(" Re-run `cerefox deploy-server --functions-only` after fixing the cause."));
|
|
41788
|
+
process.exit(1);
|
|
41789
|
+
}
|
|
41790
|
+
println(c.green(` ✓ Deployed ${efOk} Edge Function(s).`));
|
|
41791
|
+
}
|
|
41792
|
+
println(c.green(`
|
|
41793
|
+
✓ Server deploy complete.`));
|
|
41794
|
+
println(c.dim("Verify with: cerefox doctor"));
|
|
41795
|
+
}
|
|
41796
|
+
function registerDeployServer(program2) {
|
|
41797
|
+
program2.command("deploy-server").description("Deploy the Cerefox server side (schema + RPCs + Edge Functions) to Supabase.").option("--dry-run", "Print the plan + pre-flight without deploying.").option("--reset", "DROP existing Cerefox tables before redeploying the schema (DESTRUCTIVE).").option("--schema-only", "Deploy only the schema + RPCs (skip Edge Functions).").option("--functions-only", "Deploy only the Edge Functions (skip the schema).").action(action7);
|
|
41798
|
+
}
|
|
41799
|
+
|
|
41530
41800
|
// src/cli/commands/docs.ts
|
|
41531
41801
|
init_cli_core();
|
|
41532
41802
|
init_bundled_docs();
|
|
41533
|
-
import { spawnSync as
|
|
41803
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
41534
41804
|
function openInBrowser(path) {
|
|
41535
41805
|
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
41536
|
-
const result =
|
|
41806
|
+
const result = spawnSync3(cmd, [path], { stdio: "ignore" });
|
|
41537
41807
|
if (result.status !== 0) {
|
|
41538
41808
|
println(c.dim(`(could not auto-open; the file is at: ${path})`));
|
|
41539
41809
|
}
|
|
41540
41810
|
}
|
|
41541
|
-
function
|
|
41811
|
+
function action8(topic, options) {
|
|
41542
41812
|
const docs = listBundledDocs();
|
|
41543
41813
|
if (options.list || !topic && !options.print) {
|
|
41544
41814
|
if (docs.length === 0) {
|
|
@@ -41567,7 +41837,7 @@ function action7(topic, options) {
|
|
|
41567
41837
|
openInBrowser(doc.path);
|
|
41568
41838
|
}
|
|
41569
41839
|
function registerDocs(program2) {
|
|
41570
|
-
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(
|
|
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(action8);
|
|
41571
41841
|
}
|
|
41572
41842
|
|
|
41573
41843
|
// ../../node_modules/.bun/ora@9.4.0/node_modules/ora/index.js
|
|
@@ -41753,7 +42023,7 @@ var ansi_styles_default = ansiStyles;
|
|
|
41753
42023
|
|
|
41754
42024
|
// ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/supports-color/index.js
|
|
41755
42025
|
import process2 from "node:process";
|
|
41756
|
-
import
|
|
42026
|
+
import os2 from "node:os";
|
|
41757
42027
|
import tty from "node:tty";
|
|
41758
42028
|
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
|
|
41759
42029
|
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
@@ -41818,7 +42088,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
|
41818
42088
|
return min;
|
|
41819
42089
|
}
|
|
41820
42090
|
if (process2.platform === "win32") {
|
|
41821
|
-
const osRelease =
|
|
42091
|
+
const osRelease = os2.release().split(".");
|
|
41822
42092
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
41823
42093
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
41824
42094
|
}
|
|
@@ -44132,7 +44402,7 @@ var format = (open, close) => {
|
|
|
44132
44402
|
return result;
|
|
44133
44403
|
};
|
|
44134
44404
|
};
|
|
44135
|
-
var
|
|
44405
|
+
var reset2 = format(0, 0);
|
|
44136
44406
|
var bold = format(1, 22);
|
|
44137
44407
|
var dim = format(2, 22);
|
|
44138
44408
|
var italic = format(3, 23);
|
|
@@ -44959,9 +45229,105 @@ init_cli_core();
|
|
|
44959
45229
|
init_meta();
|
|
44960
45230
|
init_config();
|
|
44961
45231
|
init_config();
|
|
44962
|
-
import { existsSync as
|
|
45232
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, realpathSync, statSync as statSync2 } from "node:fs";
|
|
44963
45233
|
import { homedir as homedir4 } from "node:os";
|
|
44964
|
-
import { join as
|
|
45234
|
+
import { join as join6 } from "node:path";
|
|
45235
|
+
|
|
45236
|
+
// ../../_shared/compatibility/index.ts
|
|
45237
|
+
var COMPATIBILITY = {
|
|
45238
|
+
minSchema: "0.3.1",
|
|
45239
|
+
minEdgeFunctions: "0.6.0"
|
|
45240
|
+
};
|
|
45241
|
+
function compareSemver(a, b2) {
|
|
45242
|
+
const norm = (v) => v.split(/[.-]/).slice(0, 3).map((p) => Number.parseInt(p, 10)).map((n) => Number.isFinite(n) ? n : 0);
|
|
45243
|
+
const pa = norm(a);
|
|
45244
|
+
const pb = norm(b2);
|
|
45245
|
+
for (let i = 0;i < 3; i++) {
|
|
45246
|
+
const x = pa[i] ?? 0;
|
|
45247
|
+
const y = pb[i] ?? 0;
|
|
45248
|
+
if (x !== y)
|
|
45249
|
+
return x < y ? -1 : 1;
|
|
45250
|
+
}
|
|
45251
|
+
return 0;
|
|
45252
|
+
}
|
|
45253
|
+
function classifyCompat(deployed, min, bundled) {
|
|
45254
|
+
if (!deployed)
|
|
45255
|
+
return "unknown";
|
|
45256
|
+
if (compareSemver(deployed, min) < 0)
|
|
45257
|
+
return "below-min";
|
|
45258
|
+
if (bundled && compareSemver(deployed, bundled) < 0)
|
|
45259
|
+
return "above-min-but-old";
|
|
45260
|
+
return "ok";
|
|
45261
|
+
}
|
|
45262
|
+
function aggregatorUrlFor(supabaseUrl) {
|
|
45263
|
+
const base = supabaseUrl.replace(/\/$/, "");
|
|
45264
|
+
return `${base}/functions/v1/cerefox-mcp/version?peers=true`;
|
|
45265
|
+
}
|
|
45266
|
+
async function checkServerCompatibility(opts) {
|
|
45267
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
45268
|
+
const result = {
|
|
45269
|
+
schema: { deployed: null, min: COMPATIBILITY.minSchema, level: "unknown" },
|
|
45270
|
+
edgeFunctions: {
|
|
45271
|
+
deployed: null,
|
|
45272
|
+
min: COMPATIBILITY.minEdgeFunctions,
|
|
45273
|
+
level: "unknown",
|
|
45274
|
+
errors: []
|
|
45275
|
+
},
|
|
45276
|
+
blocking: false,
|
|
45277
|
+
efProbeSkipped: false
|
|
45278
|
+
};
|
|
45279
|
+
if (!opts.bearer) {
|
|
45280
|
+
result.efProbeSkipped = true;
|
|
45281
|
+
result.efSkipReason = "No anon JWT (CEREFOX_SUPABASE_ANON_KEY) configured; Edge Function version check skipped.";
|
|
45282
|
+
return result;
|
|
45283
|
+
}
|
|
45284
|
+
let agg = null;
|
|
45285
|
+
try {
|
|
45286
|
+
const ctrl = new AbortController;
|
|
45287
|
+
const timer2 = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 6000);
|
|
45288
|
+
try {
|
|
45289
|
+
const resp = await fetchImpl(opts.aggregatorUrl, {
|
|
45290
|
+
method: "GET",
|
|
45291
|
+
headers: { Authorization: `Bearer ${opts.bearer}`, apikey: opts.bearer },
|
|
45292
|
+
signal: ctrl.signal
|
|
45293
|
+
});
|
|
45294
|
+
if (resp.ok) {
|
|
45295
|
+
agg = await resp.json();
|
|
45296
|
+
} else {
|
|
45297
|
+
result.efProbeSkipped = true;
|
|
45298
|
+
result.efSkipReason = resp.status === 404 || resp.status === 405 ? "Edge Functions predate v0.8 (no /version route). Redeploy with `cerefox deploy-server --functions-only` to enable version checks." : `Aggregator returned HTTP ${resp.status}; Edge Function version check skipped.`;
|
|
45299
|
+
}
|
|
45300
|
+
} finally {
|
|
45301
|
+
clearTimeout(timer2);
|
|
45302
|
+
}
|
|
45303
|
+
} catch (err) {
|
|
45304
|
+
result.efProbeSkipped = true;
|
|
45305
|
+
result.efSkipReason = `Could not reach the version aggregator: ${err instanceof Error ? err.message : String(err)}`;
|
|
45306
|
+
}
|
|
45307
|
+
if (!agg)
|
|
45308
|
+
return result;
|
|
45309
|
+
result.schema.deployed = agg.schema ?? null;
|
|
45310
|
+
result.schema.level = classifyCompat(result.schema.deployed, COMPATIBILITY.minSchema, opts.bundledSchema);
|
|
45311
|
+
const versions = [];
|
|
45312
|
+
if (agg.version)
|
|
45313
|
+
versions.push(agg.version);
|
|
45314
|
+
for (const ef of agg.efs ?? [])
|
|
45315
|
+
versions.push(ef.version);
|
|
45316
|
+
result.edgeFunctions.errors = agg.errors ?? [];
|
|
45317
|
+
if (versions.length > 0) {
|
|
45318
|
+
const weakest = versions.reduce((lo, v) => compareSemver(v, lo) < 0 ? v : lo);
|
|
45319
|
+
result.edgeFunctions.deployed = weakest;
|
|
45320
|
+
result.edgeFunctions.level = classifyCompat(weakest, COMPATIBILITY.minEdgeFunctions, opts.bundledEf);
|
|
45321
|
+
} else {
|
|
45322
|
+
result.edgeFunctions.level = "unknown";
|
|
45323
|
+
result.efProbeSkipped = true;
|
|
45324
|
+
result.efSkipReason = "Aggregator reported no Edge Function versions; check skipped.";
|
|
45325
|
+
}
|
|
45326
|
+
result.blocking = result.schema.level === "below-min" || result.edgeFunctions.level === "below-min";
|
|
45327
|
+
return result;
|
|
45328
|
+
}
|
|
45329
|
+
|
|
45330
|
+
// src/cli/util/checks.ts
|
|
44965
45331
|
function checkBinary() {
|
|
44966
45332
|
return {
|
|
44967
45333
|
name: "binary",
|
|
@@ -45012,7 +45378,7 @@ function checkConfig() {
|
|
|
45012
45378
|
hint: "Run `cerefox init` to bootstrap."
|
|
45013
45379
|
};
|
|
45014
45380
|
}
|
|
45015
|
-
if (!
|
|
45381
|
+
if (!existsSync8(envPath)) {
|
|
45016
45382
|
return {
|
|
45017
45383
|
name: "config",
|
|
45018
45384
|
status: "error",
|
|
@@ -45179,10 +45545,10 @@ async function checkSchemaVersion() {
|
|
|
45179
45545
|
}
|
|
45180
45546
|
}
|
|
45181
45547
|
function hasCerefoxInJsonFile(path) {
|
|
45182
|
-
if (!
|
|
45548
|
+
if (!existsSync8(path))
|
|
45183
45549
|
return false;
|
|
45184
45550
|
try {
|
|
45185
|
-
const parsed = JSON.parse(
|
|
45551
|
+
const parsed = JSON.parse(readFileSync6(path, "utf8"));
|
|
45186
45552
|
const mcpServers = parsed.mcpServers;
|
|
45187
45553
|
return Boolean(mcpServers && typeof mcpServers === "object" && "cerefox" in mcpServers);
|
|
45188
45554
|
} catch {
|
|
@@ -45191,9 +45557,9 @@ function hasCerefoxInJsonFile(path) {
|
|
|
45191
45557
|
}
|
|
45192
45558
|
function checkMcpConfigs() {
|
|
45193
45559
|
const home = homedir4();
|
|
45194
|
-
const claudeCodeUser =
|
|
45195
|
-
const claudeCodeProj =
|
|
45196
|
-
const claudeDesktop = process.platform === "darwin" ?
|
|
45560
|
+
const claudeCodeUser = join6(home, ".claude.json");
|
|
45561
|
+
const claudeCodeProj = join6(process.cwd(), ".mcp.json");
|
|
45562
|
+
const claudeDesktop = process.platform === "darwin" ? join6(home, "Library", "Application Support", "Claude", "claude_desktop_config.json") : process.platform === "win32" ? join6(process.env.APPDATA ?? "", "Claude", "claude_desktop_config.json") : join6(home, ".config", "Claude", "claude_desktop_config.json");
|
|
45197
45563
|
const found = [];
|
|
45198
45564
|
if (hasCerefoxInJsonFile(claudeCodeUser))
|
|
45199
45565
|
found.push("Claude Code (user)");
|
|
@@ -45217,9 +45583,9 @@ function checkMcpConfigs() {
|
|
|
45217
45583
|
}
|
|
45218
45584
|
function checkLegacyShadowEnv() {
|
|
45219
45585
|
const home = homedir4();
|
|
45220
|
-
const homeEnv =
|
|
45221
|
-
const cwdEnv =
|
|
45222
|
-
if (!
|
|
45586
|
+
const homeEnv = join6(home, USER_STATE_DIR_NAME, ".env");
|
|
45587
|
+
const cwdEnv = join6(process.cwd(), ".env");
|
|
45588
|
+
if (!existsSync8(homeEnv) || !existsSync8(cwdEnv))
|
|
45223
45589
|
return null;
|
|
45224
45590
|
try {
|
|
45225
45591
|
if (realpathSync(homeEnv) === realpathSync(cwdEnv))
|
|
@@ -45278,6 +45644,68 @@ async function checkPostgres() {
|
|
|
45278
45644
|
await sql.end({ timeout: 1 }).catch(() => {});
|
|
45279
45645
|
}
|
|
45280
45646
|
}
|
|
45647
|
+
async function checkEdgeFunctionsCompat() {
|
|
45648
|
+
const settings = loadSettings();
|
|
45649
|
+
if (!settings.supabaseUrl) {
|
|
45650
|
+
return {
|
|
45651
|
+
name: "edge functions",
|
|
45652
|
+
status: "skipped",
|
|
45653
|
+
detail: "Supabase URL not set; EF version check skipped."
|
|
45654
|
+
};
|
|
45655
|
+
}
|
|
45656
|
+
if (!settings.supabaseAnonKey) {
|
|
45657
|
+
return {
|
|
45658
|
+
name: "edge functions",
|
|
45659
|
+
status: "skipped",
|
|
45660
|
+
detail: "No CEREFOX_SUPABASE_ANON_KEY set; EF version check skipped.",
|
|
45661
|
+
hint: "Set the legacy anon JWT (eyJ…) to enable client↔server version checks."
|
|
45662
|
+
};
|
|
45663
|
+
}
|
|
45664
|
+
let compat;
|
|
45665
|
+
try {
|
|
45666
|
+
compat = await checkServerCompatibility({
|
|
45667
|
+
aggregatorUrl: aggregatorUrlFor(settings.supabaseUrl),
|
|
45668
|
+
bearer: settings.supabaseAnonKey,
|
|
45669
|
+
bundledEf: PKG_VERSION
|
|
45670
|
+
});
|
|
45671
|
+
} catch (err) {
|
|
45672
|
+
return {
|
|
45673
|
+
name: "edge functions",
|
|
45674
|
+
status: "skipped",
|
|
45675
|
+
detail: `Version probe failed: ${err instanceof Error ? err.message : String(err)}`
|
|
45676
|
+
};
|
|
45677
|
+
}
|
|
45678
|
+
if (compat.efProbeSkipped) {
|
|
45679
|
+
return {
|
|
45680
|
+
name: "edge functions",
|
|
45681
|
+
status: "skipped",
|
|
45682
|
+
detail: compat.efSkipReason ?? "EF version check skipped."
|
|
45683
|
+
};
|
|
45684
|
+
}
|
|
45685
|
+
const deployed = compat.edgeFunctions.deployed ?? "unknown";
|
|
45686
|
+
switch (compat.edgeFunctions.level) {
|
|
45687
|
+
case "below-min":
|
|
45688
|
+
return {
|
|
45689
|
+
name: "edge functions",
|
|
45690
|
+
status: "error",
|
|
45691
|
+
detail: `Deployed EF v${deployed} is below the required minimum v${compat.edgeFunctions.min}.`,
|
|
45692
|
+
hint: "Redeploy the Edge Functions: `cerefox deploy-server --functions-only`."
|
|
45693
|
+
};
|
|
45694
|
+
case "above-min-but-old":
|
|
45695
|
+
return {
|
|
45696
|
+
name: "edge functions",
|
|
45697
|
+
status: "warn",
|
|
45698
|
+
detail: `Deployed EF v${deployed} works but is older than this client (v${PKG_VERSION}).`,
|
|
45699
|
+
hint: "Consider redeploying: `cerefox deploy-server --functions-only`."
|
|
45700
|
+
};
|
|
45701
|
+
default:
|
|
45702
|
+
return {
|
|
45703
|
+
name: "edge functions",
|
|
45704
|
+
status: "ok",
|
|
45705
|
+
detail: `Deployed EF v${deployed} (≥ required v${compat.edgeFunctions.min}).`
|
|
45706
|
+
};
|
|
45707
|
+
}
|
|
45708
|
+
}
|
|
45281
45709
|
async function runSteps(steps, opts) {
|
|
45282
45710
|
const results = [];
|
|
45283
45711
|
for (let i = 0;i < steps.length; i++) {
|
|
@@ -45304,6 +45732,7 @@ async function runAllChecks(opts = {}) {
|
|
|
45304
45732
|
{ name: "supabase", phase: "Probing Supabase Data API", run: () => checkSupabase() },
|
|
45305
45733
|
{ name: "openai", phase: "Probing OpenAI embeddings", run: () => checkOpenAI() },
|
|
45306
45734
|
{ name: "schema", phase: "Reading schema version", run: () => checkSchemaVersion() },
|
|
45735
|
+
{ name: "edge functions", phase: "Probing Edge Function versions", run: () => checkEdgeFunctionsCompat() },
|
|
45307
45736
|
{ name: "postgres", phase: "Probing Postgres DDL endpoint", run: () => checkPostgres() },
|
|
45308
45737
|
{ name: "mcp clients", phase: "Scanning MCP client configs", run: () => checkMcpConfigs() }
|
|
45309
45738
|
];
|
|
@@ -45331,7 +45760,7 @@ function symbol(status) {
|
|
|
45331
45760
|
return cErr.dim("ℹ");
|
|
45332
45761
|
}
|
|
45333
45762
|
}
|
|
45334
|
-
async function
|
|
45763
|
+
async function action9(options) {
|
|
45335
45764
|
const useSpinner = !options.json && process.stderr.isTTY;
|
|
45336
45765
|
const spinner = useSpinner ? ora({ text: "Starting checks…", spinner: "dots", stream: process.stderr }).start() : null;
|
|
45337
45766
|
const results = await runAllChecks({
|
|
@@ -45368,13 +45797,13 @@ async function action8(options) {
|
|
|
45368
45797
|
}
|
|
45369
45798
|
}
|
|
45370
45799
|
function registerDoctor(program2) {
|
|
45371
|
-
program2.command("doctor").description("Run diagnostic checks against the installed Cerefox.").option("--json", "Emit machine-readable JSON (no colours, structured output).").action(
|
|
45800
|
+
program2.command("doctor").description("Run diagnostic checks against the installed Cerefox.").option("--json", "Emit machine-readable JSON (no colours, structured output).").action(action9);
|
|
45372
45801
|
}
|
|
45373
45802
|
|
|
45374
45803
|
// src/cli/commands/get-audit-log.ts
|
|
45375
45804
|
init_cli_core();
|
|
45376
45805
|
init_client();
|
|
45377
|
-
async function
|
|
45806
|
+
async function action10(options) {
|
|
45378
45807
|
const limit = parsePositiveInt(options.limit, "--limit", 50);
|
|
45379
45808
|
const client = getClient();
|
|
45380
45809
|
const data = await client.rpc("cerefox_list_audit_entries", {
|
|
@@ -45412,14 +45841,14 @@ async function action9(options) {
|
|
|
45412
45841
|
})));
|
|
45413
45842
|
}
|
|
45414
45843
|
function registerGetAuditLog(program2) {
|
|
45415
|
-
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(
|
|
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(action10);
|
|
45416
45845
|
}
|
|
45417
45846
|
|
|
45418
45847
|
// src/cli/commands/get-doc.ts
|
|
45419
45848
|
init_cli_core();
|
|
45420
45849
|
init_cli_core();
|
|
45421
45850
|
init_client();
|
|
45422
|
-
async function
|
|
45851
|
+
async function action11(documentId, options) {
|
|
45423
45852
|
const client = getClient();
|
|
45424
45853
|
const rows = await client.rpc("cerefox_get_document", {
|
|
45425
45854
|
p_document_id: documentId,
|
|
@@ -45449,18 +45878,18 @@ async function action10(documentId, options) {
|
|
|
45449
45878
|
println(doc.full_content);
|
|
45450
45879
|
}
|
|
45451
45880
|
function registerGetDoc(program2) {
|
|
45452
|
-
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(
|
|
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(action11);
|
|
45453
45882
|
}
|
|
45454
45883
|
|
|
45455
45884
|
// src/cli/commands/ingest.ts
|
|
45456
45885
|
init_dist4();
|
|
45457
45886
|
init_cli_core();
|
|
45458
45887
|
init_config();
|
|
45459
|
-
import { readFileSync as
|
|
45888
|
+
import { readFileSync as readFileSync8 } from "node:fs";
|
|
45460
45889
|
import { basename as basename2, extname as extname2 } from "node:path";
|
|
45461
45890
|
|
|
45462
45891
|
// src/ingestion/pipeline.ts
|
|
45463
|
-
import { readFileSync as
|
|
45892
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
45464
45893
|
import { basename, extname, resolve as resolve3 } from "node:path";
|
|
45465
45894
|
|
|
45466
45895
|
// ../../_shared/ingest/chunker.ts
|
|
@@ -46144,7 +46573,7 @@ ${c2.content}`);
|
|
|
46144
46573
|
};
|
|
46145
46574
|
}
|
|
46146
46575
|
async ingestFile(path, opts = {}) {
|
|
46147
|
-
const text =
|
|
46576
|
+
const text = readFileSync7(path, "utf8");
|
|
46148
46577
|
const absPath = resolve3(path);
|
|
46149
46578
|
const stem = basename(absPath, extname(absPath));
|
|
46150
46579
|
return this.ingestText({
|
|
@@ -46178,7 +46607,7 @@ async function readContent(path, paste) {
|
|
|
46178
46607
|
}
|
|
46179
46608
|
let content;
|
|
46180
46609
|
try {
|
|
46181
|
-
content =
|
|
46610
|
+
content = readFileSync8(path, "utf8");
|
|
46182
46611
|
} catch (err) {
|
|
46183
46612
|
const msg = err instanceof Error ? err.message : String(err);
|
|
46184
46613
|
throw userError(`Cannot read ${path}: ${msg}`);
|
|
@@ -46186,7 +46615,7 @@ async function readContent(path, paste) {
|
|
|
46186
46615
|
const titleFromPath = basename2(path, extname2(path));
|
|
46187
46616
|
return { content, titleFromPath };
|
|
46188
46617
|
}
|
|
46189
|
-
async function
|
|
46618
|
+
async function action12(path, options) {
|
|
46190
46619
|
const { content, titleFromPath } = await readContent(path, Boolean(options.paste));
|
|
46191
46620
|
const title = options.title ?? titleFromPath;
|
|
46192
46621
|
if (!title || title.trim() === "") {
|
|
@@ -46258,7 +46687,7 @@ async function action11(path, options) {
|
|
|
46258
46687
|
}
|
|
46259
46688
|
}
|
|
46260
46689
|
function registerIngest(program2) {
|
|
46261
|
-
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(
|
|
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(action12);
|
|
46262
46691
|
}
|
|
46263
46692
|
|
|
46264
46693
|
// src/cli/commands/ingest-dir.ts
|
|
@@ -46266,18 +46695,18 @@ init_dist4();
|
|
|
46266
46695
|
init_cli_core();
|
|
46267
46696
|
init_config();
|
|
46268
46697
|
var import_cli_progress = __toESM(require_cli_progress(), 1);
|
|
46269
|
-
import { readdirSync as
|
|
46270
|
-
import { basename as basename3, extname as extname3, join as
|
|
46698
|
+
import { readdirSync as readdirSync4, statSync as statSync3 } from "node:fs";
|
|
46699
|
+
import { basename as basename3, extname as extname3, join as join7 } from "node:path";
|
|
46271
46700
|
function walk(dir, extensions) {
|
|
46272
46701
|
let entries;
|
|
46273
46702
|
try {
|
|
46274
|
-
entries =
|
|
46703
|
+
entries = readdirSync4(dir);
|
|
46275
46704
|
} catch (err) {
|
|
46276
46705
|
throw userError(`Cannot read directory ${dir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
46277
46706
|
}
|
|
46278
46707
|
const files = [];
|
|
46279
46708
|
for (const name of entries) {
|
|
46280
|
-
const full =
|
|
46709
|
+
const full = join7(dir, name);
|
|
46281
46710
|
let stat;
|
|
46282
46711
|
try {
|
|
46283
46712
|
stat = statSync3(full);
|
|
@@ -46294,7 +46723,7 @@ function walk(dir, extensions) {
|
|
|
46294
46723
|
}
|
|
46295
46724
|
return files;
|
|
46296
46725
|
}
|
|
46297
|
-
async function
|
|
46726
|
+
async function action13(dir, options) {
|
|
46298
46727
|
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));
|
|
46299
46728
|
const files = walk(dir, extensions);
|
|
46300
46729
|
if (files.length === 0) {
|
|
@@ -46367,29 +46796,30 @@ async function action12(dir, options) {
|
|
|
46367
46796
|
}
|
|
46368
46797
|
}
|
|
46369
46798
|
function registerIngestDir(program2) {
|
|
46370
|
-
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(
|
|
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(action13);
|
|
46371
46800
|
}
|
|
46372
46801
|
|
|
46373
46802
|
// src/cli/commands/init.ts
|
|
46374
46803
|
init_cli_core();
|
|
46375
46804
|
init_config();
|
|
46805
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
46376
46806
|
import {
|
|
46377
46807
|
chmodSync,
|
|
46378
46808
|
copyFileSync as copyFileSync2,
|
|
46379
|
-
existsSync as
|
|
46809
|
+
existsSync as existsSync9,
|
|
46380
46810
|
mkdirSync as mkdirSync3,
|
|
46381
|
-
readFileSync as
|
|
46811
|
+
readFileSync as readFileSync10,
|
|
46382
46812
|
writeFileSync as writeFileSync3
|
|
46383
46813
|
} from "node:fs";
|
|
46384
46814
|
import { homedir as homedir5 } from "node:os";
|
|
46385
|
-
import { dirname as
|
|
46815
|
+
import { dirname as dirname4, join as join8 } from "node:path";
|
|
46386
46816
|
async function readConfigFile(path) {
|
|
46387
|
-
if (!
|
|
46817
|
+
if (!existsSync9(path)) {
|
|
46388
46818
|
throw userError(`--config file not found: ${path}`);
|
|
46389
46819
|
}
|
|
46390
46820
|
let parsed;
|
|
46391
46821
|
try {
|
|
46392
|
-
parsed = JSON.parse(
|
|
46822
|
+
parsed = JSON.parse(readFileSync10(path, "utf8"));
|
|
46393
46823
|
} catch (err) {
|
|
46394
46824
|
throw userError(`--config: invalid JSON in ${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
46395
46825
|
}
|
|
@@ -46431,7 +46861,7 @@ function parseDotEnvFile(content) {
|
|
|
46431
46861
|
return map;
|
|
46432
46862
|
}
|
|
46433
46863
|
function answersFromEnvFile(path) {
|
|
46434
|
-
const parsed = parseDotEnvFile(
|
|
46864
|
+
const parsed = parseDotEnvFile(readFileSync10(path, "utf8"));
|
|
46435
46865
|
const required = ["CEREFOX_SUPABASE_URL", "CEREFOX_SUPABASE_KEY", "OPENAI_API_KEY"];
|
|
46436
46866
|
for (const key of required) {
|
|
46437
46867
|
if (!parsed[key] || parsed[key].trim() === "") {
|
|
@@ -46592,14 +47022,60 @@ async function promptMigrationChoice() {
|
|
|
46592
47022
|
const ch = choice.trim().toLowerCase() || "c";
|
|
46593
47023
|
return ch;
|
|
46594
47024
|
}
|
|
46595
|
-
async function
|
|
46596
|
-
|
|
47025
|
+
async function probeSchemaVersion(url, key) {
|
|
47026
|
+
try {
|
|
47027
|
+
const resp = await fetch(`${url.replace(/\/$/, "")}/rest/v1/rpc/cerefox_schema_version`, {
|
|
47028
|
+
method: "POST",
|
|
47029
|
+
headers: { "Content-Type": "application/json", apikey: key, Authorization: `Bearer ${key}` },
|
|
47030
|
+
body: "{}"
|
|
47031
|
+
});
|
|
47032
|
+
if (!resp.ok)
|
|
47033
|
+
return null;
|
|
47034
|
+
const data = await resp.json();
|
|
47035
|
+
return typeof data === "string" ? data : null;
|
|
47036
|
+
} catch {
|
|
47037
|
+
return null;
|
|
47038
|
+
}
|
|
47039
|
+
}
|
|
47040
|
+
function launchDeployServer(extraArgs = []) {
|
|
47041
|
+
const r = spawnSync4(process.execPath, [process.argv[1], "deploy-server", ...extraArgs], {
|
|
47042
|
+
stdio: "inherit"
|
|
47043
|
+
});
|
|
47044
|
+
return r.status ?? 1;
|
|
47045
|
+
}
|
|
47046
|
+
async function maybeOfferServerDeploy() {
|
|
47047
|
+
const settings = loadSettings();
|
|
47048
|
+
if (!settings.supabaseUrl || !settings.supabaseKey)
|
|
47049
|
+
return;
|
|
47050
|
+
const deployed = await probeSchemaVersion(settings.supabaseUrl, settings.supabaseKey);
|
|
47051
|
+
if (deployed === null) {
|
|
46597
47052
|
println(c.bold("Schema deploy"));
|
|
46598
|
-
println(c.dim(
|
|
46599
|
-
|
|
46600
|
-
|
|
46601
|
-
|
|
47053
|
+
println(c.dim(" No Cerefox schema detected on this Supabase project."));
|
|
47054
|
+
const yes = await confirm(" Deploy the server now (schema + RPCs + Edge Functions)?", false);
|
|
47055
|
+
if (yes)
|
|
47056
|
+
launchDeployServer();
|
|
47057
|
+
else
|
|
47058
|
+
println(c.dim(" Skipped. Run `cerefox deploy-server` later (or `cerefox doctor` to recheck)."));
|
|
46602
47059
|
println("");
|
|
47060
|
+
return;
|
|
47061
|
+
}
|
|
47062
|
+
if (compareSemver(deployed, COMPATIBILITY.minSchema) < 0) {
|
|
47063
|
+
println(c.bold("Schema deploy"));
|
|
47064
|
+
println(c.yellow(` Deployed schema v${deployed} is below the required v${COMPATIBILITY.minSchema}.`));
|
|
47065
|
+
const yes = await confirm(" Redeploy the server now (--reset DROPS existing data)?", true);
|
|
47066
|
+
if (yes)
|
|
47067
|
+
launchDeployServer(["--reset"]);
|
|
47068
|
+
else
|
|
47069
|
+
println(c.dim(" Skipped. Run `cerefox deploy-server --reset` when ready."));
|
|
47070
|
+
println("");
|
|
47071
|
+
return;
|
|
47072
|
+
}
|
|
47073
|
+
println(c.dim(`Schema v${deployed} already deployed (≥ required v${COMPATIBILITY.minSchema}).`));
|
|
47074
|
+
println("");
|
|
47075
|
+
}
|
|
47076
|
+
async function postWriteLifecycle(envPath, options) {
|
|
47077
|
+
if (!options.skipSchema) {
|
|
47078
|
+
await maybeOfferServerDeploy();
|
|
46603
47079
|
}
|
|
46604
47080
|
if (!options.skipSelfDocs) {
|
|
46605
47081
|
println(c.bold("Self-doc ingest"));
|
|
@@ -46640,7 +47116,7 @@ async function postWriteLifecycle(envPath, options) {
|
|
|
46640
47116
|
println(c.dim(` Config in effect: ${envPath}`));
|
|
46641
47117
|
}
|
|
46642
47118
|
function writeAnswersTo(target, answers) {
|
|
46643
|
-
mkdirSync3(
|
|
47119
|
+
mkdirSync3(dirname4(target), { recursive: true });
|
|
46644
47120
|
writeFileSync3(target, buildEnvFile(answers), "utf8");
|
|
46645
47121
|
if (process.platform !== "win32") {
|
|
46646
47122
|
try {
|
|
@@ -46650,13 +47126,13 @@ function writeAnswersTo(target, answers) {
|
|
|
46650
47126
|
}
|
|
46651
47127
|
}
|
|
46652
47128
|
}
|
|
46653
|
-
async function
|
|
46654
|
-
const homeEnv =
|
|
46655
|
-
const cwdEnv =
|
|
47129
|
+
async function action15(options) {
|
|
47130
|
+
const homeEnv = join8(homedir5(), USER_STATE_DIR_NAME, ".env");
|
|
47131
|
+
const cwdEnv = join8(process.cwd(), ".env");
|
|
46656
47132
|
const explicitDir = (process.env.CEREFOX_CONFIG_DIR ?? "").trim();
|
|
46657
47133
|
if (explicitDir) {
|
|
46658
47134
|
const target2 = resolveEnvFile();
|
|
46659
|
-
if (
|
|
47135
|
+
if (existsSync9(target2) && !options.force) {
|
|
46660
47136
|
println(c.yellow(`⚠ Config already exists at ${target2}.`));
|
|
46661
47137
|
const ok2 = await confirm("Overwrite?", true);
|
|
46662
47138
|
if (!ok2) {
|
|
@@ -46678,7 +47154,7 @@ async function action14(options) {
|
|
|
46678
47154
|
await postWriteLifecycle(target2, options);
|
|
46679
47155
|
return;
|
|
46680
47156
|
}
|
|
46681
|
-
if (
|
|
47157
|
+
if (existsSync9(homeEnv) && !options.force) {
|
|
46682
47158
|
println(c.yellow(`⚠ Config already exists at ${homeEnv}.`));
|
|
46683
47159
|
const ok2 = await confirm("Overwrite?", true);
|
|
46684
47160
|
if (!ok2) {
|
|
@@ -46699,12 +47175,12 @@ async function action14(options) {
|
|
|
46699
47175
|
await postWriteLifecycle(homeEnv, options);
|
|
46700
47176
|
return;
|
|
46701
47177
|
}
|
|
46702
|
-
if (
|
|
47178
|
+
if (existsSync9(cwdEnv) && !options.force && !options.config) {
|
|
46703
47179
|
printMigrationMenu(cwdEnv, homeEnv);
|
|
46704
47180
|
const ch = await promptMigrationChoice();
|
|
46705
47181
|
println("");
|
|
46706
47182
|
if (ch === "c") {
|
|
46707
|
-
mkdirSync3(
|
|
47183
|
+
mkdirSync3(dirname4(homeEnv), { recursive: true });
|
|
46708
47184
|
copyFileSync2(cwdEnv, homeEnv);
|
|
46709
47185
|
if (process.platform !== "win32") {
|
|
46710
47186
|
try {
|
|
@@ -46759,13 +47235,13 @@ async function action14(options) {
|
|
|
46759
47235
|
await postWriteLifecycle(target, options);
|
|
46760
47236
|
}
|
|
46761
47237
|
function registerInit(program2) {
|
|
46762
|
-
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(
|
|
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(action15);
|
|
46763
47239
|
}
|
|
46764
47240
|
|
|
46765
47241
|
// src/cli/commands/list-docs.ts
|
|
46766
47242
|
init_cli_core();
|
|
46767
47243
|
init_client();
|
|
46768
|
-
async function
|
|
47244
|
+
async function action16(options) {
|
|
46769
47245
|
const limit = parsePositiveInt(options.limit, "--limit", 100);
|
|
46770
47246
|
const client = getClient();
|
|
46771
47247
|
let projectId;
|
|
@@ -46820,13 +47296,13 @@ async function action15(options) {
|
|
|
46820
47296
|
})));
|
|
46821
47297
|
}
|
|
46822
47298
|
function registerListDocs(program2) {
|
|
46823
|
-
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(
|
|
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(action16);
|
|
46824
47300
|
}
|
|
46825
47301
|
|
|
46826
47302
|
// src/cli/commands/list-metadata-keys.ts
|
|
46827
47303
|
init_cli_core();
|
|
46828
47304
|
init_client();
|
|
46829
|
-
async function
|
|
47305
|
+
async function action17(options) {
|
|
46830
47306
|
const client = getClient();
|
|
46831
47307
|
const data = await client.rpc("cerefox_list_metadata_keys");
|
|
46832
47308
|
if (data === null) {
|
|
@@ -46854,13 +47330,13 @@ async function action16(options) {
|
|
|
46854
47330
|
})));
|
|
46855
47331
|
}
|
|
46856
47332
|
function registerListMetadataKeys(program2) {
|
|
46857
|
-
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(
|
|
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(action17);
|
|
46858
47334
|
}
|
|
46859
47335
|
|
|
46860
47336
|
// src/cli/commands/list-projects.ts
|
|
46861
47337
|
init_cli_core();
|
|
46862
47338
|
init_client();
|
|
46863
|
-
async function
|
|
47339
|
+
async function action18(options) {
|
|
46864
47340
|
const client = getClient();
|
|
46865
47341
|
const { data, error: error2 } = await client.raw.from("cerefox_projects").select("id, name, description, created_at").order("name", { ascending: true });
|
|
46866
47342
|
if (error2) {
|
|
@@ -46889,13 +47365,13 @@ async function action17(options) {
|
|
|
46889
47365
|
})), "(no projects)");
|
|
46890
47366
|
}
|
|
46891
47367
|
function registerListProjects(program2) {
|
|
46892
|
-
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(
|
|
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(action18);
|
|
46893
47369
|
}
|
|
46894
47370
|
|
|
46895
47371
|
// src/cli/commands/list-versions.ts
|
|
46896
47372
|
init_cli_core();
|
|
46897
47373
|
init_client();
|
|
46898
|
-
async function
|
|
47374
|
+
async function action19(documentId, options) {
|
|
46899
47375
|
const client = getClient();
|
|
46900
47376
|
const data = await client.rpc("cerefox_list_document_versions", {
|
|
46901
47377
|
p_document_id: documentId
|
|
@@ -46936,7 +47412,7 @@ async function action18(documentId, options) {
|
|
|
46936
47412
|
})));
|
|
46937
47413
|
}
|
|
46938
47414
|
function registerListVersions(program2) {
|
|
46939
|
-
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(
|
|
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(action19);
|
|
46940
47416
|
}
|
|
46941
47417
|
|
|
46942
47418
|
// src/cli/commands/mcp.ts
|
|
@@ -46951,7 +47427,7 @@ function registerMcp(program2) {
|
|
|
46951
47427
|
// src/cli/commands/metadata-search.ts
|
|
46952
47428
|
init_cli_core();
|
|
46953
47429
|
init_client();
|
|
46954
|
-
async function
|
|
47430
|
+
async function action20(options) {
|
|
46955
47431
|
const metadataFilter = parseJsonObjectArg(options.metadataFilter, "--metadata-filter");
|
|
46956
47432
|
if (!metadataFilter || Object.keys(metadataFilter).length === 0) {
|
|
46957
47433
|
throw userError("--metadata-filter is required and must be a non-empty JSON object.", `Example: --metadata-filter '{"type":"decision-log"}'.`);
|
|
@@ -47014,7 +47490,7 @@ async function action19(options) {
|
|
|
47014
47490
|
}
|
|
47015
47491
|
}
|
|
47016
47492
|
function registerMetadataSearch(program2) {
|
|
47017
|
-
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(
|
|
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(action20);
|
|
47018
47494
|
}
|
|
47019
47495
|
|
|
47020
47496
|
// src/cli/commands/reindex.ts
|
|
@@ -47022,7 +47498,7 @@ init_dist4();
|
|
|
47022
47498
|
init_cli_core();
|
|
47023
47499
|
init_config();
|
|
47024
47500
|
var DEFAULT_MODEL = "text-embedding-3-small";
|
|
47025
|
-
async function
|
|
47501
|
+
async function action21(options) {
|
|
47026
47502
|
const settings = loadSettings();
|
|
47027
47503
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
47028
47504
|
throw userError("Supabase credentials not configured — run `cerefox init` first.");
|
|
@@ -47101,41 +47577,41 @@ ${c2.content}`;
|
|
|
47101
47577
|
}
|
|
47102
47578
|
}
|
|
47103
47579
|
function registerReindex(program2) {
|
|
47104
|
-
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(
|
|
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(action21);
|
|
47105
47581
|
}
|
|
47106
47582
|
|
|
47107
47583
|
// src/cli/commands/restore.ts
|
|
47108
47584
|
init_cli_core();
|
|
47109
47585
|
init_client();
|
|
47110
|
-
import { existsSync as
|
|
47586
|
+
import { existsSync as existsSync10, readFileSync as readFileSync11, readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
|
|
47111
47587
|
import { homedir as homedir6 } from "node:os";
|
|
47112
|
-
import { join as
|
|
47588
|
+
import { join as join9, resolve as resolve4 } from "node:path";
|
|
47113
47589
|
function expandHome2(path) {
|
|
47114
47590
|
if (path === "~")
|
|
47115
47591
|
return homedir6();
|
|
47116
47592
|
if (path.startsWith("~/"))
|
|
47117
|
-
return
|
|
47593
|
+
return join9(homedir6(), path.slice(2));
|
|
47118
47594
|
return path;
|
|
47119
47595
|
}
|
|
47120
47596
|
function resolveBackupFile(target) {
|
|
47121
47597
|
const path = resolve4(expandHome2(target));
|
|
47122
|
-
if (!
|
|
47598
|
+
if (!existsSync10(path)) {
|
|
47123
47599
|
throw userError(`Backup path not found: ${target}`);
|
|
47124
47600
|
}
|
|
47125
47601
|
const stat = statSync4(path);
|
|
47126
47602
|
if (stat.isFile())
|
|
47127
47603
|
return path;
|
|
47128
|
-
const candidates =
|
|
47604
|
+
const candidates = readdirSync5(path).filter((n) => n.endsWith(".json") && n.startsWith("cerefox-")).map((n) => ({ name: n, mtime: statSync4(join9(path, n)).mtimeMs })).sort((a, b2) => b2.mtime - a.mtime);
|
|
47129
47605
|
if (candidates.length === 0) {
|
|
47130
47606
|
throw userError(`No cerefox-*.json files in ${path}`);
|
|
47131
47607
|
}
|
|
47132
|
-
return
|
|
47608
|
+
return join9(path, candidates[0].name);
|
|
47133
47609
|
}
|
|
47134
|
-
async function
|
|
47610
|
+
async function action22(target, options) {
|
|
47135
47611
|
const file = resolveBackupFile(target);
|
|
47136
47612
|
let payload;
|
|
47137
47613
|
try {
|
|
47138
|
-
payload = JSON.parse(
|
|
47614
|
+
payload = JSON.parse(readFileSync11(file, "utf8"));
|
|
47139
47615
|
} catch (err) {
|
|
47140
47616
|
throw userError(`Could not parse backup file ${file}: ${err instanceof Error ? err.message : String(err)}`);
|
|
47141
47617
|
}
|
|
@@ -47187,7 +47663,7 @@ async function action21(target, options) {
|
|
|
47187
47663
|
}
|
|
47188
47664
|
}
|
|
47189
47665
|
function registerRestore(program2) {
|
|
47190
|
-
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(
|
|
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(action22);
|
|
47191
47667
|
}
|
|
47192
47668
|
|
|
47193
47669
|
// src/cli/commands/search.ts
|
|
@@ -47212,7 +47688,7 @@ async function embedQuery(query) {
|
|
|
47212
47688
|
}
|
|
47213
47689
|
|
|
47214
47690
|
// src/cli/commands/search.ts
|
|
47215
|
-
async function
|
|
47691
|
+
async function action23(query, options) {
|
|
47216
47692
|
if (!query || query.trim() === "") {
|
|
47217
47693
|
throw userError("Empty query.");
|
|
47218
47694
|
}
|
|
@@ -47346,13 +47822,13 @@ async function action22(query, options) {
|
|
|
47346
47822
|
}
|
|
47347
47823
|
}
|
|
47348
47824
|
function registerSearch(program2) {
|
|
47349
|
-
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(
|
|
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(action23);
|
|
47350
47826
|
}
|
|
47351
47827
|
|
|
47352
47828
|
// src/cli/commands/self-update.ts
|
|
47353
47829
|
init_cli_core();
|
|
47354
47830
|
init_meta();
|
|
47355
|
-
import { spawnSync as
|
|
47831
|
+
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
47356
47832
|
function detectRuntime() {
|
|
47357
47833
|
const bin = (process.argv[1] ?? "").toLowerCase();
|
|
47358
47834
|
if (bin.includes(".bun") || bin.includes("/bun/")) {
|
|
@@ -47393,7 +47869,7 @@ async function fetchLatestVersion() {
|
|
|
47393
47869
|
}
|
|
47394
47870
|
return body.version;
|
|
47395
47871
|
}
|
|
47396
|
-
async function
|
|
47872
|
+
async function action24(options) {
|
|
47397
47873
|
let target;
|
|
47398
47874
|
try {
|
|
47399
47875
|
target = options.version ?? await fetchLatestVersion();
|
|
@@ -47425,7 +47901,7 @@ async function action23(options) {
|
|
|
47425
47901
|
return;
|
|
47426
47902
|
}
|
|
47427
47903
|
}
|
|
47428
|
-
const result =
|
|
47904
|
+
const result = spawnSync5(runtime.command, runtime.args(target), {
|
|
47429
47905
|
stdio: "inherit"
|
|
47430
47906
|
});
|
|
47431
47907
|
if (result.status !== 0) {
|
|
@@ -47445,7 +47921,7 @@ async function action23(options) {
|
|
|
47445
47921
|
}
|
|
47446
47922
|
function registerSelfUpdate(program2) {
|
|
47447
47923
|
const desc = "Upgrade Cerefox in place. Alias: `cerefox upgrade`.";
|
|
47448
|
-
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(
|
|
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(action24);
|
|
47449
47925
|
declaration(program2.command("self-update"));
|
|
47450
47926
|
declaration(program2.command("upgrade"));
|
|
47451
47927
|
}
|
|
@@ -47464,7 +47940,7 @@ function symbol2(status) {
|
|
|
47464
47940
|
return cErr.dim("ℹ");
|
|
47465
47941
|
}
|
|
47466
47942
|
}
|
|
47467
|
-
async function
|
|
47943
|
+
async function action25(options) {
|
|
47468
47944
|
const useSpinner = !options.json && process.stderr.isTTY;
|
|
47469
47945
|
const spinner = useSpinner ? ora({ text: "Starting checks…", spinner: "dots", stream: process.stderr }).start() : null;
|
|
47470
47946
|
const results = await runFastChecks({
|
|
@@ -47485,7 +47961,7 @@ async function action24(options) {
|
|
|
47485
47961
|
}
|
|
47486
47962
|
}
|
|
47487
47963
|
function registerStatus(program2) {
|
|
47488
|
-
program2.command("status").description("Quick sanity check (fast subset of `cerefox doctor`).").option("--json", "Emit machine-readable JSON.").action(
|
|
47964
|
+
program2.command("status").description("Quick sanity check (fast subset of `cerefox doctor`).").option("--json", "Emit machine-readable JSON.").action(action25);
|
|
47489
47965
|
}
|
|
47490
47966
|
|
|
47491
47967
|
// src/cli/commands/sync-docs.ts
|
|
@@ -47494,19 +47970,19 @@ init_mcp_tools();
|
|
|
47494
47970
|
init_config();
|
|
47495
47971
|
init_client();
|
|
47496
47972
|
import {
|
|
47497
|
-
existsSync as
|
|
47498
|
-
readFileSync as
|
|
47499
|
-
readdirSync as
|
|
47973
|
+
existsSync as existsSync11,
|
|
47974
|
+
readFileSync as readFileSync12,
|
|
47975
|
+
readdirSync as readdirSync6,
|
|
47500
47976
|
statSync as statSync5
|
|
47501
47977
|
} from "node:fs";
|
|
47502
|
-
import { basename as basename5, extname as extname5, join as
|
|
47978
|
+
import { basename as basename5, extname as extname5, join as join10, relative } from "node:path";
|
|
47503
47979
|
var ROOT_LEVEL_DOCS = ["README.md", "AGENT_GUIDE.md", "AGENT_QUICK_REFERENCE.md"];
|
|
47504
47980
|
function walkMarkdown(dir) {
|
|
47505
47981
|
const out = [];
|
|
47506
|
-
if (!
|
|
47982
|
+
if (!existsSync11(dir))
|
|
47507
47983
|
return out;
|
|
47508
|
-
for (const name of
|
|
47509
|
-
const full =
|
|
47984
|
+
for (const name of readdirSync6(dir)) {
|
|
47985
|
+
const full = join10(dir, name);
|
|
47510
47986
|
let stat;
|
|
47511
47987
|
try {
|
|
47512
47988
|
stat = statSync5(full);
|
|
@@ -47521,16 +47997,16 @@ function walkMarkdown(dir) {
|
|
|
47521
47997
|
}
|
|
47522
47998
|
return out;
|
|
47523
47999
|
}
|
|
47524
|
-
async function
|
|
48000
|
+
async function action26(options) {
|
|
47525
48001
|
const cwd = process.cwd();
|
|
47526
48002
|
const project = options.project ?? "cerefox";
|
|
47527
48003
|
const targets = [];
|
|
47528
48004
|
for (const rel of ROOT_LEVEL_DOCS) {
|
|
47529
|
-
const abs =
|
|
47530
|
-
if (
|
|
48005
|
+
const abs = join10(cwd, rel);
|
|
48006
|
+
if (existsSync11(abs))
|
|
47531
48007
|
targets.push({ abs, rel });
|
|
47532
48008
|
}
|
|
47533
|
-
for (const abs of walkMarkdown(
|
|
48009
|
+
for (const abs of walkMarkdown(join10(cwd, "docs"))) {
|
|
47534
48010
|
targets.push({ abs, rel: relative(cwd, abs) });
|
|
47535
48011
|
}
|
|
47536
48012
|
if (targets.length === 0) {
|
|
@@ -47554,7 +48030,7 @@ async function action25(options) {
|
|
|
47554
48030
|
const authorType = resolveAuthorType("agent");
|
|
47555
48031
|
const outcomes = [];
|
|
47556
48032
|
for (const t of targets) {
|
|
47557
|
-
const content =
|
|
48033
|
+
const content = readFileSync12(t.abs, "utf8");
|
|
47558
48034
|
const title = basename5(t.abs, extname5(t.abs));
|
|
47559
48035
|
try {
|
|
47560
48036
|
const message = await ingestTool.handler(client.raw, {
|
|
@@ -47583,7 +48059,7 @@ async function action25(options) {
|
|
|
47583
48059
|
}
|
|
47584
48060
|
}
|
|
47585
48061
|
function registerSyncDocs(program2) {
|
|
47586
|
-
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(
|
|
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(action26);
|
|
47587
48063
|
}
|
|
47588
48064
|
|
|
47589
48065
|
// src/cli/program.ts
|
|
@@ -48918,8 +49394,8 @@ var _baseMimes = {
|
|
|
48918
49394
|
var baseMimes = _baseMimes;
|
|
48919
49395
|
|
|
48920
49396
|
// ../../node_modules/.bun/@hono+node-server@2.0.4+1bbe96acb4c5ebf1/node_modules/@hono/node-server/dist/serve-static.mjs
|
|
48921
|
-
import { createReadStream, existsSync as
|
|
48922
|
-
import { join as
|
|
49397
|
+
import { createReadStream, existsSync as existsSync12, statSync as statSync6 } from "node:fs";
|
|
49398
|
+
import { join as join11 } from "node:path";
|
|
48923
49399
|
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;
|
|
48924
49400
|
var ENCODINGS = {
|
|
48925
49401
|
br: ".br",
|
|
@@ -48951,7 +49427,7 @@ var tryDecodeURI = (str) => tryDecode(str, decodeURI);
|
|
|
48951
49427
|
var serveStatic = (options = { root: "" }) => {
|
|
48952
49428
|
const root = options.root || "";
|
|
48953
49429
|
const optionPath = options.path;
|
|
48954
|
-
if (root !== "" && !
|
|
49430
|
+
if (root !== "" && !existsSync12(root))
|
|
48955
49431
|
console.error(`serveStatic: root path '${root}' is not found, are you sure it's correct?`);
|
|
48956
49432
|
return async (c2, next) => {
|
|
48957
49433
|
if (c2.finalized)
|
|
@@ -48968,11 +49444,11 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
48968
49444
|
await options.onNotFound?.(c2.req.path, c2);
|
|
48969
49445
|
return next();
|
|
48970
49446
|
}
|
|
48971
|
-
let path =
|
|
49447
|
+
let path = join11(root, !optionPath && options.rewriteRequestPath ? options.rewriteRequestPath(filename, c2) : filename);
|
|
48972
49448
|
let stats = getStats(path);
|
|
48973
49449
|
if (stats && stats.isDirectory()) {
|
|
48974
49450
|
const indexFile = options.index ?? "index.html";
|
|
48975
|
-
path =
|
|
49451
|
+
path = join11(path, indexFile);
|
|
48976
49452
|
stats = getStats(path);
|
|
48977
49453
|
}
|
|
48978
49454
|
if (!stats) {
|
|
@@ -49029,9 +49505,9 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
49029
49505
|
};
|
|
49030
49506
|
|
|
49031
49507
|
// src/web/server.ts
|
|
49032
|
-
import { existsSync as
|
|
49033
|
-
import { readFileSync as
|
|
49034
|
-
import { join as
|
|
49508
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
49509
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
49510
|
+
import { join as join14 } from "node:path";
|
|
49035
49511
|
|
|
49036
49512
|
// ../../node_modules/.bun/hono@4.12.23/node_modules/hono/dist/compose.js
|
|
49037
49513
|
var compose = (middleware, onError, onNotFound) => {
|
|
@@ -50579,6 +51055,66 @@ var Hono2 = class extends Hono {
|
|
|
50579
51055
|
}
|
|
50580
51056
|
};
|
|
50581
51057
|
|
|
51058
|
+
// ../../node_modules/.bun/hono@4.12.23/node_modules/hono/dist/utils/color.js
|
|
51059
|
+
function getColorEnabled() {
|
|
51060
|
+
const { process: process10, Deno: Deno2 } = globalThis;
|
|
51061
|
+
const isNoColor = typeof Deno2?.noColor === "boolean" ? Deno2.noColor : process10 !== undefined ? "NO_COLOR" in process10?.env : false;
|
|
51062
|
+
return !isNoColor;
|
|
51063
|
+
}
|
|
51064
|
+
async function getColorEnabledAsync() {
|
|
51065
|
+
const { navigator: navigator2 } = globalThis;
|
|
51066
|
+
const cfWorkers = "cloudflare:workers";
|
|
51067
|
+
const isNoColor = navigator2 !== undefined && navigator2.userAgent === "Cloudflare-Workers" ? await (async () => {
|
|
51068
|
+
try {
|
|
51069
|
+
return "NO_COLOR" in ((await import(cfWorkers)).env ?? {});
|
|
51070
|
+
} catch {
|
|
51071
|
+
return false;
|
|
51072
|
+
}
|
|
51073
|
+
})() : !getColorEnabled();
|
|
51074
|
+
return !isNoColor;
|
|
51075
|
+
}
|
|
51076
|
+
|
|
51077
|
+
// ../../node_modules/.bun/hono@4.12.23/node_modules/hono/dist/middleware/logger/index.js
|
|
51078
|
+
var humanize = (times) => {
|
|
51079
|
+
const [delimiter, separator] = [",", "."];
|
|
51080
|
+
const orderTimes = times.map((v) => v.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1" + delimiter));
|
|
51081
|
+
return orderTimes.join(separator);
|
|
51082
|
+
};
|
|
51083
|
+
var time3 = (start) => {
|
|
51084
|
+
const delta = Date.now() - start;
|
|
51085
|
+
return humanize([delta < 1000 ? delta + "ms" : Math.round(delta / 1000) + "s"]);
|
|
51086
|
+
};
|
|
51087
|
+
var colorStatus = async (status) => {
|
|
51088
|
+
const colorEnabled = await getColorEnabledAsync();
|
|
51089
|
+
if (colorEnabled) {
|
|
51090
|
+
switch (status / 100 | 0) {
|
|
51091
|
+
case 5:
|
|
51092
|
+
return `\x1B[31m${status}\x1B[0m`;
|
|
51093
|
+
case 4:
|
|
51094
|
+
return `\x1B[33m${status}\x1B[0m`;
|
|
51095
|
+
case 3:
|
|
51096
|
+
return `\x1B[36m${status}\x1B[0m`;
|
|
51097
|
+
case 2:
|
|
51098
|
+
return `\x1B[32m${status}\x1B[0m`;
|
|
51099
|
+
}
|
|
51100
|
+
}
|
|
51101
|
+
return `${status}`;
|
|
51102
|
+
};
|
|
51103
|
+
async function log(fn, prefix, method, path, status = 0, elapsed) {
|
|
51104
|
+
const out = prefix === "<--" ? `${prefix} ${method} ${path}` : `${prefix} ${method} ${path} ${await colorStatus(status)} ${elapsed}`;
|
|
51105
|
+
fn(out);
|
|
51106
|
+
}
|
|
51107
|
+
var logger = (fn = console.log) => {
|
|
51108
|
+
return async function logger2(c2, next) {
|
|
51109
|
+
const { method, url } = c2.req;
|
|
51110
|
+
const path = url.slice(url.indexOf("/", 8));
|
|
51111
|
+
await log(fn, "<--", method, path);
|
|
51112
|
+
const start = Date.now();
|
|
51113
|
+
await next();
|
|
51114
|
+
await log(fn, "-->", method, path, c2.res.status, time3(start));
|
|
51115
|
+
};
|
|
51116
|
+
};
|
|
51117
|
+
|
|
50582
51118
|
// src/web/context.ts
|
|
50583
51119
|
init_dist4();
|
|
50584
51120
|
init_config();
|
|
@@ -51820,13 +52356,13 @@ import { execFileSync } from "node:child_process";
|
|
|
51820
52356
|
|
|
51821
52357
|
// src/web/docs.ts
|
|
51822
52358
|
import {
|
|
51823
|
-
existsSync as
|
|
51824
|
-
readFileSync as
|
|
51825
|
-
readdirSync as
|
|
52359
|
+
existsSync as existsSync13,
|
|
52360
|
+
readFileSync as readFileSync13,
|
|
52361
|
+
readdirSync as readdirSync7,
|
|
51826
52362
|
statSync as statSync7
|
|
51827
52363
|
} from "node:fs";
|
|
51828
|
-
import { basename as basename6, dirname as
|
|
51829
|
-
import { fileURLToPath as
|
|
52364
|
+
import { basename as basename6, dirname as dirname5, join as join12, resolve as resolve5 } from "node:path";
|
|
52365
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
51830
52366
|
var TOP_LEVEL_DOCS = [
|
|
51831
52367
|
{ filename: "README.md", path: "README.md", category: "readme" },
|
|
51832
52368
|
{
|
|
@@ -51840,38 +52376,38 @@ var TOP_LEVEL_DOCS = [
|
|
|
51840
52376
|
category: "agent-guide"
|
|
51841
52377
|
}
|
|
51842
52378
|
];
|
|
51843
|
-
function
|
|
51844
|
-
return
|
|
52379
|
+
function moduleDir2() {
|
|
52380
|
+
return dirname5(fileURLToPath3(import.meta.url));
|
|
51845
52381
|
}
|
|
51846
52382
|
function resolveDocsRoots() {
|
|
51847
|
-
const here =
|
|
52383
|
+
const here = moduleDir2();
|
|
51848
52384
|
const pkgRootCandidates = [
|
|
51849
|
-
|
|
51850
|
-
|
|
52385
|
+
join12(here, "..", ".."),
|
|
52386
|
+
join12(here, "..", "..", "..", "..")
|
|
51851
52387
|
];
|
|
51852
52388
|
let pkgGuides = null;
|
|
51853
52389
|
let pkgTopLevel = null;
|
|
51854
52390
|
for (const pkg of pkgRootCandidates) {
|
|
51855
|
-
const guides =
|
|
51856
|
-
if (
|
|
52391
|
+
const guides = join12(pkg, "docs", "guides");
|
|
52392
|
+
if (existsSync13(guides) && statSync7(guides).isDirectory()) {
|
|
51857
52393
|
pkgGuides = guides;
|
|
51858
52394
|
pkgTopLevel = pkg;
|
|
51859
52395
|
break;
|
|
51860
52396
|
}
|
|
51861
52397
|
}
|
|
51862
|
-
const repoCandidate =
|
|
51863
|
-
const repoGuides =
|
|
52398
|
+
const repoCandidate = join12(here, "..", "..", "..", "..");
|
|
52399
|
+
const repoGuides = join12(repoCandidate, "docs", "guides");
|
|
51864
52400
|
const repoTopLevel = repoCandidate;
|
|
51865
52401
|
return {
|
|
51866
52402
|
pkgGuides,
|
|
51867
52403
|
pkgTopLevel,
|
|
51868
|
-
repoGuides:
|
|
51869
|
-
repoTopLevel:
|
|
52404
|
+
repoGuides: existsSync13(repoGuides) ? repoGuides : null,
|
|
52405
|
+
repoTopLevel: existsSync13(join12(repoTopLevel, "README.md")) ? repoTopLevel : null
|
|
51870
52406
|
};
|
|
51871
52407
|
}
|
|
51872
52408
|
function readH1(filePath) {
|
|
51873
52409
|
try {
|
|
51874
|
-
const content =
|
|
52410
|
+
const content = readFileSync13(filePath, "utf8");
|
|
51875
52411
|
const match2 = content.match(/^#\s+(.+?)\s*$/m);
|
|
51876
52412
|
return match2 ? match2[1] : null;
|
|
51877
52413
|
} catch {
|
|
@@ -51891,17 +52427,17 @@ function listBundledDocs2() {
|
|
|
51891
52427
|
const topRoot = pkgTopLevel ?? repoTopLevel;
|
|
51892
52428
|
if (topRoot) {
|
|
51893
52429
|
for (const t of TOP_LEVEL_DOCS) {
|
|
51894
|
-
const abs =
|
|
51895
|
-
if (
|
|
52430
|
+
const abs = join12(topRoot, t.filename);
|
|
52431
|
+
if (existsSync13(abs)) {
|
|
51896
52432
|
entries.push(entryForFile(abs, t.path, t.category));
|
|
51897
52433
|
}
|
|
51898
52434
|
}
|
|
51899
52435
|
}
|
|
51900
52436
|
const guidesRoot = pkgGuides ?? repoGuides;
|
|
51901
52437
|
if (guidesRoot) {
|
|
51902
|
-
const names =
|
|
52438
|
+
const names = readdirSync7(guidesRoot).filter((n) => n.endsWith(".md")).sort();
|
|
51903
52439
|
for (const name of names) {
|
|
51904
|
-
const abs =
|
|
52440
|
+
const abs = join12(guidesRoot, name);
|
|
51905
52441
|
entries.push(entryForFile(abs, `guides/${name}`, "guide"));
|
|
51906
52442
|
}
|
|
51907
52443
|
}
|
|
@@ -51915,9 +52451,9 @@ function readDoc(docPath) {
|
|
|
51915
52451
|
if (!candidate.startsWith(resolve5(root) + "/") && candidate !== resolve5(root)) {
|
|
51916
52452
|
continue;
|
|
51917
52453
|
}
|
|
51918
|
-
if (
|
|
52454
|
+
if (existsSync13(candidate) && statSync7(candidate).isFile()) {
|
|
51919
52455
|
try {
|
|
51920
|
-
return
|
|
52456
|
+
return readFileSync13(candidate, "utf8");
|
|
51921
52457
|
} catch {
|
|
51922
52458
|
return null;
|
|
51923
52459
|
}
|
|
@@ -51963,17 +52499,17 @@ function registerMetaRoutes(app, ctx) {
|
|
|
51963
52499
|
app.get("/api/v1/schema-version", async (c2) => {
|
|
51964
52500
|
let bundled = null;
|
|
51965
52501
|
try {
|
|
51966
|
-
const { readFileSync:
|
|
51967
|
-
const { fileURLToPath:
|
|
51968
|
-
const { dirname:
|
|
51969
|
-
const here =
|
|
52502
|
+
const { readFileSync: readFileSync14, existsSync: existsSync14 } = await import("node:fs");
|
|
52503
|
+
const { fileURLToPath: fileURLToPath4 } = await import("node:url");
|
|
52504
|
+
const { dirname: dirname6, join: join13 } = await import("node:path");
|
|
52505
|
+
const here = dirname6(fileURLToPath4(import.meta.url));
|
|
51970
52506
|
const candidates = [
|
|
51971
|
-
|
|
51972
|
-
|
|
52507
|
+
join13(here, "..", "..", "..", "db", "schema.sql"),
|
|
52508
|
+
join13(here, "..", "..", "..", "..", "..", "src", "cerefox", "db", "schema.sql")
|
|
51973
52509
|
];
|
|
51974
52510
|
for (const path of candidates) {
|
|
51975
|
-
if (
|
|
51976
|
-
const sql =
|
|
52511
|
+
if (existsSync14(path)) {
|
|
52512
|
+
const sql = readFileSync14(path, "utf8");
|
|
51977
52513
|
const match2 = sql.match(SCHEMA_VERSION_RE);
|
|
51978
52514
|
bundled = match2 ? match2[1] : null;
|
|
51979
52515
|
break;
|
|
@@ -52011,7 +52547,14 @@ function registerMetaRoutes(app, ctx) {
|
|
|
52011
52547
|
} catch {}
|
|
52012
52548
|
}
|
|
52013
52549
|
const mismatch = Boolean(bundled && deployed && bundled !== deployed);
|
|
52014
|
-
|
|
52550
|
+
const level = classifyCompat(deployed, COMPATIBILITY.minSchema, bundled);
|
|
52551
|
+
return c2.json({
|
|
52552
|
+
bundled,
|
|
52553
|
+
deployed,
|
|
52554
|
+
mismatch,
|
|
52555
|
+
level,
|
|
52556
|
+
min: COMPATIBILITY.minSchema
|
|
52557
|
+
});
|
|
52015
52558
|
});
|
|
52016
52559
|
}
|
|
52017
52560
|
|
|
@@ -52076,21 +52619,21 @@ function registerProjectsRoutes(app, ctx) {
|
|
|
52076
52619
|
}
|
|
52077
52620
|
|
|
52078
52621
|
// src/web/static.ts
|
|
52079
|
-
import { existsSync as
|
|
52080
|
-
import { dirname as
|
|
52081
|
-
import { fileURLToPath as
|
|
52082
|
-
function
|
|
52083
|
-
return
|
|
52622
|
+
import { existsSync as existsSync14, statSync as statSync8 } from "node:fs";
|
|
52623
|
+
import { dirname as dirname6, join as join13 } from "node:path";
|
|
52624
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
52625
|
+
function moduleDir3() {
|
|
52626
|
+
return dirname6(fileURLToPath4(import.meta.url));
|
|
52084
52627
|
}
|
|
52085
52628
|
function isUsableSpaDir(dir) {
|
|
52086
|
-
return
|
|
52629
|
+
return existsSync14(dir) && statSync8(dir).isDirectory() && existsSync14(join13(dir, "index.html"));
|
|
52087
52630
|
}
|
|
52088
52631
|
function resolveSpaDist() {
|
|
52089
|
-
const here =
|
|
52632
|
+
const here = moduleDir3();
|
|
52090
52633
|
const candidates = [
|
|
52091
|
-
|
|
52092
|
-
|
|
52093
|
-
|
|
52634
|
+
join13(here, "..", "frontend"),
|
|
52635
|
+
join13(here, "..", "..", "..", "..", "frontend", "dist"),
|
|
52636
|
+
join13(here, "..", "..", "dist", "frontend")
|
|
52094
52637
|
];
|
|
52095
52638
|
for (const c2 of candidates) {
|
|
52096
52639
|
if (isUsableSpaDir(c2))
|
|
@@ -52099,13 +52642,13 @@ function resolveSpaDist() {
|
|
|
52099
52642
|
return null;
|
|
52100
52643
|
}
|
|
52101
52644
|
function resolveStaticDir() {
|
|
52102
|
-
const here =
|
|
52645
|
+
const here = moduleDir3();
|
|
52103
52646
|
const candidates = [
|
|
52104
|
-
|
|
52105
|
-
|
|
52647
|
+
join13(here, "..", "static"),
|
|
52648
|
+
join13(here, "..", "..", "..", "..", "web", "static")
|
|
52106
52649
|
];
|
|
52107
52650
|
for (const c2 of candidates) {
|
|
52108
|
-
if (
|
|
52651
|
+
if (existsSync14(c2) && statSync8(c2).isDirectory())
|
|
52109
52652
|
return c2;
|
|
52110
52653
|
}
|
|
52111
52654
|
return null;
|
|
@@ -52147,8 +52690,13 @@ var ROOT_REDIRECT_HTML = `<!DOCTYPE html>
|
|
|
52147
52690
|
</html>`;
|
|
52148
52691
|
|
|
52149
52692
|
// src/web/server.ts
|
|
52693
|
+
init_meta();
|
|
52694
|
+
init_config();
|
|
52150
52695
|
function buildApp(ctx = buildWebContext()) {
|
|
52151
52696
|
const app = new Hono2;
|
|
52697
|
+
if (true) {
|
|
52698
|
+
app.use(logger());
|
|
52699
|
+
}
|
|
52152
52700
|
registerMetaRoutes(app, ctx);
|
|
52153
52701
|
if (ctx) {
|
|
52154
52702
|
registerDiscoveryRoutes(app, ctx);
|
|
@@ -52179,18 +52727,56 @@ function buildApp(ctx = buildWebContext()) {
|
|
|
52179
52727
|
root: spaDist,
|
|
52180
52728
|
rewriteRequestPath: (path) => path.replace(/^\/app/, "")
|
|
52181
52729
|
}));
|
|
52182
|
-
|
|
52183
|
-
|
|
52184
|
-
|
|
52730
|
+
app.use("/app/*", serveStatic({
|
|
52731
|
+
root: spaDist,
|
|
52732
|
+
rewriteRequestPath: (path) => path.replace(/^\/app/, "") || "/"
|
|
52733
|
+
}));
|
|
52734
|
+
const indexPath = join14(spaDist, "index.html");
|
|
52735
|
+
if (existsSync15(indexPath)) {
|
|
52736
|
+
const indexHtml = readFileSync14(indexPath, "utf8");
|
|
52185
52737
|
app.get("/app/*", (c2) => c2.html(indexHtml));
|
|
52186
52738
|
}
|
|
52187
52739
|
}
|
|
52188
52740
|
app.get("/", (c2) => c2.html(ROOT_REDIRECT_HTML));
|
|
52189
52741
|
return app;
|
|
52190
52742
|
}
|
|
52743
|
+
|
|
52744
|
+
class CompatibilityError extends Error {
|
|
52745
|
+
}
|
|
52746
|
+
async function assertServerCompatible() {
|
|
52747
|
+
const settings = loadSettings();
|
|
52748
|
+
if (!settings.supabaseUrl || !settings.supabaseAnonKey)
|
|
52749
|
+
return;
|
|
52750
|
+
let compat2;
|
|
52751
|
+
try {
|
|
52752
|
+
compat2 = await checkServerCompatibility({
|
|
52753
|
+
aggregatorUrl: aggregatorUrlFor(settings.supabaseUrl),
|
|
52754
|
+
bearer: settings.supabaseAnonKey,
|
|
52755
|
+
bundledEf: PKG_VERSION
|
|
52756
|
+
});
|
|
52757
|
+
} catch {
|
|
52758
|
+
return;
|
|
52759
|
+
}
|
|
52760
|
+
if (!compat2.blocking)
|
|
52761
|
+
return;
|
|
52762
|
+
const parts = [];
|
|
52763
|
+
if (compat2.schema.level === "below-min") {
|
|
52764
|
+
parts.push(` • schema v${compat2.schema.deployed} is below the required v${compat2.schema.min}`);
|
|
52765
|
+
}
|
|
52766
|
+
if (compat2.edgeFunctions.level === "below-min") {
|
|
52767
|
+
parts.push(` • Edge Functions v${compat2.edgeFunctions.deployed} are below the required v${compat2.edgeFunctions.min}`);
|
|
52768
|
+
}
|
|
52769
|
+
throw new CompatibilityError(`Refusing to start: the deployed Cerefox server is incompatible with this client (v${PKG_VERSION}).
|
|
52770
|
+
` + parts.join(`
|
|
52771
|
+
`) + `
|
|
52772
|
+
|
|
52773
|
+
Redeploy your server: cerefox deploy-server
|
|
52774
|
+
` + `(or downgrade the client to match the deployed server).`);
|
|
52775
|
+
}
|
|
52191
52776
|
async function buildWebServer(options = {}) {
|
|
52192
52777
|
const host = options.host ?? "127.0.0.1";
|
|
52193
52778
|
const port = options.port ?? 8000;
|
|
52779
|
+
await assertServerCompatible();
|
|
52194
52780
|
const app = buildApp();
|
|
52195
52781
|
const server = serve({ fetch: app.fetch, hostname: host, port });
|
|
52196
52782
|
return {
|
|
@@ -52202,31 +52788,263 @@ async function buildWebServer(options = {}) {
|
|
|
52202
52788
|
};
|
|
52203
52789
|
}
|
|
52204
52790
|
|
|
52791
|
+
// src/web/daemon.ts
|
|
52792
|
+
import { spawn } from "node:child_process";
|
|
52793
|
+
import {
|
|
52794
|
+
existsSync as existsSync16,
|
|
52795
|
+
mkdirSync as mkdirSync4,
|
|
52796
|
+
openSync,
|
|
52797
|
+
readFileSync as readFileSync15,
|
|
52798
|
+
rmSync,
|
|
52799
|
+
writeFileSync as writeFileSync4
|
|
52800
|
+
} from "node:fs";
|
|
52801
|
+
import { homedir as homedir7 } from "node:os";
|
|
52802
|
+
import { join as join15 } from "node:path";
|
|
52803
|
+
var STATE_DIR = join15(homedir7(), ".cerefox");
|
|
52804
|
+
var PID_FILE = join15(STATE_DIR, "web.pid");
|
|
52805
|
+
var LOG_FILE = join15(STATE_DIR, "web.log");
|
|
52806
|
+
var daemonPaths = { stateDir: STATE_DIR, pidFile: PID_FILE, logFile: LOG_FILE };
|
|
52807
|
+
function ensureStateDir() {
|
|
52808
|
+
if (!existsSync16(STATE_DIR))
|
|
52809
|
+
mkdirSync4(STATE_DIR, { recursive: true });
|
|
52810
|
+
}
|
|
52811
|
+
function readPidFile() {
|
|
52812
|
+
if (!existsSync16(PID_FILE))
|
|
52813
|
+
return null;
|
|
52814
|
+
try {
|
|
52815
|
+
const parsed = JSON.parse(readFileSync15(PID_FILE, "utf8"));
|
|
52816
|
+
if (typeof parsed.pid !== "number")
|
|
52817
|
+
return null;
|
|
52818
|
+
return {
|
|
52819
|
+
pid: parsed.pid,
|
|
52820
|
+
port: typeof parsed.port === "number" ? parsed.port : 8000,
|
|
52821
|
+
host: typeof parsed.host === "string" ? parsed.host : "127.0.0.1",
|
|
52822
|
+
startedAt: typeof parsed.startedAt === "string" ? parsed.startedAt : "unknown"
|
|
52823
|
+
};
|
|
52824
|
+
} catch {
|
|
52825
|
+
return null;
|
|
52826
|
+
}
|
|
52827
|
+
}
|
|
52828
|
+
function writePidFile(info3) {
|
|
52829
|
+
ensureStateDir();
|
|
52830
|
+
writeFileSync4(PID_FILE, JSON.stringify(info3, null, 2) + `
|
|
52831
|
+
`, "utf8");
|
|
52832
|
+
}
|
|
52833
|
+
function removePidFile() {
|
|
52834
|
+
rmSync(PID_FILE, { force: true });
|
|
52835
|
+
}
|
|
52836
|
+
function isProcessAlive(pid) {
|
|
52837
|
+
try {
|
|
52838
|
+
process.kill(pid, 0);
|
|
52839
|
+
return true;
|
|
52840
|
+
} catch (err) {
|
|
52841
|
+
return err.code === "EPERM";
|
|
52842
|
+
}
|
|
52843
|
+
}
|
|
52844
|
+
async function isResponding(host, port, timeoutMs = 1500) {
|
|
52845
|
+
const probeHost = host === "0.0.0.0" ? "127.0.0.1" : host;
|
|
52846
|
+
try {
|
|
52847
|
+
const ctrl = new AbortController;
|
|
52848
|
+
const timer2 = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
52849
|
+
try {
|
|
52850
|
+
const resp = await fetch(`http://${probeHost}:${port}/api/v1/version`, {
|
|
52851
|
+
signal: ctrl.signal
|
|
52852
|
+
});
|
|
52853
|
+
return resp.ok;
|
|
52854
|
+
} finally {
|
|
52855
|
+
clearTimeout(timer2);
|
|
52856
|
+
}
|
|
52857
|
+
} catch {
|
|
52858
|
+
return false;
|
|
52859
|
+
}
|
|
52860
|
+
}
|
|
52861
|
+
var sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
52862
|
+
function assertUnix() {
|
|
52863
|
+
if (process.platform === "win32") {
|
|
52864
|
+
throw new Error("Daemon mode (`cerefox web start/stop/status`) is not supported on Windows yet. " + "Run `cerefox web` in the foreground, or set up a Windows service manually.");
|
|
52865
|
+
}
|
|
52866
|
+
}
|
|
52867
|
+
async function startDaemon(opts) {
|
|
52868
|
+
assertUnix();
|
|
52869
|
+
ensureStateDir();
|
|
52870
|
+
const existing = readPidFile();
|
|
52871
|
+
if (existing && isProcessAlive(existing.pid)) {
|
|
52872
|
+
return existing.port === opts.port ? { kind: "already-running", info: existing } : { kind: "port-conflict", info: existing };
|
|
52873
|
+
}
|
|
52874
|
+
if (existing)
|
|
52875
|
+
removePidFile();
|
|
52876
|
+
const logFd = openSync(LOG_FILE, "a");
|
|
52877
|
+
const child = spawn(opts.runtime, [opts.scriptPath, "web", "--host", opts.host, "--port", String(opts.port)], { detached: true, stdio: ["ignore", logFd, logFd] });
|
|
52878
|
+
child.unref();
|
|
52879
|
+
if (typeof child.pid !== "number") {
|
|
52880
|
+
throw new Error("Failed to spawn the web server process (no pid).");
|
|
52881
|
+
}
|
|
52882
|
+
writePidFile({
|
|
52883
|
+
pid: child.pid,
|
|
52884
|
+
port: opts.port,
|
|
52885
|
+
host: opts.host,
|
|
52886
|
+
startedAt: new Date().toISOString()
|
|
52887
|
+
});
|
|
52888
|
+
let responding = false;
|
|
52889
|
+
for (let i = 0;i < 20; i++) {
|
|
52890
|
+
if (!isProcessAlive(child.pid))
|
|
52891
|
+
break;
|
|
52892
|
+
if (await isResponding(opts.host, opts.port)) {
|
|
52893
|
+
responding = true;
|
|
52894
|
+
break;
|
|
52895
|
+
}
|
|
52896
|
+
await sleep2(250);
|
|
52897
|
+
}
|
|
52898
|
+
return { kind: "started", pid: child.pid, responding };
|
|
52899
|
+
}
|
|
52900
|
+
async function stopDaemon() {
|
|
52901
|
+
assertUnix();
|
|
52902
|
+
const info3 = readPidFile();
|
|
52903
|
+
if (!info3 || !isProcessAlive(info3.pid)) {
|
|
52904
|
+
removePidFile();
|
|
52905
|
+
return { kind: "not-running" };
|
|
52906
|
+
}
|
|
52907
|
+
try {
|
|
52908
|
+
process.kill(info3.pid, "SIGTERM");
|
|
52909
|
+
} catch {}
|
|
52910
|
+
let forced = false;
|
|
52911
|
+
let alive = true;
|
|
52912
|
+
for (let i = 0;i < 12; i++) {
|
|
52913
|
+
await sleep2(250);
|
|
52914
|
+
if (!isProcessAlive(info3.pid)) {
|
|
52915
|
+
alive = false;
|
|
52916
|
+
break;
|
|
52917
|
+
}
|
|
52918
|
+
}
|
|
52919
|
+
if (alive) {
|
|
52920
|
+
try {
|
|
52921
|
+
process.kill(info3.pid, "SIGKILL");
|
|
52922
|
+
forced = true;
|
|
52923
|
+
} catch {}
|
|
52924
|
+
}
|
|
52925
|
+
removePidFile();
|
|
52926
|
+
return { kind: "stopped", pid: info3.pid, forced };
|
|
52927
|
+
}
|
|
52928
|
+
async function statusDaemon() {
|
|
52929
|
+
const info3 = readPidFile();
|
|
52930
|
+
if (!info3)
|
|
52931
|
+
return { kind: "stopped" };
|
|
52932
|
+
if (!isProcessAlive(info3.pid))
|
|
52933
|
+
return { kind: "stale", info: info3 };
|
|
52934
|
+
const responding = await isResponding(info3.host, info3.port);
|
|
52935
|
+
return { kind: "running", info: info3, responding };
|
|
52936
|
+
}
|
|
52937
|
+
|
|
52205
52938
|
// src/cli/commands/web.ts
|
|
52939
|
+
function parsePort(raw2) {
|
|
52940
|
+
const port = Number.parseInt(raw2, 10);
|
|
52941
|
+
if (!Number.isFinite(port) || port < 1 || port > 65535) {
|
|
52942
|
+
eprintln(`Invalid --port: ${raw2}`);
|
|
52943
|
+
process.exit(2);
|
|
52944
|
+
}
|
|
52945
|
+
return port;
|
|
52946
|
+
}
|
|
52947
|
+
async function runForeground(host, port, watch) {
|
|
52948
|
+
if (watch) {
|
|
52949
|
+
info("--watch is reserved; not yet implemented.");
|
|
52950
|
+
}
|
|
52951
|
+
try {
|
|
52952
|
+
const handle = await buildWebServer({ host, port });
|
|
52953
|
+
info(`Cerefox web listening on http://${handle.host}:${handle.port}/`);
|
|
52954
|
+
println(` Web UI: http://${handle.host}:${handle.port}/app/`);
|
|
52955
|
+
println(` API: http://${handle.host}:${handle.port}/api/v1/`);
|
|
52956
|
+
const shutdown = async (signal) => {
|
|
52957
|
+
info(`Received ${signal}; shutting down.`);
|
|
52958
|
+
await handle.close().catch(() => {});
|
|
52959
|
+
process.exit(0);
|
|
52960
|
+
};
|
|
52961
|
+
process.on("SIGINT", () => void shutdown("SIGINT"));
|
|
52962
|
+
process.on("SIGTERM", () => void shutdown("SIGTERM"));
|
|
52963
|
+
} catch (err) {
|
|
52964
|
+
if (err instanceof CompatibilityError) {
|
|
52965
|
+
eprintln(err.message);
|
|
52966
|
+
} else {
|
|
52967
|
+
eprintln(`Failed to start web server: ${err instanceof Error ? err.message : String(err)}`);
|
|
52968
|
+
}
|
|
52969
|
+
process.exit(1);
|
|
52970
|
+
}
|
|
52971
|
+
}
|
|
52206
52972
|
function registerWeb(program2) {
|
|
52207
|
-
program2.command("web").description("Start the local web UI / API server.").option("--host <host>", "Bind host.", "127.0.0.1").option("--port <port>", "Bind port.", "8000").option("--watch", "Enable hot-reload (dev mode; reserved
|
|
52208
|
-
|
|
52209
|
-
|
|
52210
|
-
|
|
52211
|
-
|
|
52973
|
+
const web = program2.command("web").description("Start the local web UI / API server (foreground; see `web start` for daemon).").option("--host <host>", "Bind host.", "127.0.0.1").option("--port <port>", "Bind port.", "8000").option("--watch", "Enable hot-reload (dev mode; reserved).").action(async (rawOpts) => {
|
|
52974
|
+
await runForeground(rawOpts.host, parsePort(rawOpts.port), rawOpts.watch);
|
|
52975
|
+
});
|
|
52976
|
+
web.command("start").description("Start the web server in the background (detached daemon).").option("--host <host>", "Bind host.", "127.0.0.1").option("--port <port>", "Bind port.", "8000").action(async (rawOpts) => {
|
|
52977
|
+
const port = parsePort(rawOpts.port);
|
|
52978
|
+
try {
|
|
52979
|
+
const outcome = await startDaemon({
|
|
52980
|
+
host: rawOpts.host,
|
|
52981
|
+
port,
|
|
52982
|
+
scriptPath: process.argv[1],
|
|
52983
|
+
runtime: process.execPath
|
|
52984
|
+
});
|
|
52985
|
+
switch (outcome.kind) {
|
|
52986
|
+
case "already-running":
|
|
52987
|
+
info(`Cerefox web is already running on :${outcome.info.port} (pid ${outcome.info.pid}).`);
|
|
52988
|
+
process.exit(0);
|
|
52989
|
+
break;
|
|
52990
|
+
case "port-conflict":
|
|
52991
|
+
eprintln(`A Cerefox web daemon is already running on :${outcome.info.port} (pid ${outcome.info.pid}).
|
|
52992
|
+
` + `Stop it first (\`cerefox web stop\`) or start on its port.`);
|
|
52993
|
+
process.exit(1);
|
|
52994
|
+
break;
|
|
52995
|
+
case "started":
|
|
52996
|
+
if (outcome.responding) {
|
|
52997
|
+
info(`Cerefox web started (pid ${outcome.pid}) on http://${rawOpts.host}:${port}/`);
|
|
52998
|
+
println(` Web UI: http://${rawOpts.host}:${port}/app/`);
|
|
52999
|
+
println(c.dim(` Logs: ${daemonPaths.logFile}`));
|
|
53000
|
+
println(c.dim(` Stop: cerefox web stop`));
|
|
53001
|
+
} else {
|
|
53002
|
+
eprintln(`Started (pid ${outcome.pid}) but it is not responding on :${port} yet.
|
|
53003
|
+
` + `Check the log for errors: ${daemonPaths.logFile}`);
|
|
53004
|
+
process.exit(1);
|
|
53005
|
+
}
|
|
53006
|
+
break;
|
|
53007
|
+
}
|
|
53008
|
+
} catch (err) {
|
|
53009
|
+
eprintln(err instanceof Error ? err.message : String(err));
|
|
53010
|
+
process.exit(1);
|
|
52212
53011
|
}
|
|
52213
|
-
|
|
52214
|
-
|
|
53012
|
+
});
|
|
53013
|
+
web.command("stop").description("Stop the background web server daemon.").action(async () => {
|
|
53014
|
+
try {
|
|
53015
|
+
const outcome = await stopDaemon();
|
|
53016
|
+
if (outcome.kind === "not-running") {
|
|
53017
|
+
info("No Cerefox web daemon is running.");
|
|
53018
|
+
} else {
|
|
53019
|
+
info(`Stopped Cerefox web (pid ${outcome.pid})${outcome.forced ? " — forced (SIGKILL)" : ""}.`);
|
|
53020
|
+
}
|
|
53021
|
+
} catch (err) {
|
|
53022
|
+
eprintln(err instanceof Error ? err.message : String(err));
|
|
53023
|
+
process.exit(1);
|
|
52215
53024
|
}
|
|
53025
|
+
});
|
|
53026
|
+
web.command("status").description("Show the background web server daemon status.").action(async () => {
|
|
52216
53027
|
try {
|
|
52217
|
-
const
|
|
52218
|
-
|
|
52219
|
-
|
|
52220
|
-
|
|
52221
|
-
|
|
52222
|
-
|
|
52223
|
-
|
|
52224
|
-
|
|
52225
|
-
|
|
52226
|
-
|
|
52227
|
-
|
|
53028
|
+
const status = await statusDaemon();
|
|
53029
|
+
switch (status.kind) {
|
|
53030
|
+
case "stopped":
|
|
53031
|
+
println("Cerefox web: stopped (no daemon running).");
|
|
53032
|
+
break;
|
|
53033
|
+
case "stale":
|
|
53034
|
+
println(c.yellow(`Cerefox web: stale pidfile — process ${status.info.pid} is not running.`));
|
|
53035
|
+
println(c.dim(` Clean up: cerefox web stop (removes ${daemonPaths.pidFile})`));
|
|
53036
|
+
break;
|
|
53037
|
+
case "running":
|
|
53038
|
+
if (status.responding) {
|
|
53039
|
+
println(c.green(`Cerefox web: running on :${status.info.port} (pid ${status.info.pid}, since ${status.info.startedAt}).`));
|
|
53040
|
+
} else {
|
|
53041
|
+
println(c.yellow(`Cerefox web: process ${status.info.pid} alive but not responding on :${status.info.port}.`));
|
|
53042
|
+
println(c.dim(` Check the log: ${daemonPaths.logFile}`));
|
|
53043
|
+
}
|
|
53044
|
+
break;
|
|
53045
|
+
}
|
|
52228
53046
|
} catch (err) {
|
|
52229
|
-
eprintln(
|
|
53047
|
+
eprintln(err instanceof Error ? err.message : String(err));
|
|
52230
53048
|
process.exit(1);
|
|
52231
53049
|
}
|
|
52232
53050
|
});
|
|
@@ -52240,7 +53058,7 @@ Command groups (each row in the list above falls into one):
|
|
|
52240
53058
|
` + ` · list-metadata-keys · metadata-search · get-audit-log
|
|
52241
53059
|
` + ` WRITES ingest · ingest-dir · delete-doc
|
|
52242
53060
|
` + ` SERVERS mcp · web
|
|
52243
|
-
` + ` LIFECYCLE init · doctor · status · configure-agent · self-update · upgrade · sync-self-docs
|
|
53061
|
+
` + ` LIFECYCLE init · doctor · status · configure-agent · self-update · upgrade · sync-self-docs · deploy-server
|
|
52244
53062
|
` + ` OPS backup · restore · sync-docs · docs · reindex · config-get · config-set · completion
|
|
52245
53063
|
` + `
|
|
52246
53064
|
Exit codes:
|
|
@@ -52271,6 +53089,7 @@ Learn more:
|
|
|
52271
53089
|
registerConfigureAgent(program2);
|
|
52272
53090
|
registerSelfUpdate(program2);
|
|
52273
53091
|
registerSyncSelfDocs(program2);
|
|
53092
|
+
registerDeployServer(program2);
|
|
52274
53093
|
registerBackup(program2);
|
|
52275
53094
|
registerRestore(program2);
|
|
52276
53095
|
registerSyncDocs(program2);
|
|
@@ -52284,7 +53103,7 @@ Learn more:
|
|
|
52284
53103
|
|
|
52285
53104
|
// src/bin/cerefox.ts
|
|
52286
53105
|
async function bareEntryPoint() {
|
|
52287
|
-
const { existsSync:
|
|
53106
|
+
const { existsSync: existsSync17 } = await import("node:fs");
|
|
52288
53107
|
const { resolveEnvFile: resolveEnvFile2 } = await Promise.resolve().then(() => (init_config(), exports_config));
|
|
52289
53108
|
const { c: c2, println: println2 } = await Promise.resolve().then(() => (init_cli_core(), exports_cli_core));
|
|
52290
53109
|
const { PKG_VERSION: PKG_VERSION2 } = await Promise.resolve().then(() => (init_meta(), exports_meta));
|
|
@@ -52293,7 +53112,7 @@ async function bareEntryPoint() {
|
|
|
52293
53112
|
println2("");
|
|
52294
53113
|
let configExists = false;
|
|
52295
53114
|
try {
|
|
52296
|
-
configExists =
|
|
53115
|
+
configExists = existsSync17(resolveEnvFile2());
|
|
52297
53116
|
} catch {}
|
|
52298
53117
|
if (!configExists) {
|
|
52299
53118
|
println2(c2.yellow("⚠ No config detected."));
|