@seanhogg/builderforce-memory-mcp 2026.10.3 → 2026.10.22
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 +22 -5
- package/dist/backend.d.ts +26 -0
- package/dist/backend.d.ts.map +1 -1
- package/dist/backends/memory-store.d.ts +50 -2
- package/dist/backends/memory-store.d.ts.map +1 -1
- package/dist/backends/memory-store.js +88 -10
- package/dist/backends/memory-store.js.map +1 -1
- package/dist/bin/http.js +7 -1
- package/dist/bin/http.js.map +1 -1
- package/dist/bin/install.js +6 -3
- package/dist/bin/install.js.map +1 -1
- package/dist/bin/stdio.d.ts +9 -4
- package/dist/bin/stdio.d.ts.map +1 -1
- package/dist/bin/stdio.js +20 -5
- package/dist/bin/stdio.js.map +1 -1
- package/dist/compaction-tools.d.ts +15 -0
- package/dist/compaction-tools.d.ts.map +1 -0
- package/dist/compaction-tools.js +192 -0
- package/dist/compaction-tools.js.map +1 -0
- package/dist/compaction.d.ts +114 -8
- package/dist/compaction.d.ts.map +1 -1
- package/dist/compaction.js +161 -7
- package/dist/compaction.js.map +1 -1
- package/dist/index.d.ts +13 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -7
- package/dist/index.js.map +1 -1
- package/dist/install/claude-hooks.d.ts +5 -0
- package/dist/install/claude-hooks.d.ts.map +1 -1
- package/dist/install/claude-hooks.js +69 -9
- package/dist/install/claude-hooks.js.map +1 -1
- package/dist/install/server-spec.d.ts +33 -7
- package/dist/install/server-spec.d.ts.map +1 -1
- package/dist/install/server-spec.js +59 -9
- package/dist/install/server-spec.js.map +1 -1
- package/dist/model/recall-probe.d.ts +29 -0
- package/dist/model/recall-probe.d.ts.map +1 -0
- package/dist/model/recall-probe.js +72 -0
- package/dist/model/recall-probe.js.map +1 -0
- package/dist/persistence/fact-archive.d.ts +47 -0
- package/dist/persistence/fact-archive.d.ts.map +1 -0
- package/dist/persistence/fact-archive.js +85 -0
- package/dist/persistence/fact-archive.js.map +1 -0
- package/dist/persistence/shared-json-file.d.ts +24 -1
- package/dist/persistence/shared-json-file.d.ts.map +1 -1
- package/dist/persistence/shared-json-file.js +46 -1
- package/dist/persistence/shared-json-file.js.map +1 -1
- package/dist/restore.d.ts +56 -0
- package/dist/restore.d.ts.map +1 -0
- package/dist/restore.js +118 -0
- package/dist/restore.js.map +1 -0
- package/dist/tools.d.ts +13 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +11 -90
- package/dist/tools.js.map +1 -1
- package/package.json +6 -6
- package/server.json +2 -2
- package/src/backend.ts +29 -0
- package/src/backends/memory-store.ts +141 -11
- package/src/bin/http.ts +7 -1
- package/src/bin/install.ts +7 -3
- package/src/bin/stdio.ts +20 -5
- package/src/compaction-tools.ts +206 -0
- package/src/compaction.ts +228 -9
- package/src/index.ts +55 -10
- package/src/install/claude-hooks.ts +72 -9
- package/src/install/server-spec.ts +74 -8
- package/src/model/recall-probe.ts +81 -0
- package/src/persistence/fact-archive.ts +101 -0
- package/src/persistence/shared-json-file.ts +54 -1
- package/src/restore.ts +144 -0
- package/src/tools.ts +24 -93
package/dist/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seanhogg/builderforce-memory-mcp",
|
|
3
|
-
"version": "2026.10.
|
|
3
|
+
"version": "2026.10.22",
|
|
4
4
|
"mcpName": "io.github.SeanHogg/builderforce-memory",
|
|
5
5
|
"description": "BuilderForce Agent Memory — MCP transport. Exposes @seanhogg/builderforce-memory to any MCP client (Claude Agent SDK in-process, stdio, or HTTP) over a pluggable MemoryBackend, with token-saving fetch-on-demand recall.",
|
|
6
6
|
"type": "module",
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"@anthropic-ai/claude-agent-sdk": ">=0.1.0",
|
|
59
|
-
"@seanhogg/builderforce-memory": "^2026.10.
|
|
60
|
-
"@seanhogg/builderforce-memory-engine": "^2026.10.
|
|
59
|
+
"@seanhogg/builderforce-memory": "^2026.10.22",
|
|
60
|
+
"@seanhogg/builderforce-memory-engine": "^2026.10.22",
|
|
61
61
|
"fake-indexeddb": "^6.0.0"
|
|
62
62
|
},
|
|
63
63
|
"peerDependenciesMeta": {
|
|
@@ -83,8 +83,8 @@
|
|
|
83
83
|
"fake-indexeddb": "^6.0.0",
|
|
84
84
|
"typescript": "^6.0.3",
|
|
85
85
|
"@typescript/native-preview": "7.0.0-dev.20260627.2",
|
|
86
|
-
"@seanhogg/builderforce-memory": "2026.10.
|
|
87
|
-
"@seanhogg/builderforce-memory-engine": "2026.10.
|
|
86
|
+
"@seanhogg/builderforce-memory": "2026.10.22",
|
|
87
|
+
"@seanhogg/builderforce-memory-engine": "2026.10.22"
|
|
88
88
|
},
|
|
89
89
|
"engines": {
|
|
90
90
|
"node": ">=18.0.0"
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
},
|
|
95
95
|
"scripts": {
|
|
96
96
|
"build": "tsc",
|
|
97
|
-
"test": "tsc && node --test tests/install.test.mjs tests/tools.test.mjs tests/http.test.mjs tests/compaction.test.mjs tests/recall-method.test.mjs tests/experience.test.mjs",
|
|
97
|
+
"test": "tsc && node --test tests/install.test.mjs tests/tools.test.mjs tests/http.test.mjs tests/compaction.test.mjs tests/recall-method.test.mjs tests/experience.test.mjs tests/lossless.test.mjs",
|
|
98
98
|
"lint": "eslint src/",
|
|
99
99
|
"typecheck:native": "tsgo --noEmit"
|
|
100
100
|
}
|
package/server.json
CHANGED
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
"source": "github",
|
|
9
9
|
"subfolder": "packages/memory-mcp"
|
|
10
10
|
},
|
|
11
|
-
"version": "2026.10.
|
|
11
|
+
"version": "2026.10.22",
|
|
12
12
|
"websiteUrl": "https://builderforce.ai",
|
|
13
13
|
"packages": [
|
|
14
14
|
{
|
|
15
15
|
"registryType": "npm",
|
|
16
16
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
17
17
|
"identifier": "@seanhogg/builderforce-memory-mcp",
|
|
18
|
-
"version": "2026.10.
|
|
18
|
+
"version": "2026.10.22",
|
|
19
19
|
"transport": {
|
|
20
20
|
"type": "stdio"
|
|
21
21
|
},
|
package/src/backend.ts
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
* transports.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import type { ArchivedFact } from "./compaction.js";
|
|
12
|
+
|
|
11
13
|
/** A single recalled memory, normalised across backends. */
|
|
12
14
|
export interface RecallHit {
|
|
13
15
|
/** Stable identifier for the memory. */
|
|
@@ -26,6 +28,18 @@ export interface RecallHit {
|
|
|
26
28
|
importance?: number;
|
|
27
29
|
/** Unix-ms write time. */
|
|
28
30
|
timestamp?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Set when the stored body is a compaction stub that was resolved to its
|
|
33
|
+
* archived original: `content` is then the FULL original and this is the stub
|
|
34
|
+
* actually stored. Absent for an ordinary (uncompacted) memory.
|
|
35
|
+
*/
|
|
36
|
+
stub?: string;
|
|
37
|
+
/**
|
|
38
|
+
* True when the stored body is a compaction stub with NO archived original — the
|
|
39
|
+
* text is gone and only the one-line pointer remains. Readers must label it
|
|
40
|
+
* (`CONTENT_LOST_LABEL`) and treat it as unverified; `memory_restore` clears it.
|
|
41
|
+
*/
|
|
42
|
+
contentLost?: boolean;
|
|
29
43
|
}
|
|
30
44
|
|
|
31
45
|
/**
|
|
@@ -99,4 +113,19 @@ export interface MemoryBackend {
|
|
|
99
113
|
|
|
100
114
|
/** Delete a memory by key. Optional — read-only backends omit it. */
|
|
101
115
|
forget?(key: string): Promise<void>;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Durably store the full originals of facts about to be compacted. Optional —
|
|
119
|
+
* but `memory_compact` stubs NOTHING on a backend without it, because a stub
|
|
120
|
+
* whose original was never kept is lost content. Must be durable before it
|
|
121
|
+
* resolves: the compactor writes the stubs only afterwards.
|
|
122
|
+
*/
|
|
123
|
+
archive?(facts: ArchivedFact[]): Promise<void>;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Keys whose stored body is a compaction stub with no archived original
|
|
127
|
+
* (`contentLost`). Optional; `memory_restore` uses it to match restore records
|
|
128
|
+
* by text, and falls back to key-only matching without it.
|
|
129
|
+
*/
|
|
130
|
+
lostKeys?(): Promise<string[]>;
|
|
102
131
|
}
|
|
@@ -12,10 +12,20 @@
|
|
|
12
12
|
* The embedder does NOT have to be a GPU runtime: `EvermindTextEmbedder` from the
|
|
13
13
|
* engine is a pure-CPU `EvermindLM`, which is what lets the headless stdio server
|
|
14
14
|
* rank recall semantically (see ./evermind-embedder.ts).
|
|
15
|
+
*
|
|
16
|
+
* Ranking signals: recall also weights each fused score by the fact's importance
|
|
17
|
+
* (x(0.5+importance), the cloud recall's factor) and a half-life recency decay —
|
|
18
|
+
* both ON by default here ({@link DEFAULT_RECALL_RANKING}).
|
|
19
|
+
*
|
|
20
|
+
* Compaction stubs: a stored body that is an `[absorbed→Evermind …]` stub is
|
|
21
|
+
* resolved to its ARCHIVED original (../persistence/fact-archive.ts) on every read,
|
|
22
|
+
* so recall returns the full text; a stub with no archive is flagged `contentLost`.
|
|
15
23
|
*/
|
|
16
24
|
|
|
17
25
|
import type { MemoryBackend, RankedRecall, RecallHit, RememberInput } from "../backend.js";
|
|
26
|
+
import { defaultArchiveFile, isContentLost, isStub, type ArchivedFact } from "../compaction.js";
|
|
18
27
|
import { dynamicImport } from "../dynamic-import.js";
|
|
28
|
+
import { FileFactArchive, MemoryFactArchive, type FactArchive } from "../persistence/fact-archive.js";
|
|
19
29
|
import { SharedJsonFile, type SharedFileFs } from "../persistence/shared-json-file.js";
|
|
20
30
|
|
|
21
31
|
// Structural views of the @seanhogg/builderforce-memory surface we use, so this package
|
|
@@ -28,8 +38,29 @@ interface MemoryEntryLike {
|
|
|
28
38
|
importance?: number;
|
|
29
39
|
}
|
|
30
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Recall ranking signals — the subset of the store's `HybridRetrieveOptions` this
|
|
43
|
+
* backend sets. Structural, so this package needs no type import from the runtime.
|
|
44
|
+
*/
|
|
45
|
+
export interface RecallRanking {
|
|
46
|
+
/** Weight each fused score by `0.5 + importance`. */
|
|
47
|
+
importanceWeight?: boolean;
|
|
48
|
+
/** Half-life (days) of the recency decay over each fact's write time; 0 = off. */
|
|
49
|
+
recencyHalfLifeDays?: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Recall ranking defaults: importance ON, 90-day half-life recency decay ON. */
|
|
53
|
+
export const DEFAULT_RECALL_RANKING: Readonly<Required<RecallRanking>> = Object.freeze({
|
|
54
|
+
importanceWeight: true,
|
|
55
|
+
recencyHalfLifeDays: 90,
|
|
56
|
+
});
|
|
57
|
+
|
|
31
58
|
interface MemoryStoreLike {
|
|
32
|
-
remember(
|
|
59
|
+
remember(
|
|
60
|
+
key: string,
|
|
61
|
+
content: string,
|
|
62
|
+
opts?: { ttlMs?: number; tags?: string[]; importance?: number; timestamp?: number },
|
|
63
|
+
): Promise<void>;
|
|
33
64
|
recall(key: string): Promise<MemoryEntryLike | undefined>;
|
|
34
65
|
recallAll(): Promise<MemoryEntryLike[]>;
|
|
35
66
|
recallByTag(tag: string): Promise<MemoryEntryLike[]>;
|
|
@@ -38,12 +69,18 @@ interface MemoryStoreLike {
|
|
|
38
69
|
query: string,
|
|
39
70
|
topK: number,
|
|
40
71
|
runtime?: unknown,
|
|
72
|
+
opts?: RecallRanking,
|
|
41
73
|
): Promise<{ hits: Array<{ entry: MemoryEntryLike; score: number }>; method: "embedding" | "lexical" }>;
|
|
42
74
|
forget(key: string): Promise<void>;
|
|
43
75
|
}
|
|
44
76
|
|
|
45
|
-
|
|
46
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Normalise a stored entry into a hit, resolving a compaction stub: with an archived
|
|
79
|
+
* original the hit carries the FULL text (and the stored stub in `stub`); without one
|
|
80
|
+
* it keeps the stub and is flagged `contentLost`.
|
|
81
|
+
*/
|
|
82
|
+
function toHit(e: MemoryEntryLike, archived: ArchivedFact | undefined, score?: number): RecallHit {
|
|
83
|
+
const base: RecallHit = {
|
|
47
84
|
key: e.key,
|
|
48
85
|
content: e.content,
|
|
49
86
|
...(score === undefined ? {} : { score }),
|
|
@@ -51,14 +88,31 @@ function toHit(e: MemoryEntryLike, score?: number): RecallHit {
|
|
|
51
88
|
importance: e.importance,
|
|
52
89
|
timestamp: e.timestamp,
|
|
53
90
|
};
|
|
91
|
+
if (!isStub(e.content)) return base;
|
|
92
|
+
if (archived) return { ...base, content: archived.content, stub: e.content };
|
|
93
|
+
return { ...base, contentLost: true };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface MemoryStoreBackendOptions {
|
|
97
|
+
/** Where compacted originals are kept. Default: an in-process archive. */
|
|
98
|
+
archive?: FactArchive;
|
|
99
|
+
/** Recall ranking signals. Default {@link DEFAULT_RECALL_RANKING}; `false` = fusion alone. */
|
|
100
|
+
ranking?: RecallRanking | false;
|
|
54
101
|
}
|
|
55
102
|
|
|
56
103
|
export class MemoryStoreBackend implements MemoryBackend {
|
|
104
|
+
private readonly facts: FactArchive;
|
|
105
|
+
private readonly ranking: RecallRanking | undefined;
|
|
106
|
+
|
|
57
107
|
constructor(
|
|
58
108
|
private readonly store: MemoryStoreLike,
|
|
59
109
|
/** Optional SSMRuntime; enables embedding-based recall when present. */
|
|
60
110
|
private readonly runtime?: unknown,
|
|
61
|
-
|
|
111
|
+
opts: MemoryStoreBackendOptions = {},
|
|
112
|
+
) {
|
|
113
|
+
this.facts = opts.archive ?? new MemoryFactArchive();
|
|
114
|
+
this.ranking = opts.ranking === false ? undefined : { ...DEFAULT_RECALL_RANKING, ...opts.ranking };
|
|
115
|
+
}
|
|
62
116
|
|
|
63
117
|
/** Plain recall — {@link recallRanked} with the ranker's name dropped. ONE path. */
|
|
64
118
|
async recall(query: string, topK: number): Promise<RecallHit[]> {
|
|
@@ -66,18 +120,35 @@ export class MemoryStoreBackend implements MemoryBackend {
|
|
|
66
120
|
}
|
|
67
121
|
|
|
68
122
|
async recallRanked(query: string, topK: number): Promise<RankedRecall> {
|
|
69
|
-
const ranked = await this.store.recallRanked(query, topK, this.runtime);
|
|
70
|
-
|
|
123
|
+
const ranked = await this.store.recallRanked(query, topK, this.runtime, this.ranking);
|
|
124
|
+
const rows = this.facts.all();
|
|
125
|
+
return { hits: ranked.hits.map((h) => toHit(h.entry, rows[h.entry.key], h.score)), method: ranked.method };
|
|
71
126
|
}
|
|
72
127
|
|
|
73
128
|
async get(key: string): Promise<RecallHit | undefined> {
|
|
74
129
|
const e = await this.store.recall(key);
|
|
75
|
-
return e ? toHit(e) : undefined;
|
|
130
|
+
return e ? toHit(e, this.facts.get(key)) : undefined;
|
|
76
131
|
}
|
|
77
132
|
|
|
78
133
|
async recallByTag(tag: string, limit: number): Promise<RecallHit[]> {
|
|
79
134
|
const entries = await this.store.recallByTag(tag);
|
|
80
|
-
|
|
135
|
+
const rows = this.facts.all();
|
|
136
|
+
return entries.slice(0, limit).map((e) => toHit(e, rows[e.key]));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async archive(facts: ArchivedFact[]): Promise<void> {
|
|
140
|
+
this.facts.putMany(facts);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Keys whose stored body is a stub with no archived original. */
|
|
144
|
+
async lostKeys(): Promise<string[]> {
|
|
145
|
+
const rows = this.facts.all();
|
|
146
|
+
return (await this.store.recallAll()).filter((e) => isContentLost(e.content, rows[e.key])).map((e) => e.key);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Every archived row, read once — the snapshot writer's `contentLost` source. */
|
|
150
|
+
archivedRows(): Readonly<Record<string, ArchivedFact>> {
|
|
151
|
+
return this.facts.all();
|
|
81
152
|
}
|
|
82
153
|
|
|
83
154
|
async remember(input: RememberInput): Promise<void> {
|
|
@@ -144,6 +215,18 @@ export interface LocalBackendOptions {
|
|
|
144
215
|
* when `BUILDERFORCE_MEMORY_MODEL` is set, so this is mostly for tests.
|
|
145
216
|
*/
|
|
146
217
|
semanticRecall?: false;
|
|
218
|
+
/**
|
|
219
|
+
* Recall ranking signals (importance weighting, half-life recency decay).
|
|
220
|
+
* Default {@link DEFAULT_RECALL_RANKING} — both on; `false` ranks by fusion alone.
|
|
221
|
+
*/
|
|
222
|
+
ranking?: RecallRanking | false;
|
|
223
|
+
/**
|
|
224
|
+
* Where compacted originals are archived. Default: beside `persistFile`
|
|
225
|
+
* (`memory.archive.json`) when there is one, else in-process.
|
|
226
|
+
*/
|
|
227
|
+
archiveFile?: string;
|
|
228
|
+
/** Diagnostic sink (stderr by default — stdout is the MCP stdio channel). */
|
|
229
|
+
log?: (line: string) => void;
|
|
147
230
|
}
|
|
148
231
|
|
|
149
232
|
/**
|
|
@@ -159,6 +242,14 @@ interface SnapshotEntry {
|
|
|
159
242
|
content: string;
|
|
160
243
|
tags?: string[];
|
|
161
244
|
importance?: number;
|
|
245
|
+
/** Unix-ms write time — persisted so recency ranking survives a respawn. */
|
|
246
|
+
timestamp?: number;
|
|
247
|
+
/**
|
|
248
|
+
* Written as true for a stub with no archived original, so dependency-free
|
|
249
|
+
* readers (the Claude Code hook) can label it without reading the archive.
|
|
250
|
+
* Derived on every write — never read back as truth; the archive decides.
|
|
251
|
+
*/
|
|
252
|
+
contentLost?: true;
|
|
162
253
|
}
|
|
163
254
|
|
|
164
255
|
type FsLike = SharedFileFs & { mkdirSync(path: string, opts: { recursive: boolean }): void };
|
|
@@ -269,17 +360,41 @@ class DiskPersistedBackend implements MemoryBackend {
|
|
|
269
360
|
if (!wanted.has(existing.key)) await this.store.forget(existing.key);
|
|
270
361
|
}
|
|
271
362
|
for (const raw of entries) {
|
|
272
|
-
await this.store.remember(raw.key, raw.content, {
|
|
363
|
+
await this.store.remember(raw.key, raw.content, {
|
|
364
|
+
tags: raw.tags,
|
|
365
|
+
importance: raw.importance,
|
|
366
|
+
...(typeof raw.timestamp === "number" && Number.isFinite(raw.timestamp) ? { timestamp: raw.timestamp } : {}),
|
|
367
|
+
});
|
|
273
368
|
}
|
|
274
369
|
}
|
|
275
370
|
|
|
371
|
+
/**
|
|
372
|
+
* Archive first — durable before the caller writes the stubs. When the rows
|
|
373
|
+
* RESTORE lost stubs (memory_restore), the snapshot is rewritten too, so its
|
|
374
|
+
* derived `contentLost` flags stop naming them.
|
|
375
|
+
*/
|
|
376
|
+
async archive(facts: ArchivedFact[]): Promise<void> {
|
|
377
|
+
await this.ensureFresh();
|
|
378
|
+
const lostBefore = new Set(await this.inner.lostKeys());
|
|
379
|
+
await this.inner.archive(facts);
|
|
380
|
+
if (facts.some((f) => lostBefore.has(f.key))) await this.snapshot();
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async lostKeys(): Promise<string[]> {
|
|
384
|
+
await this.ensureFresh();
|
|
385
|
+
return this.inner.lostKeys();
|
|
386
|
+
}
|
|
387
|
+
|
|
276
388
|
private async snapshot(): Promise<void> {
|
|
277
389
|
const entries = await this.store.recallAll();
|
|
390
|
+
const rows = this.inner.archivedRows();
|
|
278
391
|
const out: SnapshotEntry[] = entries.map((e) => ({
|
|
279
392
|
key: e.key,
|
|
280
393
|
content: e.content,
|
|
281
394
|
tags: e.tags,
|
|
282
395
|
importance: e.importance,
|
|
396
|
+
timestamp: e.timestamp,
|
|
397
|
+
...(isContentLost(e.content, rows[e.key]) ? { contentLost: true as const } : {}),
|
|
283
398
|
}));
|
|
284
399
|
this.file.write(JSON.stringify(out, null, 2));
|
|
285
400
|
}
|
|
@@ -321,9 +436,9 @@ export async function createLocalMemoryStoreBackend(opts: LocalBackendOptions =
|
|
|
321
436
|
}
|
|
322
437
|
|
|
323
438
|
const store = new MemoryStore({ idbFactory, dbName: opts.dbName, maxEntries });
|
|
324
|
-
const
|
|
439
|
+
const log = opts.log ?? ((line: string) => void globalThis.process?.stderr?.write(`${line}\n`));
|
|
325
440
|
|
|
326
|
-
if (!opts.persistFile) return
|
|
441
|
+
if (!opts.persistFile) return new MemoryStoreBackend(store, runtime, { ranking: opts.ranking });
|
|
327
442
|
|
|
328
443
|
// Disk-mirror requested. node:fs/path are loaded indirectly so a browser
|
|
329
444
|
// bundle of this module never statically pulls in Node builtins.
|
|
@@ -332,8 +447,23 @@ export async function createLocalMemoryStoreBackend(opts: LocalBackendOptions =
|
|
|
332
447
|
const dir = path.dirname(opts.persistFile);
|
|
333
448
|
if (dir && !fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
334
449
|
|
|
450
|
+
// The archive sits beside the snapshot, OUTSIDE it: it must survive the snapshot
|
|
451
|
+
// being rebuilt, rewritten by another process, or capped — see fact-archive.ts.
|
|
452
|
+
const archive = new FileFactArchive(opts.archiveFile ?? defaultArchiveFile(opts.persistFile), fs);
|
|
453
|
+
const backend = new MemoryStoreBackend(store, runtime, { archive, ranking: opts.ranking });
|
|
335
454
|
const persisted = new DiskPersistedBackend(backend, store, new SharedJsonFile(opts.persistFile, fs));
|
|
336
455
|
// Boot hydration IS the freshness check with no stamp yet — see ensureFresh().
|
|
337
456
|
await persisted.ensureFresh();
|
|
457
|
+
|
|
458
|
+
// Facts compacted before archiving existed are stubs whose text is gone. Every
|
|
459
|
+
// read flags them `contentLost` (and so does the next snapshot); say so once at
|
|
460
|
+
// boot so the loss is visible, with the way back.
|
|
461
|
+
const lost = await persisted.lostKeys();
|
|
462
|
+
if (lost.length > 0) {
|
|
463
|
+
log(
|
|
464
|
+
`[builderforce-memory] ${lost.length} memory(ies) are compaction stubs with no archived original ` +
|
|
465
|
+
`(content lost — re-verify before relying on them). Recover the text with memory_restore.`,
|
|
466
|
+
);
|
|
467
|
+
}
|
|
338
468
|
return persisted;
|
|
339
469
|
}
|
package/src/bin/http.ts
CHANGED
|
@@ -24,9 +24,12 @@ import { createLocalMemoryStoreBackend } from "../backends/memory-store.js";
|
|
|
24
24
|
import { createRecallEmbedder } from "../embedding/index.js";
|
|
25
25
|
import { createExperienceHost } from "../experience/host.js";
|
|
26
26
|
import { resolveMemoryFile } from "../install/server-spec.js";
|
|
27
|
+
import { lazyRecallProbe } from "../model/recall-probe.js";
|
|
27
28
|
import { createMemoryHttpHandler } from "../transports/http.js";
|
|
28
29
|
|
|
29
|
-
const memoryFile = resolveMemoryFile(
|
|
30
|
+
const memoryFile = resolveMemoryFile(process.env, undefined, {
|
|
31
|
+
log: (line) => void process.stderr.write(`${line}\n`),
|
|
32
|
+
});
|
|
30
33
|
|
|
31
34
|
const backend = await createLocalMemoryStoreBackend({
|
|
32
35
|
dbName: process.env["BUILDERFORCE_MEMORY_DB"],
|
|
@@ -46,6 +49,9 @@ const handler = createMemoryHttpHandler(backend, {
|
|
|
46
49
|
gatewayUrl: process.env["BUILDERFORCE_GATEWAY_URL"] ?? "https://api.builderforce.ai",
|
|
47
50
|
gatewayApiKey: process.env["BUILDERFORCE_API_KEY"],
|
|
48
51
|
experience: await createExperienceHost({ memoryFile }),
|
|
52
|
+
recallProbe: lazyRecallProbe(),
|
|
53
|
+
// No readRestoreFile: a networked server never reads a caller-named path —
|
|
54
|
+
// memory_restore takes the export inline.
|
|
49
55
|
});
|
|
50
56
|
|
|
51
57
|
if (process.env["BUILDERFORCE_MEMORY_EXPERIENCE"] === "1" && !process.env["BUILDERFORCE_MEMORY_TOKEN"]) {
|
package/src/bin/install.ts
CHANGED
|
@@ -22,7 +22,7 @@ import nodeFs from "node:fs";
|
|
|
22
22
|
import { HOSTS } from "../install/hosts.js";
|
|
23
23
|
import { installMemoryServer, type HostSelector } from "../install/install.js";
|
|
24
24
|
import { installClaudeCombo } from "../install/claude-hooks.js";
|
|
25
|
-
import {
|
|
25
|
+
import { resolveMemoryFile } from "../install/server-spec.js";
|
|
26
26
|
|
|
27
27
|
function argValue(name: string): string | undefined {
|
|
28
28
|
const hit = process.argv.find((a) => a.startsWith(`--${name}=`));
|
|
@@ -55,7 +55,11 @@ const hosts: HostSelector =
|
|
|
55
55
|
? "all"
|
|
56
56
|
: hostArg.split(",").map((s) => s.trim()).filter(Boolean);
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
// The SAME resolver the servers and the hook use — so an install on a machine whose
|
|
59
|
+
// live store sits at a legacy location bakes THAT path, not an empty new one.
|
|
60
|
+
const memoryFile =
|
|
61
|
+
argValue("memory-file") ??
|
|
62
|
+
resolveMemoryFile(process.env, undefined, { log: (line) => process.stderr.write(`${line}\n`) });
|
|
59
63
|
|
|
60
64
|
let results;
|
|
61
65
|
try {
|
|
@@ -112,6 +116,6 @@ if (results.length === 0) {
|
|
|
112
116
|
);
|
|
113
117
|
} else {
|
|
114
118
|
process.stdout.write(
|
|
115
|
-
`\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`,
|
|
119
|
+
`\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 · memory_restore\n`,
|
|
116
120
|
);
|
|
117
121
|
}
|
package/src/bin/stdio.ts
CHANGED
|
@@ -6,15 +6,20 @@
|
|
|
6
6
|
* BUILDERFORCE_MEMORY_DB IndexedDB database name (default: MemoryStore default).
|
|
7
7
|
* BUILDERFORCE_MEMORY_READONLY '1' to disable remember/forget tools.
|
|
8
8
|
* BUILDERFORCE_MEMORY_FILE Absolute path to a JSON snapshot. Defaults to the
|
|
9
|
-
* shared per-machine store (
|
|
10
|
-
* memory.json
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* shared per-machine store — resolveMemoryFile():
|
|
10
|
+
* ~/.builderforce-memory/memory.json, or the legacy
|
|
11
|
+
* ~/.claude/builderforce-memory/memory.json when that
|
|
12
|
+
* is where the live memory.json is — so memory
|
|
13
|
+
* survives the respawn every MCP client does between
|
|
14
|
+
* sessions. Compacted originals are archived beside it
|
|
15
|
+
* (memory.archive.json); each overwrite keeps .bak.1-3.
|
|
13
16
|
* BUILDERFORCE_MEMORY_MODEL Absolute path to a `.evermind` package (an
|
|
14
17
|
* `evermind-lm`). When set, recall is ranked by SSM
|
|
15
18
|
* embedding cosine FUSED with the lexical ranking
|
|
16
19
|
* instead of lexically alone. Pure CPU — no GPU is
|
|
17
20
|
* involved; see src/embedding/evermind-embedder.ts.
|
|
21
|
+
* Also the model memory_compact's recall probe asks
|
|
22
|
+
* before stubbing a fact; unset = nothing is compacted.
|
|
18
23
|
* BUILDERFORCE_MEMORY_TOKENIZER Tokenizer JSON matching that checkpoint. Defaults
|
|
19
24
|
* to `<model>.tokenizer.json`.
|
|
20
25
|
* BUILDERFORCE_MEMORY_VECTORS Persistent vector-cache path. Defaults beside the
|
|
@@ -34,11 +39,16 @@
|
|
|
34
39
|
|
|
35
40
|
import { createLocalMemoryStoreBackend } from "../backends/memory-store.js";
|
|
36
41
|
import { createRecallEmbedder } from "../embedding/index.js";
|
|
42
|
+
import { readFile } from "node:fs/promises";
|
|
37
43
|
import { createExperienceHost } from "../experience/host.js";
|
|
38
44
|
import { resolveMemoryFile } from "../install/server-spec.js";
|
|
45
|
+
import { lazyRecallProbe } from "../model/recall-probe.js";
|
|
39
46
|
import { runStdio } from "../transports/stdio.js";
|
|
40
47
|
|
|
41
|
-
const
|
|
48
|
+
const log = (line: string) => void process.stderr.write(`${line}\n`);
|
|
49
|
+
// ONE resolver for installer, servers and hook: env, else whichever location holds
|
|
50
|
+
// the live memory.json (logged when there is a choice), else the canonical default.
|
|
51
|
+
const memoryFile = resolveMemoryFile(process.env, undefined, { log });
|
|
42
52
|
|
|
43
53
|
const backend = await createLocalMemoryStoreBackend({
|
|
44
54
|
dbName: process.env["BUILDERFORCE_MEMORY_DB"],
|
|
@@ -56,4 +66,9 @@ await runStdio(backend, {
|
|
|
56
66
|
gatewayApiKey: process.env["BUILDERFORCE_API_KEY"],
|
|
57
67
|
// Null unless BUILDERFORCE_MEMORY_EXPERIENCE=1 — Synapse's opt-in.
|
|
58
68
|
experience: await createExperienceHost({ memoryFile }),
|
|
69
|
+
// memory_compact proves absorption with the configured Evermind before stubbing;
|
|
70
|
+
// no model → nothing is compacted (and the tool says so).
|
|
71
|
+
recallProbe: lazyRecallProbe(),
|
|
72
|
+
// A local subprocess may read the user's own export file for memory_restore.
|
|
73
|
+
readRestoreFile: (path) => readFile(path, "utf8"),
|
|
59
74
|
});
|