neuronlayer 0.1.8 → 0.2.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.

Potentially problematic release.


This version of neuronlayer might be problematic. Click here for more details.

Files changed (80) hide show
  1. package/README.md +95 -269
  2. package/dist/index.js +478 -126
  3. package/dist/index.js.map +7 -0
  4. package/package.json +7 -2
  5. package/esbuild.config.js +0 -26
  6. package/src/cli/commands.ts +0 -518
  7. package/src/core/adr-exporter.ts +0 -253
  8. package/src/core/architecture/architecture-enforcement.ts +0 -228
  9. package/src/core/architecture/duplicate-detector.ts +0 -288
  10. package/src/core/architecture/index.ts +0 -6
  11. package/src/core/architecture/pattern-learner.ts +0 -306
  12. package/src/core/architecture/pattern-library.ts +0 -403
  13. package/src/core/architecture/pattern-validator.ts +0 -324
  14. package/src/core/change-intelligence/bug-correlator.ts +0 -544
  15. package/src/core/change-intelligence/change-intelligence.ts +0 -264
  16. package/src/core/change-intelligence/change-tracker.ts +0 -334
  17. package/src/core/change-intelligence/fix-suggester.ts +0 -340
  18. package/src/core/change-intelligence/index.ts +0 -5
  19. package/src/core/code-verifier.ts +0 -843
  20. package/src/core/confidence/confidence-scorer.ts +0 -251
  21. package/src/core/confidence/conflict-checker.ts +0 -289
  22. package/src/core/confidence/index.ts +0 -5
  23. package/src/core/confidence/source-tracker.ts +0 -263
  24. package/src/core/confidence/warning-detector.ts +0 -241
  25. package/src/core/context-rot/compaction.ts +0 -284
  26. package/src/core/context-rot/context-health.ts +0 -243
  27. package/src/core/context-rot/context-rot-prevention.ts +0 -213
  28. package/src/core/context-rot/critical-context.ts +0 -221
  29. package/src/core/context-rot/drift-detector.ts +0 -255
  30. package/src/core/context-rot/index.ts +0 -7
  31. package/src/core/context.ts +0 -263
  32. package/src/core/decision-extractor.ts +0 -339
  33. package/src/core/decisions.ts +0 -69
  34. package/src/core/deja-vu.ts +0 -421
  35. package/src/core/engine.ts +0 -1646
  36. package/src/core/feature-context.ts +0 -726
  37. package/src/core/ghost-mode.ts +0 -465
  38. package/src/core/learning.ts +0 -519
  39. package/src/core/living-docs/activity-tracker.ts +0 -296
  40. package/src/core/living-docs/architecture-generator.ts +0 -428
  41. package/src/core/living-docs/changelog-generator.ts +0 -348
  42. package/src/core/living-docs/component-generator.ts +0 -230
  43. package/src/core/living-docs/doc-engine.ts +0 -134
  44. package/src/core/living-docs/doc-validator.ts +0 -282
  45. package/src/core/living-docs/index.ts +0 -8
  46. package/src/core/project-manager.ts +0 -301
  47. package/src/core/refresh/activity-gate.ts +0 -256
  48. package/src/core/refresh/git-staleness-checker.ts +0 -108
  49. package/src/core/refresh/index.ts +0 -27
  50. package/src/core/summarizer.ts +0 -290
  51. package/src/core/test-awareness/change-validator.ts +0 -499
  52. package/src/core/test-awareness/index.ts +0 -5
  53. package/src/index.ts +0 -49
  54. package/src/indexing/ast.ts +0 -868
  55. package/src/indexing/embeddings.ts +0 -85
  56. package/src/indexing/indexer.ts +0 -270
  57. package/src/indexing/watcher.ts +0 -78
  58. package/src/server/gateways/aggregator.ts +0 -374
  59. package/src/server/gateways/index.ts +0 -473
  60. package/src/server/gateways/memory-ghost.ts +0 -343
  61. package/src/server/gateways/memory-query.ts +0 -452
  62. package/src/server/gateways/memory-record.ts +0 -346
  63. package/src/server/gateways/memory-review.ts +0 -410
  64. package/src/server/gateways/memory-status.ts +0 -517
  65. package/src/server/gateways/memory-verify.ts +0 -392
  66. package/src/server/gateways/router.ts +0 -434
  67. package/src/server/gateways/types.ts +0 -610
  68. package/src/server/mcp.ts +0 -154
  69. package/src/server/resources.ts +0 -85
  70. package/src/server/tools.ts +0 -2460
  71. package/src/storage/database.ts +0 -271
  72. package/src/storage/tier1.ts +0 -135
  73. package/src/storage/tier2.ts +0 -972
  74. package/src/storage/tier3.ts +0 -123
  75. package/src/types/documentation.ts +0 -619
  76. package/src/types/index.ts +0 -222
  77. package/src/utils/config.ts +0 -193
  78. package/src/utils/files.ts +0 -117
  79. package/src/utils/time.ts +0 -37
  80. package/src/utils/tokens.ts +0 -52
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "neuronlayer",
3
- "version": "0.1.8",
4
- "description": "Code intelligence layer disguised as memory - MCP server giving AI persistent understanding of your codebase",
3
+ "version": "0.2.0",
4
+ "description": "MCP server that gives AI assistants persistent understanding of your codebase",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
8
  "neuronlayer": "dist/index.js"
9
9
  },
10
+ "files": [
11
+ "dist/**",
12
+ "wasm/**"
13
+ ],
10
14
  "scripts": {
11
15
  "build": "node esbuild.config.js",
12
16
  "dev": "node --watch dist/index.js",
@@ -40,6 +44,7 @@
40
44
  "better-sqlite3": "^11.8.0",
41
45
  "chokidar": "^4.0.0",
42
46
  "glob": "^13.0.0",
47
+ "tree-sitter-wasms": "^0.1.13",
43
48
  "web-tree-sitter": "^0.24.0"
44
49
  },
45
50
  "devDependencies": {
package/esbuild.config.js DELETED
@@ -1,26 +0,0 @@
1
- import { build } from 'esbuild';
2
-
3
- const commonOptions = {
4
- bundle: true,
5
- platform: 'node',
6
- target: 'node18',
7
- format: 'esm',
8
- sourcemap: true,
9
- external: [
10
- 'better-sqlite3', // Native module
11
- '@xenova/transformers', // Large, keep external
12
- 'chokidar', // Uses CommonJS require
13
- 'glob', // Keep external
14
- 'web-tree-sitter' // WASM module
15
- ]
16
- };
17
-
18
- // Build main MCP server
19
- await build({
20
- ...commonOptions,
21
- entryPoints: ['src/index.ts'],
22
- outfile: 'dist/index.js',
23
- banner: { js: '#!/usr/bin/env node' },
24
- });
25
-
26
- console.log('Build complete!');
@@ -1,518 +0,0 @@
1
- import { ProjectManager, type ProjectInfo } from '../core/project-manager.js';
2
- import { ADRExporter } from '../core/adr-exporter.js';
3
- import { initializeDatabase } from '../storage/database.js';
4
- import { Tier2Storage } from '../storage/tier2.js';
5
- import { join } from 'path';
6
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
7
- import { homedir } from 'os';
8
-
9
- const projectManager = new ProjectManager();
10
-
11
- interface CommandResult {
12
- success: boolean;
13
- message: string;
14
- data?: unknown;
15
- }
16
-
17
- // List all projects
18
- export function listProjects(): CommandResult {
19
- const projects = projectManager.listProjects();
20
- const activeProject = projectManager.getActiveProject();
21
-
22
- if (projects.length === 0) {
23
- return {
24
- success: true,
25
- message: 'No projects registered. Use "memorylayer projects add <path>" to add one.'
26
- };
27
- }
28
-
29
- const lines = ['Registered Projects:', ''];
30
- for (const project of projects) {
31
- const isActive = activeProject?.id === project.id ? ' (active)' : '';
32
- lines.push(` ${project.name}${isActive}`);
33
- lines.push(` ID: ${project.id}`);
34
- lines.push(` Path: ${project.path}`);
35
- lines.push(` Files: ${project.totalFiles}, Decisions: ${project.totalDecisions}`);
36
- lines.push(` Languages: ${project.languages.join(', ') || 'N/A'}`);
37
- lines.push('');
38
- }
39
-
40
- return {
41
- success: true,
42
- message: lines.join('\n'),
43
- data: projects
44
- };
45
- }
46
-
47
- // Add a project
48
- export function addProject(projectPath: string): CommandResult {
49
- try {
50
- const projectInfo = projectManager.registerProject(projectPath);
51
- projectManager.setActiveProject(projectInfo.id);
52
-
53
- return {
54
- success: true,
55
- message: `Project "${projectInfo.name}" registered and set as active.\nID: ${projectInfo.id}\nData directory: ${projectInfo.dataDir}`,
56
- data: projectInfo
57
- };
58
- } catch (error) {
59
- return {
60
- success: false,
61
- message: `Failed to add project: ${error instanceof Error ? error.message : String(error)}`
62
- };
63
- }
64
- }
65
-
66
- // Remove a project
67
- export function removeProject(projectId: string): CommandResult {
68
- const project = projectManager.getProject(projectId);
69
-
70
- if (!project) {
71
- return {
72
- success: false,
73
- message: `Project not found: ${projectId}`
74
- };
75
- }
76
-
77
- const removed = projectManager.removeProject(projectId);
78
-
79
- return {
80
- success: removed,
81
- message: removed
82
- ? `Project "${project.name}" removed from registry.`
83
- : `Failed to remove project.`
84
- };
85
- }
86
-
87
- // Switch to a project
88
- export function switchProject(projectId: string): CommandResult {
89
- const project = projectManager.getProject(projectId);
90
-
91
- if (!project) {
92
- return {
93
- success: false,
94
- message: `Project not found: ${projectId}`
95
- };
96
- }
97
-
98
- const switched = projectManager.setActiveProject(projectId);
99
-
100
- return {
101
- success: switched,
102
- message: switched
103
- ? `Switched to project: ${project.name}`
104
- : `Failed to switch project.`
105
- };
106
- }
107
-
108
- // Discover projects
109
- export function discoverProjects(): CommandResult {
110
- const discovered = projectManager.discoverProjects();
111
-
112
- if (discovered.length === 0) {
113
- return {
114
- success: true,
115
- message: 'No projects discovered in common locations.'
116
- };
117
- }
118
-
119
- const lines = [`Discovered ${discovered.length} potential projects:`, ''];
120
- for (const path of discovered) {
121
- const name = path.split(/[/\\]/).pop();
122
- lines.push(` ${name}`);
123
- lines.push(` ${path}`);
124
- lines.push('');
125
- }
126
- lines.push('Use "memorylayer projects add <path>" to register a project.');
127
-
128
- return {
129
- success: true,
130
- message: lines.join('\n'),
131
- data: discovered
132
- };
133
- }
134
-
135
- // Export decisions to ADR
136
- export function exportDecisions(
137
- projectPath?: string,
138
- options: { outputDir?: string; format?: 'madr' | 'nygard' | 'simple' } = {}
139
- ): CommandResult {
140
- // Determine project path
141
- let targetPath = projectPath;
142
- if (!targetPath) {
143
- const activeProject = projectManager.getActiveProject();
144
- if (!activeProject) {
145
- return {
146
- success: false,
147
- message: 'No project specified and no active project. Use "memorylayer projects switch <id>" first.'
148
- };
149
- }
150
- targetPath = activeProject.path;
151
- }
152
-
153
- // Get project info
154
- const projectInfo = projectManager.getProjectByPath(targetPath);
155
- if (!projectInfo) {
156
- return {
157
- success: false,
158
- message: `Project not registered: ${targetPath}. Use "memorylayer projects add ${targetPath}" first.`
159
- };
160
- }
161
-
162
- // Open database and get decisions (check both new and old names)
163
- let dbPath = join(projectInfo.dataDir, 'neuronlayer.db');
164
- if (!existsSync(dbPath)) {
165
- // Fall back to old name for backwards compatibility
166
- const oldDbPath = join(projectInfo.dataDir, 'memorylayer.db');
167
- if (existsSync(oldDbPath)) {
168
- dbPath = oldDbPath;
169
- } else {
170
- return {
171
- success: false,
172
- message: `Project database not found. Has the project been indexed?`
173
- };
174
- }
175
- }
176
-
177
- const db = initializeDatabase(dbPath);
178
- const tier2 = new Tier2Storage(db);
179
- const decisions = tier2.getAllDecisions();
180
- db.close();
181
-
182
- if (decisions.length === 0) {
183
- return {
184
- success: true,
185
- message: 'No decisions to export.'
186
- };
187
- }
188
-
189
- // Export
190
- const exporter = new ADRExporter(targetPath);
191
- const exportedFiles = exporter.exportAllDecisions(decisions, {
192
- outputDir: options.outputDir,
193
- format: options.format,
194
- includeIndex: true
195
- });
196
-
197
- return {
198
- success: true,
199
- message: `Exported ${exportedFiles.length} ADR files to ${options.outputDir || join(targetPath, 'docs', 'decisions')}`,
200
- data: exportedFiles
201
- };
202
- }
203
-
204
- // Show project info
205
- export function showProject(projectId?: string): CommandResult {
206
- let project: ProjectInfo | null;
207
-
208
- if (projectId) {
209
- project = projectManager.getProject(projectId);
210
- } else {
211
- project = projectManager.getActiveProject();
212
- }
213
-
214
- if (!project) {
215
- return {
216
- success: false,
217
- message: projectId
218
- ? `Project not found: ${projectId}`
219
- : 'No active project. Use "memorylayer projects switch <id>" first.'
220
- };
221
- }
222
-
223
- const lines = [
224
- `Project: ${project.name}`,
225
- `ID: ${project.id}`,
226
- `Path: ${project.path}`,
227
- `Data Directory: ${project.dataDir}`,
228
- `Files Indexed: ${project.totalFiles}`,
229
- `Decisions: ${project.totalDecisions}`,
230
- `Languages: ${project.languages.join(', ') || 'N/A'}`,
231
- `Last Accessed: ${new Date(project.lastAccessed).toLocaleString()}`
232
- ];
233
-
234
- return {
235
- success: true,
236
- message: lines.join('\n'),
237
- data: project
238
- };
239
- }
240
-
241
- // Helper to configure an MCP client
242
- function configureMCPClient(
243
- clientName: string,
244
- configPath: string,
245
- serverName: string,
246
- projectPath: string
247
- ): { success: boolean; message: string } {
248
- let config: { mcpServers?: Record<string, unknown> } = { mcpServers: {} };
249
-
250
- try {
251
- if (existsSync(configPath)) {
252
- const content = readFileSync(configPath, 'utf-8');
253
- config = JSON.parse(content);
254
- } else {
255
- // Create directory if needed
256
- const sep = process.platform === 'win32' ? '\\' : '/';
257
- const configDir = configPath.substring(0, configPath.lastIndexOf(sep));
258
- mkdirSync(configDir, { recursive: true });
259
- }
260
- } catch {
261
- // Config doesn't exist or is invalid, start fresh
262
- }
263
-
264
- if (!config.mcpServers) {
265
- config.mcpServers = {};
266
- }
267
-
268
- config.mcpServers[serverName] = {
269
- command: 'npx',
270
- args: ['-y', 'neuronlayer', '--project', projectPath]
271
- };
272
-
273
- try {
274
- writeFileSync(configPath, JSON.stringify(config, null, 2));
275
- return { success: true, message: `${clientName}: ${configPath}` };
276
- } catch (err) {
277
- return { success: false, message: `${clientName}: Failed - ${err instanceof Error ? err.message : String(err)}` };
278
- }
279
- }
280
-
281
- // Initialize neuronlayer for current project + auto-configure Claude Desktop & OpenCode
282
- export function initProject(projectPath?: string): CommandResult {
283
- const targetPath = projectPath || process.cwd();
284
-
285
- // 1. Register the project
286
- const addResult = addProject(targetPath);
287
- if (!addResult.success) {
288
- return addResult;
289
- }
290
-
291
- const projectInfo = addResult.data as ProjectInfo;
292
- const serverName = `neuronlayer-${projectInfo.name.toLowerCase().replace(/[^a-z0-9]/g, '-')}`;
293
- const platform = process.platform;
294
-
295
- const configuredClients: string[] = [];
296
- const failedClients: string[] = [];
297
-
298
- // 2. Configure Claude Desktop
299
- let claudeConfigPath: string;
300
- if (platform === 'win32') {
301
- claudeConfigPath = join(homedir(), 'AppData', 'Roaming', 'Claude', 'claude_desktop_config.json');
302
- } else if (platform === 'darwin') {
303
- claudeConfigPath = join(homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
304
- } else {
305
- claudeConfigPath = join(homedir(), '.config', 'claude', 'claude_desktop_config.json');
306
- }
307
-
308
- const claudeResult = configureMCPClient('Claude Desktop', claudeConfigPath, serverName, targetPath);
309
- if (claudeResult.success) {
310
- configuredClients.push(claudeResult.message);
311
- } else {
312
- failedClients.push(claudeResult.message);
313
- }
314
-
315
- // 3. Configure OpenCode
316
- const openCodeConfigPath = join(homedir(), '.opencode', 'config.json');
317
- const openCodeResult = configureMCPClient('OpenCode', openCodeConfigPath, serverName, targetPath);
318
- if (openCodeResult.success) {
319
- configuredClients.push(openCodeResult.message);
320
- } else {
321
- failedClients.push(openCodeResult.message);
322
- }
323
-
324
- // 4. Configure Claude Code (CLI) - uses same config location as Claude Desktop on some systems
325
- // Also check for .claude.json in home directory
326
- const claudeCodeConfigPath = join(homedir(), '.claude.json');
327
- const claudeCodeResult = configureMCPClient('Claude Code', claudeCodeConfigPath, serverName, targetPath);
328
- if (claudeCodeResult.success) {
329
- configuredClients.push(claudeCodeResult.message);
330
- }
331
-
332
- // Build result message
333
- let message = `
334
- NeuronLayer initialized!
335
-
336
- Project: ${projectInfo.name}
337
- Path: ${targetPath}
338
- Data: ${projectInfo.dataDir}
339
-
340
- Configured MCP Clients:
341
- ${configuredClients.map(c => ' ✓ ' + c).join('\n')}
342
- `;
343
-
344
- if (failedClients.length > 0) {
345
- message += `\nFailed:\n${failedClients.map(c => ' ✗ ' + c).join('\n')}`;
346
- }
347
-
348
- message += `\n\nRestart your AI tools to activate.`;
349
-
350
- return {
351
- success: true,
352
- message: message.trim(),
353
- data: { projectInfo, serverName, configuredClients }
354
- };
355
- }
356
-
357
- // Print help
358
- export function printHelp(): void {
359
- console.log(`
360
- MemoryLayer CLI - Persistent Memory for AI Coding Assistants
361
-
362
- USAGE:
363
- memorylayer [command] [options]
364
-
365
- COMMANDS:
366
- init [path] Initialize project + auto-configure Claude Desktop
367
- (no command) Start MCP server for Claude Desktop
368
- projects list List all registered projects
369
- projects add <path> Add a project to the registry
370
- projects remove <id> Remove a project from the registry
371
- projects switch <id> Set a project as active
372
- projects show [id] Show project details
373
- projects discover Discover projects in common locations
374
- export [options] Export decisions to ADR files
375
- help Show this help message
376
-
377
- OPTIONS:
378
- --project, -p <path> Path to the project directory
379
- --output, -o <dir> Output directory for exports
380
- --format <type> ADR format: madr, nygard, simple
381
-
382
- EXAMPLES:
383
- # Quick setup (auto-configures Claude Desktop)
384
- cd /path/to/project
385
- neuronlayer init
386
-
387
- # Start MCP server
388
- neuronlayer --project /path/to/project
389
-
390
- # List all projects
391
- memorylayer projects list
392
-
393
- # Add a new project
394
- memorylayer projects add /path/to/my-project
395
-
396
- # Switch active project
397
- memorylayer projects switch abc123
398
-
399
- # Export decisions to ADR files
400
- memorylayer export --format madr
401
-
402
- # Discover projects
403
- memorylayer projects discover
404
-
405
- For more information, visit: https://github.com/abhisavakar/neuronlayer
406
- `);
407
- }
408
-
409
- // Parse and execute CLI commands
410
- export function executeCLI(args: string[]): void {
411
- const command = args[0];
412
- const subcommand = args[1];
413
-
414
- switch (command) {
415
- case 'help':
416
- case '--help':
417
- case '-h':
418
- printHelp();
419
- break;
420
-
421
- case 'init': {
422
- const path = args[1];
423
- const result = initProject(path);
424
- console.log(result.message);
425
- if (!result.success) process.exit(1);
426
- break;
427
- }
428
-
429
- case 'projects': {
430
- switch (subcommand) {
431
- case 'list':
432
- console.log(listProjects().message);
433
- break;
434
- case 'add': {
435
- const path = args[2];
436
- if (!path) {
437
- console.error('Error: Project path required.');
438
- console.error('Usage: memorylayer projects add <path>');
439
- process.exit(1);
440
- }
441
- const result = addProject(path);
442
- console.log(result.message);
443
- if (!result.success) process.exit(1);
444
- break;
445
- }
446
- case 'remove': {
447
- const id = args[2];
448
- if (!id) {
449
- console.error('Error: Project ID required.');
450
- console.error('Usage: memorylayer projects remove <id>');
451
- process.exit(1);
452
- }
453
- const result = removeProject(id);
454
- console.log(result.message);
455
- if (!result.success) process.exit(1);
456
- break;
457
- }
458
- case 'switch': {
459
- const id = args[2];
460
- if (!id) {
461
- console.error('Error: Project ID required.');
462
- console.error('Usage: memorylayer projects switch <id>');
463
- process.exit(1);
464
- }
465
- const result = switchProject(id);
466
- console.log(result.message);
467
- if (!result.success) process.exit(1);
468
- break;
469
- }
470
- case 'show': {
471
- const id = args[2];
472
- const result = showProject(id);
473
- console.log(result.message);
474
- if (!result.success) process.exit(1);
475
- break;
476
- }
477
- case 'discover':
478
- console.log(discoverProjects().message);
479
- break;
480
- default:
481
- console.error(`Unknown subcommand: ${subcommand}`);
482
- console.error('Available: list, add, remove, switch, show, discover');
483
- process.exit(1);
484
- }
485
- break;
486
- }
487
-
488
- case 'export': {
489
- // Parse export options
490
- let outputDir: string | undefined;
491
- let format: 'madr' | 'nygard' | 'simple' | undefined;
492
-
493
- for (let i = 1; i < args.length; i++) {
494
- const arg = args[i];
495
- const nextArg = args[i + 1];
496
- if ((arg === '--output' || arg === '-o') && nextArg) {
497
- outputDir = nextArg;
498
- i++;
499
- } else if (arg === '--format' && nextArg) {
500
- format = nextArg as 'madr' | 'nygard' | 'simple';
501
- i++;
502
- }
503
- }
504
-
505
- const result = exportDecisions(undefined, { outputDir, format });
506
- console.log(result.message);
507
- if (!result.success) process.exit(1);
508
- break;
509
- }
510
-
511
- default:
512
- // If no command matches, it might be the default MCP server mode
513
- // Return without handling - let main() handle it
514
- return;
515
- }
516
-
517
- process.exit(0);
518
- }