@cerefox/memory 0.9.11 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cerefox.js +114 -21
- package/dist/frontend/assets/{index-AFUS7_0T.js → index-DVXDQ7__.js} +2 -2
- package/dist/frontend/assets/{index-AFUS7_0T.js.map → index-DVXDQ7__.js.map} +1 -1
- package/dist/frontend/index.html +1 -1
- package/dist/server-assets/_shared/ef-meta/index.ts +1 -1
- package/dist/server-assets/_shared/embeddings/index.ts +34 -6
- package/dist/server-assets/_shared/mcp-tools/_utils.ts +38 -2
- package/dist/server-assets/_shared/mcp-tools/metadata-search.ts +3 -2
- package/dist/server-assets/_shared/mcp-tools/search.ts +4 -3
- package/docs/guides/cli.md +2 -2
- package/docs/guides/configuration.md +20 -20
- package/docs/guides/ops-scripts.md +1 -1
- package/docs/guides/quickstart.md +13 -7
- package/docs/guides/setup-local.md +85 -120
- package/docs/guides/setup-supabase.md +1 -1
- package/package.json +1 -1
package/dist/bin/cerefox.js
CHANGED
|
@@ -7184,7 +7184,7 @@ var exports_meta = {};
|
|
|
7184
7184
|
__export(exports_meta, {
|
|
7185
7185
|
PKG_VERSION: () => PKG_VERSION
|
|
7186
7186
|
});
|
|
7187
|
-
var PKG_VERSION = "0.
|
|
7187
|
+
var PKG_VERSION = "0.10.1";
|
|
7188
7188
|
var init_meta = () => {};
|
|
7189
7189
|
|
|
7190
7190
|
// ../../node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.js
|
|
@@ -24852,20 +24852,31 @@ var init_bundled_docs = __esm(() => {
|
|
|
24852
24852
|
});
|
|
24853
24853
|
|
|
24854
24854
|
// ../../_shared/embeddings/index.ts
|
|
24855
|
+
function openaiEmbeddingConfig() {
|
|
24856
|
+
const env4 = globalThis.process?.env ?? {};
|
|
24857
|
+
const base = env4.CEREFOX_OPENAI_BASE_URL?.replace(/\/+$/, "");
|
|
24858
|
+
const dims = Number.parseInt(env4.CEREFOX_OPENAI_EMBEDDING_DIMENSIONS ?? "", 10);
|
|
24859
|
+
return {
|
|
24860
|
+
url: base ? `${base}/embeddings` : OPENAI_EMBEDDING_URL,
|
|
24861
|
+
model: env4.CEREFOX_OPENAI_EMBEDDING_MODEL || OPENAI_MODEL,
|
|
24862
|
+
dimensions: Number.isNaN(dims) || dims <= 0 ? EMBEDDING_DIMENSIONS : dims
|
|
24863
|
+
};
|
|
24864
|
+
}
|
|
24855
24865
|
async function getEmbedding(text, apiKey) {
|
|
24856
24866
|
let lastError = null;
|
|
24867
|
+
const cfg = openaiEmbeddingConfig();
|
|
24857
24868
|
for (let attempt = 0;attempt < EMBEDDING_MAX_RETRIES; attempt++) {
|
|
24858
24869
|
try {
|
|
24859
|
-
const response = await fetch(
|
|
24870
|
+
const response = await fetch(cfg.url, {
|
|
24860
24871
|
method: "POST",
|
|
24861
24872
|
headers: {
|
|
24862
24873
|
Authorization: `Bearer ${apiKey}`,
|
|
24863
24874
|
"Content-Type": "application/json"
|
|
24864
24875
|
},
|
|
24865
24876
|
body: JSON.stringify({
|
|
24866
|
-
model:
|
|
24877
|
+
model: cfg.model,
|
|
24867
24878
|
input: text,
|
|
24868
|
-
dimensions:
|
|
24879
|
+
dimensions: cfg.dimensions
|
|
24869
24880
|
})
|
|
24870
24881
|
});
|
|
24871
24882
|
if (!response.ok) {
|
|
@@ -24896,18 +24907,19 @@ async function getEmbedding(text, apiKey) {
|
|
|
24896
24907
|
}
|
|
24897
24908
|
async function embedBatchSingleCall(texts, apiKey) {
|
|
24898
24909
|
let lastError = null;
|
|
24910
|
+
const cfg = openaiEmbeddingConfig();
|
|
24899
24911
|
for (let attempt = 0;attempt < EMBEDDING_MAX_RETRIES; attempt++) {
|
|
24900
24912
|
try {
|
|
24901
|
-
const response = await fetch(
|
|
24913
|
+
const response = await fetch(cfg.url, {
|
|
24902
24914
|
method: "POST",
|
|
24903
24915
|
headers: {
|
|
24904
24916
|
Authorization: `Bearer ${apiKey}`,
|
|
24905
24917
|
"Content-Type": "application/json"
|
|
24906
24918
|
},
|
|
24907
24919
|
body: JSON.stringify({
|
|
24908
|
-
model:
|
|
24920
|
+
model: cfg.model,
|
|
24909
24921
|
input: texts,
|
|
24910
|
-
dimensions:
|
|
24922
|
+
dimensions: cfg.dimensions
|
|
24911
24923
|
})
|
|
24912
24924
|
});
|
|
24913
24925
|
if (!response.ok) {
|
|
@@ -53721,6 +53733,20 @@ var require_cli_progress = __commonJS((exports, module) => {
|
|
|
53721
53733
|
});
|
|
53722
53734
|
|
|
53723
53735
|
// ../../_shared/mcp-tools/_utils.ts
|
|
53736
|
+
function getMaxResponseBytes() {
|
|
53737
|
+
const raw = globalThis.process?.env?.CEREFOX_MAX_RESPONSE_BYTES;
|
|
53738
|
+
if (raw === undefined || raw === "")
|
|
53739
|
+
return MAX_RESPONSE_BYTES;
|
|
53740
|
+
const n = Number.parseInt(raw, 10);
|
|
53741
|
+
return Number.isNaN(n) || n <= 0 ? MAX_RESPONSE_BYTES : n;
|
|
53742
|
+
}
|
|
53743
|
+
function getMinSearchScore() {
|
|
53744
|
+
const raw = globalThis.process?.env?.CEREFOX_MIN_SEARCH_SCORE;
|
|
53745
|
+
if (raw === undefined || raw === "")
|
|
53746
|
+
return DEFAULT_MIN_SEARCH_SCORE;
|
|
53747
|
+
const n = Number.parseFloat(raw);
|
|
53748
|
+
return Number.isNaN(n) || n < 0 || n > 1 ? DEFAULT_MIN_SEARCH_SCORE : n;
|
|
53749
|
+
}
|
|
53724
53750
|
function applyByteBudget(rows, maxBytes) {
|
|
53725
53751
|
const accepted = [];
|
|
53726
53752
|
let usedBytes = 0;
|
|
@@ -53748,7 +53774,7 @@ function logUsage(supabase, params) {
|
|
|
53748
53774
|
p_extra: params.extra ?? {}
|
|
53749
53775
|
})).catch(() => {});
|
|
53750
53776
|
}
|
|
53751
|
-
var MAX_RESPONSE_BYTES = 200000;
|
|
53777
|
+
var MAX_RESPONSE_BYTES = 200000, DEFAULT_MIN_SEARCH_SCORE = 0.5;
|
|
53752
53778
|
|
|
53753
53779
|
// ../../_shared/mcp-tools/audit-log.ts
|
|
53754
53780
|
async function handler(supabase, args, ctx) {
|
|
@@ -54531,7 +54557,8 @@ async function handler8(supabase, args, ctx) {
|
|
|
54531
54557
|
if (!projectId)
|
|
54532
54558
|
throw new Error(`Project not found: ${project_name}`);
|
|
54533
54559
|
}
|
|
54534
|
-
const
|
|
54560
|
+
const ceiling = getMaxResponseBytes();
|
|
54561
|
+
const max_bytes = include_content ? Math.min(requested_max_bytes ?? ceiling, ceiling) : null;
|
|
54535
54562
|
const params = {
|
|
54536
54563
|
p_metadata_filter: metadata_filter,
|
|
54537
54564
|
p_project_id: projectId,
|
|
@@ -54624,10 +54651,11 @@ async function handler9(supabase, args, ctx) {
|
|
|
54624
54651
|
const match_count = args.match_count ?? 5;
|
|
54625
54652
|
const mode = args.mode ?? "docs";
|
|
54626
54653
|
const alpha = args.alpha ?? 0.7;
|
|
54627
|
-
const min_score = args.min_score ??
|
|
54654
|
+
const min_score = args.min_score ?? getMinSearchScore();
|
|
54628
54655
|
const metadata_filter = args.metadata_filter ?? null;
|
|
54629
54656
|
const requested_max_bytes = args.max_bytes;
|
|
54630
|
-
const
|
|
54657
|
+
const ceiling = getMaxResponseBytes();
|
|
54658
|
+
const max_bytes = Math.min(requested_max_bytes ?? ceiling, ceiling);
|
|
54631
54659
|
if (metadata_filter !== null && metadata_filter !== undefined && (typeof metadata_filter !== "object" || Array.isArray(metadata_filter))) {
|
|
54632
54660
|
throw new McpInvalidParams("metadata_filter must be a JSON object or null");
|
|
54633
54661
|
}
|
|
@@ -68087,7 +68115,7 @@ function utcStamp() {
|
|
|
68087
68115
|
return d.getUTCFullYear().toString() + pad(d.getUTCMonth() + 1) + pad(d.getUTCDate()) + "T" + pad(d.getUTCHours()) + pad(d.getUTCMinutes()) + pad(d.getUTCSeconds()) + "Z";
|
|
68088
68116
|
}
|
|
68089
68117
|
async function action(options) {
|
|
68090
|
-
const outDir = resolve(expandHome(options.outputDir ?? "~/.cerefox/backups"));
|
|
68118
|
+
const outDir = resolve(expandHome(options.outputDir ?? process.env.CEREFOX_BACKUP_DIR ?? "~/.cerefox/backups"));
|
|
68091
68119
|
if (!existsSync2(outDir))
|
|
68092
68120
|
mkdirSync(outDir, { recursive: true });
|
|
68093
68121
|
const stamp = utcStamp();
|
|
@@ -68133,7 +68161,7 @@ async function action(options) {
|
|
|
68133
68161
|
}
|
|
68134
68162
|
}
|
|
68135
68163
|
function registerBackup(program2) {
|
|
68136
|
-
program2.command("backup").description("Write a JSON snapshot of the knowledge base.").option("-o, --output-dir <dir>", "Snapshot output directory
|
|
68164
|
+
program2.command("backup").description("Write a JSON snapshot of the knowledge base.").option("-o, --output-dir <dir>", "Snapshot output directory (default: CEREFOX_BACKUP_DIR or ~/.cerefox/backups).").option("-l, --label <label>", "Optional suffix added to the filename.").option("--include-versions", "Include archived versions in the snapshot. (v0.5: ignored — current chunks only.)").option("--git", "Commit the snapshot to the output dir as a git checkpoint. (v0.5: ignored.)").action(action);
|
|
68137
68165
|
}
|
|
68138
68166
|
|
|
68139
68167
|
// src/cli/commands/completion.ts
|
|
@@ -73925,7 +73953,7 @@ import { homedir as homedir5 } from "node:os";
|
|
|
73925
73953
|
import { join as join8 } from "node:path";
|
|
73926
73954
|
|
|
73927
73955
|
// ../../_shared/ef-meta/index.ts
|
|
73928
|
-
var EF_VERSION = "0.
|
|
73956
|
+
var EF_VERSION = "0.10.1";
|
|
73929
73957
|
|
|
73930
73958
|
// src/cli/util/checks.ts
|
|
73931
73959
|
init_config();
|
|
@@ -75049,6 +75077,22 @@ var DEFAULT_PIPELINE_SETTINGS = {
|
|
|
75049
75077
|
versionRetentionHours: 48,
|
|
75050
75078
|
versionCleanupEnabled: true
|
|
75051
75079
|
};
|
|
75080
|
+
function loadPipelineSettings() {
|
|
75081
|
+
const env4 = globalThis.process?.env ?? {};
|
|
75082
|
+
const intMin = (raw, def, min) => {
|
|
75083
|
+
if (raw === undefined || raw === "")
|
|
75084
|
+
return def;
|
|
75085
|
+
const n = Number.parseInt(raw, 10);
|
|
75086
|
+
return Number.isNaN(n) || n < min ? def : n;
|
|
75087
|
+
};
|
|
75088
|
+
const bool = (raw, def) => raw === undefined || raw === "" ? def : !/^(false|0|no|off)$/i.test(raw.trim());
|
|
75089
|
+
return {
|
|
75090
|
+
maxChunkChars: intMin(env4.CEREFOX_MAX_CHUNK_CHARS, DEFAULT_PIPELINE_SETTINGS.maxChunkChars, 1),
|
|
75091
|
+
minChunkChars: intMin(env4.CEREFOX_MIN_CHUNK_CHARS, DEFAULT_PIPELINE_SETTINGS.minChunkChars, 0),
|
|
75092
|
+
versionRetentionHours: intMin(env4.CEREFOX_VERSION_RETENTION_HOURS, DEFAULT_PIPELINE_SETTINGS.versionRetentionHours, 0),
|
|
75093
|
+
versionCleanupEnabled: bool(env4.CEREFOX_VERSION_CLEANUP_ENABLED, DEFAULT_PIPELINE_SETTINGS.versionCleanupEnabled)
|
|
75094
|
+
};
|
|
75095
|
+
}
|
|
75052
75096
|
|
|
75053
75097
|
// src/ingestion/pipeline.ts
|
|
75054
75098
|
class IngestionPipeline {
|
|
@@ -75060,7 +75104,7 @@ class IngestionPipeline {
|
|
|
75060
75104
|
this.db = new IngestionDbBridge(deps.supabase);
|
|
75061
75105
|
this.apiKey = deps.openAiApiKey;
|
|
75062
75106
|
this.embedderModel = deps.embedderModel ?? "text-embedding-3-small";
|
|
75063
|
-
this.settings = { ...
|
|
75107
|
+
this.settings = { ...loadPipelineSettings(), ...deps.settings ?? {} };
|
|
75064
75108
|
}
|
|
75065
75109
|
async ingestText(opts) {
|
|
75066
75110
|
const {
|
|
@@ -76474,7 +76518,7 @@ async function action28(query, options) {
|
|
|
76474
76518
|
}
|
|
76475
76519
|
const matchCount = parsePositiveInt(options.matchCount, "--match-count", 5);
|
|
76476
76520
|
const alpha = parseFloat01(options.alpha, "--alpha", 0.7);
|
|
76477
|
-
const minScore = parseFloat01(options.minScore, "--min-score",
|
|
76521
|
+
const minScore = parseFloat01(options.minScore, "--min-score", getMinSearchScore());
|
|
76478
76522
|
const maxBytes = parseNonNegativeInt(options.maxBytes, "--max-bytes", 200000);
|
|
76479
76523
|
const mode = options.mode ?? "docs";
|
|
76480
76524
|
if (!["docs", "hybrid", "fts"].includes(mode)) {
|
|
@@ -76620,7 +76664,7 @@ async function action28(query, options) {
|
|
|
76620
76664
|
}
|
|
76621
76665
|
}
|
|
76622
76666
|
function registerSearch(program2) {
|
|
76623
|
-
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
|
|
76667
|
+
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 (default: CEREFOX_MIN_SEARCH_SCORE or 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.").option("--only-metadata", "List matching docs (id, score, chunks, chars, partial/full) WITHOUT their content — like the web UI's collapsed result list. Grab a [id:…] then `cerefox document get <id>`.").action(action28);
|
|
76624
76668
|
}
|
|
76625
76669
|
|
|
76626
76670
|
// src/cli/commands/self-update.ts
|
|
@@ -80241,7 +80285,7 @@ async function runSearch(ctx, opts) {
|
|
|
80241
80285
|
p_alpha: 0.7,
|
|
80242
80286
|
p_use_upgrade: false,
|
|
80243
80287
|
p_project_id: projectId,
|
|
80244
|
-
p_min_score:
|
|
80288
|
+
p_min_score: getMinSearchScore()
|
|
80245
80289
|
};
|
|
80246
80290
|
if (metadataFilter)
|
|
80247
80291
|
params2.p_metadata_filter = metadataFilter;
|
|
@@ -81323,6 +81367,51 @@ function registerMetaRoutes(app, ctx) {
|
|
|
81323
81367
|
});
|
|
81324
81368
|
}
|
|
81325
81369
|
|
|
81370
|
+
// src/web/routes/postgrest-proxy.ts
|
|
81371
|
+
var STRIP_RESPONSE_HEADERS = [
|
|
81372
|
+
"connection",
|
|
81373
|
+
"keep-alive",
|
|
81374
|
+
"transfer-encoding",
|
|
81375
|
+
"content-length",
|
|
81376
|
+
"content-encoding",
|
|
81377
|
+
"te",
|
|
81378
|
+
"trailer",
|
|
81379
|
+
"upgrade",
|
|
81380
|
+
"proxy-authenticate",
|
|
81381
|
+
"proxy-authorization"
|
|
81382
|
+
];
|
|
81383
|
+
function registerPostgrestProxy(app) {
|
|
81384
|
+
const upstream = (process.env.CEREFOX_POSTGREST_UPSTREAM ?? "").trim().replace(/\/+$/, "");
|
|
81385
|
+
if (!upstream)
|
|
81386
|
+
return;
|
|
81387
|
+
app.all("/rest/v1/*", async (c2) => {
|
|
81388
|
+
const url = new URL(c2.req.url);
|
|
81389
|
+
const path = url.pathname.replace(/^\/rest\/v1/, "");
|
|
81390
|
+
const target = `${upstream}${path}${url.search}`;
|
|
81391
|
+
const headers = new Headers(c2.req.raw.headers);
|
|
81392
|
+
headers.delete("host");
|
|
81393
|
+
headers.delete("accept-encoding");
|
|
81394
|
+
const method = c2.req.method;
|
|
81395
|
+
const init = { method, headers };
|
|
81396
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
81397
|
+
init.body = c2.req.raw.body;
|
|
81398
|
+
init.duplex = "half";
|
|
81399
|
+
}
|
|
81400
|
+
let resp;
|
|
81401
|
+
try {
|
|
81402
|
+
resp = await fetch(target, init);
|
|
81403
|
+
} catch (err) {
|
|
81404
|
+
return c2.json({
|
|
81405
|
+
detail: `PostgREST upstream unreachable: ${err instanceof Error ? err.message : String(err)}`
|
|
81406
|
+
}, 502);
|
|
81407
|
+
}
|
|
81408
|
+
const respHeaders = new Headers(resp.headers);
|
|
81409
|
+
for (const h of STRIP_RESPONSE_HEADERS)
|
|
81410
|
+
respHeaders.delete(h);
|
|
81411
|
+
return new Response(resp.body, { status: resp.status, headers: respHeaders });
|
|
81412
|
+
});
|
|
81413
|
+
}
|
|
81414
|
+
|
|
81326
81415
|
// src/web/routes/preferences.ts
|
|
81327
81416
|
init_config();
|
|
81328
81417
|
import { existsSync as existsSync14, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync5 } from "node:fs";
|
|
@@ -81520,6 +81609,7 @@ function buildApp(ctx = buildWebContext()) {
|
|
|
81520
81609
|
app.post("/api/v1/ingest/file", ingest503);
|
|
81521
81610
|
app.post("/api/v1/documents/:document_id/upload", ingest503);
|
|
81522
81611
|
}
|
|
81612
|
+
registerPostgrestProxy(app);
|
|
81523
81613
|
const staticDir = resolveStaticDir();
|
|
81524
81614
|
if (staticDir) {
|
|
81525
81615
|
app.use("/static/*", serveStatic({
|
|
@@ -81893,7 +81983,10 @@ function registerRenameHusks(program2) {
|
|
|
81893
81983
|
}
|
|
81894
81984
|
}
|
|
81895
81985
|
function buildProgram() {
|
|
81896
|
-
const
|
|
81986
|
+
const progName = process.env.CEREFOX_PROG_NAME || "cerefox";
|
|
81987
|
+
const program2 = new Command(progName).description("Cerefox — user-owned shared memory for AI agents.").version(PKG_VERSION, "-v, --version", `Print the ${progName} version and exit.`).addOption(new Option("--json", "Emit machine-readable JSON on stdout instead of the default human text. " + "Available on read commands; ignored on commands without a JSON shape.").hideHelp()).showHelpAfterError(`(run \`${progName} --help\` for usage)`).enablePositionalOptions().addHelpText("after", `
|
|
81988
|
+
Resource groups (run \`${progName} <group> --help\`):
|
|
81989
|
+
` + ` document get · list · edit · delete · restore · ingest · ingest-dir · version {list·archive·unarchive}
|
|
81897
81990
|
` + ` project list · create · edit · delete
|
|
81898
81991
|
` + ` metadata keys · search
|
|
81899
81992
|
` + ` audit list
|
|
@@ -81915,8 +82008,8 @@ Exit codes:
|
|
|
81915
82008
|
` + ` 1 user error 3 not found (document / version / project)
|
|
81916
82009
|
` + `
|
|
81917
82010
|
Learn more:
|
|
81918
|
-
` + `
|
|
81919
|
-
` + `
|
|
82011
|
+
` + ` ${progName} guides list # bundled docs (offline)
|
|
82012
|
+
` + ` ${progName} doctor # diagnose your install
|
|
81920
82013
|
` + ` https://github.com/fstamatelopoulos/cerefox
|
|
81921
82014
|
`);
|
|
81922
82015
|
registerSearch(program2);
|