neuronlayer 0.1.7 → 0.1.9

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.

package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "neuronlayer",
3
- "version": "0.1.7",
4
- "description": "Persistent memory layer for AI coding assistants - MCP server that makes AI truly understand your codebase",
3
+ "version": "0.1.9",
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": {
@@ -22,7 +22,7 @@ export function listProjects(): CommandResult {
22
22
  if (projects.length === 0) {
23
23
  return {
24
24
  success: true,
25
- message: 'No projects registered. Use "memorylayer projects add <path>" to add one.'
25
+ message: 'No projects registered. Use "neuronlayer projects add <path>" to add one.'
26
26
  };
27
27
  }
28
28
 
@@ -123,7 +123,7 @@ export function discoverProjects(): CommandResult {
123
123
  lines.push(` ${path}`);
124
124
  lines.push('');
125
125
  }
126
- lines.push('Use "memorylayer projects add <path>" to register a project.');
126
+ lines.push('Use "neuronlayer projects add <path>" to register a project.');
127
127
 
128
128
  return {
129
129
  success: true,
@@ -144,7 +144,7 @@ export function exportDecisions(
144
144
  if (!activeProject) {
145
145
  return {
146
146
  success: false,
147
- message: 'No project specified and no active project. Use "memorylayer projects switch <id>" first.'
147
+ message: 'No project specified and no active project. Use "neuronlayer projects switch <id>" first.'
148
148
  };
149
149
  }
150
150
  targetPath = activeProject.path;
@@ -155,17 +155,23 @@ export function exportDecisions(
155
155
  if (!projectInfo) {
156
156
  return {
157
157
  success: false,
158
- message: `Project not registered: ${targetPath}. Use "memorylayer projects add ${targetPath}" first.`
158
+ message: `Project not registered: ${targetPath}. Use "neuronlayer projects add ${targetPath}" first.`
159
159
  };
160
160
  }
161
161
 
162
- // Open database and get decisions
163
- const dbPath = join(projectInfo.dataDir, 'memorylayer.db');
162
+ // Open database and get decisions (check both new and old names)
163
+ let dbPath = join(projectInfo.dataDir, 'neuronlayer.db');
164
164
  if (!existsSync(dbPath)) {
165
- return {
166
- success: false,
167
- message: `Project database not found. Has the project been indexed?`
168
- };
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
+ }
169
175
  }
170
176
 
171
177
  const db = initializeDatabase(dbPath);
@@ -210,7 +216,7 @@ export function showProject(projectId?: string): CommandResult {
210
216
  success: false,
211
217
  message: projectId
212
218
  ? `Project not found: ${projectId}`
213
- : 'No active project. Use "memorylayer projects switch <id>" first.'
219
+ : 'No active project. Use "neuronlayer projects switch <id>" first.'
214
220
  };
215
221
  }
216
222
 
@@ -272,6 +278,40 @@ function configureMCPClient(
272
278
  }
273
279
  }
274
280
 
281
+ // Helper to configure project-local .mcp.json for Claude Code
282
+ function configureProjectMCP(
283
+ configPath: string,
284
+ projectPath: string
285
+ ): { success: boolean; message: string } {
286
+ let config: { mcpServers?: Record<string, unknown> } = { mcpServers: {} };
287
+
288
+ try {
289
+ if (existsSync(configPath)) {
290
+ const content = readFileSync(configPath, 'utf-8');
291
+ config = JSON.parse(content);
292
+ }
293
+ } catch {
294
+ // Config doesn't exist or is invalid, start fresh
295
+ }
296
+
297
+ if (!config.mcpServers) {
298
+ config.mcpServers = {};
299
+ }
300
+
301
+ // Use simple name since this is project-specific
302
+ config.mcpServers['neuronlayer'] = {
303
+ command: 'npx',
304
+ args: ['-y', 'neuronlayer', '--project', '.']
305
+ };
306
+
307
+ try {
308
+ writeFileSync(configPath, JSON.stringify(config, null, 2));
309
+ return { success: true, message: `Claude Code: ${configPath} (project-local)` };
310
+ } catch (err) {
311
+ return { success: false, message: `Claude Code: Failed - ${err instanceof Error ? err.message : String(err)}` };
312
+ }
313
+ }
314
+
275
315
  // Initialize neuronlayer for current project + auto-configure Claude Desktop & OpenCode
276
316
  export function initProject(projectPath?: string): CommandResult {
277
317
  const targetPath = projectPath || process.cwd();
@@ -315,14 +355,29 @@ export function initProject(projectPath?: string): CommandResult {
315
355
  failedClients.push(openCodeResult.message);
316
356
  }
317
357
 
318
- // 4. Configure Claude Code (CLI) - uses same config location as Claude Desktop on some systems
319
- // Also check for .claude.json in home directory
320
- const claudeCodeConfigPath = join(homedir(), '.claude.json');
321
- const claudeCodeResult = configureMCPClient('Claude Code', claudeCodeConfigPath, serverName, targetPath);
358
+ // 4. Configure Claude Code (CLI) - use project-local .mcp.json
359
+ // This ensures only the current project's NeuronLayer connects
360
+ const claudeCodeConfigPath = join(targetPath, '.mcp.json');
361
+ const claudeCodeResult = configureProjectMCP(claudeCodeConfigPath, targetPath);
322
362
  if (claudeCodeResult.success) {
323
363
  configuredClients.push(claudeCodeResult.message);
324
364
  }
325
365
 
366
+ // 5. Configure Cursor
367
+ let cursorConfigPath: string;
368
+ if (platform === 'win32') {
369
+ cursorConfigPath = join(homedir(), 'AppData', 'Roaming', 'Cursor', 'User', 'globalStorage', 'cursor.mcp', 'mcp.json');
370
+ } else if (platform === 'darwin') {
371
+ cursorConfigPath = join(homedir(), 'Library', 'Application Support', 'Cursor', 'User', 'globalStorage', 'cursor.mcp', 'mcp.json');
372
+ } else {
373
+ cursorConfigPath = join(homedir(), '.config', 'Cursor', 'User', 'globalStorage', 'cursor.mcp', 'mcp.json');
374
+ }
375
+
376
+ const cursorResult = configureMCPClient('Cursor', cursorConfigPath, serverName, targetPath);
377
+ if (cursorResult.success) {
378
+ configuredClients.push(cursorResult.message);
379
+ }
380
+
326
381
  // Build result message
327
382
  let message = `
328
383
  NeuronLayer initialized!
@@ -351,14 +406,15 @@ ${configuredClients.map(c => ' ✓ ' + c).join('\n')}
351
406
  // Print help
352
407
  export function printHelp(): void {
353
408
  console.log(`
354
- MemoryLayer CLI - Persistent Memory for AI Coding Assistants
409
+ NeuronLayer CLI - Code Intelligence for AI Coding Assistants
355
410
 
356
411
  USAGE:
357
- memorylayer [command] [options]
412
+ neuronlayer [command] [options]
358
413
 
359
414
  COMMANDS:
360
- init [path] Initialize project + auto-configure Claude Desktop
361
- (no command) Start MCP server for Claude Desktop
415
+ init [path] Initialize project + auto-configure AI tools
416
+ serve [options] Start HTTP API server (for non-MCP tools)
417
+ (no command) Start MCP server
362
418
  projects list List all registered projects
363
419
  projects add <path> Add a project to the registry
364
420
  projects remove <id> Remove a project from the registry
@@ -370,6 +426,7 @@ COMMANDS:
370
426
 
371
427
  OPTIONS:
372
428
  --project, -p <path> Path to the project directory
429
+ --port <number> Port for HTTP server (default: 3333)
373
430
  --output, -o <dir> Output directory for exports
374
431
  --format <type> ADR format: madr, nygard, simple
375
432
 
@@ -382,19 +439,23 @@ EXAMPLES:
382
439
  neuronlayer --project /path/to/project
383
440
 
384
441
  # List all projects
385
- memorylayer projects list
442
+ neuronlayer projects list
386
443
 
387
444
  # Add a new project
388
- memorylayer projects add /path/to/my-project
445
+ neuronlayer projects add /path/to/my-project
389
446
 
390
447
  # Switch active project
391
- memorylayer projects switch abc123
448
+ neuronlayer projects switch abc123
392
449
 
393
450
  # Export decisions to ADR files
394
- memorylayer export --format madr
451
+ neuronlayer export --format madr
395
452
 
396
453
  # Discover projects
397
- memorylayer projects discover
454
+ neuronlayer projects discover
455
+
456
+ # Start HTTP API server (for tools without MCP support)
457
+ neuronlayer serve --project /path/to/project
458
+ neuronlayer serve --port 8080
398
459
 
399
460
  For more information, visit: https://github.com/abhisavakar/neuronlayer
400
461
  `);
@@ -429,7 +490,7 @@ export function executeCLI(args: string[]): void {
429
490
  const path = args[2];
430
491
  if (!path) {
431
492
  console.error('Error: Project path required.');
432
- console.error('Usage: memorylayer projects add <path>');
493
+ console.error('Usage: neuronlayer projects add <path>');
433
494
  process.exit(1);
434
495
  }
435
496
  const result = addProject(path);
@@ -441,7 +502,7 @@ export function executeCLI(args: string[]): void {
441
502
  const id = args[2];
442
503
  if (!id) {
443
504
  console.error('Error: Project ID required.');
444
- console.error('Usage: memorylayer projects remove <id>');
505
+ console.error('Usage: neuronlayer projects remove <id>');
445
506
  process.exit(1);
446
507
  }
447
508
  const result = removeProject(id);
@@ -453,7 +514,7 @@ export function executeCLI(args: string[]): void {
453
514
  const id = args[2];
454
515
  if (!id) {
455
516
  console.error('Error: Project ID required.');
456
- console.error('Usage: memorylayer projects switch <id>');
517
+ console.error('Usage: neuronlayer projects switch <id>');
457
518
  process.exit(1);
458
519
  }
459
520
  const result = switchProject(id);
@@ -107,7 +107,7 @@ export class ADRExporter {
107
107
  lines.push('');
108
108
  lines.push('---');
109
109
  lines.push('');
110
- lines.push('*Generated by MemoryLayer*');
110
+ lines.push('*Generated by NeuronLayer*');
111
111
 
112
112
  writeFileSync(indexPath, lines.join('\n'));
113
113
  return indexPath;
@@ -157,7 +157,7 @@ ${decision.supersededBy ? `## Superseded By
157
157
  This decision has been superseded by [ADR ${decision.supersededBy}](./${decision.supersededBy}.md).
158
158
  ` : ''}
159
159
  ---
160
- *Exported from MemoryLayer*
160
+ *Exported from NeuronLayer*
161
161
  `;
162
162
  }
163
163
 
@@ -192,7 +192,7 @@ ${decision.files.length > 0 ? `## Related Files
192
192
  ${decision.files.map(f => `- ${f}`).join('\n')}
193
193
  ` : ''}
194
194
  ---
195
- *Exported from MemoryLayer*
195
+ *Exported from NeuronLayer*
196
196
  `;
197
197
  }
198
198
 
@@ -216,7 +216,7 @@ ${decision.files.length > 0 ? `## Related Files
216
216
  ${decision.files.map(f => `- \`${f}\``).join('\n')}
217
217
  ` : ''}
218
218
  ---
219
- *Exported from MemoryLayer*
219
+ *Exported from NeuronLayer*
220
220
  `;
221
221
  }
222
222
 
@@ -1,5 +1,5 @@
1
1
  import { join, basename } from 'path';
2
- import { existsSync, mkdirSync, readFileSync, statSync } from 'fs';
2
+ import { existsSync, mkdirSync, readFileSync, statSync, renameSync } from 'fs';
3
3
  import { initializeDatabase, closeDatabase } from '../storage/database.js';
4
4
  import { Tier1Storage } from '../storage/tier1.js';
5
5
  import { Tier2Storage } from '../storage/tier2.js';
@@ -24,15 +24,15 @@ import { DejaVuDetector, type DejaVuMatch } from './deja-vu.js';
24
24
  import { CodeVerifier, type VerificationResult, type VerificationCheck, type ImportVerification, type SecurityScanResult, type DependencyCheckResult } from './code-verifier.js';
25
25
  import { GitStalenessChecker, ActivityGate } from './refresh/index.js';
26
26
  import { detectLanguage, getPreview, countLines } from '../utils/files.js';
27
- import type { MemoryLayerConfig, AssembledContext, Decision, ProjectSummary, SearchResult, CodeSymbol, SymbolKind, ActiveFeatureContext, HotContext } from '../types/index.js';
27
+ import type { NeuronLayerConfig, AssembledContext, Decision, ProjectSummary, SearchResult, CodeSymbol, SymbolKind, ActiveFeatureContext, HotContext } from '../types/index.js';
28
28
  import type { ArchitectureDoc, ComponentDoc, DailyChangelog, ChangelogOptions, ValidationResult, ActivityResult, UndocumentedItem, ContextHealth, CompactionResult, CompactionOptions, CriticalContext, DriftResult, ConfidenceResult, ConfidenceLevel, ConfidenceSources, ConflictResult, ChangeQueryResult, ChangeQueryOptions, Diagnosis, PastBug, FixSuggestion, Change, Pattern, PatternCategory, PatternValidationResult, ExistingFunction, TestInfo, TestFramework, TestValidationResult, TestUpdate, TestCoverage } from '../types/documentation.js';
29
29
  import type Database from 'better-sqlite3';
30
30
 
31
31
  // Re-export types for external use
32
32
  export type { GhostInsight, ConflictWarning, DejaVuMatch, ResurrectedContext, VerificationResult, VerificationCheck, ImportVerification, SecurityScanResult, DependencyCheckResult };
33
33
 
34
- export class MemoryLayerEngine {
35
- private config: MemoryLayerConfig;
34
+ export class NeuronLayerEngine {
35
+ private config: NeuronLayerConfig;
36
36
  private db: Database.Database;
37
37
  private tier1: Tier1Storage;
38
38
  private tier2: Tier2Storage;
@@ -60,7 +60,7 @@ export class MemoryLayerEngine {
60
60
  private initializationStatus: 'pending' | 'indexing' | 'ready' | 'error' = 'pending';
61
61
  private indexingProgress: { indexed: number; total: number } = { indexed: 0, total: 0 };
62
62
 
63
- constructor(config: MemoryLayerConfig) {
63
+ constructor(config: NeuronLayerConfig) {
64
64
  this.config = config;
65
65
 
66
66
  // Ensure data directory exists
@@ -68,8 +68,22 @@ export class MemoryLayerEngine {
68
68
  mkdirSync(config.dataDir, { recursive: true });
69
69
  }
70
70
 
71
- // Initialize database
72
- const dbPath = join(config.dataDir, 'memorylayer.db');
71
+ // Initialize database (with migration from old name)
72
+ let dbPath = join(config.dataDir, 'neuronlayer.db');
73
+ const oldDbPath = join(config.dataDir, 'memorylayer.db');
74
+
75
+ // Migrate from old database name if it exists
76
+ if (!existsSync(dbPath) && existsSync(oldDbPath)) {
77
+ try {
78
+ console.error('Migrating database from memorylayer.db to neuronlayer.db...');
79
+ renameSync(oldDbPath, dbPath);
80
+ } catch (err) {
81
+ // If rename fails (file locked), use the old database path
82
+ console.error('Migration skipped (file in use), using existing database');
83
+ dbPath = oldDbPath;
84
+ }
85
+ }
86
+
73
87
  this.db = initializeDatabase(dbPath);
74
88
 
75
89
  // Initialize storage tiers
@@ -214,6 +228,16 @@ export class MemoryLayerEngine {
214
228
  this.updateProjectStats();
215
229
  // Extract decisions from git and comments
216
230
  this.extractDecisions().catch(err => console.error('Decision extraction error:', err));
231
+
232
+ // Index tests after code indexing is complete
233
+ try {
234
+ const testResult = this.testAwareness.refreshIndex();
235
+ if (testResult.testsIndexed > 0) {
236
+ console.error(`Test index: ${testResult.testsIndexed} tests (${testResult.framework})`);
237
+ }
238
+ } catch (err) {
239
+ console.error('Test indexing error:', err);
240
+ }
217
241
  });
218
242
 
219
243
  this.indexer.on('fileIndexed', (path) => {
@@ -224,6 +248,22 @@ export class MemoryLayerEngine {
224
248
  this.summarizer.invalidateSummaryByPath(path);
225
249
  });
226
250
 
251
+ this.indexer.on('fileImpact', (impact: { file: string; affectedFiles: string[]; affectedCount: number }) => {
252
+ // Log impact warning for file changes
253
+ if (impact.affectedCount > 0) {
254
+ console.error(`[Impact] ${impact.file} changed → ${impact.affectedCount} file(s) may be affected`);
255
+ if (impact.affectedCount <= 5) {
256
+ impact.affectedFiles.forEach(f => console.error(` → ${f}`));
257
+ } else {
258
+ impact.affectedFiles.slice(0, 3).forEach(f => console.error(` → ${f}`));
259
+ console.error(` ... and ${impact.affectedCount - 3} more`);
260
+ }
261
+
262
+ // Track impact in ghost mode for proactive warnings
263
+ this.ghostMode.onFileImpact(impact.file, impact.affectedFiles);
264
+ }
265
+ });
266
+
227
267
  this.indexer.on('error', (error) => {
228
268
  console.error('Indexer error:', error);
229
269
  });
@@ -232,7 +272,7 @@ export class MemoryLayerEngine {
232
272
  async initialize(): Promise<void> {
233
273
  if (this.initialized) return;
234
274
 
235
- console.error(`Initializing MemoryLayer for: ${this.config.projectPath}`);
275
+ console.error(`Initializing NeuronLayer for: ${this.config.projectPath}`);
236
276
 
237
277
  try {
238
278
  // Perform initial indexing
@@ -274,7 +314,7 @@ export class MemoryLayerEngine {
274
314
 
275
315
  this.initialized = true;
276
316
  this.initializationStatus = 'ready';
277
- console.error('MemoryLayer initialized');
317
+ console.error('NeuronLayer initialized');
278
318
  } catch (error) {
279
319
  this.initializationStatus = 'error';
280
320
  throw error;
@@ -727,6 +767,16 @@ export class MemoryLayerEngine {
727
767
  return { imports, importedBy, symbols };
728
768
  }
729
769
 
770
+ // Find circular dependencies in the project
771
+ findCircularDependencies(): Array<string[]> {
772
+ return this.tier2.findCircularDependencies();
773
+ }
774
+
775
+ // Get transitive dependents (all files affected by changing a file)
776
+ getTransitiveDependents(filePath: string, maxDepth: number = 3): Array<{ file: string; depth: number; imports: string[] }> {
777
+ return this.tier2.getTransitiveDependents(filePath, maxDepth);
778
+ }
779
+
730
780
  // Phase 2: Get symbol count
731
781
  getSymbolCount(): number {
732
782
  return this.tier2.getSymbolCount();
@@ -1586,7 +1636,7 @@ export class MemoryLayerEngine {
1586
1636
  }
1587
1637
 
1588
1638
  shutdown(): void {
1589
- console.error('Shutting down MemoryLayer...');
1639
+ console.error('Shutting down NeuronLayer...');
1590
1640
  this.indexer.stopWatching();
1591
1641
  this.activityGate.shutdown();
1592
1642
  this.tier1.save();
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Silently tracks what files Claude reads/writes. When code is written that
5
5
  * touches a file with recorded decisions, automatically checks for conflicts.
6
- * Makes MemoryLayer feel "telepathic" by surfacing relevant context proactively.
6
+ * Makes NeuronLayer feel "telepathic" by surfacing relevant context proactively.
7
7
  */
8
8
 
9
9
  import type { Decision } from '../types/index.js';
@@ -64,9 +64,16 @@ const TECH_PATTERNS = [
64
64
  { pattern: /\b(sass|scss|less)\b/i, category: 'styling', term: 'CSS preprocessor' },
65
65
  ];
66
66
 
67
+ export interface FileImpact {
68
+ changedFile: string;
69
+ affectedFiles: string[];
70
+ timestamp: Date;
71
+ }
72
+
67
73
  export class GhostMode {
68
74
  private activeFiles: Map<string, FileContext> = new Map();
69
75
  private recentDecisions: Map<string, Decision[]> = new Map();
76
+ private recentImpacts: Map<string, FileImpact> = new Map(); // Track file impacts
70
77
  private tier2: Tier2Storage;
71
78
  private embeddingGenerator: EmbeddingGenerator;
72
79
 
@@ -74,12 +81,58 @@ export class GhostMode {
74
81
  private readonly MAX_ACTIVE_FILES = 20;
75
82
  private readonly FILE_TTL_MS = 60 * 60 * 1000; // 1 hour
76
83
  private readonly DECISION_CACHE_SIZE = 50;
84
+ private readonly IMPACT_TTL_MS = 30 * 60 * 1000; // 30 minutes
77
85
 
78
86
  constructor(tier2: Tier2Storage, embeddingGenerator: EmbeddingGenerator) {
79
87
  this.tier2 = tier2;
80
88
  this.embeddingGenerator = embeddingGenerator;
81
89
  }
82
90
 
91
+ /**
92
+ * Called when a file change impacts other files
93
+ */
94
+ onFileImpact(changedFile: string, affectedFiles: string[]): void {
95
+ const impact: FileImpact = {
96
+ changedFile,
97
+ affectedFiles,
98
+ timestamp: new Date()
99
+ };
100
+
101
+ // Store impact for each affected file
102
+ for (const file of affectedFiles) {
103
+ this.recentImpacts.set(file, impact);
104
+ }
105
+
106
+ // Evict old impacts
107
+ this.evictStaleImpacts();
108
+ }
109
+
110
+ /**
111
+ * Check if a file was recently impacted by changes to another file
112
+ */
113
+ getImpactWarning(filePath: string): FileImpact | null {
114
+ const impact = this.recentImpacts.get(filePath);
115
+ if (!impact) return null;
116
+
117
+ // Check if still within TTL
118
+ const age = Date.now() - impact.timestamp.getTime();
119
+ if (age > this.IMPACT_TTL_MS) {
120
+ this.recentImpacts.delete(filePath);
121
+ return null;
122
+ }
123
+
124
+ return impact;
125
+ }
126
+
127
+ private evictStaleImpacts(): void {
128
+ const now = Date.now();
129
+ for (const [file, impact] of this.recentImpacts) {
130
+ if (now - impact.timestamp.getTime() > this.IMPACT_TTL_MS) {
131
+ this.recentImpacts.delete(file);
132
+ }
133
+ }
134
+ }
135
+
83
136
  /**
84
137
  * Called when any file is read - silently track and pre-fetch decisions
85
138
  */
@@ -3,7 +3,7 @@ import { join, basename, resolve } from 'path';
3
3
  import { createHash } from 'crypto';
4
4
  import { homedir } from 'os';
5
5
  import Database from 'better-sqlite3';
6
- import type { MemoryLayerConfig } from '../types/index.js';
6
+ import type { NeuronLayerConfig } from '../types/index.js';
7
7
 
8
8
  export interface ProjectInfo {
9
9
  id: string;
@@ -177,7 +177,7 @@ export class ProjectManager {
177
177
  }
178
178
 
179
179
  // Get config for a project
180
- getProjectConfig(projectPath: string): MemoryLayerConfig {
180
+ getProjectConfig(projectPath: string): NeuronLayerConfig {
181
181
  const normalizedPath = resolve(projectPath);
182
182
  const dataDir = this.getProjectDataDir(normalizedPath);
183
183
 
@@ -269,7 +269,11 @@ export class ProjectManager {
269
269
  const result: Array<{ project: ProjectInfo; db: Database.Database }> = [];
270
270
 
271
271
  for (const project of this.listProjects()) {
272
- const dbPath = join(project.dataDir, 'memorylayer.db');
272
+ // Check both new and old database names
273
+ let dbPath = join(project.dataDir, 'neuronlayer.db');
274
+ if (!existsSync(dbPath)) {
275
+ dbPath = join(project.dataDir, 'memorylayer.db');
276
+ }
273
277
 
274
278
  if (existsSync(dbPath)) {
275
279
  try {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Intelligent Refresh System for MemoryLayer
2
+ * Intelligent Refresh System for NeuronLayer
3
3
  *
4
4
  * This module provides a tiered refresh architecture:
5
5
  *
package/src/index.ts CHANGED
@@ -1,7 +1,27 @@
1
1
  import { MCPServer } from './server/mcp.js';
2
+ import { HTTPServer } from './server/http.js';
2
3
  import { getDefaultConfig, parseArgs } from './utils/config.js';
3
4
  import { executeCLI, printHelp } from './cli/commands.js';
4
5
 
6
+ function parseServeArgs(args: string[]): { projectPath: string; port: number } {
7
+ let projectPath = process.cwd();
8
+ let port = 3333;
9
+
10
+ for (let i = 0; i < args.length; i++) {
11
+ const arg = args[i];
12
+ const nextArg = args[i + 1];
13
+ if ((arg === '--project' || arg === '-p') && nextArg) {
14
+ projectPath = nextArg;
15
+ i++;
16
+ } else if (arg === '--port' && nextArg) {
17
+ port = parseInt(nextArg) || 3333;
18
+ i++;
19
+ }
20
+ }
21
+
22
+ return { projectPath, port };
23
+ }
24
+
5
25
  async function main(): Promise<void> {
6
26
  const args = process.argv.slice(2);
7
27
 
@@ -15,10 +35,31 @@ async function main(): Promise<void> {
15
35
  return;
16
36
  }
17
37
 
38
+ // Handle serve command - start HTTP API server
39
+ if (firstArg === 'serve') {
40
+ const { projectPath, port } = parseServeArgs(args.slice(1));
41
+ const config = getDefaultConfig(projectPath);
42
+
43
+ console.log('NeuronLayer HTTP API starting...');
44
+ console.log(`Project: ${config.projectPath}`);
45
+ console.log(`Data directory: ${config.dataDir}`);
46
+ console.log('');
47
+
48
+ const server = new HTTPServer(config, port);
49
+ try {
50
+ await server.start();
51
+ } catch (error) {
52
+ console.error('Failed to start HTTP server:', error);
53
+ process.exit(1);
54
+ }
55
+ return;
56
+ }
57
+
18
58
  // No arguments and not piped - show help
19
59
  if (args.length === 0 && process.stdin.isTTY) {
20
60
  printHelp();
21
- console.log('\nTo start as MCP server, use: memorylayer --project <path>\n');
61
+ console.log('\nTo start as MCP server, use: neuronlayer --project <path>');
62
+ console.log('To start HTTP API, use: neuronlayer serve --project <path>\n');
22
63
  return;
23
64
  }
24
65
 
@@ -28,7 +69,7 @@ async function main(): Promise<void> {
28
69
  // Get configuration
29
70
  const config = getDefaultConfig(projectPath);
30
71
 
31
- console.error('MemoryLayer starting...');
72
+ console.error('NeuronLayer starting...');
32
73
  console.error(`Project: ${config.projectPath}`);
33
74
  console.error(`Data directory: ${config.dataDir}`);
34
75
 
@@ -38,7 +79,7 @@ async function main(): Promise<void> {
38
79
  try {
39
80
  await server.start();
40
81
  } catch (error) {
41
- console.error('Failed to start MemoryLayer:', error);
82
+ console.error('Failed to start NeuronLayer:', error);
42
83
  process.exit(1);
43
84
  }
44
85
  }