@cerefox/memory 1.0.0-rc.3 → 1.0.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 CHANGED
@@ -56,7 +56,7 @@ You deploy the server side with this package's CLI — `cerefox server deploy` s
56
56
  | Prerequisite | Why | How |
57
57
  |---|---|---|
58
58
  | A **Supabase project** | Hosts Postgres + pgvector + Edge Functions. Free tier is enough for most personal use. | [supabase.com](https://supabase.com) → New project |
59
- | An **embedding API key** | OpenAI `text-embedding-3-small` (the only embedder wired today). Pennies/month for typical personal use (see [operational-cost.md](https://github.com/fstamatelopoulos/cerefox/blob/main/docs/guides/operational-cost.md)). | Get an [OpenAI API key](https://platform.openai.com/api-keys). |
59
+ | An **embedding API key** | OpenAI `text-embedding-3-small` (the cloud backend's embedder; Cerefox Local can instead run a fully-offline local model). Pennies/month for typical personal use (see [operational-cost.md](https://github.com/fstamatelopoulos/cerefox/blob/main/docs/guides/operational-cost.md)). | Get an [OpenAI API key](https://platform.openai.com/api-keys). |
60
60
  | **Node ≥ 20** or **Bun ≥ 1.0** | Runtime for the `cerefox` bin (and the bundled `cerefox mcp` server). | [nodejs.org](https://nodejs.org) · [bun.sh](https://bun.sh). The one-line installer below bootstraps Bun if neither is present. |
61
61
 
62
62
  ### One-time server-side setup (~10 min — no clone needed)
@@ -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.0-rc.3";
7187
+ var PKG_VERSION = "1.0.0";
7188
7188
  var init_meta = () => {};
7189
7189
 
7190
7190
  // ../../node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.js
@@ -25008,10 +25008,11 @@ function getMaxResponseBytes() {
25008
25008
  }
25009
25009
  function getMinSearchScore() {
25010
25010
  const raw = globalThis.process?.env?.CEREFOX_MIN_SEARCH_SCORE;
25011
+ const fallback = globalThis.process?.env?.CEREFOX_EMBEDDER === "local" ? DEFAULT_MIN_SEARCH_SCORE_LOCAL : DEFAULT_MIN_SEARCH_SCORE;
25011
25012
  if (raw === undefined || raw === "")
25012
- return DEFAULT_MIN_SEARCH_SCORE;
25013
+ return fallback;
25013
25014
  const n = Number.parseFloat(raw);
25014
- return Number.isNaN(n) || n < 0 || n > 1 ? DEFAULT_MIN_SEARCH_SCORE : n;
25015
+ return Number.isNaN(n) || n < 0 || n > 1 ? fallback : n;
25015
25016
  }
25016
25017
  function applyByteBudget(rows, maxBytes) {
25017
25018
  const accepted = [];
@@ -25040,7 +25041,7 @@ function logUsage(supabase, params) {
25040
25041
  p_extra: params.extra ?? {}
25041
25042
  })).catch(() => {});
25042
25043
  }
25043
- var MAX_RESPONSE_BYTES = 200000, DEFAULT_MIN_SEARCH_SCORE = 0.5;
25044
+ var MAX_RESPONSE_BYTES = 200000, DEFAULT_MIN_SEARCH_SCORE = 0.5, DEFAULT_MIN_SEARCH_SCORE_LOCAL = 0.6;
25044
25045
 
25045
25046
  // ../../_shared/mcp-tools/_projects.ts
25046
25047
  async function ensureDocumentInProject(supabase, documentId, projectName) {
@@ -74659,7 +74660,7 @@ import { homedir as homedir6 } from "node:os";
74659
74660
  import { join as join9 } from "node:path";
74660
74661
 
74661
74662
  // ../../_shared/ef-meta/index.ts
74662
- var EF_VERSION = "1.0.0-rc.3";
74663
+ var EF_VERSION = "1.0.0-rc.4";
74663
74664
 
74664
74665
  // src/cli/util/checks.ts
74665
74666
  init_config();
@@ -74717,6 +74718,14 @@ function checkConfig() {
74717
74718
  };
74718
74719
  }
74719
74720
  if (!existsSync10(envPath)) {
74721
+ const settings = loadSettings();
74722
+ if (settings.supabaseUrl && settings.supabaseKey) {
74723
+ return {
74724
+ name: "config",
74725
+ status: "ok",
74726
+ detail: "configured via environment variables (no .env file — normal for Cerefox Local)"
74727
+ };
74728
+ }
74720
74729
  return {
74721
74730
  name: "config",
74722
74731
  status: "error",
@@ -75036,9 +75045,9 @@ function checkMcpConfigs() {
75036
75045
  if (found.length === 0) {
75037
75046
  return {
75038
75047
  name: "mcp clients",
75039
- status: "warn",
75040
- detail: "No MCP client configs reference Cerefox.",
75041
- hint: "Run `cerefox configure-agent --tool claude-code` (or `--tool claude-desktop`) to wire up a client."
75048
+ status: isLocalBackend() ? "skipped" : "warn",
75049
+ detail: isLocalBackend() ? "checked from inside the container — host MCP configs are not visible here." : "No MCP client configs reference Cerefox.",
75050
+ hint: isLocalBackend() ? "Configure agents on the host with `cerefox-local configure-agent`." : "Run `cerefox configure-agent --tool claude-code` (or `--tool claude-desktop`) to wire up a client."
75042
75051
  };
75043
75052
  }
75044
75053
  return {
@@ -75110,7 +75119,17 @@ async function checkPostgres() {
75110
75119
  await sql.end({ timeout: 1 }).catch(() => {});
75111
75120
  }
75112
75121
  }
75122
+ function isLocalBackend() {
75123
+ return Boolean(process.env.CEREFOX_POSTGREST_UPSTREAM);
75124
+ }
75113
75125
  async function checkEdgeFunctionsCompat() {
75126
+ if (isLocalBackend()) {
75127
+ return {
75128
+ name: "edge functions",
75129
+ status: "skipped",
75130
+ detail: "local backend — Edge Functions are not used (cloud-only surface)."
75131
+ };
75132
+ }
75114
75133
  const settings = loadSettings();
75115
75134
  if (!settings.supabaseUrl) {
75116
75135
  return {
@@ -77247,7 +77266,7 @@ async function action29(query, options) {
77247
77266
  }
77248
77267
  }
77249
77268
  function registerSearch(program2) {
77250
- 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 (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);
77269
+ 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("--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);
77251
77270
  }
77252
77271
 
77253
77272
  // src/cli/commands/self-update.ts
@@ -18,7 +18,7 @@
18
18
  * doesn't touch `supabase/functions/` leaves it alone).
19
19
  */
20
20
 
21
- export const EF_VERSION = "1.0.0-rc.3";
21
+ export const EF_VERSION = "1.0.0-rc.4";
22
22
 
23
23
  /**
24
24
  * The 8 peer EFs the cerefox-mcp aggregator probes (excludes cerefox-mcp
@@ -35,6 +35,15 @@ export function getMaxResponseBytes(): number {
35
35
  /** Built-in default cosine-similarity floor for hybrid/semantic search. */
36
36
  export const DEFAULT_MIN_SEARCH_SCORE = 0.5;
37
37
 
38
+ /**
39
+ * Nomic's cosine-score distribution sits higher than OpenAI's: unrelated text
40
+ * lands ~0.4–0.55 (vs ~0.1–0.3), so the 0.5 floor calibrated for
41
+ * text-embedding-3-small lets weak matches through on the local embedder
42
+ * (rc.3 dogfood: an unrelated doc passed at vec≈0.54). 0.6 restores the
43
+ * intended precision; relevant nomic matches score ~0.7+.
44
+ */
45
+ export const DEFAULT_MIN_SEARCH_SCORE_LOCAL = 0.6;
46
+
38
47
  /**
39
48
  * Resolve the minimum cosine-similarity floor for hybrid/semantic search
40
49
  * (vector-only matches below this are dropped; FTS matches always pass).
@@ -49,9 +58,14 @@ export const DEFAULT_MIN_SEARCH_SCORE = 0.5;
49
58
  export function getMinSearchScore(): number {
50
59
  const raw = (globalThis as { process?: { env?: Record<string, string | undefined> } })
51
60
  .process?.env?.CEREFOX_MIN_SEARCH_SCORE;
52
- if (raw === undefined || raw === "") return DEFAULT_MIN_SEARCH_SCORE;
61
+ const fallback =
62
+ (globalThis as { process?: { env?: Record<string, string | undefined> } })
63
+ .process?.env?.CEREFOX_EMBEDDER === "local"
64
+ ? DEFAULT_MIN_SEARCH_SCORE_LOCAL
65
+ : DEFAULT_MIN_SEARCH_SCORE;
66
+ if (raw === undefined || raw === "") return fallback;
53
67
  const n = Number.parseFloat(raw);
54
- return Number.isNaN(n) || n < 0 || n > 1 ? DEFAULT_MIN_SEARCH_SCORE : n;
68
+ return Number.isNaN(n) || n < 0 || n > 1 ? fallback : n;
55
69
  }
56
70
 
57
71
  export function applyByteBudget(
@@ -118,7 +118,10 @@ This handles intermittent OpenAI API errors (500s) that would otherwise cause se
118
118
  | Variable | Default | Description |
119
119
  |----------|---------|-------------|
120
120
  | `CEREFOX_MAX_RESPONSE_BYTES` | `200000` | Maximum bytes in a single search response (local MCP path). See explanation below. |
121
- | `CEREFOX_MIN_SEARCH_SCORE` | `0.50` | Minimum cosine similarity for hybrid and semantic search results (0.0–1.0). In **hybrid search**, chunks that matched the FTS keyword operator (`@@`) always pass through regardless of their vector score — the threshold only filters vector-only results. In **semantic search**, all results are filtered. The pure **FTS search** mode is unaffected. Increase for stricter precision; decrease for wider recall. |
121
+ | `CEREFOX_MIN_SEARCH_SCORE` | `0.50` (`0.60` with the local embedder) | Minimum cosine similarity for hybrid and semantic search results (0.0–1.0). The default is embedder-aware: nomic scores unrelated text higher than OpenAI, so `CEREFOX_EMBEDDER=local` raises the floor to 0.60. In **hybrid search**, chunks that matched the FTS keyword operator (`@@`) always pass through regardless of their vector score — the threshold only filters vector-only results. In **semantic search**, all results are filtered. The pure **FTS search** mode is unaffected. Increase for stricter precision; decrease for wider recall. |
122
+ | `CEREFOX_EMBED_MAX_INPUT_CHARS` | `20000` | Safety cap on the characters sent to the embedding model per input. The full chunk content is always stored and reconstructed untouched; only the embedding uses the (rare) truncated prefix, so an oversized chunk can never fail an ingest. |
123
+ | `CEREFOX_MODELS_DIR` | `~/.cerefox/models` (in-container: inside the data volume) | Where the local embedder caches downloaded model weights (Cerefox Local; `CEREFOX_EMBEDDER=local`). |
124
+ | `CEREFOX_ONNX_BATCH` | `4` | Texts per local-embedder inference call. Peak memory scales with this; the small default keeps ingest/reindex safe on small Docker VMs. |
122
125
 
123
126
  ### Metadata filter
124
127
 
@@ -257,9 +260,9 @@ OPENAI_API_KEY=sk-...
257
260
  # All other settings use defaults
258
261
  ```
259
262
 
260
- > **Fireworks is not wired in the TS runtime yet** — `CEREFOX_EMBEDDER=fireworks` /
261
- > `CEREFOX_FIREWORKS_*` are documented but currently no-ops (OpenAI is the only embedder
262
- > implemented today). Tracked for a future release.
263
+ > **Fireworks is not wired yet** — `CEREFOX_EMBEDDER=fireworks` / `CEREFOX_FIREWORKS_*`
264
+ > are documented but currently no-ops. The wired embedders are `openai` (default) and
265
+ > `local` (Cerefox Local only). Fireworks is tracked for a future release.
263
266
 
264
267
  ---
265
268
 
@@ -4,9 +4,6 @@ Cerefox 1.0.0 is the first stable release. Two changes need attention when you
4
4
  upgrade an existing Supabase deployment; a third is automatic. **Nothing here
5
5
  affects the local/self-hosted (World B) backend.**
6
6
 
7
- Pre-releases are published on the `1.0.0-beta.N` line (breaking changes may still
8
- occur between betas) leading up to `1.0.0`.
9
-
10
7
  ## 1. Edge Function auth: anon key → Cerefox access token (action required)
11
8
 
12
9
  The legacy Supabase **anon JWT** is no longer accepted for calling Cerefox Edge
@@ -52,7 +49,7 @@ Claude uses OAuth).
52
49
  Rotating the token later: `cerefox token rotate` (accepts new + old for zero-downtime),
53
50
  then `cerefox token rotate --finalize` once every client is on the new token.
54
51
 
55
- ## 2. New schema (0.7.0 → 0.8.0): document reconstruction fix (redeploy required, no data action)
52
+ ## 2. New schema (→ 0.8.1): document reconstruction fix (redeploy required, no data action)
56
53
 
57
54
  1.0.0 fixes a document-reconstruction bug that could corrupt documents containing large
58
55
  tables or blank-line-free paragraphs. It adds a `content_format` column on
@@ -90,7 +87,7 @@ unaffected — they are not Python and remain the source of truth for the schema
90
87
  ```bash
91
88
  cerefox self-update # or: npm install -g @cerefox/memory@latest
92
89
  cerefox token generate # change #1: mint + set the access token
93
- cerefox server deploy # changes #1 + #2: token-gated EFs + schema 0.8.0
90
+ cerefox server deploy # changes #1 + #2: token-gated EFs + schema 0.8.1
94
91
  cerefox doctor # verify (edge-functions green; content-format ℹ)
95
92
  # then: update GPT Actions / remote MCP clients to the token; revoke the anon key
96
93
  ```
@@ -142,8 +142,11 @@ embedding costs" below.
142
142
 
143
143
  If you want to keep costs as low as possible:
144
144
 
145
- - **Cheaper embedding models**: a lower-cost OpenAI-compatible provider (e.g. Fireworks AI)
146
- is on the roadmap — **not yet wired in the TS runtime** (OpenAI only today).
145
+ - **Zero-cost embeddings (Cerefox Local)**: the self-hosted backend can run a local
146
+ embedding model in-container (`CEREFOX_EMBEDDER=local`) — no API key, no per-token
147
+ cost at all. See [setup-local.md](setup-local.md#choose-your-embedder-openai-vs-fully-local).
148
+ - **Cheaper cloud models**: a lower-cost OpenAI-compatible provider (e.g. Fireworks AI)
149
+ is on the roadmap — not yet wired.
147
150
  - **Batch ingest, don't re-ingest**: Cerefox deduplicates by content hash — re-ingesting the
148
151
  same file twice costs nothing. Only new or changed content triggers embedding calls.
149
152
  - **`cerefox server reindex`**: Re-embeds all existing chunks if you switch embedders. Run this once
@@ -60,6 +60,10 @@ data volume, so it survives `cerefox-local upgrade`.
60
60
  > `cerefox-local server reindex` to re-embed everything. `cerefox-local doctor`
61
61
  > flags any mismatch.
62
62
 
63
+ > Scores are calibrated per embedder: with the local model the default semantic
64
+ > threshold is **0.6** (vs 0.5 for OpenAI) because nomic scores unrelated text
65
+ > higher. Override per call with `--min-score` or via `CEREFOX_MIN_SEARCH_SCORE`.
66
+
63
67
  ---
64
68
 
65
69
  ## Step 1 — Install
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cerefox/memory",
3
- "version": "1.0.0-rc.3",
4
- "description": "Cerefox — user-owned shared memory for AI agents. The local TypeScript runtime: stdio MCP server in v0.4; CLI binary added in v0.5; in-process web server in v0.6; ingestion pipeline in v0.7.",
3
+ "version": "1.0.0",
4
+ "description": "Cerefox — user-owned shared memory for AI agents. CLI + stdio MCP server + web UI + ingestion for a knowledge base on your own Supabase project (or fully self-hosted with Cerefox Local).",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/fstamatelopoulos/cerefox",
7
7
  "repository": {