@vortex-os/memory-extended 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/README.md +244 -0
  2. package/dist/consolidate/index.d.ts +7 -0
  3. package/dist/consolidate/index.d.ts.map +1 -0
  4. package/dist/consolidate/index.js +4 -0
  5. package/dist/consolidate/index.js.map +1 -0
  6. package/dist/consolidate/proposer.d.ts +43 -0
  7. package/dist/consolidate/proposer.d.ts.map +1 -0
  8. package/dist/consolidate/proposer.js +276 -0
  9. package/dist/consolidate/proposer.js.map +1 -0
  10. package/dist/consolidate/query.d.ts +32 -0
  11. package/dist/consolidate/query.d.ts.map +1 -0
  12. package/dist/consolidate/query.js +40 -0
  13. package/dist/consolidate/query.js.map +1 -0
  14. package/dist/consolidate/store.d.ts +21 -0
  15. package/dist/consolidate/store.d.ts.map +1 -0
  16. package/dist/consolidate/store.js +91 -0
  17. package/dist/consolidate/store.js.map +1 -0
  18. package/dist/consolidate/types.d.ts +68 -0
  19. package/dist/consolidate/types.d.ts.map +1 -0
  20. package/dist/consolidate/types.js +2 -0
  21. package/dist/consolidate/types.js.map +1 -0
  22. package/dist/index.d.ts +7 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +7 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/internal/frontmatter.d.ts +6 -0
  27. package/dist/internal/frontmatter.d.ts.map +1 -0
  28. package/dist/internal/frontmatter.js +38 -0
  29. package/dist/internal/frontmatter.js.map +1 -0
  30. package/dist/internal/proactive-curator-helpers.d.ts +171 -0
  31. package/dist/internal/proactive-curator-helpers.d.ts.map +1 -0
  32. package/dist/internal/proactive-curator-helpers.js +162 -0
  33. package/dist/internal/proactive-curator-helpers.js.map +1 -0
  34. package/dist/mcp/document-tools.d.ts +144 -0
  35. package/dist/mcp/document-tools.d.ts.map +1 -0
  36. package/dist/mcp/document-tools.js +319 -0
  37. package/dist/mcp/document-tools.js.map +1 -0
  38. package/dist/mcp/index.d.ts +34 -0
  39. package/dist/mcp/index.d.ts.map +1 -0
  40. package/dist/mcp/index.js +29 -0
  41. package/dist/mcp/index.js.map +1 -0
  42. package/dist/mcp/install.d.ts +72 -0
  43. package/dist/mcp/install.d.ts.map +1 -0
  44. package/dist/mcp/install.js +92 -0
  45. package/dist/mcp/install.js.map +1 -0
  46. package/dist/mcp/memory-tools.d.ts +101 -0
  47. package/dist/mcp/memory-tools.d.ts.map +1 -0
  48. package/dist/mcp/memory-tools.js +105 -0
  49. package/dist/mcp/memory-tools.js.map +1 -0
  50. package/dist/mcp/recall-tool.d.ts +52 -0
  51. package/dist/mcp/recall-tool.d.ts.map +1 -0
  52. package/dist/mcp/recall-tool.js +60 -0
  53. package/dist/mcp/recall-tool.js.map +1 -0
  54. package/dist/mcp/server.d.ts +32 -0
  55. package/dist/mcp/server.d.ts.map +1 -0
  56. package/dist/mcp/server.js +113 -0
  57. package/dist/mcp/server.js.map +1 -0
  58. package/dist/recall/engine.d.ts +38 -0
  59. package/dist/recall/engine.d.ts.map +1 -0
  60. package/dist/recall/engine.js +113 -0
  61. package/dist/recall/engine.js.map +1 -0
  62. package/dist/recall/index.d.ts +22 -0
  63. package/dist/recall/index.d.ts.map +1 -0
  64. package/dist/recall/index.js +20 -0
  65. package/dist/recall/index.js.map +1 -0
  66. package/dist/recall/intent.d.ts +24 -0
  67. package/dist/recall/intent.d.ts.map +1 -0
  68. package/dist/recall/intent.js +95 -0
  69. package/dist/recall/intent.js.map +1 -0
  70. package/dist/recall/render.d.ts +11 -0
  71. package/dist/recall/render.d.ts.map +1 -0
  72. package/dist/recall/render.js +23 -0
  73. package/dist/recall/render.js.map +1 -0
  74. package/dist/recall/types.d.ts +72 -0
  75. package/dist/recall/types.d.ts.map +1 -0
  76. package/dist/recall/types.js +2 -0
  77. package/dist/recall/types.js.map +1 -0
  78. package/dist/sessionArchive/adapters/claude-code.d.ts +3 -0
  79. package/dist/sessionArchive/adapters/claude-code.d.ts.map +1 -0
  80. package/dist/sessionArchive/adapters/claude-code.js +276 -0
  81. package/dist/sessionArchive/adapters/claude-code.js.map +1 -0
  82. package/dist/sessionArchive/adapters/claude-desktop.d.ts +3 -0
  83. package/dist/sessionArchive/adapters/claude-desktop.d.ts.map +1 -0
  84. package/dist/sessionArchive/adapters/claude-desktop.js +234 -0
  85. package/dist/sessionArchive/adapters/claude-desktop.js.map +1 -0
  86. package/dist/sessionArchive/adapters/codex.d.ts +3 -0
  87. package/dist/sessionArchive/adapters/codex.d.ts.map +1 -0
  88. package/dist/sessionArchive/adapters/codex.js +322 -0
  89. package/dist/sessionArchive/adapters/codex.js.map +1 -0
  90. package/dist/sessionArchive/adapters/gemini.d.ts +3 -0
  91. package/dist/sessionArchive/adapters/gemini.d.ts.map +1 -0
  92. package/dist/sessionArchive/adapters/gemini.js +248 -0
  93. package/dist/sessionArchive/adapters/gemini.js.map +1 -0
  94. package/dist/sessionArchive/adapters/index.d.ts +5 -0
  95. package/dist/sessionArchive/adapters/index.d.ts.map +1 -0
  96. package/dist/sessionArchive/adapters/index.js +5 -0
  97. package/dist/sessionArchive/adapters/index.js.map +1 -0
  98. package/dist/sessionArchive/index.d.ts +9 -0
  99. package/dist/sessionArchive/index.d.ts.map +1 -0
  100. package/dist/sessionArchive/index.js +6 -0
  101. package/dist/sessionArchive/index.js.map +1 -0
  102. package/dist/sessionArchive/ingest.d.ts +68 -0
  103. package/dist/sessionArchive/ingest.d.ts.map +1 -0
  104. package/dist/sessionArchive/ingest.js +134 -0
  105. package/dist/sessionArchive/ingest.js.map +1 -0
  106. package/dist/sessionArchive/normalize.d.ts +15 -0
  107. package/dist/sessionArchive/normalize.d.ts.map +1 -0
  108. package/dist/sessionArchive/normalize.js +40 -0
  109. package/dist/sessionArchive/normalize.js.map +1 -0
  110. package/dist/sessionArchive/store.d.ts +118 -0
  111. package/dist/sessionArchive/store.d.ts.map +1 -0
  112. package/dist/sessionArchive/store.js +491 -0
  113. package/dist/sessionArchive/store.js.map +1 -0
  114. package/dist/sessionArchive/types.d.ts +124 -0
  115. package/dist/sessionArchive/types.d.ts.map +1 -0
  116. package/dist/sessionArchive/types.js +24 -0
  117. package/dist/sessionArchive/types.js.map +1 -0
  118. package/dist/sqlite/drift.d.ts +22 -0
  119. package/dist/sqlite/drift.d.ts.map +1 -0
  120. package/dist/sqlite/drift.js +69 -0
  121. package/dist/sqlite/drift.js.map +1 -0
  122. package/dist/sqlite/index.d.ts +22 -0
  123. package/dist/sqlite/index.d.ts.map +1 -0
  124. package/dist/sqlite/index.js +4 -0
  125. package/dist/sqlite/index.js.map +1 -0
  126. package/dist/sqlite/rebuild.d.ts +32 -0
  127. package/dist/sqlite/rebuild.d.ts.map +1 -0
  128. package/dist/sqlite/rebuild.js +80 -0
  129. package/dist/sqlite/rebuild.js.map +1 -0
  130. package/dist/sqlite/schema.d.ts +15 -0
  131. package/dist/sqlite/schema.d.ts.map +1 -0
  132. package/dist/sqlite/schema.js +41 -0
  133. package/dist/sqlite/schema.js.map +1 -0
  134. package/dist/sqlite/store.d.ts +49 -0
  135. package/dist/sqlite/store.d.ts.map +1 -0
  136. package/dist/sqlite/store.js +179 -0
  137. package/dist/sqlite/store.js.map +1 -0
  138. package/dist/sqlite/types.d.ts +57 -0
  139. package/dist/sqlite/types.d.ts.map +1 -0
  140. package/dist/sqlite/types.js +2 -0
  141. package/dist/sqlite/types.js.map +1 -0
  142. package/dist/vector/backend-brute.d.ts +38 -0
  143. package/dist/vector/backend-brute.d.ts.map +1 -0
  144. package/dist/vector/backend-brute.js +112 -0
  145. package/dist/vector/backend-brute.js.map +1 -0
  146. package/dist/vector/embedder.d.ts +59 -0
  147. package/dist/vector/embedder.d.ts.map +1 -0
  148. package/dist/vector/embedder.js +47 -0
  149. package/dist/vector/embedder.js.map +1 -0
  150. package/dist/vector/index.d.ts +24 -0
  151. package/dist/vector/index.d.ts.map +1 -0
  152. package/dist/vector/index.js +7 -0
  153. package/dist/vector/index.js.map +1 -0
  154. package/dist/vector/math.d.ts +21 -0
  155. package/dist/vector/math.d.ts.map +1 -0
  156. package/dist/vector/math.js +34 -0
  157. package/dist/vector/math.js.map +1 -0
  158. package/dist/vector/schema.d.ts +14 -0
  159. package/dist/vector/schema.d.ts.map +1 -0
  160. package/dist/vector/schema.js +24 -0
  161. package/dist/vector/schema.js.map +1 -0
  162. package/dist/vector/segment.d.ts +65 -0
  163. package/dist/vector/segment.d.ts.map +1 -0
  164. package/dist/vector/segment.js +72 -0
  165. package/dist/vector/segment.js.map +1 -0
  166. package/dist/vector/session.d.ts +90 -0
  167. package/dist/vector/session.d.ts.map +1 -0
  168. package/dist/vector/session.js +242 -0
  169. package/dist/vector/session.js.map +1 -0
  170. package/dist/vector/store.d.ts +69 -0
  171. package/dist/vector/store.d.ts.map +1 -0
  172. package/dist/vector/store.js +131 -0
  173. package/dist/vector/store.js.map +1 -0
  174. package/dist/vector/types.d.ts +109 -0
  175. package/dist/vector/types.d.ts.map +1 -0
  176. package/dist/vector/types.js +24 -0
  177. package/dist/vector/types.js.map +1 -0
  178. package/package.json +96 -0
  179. package/scripts/mcp-stdio.mjs +143 -0
  180. package/scripts/rebuild-memory-sqlite.mjs +39 -0
  181. package/scripts/rebuild-memory-vector.mjs +64 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * `vector` namespace types — semantic similarity over markdown memories.
3
+ *
4
+ * Phase 11c, operator decisions (2026-05-29 afternoon):
5
+ *
6
+ * - **Decision 1 (embedder)** — host-injected `EmbedFn`. A default local
7
+ * embedder (`createLocalEmbedder`, `@huggingface/transformers` MiniLM)
8
+ * ships with this package and loads lazily on first use; operators can
9
+ * swap it for an API embedder by passing their own `EmbedFn`.
10
+ * - **Decision 2 (backend)** — default is in-process brute-force cosine
11
+ * (`BruteForceBackend`), no native vector engine. The `VectorBackend`
12
+ * interface keeps sqlite-vec / Qdrant as drop-in upgrades once the
13
+ * corpus outgrows brute force (≈10k+ vectors). This intentionally
14
+ * deviates from the design doc's original sqlite-vec default — see
15
+ * `docs/memory-extended-design.md` §vector namespace revision.
16
+ * - **Decision 3 (storage)** — vectors live in the *same* `memory.sqlite`
17
+ * as a plain `memory_vectors` table (Float32 BLOB). No extension, no
18
+ * second file; one DB, one rebuild path.
19
+ * - **Decision 5 (scope)** — `source` discriminates `"memory"` vs
20
+ * `"session-archive"`. This cycle populates `"memory"` only; the
21
+ * session-archive column is plumbing for a later cycle.
22
+ */
23
+ /** A dense embedding. Either form is accepted; the store normalizes to Float32Array. */
24
+ export type EmbedVector = Float32Array | readonly number[];
25
+ /**
26
+ * Whether a text is being embedded as an indexed document (`passage`) or as
27
+ * a search query (`query`). Most embedders ignore this, but asymmetric
28
+ * retrieval models (the e5 family) require a different instruction prefix
29
+ * for each side. `undefined` is treated as `passage` (the indexing path).
30
+ */
31
+ export type EmbedKind = "query" | "passage";
32
+ /**
33
+ * Host-supplied embedding function: text in, dense vector out.
34
+ *
35
+ * Mirrors the `LLMJudge` / `TranscriptAdapter` host-injection pattern —
36
+ * the namespace does not hard-depend on any particular embedding runtime.
37
+ * The default `createLocalEmbedder()` satisfies this signature; an OpenAI /
38
+ * Voyage adapter would too.
39
+ *
40
+ * The optional `kind` lets asymmetric models (e5) prefix query vs passage
41
+ * differently. Indexing call sites omit it (→ passage); only the recall
42
+ * query path passes `"query"`. Symmetric models ignore the argument.
43
+ *
44
+ * Implementations should return a vector of stable dimensionality for a
45
+ * given configuration. The store records each vector's `dim` and refuses
46
+ * to compare across mismatched dimensions (a model change is surfaced as a
47
+ * rebuild signal rather than silently producing garbage similarities).
48
+ */
49
+ export type EmbedFn = (text: string, kind?: EmbedKind) => Promise<EmbedVector>;
50
+ /** Which corpus a vector belongs to. `memory` is populated this cycle. */
51
+ export type VectorSource = "memory" | "session-archive";
52
+ /** One stored vector row. */
53
+ export interface VectorRow {
54
+ readonly id: string;
55
+ readonly source: VectorSource;
56
+ readonly dim: number;
57
+ readonly vector: Float32Array;
58
+ }
59
+ /** A search result: id + cosine similarity (1 = identical direction). */
60
+ export interface VectorSearchHit {
61
+ readonly id: string;
62
+ readonly source: VectorSource;
63
+ readonly score: number;
64
+ }
65
+ /** Options for a vector search. */
66
+ export interface VectorSearchOptions {
67
+ /** Max hits to return. Default 10. */
68
+ readonly k?: number;
69
+ /** Restrict to one source. Omit to search all sources. */
70
+ readonly source?: VectorSource;
71
+ /**
72
+ * Optional id allowlist — restrict the search to these ids. Used by the
73
+ * `recall` engine to apply a SQLite hard-filter before semantic rerank.
74
+ * Omit to search the whole index.
75
+ */
76
+ readonly ids?: ReadonlySet<string>;
77
+ }
78
+ /**
79
+ * Pluggable storage + similarity backend.
80
+ *
81
+ * The default `BruteForceBackend` persists vectors in a SQLite table and
82
+ * computes cosine in JavaScript. A future `SqliteVecBackend` or
83
+ * `QdrantBackend` implements the same interface; `MemoryVectorStore` is
84
+ * backend-agnostic.
85
+ */
86
+ export interface VectorBackend {
87
+ /** Insert or replace a vector for (id, source). */
88
+ upsert(row: VectorRow): void;
89
+ /** Remove a vector. Returns true if a row was deleted. */
90
+ delete(id: string, source?: VectorSource): boolean;
91
+ /** Brute-force / ANN search for the query vector. Synchronous. */
92
+ search(query: Float32Array, options?: VectorSearchOptions): readonly VectorSearchHit[];
93
+ /** Ids currently indexed (for drift / rebuild bookkeeping). */
94
+ listIds(source?: VectorSource): readonly string[];
95
+ /** Number of vectors indexed. */
96
+ count(source?: VectorSource): number;
97
+ /** Release any held resources (DB handle). */
98
+ close(): void;
99
+ }
100
+ /** Result of {@link MemoryVectorStore.rebuild}. */
101
+ export interface VectorRebuildResult {
102
+ /** Memories embedded + written. */
103
+ readonly indexed: number;
104
+ /** Memories skipped (empty text after trim). */
105
+ readonly skipped: number;
106
+ /** Stale vectors removed (id present in index but no longer in source). */
107
+ readonly pruned: number;
108
+ }
109
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/vector/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,wFAAwF;AACxF,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,SAAS,MAAM,EAAE,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAE5C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AAE/E,0EAA0E;AAC1E,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,iBAAiB,CAAC;AAExD,6BAA6B;AAC7B,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;CAC/B;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,mCAAmC;AACnC,MAAM,WAAW,mBAAmB;IAClC,sCAAsC;IACtC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACpC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,MAAM,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC;IACnD,kEAAkE;IAClE,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,SAAS,eAAe,EAAE,CAAC;IACvF,+DAA+D;IAC/D,OAAO,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,SAAS,MAAM,EAAE,CAAC;IAClD,iCAAiC;IACjC,KAAK,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IACrC,8CAA8C;IAC9C,KAAK,IAAI,IAAI,CAAC;CACf;AAED,mDAAmD;AACnD,MAAM,WAAW,mBAAmB;IAClC,mCAAmC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * `vector` namespace types — semantic similarity over markdown memories.
3
+ *
4
+ * Phase 11c, operator decisions (2026-05-29 afternoon):
5
+ *
6
+ * - **Decision 1 (embedder)** — host-injected `EmbedFn`. A default local
7
+ * embedder (`createLocalEmbedder`, `@huggingface/transformers` MiniLM)
8
+ * ships with this package and loads lazily on first use; operators can
9
+ * swap it for an API embedder by passing their own `EmbedFn`.
10
+ * - **Decision 2 (backend)** — default is in-process brute-force cosine
11
+ * (`BruteForceBackend`), no native vector engine. The `VectorBackend`
12
+ * interface keeps sqlite-vec / Qdrant as drop-in upgrades once the
13
+ * corpus outgrows brute force (≈10k+ vectors). This intentionally
14
+ * deviates from the design doc's original sqlite-vec default — see
15
+ * `docs/memory-extended-design.md` §vector namespace revision.
16
+ * - **Decision 3 (storage)** — vectors live in the *same* `memory.sqlite`
17
+ * as a plain `memory_vectors` table (Float32 BLOB). No extension, no
18
+ * second file; one DB, one rebuild path.
19
+ * - **Decision 5 (scope)** — `source` discriminates `"memory"` vs
20
+ * `"session-archive"`. This cycle populates `"memory"` only; the
21
+ * session-archive column is plumbing for a later cycle.
22
+ */
23
+ export {};
24
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/vector/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG"}
package/package.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "name": "@vortex-os/memory-extended",
3
+ "version": "0.5.1",
4
+ "description": "Add-on cluster — extended memory namespaces (sqlite, vector, sessionArchive, recall, consolidate) layered on @vortex-os/base.",
5
+ "license": "MIT",
6
+ "author": "vortex-os-project",
7
+ "homepage": "https://github.com/vortex-os-project/vortex#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/vortex-os-project/vortex.git",
11
+ "directory": "modules/memory-extended"
12
+ },
13
+ "type": "module",
14
+ "main": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "default": "./dist/index.js"
20
+ },
21
+ "./sessionArchive": {
22
+ "types": "./dist/sessionArchive/index.d.ts",
23
+ "default": "./dist/sessionArchive/index.js"
24
+ },
25
+ "./consolidate": {
26
+ "types": "./dist/consolidate/index.d.ts",
27
+ "default": "./dist/consolidate/index.js"
28
+ },
29
+ "./sqlite": {
30
+ "types": "./dist/sqlite/index.d.ts",
31
+ "default": "./dist/sqlite/index.js"
32
+ },
33
+ "./vector": {
34
+ "types": "./dist/vector/index.d.ts",
35
+ "default": "./dist/vector/index.js"
36
+ },
37
+ "./recall": {
38
+ "types": "./dist/recall/index.d.ts",
39
+ "default": "./dist/recall/index.js"
40
+ },
41
+ "./mcp": {
42
+ "types": "./dist/mcp/index.d.ts",
43
+ "default": "./dist/mcp/index.js"
44
+ }
45
+ },
46
+ "files": [
47
+ "dist",
48
+ "scripts/rebuild-memory-sqlite.mjs",
49
+ "scripts/rebuild-memory-vector.mjs",
50
+ "scripts/mcp-stdio.mjs",
51
+ "README.md"
52
+ ],
53
+ "bin": {
54
+ "rebuild-memory-sqlite": "scripts/rebuild-memory-sqlite.mjs",
55
+ "rebuild-memory-vector": "scripts/rebuild-memory-vector.mjs",
56
+ "vortex-mcp-recall": "scripts/mcp-stdio.mjs"
57
+ },
58
+ "scripts": {
59
+ "build": "tsc -p tsconfig.json",
60
+ "typecheck": "tsc -p tsconfig.json --noEmit",
61
+ "verify": "node scripts/verify.mjs",
62
+ "prepublishOnly": "npm run build"
63
+ },
64
+ "dependencies": {
65
+ "yaml": "^2.6.0"
66
+ },
67
+ "_releaseNote": "@vortex-os/base (^0.3.0 || ^0.4.0) is the only @vortex-os peer; it is published. The proactive-curator surface this add-on used is inlined (src/internal/proactive-curator-helpers.ts), so no separate @vortex-os/proactive-curator dependency is needed. better-sqlite3 / classic-level are native peers.",
68
+ "peerDependencies": {
69
+ "@vortex-os/base": "^0.3.0 || ^0.4.0",
70
+ "better-sqlite3": "^12.0.0",
71
+ "classic-level": "^3.0.0"
72
+ },
73
+ "peerDependenciesMeta": {
74
+ "@vortex-os/base": {
75
+ "optional": false
76
+ },
77
+ "better-sqlite3": {
78
+ "optional": false
79
+ },
80
+ "classic-level": {
81
+ "optional": true
82
+ }
83
+ },
84
+ "optionalDependencies": {
85
+ "@huggingface/transformers": "^3.0.0",
86
+ "@modelcontextprotocol/sdk": "^1.21.0"
87
+ },
88
+ "devDependencies": {
89
+ "@types/better-sqlite3": "^7.6.13",
90
+ "better-sqlite3": "^12.10.0",
91
+ "classic-level": "^3.0.0"
92
+ },
93
+ "publishConfig": {
94
+ "access": "public"
95
+ }
96
+ }
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * vortex-mcp-recall — MCP recall surface for memory-extended.
4
+ *
5
+ * Two modes:
6
+ *
7
+ * 1. Serve (default) — run the stdio server. Usually launched by an MCP host
8
+ * such as Claude Desktop, not by hand:
9
+ * npx vortex-mcp-recall [--data-dir <path>]
10
+ * Resolves the data dir (--data-dir flag, VORTEX_DATA_DIR, or cwd), builds
11
+ * the local embedder once, opens the recall stores under <dataDir>/_indexes/,
12
+ * and serves MCP over stdio. NEVER writes to stdout (the protocol channel);
13
+ * diagnostics go to stderr. Requires the optional `@modelcontextprotocol/sdk`.
14
+ *
15
+ * 2. Install — register this server in Claude Desktop's config (slice 2):
16
+ * npx vortex-mcp-recall install --data-dir <path> [options]
17
+ * Merges our one server entry into claude_desktop_config.json WITHOUT
18
+ * touching any other server. Options:
19
+ * --data-dir <path> (required) instance data dir
20
+ * --config <path> override the config file location
21
+ * --key <name> server key (default "vortex-recall")
22
+ * --command <cmd> launcher (default "npx")
23
+ * --dry-run show what would change; write nothing
24
+ * --print print the merged config to stdout; write nothing
25
+ */
26
+ import { join } from "node:path";
27
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, copyFileSync } from "node:fs";
28
+ import { vector, mcp } from "../dist/index.js";
29
+
30
+ function getFlag(argv, name) {
31
+ const i = argv.indexOf(name);
32
+ return i >= 0 && argv[i + 1] ? argv[i + 1] : undefined;
33
+ }
34
+ function hasFlag(argv, name) {
35
+ return argv.includes(name);
36
+ }
37
+
38
+ function resolveDataDir(argv, env) {
39
+ return getFlag(argv, "--data-dir") ?? env.VORTEX_DATA_DIR?.trim() ?? process.cwd();
40
+ }
41
+
42
+ function resolveDbPath(dataDir) {
43
+ return join(dataDir, "_indexes", "memory.sqlite");
44
+ }
45
+
46
+ // ── serve mode ──────────────────────────────────────────────────────────────
47
+ async function serve(argv, env) {
48
+ const dataDir = resolveDataDir(argv, env);
49
+ const dbPath = resolveDbPath(dataDir);
50
+
51
+ // Build the embedder once: the model load is the only heavy cost; reusing the
52
+ // returned function keeps every subsequent recall fast.
53
+ const embed = vector.createLocalEmbedder();
54
+ const server = await mcp.createRecallServer({ embed, dbPath, dataDir });
55
+
56
+ // The transport is also part of the optional SDK — resolved at runtime.
57
+ const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
58
+ await server.connect(new StdioServerTransport());
59
+
60
+ process.stderr.write(`[vortex-mcp-recall] recall server ready (db: ${dbPath})\n`);
61
+ }
62
+
63
+ // ── install mode ────────────────────────────────────────────────────────────
64
+ function install(argv, env) {
65
+ const dataDir = getFlag(argv, "--data-dir") ?? env.VORTEX_DATA_DIR?.trim();
66
+ if (!dataDir) {
67
+ process.stderr.write(
68
+ "[vortex-mcp-recall] install: --data-dir <path> is required " +
69
+ "(the absolute path to your instance data directory).\n",
70
+ );
71
+ process.exit(1);
72
+ }
73
+
74
+ const configPath = getFlag(argv, "--config") ?? mcp.claudeDesktopConfigPath();
75
+ const key = getFlag(argv, "--key") ?? mcp.DEFAULT_SERVER_KEY;
76
+ const command = getFlag(argv, "--command");
77
+ const dryRun = hasFlag(argv, "--dry-run");
78
+ const printOnly = hasFlag(argv, "--print");
79
+
80
+ const entry = mcp.buildRecallServerEntry(command ? { dataDir, command } : { dataDir });
81
+
82
+ // Read + parse existing config (empty/missing → fresh {}; malformed → abort).
83
+ let existingText = null;
84
+ if (existsSync(configPath)) {
85
+ existingText = readFileSync(configPath, "utf8");
86
+ }
87
+ let existingConfig;
88
+ try {
89
+ existingConfig = mcp.parseExistingConfig(existingText);
90
+ } catch (e) {
91
+ process.stderr.write(`[vortex-mcp-recall] install: ${e.message}\n config: ${configPath}\n`);
92
+ process.exit(1);
93
+ }
94
+
95
+ const { config, action, preservedKeys } = mcp.mergeServerEntry(existingConfig, entry, key);
96
+ const serialized = mcp.serializeConfig(config);
97
+
98
+ if (printOnly) {
99
+ process.stdout.write(serialized);
100
+ return;
101
+ }
102
+
103
+ if (dryRun) {
104
+ process.stderr.write(
105
+ `[vortex-mcp-recall] install --dry-run\n` +
106
+ ` config: ${configPath}\n` +
107
+ ` action: ${action} server "${key}"\n` +
108
+ ` command: ${entry.command} ${entry.args.join(" ")}\n` +
109
+ ` preserved: ${preservedKeys.length ? preservedKeys.join(", ") : "(none)"}\n` +
110
+ ` (no files written)\n`,
111
+ );
112
+ return;
113
+ }
114
+
115
+ // Write: ensure dir, back up an existing file, then write merged config.
116
+ mkdirSync(join(configPath, ".."), { recursive: true });
117
+ if (existsSync(configPath)) {
118
+ copyFileSync(configPath, `${configPath}.vortex-backup`);
119
+ }
120
+ writeFileSync(configPath, serialized, "utf8");
121
+
122
+ process.stderr.write(
123
+ `[vortex-mcp-recall] installed: ${action} server "${key}"\n` +
124
+ ` config: ${configPath}\n` +
125
+ ` command: ${entry.command} ${entry.args.join(" ")}\n` +
126
+ ` preserved: ${preservedKeys.length ? preservedKeys.join(", ") : "(none)"}\n` +
127
+ ` Restart Claude Desktop to load the recall tool.\n`,
128
+ );
129
+ }
130
+
131
+ async function main() {
132
+ const argv = process.argv.slice(2);
133
+ if (argv[0] === "install") {
134
+ install(argv.slice(1), process.env);
135
+ return;
136
+ }
137
+ await serve(argv, process.env);
138
+ }
139
+
140
+ main().catch((err) => {
141
+ process.stderr.write(`[vortex-mcp-recall] fatal: ${err?.message ?? err}\n`);
142
+ process.exit(1);
143
+ });
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ // One-shot CLI — rebuild the memory sqlite index from data/_memory/*.md.
3
+ // Usage from a vortex instance root:
4
+ // npx rebuild-memory-sqlite # default paths
5
+ // npx rebuild-memory-sqlite --memory-dir <p> --db <p>
6
+ //
7
+ // Operator decision 4 (2026-05-29): rebuild is a one-shot CLI, not a
8
+ // filesystem watcher. Watcher waits until Phase 11c lands and we know
9
+ // whether reactive update is needed for the recall pipeline.
10
+
11
+ import { resolve } from "node:path";
12
+ import { MemorySqliteStore, rebuildFromMemoryDir } from "../dist/sqlite/index.js";
13
+
14
+ const args = process.argv.slice(2);
15
+ let memoryDir = resolve(process.cwd(), "data/_memory");
16
+ let dbPath = resolve(process.cwd(), "data/_indexes/memory.sqlite");
17
+ for (let i = 0; i < args.length; i++) {
18
+ if (args[i] === "--memory-dir" && i + 1 < args.length) {
19
+ memoryDir = resolve(args[++i]);
20
+ } else if (args[i] === "--db" && i + 1 < args.length) {
21
+ dbPath = resolve(args[++i]);
22
+ } else if (args[i] === "--help" || args[i] === "-h") {
23
+ console.log("Usage: rebuild-memory-sqlite [--memory-dir <p>] [--db <p>]");
24
+ process.exit(0);
25
+ }
26
+ }
27
+
28
+ console.log(`[rebuild] memory dir: ${memoryDir}`);
29
+ console.log(`[rebuild] sqlite db: ${dbPath}`);
30
+
31
+ const store = new MemorySqliteStore(dbPath);
32
+ try {
33
+ const result = await rebuildFromMemoryDir(store, memoryDir);
34
+ console.log(
35
+ `[rebuild] scanned=${result.scanned} upserted=${result.upserted} skipped=${result.skipped}`,
36
+ );
37
+ } finally {
38
+ store.close();
39
+ }
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+ // One-shot CLI — rebuild the memory vector index (and optionally session vectors).
3
+ // Usage from a vortex instance root:
4
+ // npx rebuild-memory-vector # memory vectors only
5
+ // npx rebuild-memory-vector --sessions # memory + session-archive vectors
6
+ // npx rebuild-memory-vector --sessions-only # session vectors only
7
+ // npx rebuild-memory-vector --data-dir <p> --db <p>
8
+ //
9
+ // Phase 11c + follow-up (2026-05-29): memory and session vectors share the
10
+ // same memory.sqlite (operator decision 3). Session vectors are topic chunks
11
+ // found by embedding-similarity segmentation. The default local embedder
12
+ // downloads its model (~470 MB multilingual) on first run and caches it.
13
+ // Run `rebuild-memory-sqlite` first if the sqlite store is empty/stale.
14
+
15
+ import { resolve, join } from "node:path";
16
+ import { MemorySqliteStore } from "../dist/sqlite/index.js";
17
+ import { MemoryVectorStore, createLocalEmbedder } from "../dist/vector/index.js";
18
+ import { SessionArchiveStore } from "../dist/sessionArchive/index.js";
19
+
20
+ const args = process.argv.slice(2);
21
+ let dataDir = resolve(process.cwd(), "data");
22
+ let dbPath = null;
23
+ let doSessions = false;
24
+ let sessionsOnly = false;
25
+ for (let i = 0; i < args.length; i++) {
26
+ if (args[i] === "--data-dir" && i + 1 < args.length) dataDir = resolve(args[++i]);
27
+ else if (args[i] === "--db" && i + 1 < args.length) dbPath = resolve(args[++i]);
28
+ else if (args[i] === "--sessions") doSessions = true;
29
+ else if (args[i] === "--sessions-only") { doSessions = true; sessionsOnly = true; }
30
+ else if (args[i] === "--help" || args[i] === "-h") {
31
+ console.log("Usage: rebuild-memory-vector [--sessions | --sessions-only] [--data-dir <p>] [--db <p>]");
32
+ process.exit(0);
33
+ }
34
+ }
35
+ if (!dbPath) dbPath = join(dataDir, "_indexes", "memory.sqlite");
36
+
37
+ console.log(`[rebuild-vector] data dir: ${dataDir}`);
38
+ console.log(`[rebuild-vector] sqlite db: ${dbPath}`);
39
+ console.log(`[rebuild-vector] embedder: local (downloads model on first run)`);
40
+
41
+ const embed = createLocalEmbedder();
42
+ const vector = new MemoryVectorStore({ db: dbPath });
43
+ try {
44
+ if (!sessionsOnly) {
45
+ const sqlite = new MemorySqliteStore(dbPath);
46
+ try {
47
+ const r = await vector.rebuild(sqlite, embed);
48
+ console.log(`[rebuild-vector] memory: indexed=${r.indexed} skipped=${r.skipped} pruned=${r.pruned}`);
49
+ } finally {
50
+ sqlite.close();
51
+ }
52
+ }
53
+ if (doSessions) {
54
+ const sessions = new SessionArchiveStore(dataDir);
55
+ try {
56
+ const r = await vector.rebuildSessions(sessions, embed);
57
+ console.log(`[rebuild-vector] sessions: sessions=${r.sessions} chunks=${r.chunks} pruned=${r.prunedSessions}`);
58
+ } finally {
59
+ sessions.close();
60
+ }
61
+ }
62
+ } finally {
63
+ vector.close();
64
+ }