@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/index.d.ts
CHANGED
|
@@ -9,16 +9,23 @@
|
|
|
9
9
|
export type { MemoryBackend, RankedRecall, RecallHit, RecallMethod, RememberInput } from "./backend.js";
|
|
10
10
|
export { createRecallEmbedder, createEvermindEmbedder, CachedTextEmbedder, defaultVectorCacheFile, MODEL_FILE_ENV, TOKENIZER_FILE_ENV, VECTOR_CACHE_ENV } from "./embedding/index.js";
|
|
11
11
|
export type { EvermindEmbedderOptions, PersistentTextEmbedder, TextEmbedderLike, RecallEmbedderEnv } from "./embedding/index.js";
|
|
12
|
-
export { MemoryStoreBackend, createLocalMemoryStoreBackend } from "./backends/memory-store.js";
|
|
13
|
-
export type { LocalBackendOptions } from "./backends/memory-store.js";
|
|
12
|
+
export { MemoryStoreBackend, createLocalMemoryStoreBackend, DEFAULT_RECALL_RANKING } from "./backends/memory-store.js";
|
|
13
|
+
export type { LocalBackendOptions, MemoryStoreBackendOptions, RecallRanking } from "./backends/memory-store.js";
|
|
14
|
+
export { FileFactArchive, MemoryFactArchive } from "./persistence/fact-archive.js";
|
|
15
|
+
export type { FactArchive } from "./persistence/fact-archive.js";
|
|
16
|
+
export { SharedJsonFile, DEFAULT_BACKUPS, backupFile } from "./persistence/shared-json-file.js";
|
|
17
|
+
export type { SharedJsonFileOptions } from "./persistence/shared-json-file.js";
|
|
14
18
|
export { buildMemoryTools } from "./tools.js";
|
|
15
19
|
export type { MemoryToolsOptions } from "./tools.js";
|
|
16
20
|
export type { MemoryTool, ToolResult } from "./tool-core.js";
|
|
17
21
|
export { createExperienceHost, EXPERIENCE_ENV } from "./experience/host.js";
|
|
18
22
|
export type { ExperienceHost, ExperienceHostOptions, ExperienceEngine } from "./experience/host.js";
|
|
19
23
|
export { nextExperienceVersion } from "./experience/train.js";
|
|
20
|
-
export { STUB_PREFIX, DEFAULT_STUB_CHARS, isStub, firstLine, memoryStub, planCompaction } from "./compaction.js";
|
|
21
|
-
export type { CompactionCandidate, CompactionWrite, CompactionSkip, CompactionPlan, CompactionOptions } from "./compaction.js";
|
|
24
|
+
export { STUB_PREFIX, DEFAULT_STUB_CHARS, CONTENT_LOST_LABEL, isStub, isContentLost, firstLine, memoryStub, stubPointer, planCompaction, planLosslessCompaction, probeQuestionFor, probePasses, defaultArchiveFile, parseArchive, mergeArchive, } from "./compaction.js";
|
|
25
|
+
export type { ArchivedFact, ArchiveSnapshot, CompactionCandidate, CompactionWrite, CompactionSkip, CompactionPlan, CompactionOptions, LosslessCompactionOptions, ProbeQuestion, RecallProbe, } from "./compaction.js";
|
|
26
|
+
export { createRecallProbe, lazyRecallProbe, generatorProbe, PROBE_MAX_NEW_TOKENS } from "./model/recall-probe.js";
|
|
27
|
+
export { parseRestoreSource, planRestore, restoredArchive, stubVersion, MIN_POINTER_CHARS } from "./restore.js";
|
|
28
|
+
export type { RestoreRecord, RestoreTarget, RestoreMatch, RestorePlan } from "./restore.js";
|
|
22
29
|
export { createMemoryMcpServer } from "./transports/sdk.js";
|
|
23
30
|
export type { SdkServerOptions, SdkMcpServerConfig } from "./transports/sdk.js";
|
|
24
31
|
export { buildMcpServer } from "./transports/mcp-server.js";
|
|
@@ -27,8 +34,8 @@ export { runStdio } from "./transports/stdio.js";
|
|
|
27
34
|
export { createMemoryHttpHandler } from "./transports/http.js";
|
|
28
35
|
export type { HttpHandlerOptions } from "./transports/http.js";
|
|
29
36
|
export { hashToken, timingSafeEqualStr, buildTenantIndex, bearerToken, RateLimiter } from "./transports/auth.js";
|
|
30
|
-
export { buildServerSpec, defaultMemoryFile, resolveMemoryFile, MCP_PACKAGE, MCP_BIN, MEMORY_FILE_ENV, RUNTIME_PEERS } from "./install/server-spec.js";
|
|
31
|
-
export type { StdioServerSpec, ServerSpecOptions } from "./install/server-spec.js";
|
|
37
|
+
export { buildServerSpec, defaultMemoryFile, memoryFileCandidates, resolveMemoryFile, CANONICAL_MEMORY_SEGMENTS, LEGACY_MEMORY_SEGMENTS, MCP_PACKAGE, MCP_BIN, MEMORY_FILE_ENV, RUNTIME_PEERS, } from "./install/server-spec.js";
|
|
38
|
+
export type { StdioServerSpec, ServerSpecOptions, MemoryFileProbe, ResolveMemoryFileOptions } from "./install/server-spec.js";
|
|
32
39
|
export { installMemoryServer } from "./install/install.js";
|
|
33
40
|
export type { InstallOptions, InstallResult, InstallStatus, HostSelector, FsLike } from "./install/install.js";
|
|
34
41
|
export { HOSTS, SERVER_KEY, findHost } from "./install/hosts.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAMxG,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACtL,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGjI,OAAO,EAAE,kBAAkB,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -12,18 +12,22 @@
|
|
|
12
12
|
// host can build the same embedder (and share its persistent vector cache).
|
|
13
13
|
export { createRecallEmbedder, createEvermindEmbedder, CachedTextEmbedder, defaultVectorCacheFile, MODEL_FILE_ENV, TOKENIZER_FILE_ENV, VECTOR_CACHE_ENV } from "./embedding/index.js";
|
|
14
14
|
// ── Local backend (IndexedDB via @seanhogg/builderforce-memory) ────────────────────────
|
|
15
|
-
export { MemoryStoreBackend, createLocalMemoryStoreBackend } from "./backends/memory-store.js";
|
|
15
|
+
export { MemoryStoreBackend, createLocalMemoryStoreBackend, DEFAULT_RECALL_RANKING } from "./backends/memory-store.js";
|
|
16
|
+
export { FileFactArchive, MemoryFactArchive } from "./persistence/fact-archive.js";
|
|
17
|
+
export { SharedJsonFile, DEFAULT_BACKUPS, backupFile } from "./persistence/shared-json-file.js";
|
|
16
18
|
// ── Tool core ─────────────────────────────────────────────────────────────────
|
|
17
19
|
export { buildMemoryTools } from "./tools.js";
|
|
18
20
|
// ── Experience (demonstrations → Train Once skills → runs → the private model) ─
|
|
19
21
|
// The domain is the engine's; this is its durable host and its tools.
|
|
20
22
|
export { createExperienceHost, EXPERIENCE_ENV } from "./experience/host.js";
|
|
21
23
|
export { nextExperienceVersion } from "./experience/train.js";
|
|
22
|
-
// ── Compaction (absorbed fact → one-line pointer stub)
|
|
23
|
-
// Exported so an EXTERNAL compactor (the BuilderForce VS Code extension
|
|
24
|
-
//
|
|
25
|
-
// paths idempotent with respect to each other.
|
|
26
|
-
export { STUB_PREFIX, DEFAULT_STUB_CHARS, isStub, firstLine, memoryStub, planCompaction } from "./compaction.js";
|
|
24
|
+
// ── Compaction (absorbed fact → one-line pointer stub, LOSSLESS) ─────────────
|
|
25
|
+
// Exported so an EXTERNAL compactor (the BuilderForce VS Code extension) produces
|
|
26
|
+
// byte-identical stubs AND follows the same archive + recall-probe rules, keeping
|
|
27
|
+
// the two paths idempotent with respect to each other.
|
|
28
|
+
export { STUB_PREFIX, DEFAULT_STUB_CHARS, CONTENT_LOST_LABEL, isStub, isContentLost, firstLine, memoryStub, stubPointer, planCompaction, planLosslessCompaction, probeQuestionFor, probePasses, defaultArchiveFile, parseArchive, mergeArchive, } from "./compaction.js";
|
|
29
|
+
export { createRecallProbe, lazyRecallProbe, generatorProbe, PROBE_MAX_NEW_TOKENS } from "./model/recall-probe.js";
|
|
30
|
+
export { parseRestoreSource, planRestore, restoredArchive, stubVersion, MIN_POINTER_CHARS } from "./restore.js";
|
|
27
31
|
// ── Transports ──────────────────────────────────────────────────────────────
|
|
28
32
|
export { createMemoryMcpServer } from "./transports/sdk.js";
|
|
29
33
|
export { buildMcpServer } from "./transports/mcp-server.js";
|
|
@@ -31,7 +35,7 @@ export { runStdio } from "./transports/stdio.js";
|
|
|
31
35
|
export { createMemoryHttpHandler } from "./transports/http.js";
|
|
32
36
|
export { hashToken, timingSafeEqualStr, buildTenantIndex, bearerToken, RateLimiter } from "./transports/auth.js";
|
|
33
37
|
// ── Multi-host installer (wire the stdio server into any MCP-capable agent) ───
|
|
34
|
-
export { buildServerSpec, defaultMemoryFile, resolveMemoryFile, MCP_PACKAGE, MCP_BIN, MEMORY_FILE_ENV, RUNTIME_PEERS } from "./install/server-spec.js";
|
|
38
|
+
export { buildServerSpec, defaultMemoryFile, memoryFileCandidates, resolveMemoryFile, CANONICAL_MEMORY_SEGMENTS, LEGACY_MEMORY_SEGMENTS, MCP_PACKAGE, MCP_BIN, MEMORY_FILE_ENV, RUNTIME_PEERS, } from "./install/server-spec.js";
|
|
35
39
|
export { installMemoryServer } from "./install/install.js";
|
|
36
40
|
export { HOSTS, SERVER_KEY, findHost } from "./install/hosts.js";
|
|
37
41
|
// Claude Code "memory combo" — hooks (SessionStart/PreCompact/UserPromptSubmit/Stop)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,8EAA8E;AAC9E,iFAAiF;AACjF,gFAAgF;AAChF,4EAA4E;AAC5E,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGtL,0FAA0F;AAC1F,OAAO,EAAE,kBAAkB,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,8EAA8E;AAC9E,iFAAiF;AACjF,gFAAgF;AAChF,4EAA4E;AAC5E,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGtL,0FAA0F;AAC1F,OAAO,EAAE,kBAAkB,EAAE,6BAA6B,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEvH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAEnF,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAGhG,iFAAiF;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAI9C,kFAAkF;AAClF,sEAAsE;AACtE,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,gFAAgF;AAChF,kFAAkF;AAClF,kFAAkF;AAClF,uDAAuD;AACvD,OAAO,EACH,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,MAAM,EACN,aAAa,EACb,SAAS,EACT,UAAU,EACV,WAAW,EACX,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,YAAY,GACf,MAAM,iBAAiB,CAAC;AAazB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACnH,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGhH,+EAA+E;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG5D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEjH,iFAAiF;AACjF,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,yBAAyB,EACzB,sBAAsB,EACtB,WAAW,EACX,OAAO,EACP,eAAe,EACf,aAAa,GAChB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEjE,qFAAqF;AACrF,4FAA4F;AAC5F,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -28,6 +28,11 @@ import type { FsLike } from "./install.js";
|
|
|
28
28
|
* Code plugin, whose files are static and machine-independent. The runtime
|
|
29
29
|
* branch must stay in lockstep with `resolveMemoryFile`; `install.test.mjs`
|
|
30
30
|
* asserts it does.
|
|
31
|
+
*
|
|
32
|
+
* Compaction stubs whose original was never archived (`contentLost`) are still
|
|
33
|
+
* injected — the pointer is a real lead — but labelled
|
|
34
|
+
* {@link CONTENT_LOST_LABEL} and importance-demoted, so they rank below intact
|
|
35
|
+
* memories and are never presented as verified fact.
|
|
31
36
|
*/
|
|
32
37
|
export declare function bfmemHookSource(memoryFile: string | null): string;
|
|
33
38
|
/** The companion skill doc that teaches the recall/remember discipline. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-hooks.d.ts","sourceRoot":"","sources":["../../src/install/claude-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;
|
|
1
|
+
{"version":3,"file":"claude-hooks.d.ts","sourceRoot":"","sources":["../../src/install/claude-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AA2B3C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CA2NjE;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,IAAI,MAAM,CAiCzC;AAED,qFAAqF;AACrF,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAOpE;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;EAKd,CAAC;AAEX,qFAAqF;AACrF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAAC,CAAC;AAEvG;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,aAAa,SAAyB,GAAG,UAAU,CAQpF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACtB,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAmDrE"}
|
|
@@ -20,7 +20,29 @@
|
|
|
20
20
|
* is idempotent and backup-safe, matching install.ts.
|
|
21
21
|
*/
|
|
22
22
|
import nodePath from "node:path";
|
|
23
|
-
import {
|
|
23
|
+
import { CONTENT_LOST_LABEL, STUB_PREFIX } from "../compaction.js";
|
|
24
|
+
import { CANONICAL_MEMORY_SEGMENTS, LEGACY_MEMORY_SEGMENTS, MEMORY_FILE_ENV } from "./server-spec.js";
|
|
25
|
+
/** `path.join(os.homedir(), "<seg>", …)` as hook-script source. */
|
|
26
|
+
const homeJoin = (segments) => `path.join(os.homedir(), ${segments.map((s) => JSON.stringify(s)).join(", ")})`;
|
|
27
|
+
/**
|
|
28
|
+
* The run-time twin of `resolveMemoryFile`, as hook-script source: the env
|
|
29
|
+
* override, else whichever candidate holds a memory.json (the most recently
|
|
30
|
+
* written when both do), else the canonical default. Built from the SAME segment
|
|
31
|
+
* constants, so the two cannot name different files.
|
|
32
|
+
*/
|
|
33
|
+
function runtimeMemoryFileExpr() {
|
|
34
|
+
return `(() => {
|
|
35
|
+
const explicit = process.env[${JSON.stringify(MEMORY_FILE_ENV)}];
|
|
36
|
+
if (explicit) return explicit;
|
|
37
|
+
const candidates = [${homeJoin(CANONICAL_MEMORY_SEGMENTS)}, ${homeJoin(LEGACY_MEMORY_SEGMENTS)}];
|
|
38
|
+
let best = null, bestMtime = -Infinity;
|
|
39
|
+
for (const c of candidates) {
|
|
40
|
+
try { const st = fs.statSync(c); if (st.isFile() && st.mtimeMs > bestMtime) { best = c; bestMtime = st.mtimeMs; } }
|
|
41
|
+
catch { /* absent */ }
|
|
42
|
+
}
|
|
43
|
+
return best || candidates[0];
|
|
44
|
+
})()`;
|
|
45
|
+
}
|
|
24
46
|
/**
|
|
25
47
|
* The single hook script, four modes.
|
|
26
48
|
*
|
|
@@ -29,11 +51,14 @@ import { MEMORY_FILE_ENV } from "./server-spec.js";
|
|
|
29
51
|
* Code plugin, whose files are static and machine-independent. The runtime
|
|
30
52
|
* branch must stay in lockstep with `resolveMemoryFile`; `install.test.mjs`
|
|
31
53
|
* asserts it does.
|
|
54
|
+
*
|
|
55
|
+
* Compaction stubs whose original was never archived (`contentLost`) are still
|
|
56
|
+
* injected — the pointer is a real lead — but labelled
|
|
57
|
+
* {@link CONTENT_LOST_LABEL} and importance-demoted, so they rank below intact
|
|
58
|
+
* memories and are never presented as verified fact.
|
|
32
59
|
*/
|
|
33
60
|
export function bfmemHookSource(memoryFile) {
|
|
34
|
-
const fileExpr = memoryFile === null
|
|
35
|
-
? `process.env[${JSON.stringify(MEMORY_FILE_ENV)}] || path.join(os.homedir(), ".builderforce-memory", "memory.json")`
|
|
36
|
-
: JSON.stringify(memoryFile);
|
|
61
|
+
const fileExpr = memoryFile === null ? runtimeMemoryFileExpr() : JSON.stringify(memoryFile);
|
|
37
62
|
return `#!/usr/bin/env node
|
|
38
63
|
/**
|
|
39
64
|
* builderforce-memory hook — generated by builderforce-memory-install. Dependency-free:
|
|
@@ -58,6 +83,29 @@ function loadEntries() {
|
|
|
58
83
|
try { const p = JSON.parse(fs.readFileSync(FILE, "utf8")); return Array.isArray(p) ? p : []; }
|
|
59
84
|
catch { return []; }
|
|
60
85
|
}
|
|
86
|
+
|
|
87
|
+
// ── Compaction stubs ─────────────────────────────────────────────────────────
|
|
88
|
+
// A compacted memory's full original lives in the archive beside the snapshot
|
|
89
|
+
// (memory.json → memory.archive.json). A stub with NO archived original is lost
|
|
90
|
+
// content: still injected (the pointer is a real lead) but labelled and demoted.
|
|
91
|
+
const ARCHIVE = FILE.replace(/\\.json$/i, "") + ".archive.json";
|
|
92
|
+
const STUB_PREFIX = ${JSON.stringify(STUB_PREFIX)};
|
|
93
|
+
const LOST_LABEL = ${JSON.stringify(CONTENT_LOST_LABEL)};
|
|
94
|
+
const LOST_DEMOTION = 0.5;
|
|
95
|
+
let archivedKeys = null;
|
|
96
|
+
function archived() {
|
|
97
|
+
if (archivedKeys) return archivedKeys;
|
|
98
|
+
try { const a = JSON.parse(fs.readFileSync(ARCHIVE, "utf8")); archivedKeys = new Set(Object.keys((a && a.facts) || {})); }
|
|
99
|
+
catch { archivedKeys = new Set(); }
|
|
100
|
+
return archivedKeys;
|
|
101
|
+
}
|
|
102
|
+
function isLost(e) {
|
|
103
|
+
// The archive decides (a snapshot's contentLost flag can trail a restore).
|
|
104
|
+
return String(e.content || "").trimStart().startsWith(STUB_PREFIX) && !archived().has(e.key);
|
|
105
|
+
}
|
|
106
|
+
function render(e, max) {
|
|
107
|
+
return "• " + e.key + ": " + String(e.content || "").slice(0, max) + (isLost(e) ? " " + LOST_LABEL : "");
|
|
108
|
+
}
|
|
61
109
|
function tokens(s) {
|
|
62
110
|
return String(s || "").toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 3);
|
|
63
111
|
}
|
|
@@ -108,16 +156,17 @@ if (mode === "--recall") {
|
|
|
108
156
|
const hay = new Set(tokens([e.key, e.content, (e.tags || []).join(" ")].join(" ")));
|
|
109
157
|
let score = 0;
|
|
110
158
|
for (const t of q) if (hay.has(t)) score++;
|
|
111
|
-
|
|
159
|
+
// Lost content still qualifies on overlap, but ranks below intact memories.
|
|
160
|
+
return { e, score, rank: isLost(e) ? score * LOST_DEMOTION : score };
|
|
112
161
|
})
|
|
113
162
|
.filter((x) => x.score >= 2)
|
|
114
163
|
.filter((x) => !led.has(x.e.key)) // already surfaced this session → don't re-inject
|
|
115
|
-
.sort((a, b) => b.
|
|
164
|
+
.sort((a, b) => b.rank - a.rank)
|
|
116
165
|
.slice(0, 3);
|
|
117
166
|
if (scored.length === 0) process.exit(0);
|
|
118
167
|
for (const x of scored) led.add(x.e.key);
|
|
119
168
|
saveLedger(sid, led);
|
|
120
|
-
const lines = scored.map((x) =>
|
|
169
|
+
const lines = scored.map((x) => render(x.e, 200)).join("\\n");
|
|
121
170
|
process.stdout.write(
|
|
122
171
|
"[builderforce-memory] Relevant stored memories for this request — use these instead of re-deriving or re-reading:\\n" + lines,
|
|
123
172
|
);
|
|
@@ -207,7 +256,11 @@ if (entries.length === 0) {
|
|
|
207
256
|
process.exit(0);
|
|
208
257
|
}
|
|
209
258
|
const ranked = entries
|
|
210
|
-
.map((e) =>
|
|
259
|
+
.map((e) => {
|
|
260
|
+
const importance = typeof e.importance === "number" ? e.importance : 0.5;
|
|
261
|
+
// Lost content is importance-demoted so intact memories lead the digest.
|
|
262
|
+
return { key: e.key, content: String(e.content ?? ""), importance: isLost(e) ? importance * LOST_DEMOTION : importance };
|
|
263
|
+
})
|
|
211
264
|
.sort((a, b) => b.importance - a.importance)
|
|
212
265
|
.slice(0, 6);
|
|
213
266
|
|
|
@@ -218,7 +271,7 @@ for (const e of ranked) led.add(e.key);
|
|
|
218
271
|
saveLedger(sessionId, led);
|
|
219
272
|
|
|
220
273
|
if (src === "resume") process.exit(0); // context retained across resume — nothing to re-inject
|
|
221
|
-
const top = ranked.map((e) =>
|
|
274
|
+
const top = ranked.map((e) => render(e, 180)).join("\\n");
|
|
222
275
|
process.stdout.write(
|
|
223
276
|
"[builderforce-memory] Active — token-saving memory loaded. Before re-reading files or history, call memory_recall. Store durable facts with memory_remember.\\nTop memories:\\n" + top,
|
|
224
277
|
);
|
|
@@ -245,6 +298,13 @@ capture that won't let a durable correction go unrecorded.
|
|
|
245
298
|
- \`memory_recall_by_tag(tag)\` — everything under a tag.
|
|
246
299
|
- \`memory_remember(key, content, [tags], [importance])\` — store ONE durable fact.
|
|
247
300
|
- \`memory_forget(key)\` — drop a superseded fact.
|
|
301
|
+
- \`memory_compact(keys)\` — stub facts the local Evermind has absorbed (proven by a
|
|
302
|
+
recall probe; the original is archived, so recall still returns it).
|
|
303
|
+
- \`memory_restore(file|json)\` — bring back the text of memories marked
|
|
304
|
+
"${CONTENT_LOST_LABEL}" from an export.
|
|
305
|
+
|
|
306
|
+
A memory labelled "${CONTENT_LOST_LABEL}" is a one-line pointer whose full
|
|
307
|
+
text is gone: treat it as a lead, verify it before acting on it.
|
|
248
308
|
|
|
249
309
|
## Discipline
|
|
250
310
|
Reuse a stable key to REPLACE a fact (write-through), don't append duplicates.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-hooks.js","sourceRoot":"","sources":["../../src/install/claude-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,QAAQ,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-hooks.js","sourceRoot":"","sources":["../../src/install/claude-hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,17 +12,43 @@ export interface StdioServerSpec {
|
|
|
12
12
|
env?: Record<string, string>;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* The
|
|
16
|
-
* (Claude Code, Cursor, Claude Desktop, …) shares the same memory.
|
|
15
|
+
* The snapshot path override every reader and writer honours first.
|
|
17
16
|
*
|
|
18
|
-
*
|
|
19
|
-
* Claude Code
|
|
20
|
-
*
|
|
17
|
+
* ONE resolver ({@link resolveMemoryFile}) serves the installer, both server bins
|
|
18
|
+
* and the Claude Code hook script (which inlines the same rules — see
|
|
19
|
+
* `bfmemHookSource`) — a memory file the writer and the reader disagree about is
|
|
20
|
+
* memory that silently disappears.
|
|
21
21
|
*/
|
|
22
22
|
export declare const MEMORY_FILE_ENV = "BUILDERFORCE_MEMORY_FILE";
|
|
23
|
+
/** The canonical per-machine store, relative to the home directory. */
|
|
24
|
+
export declare const CANONICAL_MEMORY_SEGMENTS: readonly [".builderforce-memory", "memory.json"];
|
|
25
|
+
/**
|
|
26
|
+
* Where earlier installers put the store (`~/.claude/builderforce-memory/memory.json`).
|
|
27
|
+
* Still honoured: a machine whose live memory sits here keeps using it.
|
|
28
|
+
*/
|
|
29
|
+
export declare const LEGACY_MEMORY_SEGMENTS: readonly [".claude", "builderforce-memory", "memory.json"];
|
|
30
|
+
/** The default JSON snapshot path: ONE store per machine, shared by every MCP host. */
|
|
23
31
|
export declare function defaultMemoryFile(homedir?: string): string;
|
|
24
|
-
/**
|
|
25
|
-
export declare function
|
|
32
|
+
/** Every location a store may live in, canonical first. */
|
|
33
|
+
export declare function memoryFileCandidates(homedir?: string): string[];
|
|
34
|
+
/** File probe the resolver uses — injectable for tests. */
|
|
35
|
+
export interface MemoryFileProbe {
|
|
36
|
+
/** Unix-ms modification time of `path` when it is a file, else null. */
|
|
37
|
+
fileMtime(path: string): number | null;
|
|
38
|
+
}
|
|
39
|
+
export interface ResolveMemoryFileOptions {
|
|
40
|
+
probe?: MemoryFileProbe;
|
|
41
|
+
/** Told which store won when more than one location is in play. Default: silent. */
|
|
42
|
+
log?: (line: string) => void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The snapshot path in effect:
|
|
46
|
+
* 1. `BUILDERFORCE_MEMORY_FILE`, when set;
|
|
47
|
+
* 2. else whichever candidate location actually holds a `memory.json` — the
|
|
48
|
+
* most recently written one if both do (logged; neither is ever deleted);
|
|
49
|
+
* 3. else the canonical default.
|
|
50
|
+
*/
|
|
51
|
+
export declare function resolveMemoryFile(env?: Record<string, string | undefined>, homedir?: string, opts?: ResolveMemoryFileOptions): string;
|
|
26
52
|
export interface ServerSpecOptions {
|
|
27
53
|
/** Absolute path to the JSON snapshot that makes memory survive restarts. */
|
|
28
54
|
memoryFile?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-spec.d.ts","sourceRoot":"","sources":["../../src/install/server-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"server-spec.d.ts","sourceRoot":"","sources":["../../src/install/server-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,6BAA6B,CAAC;AAE1D,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,kDAAmD,CAAC;AAE1F;;;GAGG;AACH,eAAO,MAAM,sBAAsB,4DAA6D,CAAC;AAEjG,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,MAAyB,GAAG,MAAM,CAE5E;AAED,2DAA2D;AAC3D,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,MAAyB,GAAG,MAAM,EAAE,CAEjF;AAED,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC5B,wEAAwE;IACxE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAC1C;AAaD,MAAM,WAAW,wBAAwB;IACrC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,oFAAoF;IACpF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC7B,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,EACrD,OAAO,CAAC,EAAE,MAAM,EAChB,IAAI,GAAE,wBAA6B,GACpC,MAAM,CAsBR;AAED,MAAM,WAAW,iBAAiB;IAC9B,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,+EAA+E;AAC/E,eAAO,MAAM,WAAW,sCAAsC,CAAC;AAC/D,eAAO,MAAM,OAAO,4BAA4B,CAAC;AAEjD;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,UAIzB,CAAC;AASF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,iBAAsB,GAAG,eAAe,CAc7E"}
|
|
@@ -6,23 +6,73 @@
|
|
|
6
6
|
* file/shape differs. This module is the single source of truth for HOW the
|
|
7
7
|
* server is launched, so the per-host adapters never re-derive the command.
|
|
8
8
|
*/
|
|
9
|
+
import nodeFs from "node:fs";
|
|
9
10
|
import nodeOs from "node:os";
|
|
10
11
|
import nodePath from "node:path";
|
|
11
12
|
/**
|
|
12
|
-
* The
|
|
13
|
-
* (Claude Code, Cursor, Claude Desktop, …) shares the same memory.
|
|
13
|
+
* The snapshot path override every reader and writer honours first.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
* Claude Code
|
|
17
|
-
*
|
|
15
|
+
* ONE resolver ({@link resolveMemoryFile}) serves the installer, both server bins
|
|
16
|
+
* and the Claude Code hook script (which inlines the same rules — see
|
|
17
|
+
* `bfmemHookSource`) — a memory file the writer and the reader disagree about is
|
|
18
|
+
* memory that silently disappears.
|
|
18
19
|
*/
|
|
19
20
|
export const MEMORY_FILE_ENV = "BUILDERFORCE_MEMORY_FILE";
|
|
21
|
+
/** The canonical per-machine store, relative to the home directory. */
|
|
22
|
+
export const CANONICAL_MEMORY_SEGMENTS = [".builderforce-memory", "memory.json"];
|
|
23
|
+
/**
|
|
24
|
+
* Where earlier installers put the store (`~/.claude/builderforce-memory/memory.json`).
|
|
25
|
+
* Still honoured: a machine whose live memory sits here keeps using it.
|
|
26
|
+
*/
|
|
27
|
+
export const LEGACY_MEMORY_SEGMENTS = [".claude", "builderforce-memory", "memory.json"];
|
|
28
|
+
/** The default JSON snapshot path: ONE store per machine, shared by every MCP host. */
|
|
20
29
|
export function defaultMemoryFile(homedir = nodeOs.homedir()) {
|
|
21
|
-
return nodePath.join(homedir,
|
|
30
|
+
return nodePath.join(homedir, ...CANONICAL_MEMORY_SEGMENTS);
|
|
31
|
+
}
|
|
32
|
+
/** Every location a store may live in, canonical first. */
|
|
33
|
+
export function memoryFileCandidates(homedir = nodeOs.homedir()) {
|
|
34
|
+
return [defaultMemoryFile(homedir), nodePath.join(homedir, ...LEGACY_MEMORY_SEGMENTS)];
|
|
22
35
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
36
|
+
const nodeProbe = {
|
|
37
|
+
fileMtime(path) {
|
|
38
|
+
try {
|
|
39
|
+
const st = nodeFs.statSync(path);
|
|
40
|
+
return st.isFile() ? st.mtimeMs : null;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* The snapshot path in effect:
|
|
49
|
+
* 1. `BUILDERFORCE_MEMORY_FILE`, when set;
|
|
50
|
+
* 2. else whichever candidate location actually holds a `memory.json` — the
|
|
51
|
+
* most recently written one if both do (logged; neither is ever deleted);
|
|
52
|
+
* 3. else the canonical default.
|
|
53
|
+
*/
|
|
54
|
+
export function resolveMemoryFile(env = process.env, homedir, opts = {}) {
|
|
55
|
+
const explicit = env[MEMORY_FILE_ENV];
|
|
56
|
+
if (explicit)
|
|
57
|
+
return explicit;
|
|
58
|
+
const probe = opts.probe ?? nodeProbe;
|
|
59
|
+
const candidates = memoryFileCandidates(homedir);
|
|
60
|
+
const present = candidates
|
|
61
|
+
.map((path) => ({ path, mtime: probe.fileMtime(path) }))
|
|
62
|
+
.filter((c) => c.mtime !== null);
|
|
63
|
+
if (present.length === 0)
|
|
64
|
+
return candidates[0];
|
|
65
|
+
if (present.length === 1) {
|
|
66
|
+
if (present[0].path !== candidates[0]) {
|
|
67
|
+
opts.log?.(`[builderforce-memory] using the store at ${present[0].path} (no memory.json at ${candidates[0]}).`);
|
|
68
|
+
}
|
|
69
|
+
return present[0].path;
|
|
70
|
+
}
|
|
71
|
+
const winner = present.reduce((a, b) => (b.mtime > a.mtime ? b : a));
|
|
72
|
+
const others = present.filter((c) => c !== winner).map((c) => c.path);
|
|
73
|
+
opts.log?.(`[builderforce-memory] memory.json exists in ${present.length} locations; using ${winner.path} ` +
|
|
74
|
+
`(most recently written). Left untouched: ${others.join(", ")}.`);
|
|
75
|
+
return winner.path;
|
|
26
76
|
}
|
|
27
77
|
/** Published package + bin. The bin name matches the unscoped package name. */
|
|
28
78
|
export const MCP_PACKAGE = "@seanhogg/builderforce-memory-mcp";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-spec.js","sourceRoot":"","sources":["../../src/install/server-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,MAAM,MAAM,SAAS,CAAC;AAC7B,OAAO,QAAQ,MAAM,WAAW,CAAC;AAQjC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,0BAA0B,CAAC;AAE1D,MAAM,UAAU,iBAAiB,CAAC,UAAkB,MAAM,CAAC,OAAO,EAAE;IAChE,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"server-spec.js","sourceRoot":"","sources":["../../src/install/server-spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The recall probe compaction runs before it stubs a fact: the person's local
|
|
3
|
+
* Evermind model — the same `.evermind` package recall embeds with and experience
|
|
4
|
+
* training adapts (`BUILDERFORCE_MEMORY_MODEL`) — is asked the question generated
|
|
5
|
+
* from the fact (`probeQuestionFor`), and the fact is stubbed only when the answer
|
|
6
|
+
* carries it. No model configured, or one that cannot generate, means no probe —
|
|
7
|
+
* and no probe means nothing is compacted.
|
|
8
|
+
*/
|
|
9
|
+
import type { RecallProbe } from "../compaction.js";
|
|
10
|
+
/** Tokens the model may spend answering one probe — a cloze answer is a word or two. */
|
|
11
|
+
export declare const PROBE_MAX_NEW_TOKENS = 16;
|
|
12
|
+
/** Wrap any text generator as a probe. Greedy, short, never throws. */
|
|
13
|
+
export declare function generatorProbe(generate: (prompt: string) => string | Promise<string>): RecallProbe;
|
|
14
|
+
export interface RecallProbeEnv {
|
|
15
|
+
env?: Record<string, string | undefined>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The probe for this server, or null when no model is configured, the package is
|
|
19
|
+
* not a text LM, or its tokenizer cannot decode (no answer text to check).
|
|
20
|
+
*/
|
|
21
|
+
export declare function createRecallProbe(opts?: RecallProbeEnv): Promise<RecallProbe | null>;
|
|
22
|
+
/**
|
|
23
|
+
* {@link createRecallProbe}, deferred to the first compaction — a server should not
|
|
24
|
+
* load a checkpoint at boot for a tool most sessions never call. Null when no model
|
|
25
|
+
* is configured; a model that then fails to load answers nothing (every probe fails,
|
|
26
|
+
* so nothing is stubbed).
|
|
27
|
+
*/
|
|
28
|
+
export declare function lazyRecallProbe(opts?: RecallProbeEnv): RecallProbe | null;
|
|
29
|
+
//# sourceMappingURL=recall-probe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recall-probe.d.ts","sourceRoot":"","sources":["../../src/model/recall-probe.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AASpD,wFAAwF;AACxF,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,WAAW,CAWlG;AAED,MAAM,WAAW,cAAc;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC5C;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAkB9F;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,cAAmB,GAAG,WAAW,GAAG,IAAI,CAW7E"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The recall probe compaction runs before it stubs a fact: the person's local
|
|
3
|
+
* Evermind model — the same `.evermind` package recall embeds with and experience
|
|
4
|
+
* training adapts (`BUILDERFORCE_MEMORY_MODEL`) — is asked the question generated
|
|
5
|
+
* from the fact (`probeQuestionFor`), and the fact is stubbed only when the answer
|
|
6
|
+
* carries it. No model configured, or one that cannot generate, means no probe —
|
|
7
|
+
* and no probe means nothing is compacted.
|
|
8
|
+
*/
|
|
9
|
+
import { MODEL_FILE_ENV, TOKENIZER_FILE_ENV } from "../embedding/index.js";
|
|
10
|
+
import { loadEvermindPackage } from "./evermind-package.js";
|
|
11
|
+
/** Tokens the model may spend answering one probe — a cloze answer is a word or two. */
|
|
12
|
+
export const PROBE_MAX_NEW_TOKENS = 16;
|
|
13
|
+
/** Wrap any text generator as a probe. Greedy, short, never throws. */
|
|
14
|
+
export function generatorProbe(generate) {
|
|
15
|
+
return {
|
|
16
|
+
async answer(question) {
|
|
17
|
+
try {
|
|
18
|
+
const out = await generate(question);
|
|
19
|
+
return typeof out === "string" ? out : null;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The probe for this server, or null when no model is configured, the package is
|
|
29
|
+
* not a text LM, or its tokenizer cannot decode (no answer text to check).
|
|
30
|
+
*/
|
|
31
|
+
export async function createRecallProbe(opts = {}) {
|
|
32
|
+
const env = opts.env ?? process.env;
|
|
33
|
+
const modelFile = env[MODEL_FILE_ENV];
|
|
34
|
+
if (!modelFile)
|
|
35
|
+
return null;
|
|
36
|
+
const loaded = await loadEvermindPackage(modelFile, env[TOKENIZER_FILE_ENV] || undefined);
|
|
37
|
+
if (!loaded)
|
|
38
|
+
return null;
|
|
39
|
+
const codec = loaded.codec;
|
|
40
|
+
if (typeof codec.decode !== "function")
|
|
41
|
+
return null;
|
|
42
|
+
let lm;
|
|
43
|
+
try {
|
|
44
|
+
lm = loaded.pkg.loadLM();
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
if (typeof lm?.generateText !== "function")
|
|
50
|
+
return null;
|
|
51
|
+
return generatorProbe((prompt) => lm.generateText(prompt, loaded.codec, { maxNewTokens: PROBE_MAX_NEW_TOKENS, temperature: 0 }));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* {@link createRecallProbe}, deferred to the first compaction — a server should not
|
|
55
|
+
* load a checkpoint at boot for a tool most sessions never call. Null when no model
|
|
56
|
+
* is configured; a model that then fails to load answers nothing (every probe fails,
|
|
57
|
+
* so nothing is stubbed).
|
|
58
|
+
*/
|
|
59
|
+
export function lazyRecallProbe(opts = {}) {
|
|
60
|
+
const env = opts.env ?? process.env;
|
|
61
|
+
if (!env[MODEL_FILE_ENV])
|
|
62
|
+
return null;
|
|
63
|
+
let probe = null;
|
|
64
|
+
return {
|
|
65
|
+
async answer(question) {
|
|
66
|
+
probe ??= createRecallProbe({ env });
|
|
67
|
+
const p = await probe;
|
|
68
|
+
return p ? p.answer(question) : null;
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=recall-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recall-probe.js","sourceRoot":"","sources":["../../src/model/recall-probe.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAO5D,wFAAwF;AACxF,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,uEAAuE;AACvE,MAAM,UAAU,cAAc,CAAC,QAAsD;IACjF,OAAO;QACH,KAAK,CAAC,MAAM,CAAC,QAAgB;YACzB,IAAI,CAAC;gBACD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBACrC,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAChD,CAAC;YAAC,MAAM,CAAC;gBACL,OAAO,IAAI,CAAC;YAChB,CAAC;QACL,CAAC;KACJ,CAAC;AACN,CAAC;AAMD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAuB,EAAE;IAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,MAAM,SAAS,GAAG,GAAG,CAAC,cAAc,CAAC,CAAC;IACtC,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,kBAAkB,CAAC,IAAI,SAAS,CAAC,CAAC;IAC1F,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAwC,CAAC;IAC9D,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACpD,IAAI,EAAgB,CAAC;IACrB,IAAI,CAAC;QACD,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,EAAkB,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,OAAO,EAAE,EAAE,YAAY,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACxD,OAAO,cAAc,CAAC,CAAC,MAAM,EAAE,EAAE,CAC7B,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,EAAE,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAChG,CAAC;AACN,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAuB,EAAE;IACrD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,KAAK,GAAuC,IAAI,CAAC;IACrD,OAAO;QACH,KAAK,CAAC,MAAM,CAAC,QAAgB;YACzB,KAAK,KAAK,iBAAiB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;YACrC,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC;YACtB,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACzC,CAAC;KACJ,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FactArchive — where a compacted fact's full original lives once its body is a stub.
|
|
3
|
+
*
|
|
4
|
+
* The archive is deliberately NOT a field on the stored entry: the store snapshot is
|
|
5
|
+
* rebuilt from the store on every write, rewritten in place by other processes, and
|
|
6
|
+
* capped/evicted at {@link DEFAULT_MAX_ENTRIES}; an archived original riding inside
|
|
7
|
+
* it would be lost to any one of those. A separate sidecar (`memory.archive.json`,
|
|
8
|
+
* see `defaultArchiveFile`) is only ever merged into, never pruned, so an evicted or
|
|
9
|
+
* forgotten stub still has its original.
|
|
10
|
+
*
|
|
11
|
+
* Two implementations, one contract: in-memory (a backend with no disk mirror) and
|
|
12
|
+
* file-backed (shared across processes through {@link SharedJsonFile}, with its
|
|
13
|
+
* rotating backups and freshness check).
|
|
14
|
+
*/
|
|
15
|
+
import { type ArchivedFact } from "../compaction.js";
|
|
16
|
+
import { type SharedFileFs } from "./shared-json-file.js";
|
|
17
|
+
export interface FactArchive {
|
|
18
|
+
/** The archived original for `key`, if one exists. */
|
|
19
|
+
get(key: string): ArchivedFact | undefined;
|
|
20
|
+
/** Every row, read once — for callers resolving many keys in one pass. */
|
|
21
|
+
all(): Readonly<Record<string, ArchivedFact>>;
|
|
22
|
+
/** Add or replace archive rows. Durable before it returns. */
|
|
23
|
+
putMany(facts: ArchivedFact[]): void;
|
|
24
|
+
}
|
|
25
|
+
/** Process-local archive — the default for a backend with no disk mirror. */
|
|
26
|
+
export declare class MemoryFactArchive implements FactArchive {
|
|
27
|
+
private readonly rows;
|
|
28
|
+
get(key: string): ArchivedFact | undefined;
|
|
29
|
+
all(): Readonly<Record<string, ArchivedFact>>;
|
|
30
|
+
putMany(facts: ArchivedFact[]): void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Archive mirrored to a JSON file several processes share. Re-reads the file when it
|
|
34
|
+
* changed underneath this process; every write merges into the latest on-disk text,
|
|
35
|
+
* so two writers add to one archive rather than overwriting each other's rows.
|
|
36
|
+
*/
|
|
37
|
+
export declare class FileFactArchive implements FactArchive {
|
|
38
|
+
private rows;
|
|
39
|
+
private text;
|
|
40
|
+
private readonly file;
|
|
41
|
+
constructor(path: string, fs: SharedFileFs);
|
|
42
|
+
get(key: string): ArchivedFact | undefined;
|
|
43
|
+
all(): Readonly<Record<string, ArchivedFact>>;
|
|
44
|
+
putMany(facts: ArchivedFact[]): void;
|
|
45
|
+
private refresh;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=fact-archive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-archive.d.ts","sourceRoot":"","sources":["../../src/persistence/fact-archive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAA8B,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAW1E,MAAM,WAAW,WAAW;IACxB,sDAAsD;IACtD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IAC3C,0EAA0E;IAC1E,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAC9C,8DAA8D;IAC9D,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;CACxC;AAED,6EAA6E;AAC7E,qBAAa,iBAAkB,YAAW,WAAW;IACjD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqF;IAE1G,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI1C,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAI7C,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI;CAGvC;AAED;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,WAAW;IAC/C,OAAO,CAAC,IAAI,CAAoC;IAChD,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;gBAE1B,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY;IAK1C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAK1C,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAK7C,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI;IAepC,OAAO,CAAC,OAAO;CAOlB"}
|