mnemosyne-core 2.0.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 (47) hide show
  1. package/README.md +176 -0
  2. package/dist/Store-N3j0Vaj6.d.mts +320 -0
  3. package/dist/Store-N3j0Vaj6.d.ts +320 -0
  4. package/dist/cli/index.d.mts +8 -0
  5. package/dist/cli/index.d.ts +8 -0
  6. package/dist/cli/index.js +16352 -0
  7. package/dist/cli/index.js.map +1 -0
  8. package/dist/cli/index.mjs +16348 -0
  9. package/dist/cli/index.mjs.map +1 -0
  10. package/dist/mcp/index.d.mts +94 -0
  11. package/dist/mcp/index.d.ts +94 -0
  12. package/dist/mcp/index.js +401 -0
  13. package/dist/mcp/index.js.map +1 -0
  14. package/dist/mcp/index.mjs +371 -0
  15. package/dist/mcp/index.mjs.map +1 -0
  16. package/dist/sdk/index.d.mts +102 -0
  17. package/dist/sdk/index.d.ts +102 -0
  18. package/dist/sdk/index.js +143 -0
  19. package/dist/sdk/index.js.map +1 -0
  20. package/dist/sdk/index.mjs +116 -0
  21. package/dist/sdk/index.mjs.map +1 -0
  22. package/dist/server/api.d.mts +14 -0
  23. package/dist/server/api.d.ts +14 -0
  24. package/dist/server/api.js +1699 -0
  25. package/dist/server/api.js.map +1 -0
  26. package/dist/server/api.mjs +1669 -0
  27. package/dist/server/api.mjs.map +1 -0
  28. package/dist/server/index.d.mts +111 -0
  29. package/dist/server/index.d.ts +111 -0
  30. package/dist/server/index.js +12446 -0
  31. package/dist/server/index.js.map +1 -0
  32. package/dist/server/index.mjs +12442 -0
  33. package/dist/server/index.mjs.map +1 -0
  34. package/dist/server/websocket.d.mts +23 -0
  35. package/dist/server/websocket.d.ts +23 -0
  36. package/dist/server/websocket.js +3807 -0
  37. package/dist/server/websocket.js.map +1 -0
  38. package/dist/server/websocket.mjs +3798 -0
  39. package/dist/server/websocket.mjs.map +1 -0
  40. package/dist/sharp-win32-x64-CXV3GA3G.node +0 -0
  41. package/dist/ws/index.d.mts +22 -0
  42. package/dist/ws/index.d.ts +22 -0
  43. package/dist/ws/index.js +3827 -0
  44. package/dist/ws/index.js.map +1 -0
  45. package/dist/ws/index.mjs +3817 -0
  46. package/dist/ws/index.mjs.map +1 -0
  47. package/package.json +69 -0
package/README.md ADDED
@@ -0,0 +1,176 @@
1
+ <p align="center">
2
+ <img src="logo.png" width="120" alt="Mnemosyne logo">
3
+ </p>
4
+
5
+ <h1 align="center">Mnemosyne</h1>
6
+
7
+ <p align="center">
8
+ <strong>An open-source exocortex for humans and AI.</strong>
9
+ </p>
10
+
11
+ Your knowledge. One SQLite file. Accessible to you and your agents.
12
+
13
+ ```bash
14
+ npm install -g mnemosyne-core
15
+ mnemosyne init
16
+ mnemosyne start
17
+ # Open http://localhost:7321/dashboard
18
+ ```
19
+
20
+ ---
21
+
22
+ ## What is Mnemosyne?
23
+
24
+ Mnemosyne is an **exocortex** β€” an external brain that belongs to you.
25
+
26
+ **For humans:** A spatial canvas + table view to store ideas, files, and connections. Dark mode. Fast. Local. SQLite-backed.
27
+
28
+ **For AI agents:** A memory system agents can safely read and write to via [MCP](https://modelcontextprotocol.io/) (Model Context Protocol). Agents remember context across conversations.
29
+
30
+ ---
31
+
32
+ ## Features
33
+
34
+ | Feature | What it does |
35
+ |---------|-------------|
36
+ | πŸ•ΈοΈ **Graph + Table views** | Spatial canvas and structured database in one |
37
+ | πŸ” **Semantic search** | Find ideas by meaning, not just keywords (sqlite-vec) |
38
+ | πŸ“Ž **File intelligence** | Drop PDFs/images, auto-summarized for agents |
39
+ | πŸ€– **Agent collaboration** | Claude, Cursor, custom agents via MCP stdio/SSE |
40
+ | πŸ”’ **Checkout system** | Agents lock atoms while editing, queue when busy |
41
+ | πŸ“ **Suggestion mode** | Agents propose edits, you approve or reject |
42
+ | ⏳ **Time travel** | Every change is logged. Rewind to any version. |
43
+ | πŸ“€ **Portable** | Your entire brain in one SQLite file: `data/nexus.db` |
44
+
45
+ ---
46
+
47
+ ## Install
48
+
49
+ **One-line global install:**
50
+
51
+ ```bash
52
+ npm install -g mnemosyne-core
53
+ mnemosyne init
54
+ mnemosyne start
55
+ ```
56
+
57
+ **Or in your project:**
58
+
59
+ ```bash
60
+ npm install mnemosyne-core
61
+ npx mnemosyne init
62
+ npx mnemosyne start
63
+ ```
64
+
65
+ **Requirements:** Node.js 20+
66
+
67
+ ---
68
+
69
+ ## Agent Setup
70
+
71
+ ### Claude Desktop (stdio β€” no server needed)
72
+
73
+ Add to `claude_desktop_config.json`:
74
+
75
+ ```json
76
+ {
77
+ "mcpServers": {
78
+ "mnemosyne": {
79
+ "command": "npx",
80
+ "args": ["mnemosyne-core", "start", "--mcp-transport", "stdio"]
81
+ }
82
+ }
83
+ }
84
+ ```
85
+
86
+ Restart Claude Desktop β†’ Settings β†’ MCP β†’ Mnemosyne appears with all tools.
87
+
88
+ ### Cursor (SSE β€” server mode)
89
+
90
+ ```bash
91
+ mnemosyne start --port 7321
92
+ ```
93
+
94
+ Then in Cursor: Settings β†’ MCP β†’ Add server β†’ `http://localhost:7321/mcp/manifest`
95
+
96
+ ### Programmatic (SDK)
97
+
98
+ ```typescript
99
+ import { MnemosyneClient } from 'mnemosyne-core/sdk';
100
+
101
+ const client = new MnemosyneClient({ baseUrl: 'http://localhost:7321' });
102
+ const atoms = await client.searchSemantic('server setup', { limit: 5 });
103
+ ```
104
+
105
+ ### Embedded (your own app)
106
+
107
+ ```typescript
108
+ import { Mnemosyne, ApiRouter, McpServer } from 'mnemosyne-core';
109
+
110
+ const brain = new Mnemosyne();
111
+ await brain.init();
112
+
113
+ const api = new ApiRouter(brain.store);
114
+ const mcp = new McpServer(brain.store);
115
+
116
+ // Mount in your own HTTP server
117
+ server.on('request', (req, res) => api.handle(req, res));
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Architecture
123
+
124
+ ```
125
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
126
+ β”‚ Human β”‚ β”‚ Agent β”‚ β”‚ Your App β”‚
127
+ β”‚ Dashboard β”‚ β”‚ (Claude) β”‚ β”‚ (Express) β”‚
128
+ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
129
+ β”‚ β”‚ β”‚
130
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
131
+ β”‚
132
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
133
+ β”‚ mnemosyne-core β”‚
134
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
135
+ β”‚ β”‚ Mnemosyne β”‚ β”‚
136
+ β”‚ β”‚ (SQLite + vec) β”‚ β”‚
137
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
138
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
139
+ β”‚ β”‚ REST API β”‚ β”‚
140
+ β”‚ β”‚ MCP (stdio/SSE)β”‚ β”‚
141
+ β”‚ β”‚ WebSocket β”‚ β”‚
142
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
143
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
144
+ ```
145
+
146
+ - **Storage:** SQLite (better-sqlite3) + WAL mode + FTS5 full-text search + sqlite-vec embeddings
147
+ - **API:** Raw Node.js HTTP (no Express dependency)
148
+ - **MCP:** JSON-RPC 2.0 over stdio (Claude Desktop) or SSE (Cursor/web)
149
+ - **WebSocket:** Real-time atom updates and broadcasts
150
+
151
+ ---
152
+
153
+ ## Documentation
154
+
155
+ - **[Getting Started](docs/getting-started.md)** β€” Install, first project, search, export
156
+ - **[Agent Setup](docs/agent-setup.md)** β€” Claude Desktop, Cursor, SDK, permissions
157
+ - **[API Reference](docs/04-developer-guide/api-reference.md)** β€” REST endpoints
158
+ - **[Architecture](docs/04-developer-guide/architecture.md)** β€” Database schema, design decisions
159
+
160
+ ---
161
+
162
+ ## CLI Commands
163
+
164
+ ```bash
165
+ mnemosyne init # Scaffold data/ directory + config.yaml + SQLite DB
166
+ mnemosyne start # Start server (API + dashboard + MCP SSE)
167
+ mnemosyne start --mcp-transport stdio # Stdio mode for Claude Desktop
168
+ mnemosyne migrate --from v1.json --to data/nexus.db # v1.0 β†’ v2.0
169
+ mnemosyne export --project "Work" --format markdown # Export project
170
+ ```
171
+
172
+ ---
173
+
174
+ ## License
175
+
176
+ MIT
@@ -0,0 +1,320 @@
1
+ import Database from 'better-sqlite3';
2
+
3
+ type PermissionLevel = "none" | "view" | "suggest" | "edit" | "create" | "admin";
4
+ type Action = "create" | "read" | "write" | "update" | "delete" | "lock" | "manage_queue" | "force_release" | "peek" | "export" | "import" | "suggest";
5
+ type AssistantRole = "owner" | "admin" | "manager" | "lead" | "developer" | "worker" | "reviewer" | "observer" | "bot" | "guest";
6
+ interface Project {
7
+ id: string;
8
+ name: string;
9
+ description: string | null;
10
+ icon: string;
11
+ color: string;
12
+ created_at: number;
13
+ updated_at: number;
14
+ owner: string;
15
+ metadata: Record<string, any>;
16
+ }
17
+ interface Atom {
18
+ id: string;
19
+ project_id: string;
20
+ parent_id: string | null;
21
+ title: string;
22
+ summary: string | null;
23
+ icon: string;
24
+ color: string | null;
25
+ x: number | null;
26
+ y: number | null;
27
+ created_at: number;
28
+ updated_at: number;
29
+ version: number;
30
+ locked_by: string | null;
31
+ locked_at: number | null;
32
+ locked_reason: string | null;
33
+ owner: string;
34
+ status: string;
35
+ metadata: Record<string, any>;
36
+ auto_path?: string;
37
+ path_overridden?: boolean;
38
+ status_updated_at?: number;
39
+ block_count?: number;
40
+ bond_count?: number;
41
+ template_id?: string | null;
42
+ embedding_status?: string | null;
43
+ }
44
+ interface Block {
45
+ id: string;
46
+ atom_id: string;
47
+ type: string;
48
+ content: string | null;
49
+ order_index: number;
50
+ created_at: number;
51
+ updated_at: number;
52
+ metadata: Record<string, any>;
53
+ }
54
+ interface Bond {
55
+ id: string;
56
+ source_id: string;
57
+ target_id: string;
58
+ label: string;
59
+ color: string | null;
60
+ created_at: number;
61
+ }
62
+ interface Assistant {
63
+ id: string;
64
+ name: string;
65
+ role: AssistantRole;
66
+ permissions: Record<string, any>;
67
+ status: string;
68
+ provider: string | null;
69
+ connected_at: number;
70
+ last_seen: number;
71
+ metadata: Record<string, any>;
72
+ }
73
+ interface QueueEntry {
74
+ id: string;
75
+ atom_id: string;
76
+ assistant_id: string;
77
+ requested_at: number;
78
+ priority: number;
79
+ status: string;
80
+ reason: string | null;
81
+ }
82
+ interface EventLogEntry {
83
+ id: string;
84
+ timestamp: number;
85
+ event_type: string;
86
+ project_id: string | null;
87
+ atom_id: string | null;
88
+ block_id: string | null;
89
+ bond_id: string | null;
90
+ actor: string;
91
+ actor_type: string;
92
+ diff: string | null;
93
+ trigger: string | null;
94
+ metadata: Record<string, any>;
95
+ }
96
+ interface Config {
97
+ server: {
98
+ port: number;
99
+ host: string;
100
+ version: string;
101
+ };
102
+ database: {
103
+ path: string;
104
+ wal_mode: boolean;
105
+ vec_extension_path: string;
106
+ };
107
+ storage: {
108
+ files_dir: string;
109
+ max_file_size_mb: number;
110
+ backups_dir: string;
111
+ backup_interval_hours: number;
112
+ max_backups: number;
113
+ };
114
+ limits: {
115
+ max_atoms_per_project: number;
116
+ rate_limit_requests: number;
117
+ rate_limit_window_ms: number;
118
+ };
119
+ embeddings: {
120
+ model: string;
121
+ dimension: number;
122
+ max_text_length: number;
123
+ };
124
+ features: {
125
+ mcp_enabled: boolean;
126
+ auto_index_enabled: boolean;
127
+ file_processing_enabled: boolean;
128
+ };
129
+ index: {
130
+ debounce_ms: number;
131
+ };
132
+ search: {
133
+ semantic_weight: number;
134
+ fts_weight: number;
135
+ };
136
+ bonds: {
137
+ default_type: string;
138
+ };
139
+ }
140
+
141
+ /**
142
+ * Mnemosyne Store Engine
143
+ * SQLite-backed replacement for the in-memory JSON system.
144
+ *
145
+ * Naming:
146
+ * Project (was Memory) β†’ projects table
147
+ * Atom β†’ atoms table
148
+ * Block β†’ blocks table
149
+ * Bond (new) β†’ bonds table
150
+ * Assistant (was Agent) β†’ assistants table
151
+ */
152
+
153
+ declare class EventEmitter {
154
+ private listeners;
155
+ on(event: string, cb: (...args: any[]) => void): void;
156
+ emit(event: string, ...args: any[]): void;
157
+ }
158
+ declare class Store extends EventEmitter {
159
+ private db;
160
+ config: Config;
161
+ vecEnabled: boolean;
162
+ private backupInterval;
163
+ private dbPath;
164
+ private backupDir;
165
+ private backupIntervalMs;
166
+ private maxBackups;
167
+ constructor(db: Database.Database, config: Config, vecEnabled?: boolean);
168
+ shutdown(): void;
169
+ private ensureBackup;
170
+ private stmt;
171
+ private tx;
172
+ private now;
173
+ private parseMeta;
174
+ private logEvent;
175
+ can(role: AssistantRole, action: Action, atomId?: string, assistantId?: string): boolean;
176
+ private levelAllowsAction;
177
+ setAtomPermission(atomId: string, assistantId: string, level: PermissionLevel, grantedBy?: string): void;
178
+ getAtomPermission(atomId: string, assistantId: string): {
179
+ id: string;
180
+ atom_id: string;
181
+ assistant_id: string;
182
+ level: PermissionLevel;
183
+ granted_by: string | null;
184
+ granted_at: number;
185
+ } | undefined;
186
+ getAtomPermissions(atomId: string): any[];
187
+ removeAtomPermission(atomId: string, assistantId: string): boolean;
188
+ resolvePermission(atomId: string, assistantId: string): PermissionLevel;
189
+ createProject(name: string, description?: string): Project;
190
+ getProject(id: string): Project | undefined;
191
+ getProjectByName(name: string): Project | undefined;
192
+ getProjects(): Project[];
193
+ createAtom(projectId: string, title: string, type: string, createdBy: string, opts?: {
194
+ parentId?: string;
195
+ summary?: string;
196
+ tags?: string[];
197
+ path_overridden?: boolean;
198
+ auto_path?: string;
199
+ template?: string;
200
+ status?: string;
201
+ }): Atom;
202
+ getAtom(id: string): Atom | undefined;
203
+ getAtomsByProject(projectId: string): Atom[];
204
+ getAtomChildren(atomId: string): Atom[];
205
+ updateAtomParent(id: string, parentId: string | null, updatedBy: string): Atom | null;
206
+ updateAtom(id: string, fields: {
207
+ title?: string;
208
+ summary?: string;
209
+ tags?: string[];
210
+ status?: string;
211
+ auto_path?: string;
212
+ path_overridden?: boolean;
213
+ }, updatedBy: string): Atom | null;
214
+ deleteAtom(id: string, deletedBy: string): boolean;
215
+ createBlock(atomId: string, type: string, content: string, createdBy: string, opts?: {
216
+ order?: number;
217
+ tags?: string[];
218
+ }): Block;
219
+ getBlock(id: string): Block | undefined;
220
+ getBlocksByAtom(atomId: string): Block[];
221
+ updateBlock(id: string, content: string, updatedBy: string): Block | null;
222
+ deleteBlock(id: string, deletedBy: string): boolean;
223
+ createBond(sourceId: string, targetId: string, label: string, color?: string): Bond;
224
+ getBond(id: string): Bond | undefined;
225
+ getBondsByAtom(atomId: string): {
226
+ outgoing: Bond[];
227
+ incoming: Bond[];
228
+ };
229
+ updateBond(id: string, fields: {
230
+ label?: string;
231
+ color?: string;
232
+ }): Bond | null;
233
+ deleteBond(id: string): boolean;
234
+ checkout(atomId: string, assistantId: string, mode: "exclusive" | "shared", reason: string): {
235
+ success: boolean;
236
+ queuePosition?: number;
237
+ };
238
+ releaseCheckout(atomId: string, assistantId: string): boolean;
239
+ forceRelease(atomId: string, _by: string): boolean;
240
+ getQueueStatus(atomId: string): {
241
+ atomId: string;
242
+ queue: QueueEntry[];
243
+ } | undefined;
244
+ grantQueueItem(atomId: string, queueEntryId: string): boolean;
245
+ rejectQueueItem(atomId: string, queueEntryId: string): boolean;
246
+ bumpQueueItem(atomId: string, queueEntryId: string): boolean;
247
+ registerAssistant(a: {
248
+ id?: string;
249
+ name: string;
250
+ role: AssistantRole;
251
+ capabilities?: string[];
252
+ description?: string;
253
+ provider?: string;
254
+ instructions?: string;
255
+ config?: Record<string, any>;
256
+ }): Assistant;
257
+ updateAssistant(id: string, fields: {
258
+ name?: string;
259
+ role?: AssistantRole;
260
+ description?: string;
261
+ provider?: string;
262
+ instructions?: string;
263
+ config?: Record<string, any>;
264
+ capabilities?: string[];
265
+ status?: string;
266
+ }): Assistant | null;
267
+ deleteAssistant(id: string): boolean;
268
+ getAssistant(id: string): Assistant | undefined;
269
+ getAllAssistants(): Assistant[];
270
+ heartbeat(id: string): void;
271
+ search(projectId: string, q: string, limit: number): any[];
272
+ embedAtom(atomId: string): Promise<void>;
273
+ searchSemantic(projectId: string, queryEmbedding: number[], limit: number): any[];
274
+ searchHybrid(projectId: string, q: string, queryEmbedding: number[], limit: number): any[];
275
+ private embedQueue;
276
+ scheduleEmbed(atomId: string, priority?: 2): void;
277
+ importMnemosyneZip(zipBuffer: Buffer, importedBy: string): {
278
+ success: boolean;
279
+ atomsRestored: number;
280
+ error?: string;
281
+ };
282
+ importMarkdown(mdText: string, projectId: string, createdBy: string, opts?: {
283
+ title?: string;
284
+ }): {
285
+ success: boolean;
286
+ atomId?: string;
287
+ bondsCreated?: number;
288
+ error?: string;
289
+ };
290
+ private cascadePathChange;
291
+ private indexTimers;
292
+ private indexAtomTimers;
293
+ scheduleProjectIndexUpdate(projectId: string): void;
294
+ scheduleProjectIndexAtomUpdate(projectId: string): void;
295
+ regenerateProjectIndex(projectId: string): void;
296
+ getProjectIndexAtom(projectId: string): Atom | undefined;
297
+ private getOrCreateProjectIndexAtom;
298
+ regenerateProjectIndexAtom(projectId: string): void;
299
+ getGraph(projectId: string): {
300
+ atoms: Atom[];
301
+ bonds: Bond[];
302
+ };
303
+ createAttachment(fileHash: string, fileName: string, fileSize: number, mimeType: string): any;
304
+ getAttachmentByHash(fileHash: string): any | undefined;
305
+ processFileBlock(atomId: string, blockContent: string): Promise<void>;
306
+ getAtomHistory(atomId: string): any[];
307
+ exportSnapshot(): any;
308
+ importSnapshot(snapshot: any, importedBy: string): void;
309
+ getEvents(since: number, projectId?: string, limit?: number): EventLogEntry[];
310
+ getEventsByAtom(atomId: string, limit?: number): EventLogEntry[];
311
+ getStats(): {
312
+ projects: number;
313
+ atoms: number;
314
+ blocks: number;
315
+ bonds: number;
316
+ assistants: number;
317
+ };
318
+ }
319
+
320
+ export { type Atom as A, type Config as C, type Project as P, Store as S };