@seanhogg/builderforce-memory-mcp 2026.7.14 → 2026.9.28

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.
Files changed (58) hide show
  1. package/README.md +47 -5
  2. package/dist/backend.d.ts +32 -0
  3. package/dist/backend.d.ts.map +1 -1
  4. package/dist/backends/memory-store.d.ts +32 -9
  5. package/dist/backends/memory-store.d.ts.map +1 -1
  6. package/dist/backends/memory-store.js +155 -33
  7. package/dist/backends/memory-store.js.map +1 -1
  8. package/dist/bin/http.d.ts +5 -0
  9. package/dist/bin/http.d.ts.map +1 -1
  10. package/dist/bin/http.js +11 -0
  11. package/dist/bin/http.js.map +1 -1
  12. package/dist/bin/install.js +3 -2
  13. package/dist/bin/install.js.map +1 -1
  14. package/dist/bin/stdio.d.ts +17 -7
  15. package/dist/bin/stdio.d.ts.map +1 -1
  16. package/dist/bin/stdio.js +24 -8
  17. package/dist/bin/stdio.js.map +1 -1
  18. package/dist/compaction.d.ts +76 -0
  19. package/dist/compaction.d.ts.map +1 -0
  20. package/dist/compaction.js +77 -0
  21. package/dist/compaction.js.map +1 -0
  22. package/dist/embedding/evermind-embedder.d.ts +119 -0
  23. package/dist/embedding/evermind-embedder.d.ts.map +1 -0
  24. package/dist/embedding/evermind-embedder.js +201 -0
  25. package/dist/embedding/evermind-embedder.js.map +1 -0
  26. package/dist/embedding/index.d.ts +38 -0
  27. package/dist/embedding/index.d.ts.map +1 -0
  28. package/dist/embedding/index.js +44 -0
  29. package/dist/embedding/index.js.map +1 -0
  30. package/dist/index.d.ts +8 -4
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +12 -2
  33. package/dist/index.js.map +1 -1
  34. package/dist/install/claude-hooks.d.ts +42 -2
  35. package/dist/install/claude-hooks.d.ts.map +1 -1
  36. package/dist/install/claude-hooks.js +35 -3
  37. package/dist/install/claude-hooks.js.map +1 -1
  38. package/dist/install/server-spec.d.ts +12 -0
  39. package/dist/install/server-spec.d.ts.map +1 -1
  40. package/dist/install/server-spec.js +18 -0
  41. package/dist/install/server-spec.js.map +1 -1
  42. package/dist/tools.d.ts.map +1 -1
  43. package/dist/tools.js +117 -6
  44. package/dist/tools.js.map +1 -1
  45. package/package.json +15 -4
  46. package/server.json +47 -0
  47. package/src/backend.ts +36 -0
  48. package/src/backends/memory-store.ts +184 -35
  49. package/src/bin/http.ts +12 -0
  50. package/src/bin/install.ts +3 -2
  51. package/src/bin/stdio.ts +25 -8
  52. package/src/compaction.ts +126 -0
  53. package/src/embedding/evermind-embedder.ts +276 -0
  54. package/src/embedding/index.ts +54 -0
  55. package/src/index.ts +18 -4
  56. package/src/install/claude-hooks.ts +40 -4
  57. package/src/install/server-spec.ts +25 -0
  58. package/src/tools.ts +133 -12
package/README.md CHANGED
@@ -20,6 +20,9 @@ your whole memory file into every prompt. That only pays off if recall is
20
20
  - `memory_recall` returns a **ranked top-K** (default 5, hard-capped), never the store.
21
21
  - Each entry's content is **truncated** (default 500 chars) before it hits context.
22
22
  - There is **no "return everything" tool** — a dump-all is more expensive than inlining.
23
+ - `memory_compact` shrinks a fact that something durable has already ABSORBED down to a
24
+ one-line pointer stub, so it stops being recalled in full. It writes **through the live
25
+ store**, which is what keeps memory and the on-disk snapshot in agreement — see below.
23
26
 
24
27
  Tool descriptions are prescriptive ("call this *before* answering when…") because
25
28
  recent Claude models reach for tools more conservatively; the trigger condition in
@@ -65,17 +68,52 @@ for await (const msg of query({
65
68
  }
66
69
  ```
67
70
 
68
- ### SSM-embedding recall (the premium path)
71
+ ### The snapshot is shared — the server watches it
69
72
 
70
- The local backend defaults to **lexical (Jaccard)** recall. For SSM-embedding
71
- cosine recall, pass an SSM runtime — e.g. reuse the agent-runtime's already-loaded
72
- Evermind runtime instead of standing up a second model:
73
+ With `persistFile` set, the store lives in memory and the JSON snapshot is the source of
74
+ truth across process lifetimes. Other processes edit that file too (the BuilderForce VS
75
+ Code extension rewrites absorbed entries to stubs in place), so before every operation the
76
+ backend stats the file and **re-hydrates from disk when it changed underneath** — otherwise
77
+ this server, still holding the pre-edit bodies, would re-snapshot over that work on its next
78
+ write. Its own writes are stamped (mtime + size + content hash) the moment they land, so the
79
+ steady-state cost is one `stat` and there is no write-loop.
80
+
81
+ ### SSM-embedding recall — including on a headless host (no GPU)
82
+
83
+ With no model configured the local backend ranks recall **lexically** (BM25). Point it
84
+ at an Evermind checkpoint and the ordering becomes the SSM embedding's cosine ranking
85
+ **fused with** the lexical one (Reciprocal Rank Fusion — dense ⊕ sparse, so exact
86
+ tokens like identifiers and error codes are still caught). Every `memory_recall`
87
+ result names the ranker it used, so a degrade to lexical is never silent:
88
+
89
+ ```
90
+ Ranked by: semantic recall (SSM embedding fused with lexical).
91
+ Ranked by: lexical recall (fallback - no embedding model loaded).
92
+ ```
93
+
94
+ **The stdio/HTTP servers do not need a GPU for this.** `EvermindLM` is a pure-CPU
95
+ model and `EvermindLM.embed()` mean-pools + L2-normalises the same hidden state the
96
+ GPU `HybridMambaModel.embed()` does, to the same contract. Configure it with:
97
+
98
+ | Env | Meaning |
99
+ |-----|---------|
100
+ | `BUILDERFORCE_MEMORY_MODEL` | Path to a `.evermind` package holding an `evermind-lm`. |
101
+ | `BUILDERFORCE_MEMORY_TOKENIZER` | Tokenizer JSON for that checkpoint. Default `<model>.tokenizer.json`. |
102
+ | `BUILDERFORCE_MEMORY_VECTORS` | Vector-cache path. Defaults beside the memory snapshot. |
103
+
104
+ Vectors are cached **across process lifetimes** (stamped with the model's
105
+ fingerprint, so an adapted checkpoint invalidates them), because a per-session
106
+ subprocess that re-embedded the whole store on its first recall would cost more than
107
+ the lexical ranking it replaces.
108
+
109
+ In-process hosts pass an embedder directly — reuse an already-loaded GPU Evermind
110
+ runtime rather than standing up a second model:
73
111
 
74
112
  ```ts
75
113
  const backend = await createLocalMemoryStoreBackend({ runtime: ssmMemoryService.runtime });
76
114
  ```
77
115
 
78
- Recall quality then improves automatically as that model is adapted/distilled.
116
+ Either way, recall quality improves automatically as that model is adapted/distilled.
79
117
 
80
118
  ## One-shot install into any MCP host (not just Claude)
81
119
 
@@ -165,6 +203,10 @@ const remote: MemoryBackend = {
165
203
  const server = await createMemoryMcpServer(remote);
166
204
  ```
167
205
 
206
+ ## Compaction rules (`@seanhogg/builderforce-memory-mcp/compaction`)
207
+
208
+ The stub format that `memory_compact` writes (`[absorbed→Evermind vN] <first line>`) is published as a dependency-free subpath. An external compactor imports `planCompaction`, `memoryStub` and `isStub` from it, so its stubs are byte-identical to the server's and neither re-stubs the other.
209
+
168
210
  ## Dependencies
169
211
 
170
212
  `@modelcontextprotocol/sdk` + `zod` are hard deps. `@anthropic-ai/claude-agent-sdk`
package/dist/backend.d.ts CHANGED
@@ -26,6 +26,19 @@ export interface RecallHit {
26
26
  /** Unix-ms write time. */
27
27
  timestamp?: number;
28
28
  }
29
+ /**
30
+ * Which ranker produced a recall ordering.
31
+ *
32
+ * Same vocabulary the gateway's Evermind recall/validate result uses, so a host
33
+ * renders one chip ("Semantic recall" / "Lexical recall (fallback)") no matter
34
+ * which layer answered.
35
+ */
36
+ export type RecallMethod = "embedding" | "lexical";
37
+ /** A recall ordering plus the ranker that produced it. */
38
+ export interface RankedRecall {
39
+ hits: RecallHit[];
40
+ method: RecallMethod;
41
+ }
29
42
  /** Arguments for writing a memory. */
30
43
  export interface RememberInput {
31
44
  key: string;
@@ -48,12 +61,31 @@ export interface MemoryBackend {
48
61
  * clamped by the caller — the backend may return fewer, never more.
49
62
  */
50
63
  recall(query: string, topK: number): Promise<RecallHit[]>;
64
+ /**
65
+ * {@link recall} with the ranker named. Optional; callers MUST fall back to
66
+ * plain `recall` (and report nothing) when it is absent.
67
+ *
68
+ * It exists because "did this ordering come from the SSM embedding or from
69
+ * word overlap?" is the difference between semantic recall and a fallback, and
70
+ * an answer that silently degrades to lexical is indistinguishable from one
71
+ * that did not. A backend that knows which path it took says so here.
72
+ */
73
+ recallRanked?(query: string, topK: number): Promise<RankedRecall>;
51
74
  /** Exact lookup by key. Returns undefined when absent or expired. */
52
75
  get(key: string): Promise<RecallHit | undefined>;
53
76
  /** All non-expired entries carrying `tag`, capped to `limit`. */
54
77
  recallByTag(tag: string, limit: number): Promise<RecallHit[]>;
55
78
  /** Store or overwrite a memory. Optional — read-only backends omit it. */
56
79
  remember?(input: RememberInput): Promise<void>;
80
+ /**
81
+ * Store several memories as ONE durable unit. Optional; callers MUST fall
82
+ * back to a `remember` loop when it is absent.
83
+ *
84
+ * It exists for the batch writer (`memory_compact`): a durable backend that
85
+ * flushes after every write would otherwise re-serialise the entire store
86
+ * once per compacted key, which is quadratic in the size of the store.
87
+ */
88
+ rememberMany?(inputs: RememberInput[]): Promise<void>;
57
89
  /** Delete a memory by key. Optional — read-only backends omit it. */
58
90
  forget?(key: string): Promise<void>;
59
91
  }
@@ -1 +1 @@
1
- {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,4DAA4D;AAC5D,MAAM,WAAW,SAAS;IACtB,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC1B;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAE1D,qEAAqE;IACrE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAEjD,iEAAiE;IACjE,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAE9D,0EAA0E;IAC1E,QAAQ,CAAC,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/C,qEAAqE;IACrE,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC"}
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,4DAA4D;AAC5D,MAAM,WAAW,SAAS;IACtB,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;AAEnD,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;CACxB;AAED,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC1B;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAE1D;;;;;;;;OAQG;IACH,YAAY,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAElE,qEAAqE;IACrE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAEjD,iEAAiE;IACjE,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAE9D,0EAA0E;IAC1E,QAAQ,CAAC,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/C;;;;;;;OAOG;IACH,YAAY,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtD,qEAAqE;IACrE,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC"}
@@ -2,12 +2,18 @@
2
2
  * MemoryStoreBackend — local adapter mapping @seanhogg/builderforce-memory's MemoryStore
3
3
  * onto the MemoryBackend seam.
4
4
  *
5
- * Recall quality: when an SSM runtime is supplied it is forwarded to
6
- * `recallSimilar`, so recall uses SSM-embedding cosine similarity and improves
7
- * as the model is adapted/distilled. With no runtime it transparently falls
8
- * back to Jaccard word-overlap (still useful, just lexical).
5
+ * Recall quality: when a text embedder is supplied it is forwarded to the store's
6
+ * `recallRanked`, so the ordering is the shared hybrid retrieval — the SSM
7
+ * embedding's cosine ranking FUSED with BM25 by Reciprocal Rank Fusion — and it
8
+ * sharpens as the model is adapted/distilled. With no embedder the same call
9
+ * degrades to the lexical ranking alone. Either way the backend reports which of
10
+ * the two produced the ordering (`method`), so a silent degrade is visible.
11
+ *
12
+ * The embedder does NOT have to be a GPU runtime: `EvermindTextEmbedder` from the
13
+ * engine is a pure-CPU `EvermindLM`, which is what lets the headless stdio server
14
+ * rank recall semantically (see ./evermind-embedder.ts).
9
15
  */
10
- import type { MemoryBackend, RecallHit, RememberInput } from "../backend.js";
16
+ import type { MemoryBackend, RankedRecall, RecallHit, RememberInput } from "../backend.js";
11
17
  interface MemoryEntryLike {
12
18
  key: string;
13
19
  content: string;
@@ -24,7 +30,14 @@ interface MemoryStoreLike {
24
30
  recall(key: string): Promise<MemoryEntryLike | undefined>;
25
31
  recallAll(): Promise<MemoryEntryLike[]>;
26
32
  recallByTag(tag: string): Promise<MemoryEntryLike[]>;
27
- recallSimilar(query: string, topK: number, runtime?: unknown): Promise<MemoryEntryLike[]>;
33
+ /** Hybrid (dense⊕BM25) recall with each hit's fused score and the ranker used. */
34
+ recallRanked(query: string, topK: number, runtime?: unknown): Promise<{
35
+ hits: Array<{
36
+ entry: MemoryEntryLike;
37
+ score: number;
38
+ }>;
39
+ method: "embedding" | "lexical";
40
+ }>;
28
41
  forget(key: string): Promise<void>;
29
42
  }
30
43
  export declare class MemoryStoreBackend implements MemoryBackend {
@@ -34,10 +47,14 @@ export declare class MemoryStoreBackend implements MemoryBackend {
34
47
  constructor(store: MemoryStoreLike,
35
48
  /** Optional SSMRuntime; enables embedding-based recall when present. */
36
49
  runtime?: unknown | undefined);
50
+ /** Plain recall — {@link recallRanked} with the ranker's name dropped. ONE path. */
37
51
  recall(query: string, topK: number): Promise<RecallHit[]>;
52
+ recallRanked(query: string, topK: number): Promise<RankedRecall>;
38
53
  get(key: string): Promise<RecallHit | undefined>;
39
54
  recallByTag(tag: string, limit: number): Promise<RecallHit[]>;
40
55
  remember(input: RememberInput): Promise<void>;
56
+ /** The store has no batch write; sequencing here keeps ONE definition of a write. */
57
+ rememberMany(inputs: RememberInput[]): Promise<void>;
41
58
  forget(key: string): Promise<void>;
42
59
  }
43
60
  /** Options for {@link createLocalMemoryStoreBackend}. */
@@ -45,9 +62,11 @@ export interface LocalBackendOptions {
45
62
  /** IndexedDB database name. Defaults to MemoryStore's own default ('ssmjs'). */
46
63
  dbName?: string;
47
64
  /**
48
- * Optional SSMRuntime for embedding-based recall. Omit for lexical (Jaccard)
49
- * recall. In the agent-runtime, pass `ssmMemoryService.runtime` here to reuse
50
- * the already-loaded Evermind runtime instead of standing up a second model.
65
+ * Optional text embedder — anything with `embed(text): Promise<Float32Array>`.
66
+ * Omit for lexical-only recall. Pass the agent-runtime's
67
+ * `ssmMemoryService.runtime` to reuse an already-loaded GPU Evermind, or an
68
+ * `EvermindTextEmbedder` (pure CPU) via {@link createEvermindEmbedder} on a
69
+ * headless host.
51
70
  */
52
71
  runtime?: unknown;
53
72
  /**
@@ -59,6 +78,10 @@ export interface LocalBackendOptions {
59
78
  * When set, the store is hydrated from the file on creation and re-snapshotted
60
79
  * after every remember/forget, giving durable cross-process memory. TTLs are
61
80
  * dropped on persist: the snapshot is the durable long-term tier.
81
+ *
82
+ * The file is also WATCHED: it is a shared artifact (other processes compact it
83
+ * in place), so the store re-hydrates from disk whenever it changed underneath —
84
+ * see {@link DiskPersistedBackend} for the loop guard.
62
85
  */
63
86
  persistFile?: string;
64
87
  }
@@ -1 +1 @@
1
- {"version":3,"file":"memory-store.d.ts","sourceRoot":"","sources":["../../src/backends/memory-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI7E,UAAU,eAAe;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,eAAe;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;IAC1D,SAAS,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACxC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACrD,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAC1F,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAYD,qBAAa,kBAAmB,YAAW,aAAa;IAEhD,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,wEAAwE;IACxE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAFR,KAAK,EAAE,eAAe;IACvC,wEAAwE;IACvD,OAAO,CAAC,EAAE,OAAO,YAAA;IAGhC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAKzD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAKhD,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAK7D,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ7C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG3C;AAED,yDAAyD;AACzD,MAAM,WAAW,mBAAmB;IAChC,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAiFD;;;;;GAKG;AACH,wBAAsB,6BAA6B,CAAC,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,aAAa,CAAC,CAgC1G"}
1
+ {"version":3,"file":"memory-store.d.ts","sourceRoot":"","sources":["../../src/backends/memory-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI3F,UAAU,eAAe;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,eAAe;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;IAC1D,SAAS,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACxC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACrD,kFAAkF;IAClF,YAAY,CACR,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,OAAO,GAClB,OAAO,CAAC;QAAE,IAAI,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,eAAe,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;IACxG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAaD,qBAAa,kBAAmB,YAAW,aAAa;IAEhD,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,wEAAwE;IACxE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAFR,KAAK,EAAE,eAAe;IACvC,wEAAwE;IACvD,OAAO,CAAC,EAAE,OAAO,YAAA;IAGtC,oFAAoF;IAC9E,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAIzD,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAKhE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAKhD,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAK7D,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAQnD,qFAAqF;IAC/E,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG3C;AAED,yDAAyD;AACzD,MAAM,WAAW,mBAAmB;IAChC,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAwMD;;;;;GAKG;AACH,wBAAsB,6BAA6B,CAAC,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,aAAa,CAAC,CAkC1G"}
@@ -2,15 +2,22 @@
2
2
  * MemoryStoreBackend — local adapter mapping @seanhogg/builderforce-memory's MemoryStore
3
3
  * onto the MemoryBackend seam.
4
4
  *
5
- * Recall quality: when an SSM runtime is supplied it is forwarded to
6
- * `recallSimilar`, so recall uses SSM-embedding cosine similarity and improves
7
- * as the model is adapted/distilled. With no runtime it transparently falls
8
- * back to Jaccard word-overlap (still useful, just lexical).
5
+ * Recall quality: when a text embedder is supplied it is forwarded to the store's
6
+ * `recallRanked`, so the ordering is the shared hybrid retrieval — the SSM
7
+ * embedding's cosine ranking FUSED with BM25 by Reciprocal Rank Fusion — and it
8
+ * sharpens as the model is adapted/distilled. With no embedder the same call
9
+ * degrades to the lexical ranking alone. Either way the backend reports which of
10
+ * the two produced the ordering (`method`), so a silent degrade is visible.
11
+ *
12
+ * The embedder does NOT have to be a GPU runtime: `EvermindTextEmbedder` from the
13
+ * engine is a pure-CPU `EvermindLM`, which is what lets the headless stdio server
14
+ * rank recall semantically (see ./evermind-embedder.ts).
9
15
  */
10
- function toHit(e) {
16
+ function toHit(e, score) {
11
17
  return {
12
18
  key: e.key,
13
19
  content: e.content,
20
+ ...(score === undefined ? {} : { score }),
14
21
  tags: e.tags,
15
22
  importance: e.importance,
16
23
  timestamp: e.timestamp,
@@ -25,9 +32,13 @@ export class MemoryStoreBackend {
25
32
  this.store = store;
26
33
  this.runtime = runtime;
27
34
  }
35
+ /** Plain recall — {@link recallRanked} with the ranker's name dropped. ONE path. */
28
36
  async recall(query, topK) {
29
- const entries = await this.store.recallSimilar(query, topK, this.runtime);
30
- return entries.map(toHit);
37
+ return (await this.recallRanked(query, topK)).hits;
38
+ }
39
+ async recallRanked(query, topK) {
40
+ const ranked = await this.store.recallRanked(query, topK, this.runtime);
41
+ return { hits: ranked.hits.map((h) => toHit(h.entry, h.score)), method: ranked.method };
31
42
  }
32
43
  async get(key) {
33
44
  const e = await this.store.recall(key);
@@ -44,44 +55,163 @@ export class MemoryStoreBackend {
44
55
  importance: input.importance,
45
56
  });
46
57
  }
58
+ /** The store has no batch write; sequencing here keeps ONE definition of a write. */
59
+ async rememberMany(inputs) {
60
+ for (const input of inputs)
61
+ await this.remember(input);
62
+ }
47
63
  async forget(key) {
48
64
  await this.store.forget(key);
49
65
  }
50
66
  }
67
+ /**
68
+ * FNV-1a over the snapshot text. Non-cryptographic on purpose: this only has to
69
+ * separate "someone rewrote the file" from "the mtime moved but the bytes are
70
+ * ours", and node:crypto is deliberately not imported here (this module must stay
71
+ * bundleable for the browser, where the disk path is never taken).
72
+ */
73
+ function contentHash(text) {
74
+ let h = 0x811c9dc5;
75
+ for (let i = 0; i < text.length; i++) {
76
+ h ^= text.charCodeAt(i);
77
+ h = Math.imul(h, 0x01000193);
78
+ }
79
+ return (h >>> 0).toString(16);
80
+ }
81
+ /** Parse a snapshot's text into its durable entries, or null when unusable. */
82
+ function parseSnapshot(text) {
83
+ let parsed;
84
+ try {
85
+ parsed = JSON.parse(text);
86
+ }
87
+ catch {
88
+ return null;
89
+ }
90
+ if (!Array.isArray(parsed))
91
+ return null;
92
+ return parsed.filter((raw) => !!raw && typeof raw.key === "string" && typeof raw.content === "string");
93
+ }
51
94
  /**
52
95
  * Wraps a MemoryStoreBackend so every write is mirrored to a JSON file, and
53
96
  * hydrates that file back into the store on boot. This is what turns a respawned
54
97
  * stdio subprocess into a persistent memory: the store itself is in-memory, the
55
98
  * file is the source of truth across process lifetimes.
99
+ *
100
+ * It also WATCHES the file for external edits. The snapshot is a shared artifact —
101
+ * the BuilderForce VS Code extension compacts absorbed entries by rewriting it
102
+ * directly, and a second server instance may be mirroring the same path. Without a
103
+ * watch this server, still holding the pre-edit bodies, would silently re-snapshot
104
+ * over that work on its very next remember/forget; the edit would only stick once
105
+ * the client respawned the subprocess. So every operation first calls
106
+ * {@link DiskPersistedBackend.ensureFresh}, which re-hydrates the store from disk
107
+ * when — and only when — the file changed underneath us.
108
+ *
109
+ * The loop guard is the {@link FileStamp} recorded immediately AFTER each of our own
110
+ * writes: the next check stats the file, sees the same mtime+size, and returns
111
+ * without reading a byte. A stat per call is the entire steady-state cost.
56
112
  */
57
113
  class DiskPersistedBackend {
58
114
  inner;
59
115
  store;
60
116
  file;
61
117
  fs;
118
+ /** How the file looked when this process last wrote or read it. */
119
+ stamp = null;
62
120
  constructor(inner, store, file, fs) {
63
121
  this.inner = inner;
64
122
  this.store = store;
65
123
  this.file = file;
66
124
  this.fs = fs;
67
125
  }
68
- recall(query, topK) {
126
+ async recall(query, topK) {
127
+ await this.ensureFresh();
69
128
  return this.inner.recall(query, topK);
70
129
  }
71
- get(key) {
130
+ async recallRanked(query, topK) {
131
+ await this.ensureFresh();
132
+ return this.inner.recallRanked(query, topK);
133
+ }
134
+ async get(key) {
135
+ await this.ensureFresh();
72
136
  return this.inner.get(key);
73
137
  }
74
- recallByTag(tag, limit) {
138
+ async recallByTag(tag, limit) {
139
+ await this.ensureFresh();
75
140
  return this.inner.recallByTag(tag, limit);
76
141
  }
77
142
  async remember(input) {
143
+ await this.ensureFresh();
78
144
  await this.inner.remember(input);
79
145
  await this.snapshot();
80
146
  }
147
+ /** Batch write — ONE snapshot for the whole set, so compacting N keys is not N full rewrites. */
148
+ async rememberMany(inputs) {
149
+ await this.ensureFresh();
150
+ await this.inner.rememberMany(inputs);
151
+ await this.snapshot();
152
+ }
81
153
  async forget(key) {
154
+ await this.ensureFresh();
82
155
  await this.inner.forget(key);
83
156
  await this.snapshot();
84
157
  }
158
+ /**
159
+ * Re-read the snapshot into the store when the file changed since we last
160
+ * touched it. Also the BOOT hydration: with no stamp yet, an existing file is
161
+ * always read in — one routine, so disk and memory can never diverge by taking
162
+ * two different paths.
163
+ */
164
+ async ensureFresh() {
165
+ if (!this.fs.existsSync(this.file))
166
+ return;
167
+ let st;
168
+ try {
169
+ st = this.fs.statSync(this.file);
170
+ }
171
+ catch {
172
+ return;
173
+ }
174
+ // Fast path: byte-for-byte what we last wrote. No read, no parse, no writes.
175
+ if (this.stamp && st.mtimeMs === this.stamp.mtimeMs && st.size === this.stamp.size)
176
+ return;
177
+ let text;
178
+ try {
179
+ text = this.fs.readFileSync(this.file, "utf8");
180
+ }
181
+ catch {
182
+ return;
183
+ }
184
+ const hash = contentHash(text);
185
+ // Touched (mtime moved) but identical content — re-stamp, don't re-hydrate.
186
+ if (this.stamp && hash === this.stamp.hash) {
187
+ this.stamp = { mtimeMs: st.mtimeMs, size: st.size, hash };
188
+ return;
189
+ }
190
+ const entries = parseSnapshot(text);
191
+ // Corrupt/partial snapshot (a half-written file, say): keep what we have
192
+ // rather than wiping the live store, and leave the stamp alone so the next
193
+ // call re-checks.
194
+ if (!entries)
195
+ return;
196
+ await this.replaceStore(entries);
197
+ this.stamp = { mtimeMs: st.mtimeMs, size: st.size, hash };
198
+ }
199
+ /**
200
+ * Make the in-memory store equal the snapshot: drop keys the file no longer has,
201
+ * then replay every entry (a re-remember overwrites, so a body shortened to a
202
+ * stub on disk becomes the stub in memory). Replayed as durable — TTLs are
203
+ * dropped on persist; the snapshot is the long-term tier.
204
+ */
205
+ async replaceStore(entries) {
206
+ const wanted = new Set(entries.map((e) => e.key));
207
+ for (const existing of await this.store.recallAll()) {
208
+ if (!wanted.has(existing.key))
209
+ await this.store.forget(existing.key);
210
+ }
211
+ for (const raw of entries) {
212
+ await this.store.remember(raw.key, raw.content, { tags: raw.tags, importance: raw.importance });
213
+ }
214
+ }
85
215
  async snapshot() {
86
216
  const entries = await this.store.recallAll();
87
217
  const out = entries.map((e) => ({
@@ -90,27 +220,17 @@ class DiskPersistedBackend {
90
220
  tags: e.tags,
91
221
  importance: e.importance,
92
222
  }));
93
- this.fs.writeFileSync(this.file, JSON.stringify(out, null, 2));
94
- }
95
- }
96
- /** Reads a snapshot file and replays it into the store as durable (no-TTL) entries. */
97
- async function hydrateFromDisk(store, file, fs) {
98
- if (!fs.existsSync(file))
99
- return;
100
- let parsed;
101
- try {
102
- parsed = JSON.parse(fs.readFileSync(file, "utf8"));
103
- }
104
- catch {
105
- // Corrupt/partial snapshot — start clean rather than crash the server.
106
- return;
107
- }
108
- if (!Array.isArray(parsed))
109
- return;
110
- for (const raw of parsed) {
111
- if (!raw || typeof raw.key !== "string" || typeof raw.content !== "string")
112
- continue;
113
- await store.remember(raw.key, raw.content, { tags: raw.tags, importance: raw.importance });
223
+ const json = JSON.stringify(out, null, 2);
224
+ this.fs.writeFileSync(this.file, json);
225
+ // Stamp OUR write immediately — this is what stops the watch above from
226
+ // treating our own output as an external edit (and looping).
227
+ try {
228
+ const st = this.fs.statSync(this.file);
229
+ this.stamp = { mtimeMs: st.mtimeMs, size: st.size, hash: contentHash(json) };
230
+ }
231
+ catch {
232
+ this.stamp = null;
233
+ }
114
234
  }
115
235
  }
116
236
  /**
@@ -146,7 +266,9 @@ export async function createLocalMemoryStoreBackend(opts = {}) {
146
266
  const dir = path.dirname(opts.persistFile);
147
267
  if (dir && !fs.existsSync(dir))
148
268
  fs.mkdirSync(dir, { recursive: true });
149
- await hydrateFromDisk(store, opts.persistFile, fs);
150
- return new DiskPersistedBackend(backend, store, opts.persistFile, fs);
269
+ const persisted = new DiskPersistedBackend(backend, store, opts.persistFile, fs);
270
+ // Boot hydration IS the freshness check with no stamp yet — see ensureFresh().
271
+ await persisted.ensureFresh();
272
+ return persisted;
151
273
  }
152
274
  //# sourceMappingURL=memory-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory-store.js","sourceRoot":"","sources":["../../src/backends/memory-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuBH,SAAS,KAAK,CAAC,CAAkB;IAC7B,OAAO;QACH,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,SAAS,EAAE,CAAC,CAAC,SAAS;KACzB,CAAC;AACN,CAAC;AAED,MAAM,OAAO,kBAAkB;IAEN;IAEA;IAHrB,YACqB,KAAsB;IACvC,wEAAwE;IACvD,OAAiB;QAFjB,UAAK,GAAL,KAAK,CAAiB;QAEtB,YAAO,GAAP,OAAO,CAAU;IACnC,CAAC;IAEJ,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,IAAY;QACpC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1E,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACjB,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,GAAW,EAAE,KAAa;QACxC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAClD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAoB;QAC/B,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE;YAChD,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,UAAU,EAAE,KAAK,CAAC,UAAU;SAC/B,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACpB,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;CACJ;AAyCD;;;;;GAKG;AACH,MAAM,oBAAoB;IAED;IACA;IACA;IACA;IAJrB,YACqB,KAAyB,EACzB,KAAsB,EACtB,IAAY,EACZ,EAAU;QAHV,UAAK,GAAL,KAAK,CAAoB;QACzB,UAAK,GAAL,KAAK,CAAiB;QACtB,SAAI,GAAJ,IAAI,CAAQ;QACZ,OAAE,GAAF,EAAE,CAAQ;IAC5B,CAAC;IAEJ,MAAM,CAAC,KAAa,EAAE,IAAY;QAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC1C,CAAC;IACD,GAAG,CAAC,GAAW;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IACD,WAAW,CAAC,GAAW,EAAE,KAAa;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAoB;QAC/B,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACpB,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAEO,KAAK,CAAC,QAAQ;QAClB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QAC7C,MAAM,GAAG,GAAoB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7C,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,UAAU,EAAE,CAAC,CAAC,UAAU;SAC3B,CAAC,CAAC,CAAC;QACJ,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACnE,CAAC;CACJ;AAED,uFAAuF;AACvF,KAAK,UAAU,eAAe,CAAC,KAAsB,EAAE,IAAY,EAAE,EAAU;IAC3E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO;IACjC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACL,uEAAuE;QACvE,OAAO;IACX,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO;IACnC,KAAK,MAAM,GAAG,IAAI,MAAyB,EAAE,CAAC;QAC1C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;YAAE,SAAS;QACrF,MAAM,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;IAC/F,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,OAA4B,EAAE;IAC9E,0EAA0E;IAC1E,MAAM,OAAO,GAAG,CAAC,CAAS,EAAoB,EAAE;IAC5C,2EAA2E;IAC3E,IAAI,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAqB,CAAC;IAEjE,MAAM,SAAS,GAAG,CAAC,MAAM,OAAO,CAAC,+BAA+B,CAAC,CAAyD,CAAC;IAC3H,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;IAElC,4EAA4E;IAC5E,IAAI,UAAmB,CAAC;IACxB,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAsC,CAAC;QACpF,UAAU,GAAG,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACL,6EAA6E;IACjF,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAE5D,IAAI,CAAC,IAAI,CAAC,WAAW;QAAE,OAAO,OAAO,CAAC;IAEtC,yEAAyE;IACzE,iEAAiE;IACjE,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,CAAW,CAAC;IAChD,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,WAAW,CAAC,CAAa,CAAC;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEvE,MAAM,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACnD,OAAO,IAAI,oBAAoB,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;AAC1E,CAAC"}
1
+ {"version":3,"file":"memory-store.js","sourceRoot":"","sources":["../../src/backends/memory-store.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,11 @@
9
9
  * BUILDERFORCE_MEMORY_TOKEN Bearer token required on every request (recommended).
10
10
  * BUILDERFORCE_MEMORY_DB IndexedDB database name.
11
11
  * BUILDERFORCE_MEMORY_READONLY '1' to disable remember/forget tools.
12
+ * BUILDERFORCE_MEMORY_FILE JSON snapshot path (also sites the vector cache).
13
+ * BUILDERFORCE_MEMORY_MODEL `.evermind` package to rank recall by SSM embedding
14
+ * (pure CPU, no GPU). Unset = lexical ranking.
15
+ * BUILDERFORCE_MEMORY_TOKENIZER Tokenizer JSON for that checkpoint.
16
+ * BUILDERFORCE_MEMORY_VECTORS Persistent vector-cache path.
12
17
  * BUILDERFORCE_GATEWAY_URL Gateway base URL (default https://api.builderforce.ai).
13
18
  * BUILDERFORCE_API_KEY `bfk_*` tenant key. When set, exposes the cost tools.
14
19
  */
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/bin/http.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/bin/http.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG"}
package/dist/bin/http.js CHANGED
@@ -9,14 +9,25 @@
9
9
  * BUILDERFORCE_MEMORY_TOKEN Bearer token required on every request (recommended).
10
10
  * BUILDERFORCE_MEMORY_DB IndexedDB database name.
11
11
  * BUILDERFORCE_MEMORY_READONLY '1' to disable remember/forget tools.
12
+ * BUILDERFORCE_MEMORY_FILE JSON snapshot path (also sites the vector cache).
13
+ * BUILDERFORCE_MEMORY_MODEL `.evermind` package to rank recall by SSM embedding
14
+ * (pure CPU, no GPU). Unset = lexical ranking.
15
+ * BUILDERFORCE_MEMORY_TOKENIZER Tokenizer JSON for that checkpoint.
16
+ * BUILDERFORCE_MEMORY_VECTORS Persistent vector-cache path.
12
17
  * BUILDERFORCE_GATEWAY_URL Gateway base URL (default https://api.builderforce.ai).
13
18
  * BUILDERFORCE_API_KEY `bfk_*` tenant key. When set, exposes the cost tools.
14
19
  */
15
20
  import http from "node:http";
16
21
  import { createLocalMemoryStoreBackend } from "../backends/memory-store.js";
22
+ import { createRecallEmbedder } from "../embedding/index.js";
23
+ import { resolveMemoryFile } from "../install/server-spec.js";
17
24
  import { createMemoryHttpHandler } from "../transports/http.js";
25
+ const memoryFile = resolveMemoryFile();
18
26
  const backend = await createLocalMemoryStoreBackend({
19
27
  dbName: process.env["BUILDERFORCE_MEMORY_DB"],
28
+ // Same embedder decision as the stdio bin, from the same helper — the two
29
+ // servers must not rank recall differently.
30
+ runtime: (await createRecallEmbedder({ memoryFile })) ?? undefined,
20
31
  });
21
32
  const handler = createMemoryHttpHandler(backend, {
22
33
  authToken: process.env["BUILDERFORCE_MEMORY_TOKEN"],
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/bin/http.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,MAAM,OAAO,GAAG,MAAM,6BAA6B,CAAC;IAChD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;CAChD,CAAC,CAAC;AAEH,MAAM,OAAO,GAAG,uBAAuB,CAAC,OAAO,EAAE;IAC7C,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;IACnD,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,KAAK,GAAG;IAC7D,2EAA2E;IAC3E,0EAA0E;IAC1E,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,IAAI,6BAA6B;IACpF,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;CACrD,CAAC,CAAC;AAEH,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;AAEjD,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IAC3B,KAAK,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACjC,IAAI,CAAC,GAAG,CAAC,WAAW;YAAE,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACjF,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gDAAgD,IAAI,IAAI,CAAC,CAAC;AACnF,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/bin/http.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAC;AAEvC,MAAM,OAAO,GAAG,MAAM,6BAA6B,CAAC;IAChD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;IAC7C,0EAA0E;IAC1E,4CAA4C;IAC5C,OAAO,EAAE,CAAC,MAAM,oBAAoB,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,IAAI,SAAS;CACrE,CAAC,CAAC;AAEH,MAAM,OAAO,GAAG,uBAAuB,CAAC,OAAO,EAAE;IAC7C,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;IACnD,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,KAAK,GAAG;IAC7D,2EAA2E;IAC3E,0EAA0E;IAC1E,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,IAAI,6BAA6B;IACpF,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;CACrD,CAAC,CAAC;AAEH,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;AAEjD,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IAC3B,KAAK,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACjC,IAAI,CAAC,GAAG,CAAC,WAAW;YAAE,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACjF,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gDAAgD,IAAI,IAAI,CAAC,CAAC;AACnF,CAAC,CAAC,CAAC"}
@@ -21,6 +21,7 @@ import nodeFs from "node:fs";
21
21
  import { HOSTS } from "../install/hosts.js";
22
22
  import { installMemoryServer } from "../install/install.js";
23
23
  import { installClaudeCombo } from "../install/claude-hooks.js";
24
+ import { defaultMemoryFile } from "../install/server-spec.js";
24
25
  function argValue(name) {
25
26
  const hit = process.argv.find((a) => a.startsWith(`--${name}=`));
26
27
  return hit ? hit.slice(name.length + 3) : undefined;
@@ -46,7 +47,7 @@ const hosts = hostArg === undefined || hostArg === "auto"
46
47
  : hostArg === "all"
47
48
  ? "all"
48
49
  : hostArg.split(",").map((s) => s.trim()).filter(Boolean);
49
- const memoryFile = argValue("memory-file") ?? path.join(os.homedir(), ".builderforce-memory", "memory.json");
50
+ const memoryFile = argValue("memory-file") ?? defaultMemoryFile();
50
51
  let results;
51
52
  try {
52
53
  results = installMemoryServer({
@@ -99,6 +100,6 @@ if (results.length === 0) {
99
100
  process.stdout.write("No MCP hosts detected. Pass --host=all to write configs anyway, or --host=cursor (etc.).\n");
100
101
  }
101
102
  else {
102
- process.stdout.write(`\nDone — ${wrote} config(s) written. Store: ${memoryFile}\nRestart the agent(s) to connect. Tools: memory_recall · memory_remember · memory_get · memory_recall_by_tag · memory_forget\n`);
103
+ process.stdout.write(`\nDone — ${wrote} config(s) written. Store: ${memoryFile}\nRestart the agent(s) to connect. Tools: memory_recall · memory_remember · memory_get · memory_recall_by_tag · memory_forget · memory_compact\n`);
103
104
  }
104
105
  //# sourceMappingURL=install.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/bin/install.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/bin/install.ts"],"names":[],"mappings":"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"}