@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.
@@ -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.9.11";
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(OPENAI_EMBEDDING_URL, {
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: OPENAI_MODEL,
24877
+ model: cfg.model,
24867
24878
  input: text,
24868
- dimensions: EMBEDDING_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(OPENAI_EMBEDDING_URL, {
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: OPENAI_MODEL,
24920
+ model: cfg.model,
24909
24921
  input: texts,
24910
- dimensions: EMBEDDING_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 max_bytes = include_content ? Math.min(requested_max_bytes ?? MAX_RESPONSE_BYTES, MAX_RESPONSE_BYTES) : null;
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 ?? 0.5;
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 max_bytes = Math.min(requested_max_bytes ?? MAX_RESPONSE_BYTES, MAX_RESPONSE_BYTES);
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.", "~/.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);
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.9.3";
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 = { ...DEFAULT_PIPELINE_SETTINGS, ...deps.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", 0.5);
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.", "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);
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: 0
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 program2 = new Command("cerefox").description("Cerefox — user-owned shared memory for AI agents.").version(PKG_VERSION, "-v, --version", "Print the cerefox 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 `cerefox --help` for usage)").enablePositionalOptions().addHelpText("after", "\nResource groups (run `cerefox <group> --help`):\n" + ` document get · list · edit · delete · restore · ingest · ingest-dir · version {list·archive·unarchive}
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
- ` + ` cerefox docs --list # bundled docs (offline)
81919
- ` + ` cerefox doctor # diagnose your install
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);