@cerefox/memory 1.0.4 → 1.0.6

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 = "1.0.4";
7187
+ var PKG_VERSION = "1.0.6";
7188
7188
  var init_meta = () => {};
7189
7189
 
7190
7190
  // ../../node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.js
@@ -25217,21 +25217,35 @@ function getMaxResponseBytes() {
25217
25217
  const n = Number.parseInt(raw, 10);
25218
25218
  return Number.isNaN(n) || n <= 0 ? MAX_RESPONSE_BYTES : n;
25219
25219
  }
25220
- function getMinSearchScore() {
25221
- const raw = globalThis.process?.env?.CEREFOX_MIN_SEARCH_SCORE;
25222
- const fallback = globalThis.process?.env?.CEREFOX_EMBEDDER === "local" ? DEFAULT_MIN_SEARCH_SCORE_LOCAL : DEFAULT_MIN_SEARCH_SCORE;
25223
- if (raw === undefined || raw === "")
25224
- return fallback;
25225
- const n = Number.parseFloat(raw);
25226
- return Number.isNaN(n) || n < 0 || n > 1 ? fallback : n;
25220
+ function readEnv(name) {
25221
+ const g = globalThis;
25222
+ const fromProcess = g.process?.env?.[name];
25223
+ if (fromProcess !== undefined && fromProcess !== "")
25224
+ return fromProcess;
25225
+ try {
25226
+ const fromDeno = g.Deno?.env?.get(name);
25227
+ return fromDeno === "" ? undefined : fromDeno;
25228
+ } catch {
25229
+ return;
25230
+ }
25227
25231
  }
25228
- function getMinTermCoverage() {
25229
- const raw = globalThis.process?.env?.CEREFOX_MIN_TERM_COVERAGE;
25230
- if (raw === undefined || raw === "")
25232
+ function readUnitInterval(name) {
25233
+ const raw = readEnv(name);
25234
+ if (raw === undefined)
25231
25235
  return;
25232
25236
  const n = Number.parseFloat(raw);
25233
25237
  return Number.isNaN(n) || n < 0 || n > 1 ? undefined : n;
25234
25238
  }
25239
+ function getSearchAlpha() {
25240
+ return readUnitInterval("CEREFOX_SEARCH_ALPHA") ?? DEFAULT_SEARCH_ALPHA;
25241
+ }
25242
+ function getMinSearchScore() {
25243
+ const fallback = readEnv("CEREFOX_EMBEDDER") === "local" ? DEFAULT_MIN_SEARCH_SCORE_LOCAL : DEFAULT_MIN_SEARCH_SCORE;
25244
+ return readUnitInterval("CEREFOX_MIN_SEARCH_SCORE") ?? fallback;
25245
+ }
25246
+ function getMinTermCoverage() {
25247
+ return readUnitInterval("CEREFOX_MIN_TERM_COVERAGE");
25248
+ }
25235
25249
  function applyByteBudget(rows, maxBytes) {
25236
25250
  const accepted = [];
25237
25251
  let usedBytes = 0;
@@ -25259,7 +25273,7 @@ function logUsage(supabase, params) {
25259
25273
  p_extra: params.extra ?? {}
25260
25274
  })).catch(() => {});
25261
25275
  }
25262
- var MAX_RESPONSE_BYTES = 200000, DEFAULT_MIN_SEARCH_SCORE = 0.5, DEFAULT_MIN_SEARCH_SCORE_LOCAL = 0.6;
25276
+ var MAX_RESPONSE_BYTES = 200000, DEFAULT_MIN_SEARCH_SCORE = 0.5, DEFAULT_MIN_SEARCH_SCORE_LOCAL = 0.6, DEFAULT_SEARCH_ALPHA = 0.7;
25263
25277
 
25264
25278
  // ../../_shared/mcp-tools/_projects.ts
25265
25279
  async function ensureDocumentInProject(supabase, documentId, projectName) {
@@ -55577,7 +55591,7 @@ async function handler9(supabase, args, ctx) {
55577
55591
  const project_name = args.project_name;
55578
55592
  const match_count = args.match_count ?? 5;
55579
55593
  const mode = args.mode ?? "docs";
55580
- const alpha = args.alpha ?? 0.7;
55594
+ const alpha = args.alpha ?? getSearchAlpha();
55581
55595
  const min_score = args.min_score ?? getMinSearchScore();
55582
55596
  const min_term_coverage = args.min_term_coverage ?? getMinTermCoverage();
55583
55597
  const coverageParam = min_term_coverage !== undefined ? { p_min_term_coverage: min_term_coverage } : {};
@@ -69069,16 +69083,22 @@ import { join as join2, resolve } from "node:path";
69069
69083
  async function fetchAllPages(makeQuery, batchSize = 200) {
69070
69084
  const results = [];
69071
69085
  let offset = 0;
69086
+ let serverTotal = null;
69072
69087
  for (;; ) {
69073
- const { data, error } = await makeQuery(offset, offset + batchSize - 1);
69088
+ const { data, error, count } = await makeQuery(offset, offset + batchSize - 1);
69074
69089
  if (error)
69075
69090
  throw new Error(error.message ?? JSON.stringify(error));
69091
+ if (typeof count === "number")
69092
+ serverTotal = count;
69076
69093
  const page = data ?? [];
69077
69094
  results.push(...page);
69078
69095
  if (page.length < batchSize)
69079
69096
  break;
69080
69097
  offset += batchSize;
69081
69098
  }
69099
+ if (serverTotal !== null && results.length !== serverTotal) {
69100
+ throw new Error(`Paginated read returned ${results.length} row(s) but the server reports ` + `${serverTotal}. Refusing to return a partial result — retry, and if this ` + `persists please report it (the rows may be changing under the read).`);
69101
+ }
69082
69102
  return results;
69083
69103
  }
69084
69104
 
@@ -75000,8 +75020,8 @@ import { homedir as homedir6 } from "node:os";
75000
75020
  import { join as join9 } from "node:path";
75001
75021
 
75002
75022
  // ../../_shared/ef-meta/index.ts
75003
- var EF_VERSION = "1.0.4";
75004
- var EF_LAST_CHANGED = "1.0.4";
75023
+ var EF_VERSION = "1.0.6";
75024
+ var EF_LAST_CHANGED = "1.0.6";
75005
75025
 
75006
75026
  // src/cli/util/checks.ts
75007
75027
  init_config();
@@ -75527,9 +75547,9 @@ async function checkEdgeFunctionsCompat() {
75527
75547
  }
75528
75548
  return {
75529
75549
  name: "edge functions",
75530
- status: "skipped",
75531
- detail: `Deployed Edge Functions (v${deployed}) are older than the ones bundled with this client (v${EF_VERSION}). Compatible — nothing is broken — but redeploying ` + `picks up the latest server-side fixes.`,
75532
- hint: "Redeploy with: cerefox server deploy --functions-only"
75550
+ status: "warn",
75551
+ detail: `Deployed Edge Functions (v${deployed}) are older than this client's bundled v${EF_VERSION} and predate server-side fixes shipped in v${EF_LAST_CHANGED}. Still compatible, but you are missing those fixes.`,
75552
+ hint: "Update the Edge Functions (see remediation below)."
75533
75553
  };
75534
75554
  default:
75535
75555
  return {
@@ -75628,11 +75648,11 @@ async function action15(options) {
75628
75648
  const needsEf = stale("edge functions");
75629
75649
  let remediation = null;
75630
75650
  if (needsSchema && needsEf) {
75631
- remediation = "Update the server (schema + RPCs + Edge Functions): cerefox server deploy";
75651
+ remediation = "This release needs a server update (schema + RPCs + Edge Functions): cerefox server deploy";
75632
75652
  } else if (needsSchema) {
75633
- remediation = "Update the schema + RPCs: cerefox server deploy --schema-only";
75653
+ remediation = "This release needs a schema + RPC update: cerefox server deploy --schema-only";
75634
75654
  } else if (needsEf) {
75635
- remediation = "Update the Edge Functions: cerefox server deploy --functions-only";
75655
+ remediation = "This release needs an Edge Function update: cerefox server deploy --functions-only";
75636
75656
  }
75637
75657
  if (remediation) {
75638
75658
  println(cErr.yellow("→ " + remediation));
@@ -75859,7 +75879,7 @@ class IngestionDbBridge {
75859
75879
  return rows.length > 0 ? rows[0] : null;
75860
75880
  }
75861
75881
  async listChunksForDocument(documentId) {
75862
- const { data } = await this.supabase.from("cerefox_chunks").select("id, document_id, chunk_index, heading_path, heading_level, title, content, char_count").eq("document_id", documentId).is("version_id", null).order("chunk_index");
75882
+ const data = await fetchAllPages((from, to) => this.supabase.from("cerefox_chunks").select("id, document_id, chunk_index, heading_path, heading_level, title, content, char_count").eq("document_id", documentId).is("version_id", null).order("chunk_index").range(from, to));
75863
75883
  return data ?? [];
75864
75884
  }
75865
75885
  async getDocumentProjectIds(documentId) {
@@ -77474,7 +77494,7 @@ async function action29(query, options) {
77474
77494
  throw userError("Empty query.");
77475
77495
  }
77476
77496
  const matchCount = parsePositiveInt(options.matchCount, "--match-count", 5);
77477
- const alpha = parseFloat01(options.alpha, "--alpha", 0.7);
77497
+ const alpha = parseFloat01(options.alpha, "--alpha", getSearchAlpha());
77478
77498
  const minScore = parseFloat01(options.minScore, "--min-score", getMinSearchScore());
77479
77499
  const envCoverage = getMinTermCoverage();
77480
77500
  const coverageParam = options.minTermCoverage !== undefined ? { p_min_term_coverage: parseFloat01(options.minTermCoverage, "--min-term-coverage", envCoverage ?? 0.5) } : envCoverage !== undefined ? { p_min_term_coverage: envCoverage } : {};
@@ -77633,7 +77653,7 @@ async function action29(query, options) {
77633
77653
  }
77634
77654
  }
77635
77655
  function registerSearch(program2) {
77636
- 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; else 0.5, or 0.6 with the local embedder).").option("--min-term-coverage <float>", "OR-fallback keyword matches must cover at least this fraction of the query's meaningful terms to count as confident hits (default: CEREFOX_MIN_TERM_COVERAGE; else the server default 0.5; needs schema ≥ 0.9.1).").option("--max-bytes <n>", "Response size budget in bytes (default: CEREFOX_MAX_RESPONSE_BYTES or 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(action29);
77656
+ 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: CEREFOX_SEARCH_ALPHA; else 0.7).").option("--min-score <float>", "Minimum cosine similarity threshold (default: CEREFOX_MIN_SEARCH_SCORE; else 0.5, or 0.6 with the local embedder).").option("--min-term-coverage <float>", "OR-fallback keyword matches must cover at least this fraction of the query's meaningful terms to count as confident hits (default: CEREFOX_MIN_TERM_COVERAGE; else the server default 0.5; needs schema ≥ 0.9.1).").option("--max-bytes <n>", "Response size budget in bytes (default: CEREFOX_MAX_RESPONSE_BYTES or 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(action29);
77637
77657
  }
77638
77658
 
77639
77659
  // src/cli/commands/self-update.ts
@@ -81451,23 +81471,18 @@ function parseMetadataFilter(raw2) {
81451
81471
  }
81452
81472
  async function listDocuments(ctx, opts) {
81453
81473
  const { projectId, limit, offset = 0 } = opts;
81454
- let docIds = null;
81455
- if (projectId) {
81456
- const { data: data2, error: error4 } = await ctx.supabase.from("cerefox_document_projects").select("document_id").eq("project_id", projectId);
81457
- if (error4)
81458
- throw error4;
81459
- docIds = (data2 ?? []).map((r) => r.document_id);
81460
- if (docIds.length === 0)
81461
- return [];
81462
- }
81463
- let q = ctx.supabase.from("cerefox_documents").select(DOC_COLS).is("deleted_at", null).order("updated_at", { ascending: false });
81464
- if (docIds)
81465
- q = q.in("id", docIds);
81474
+ const selectCols = projectId ? `${DOC_COLS}, cerefox_document_projects!inner(project_id)` : DOC_COLS;
81475
+ let q = ctx.supabase.from("cerefox_documents").select(selectCols).is("deleted_at", null).order("updated_at", { ascending: false });
81476
+ if (projectId)
81477
+ q = q.eq("cerefox_document_projects.project_id", projectId);
81466
81478
  q = q.range(offset, offset + limit - 1);
81467
81479
  const { data, error: error3 } = await q;
81468
81480
  if (error3)
81469
81481
  throw error3;
81470
- return data ?? [];
81482
+ return (data ?? []).map((row) => {
81483
+ const { cerefox_document_projects: _j, ...doc2 } = row;
81484
+ return doc2;
81485
+ });
81471
81486
  }
81472
81487
  async function listAllProjects(ctx) {
81473
81488
  const { data, error: error3 } = await ctx.supabase.from("cerefox_projects").select("*").order("name");
@@ -81583,7 +81598,8 @@ function projectDocResult(r) {
81583
81598
  chunk_count: r.chunk_count ?? 0,
81584
81599
  total_chars: r.total_chars ?? 0,
81585
81600
  doc_updated_at: r.doc_updated_at ?? null,
81586
- is_partial: r.is_partial ?? false
81601
+ is_partial: r.is_partial ?? false,
81602
+ below_confidence: r.below_confidence ?? false
81587
81603
  };
81588
81604
  }
81589
81605
  function projectChunkResult(r) {
@@ -81599,7 +81615,8 @@ function projectChunkResult(r) {
81599
81615
  doc_title: r.doc_title ?? "",
81600
81616
  doc_source: r.doc_source ?? null,
81601
81617
  doc_project_ids: r.doc_project_ids ?? [],
81602
- doc_metadata: r.doc_metadata ?? {}
81618
+ doc_metadata: r.doc_metadata ?? {},
81619
+ below_confidence: r.below_confidence ?? false
81603
81620
  };
81604
81621
  }
81605
81622
  async function runSearch(ctx, opts) {
@@ -81640,7 +81657,7 @@ async function runSearch(ctx, opts) {
81640
81657
  p_query_text: query,
81641
81658
  p_query_embedding: embedding,
81642
81659
  p_match_count: count,
81643
- p_alpha: 0.7,
81660
+ p_alpha: getSearchAlpha(),
81644
81661
  p_use_upgrade: false,
81645
81662
  p_project_id: projectId,
81646
81663
  p_min_score: getMinSearchScore()
@@ -81656,7 +81673,7 @@ async function runSearch(ctx, opts) {
81656
81673
  p_query_text: query,
81657
81674
  p_query_embedding: embedding,
81658
81675
  p_match_count: Math.min(count, 5),
81659
- p_alpha: 0.7,
81676
+ p_alpha: getSearchAlpha(),
81660
81677
  p_project_id: projectId,
81661
81678
  p_min_score: getMinSearchScore()
81662
81679
  };
@@ -82079,7 +82096,7 @@ function registerDocumentReadRoutes(app, ctx) {
82079
82096
  });
82080
82097
  app.get("/api/v1/documents/:document_id/chunks", async (c2) => {
82081
82098
  const documentId = c2.req.param("document_id");
82082
- const { data, error: error3 } = await ctx.supabase.from("cerefox_chunks").select("id, document_id, chunk_index, heading_path, heading_level, title, content, char_count").eq("document_id", documentId).is("version_id", null).order("chunk_index");
82099
+ const { data, error: error3 } = await ctx.supabase.from("cerefox_chunks").select("id, document_id, chunk_index, heading_path, heading_level, title, content, char_count").eq("document_id", documentId).is("version_id", null).order("chunk_index").range(0, 4999);
82083
82100
  if (error3)
82084
82101
  return c2.json({ detail: error3.message }, 500);
82085
82102
  const rows = data ?? [];