stellar-memory 0.5.0

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 (197) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +362 -0
  3. package/dist/api/routes/analytics.d.ts +15 -0
  4. package/dist/api/routes/analytics.js +131 -0
  5. package/dist/api/routes/analytics.js.map +1 -0
  6. package/dist/api/routes/conflicts.d.ts +12 -0
  7. package/dist/api/routes/conflicts.js +67 -0
  8. package/dist/api/routes/conflicts.js.map +1 -0
  9. package/dist/api/routes/consolidation.d.ts +11 -0
  10. package/dist/api/routes/consolidation.js +63 -0
  11. package/dist/api/routes/consolidation.js.map +1 -0
  12. package/dist/api/routes/constellation.d.ts +4 -0
  13. package/dist/api/routes/constellation.js +84 -0
  14. package/dist/api/routes/constellation.js.map +1 -0
  15. package/dist/api/routes/memories.d.ts +4 -0
  16. package/dist/api/routes/memories.js +219 -0
  17. package/dist/api/routes/memories.js.map +1 -0
  18. package/dist/api/routes/observations.d.ts +10 -0
  19. package/dist/api/routes/observations.js +42 -0
  20. package/dist/api/routes/observations.js.map +1 -0
  21. package/dist/api/routes/orbit.d.ts +4 -0
  22. package/dist/api/routes/orbit.js +71 -0
  23. package/dist/api/routes/orbit.js.map +1 -0
  24. package/dist/api/routes/projects.d.ts +15 -0
  25. package/dist/api/routes/projects.js +121 -0
  26. package/dist/api/routes/projects.js.map +1 -0
  27. package/dist/api/routes/scan.d.ts +4 -0
  28. package/dist/api/routes/scan.js +403 -0
  29. package/dist/api/routes/scan.js.map +1 -0
  30. package/dist/api/routes/sun.d.ts +4 -0
  31. package/dist/api/routes/sun.js +43 -0
  32. package/dist/api/routes/sun.js.map +1 -0
  33. package/dist/api/routes/system.d.ts +4 -0
  34. package/dist/api/routes/system.js +70 -0
  35. package/dist/api/routes/system.js.map +1 -0
  36. package/dist/api/routes/temporal.d.ts +13 -0
  37. package/dist/api/routes/temporal.js +82 -0
  38. package/dist/api/routes/temporal.js.map +1 -0
  39. package/dist/api/server.d.ts +2 -0
  40. package/dist/api/server.js +99 -0
  41. package/dist/api/server.js.map +1 -0
  42. package/dist/api/websocket.d.ts +53 -0
  43. package/dist/api/websocket.js +168 -0
  44. package/dist/api/websocket.js.map +1 -0
  45. package/dist/cli/index.d.ts +12 -0
  46. package/dist/cli/index.js +35 -0
  47. package/dist/cli/index.js.map +1 -0
  48. package/dist/cli/init.d.ts +10 -0
  49. package/dist/cli/init.js +163 -0
  50. package/dist/cli/init.js.map +1 -0
  51. package/dist/engine/analytics.d.ts +93 -0
  52. package/dist/engine/analytics.js +437 -0
  53. package/dist/engine/analytics.js.map +1 -0
  54. package/dist/engine/conflict.d.ts +54 -0
  55. package/dist/engine/conflict.js +322 -0
  56. package/dist/engine/conflict.js.map +1 -0
  57. package/dist/engine/consolidation.d.ts +83 -0
  58. package/dist/engine/consolidation.js +368 -0
  59. package/dist/engine/consolidation.js.map +1 -0
  60. package/dist/engine/constellation.d.ts +66 -0
  61. package/dist/engine/constellation.js +382 -0
  62. package/dist/engine/constellation.js.map +1 -0
  63. package/dist/engine/corona.d.ts +53 -0
  64. package/dist/engine/corona.js +181 -0
  65. package/dist/engine/corona.js.map +1 -0
  66. package/dist/engine/embedding.d.ts +44 -0
  67. package/dist/engine/embedding.js +168 -0
  68. package/dist/engine/embedding.js.map +1 -0
  69. package/dist/engine/gravity.d.ts +63 -0
  70. package/dist/engine/gravity.js +121 -0
  71. package/dist/engine/gravity.js.map +1 -0
  72. package/dist/engine/multiproject.d.ts +75 -0
  73. package/dist/engine/multiproject.js +241 -0
  74. package/dist/engine/multiproject.js.map +1 -0
  75. package/dist/engine/observation.d.ts +82 -0
  76. package/dist/engine/observation.js +357 -0
  77. package/dist/engine/observation.js.map +1 -0
  78. package/dist/engine/orbit.d.ts +91 -0
  79. package/dist/engine/orbit.js +249 -0
  80. package/dist/engine/orbit.js.map +1 -0
  81. package/dist/engine/planet.d.ts +64 -0
  82. package/dist/engine/planet.js +432 -0
  83. package/dist/engine/planet.js.map +1 -0
  84. package/dist/engine/procedural.d.ts +71 -0
  85. package/dist/engine/procedural.js +259 -0
  86. package/dist/engine/procedural.js.map +1 -0
  87. package/dist/engine/quality.d.ts +48 -0
  88. package/dist/engine/quality.js +245 -0
  89. package/dist/engine/quality.js.map +1 -0
  90. package/dist/engine/repository.d.ts +79 -0
  91. package/dist/engine/repository.js +13 -0
  92. package/dist/engine/repository.js.map +1 -0
  93. package/dist/engine/sun.d.ts +61 -0
  94. package/dist/engine/sun.js +240 -0
  95. package/dist/engine/sun.js.map +1 -0
  96. package/dist/engine/temporal.d.ts +67 -0
  97. package/dist/engine/temporal.js +283 -0
  98. package/dist/engine/temporal.js.map +1 -0
  99. package/dist/engine/types.d.ts +179 -0
  100. package/dist/engine/types.js +27 -0
  101. package/dist/engine/types.js.map +1 -0
  102. package/dist/index.d.ts +2 -0
  103. package/dist/index.js +60 -0
  104. package/dist/index.js.map +1 -0
  105. package/dist/mcp/connector-registry.d.ts +20 -0
  106. package/dist/mcp/connector-registry.js +35 -0
  107. package/dist/mcp/connector-registry.js.map +1 -0
  108. package/dist/mcp/server.d.ts +13 -0
  109. package/dist/mcp/server.js +242 -0
  110. package/dist/mcp/server.js.map +1 -0
  111. package/dist/mcp/tools/daemon-tool.d.ts +16 -0
  112. package/dist/mcp/tools/daemon-tool.js +58 -0
  113. package/dist/mcp/tools/daemon-tool.js.map +1 -0
  114. package/dist/mcp/tools/ingestion-tools.d.ts +20 -0
  115. package/dist/mcp/tools/ingestion-tools.js +34 -0
  116. package/dist/mcp/tools/ingestion-tools.js.map +1 -0
  117. package/dist/mcp/tools/memory-tools.d.ts +122 -0
  118. package/dist/mcp/tools/memory-tools.js +1037 -0
  119. package/dist/mcp/tools/memory-tools.js.map +1 -0
  120. package/dist/scanner/cloud/github.d.ts +34 -0
  121. package/dist/scanner/cloud/github.js +260 -0
  122. package/dist/scanner/cloud/github.js.map +1 -0
  123. package/dist/scanner/cloud/google-drive.d.ts +30 -0
  124. package/dist/scanner/cloud/google-drive.js +289 -0
  125. package/dist/scanner/cloud/google-drive.js.map +1 -0
  126. package/dist/scanner/cloud/notion.d.ts +33 -0
  127. package/dist/scanner/cloud/notion.js +231 -0
  128. package/dist/scanner/cloud/notion.js.map +1 -0
  129. package/dist/scanner/cloud/slack.d.ts +38 -0
  130. package/dist/scanner/cloud/slack.js +282 -0
  131. package/dist/scanner/cloud/slack.js.map +1 -0
  132. package/dist/scanner/cloud/types.d.ts +73 -0
  133. package/dist/scanner/cloud/types.js +9 -0
  134. package/dist/scanner/cloud/types.js.map +1 -0
  135. package/dist/scanner/index.d.ts +35 -0
  136. package/dist/scanner/index.js +420 -0
  137. package/dist/scanner/index.js.map +1 -0
  138. package/dist/scanner/local/filesystem.d.ts +33 -0
  139. package/dist/scanner/local/filesystem.js +203 -0
  140. package/dist/scanner/local/filesystem.js.map +1 -0
  141. package/dist/scanner/local/git.d.ts +24 -0
  142. package/dist/scanner/local/git.js +161 -0
  143. package/dist/scanner/local/git.js.map +1 -0
  144. package/dist/scanner/local/parsers/code.d.ts +3 -0
  145. package/dist/scanner/local/parsers/code.js +127 -0
  146. package/dist/scanner/local/parsers/code.js.map +1 -0
  147. package/dist/scanner/local/parsers/index.d.ts +11 -0
  148. package/dist/scanner/local/parsers/index.js +24 -0
  149. package/dist/scanner/local/parsers/index.js.map +1 -0
  150. package/dist/scanner/local/parsers/json-parser.d.ts +3 -0
  151. package/dist/scanner/local/parsers/json-parser.js +117 -0
  152. package/dist/scanner/local/parsers/json-parser.js.map +1 -0
  153. package/dist/scanner/local/parsers/markdown.d.ts +3 -0
  154. package/dist/scanner/local/parsers/markdown.js +120 -0
  155. package/dist/scanner/local/parsers/markdown.js.map +1 -0
  156. package/dist/scanner/local/parsers/text.d.ts +3 -0
  157. package/dist/scanner/local/parsers/text.js +41 -0
  158. package/dist/scanner/local/parsers/text.js.map +1 -0
  159. package/dist/scanner/metadata-scanner.d.ts +67 -0
  160. package/dist/scanner/metadata-scanner.js +356 -0
  161. package/dist/scanner/metadata-scanner.js.map +1 -0
  162. package/dist/scanner/types.d.ts +47 -0
  163. package/dist/scanner/types.js +19 -0
  164. package/dist/scanner/types.js.map +1 -0
  165. package/dist/service/daemon.d.ts +23 -0
  166. package/dist/service/daemon.js +105 -0
  167. package/dist/service/daemon.js.map +1 -0
  168. package/dist/service/scheduler.d.ts +73 -0
  169. package/dist/service/scheduler.js +281 -0
  170. package/dist/service/scheduler.js.map +1 -0
  171. package/dist/storage/database.d.ts +10 -0
  172. package/dist/storage/database.js +265 -0
  173. package/dist/storage/database.js.map +1 -0
  174. package/dist/storage/queries.d.ts +85 -0
  175. package/dist/storage/queries.js +865 -0
  176. package/dist/storage/queries.js.map +1 -0
  177. package/dist/storage/sqlite-repository.d.ts +32 -0
  178. package/dist/storage/sqlite-repository.js +68 -0
  179. package/dist/storage/sqlite-repository.js.map +1 -0
  180. package/dist/storage/vec.d.ts +62 -0
  181. package/dist/storage/vec.js +111 -0
  182. package/dist/storage/vec.js.map +1 -0
  183. package/dist/utils/config.d.ts +5 -0
  184. package/dist/utils/config.js +60 -0
  185. package/dist/utils/config.js.map +1 -0
  186. package/dist/utils/logger.d.ts +36 -0
  187. package/dist/utils/logger.js +86 -0
  188. package/dist/utils/logger.js.map +1 -0
  189. package/dist/utils/time.d.ts +21 -0
  190. package/dist/utils/time.js +42 -0
  191. package/dist/utils/time.js.map +1 -0
  192. package/dist/utils/tokenizer.d.ts +13 -0
  193. package/dist/utils/tokenizer.js +46 -0
  194. package/dist/utils/tokenizer.js.map +1 -0
  195. package/package.json +77 -0
  196. package/scripts/check-node.mjs +36 -0
  197. package/scripts/setup.mjs +157 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 sangjun0000
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,362 @@
1
+ # Stellar Memory
2
+
3
+ **Persistent AI memory powered by celestial mechanics.**
4
+
5
+ Important memories orbit close to the Sun. Forgotten ones drift to the Oort Cloud.
6
+
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
8
+ [![Node.js 22+](https://img.shields.io/badge/Node.js-22%2B-green.svg)](https://nodejs.org)
9
+ [![MCP Compatible](https://img.shields.io/badge/MCP-Compatible-purple.svg)](https://modelcontextprotocol.io)
10
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg)](https://www.typescriptlang.org)
11
+
12
+ ---
13
+
14
+ Stellar Memory is a local-first, persistent memory system for AI assistants. It uses **orbital mechanics as a cognitive model** -- memories with high importance orbit close to the Sun for instant recall, while stale knowledge naturally drifts outward through exponential decay. No cloud services, no API keys, no data leaving your machine.
15
+
16
+ ## Key Features
17
+
18
+ - **Orbital Importance Model** -- 4-factor scoring (recency, frequency, impact, relevance) maps each memory to an orbital distance from 0.1 to 100 AU
19
+ - **Hybrid Search** -- FTS5 keyword search + sqlite-vec KNN vector search, merged via Reciprocal Rank Fusion
20
+ - **Local Embeddings** -- all-MiniLM-L6-v2 (384d) runs entirely in-process via `@xenova/transformers`
21
+ - **Corona Cache** -- in-memory tier of up to 200 core memories for sub-millisecond recall
22
+ - **MCP Native** -- 16 tools + 1 resource, works with Claude Code, Claude Desktop, and any MCP client
23
+ - **REST API** -- Hono server on port 21547 with 13 route groups
24
+ - **3D Dashboard** -- React + Three.js solar system visualization with D3 orbital overlay
25
+ - **Multi-Project** -- isolated memory spaces (galaxies) with cross-project universal memories
26
+ - **Knowledge Graph** -- constellation of typed relationships between memories
27
+ - **Temporal Awareness** -- time-bounded memories, evolution chains, point-in-time queries
28
+ - **Conflict Detection** -- automatic detection of contradicting memories with resolution workflow
29
+ - **Quality Scoring** -- specificity, actionability, uniqueness, freshness metrics per memory
30
+ - **Procedural Memories** -- auto-discovered behavioral patterns that decay 3.3x slower
31
+ - **Background Daemon** -- scheduled orbit recalculation, decay, and consolidation
32
+ - **Zero Dependencies on Cloud** -- everything runs locally with `node:sqlite` and local embeddings
33
+
34
+ ## How It Works
35
+
36
+ ```
37
+ importance = 0.30 x recency
38
+ + 0.20 x frequency
39
+ + 0.30 x impact
40
+ + 0.20 x relevance
41
+
42
+ distance = 0.1 + (1 - importance)^2 x 99.9
43
+
44
+ . * . . * . . * .
45
+ . * . . . .
46
+ . CORE (0.1-1 AU) .
47
+ . . instant recall . *
48
+ * . . . . . . . . . .
49
+ . NEAR (1-5 AU) . .
50
+ . recently used . * .
51
+ . . . . . . . . . . . *
52
+ . ACTIVE (5-15 AU) . .
53
+ in-context memories . . .
54
+ . . . . . . . . . . . . . * .
55
+ ARCHIVE (15-40 AU) . .
56
+ older knowledge . . .
57
+ . . . . . . . . . . . . . . . *
58
+ FADING (40-70 AU) . .
59
+ losing relevance . . .
60
+ . . . . . . . . . . . . . . . . . .
61
+ FORGOTTEN (70-100 AU) .
62
+ the Oort Cloud -- soft deleted .
63
+ ```
64
+
65
+ When you recall a memory, it gets pulled closer to the Sun. When you stop using it, exponential decay pushes it outward. The half-life is 72 hours by default.
66
+
67
+ ## Quick Start
68
+
69
+ ### Prerequisites
70
+
71
+ - **Node.js 22+** (required for built-in `node:sqlite`)
72
+ - **npm 9+**
73
+
74
+ ### Install
75
+
76
+ ```bash
77
+ git clone https://github.com/your-username/stellar-memory.git
78
+ cd stellar-memory
79
+ npm install
80
+ npm run build
81
+ ```
82
+
83
+ ### Use with Claude Code (MCP)
84
+
85
+ Add to your Claude Code MCP settings (`~/.claude/settings.json` or project `.claude/settings.json`):
86
+
87
+ ```json
88
+ {
89
+ "mcpServers": {
90
+ "stellar-memory": {
91
+ "command": "node",
92
+ "args": ["/absolute/path/to/stellar-memory/dist/index.js"],
93
+ "env": {
94
+ "STELLAR_PROJECT": "my-project"
95
+ }
96
+ }
97
+ }
98
+ }
99
+ ```
100
+
101
+ Then in Claude Code, Stellar Memory automatically:
102
+ 1. Reads `stellar://sun` to restore working context at session start
103
+ 2. Recalls relevant memories when topics change
104
+ 3. Stores decisions, errors, and milestones as they happen
105
+ 4. Commits session state before the conversation ends
106
+
107
+ ### Use with Claude Desktop
108
+
109
+ Add to `claude_desktop_config.json`:
110
+
111
+ ```json
112
+ {
113
+ "mcpServers": {
114
+ "stellar-memory": {
115
+ "command": "node",
116
+ "args": ["/absolute/path/to/stellar-memory/dist/index.js"],
117
+ "env": {
118
+ "STELLAR_PROJECT": "my-project"
119
+ }
120
+ }
121
+ }
122
+ }
123
+ ```
124
+
125
+ ### Run the Dashboard
126
+
127
+ ```bash
128
+ # Start the API server
129
+ npm run api
130
+
131
+ # In another terminal, start the web dashboard
132
+ cd web && npm run dev
133
+ ```
134
+
135
+ Open http://localhost:5175 to see your memories orbiting in 3D.
136
+
137
+ ### Run the Background Daemon
138
+
139
+ ```bash
140
+ npm run daemon
141
+ ```
142
+
143
+ The daemon runs scheduled tasks:
144
+ | Task | Interval |
145
+ |------|----------|
146
+ | Orbit recalculation | 1 hour |
147
+ | Memory decay | 6 hours |
148
+ | Consolidation check | 24 hours |
149
+
150
+ ## System Requirements
151
+
152
+ | Requirement | Minimum |
153
+ |-------------|---------|
154
+ | Node.js | 22.0.0+ (for `node:sqlite`) |
155
+ | npm | 9.0.0+ |
156
+ | Disk | ~100 MB (embedding model) + DB |
157
+ | RAM | ~200 MB (model + corona cache) |
158
+ | OS | Windows, macOS, Linux |
159
+
160
+ The embedding model (~90 MB) downloads automatically on first use and is cached in `~/.cache/huggingface`.
161
+
162
+ ## Configuration
163
+
164
+ All configuration is via environment variables:
165
+
166
+ | Variable | Default | Description |
167
+ |----------|---------|-------------|
168
+ | `STELLAR_DB_PATH` | `~/.stellar-memory/stellar.db` | SQLite database file location |
169
+ | `STELLAR_PROJECT` | `default` | Active project name |
170
+ | `STELLAR_API_PORT` | `21547` | REST API port |
171
+ | `STELLAR_SUN_TOKEN_BUDGET` | `800` | Max tokens for sun context resource |
172
+ | `STELLAR_DECAY_HALF_LIFE` | `72` | Hours for 50% recency decay |
173
+ | `STELLAR_WEIGHT_RECENCY` | `0.30` | Weight for recency in importance formula |
174
+ | `STELLAR_WEIGHT_FREQUENCY` | `0.20` | Weight for access frequency |
175
+ | `STELLAR_WEIGHT_IMPACT` | `0.30` | Weight for memory type impact |
176
+ | `STELLAR_WEIGHT_RELEVANCE` | `0.20` | Weight for contextual relevance |
177
+
178
+ ## Architecture
179
+
180
+ ### Project Structure
181
+
182
+ ```
183
+ src/
184
+ engine/ Core: orbit, gravity, corona, embedding, quality, analytics
185
+ storage/ database.ts, queries.ts, vec.ts (sqlite-vec)
186
+ mcp/ MCP server + tools (memory-tools, ingestion-tools, daemon-tool)
187
+ api/ Hono REST server + 12 route modules
188
+ scanner/ Filesystem + git log scanners with file parsers
189
+ service/ Background daemon + scheduler
190
+ utils/ Config, logger, tokenizer, time helpers
191
+
192
+ web/src/
193
+ components/ SolarSystem (Three.js), Layout, SearchBar, MemoryDetail, etc.
194
+ api/client.ts REST API client
195
+ i18n/ EN/KO internationalization (React Context)
196
+
197
+ tests/ 15 test files, 252 tests (Vitest)
198
+ electron/ Desktop app (Electron 40)
199
+ ```
200
+
201
+ ### Database
202
+
203
+ SQLite via Node.js built-in `node:sqlite` with three search layers:
204
+
205
+ 1. **memories** table -- structured storage with 20+ columns
206
+ 2. **memories_fts** -- FTS5 virtual table for keyword search
207
+ 3. **memory_vec** -- sqlite-vec virtual table for 384-dimension KNN search
208
+
209
+ ### Search Pipeline
210
+
211
+ ```
212
+ Query
213
+ |
214
+ +---> FTS5 keyword search ----+
215
+ | |---> Reciprocal Rank Fusion ---> Re-ranked results
216
+ +---> sqlite-vec KNN search --+
217
+ ```
218
+
219
+ The hybrid approach handles both exact matches ("JWT authentication error") and semantic matches ("login token expired").
220
+
221
+ ### Corona Cache
222
+
223
+ An in-memory tier holding up to 200 core + near zone memories with a token index for O(1) keyword lookup. The corona mirrors how human System 1 thinking works -- your most important knowledge is always instantly available.
224
+
225
+ ## MCP Tools Reference
226
+
227
+ | Tool | Description |
228
+ |------|-------------|
229
+ | `status` | View memory system state, grouped by orbital zone |
230
+ | `recall` | Hybrid search -- finds memories and pulls them closer |
231
+ | `remember` | Store a new memory with type, impact, and tags |
232
+ | `forget` | Push a memory to the Oort Cloud or permanently delete it |
233
+ | `commit` | Save session state to the Sun (working context) |
234
+ | `orbit` | Force recalculation of all orbital positions |
235
+ | `scan` | Ingest a local directory into memories (idempotent) |
236
+ | `daemon` | Start/stop/status of the background scheduler |
237
+ | `constellation` | Explore the knowledge graph between memories |
238
+ | `galaxy` | Multi-project management (switch, list, universal memories) |
239
+ | `analytics` | System insights: health, topics, survival curves, movements |
240
+ | `observe` | Auto-extract memories from conversation text |
241
+ | `consolidate` | Find and merge duplicate/similar memories |
242
+ | `resolve_conflict` | View and resolve contradicting memories |
243
+ | `temporal` | Point-in-time queries and memory evolution chains |
244
+ | `export` | Backup memories as JSON or Markdown |
245
+
246
+ ### Resource
247
+
248
+ | URI | Description |
249
+ |-----|-------------|
250
+ | `stellar://sun` | Current working context (core + near memories within token budget) |
251
+
252
+ ## REST API
253
+
254
+ The API server runs on port 21547 (default) and exposes:
255
+
256
+ ```
257
+ GET /api/health Health check
258
+ GET /api/memories List memories (with filters)
259
+ POST /api/memories Create a memory
260
+ GET /api/memories/:id Get a single memory
261
+ PATCH /api/memories/:id Update a memory
262
+ DELETE /api/memories/:id Delete a memory
263
+ GET /api/sun Get sun state
264
+ POST /api/sun/commit Commit session state
265
+ POST /api/orbit/recalculate Trigger orbit recalculation
266
+ GET /api/constellation/:id Get knowledge graph
267
+ GET /api/projects List projects
268
+ POST /api/projects Create a project
269
+ GET /api/analytics/:report Get analytics report
270
+ GET /api/temporal/at Point-in-time query
271
+ GET /api/conflicts List conflicts
272
+ POST /api/scan Scan a directory
273
+ GET /api/sources List data sources
274
+ POST /api/observations Submit conversation for observation
275
+ POST /api/consolidation Run consolidation
276
+ ```
277
+
278
+ ## Development
279
+
280
+ ```bash
281
+ # Run MCP server in dev mode (stdio, watch)
282
+ npm run dev
283
+
284
+ # Run API server in dev mode (watch)
285
+ npm run api
286
+
287
+ # Run web dashboard (proxies /api to :21547)
288
+ cd web && npm run dev
289
+
290
+ # Run all tests
291
+ npm run test
292
+
293
+ # Run tests in watch mode
294
+ npm run test:watch
295
+
296
+ # Build everything
297
+ npm run build:all
298
+
299
+ # Build Electron desktop app
300
+ npm run electron:pack
301
+ ```
302
+
303
+ ## Troubleshooting
304
+
305
+ ### "Cannot find module 'node:sqlite'"
306
+
307
+ You need Node.js 22 or later. The `node:sqlite` module is a built-in that was added in Node.js 22.
308
+
309
+ ```bash
310
+ node --version # Must be >= 22.0.0
311
+ ```
312
+
313
+ ### Embedding model download hangs
314
+
315
+ The all-MiniLM-L6-v2 model (~90 MB) downloads from Hugging Face on first use. If it hangs:
316
+
317
+ 1. Check your internet connection
318
+ 2. Try setting a proxy: `export HTTPS_PROXY=http://your-proxy:port`
319
+ 3. The model caches to `~/.cache/huggingface` -- delete that directory to force re-download
320
+
321
+ ### sqlite-vec load failure
322
+
323
+ The `sqlite-vec` extension uses a native binary. If it fails to load:
324
+
325
+ 1. Ensure you ran `npm install` (the binary is fetched during install)
326
+ 2. On some platforms, you may need to build from source -- see [sqlite-vec docs](https://github.com/asg017/sqlite-vec)
327
+ 3. Stellar Memory works without sqlite-vec (falls back to keyword-only search)
328
+
329
+ ### "SQLITE_ERROR: database is locked"
330
+
331
+ Only one process should write to the database at a time. If you're running both the MCP server and API server, they share the same database file and SQLite handles locking. If you see this error:
332
+
333
+ 1. Check for zombie processes: `ps aux | grep stellar`
334
+ 2. Ensure you're not running multiple MCP server instances
335
+
336
+ ### Web dashboard shows no memories
337
+
338
+ 1. Confirm the API server is running: `curl http://localhost:21547/api/health`
339
+ 2. Confirm the web dev server proxies correctly (check `web/vite.config.ts`)
340
+ 3. Check browser console for CORS errors
341
+
342
+ ## Testing
343
+
344
+ ```bash
345
+ # Run the full test suite (252 tests)
346
+ npm run test
347
+
348
+ # Run with coverage
349
+ npx vitest run --coverage
350
+
351
+ # Run specific test file
352
+ npx vitest run tests/orbit.test.ts
353
+
354
+ # Web component tests
355
+ cd web && npm run test
356
+ ```
357
+
358
+ The test suite uses a virtual module plugin in `vitest.config.ts` to bridge `node:sqlite` for Vite's module resolver. This is required because Vite does not natively recognize Node.js built-in modules with the `node:` prefix.
359
+
360
+ ## License
361
+
362
+ MIT
@@ -0,0 +1,15 @@
1
+ /**
2
+ * routes/analytics.ts — Memory Analytics API routes
3
+ *
4
+ * GET /api/analytics/overview — full MemoryAnalytics object
5
+ * GET /api/analytics/survival — survival curve (age buckets)
6
+ * GET /api/analytics/movements — orbit movement timeline
7
+ * GET /api/analytics/clusters — topic cluster heatmap
8
+ * GET /api/analytics/patterns — periodic access pattern detection
9
+ * GET /api/analytics/health — health metrics + recommendations
10
+ * GET /api/analytics/report — full text report
11
+ */
12
+ import { Hono } from 'hono';
13
+ declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
14
+ export default app;
15
+ //# sourceMappingURL=analytics.d.ts.map
@@ -0,0 +1,131 @@
1
+ /**
2
+ * routes/analytics.ts — Memory Analytics API routes
3
+ *
4
+ * GET /api/analytics/overview — full MemoryAnalytics object
5
+ * GET /api/analytics/survival — survival curve (age buckets)
6
+ * GET /api/analytics/movements — orbit movement timeline
7
+ * GET /api/analytics/clusters — topic cluster heatmap
8
+ * GET /api/analytics/patterns — periodic access pattern detection
9
+ * GET /api/analytics/health — health metrics + recommendations
10
+ * GET /api/analytics/report — full text report
11
+ */
12
+ import { Hono } from 'hono';
13
+ import { getFullAnalytics, getSurvivalCurve, getOrbitMovements, getTopicClusters, detectAccessPatterns, getMemoryHealth, generateReport, } from '../../engine/analytics.js';
14
+ const app = new Hono();
15
+ // GET /api/analytics/overview
16
+ app.get('/overview', (c) => {
17
+ const project = c.req.query('project') ?? 'default';
18
+ try {
19
+ const data = getFullAnalytics(project);
20
+ return c.json({ ok: true, data, project });
21
+ }
22
+ catch (err) {
23
+ const message = err instanceof Error ? err.message : 'Analytics failed';
24
+ return c.json({ ok: false, error: message }, 500);
25
+ }
26
+ });
27
+ // GET /api/analytics/survival
28
+ app.get('/survival', (c) => {
29
+ const project = c.req.query('project') ?? 'default';
30
+ try {
31
+ const data = getSurvivalCurve(project);
32
+ return c.json({ ok: true, data, project });
33
+ }
34
+ catch (err) {
35
+ const message = err instanceof Error ? err.message : 'Survival curve failed';
36
+ return c.json({ ok: false, error: message }, 500);
37
+ }
38
+ });
39
+ // GET /api/analytics/movements?days=30
40
+ app.get('/movements', (c) => {
41
+ const project = c.req.query('project') ?? 'default';
42
+ const daysParam = c.req.query('days');
43
+ const days = daysParam ? parseInt(daysParam, 10) : 30;
44
+ try {
45
+ const data = getOrbitMovements(project, days > 0 ? days : 30);
46
+ return c.json({ ok: true, data, project, days });
47
+ }
48
+ catch (err) {
49
+ const message = err instanceof Error ? err.message : 'Movements failed';
50
+ return c.json({ ok: false, error: message }, 500);
51
+ }
52
+ });
53
+ // GET /api/analytics/clusters
54
+ app.get('/clusters', (c) => {
55
+ const project = c.req.query('project') ?? 'default';
56
+ try {
57
+ const data = getTopicClusters(project);
58
+ return c.json({ ok: true, data, project });
59
+ }
60
+ catch (err) {
61
+ const message = err instanceof Error ? err.message : 'Clusters failed';
62
+ return c.json({ ok: false, error: message }, 500);
63
+ }
64
+ });
65
+ // GET /api/analytics/patterns
66
+ app.get('/patterns', (c) => {
67
+ const project = c.req.query('project') ?? 'default';
68
+ try {
69
+ const data = detectAccessPatterns(project);
70
+ return c.json({ ok: true, data, project });
71
+ }
72
+ catch (err) {
73
+ const message = err instanceof Error ? err.message : 'Patterns failed';
74
+ return c.json({ ok: false, error: message }, 500);
75
+ }
76
+ });
77
+ // GET /api/analytics/health
78
+ app.get('/health', (c) => {
79
+ const project = c.req.query('project') ?? 'default';
80
+ try {
81
+ const data = getMemoryHealth(project);
82
+ return c.json({ ok: true, data, project });
83
+ }
84
+ catch (err) {
85
+ const message = err instanceof Error ? err.message : 'Health check failed';
86
+ return c.json({ ok: false, error: message }, 500);
87
+ }
88
+ });
89
+ // GET /api/analytics/report
90
+ app.get('/report', (c) => {
91
+ const project = c.req.query('project') ?? 'default';
92
+ try {
93
+ const text = generateReport(project);
94
+ const accept = c.req.header('accept') ?? '';
95
+ if (accept.includes('text/plain')) {
96
+ return c.text(text);
97
+ }
98
+ return c.json({ ok: true, data: text, project });
99
+ }
100
+ catch (err) {
101
+ const message = err instanceof Error ? err.message : 'Report failed';
102
+ return c.json({ ok: false, error: message }, 500);
103
+ }
104
+ });
105
+ // Aliases for new naming convention
106
+ // GET /api/analytics/summary — alias for overview
107
+ app.get('/summary', (c) => {
108
+ const project = c.req.query('project') ?? 'default';
109
+ try {
110
+ const data = getFullAnalytics(project);
111
+ return c.json({ ok: true, data, project });
112
+ }
113
+ catch (err) {
114
+ const message = err instanceof Error ? err.message : 'Analytics summary failed';
115
+ return c.json({ ok: false, error: message }, 500);
116
+ }
117
+ });
118
+ // GET /api/analytics/topics — alias for clusters
119
+ app.get('/topics', (c) => {
120
+ const project = c.req.query('project') ?? 'default';
121
+ try {
122
+ const data = getTopicClusters(project);
123
+ return c.json({ ok: true, data, project });
124
+ }
125
+ catch (err) {
126
+ const message = err instanceof Error ? err.message : 'Topics failed';
127
+ return c.json({ ok: false, error: message }, 500);
128
+ }
129
+ });
130
+ export default app;
131
+ //# sourceMappingURL=analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/api/routes/analytics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * routes/conflicts.ts — Memory Conflict API routes
3
+ *
4
+ * GET /api/conflicts — getUnresolvedConflicts (query: project)
5
+ * GET /api/conflicts/:memoryId — getConflictsForMemory
6
+ * POST /api/conflicts/:id/resolve — resolveConflict
7
+ * POST /api/conflicts/:id/dismiss — resolveConflict with dismiss action
8
+ */
9
+ import { Hono } from 'hono';
10
+ declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
11
+ export default app;
12
+ //# sourceMappingURL=conflicts.d.ts.map
@@ -0,0 +1,67 @@
1
+ /**
2
+ * routes/conflicts.ts — Memory Conflict API routes
3
+ *
4
+ * GET /api/conflicts — getUnresolvedConflicts (query: project)
5
+ * GET /api/conflicts/:memoryId — getConflictsForMemory
6
+ * POST /api/conflicts/:id/resolve — resolveConflict
7
+ * POST /api/conflicts/:id/dismiss — resolveConflict with dismiss action
8
+ */
9
+ import { Hono } from 'hono';
10
+ import { getUnresolvedConflicts, resolveConflict, } from '../../engine/conflict.js';
11
+ import { getConflictsForMemory } from '../../storage/queries.js';
12
+ const app = new Hono();
13
+ // GET /api/conflicts?project=default
14
+ app.get('/', (c) => {
15
+ const project = c.req.query('project') ?? 'default';
16
+ try {
17
+ const data = getUnresolvedConflicts(project);
18
+ return c.json({ ok: true, data, project, total: data.length });
19
+ }
20
+ catch (err) {
21
+ const message = err instanceof Error ? err.message : 'Get conflicts failed';
22
+ return c.json({ ok: false, error: message }, 500);
23
+ }
24
+ });
25
+ // GET /api/conflicts/:memoryId — get conflicts for a specific memory
26
+ app.get('/:memoryId', (c) => {
27
+ const memoryId = c.req.param('memoryId');
28
+ try {
29
+ const data = getConflictsForMemory(memoryId);
30
+ return c.json({ ok: true, data, memoryId, total: data.length });
31
+ }
32
+ catch (err) {
33
+ const message = err instanceof Error ? err.message : 'Get conflicts for memory failed';
34
+ return c.json({ ok: false, error: message }, 500);
35
+ }
36
+ });
37
+ // POST /api/conflicts/:id/resolve — body: { resolution, action? }
38
+ app.post('/:id/resolve', async (c) => {
39
+ const id = c.req.param('id');
40
+ try {
41
+ const body = await c.req.json();
42
+ const resolution = body.resolution ?? 'Resolved via API';
43
+ const action = body.action ?? 'supersede';
44
+ resolveConflict(id, resolution, action);
45
+ return c.json({ ok: true, id, action, resolution });
46
+ }
47
+ catch (err) {
48
+ const message = err instanceof Error ? err.message : 'Resolve conflict failed';
49
+ return c.json({ ok: false, error: message }, 500);
50
+ }
51
+ });
52
+ // POST /api/conflicts/:id/dismiss — shortcut for dismiss action
53
+ app.post('/:id/dismiss', async (c) => {
54
+ const id = c.req.param('id');
55
+ try {
56
+ const body = await c.req.json().catch(() => ({}));
57
+ const resolution = body.resolution ?? 'Dismissed via API';
58
+ resolveConflict(id, resolution, 'dismiss');
59
+ return c.json({ ok: true, id, action: 'dismiss', resolution });
60
+ }
61
+ catch (err) {
62
+ const message = err instanceof Error ? err.message : 'Dismiss conflict failed';
63
+ return c.json({ ok: false, error: message }, 500);
64
+ }
65
+ });
66
+ export default app;
67
+ //# sourceMappingURL=conflicts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conflicts.js","sourceRoot":"","sources":["../../../src/api/routes/conflicts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * routes/consolidation.ts — Memory Consolidation API routes
3
+ *
4
+ * GET /api/consolidation/candidates — findConsolidationCandidates
5
+ * POST /api/consolidation/run — runConsolidation
6
+ * GET /api/consolidation/history/:id — getConsolidationSources
7
+ */
8
+ import { Hono } from 'hono';
9
+ declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
10
+ export default app;
11
+ //# sourceMappingURL=consolidation.d.ts.map