@seanhogg/builderforce-memory-mcp 2026.7.12 → 2026.9.27
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 +47 -5
- package/dist/backend.d.ts +32 -0
- package/dist/backend.d.ts.map +1 -1
- package/dist/backends/memory-store.d.ts +32 -9
- package/dist/backends/memory-store.d.ts.map +1 -1
- package/dist/backends/memory-store.js +155 -33
- package/dist/backends/memory-store.js.map +1 -1
- package/dist/bin/http.d.ts +5 -0
- package/dist/bin/http.d.ts.map +1 -1
- package/dist/bin/http.js +11 -0
- package/dist/bin/http.js.map +1 -1
- package/dist/bin/install.js +3 -2
- package/dist/bin/install.js.map +1 -1
- package/dist/bin/stdio.d.ts +17 -7
- package/dist/bin/stdio.d.ts.map +1 -1
- package/dist/bin/stdio.js +24 -8
- package/dist/bin/stdio.js.map +1 -1
- package/dist/compaction.d.ts +76 -0
- package/dist/compaction.d.ts.map +1 -0
- package/dist/compaction.js +77 -0
- package/dist/compaction.js.map +1 -0
- package/dist/embedding/evermind-embedder.d.ts +119 -0
- package/dist/embedding/evermind-embedder.d.ts.map +1 -0
- package/dist/embedding/evermind-embedder.js +201 -0
- package/dist/embedding/evermind-embedder.js.map +1 -0
- package/dist/embedding/index.d.ts +38 -0
- package/dist/embedding/index.d.ts.map +1 -0
- package/dist/embedding/index.js +44 -0
- package/dist/embedding/index.js.map +1 -0
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/install/claude-hooks.d.ts +42 -2
- package/dist/install/claude-hooks.d.ts.map +1 -1
- package/dist/install/claude-hooks.js +111 -16
- package/dist/install/claude-hooks.js.map +1 -1
- package/dist/install/server-spec.d.ts +12 -0
- package/dist/install/server-spec.d.ts.map +1 -1
- package/dist/install/server-spec.js +18 -0
- package/dist/install/server-spec.js.map +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +117 -6
- package/dist/tools.js.map +1 -1
- package/package.json +15 -4
- package/server.json +47 -0
- package/src/backend.ts +36 -0
- package/src/backends/memory-store.ts +184 -35
- package/src/bin/http.ts +12 -0
- package/src/bin/install.ts +3 -2
- package/src/bin/stdio.ts +25 -8
- package/src/compaction.ts +126 -0
- package/src/embedding/evermind-embedder.ts +276 -0
- package/src/embedding/index.ts +54 -0
- package/src/index.ts +18 -4
- package/src/install/claude-hooks.ts +116 -15
- package/src/install/server-spec.ts +25 -0
- package/src/tools.ts +133 -12
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* embedding — stand up the recall embedder for a headless server.
|
|
3
|
+
*
|
|
4
|
+
* Both out-of-process bins (stdio and HTTP) need the SAME decision: is an
|
|
5
|
+
* embedding model configured, and if so where do its vectors get cached? That
|
|
6
|
+
* decision lives here once, so the two servers cannot drift into ranking recall
|
|
7
|
+
* differently from one another.
|
|
8
|
+
*/
|
|
9
|
+
import { createEvermindEmbedder } from "./evermind-embedder.js";
|
|
10
|
+
export { createEvermindEmbedder, CachedTextEmbedder } from "./evermind-embedder.js";
|
|
11
|
+
/** Absolute path to a `.evermind` package (an `evermind-lm`) to embed recall with. */
|
|
12
|
+
export const MODEL_FILE_ENV = "BUILDERFORCE_MEMORY_MODEL";
|
|
13
|
+
/** Absolute path to the tokenizer JSON matching that checkpoint. */
|
|
14
|
+
export const TOKENIZER_FILE_ENV = "BUILDERFORCE_MEMORY_TOKENIZER";
|
|
15
|
+
/** Absolute path for the persistent vector cache; defaults beside the snapshot. */
|
|
16
|
+
export const VECTOR_CACHE_ENV = "BUILDERFORCE_MEMORY_VECTORS";
|
|
17
|
+
/**
|
|
18
|
+
* Where vectors are cached by default: beside the memory snapshot, under the same
|
|
19
|
+
* name. They belong together — the cache is only meaningful for the memories in
|
|
20
|
+
* that snapshot, and pointing a second store at the same vectors would be a cache
|
|
21
|
+
* for the wrong corpus.
|
|
22
|
+
*/
|
|
23
|
+
export function defaultVectorCacheFile(memoryFile) {
|
|
24
|
+
return memoryFile.replace(/\.json$/i, "") + ".vectors.json";
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The embedder this server should rank recall with, or `null` when none is
|
|
28
|
+
* configured (recall then ranks lexically and says so).
|
|
29
|
+
*
|
|
30
|
+
* Opt-in by design: no model path, no model. A memory server must start and serve
|
|
31
|
+
* recall on a host that has never downloaded a checkpoint.
|
|
32
|
+
*/
|
|
33
|
+
export async function createRecallEmbedder(opts) {
|
|
34
|
+
const env = opts.env ?? process.env;
|
|
35
|
+
const modelFile = env[MODEL_FILE_ENV];
|
|
36
|
+
if (!modelFile)
|
|
37
|
+
return null;
|
|
38
|
+
return createEvermindEmbedder({
|
|
39
|
+
modelFile,
|
|
40
|
+
tokenizerFile: env[TOKENIZER_FILE_ENV],
|
|
41
|
+
cacheFile: env[VECTOR_CACHE_ENV] || defaultVectorCacheFile(opts.memoryFile),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/embedding/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,sBAAsB,EAA+B,MAAM,wBAAwB,CAAC;AAE7F,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGpF,sFAAsF;AACtF,MAAM,CAAC,MAAM,cAAc,GAAG,2BAA2B,CAAC;AAC1D,oEAAoE;AACpE,MAAM,CAAC,MAAM,kBAAkB,GAAG,+BAA+B,CAAC;AAClE,mFAAmF;AACnF,MAAM,CAAC,MAAM,gBAAgB,GAAG,6BAA6B,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACrD,OAAO,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,GAAG,eAAe,CAAC;AAChE,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAuB;IAC9D,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,OAAO,sBAAsB,CAAC;QAC1B,SAAS;QACT,aAAa,EAAE,GAAG,CAAC,kBAAkB,CAAC;QACtC,SAAS,EAAE,GAAG,CAAC,gBAAgB,CAAC,IAAI,sBAAsB,CAAC,IAAI,CAAC,UAAU,CAAC;KAC9E,CAAC,CAAC;AACP,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,11 +6,15 @@
|
|
|
6
6
|
* - runStdio → stdio subprocess (any language)
|
|
7
7
|
* - createMemoryHttpHandler→ Streamable HTTP (multi-tenant / networked)
|
|
8
8
|
*/
|
|
9
|
-
export type { MemoryBackend, RecallHit, RememberInput } from "./backend.js";
|
|
9
|
+
export type { MemoryBackend, RankedRecall, RecallHit, RecallMethod, RememberInput } from "./backend.js";
|
|
10
|
+
export { createRecallEmbedder, createEvermindEmbedder, CachedTextEmbedder, defaultVectorCacheFile, MODEL_FILE_ENV, TOKENIZER_FILE_ENV, VECTOR_CACHE_ENV } from "./embedding/index.js";
|
|
11
|
+
export type { EvermindEmbedderOptions, PersistentTextEmbedder, TextEmbedderLike, RecallEmbedderEnv } from "./embedding/index.js";
|
|
10
12
|
export { MemoryStoreBackend, createLocalMemoryStoreBackend } from "./backends/memory-store.js";
|
|
11
13
|
export type { LocalBackendOptions } from "./backends/memory-store.js";
|
|
12
14
|
export { buildMemoryTools } from "./tools.js";
|
|
13
15
|
export type { MemoryTool, MemoryToolsOptions, ToolResult } from "./tools.js";
|
|
16
|
+
export { STUB_PREFIX, DEFAULT_STUB_CHARS, isStub, firstLine, memoryStub, planCompaction } from "./compaction.js";
|
|
17
|
+
export type { CompactionCandidate, CompactionWrite, CompactionSkip, CompactionPlan, CompactionOptions } from "./compaction.js";
|
|
14
18
|
export { createMemoryMcpServer } from "./transports/sdk.js";
|
|
15
19
|
export type { SdkServerOptions, SdkMcpServerConfig } from "./transports/sdk.js";
|
|
16
20
|
export { buildMcpServer } from "./transports/mcp-server.js";
|
|
@@ -19,12 +23,12 @@ export { runStdio } from "./transports/stdio.js";
|
|
|
19
23
|
export { createMemoryHttpHandler } from "./transports/http.js";
|
|
20
24
|
export type { HttpHandlerOptions } from "./transports/http.js";
|
|
21
25
|
export { hashToken, timingSafeEqualStr, buildTenantIndex, bearerToken, RateLimiter } from "./transports/auth.js";
|
|
22
|
-
export { buildServerSpec, MCP_PACKAGE, MCP_BIN, RUNTIME_PEERS } from "./install/server-spec.js";
|
|
26
|
+
export { buildServerSpec, defaultMemoryFile, resolveMemoryFile, MCP_PACKAGE, MCP_BIN, MEMORY_FILE_ENV, RUNTIME_PEERS } from "./install/server-spec.js";
|
|
23
27
|
export type { StdioServerSpec, ServerSpecOptions } from "./install/server-spec.js";
|
|
24
28
|
export { installMemoryServer } from "./install/install.js";
|
|
25
29
|
export type { InstallOptions, InstallResult, InstallStatus, HostSelector, FsLike } from "./install/install.js";
|
|
26
30
|
export { HOSTS, SERVER_KEY, findHost } from "./install/hosts.js";
|
|
27
31
|
export type { HostAdapter, HostEnv, ConfigFormat } from "./install/hosts.js";
|
|
28
|
-
export { installClaudeCombo, bfmemHookSource, companionSkillMd, claudeComboPaths } from "./install/claude-hooks.js";
|
|
29
|
-
export type { ClaudeComboPaths } from "./install/claude-hooks.js";
|
|
32
|
+
export { installClaudeCombo, bfmemHookSource, companionSkillMd, claudeComboPaths, pluginHooksConfig, HOOK_EVENTS } from "./install/claude-hooks.js";
|
|
33
|
+
export type { ClaudeComboPaths, HookConfig } from "./install/claude-hooks.js";
|
|
30
34
|
//# sourceMappingURL=index.d.ts.map
|
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,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;
|
|
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;AAC/F,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAM7E,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjH,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAG/H,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEhF,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,YAAY,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGjH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACvJ,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC/G,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACjE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG7E,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACpJ,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,10 +6,20 @@
|
|
|
6
6
|
* - runStdio → stdio subprocess (any language)
|
|
7
7
|
* - createMemoryHttpHandler→ Streamable HTTP (multi-tenant / networked)
|
|
8
8
|
*/
|
|
9
|
+
// -- CPU SSM-embedding recall (no GPU) --------------------------------------
|
|
10
|
+
// The headless servers rank recall by EvermindLM embedding cosine fused with the
|
|
11
|
+
// lexical ranking whenever a checkpoint is configured; exported so an embedding
|
|
12
|
+
// host can build the same embedder (and share its persistent vector cache).
|
|
13
|
+
export { createRecallEmbedder, createEvermindEmbedder, CachedTextEmbedder, defaultVectorCacheFile, MODEL_FILE_ENV, TOKENIZER_FILE_ENV, VECTOR_CACHE_ENV } from "./embedding/index.js";
|
|
9
14
|
// ── Local backend (IndexedDB via @seanhogg/builderforce-memory) ────────────────────────
|
|
10
15
|
export { MemoryStoreBackend, createLocalMemoryStoreBackend } from "./backends/memory-store.js";
|
|
11
16
|
// ── Tool core ─────────────────────────────────────────────────────────────────
|
|
12
17
|
export { buildMemoryTools } from "./tools.js";
|
|
18
|
+
// ── Compaction (absorbed fact → one-line pointer stub) ───────────────────────
|
|
19
|
+
// Exported so an EXTERNAL compactor (the BuilderForce VS Code extension rewrites
|
|
20
|
+
// the snapshot file directly) can produce byte-identical stubs, keeping the two
|
|
21
|
+
// paths idempotent with respect to each other.
|
|
22
|
+
export { STUB_PREFIX, DEFAULT_STUB_CHARS, isStub, firstLine, memoryStub, planCompaction } from "./compaction.js";
|
|
13
23
|
// ── Transports ──────────────────────────────────────────────────────────────
|
|
14
24
|
export { createMemoryMcpServer } from "./transports/sdk.js";
|
|
15
25
|
export { buildMcpServer } from "./transports/mcp-server.js";
|
|
@@ -17,10 +27,10 @@ export { runStdio } from "./transports/stdio.js";
|
|
|
17
27
|
export { createMemoryHttpHandler } from "./transports/http.js";
|
|
18
28
|
export { hashToken, timingSafeEqualStr, buildTenantIndex, bearerToken, RateLimiter } from "./transports/auth.js";
|
|
19
29
|
// ── Multi-host installer (wire the stdio server into any MCP-capable agent) ───
|
|
20
|
-
export { buildServerSpec, MCP_PACKAGE, MCP_BIN, RUNTIME_PEERS } from "./install/server-spec.js";
|
|
30
|
+
export { buildServerSpec, defaultMemoryFile, resolveMemoryFile, MCP_PACKAGE, MCP_BIN, MEMORY_FILE_ENV, RUNTIME_PEERS } from "./install/server-spec.js";
|
|
21
31
|
export { installMemoryServer } from "./install/install.js";
|
|
22
32
|
export { HOSTS, SERVER_KEY, findHost } from "./install/hosts.js";
|
|
23
33
|
// Claude Code "memory combo" — hooks (SessionStart/PreCompact/UserPromptSubmit/Stop)
|
|
24
34
|
// + companion skill that make memory self-driving (contextual recall + autonomous capture).
|
|
25
|
-
export { installClaudeCombo, bfmemHookSource, companionSkillMd, claudeComboPaths } from "./install/claude-hooks.js";
|
|
35
|
+
export { installClaudeCombo, bfmemHookSource, companionSkillMd, claudeComboPaths, pluginHooksConfig, HOOK_EVENTS } from "./install/claude-hooks.js";
|
|
26
36
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,0FAA0F;AAC1F,OAAO,EAAE,kBAAkB,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AAG/F,iFAAiF;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG9C,+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,EAAE,eAAe,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,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,MAAM,4BAA4B,CAAC;AAG/F,iFAAiF;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG9C,gFAAgF;AAChF,iFAAiF;AACjF,gFAAgF;AAChF,+CAA+C;AAC/C,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjH,+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,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEvJ,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"}
|
|
@@ -20,8 +20,16 @@
|
|
|
20
20
|
* is idempotent and backup-safe, matching install.ts.
|
|
21
21
|
*/
|
|
22
22
|
import type { FsLike } from "./install.js";
|
|
23
|
-
/**
|
|
24
|
-
|
|
23
|
+
/**
|
|
24
|
+
* The single hook script, four modes.
|
|
25
|
+
*
|
|
26
|
+
* `memoryFile` is the JSON snapshot path to bake in. Pass `null` to emit a
|
|
27
|
+
* script that resolves the path at RUN time instead — required for the Claude
|
|
28
|
+
* Code plugin, whose files are static and machine-independent. The runtime
|
|
29
|
+
* branch must stay in lockstep with `resolveMemoryFile`; `install.test.mjs`
|
|
30
|
+
* asserts it does.
|
|
31
|
+
*/
|
|
32
|
+
export declare function bfmemHookSource(memoryFile: string | null): string;
|
|
25
33
|
/** The companion skill doc that teaches the recall/remember discipline. */
|
|
26
34
|
export declare function companionSkillMd(): string;
|
|
27
35
|
/** Files/paths the combo manages, derived from the Claude config dir (~/.claude). */
|
|
@@ -32,6 +40,38 @@ export interface ClaudeComboPaths {
|
|
|
32
40
|
companionSkill: string;
|
|
33
41
|
}
|
|
34
42
|
export declare function claudeComboPaths(claudeDir: string): ClaudeComboPaths;
|
|
43
|
+
/**
|
|
44
|
+
* The four events that make memory self-driving, and the hook-script mode each
|
|
45
|
+
* one runs. Single source of truth for BOTH delivery shapes: the settings.json
|
|
46
|
+
* merge performed by {@link installClaudeCombo}, and the static `hooks.json` a
|
|
47
|
+
* Claude Code plugin ships ({@link pluginHooksConfig}).
|
|
48
|
+
*/
|
|
49
|
+
export declare const HOOK_EVENTS: readonly [{
|
|
50
|
+
readonly event: "SessionStart";
|
|
51
|
+
readonly mode: "--session";
|
|
52
|
+
}, {
|
|
53
|
+
readonly event: "PreCompact";
|
|
54
|
+
readonly mode: "--precompact";
|
|
55
|
+
}, {
|
|
56
|
+
readonly event: "UserPromptSubmit";
|
|
57
|
+
readonly mode: "--recall";
|
|
58
|
+
}, {
|
|
59
|
+
readonly event: "Stop";
|
|
60
|
+
readonly mode: "--capture";
|
|
61
|
+
}];
|
|
62
|
+
/** Hook-config shape shared by `settings.json` and a plugin's `hooks/hooks.json`. */
|
|
63
|
+
export type HookConfig = Record<string, Array<{
|
|
64
|
+
hooks: Array<{
|
|
65
|
+
type: "command";
|
|
66
|
+
command: string;
|
|
67
|
+
}>;
|
|
68
|
+
}>>;
|
|
69
|
+
/**
|
|
70
|
+
* The plugin form of the combo: every event pointed at the plugin-local hook
|
|
71
|
+
* script. `${CLAUDE_PLUGIN_ROOT}` is expanded by Claude Code to the installed
|
|
72
|
+
* plugin directory, so the script needs no install step and no baked-in paths.
|
|
73
|
+
*/
|
|
74
|
+
export declare function pluginHooksConfig(scriptRelPath?: string): HookConfig;
|
|
35
75
|
/**
|
|
36
76
|
* Write the hook script + companion skill and register all four hooks in
|
|
37
77
|
* settings.json. Idempotent (skips a hook command already present) and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-hooks.d.ts","sourceRoot":"","sources":["../../src/install/claude-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-hooks.d.ts","sourceRoot":"","sources":["../../src/install/claude-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAiMjE;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,IAAI,MAAM,CA0BzC;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,8 +20,20 @@
|
|
|
20
20
|
* is idempotent and backup-safe, matching install.ts.
|
|
21
21
|
*/
|
|
22
22
|
import nodePath from "node:path";
|
|
23
|
-
|
|
23
|
+
import { MEMORY_FILE_ENV } from "./server-spec.js";
|
|
24
|
+
/**
|
|
25
|
+
* The single hook script, four modes.
|
|
26
|
+
*
|
|
27
|
+
* `memoryFile` is the JSON snapshot path to bake in. Pass `null` to emit a
|
|
28
|
+
* script that resolves the path at RUN time instead — required for the Claude
|
|
29
|
+
* Code plugin, whose files are static and machine-independent. The runtime
|
|
30
|
+
* branch must stay in lockstep with `resolveMemoryFile`; `install.test.mjs`
|
|
31
|
+
* asserts it does.
|
|
32
|
+
*/
|
|
24
33
|
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);
|
|
25
37
|
return `#!/usr/bin/env node
|
|
26
38
|
/**
|
|
27
39
|
* builderforce-memory hook — generated by builderforce-memory-install. Dependency-free:
|
|
@@ -33,8 +45,10 @@ export function bfmemHookSource(memoryFile) {
|
|
|
33
45
|
* durable correction is persisted via memory_remember.
|
|
34
46
|
*/
|
|
35
47
|
import fs from "node:fs";
|
|
48
|
+
import os from "node:os";
|
|
49
|
+
import path from "node:path";
|
|
36
50
|
|
|
37
|
-
const FILE = ${
|
|
51
|
+
const FILE = ${fileExpr};
|
|
38
52
|
const mode = process.argv[2] || "--session";
|
|
39
53
|
|
|
40
54
|
function readStdin() {
|
|
@@ -48,6 +62,27 @@ function tokens(s) {
|
|
|
48
62
|
return String(s || "").toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 3);
|
|
49
63
|
}
|
|
50
64
|
|
|
65
|
+
// ── Per-session injection ledger ─────────────────────────────────────────────
|
|
66
|
+
// The SessionStart digest and the per-prompt recall both push memory CONTENT
|
|
67
|
+
// into the context window, where it stays for the rest of the session. Without
|
|
68
|
+
// dedup, a long session re-injects the same memories on every turn — unbounded
|
|
69
|
+
// growth that is exactly what pushes a session past 150k tokens. The ledger
|
|
70
|
+
// records which keys have already been surfaced THIS session so we inject each
|
|
71
|
+
// memory at most once. Keyed by the host-provided session_id; degrades to the
|
|
72
|
+
// old always-inject behaviour when no id is available.
|
|
73
|
+
function ledgerFile(sid) {
|
|
74
|
+
const safe = String(sid || "").replace(/[^a-zA-Z0-9_.-]/g, "").slice(0, 80) || "nosession";
|
|
75
|
+
return path.join(os.tmpdir(), "bfmem-injected-" + safe + ".json");
|
|
76
|
+
}
|
|
77
|
+
function loadLedger(sid) {
|
|
78
|
+
try { const a = JSON.parse(fs.readFileSync(ledgerFile(sid), "utf8")); return new Set(Array.isArray(a) ? a : []); }
|
|
79
|
+
catch { return new Set(); }
|
|
80
|
+
}
|
|
81
|
+
function saveLedger(sid, set) {
|
|
82
|
+
if (!sid) return; // no id → no dedup state to persist (safe fallback)
|
|
83
|
+
try { fs.writeFileSync(ledgerFile(sid), JSON.stringify([...set].slice(-500))); } catch { /* best effort */ }
|
|
84
|
+
}
|
|
85
|
+
|
|
51
86
|
if (mode === "--precompact") {
|
|
52
87
|
process.stdout.write(
|
|
53
88
|
"[builderforce-memory] Context is about to be compacted. Persist any durable learnings from this session — decisions, fixes, project facts, user preferences — by calling memory_remember with concise one-line facts. Recall them later with memory_recall instead of re-reading files.",
|
|
@@ -56,13 +91,18 @@ if (mode === "--precompact") {
|
|
|
56
91
|
}
|
|
57
92
|
|
|
58
93
|
if (mode === "--recall") {
|
|
59
|
-
let prompt = "";
|
|
60
|
-
try {
|
|
94
|
+
let prompt = "", sid = "";
|
|
95
|
+
try {
|
|
96
|
+
const j = JSON.parse(readStdin() || "{}");
|
|
97
|
+
prompt = typeof j.prompt === "string" ? j.prompt : "";
|
|
98
|
+
sid = typeof j.session_id === "string" ? j.session_id : "";
|
|
99
|
+
} catch { /* no input */ }
|
|
61
100
|
if (!prompt) process.exit(0);
|
|
62
101
|
const entries = loadEntries();
|
|
63
102
|
if (entries.length === 0) process.exit(0);
|
|
64
103
|
const q = new Set(tokens(prompt));
|
|
65
104
|
if (q.size === 0) process.exit(0);
|
|
105
|
+
const led = loadLedger(sid);
|
|
66
106
|
const scored = entries
|
|
67
107
|
.map((e) => {
|
|
68
108
|
const hay = new Set(tokens([e.key, e.content, (e.tags || []).join(" ")].join(" ")));
|
|
@@ -71,10 +111,13 @@ if (mode === "--recall") {
|
|
|
71
111
|
return { e, score };
|
|
72
112
|
})
|
|
73
113
|
.filter((x) => x.score >= 2)
|
|
114
|
+
.filter((x) => !led.has(x.e.key)) // already surfaced this session → don't re-inject
|
|
74
115
|
.sort((a, b) => b.score - a.score)
|
|
75
116
|
.slice(0, 3);
|
|
76
117
|
if (scored.length === 0) process.exit(0);
|
|
77
|
-
const
|
|
118
|
+
for (const x of scored) led.add(x.e.key);
|
|
119
|
+
saveLedger(sid, led);
|
|
120
|
+
const lines = scored.map((x) => "• " + x.e.key + ": " + String(x.e.content || "").slice(0, 200)).join("\\n");
|
|
78
121
|
process.stdout.write(
|
|
79
122
|
"[builderforce-memory] Relevant stored memories for this request — use these instead of re-deriving or re-reading:\\n" + lines,
|
|
80
123
|
);
|
|
@@ -145,19 +188,37 @@ if (mode === "--capture") {
|
|
|
145
188
|
process.exit(0);
|
|
146
189
|
}
|
|
147
190
|
|
|
191
|
+
// SessionStart (default mode). Read the source + session_id so we can (a) seed
|
|
192
|
+
// the per-session ledger with the digest keys and (b) skip re-injecting on
|
|
193
|
+
// 'resume', where the earlier context — including this digest — is retained and
|
|
194
|
+
// a second copy would be pure waste.
|
|
195
|
+
let src = "startup", sessionId = "";
|
|
196
|
+
try {
|
|
197
|
+
const j = JSON.parse(readStdin() || "{}");
|
|
198
|
+
if (typeof j.source === "string") src = j.source;
|
|
199
|
+
if (typeof j.session_id === "string") sessionId = j.session_id;
|
|
200
|
+
} catch { /* no input */ }
|
|
201
|
+
|
|
148
202
|
const entries = loadEntries();
|
|
149
203
|
if (entries.length === 0) {
|
|
150
|
-
process.stdout.write(
|
|
204
|
+
if (src !== "resume") process.stdout.write(
|
|
151
205
|
"[builderforce-memory] Active (memory empty). Store durable facts with memory_remember and retrieve them with memory_recall instead of re-reading files or chat history — that is how token usage stays low.",
|
|
152
206
|
);
|
|
153
207
|
process.exit(0);
|
|
154
208
|
}
|
|
155
|
-
const
|
|
209
|
+
const ranked = entries
|
|
156
210
|
.map((e) => ({ key: e.key, content: String(e.content ?? ""), importance: typeof e.importance === "number" ? e.importance : 0.5 }))
|
|
157
211
|
.sort((a, b) => b.importance - a.importance)
|
|
158
|
-
.slice(0,
|
|
159
|
-
|
|
160
|
-
|
|
212
|
+
.slice(0, 6);
|
|
213
|
+
|
|
214
|
+
// Record the digest keys so per-prompt recall won't re-surface what's already
|
|
215
|
+
// on screen. Fresh window (startup/clear) → new ledger; otherwise merge.
|
|
216
|
+
const led = (src === "startup" || src === "clear") ? new Set() : loadLedger(sessionId);
|
|
217
|
+
for (const e of ranked) led.add(e.key);
|
|
218
|
+
saveLedger(sessionId, led);
|
|
219
|
+
|
|
220
|
+
if (src === "resume") process.exit(0); // context retained across resume — nothing to re-inject
|
|
221
|
+
const top = ranked.map((e) => "• " + e.key + ": " + e.content.slice(0, 180)).join("\\n");
|
|
161
222
|
process.stdout.write(
|
|
162
223
|
"[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,
|
|
163
224
|
);
|
|
@@ -199,12 +260,32 @@ export function claudeComboPaths(claudeDir) {
|
|
|
199
260
|
companionSkill: nodePath.join(claudeDir, "skills", "builderforce-memory", "SKILL.md"),
|
|
200
261
|
};
|
|
201
262
|
}
|
|
202
|
-
|
|
263
|
+
/**
|
|
264
|
+
* The four events that make memory self-driving, and the hook-script mode each
|
|
265
|
+
* one runs. Single source of truth for BOTH delivery shapes: the settings.json
|
|
266
|
+
* merge performed by {@link installClaudeCombo}, and the static `hooks.json` a
|
|
267
|
+
* Claude Code plugin ships ({@link pluginHooksConfig}).
|
|
268
|
+
*/
|
|
269
|
+
export const HOOK_EVENTS = [
|
|
203
270
|
{ event: "SessionStart", mode: "--session" },
|
|
204
271
|
{ event: "PreCompact", mode: "--precompact" },
|
|
205
272
|
{ event: "UserPromptSubmit", mode: "--recall" },
|
|
206
273
|
{ event: "Stop", mode: "--capture" },
|
|
207
274
|
];
|
|
275
|
+
/**
|
|
276
|
+
* The plugin form of the combo: every event pointed at the plugin-local hook
|
|
277
|
+
* script. `${CLAUDE_PLUGIN_ROOT}` is expanded by Claude Code to the installed
|
|
278
|
+
* plugin directory, so the script needs no install step and no baked-in paths.
|
|
279
|
+
*/
|
|
280
|
+
export function pluginHooksConfig(scriptRelPath = "hooks/bfmem-hook.mjs") {
|
|
281
|
+
const config = {};
|
|
282
|
+
for (const { event, mode } of HOOK_EVENTS) {
|
|
283
|
+
config[event] = [{
|
|
284
|
+
hooks: [{ type: "command", command: `node "\${CLAUDE_PLUGIN_ROOT}/${scriptRelPath}" ${mode}` }],
|
|
285
|
+
}];
|
|
286
|
+
}
|
|
287
|
+
return config;
|
|
288
|
+
}
|
|
208
289
|
/**
|
|
209
290
|
* Write the hook script + companion skill and register all four hooks in
|
|
210
291
|
* settings.json. Idempotent (skips a hook command already present) and
|
|
@@ -235,15 +316,29 @@ export function installClaudeCombo(opts) {
|
|
|
235
316
|
fs.copyFileSync(paths.settingsFile, `${paths.settingsFile}.bak`);
|
|
236
317
|
}
|
|
237
318
|
const hooks = (settings.hooks && typeof settings.hooks === "object" ? settings.hooks : {});
|
|
319
|
+
// Compare commands by a normalized form (path separators unified, whitespace
|
|
320
|
+
// collapsed, case-folded) so a re-install can't register a second copy of the
|
|
321
|
+
// same hook just because an earlier run wrote "C:/…" and this one writes
|
|
322
|
+
// "C:\…". Without this, Windows accumulates duplicate SessionStart/PreCompact
|
|
323
|
+
// hooks that each fire — doubling the memory the combo injects every session.
|
|
324
|
+
const normCmd = (c) => String(c ?? "").replace(/\\/g, "/").replace(/\s+/g, " ").trim().toLowerCase();
|
|
325
|
+
const hookRef = normCmd(paths.hookScript);
|
|
238
326
|
const added = [];
|
|
239
327
|
for (const { event, mode } of HOOK_EVENTS) {
|
|
240
328
|
const command = `node "${paths.hookScript}" ${mode}`;
|
|
241
|
-
const arr = (Array.isArray(hooks[event]) ? hooks[event] :
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
329
|
+
const arr = (Array.isArray(hooks[event]) ? hooks[event] : []);
|
|
330
|
+
// Drop any existing group that points at OUR hook script for THIS mode
|
|
331
|
+
// (any path-separator variant), then re-add exactly one canonical entry.
|
|
332
|
+
// This both dedupes accidental duplicates and refreshes the command.
|
|
333
|
+
const kept = arr.filter((g) => !(g.hooks || []).some((h) => {
|
|
334
|
+
const n = normCmd(h.command ?? "");
|
|
335
|
+
return n.includes(hookRef) && n.endsWith(mode);
|
|
336
|
+
}));
|
|
337
|
+
const wasPresent = kept.length !== arr.length;
|
|
338
|
+
kept.push({ hooks: [{ type: "command", command }] });
|
|
339
|
+
hooks[event] = kept;
|
|
340
|
+
if (!wasPresent)
|
|
245
341
|
added.push(event);
|
|
246
|
-
}
|
|
247
342
|
}
|
|
248
343
|
settings.hooks = hooks;
|
|
249
344
|
const settingsDir = nodePath.dirname(paths.settingsFile);
|
|
@@ -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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"}
|
|
@@ -11,6 +11,18 @@ export interface StdioServerSpec {
|
|
|
11
11
|
args: string[];
|
|
12
12
|
env?: Record<string, string>;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* The default JSON snapshot path: ONE store per machine, so every MCP host
|
|
16
|
+
* (Claude Code, Cursor, Claude Desktop, …) shares the same memory.
|
|
17
|
+
*
|
|
18
|
+
* Single source of truth for the installer, the stdio bin's fallback, and the
|
|
19
|
+
* Claude Code plugin's hook script — a memory file the writer and the reader
|
|
20
|
+
* disagree about is memory that silently disappears.
|
|
21
|
+
*/
|
|
22
|
+
export declare const MEMORY_FILE_ENV = "BUILDERFORCE_MEMORY_FILE";
|
|
23
|
+
export declare function defaultMemoryFile(homedir?: string): string;
|
|
24
|
+
/** The snapshot path in effect: explicit env wins, else the shared default. */
|
|
25
|
+
export declare function resolveMemoryFile(env?: Record<string, string | undefined>, homedir?: string): string;
|
|
14
26
|
export interface ServerSpecOptions {
|
|
15
27
|
/** Absolute path to the JSON snapshot that makes memory survive restarts. */
|
|
16
28
|
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;AAKH,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,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,MAAyB,GAAG,MAAM,CAE5E;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAC7B,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,EACrD,OAAO,CAAC,EAAE,MAAM,GACjB,MAAM,CAER;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,6 +6,24 @@
|
|
|
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 nodeOs from "node:os";
|
|
10
|
+
import nodePath from "node:path";
|
|
11
|
+
/**
|
|
12
|
+
* The default JSON snapshot path: ONE store per machine, so every MCP host
|
|
13
|
+
* (Claude Code, Cursor, Claude Desktop, …) shares the same memory.
|
|
14
|
+
*
|
|
15
|
+
* Single source of truth for the installer, the stdio bin's fallback, and the
|
|
16
|
+
* Claude Code plugin's hook script — a memory file the writer and the reader
|
|
17
|
+
* disagree about is memory that silently disappears.
|
|
18
|
+
*/
|
|
19
|
+
export const MEMORY_FILE_ENV = "BUILDERFORCE_MEMORY_FILE";
|
|
20
|
+
export function defaultMemoryFile(homedir = nodeOs.homedir()) {
|
|
21
|
+
return nodePath.join(homedir, ".builderforce-memory", "memory.json");
|
|
22
|
+
}
|
|
23
|
+
/** The snapshot path in effect: explicit env wins, else the shared default. */
|
|
24
|
+
export function resolveMemoryFile(env = process.env, homedir) {
|
|
25
|
+
return env[MEMORY_FILE_ENV] || defaultMemoryFile(homedir);
|
|
26
|
+
}
|
|
9
27
|
/** Published package + bin. The bin name matches the unscoped package name. */
|
|
10
28
|
export const MCP_PACKAGE = "@seanhogg/builderforce-memory-mcp";
|
|
11
29
|
export const MCP_BIN = "builderforce-memory-mcp";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-spec.js","sourceRoot":"","sources":["../../src/install/server-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
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,sBAAsB,EAAE,aAAa,CAAC,CAAC;AACzE,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,iBAAiB,CAC7B,MAA0C,OAAO,CAAC,GAAG,EACrD,OAAgB;IAEhB,OAAO,GAAG,CAAC,eAAe,CAAC,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC;AAC9D,CAAC;AAgBD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,WAAW,GAAG,mCAAmC,CAAC;AAC/D,MAAM,CAAC,MAAM,OAAO,GAAG,yBAAyB,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IACzB,+BAA+B;IAC/B,sCAAsC;IACtC,gBAAgB;CACnB,CAAC;AAEF,SAAS,OAAO,CAAC,IAAuB;IACpC,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,IAAI,IAAI,CAAC,UAAU;QAAE,GAAG,CAAC,0BAA0B,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC;IACvE,IAAI,IAAI,CAAC,QAAQ;QAAE,GAAG,CAAC,8BAA8B,CAAC,GAAG,GAAG,CAAC;IAC7D,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAA0B,EAAE;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACnD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC/E,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAE/F,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACxF,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACtE,CAAC"}
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAwD,MAAM,cAAc,CAAC;AAGxG,kEAAkE;AAClE,MAAM,WAAW,UAAU;IACvB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,2FAA2F;AAC3F,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC;IAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CACnE;AAED,MAAM,WAAW,kBAAkB;IAC/B,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oGAAoG;IACpG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAuED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,IAAI,GAAE,kBAAuB,GAAG,UAAU,EAAE,CA+NpG"}
|