@claude-flow/cli 3.0.0-alpha.62 → 3.0.0-alpha.64

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.
@@ -76,7 +76,7 @@ const storeCommand = {
76
76
  });
77
77
  }
78
78
  if (!value) {
79
- output.printError('Value is required. Use --value or -v');
79
+ output.printError('Value is required. Use --value');
80
80
  return { success: false, exitCode: 1 };
81
81
  }
82
82
  const storeData = {
@@ -90,17 +90,24 @@ const storeCommand = {
90
90
  size: Buffer.byteLength(value, 'utf8')
91
91
  };
92
92
  output.printInfo(`Storing in ${namespace}/${key}...`);
93
- if (asVector) {
94
- output.writeln(output.dim(' Generating embedding vector...'));
95
- output.writeln(output.dim(' Indexing with HNSW (M=16, ef=200)...'));
96
- }
97
- // Call MCP memory/store tool for real persistence
93
+ // Use direct sql.js storage with automatic embedding generation
98
94
  try {
99
- const result = await callMCPTool('memory/store', {
95
+ const { storeEntry } = await import('../memory/memory-initializer.js');
96
+ if (asVector) {
97
+ output.writeln(output.dim(' Generating embedding vector...'));
98
+ }
99
+ const result = await storeEntry({
100
100
  key,
101
101
  value,
102
- metadata: { namespace, tags, ttl, asVector, size: storeData.size }
102
+ namespace,
103
+ generateEmbeddingFlag: true, // Always generate embeddings for semantic search
104
+ tags,
105
+ ttl
103
106
  });
107
+ if (!result.success) {
108
+ output.printError(result.error || 'Failed to store');
109
+ return { success: false, exitCode: 1 };
110
+ }
104
111
  output.writeln();
105
112
  output.printTable({
106
113
  columns: [
@@ -113,13 +120,13 @@ const storeCommand = {
113
120
  { property: 'Size', val: `${storeData.size} bytes` },
114
121
  { property: 'TTL', val: ttl ? `${ttl}s` : 'None' },
115
122
  { property: 'Tags', val: tags.length > 0 ? tags.join(', ') : 'None' },
116
- { property: 'Vector', val: asVector ? 'Yes' : 'No' },
117
- { property: 'Total Entries', val: String(result.totalEntries || 1) }
123
+ { property: 'Vector', val: result.embedding ? `Yes (${result.embedding.dimensions}-dim)` : 'No' },
124
+ { property: 'ID', val: result.id.substring(0, 20) }
118
125
  ]
119
126
  });
120
127
  output.writeln();
121
128
  output.printSuccess('Data stored successfully');
122
- return { success: true, data: { ...storeData, ...result } };
129
+ return { success: true, data: { ...storeData, id: result.id, embedding: result.embedding } };
123
130
  }
124
131
  catch (error) {
125
132
  output.printError(`Failed to store: ${error instanceof Error ? error.message : 'Unknown error'}`);
@@ -154,42 +161,36 @@ const retrieveCommand = {
154
161
  output.printError('Key is required');
155
162
  return { success: false, exitCode: 1 };
156
163
  }
157
- // Call MCP memory/retrieve tool for real data
164
+ // Use sql.js directly for consistent data access
158
165
  try {
159
- const result = await callMCPTool('memory/retrieve', { key });
160
- if (!result.found) {
166
+ const { getEntry } = await import('../memory/memory-initializer.js');
167
+ const result = await getEntry({ key, namespace });
168
+ if (!result.success) {
169
+ output.printError(`Failed to retrieve: ${result.error}`);
170
+ return { success: false, exitCode: 1 };
171
+ }
172
+ if (!result.found || !result.entry) {
161
173
  output.printWarning(`Key not found: ${key}`);
162
174
  return { success: false, exitCode: 1, data: { key, found: false } };
163
175
  }
164
- const data = {
165
- key: result.key,
166
- namespace,
167
- value: result.value,
168
- metadata: {
169
- storedAt: result.storedAt || 'Unknown',
170
- accessCount: result.accessCount || 0,
171
- lastAccessed: new Date().toISOString(),
172
- ...(result.metadata || {})
173
- }
174
- };
176
+ const entry = result.entry;
175
177
  if (ctx.flags.format === 'json') {
176
- output.printJson(data);
177
- return { success: true, data };
178
+ output.printJson(entry);
179
+ return { success: true, data: entry };
178
180
  }
179
- const metaTags = result.metadata?.tags || [];
180
- const metaSize = result.metadata?.size || String(data.value).length;
181
181
  output.writeln();
182
182
  output.printBox([
183
- `Namespace: ${namespace}`,
184
- `Key: ${data.key}`,
185
- `Size: ${metaSize} bytes`,
186
- `Access Count: ${data.metadata.accessCount}`,
187
- `Tags: ${metaTags.length > 0 ? metaTags.join(', ') : 'None'}`,
183
+ `Namespace: ${entry.namespace}`,
184
+ `Key: ${entry.key}`,
185
+ `Size: ${entry.content.length} bytes`,
186
+ `Access Count: ${entry.accessCount}`,
187
+ `Tags: ${entry.tags.length > 0 ? entry.tags.join(', ') : 'None'}`,
188
+ `Vector: ${entry.hasEmbedding ? 'Yes' : 'No'}`,
188
189
  '',
189
190
  output.bold('Value:'),
190
- typeof data.value === 'string' ? data.value : JSON.stringify(data.value, null, 2)
191
+ entry.content
191
192
  ].join('\n'), 'Memory Entry');
192
- return { success: true, data };
193
+ return { success: true, data: entry };
193
194
  }
194
195
  catch (error) {
195
196
  output.printError(`Failed to retrieve: ${error instanceof Error ? error.message : 'Unknown error'}`);
@@ -243,36 +244,45 @@ const searchCommand = {
243
244
  ],
244
245
  action: async (ctx) => {
245
246
  const query = ctx.flags.query || ctx.args[0];
246
- const namespace = ctx.flags.namespace;
247
- const limit = ctx.flags.limit;
248
- const threshold = ctx.flags.threshold;
249
- const searchType = ctx.flags.type;
247
+ const namespace = ctx.flags.namespace || 'all';
248
+ const limit = ctx.flags.limit || 10;
249
+ const threshold = ctx.flags.threshold || 0.3;
250
+ const searchType = ctx.flags.type || 'semantic';
250
251
  if (!query) {
251
252
  output.printError('Query is required. Use --query or -q');
252
253
  return { success: false, exitCode: 1 };
253
254
  }
254
255
  output.printInfo(`Searching: "${query}" (${searchType})`);
255
256
  output.writeln();
256
- // Call MCP memory/search tool for real results
257
+ // Use direct sql.js search with vector similarity
257
258
  try {
258
- const searchResult = await callMCPTool('memory/search', { query, limit });
259
+ const { searchEntries } = await import('../memory/memory-initializer.js');
260
+ const searchResult = await searchEntries({
261
+ query,
262
+ namespace,
263
+ limit,
264
+ threshold
265
+ });
266
+ if (!searchResult.success) {
267
+ output.printError(searchResult.error || 'Search failed');
268
+ return { success: false, exitCode: 1 };
269
+ }
259
270
  const results = searchResult.results.map(r => ({
260
271
  key: r.key,
261
272
  score: r.score,
262
- namespace: namespace || 'default',
263
- preview: typeof r.value === 'string'
264
- ? r.value.substring(0, 40) + (r.value.length > 40 ? '...' : '')
265
- : JSON.stringify(r.value).substring(0, 40)
273
+ namespace: r.namespace,
274
+ preview: r.content
266
275
  }));
267
276
  if (ctx.flags.format === 'json') {
268
- output.printJson({ query, searchType, results, searchTime: searchResult.searchTime });
277
+ output.printJson({ query, searchType, results, searchTime: `${searchResult.searchTime}ms` });
269
278
  return { success: true, data: results };
270
279
  }
271
280
  // Performance stats
272
- output.writeln(output.dim(` Search time: ${searchResult.searchTime}`));
281
+ output.writeln(output.dim(` Search time: ${searchResult.searchTime}ms`));
273
282
  output.writeln();
274
283
  if (results.length === 0) {
275
284
  output.printWarning('No results found');
285
+ output.writeln(output.dim('Try: claude-flow memory store -k "key" --value "data"'));
276
286
  return { success: true, data: [] };
277
287
  }
278
288
  output.printTable({
@@ -323,26 +333,33 @@ const listCommand = {
323
333
  action: async (ctx) => {
324
334
  const namespace = ctx.flags.namespace;
325
335
  const limit = ctx.flags.limit;
326
- // Call MCP memory/list tool for real entries
336
+ // Use sql.js directly for consistent data access
327
337
  try {
328
- const listResult = await callMCPTool('memory/list', { limit, offset: 0 });
338
+ const { listEntries } = await import('../memory/memory-initializer.js');
339
+ const listResult = await listEntries({ namespace, limit, offset: 0 });
340
+ if (!listResult.success) {
341
+ output.printError(`Failed to list: ${listResult.error}`);
342
+ return { success: false, exitCode: 1 };
343
+ }
329
344
  // Format entries for display
330
345
  const entries = listResult.entries.map(e => ({
331
346
  key: e.key,
332
- namespace: namespace || 'default',
333
- size: e.preview.length + ' B',
347
+ namespace: e.namespace,
348
+ size: e.size + ' B',
349
+ vector: e.hasEmbedding ? '✓' : '-',
334
350
  accessCount: e.accessCount,
335
- updated: formatRelativeTime(e.storedAt)
351
+ updated: formatRelativeTime(e.updatedAt)
336
352
  }));
337
353
  if (ctx.flags.format === 'json') {
338
- output.printJson(entries);
339
- return { success: true, data: entries };
354
+ output.printJson(listResult.entries);
355
+ return { success: true, data: listResult.entries };
340
356
  }
341
357
  output.writeln();
342
358
  output.writeln(output.bold('Memory Entries'));
343
359
  output.writeln();
344
360
  if (entries.length === 0) {
345
361
  output.printWarning('No entries found');
362
+ output.printInfo('Store data: claude-flow memory store -k "key" --value "data"');
346
363
  return { success: true, data: [] };
347
364
  }
348
365
  output.printTable({
@@ -350,6 +367,7 @@ const listCommand = {
350
367
  { key: 'key', header: 'Key', width: 25 },
351
368
  { key: 'namespace', header: 'Namespace', width: 12 },
352
369
  { key: 'size', header: 'Size', width: 10, align: 'right' },
370
+ { key: 'vector', header: 'Vector', width: 8, align: 'center' },
353
371
  { key: 'accessCount', header: 'Accessed', width: 10, align: 'right' },
354
372
  { key: 'updated', header: 'Updated', width: 12 }
355
373
  ],
@@ -357,7 +375,7 @@ const listCommand = {
357
375
  });
358
376
  output.writeln();
359
377
  output.printInfo(`Showing ${entries.length} of ${listResult.total} entries`);
360
- return { success: true, data: entries };
378
+ return { success: true, data: listResult.entries };
361
379
  }
362
380
  catch (error) {
363
381
  output.printError(`Failed to list: ${error instanceof Error ? error.message : 'Unknown error'}`);
@@ -946,14 +964,14 @@ const importCommand = {
946
964
  // Init subcommand - initialize memory database using sql.js
947
965
  const initMemoryCommand = {
948
966
  name: 'init',
949
- description: 'Initialize memory database with sql.js (WASM SQLite)',
967
+ description: 'Initialize memory database with sql.js (WASM SQLite) - includes vector embeddings, pattern learning, temporal decay',
950
968
  options: [
951
969
  {
952
970
  name: 'backend',
953
971
  short: 'b',
954
- description: 'Backend type: sqlite (default), hybrid, or agentdb',
972
+ description: 'Backend type: hybrid (default), sqlite, or agentdb',
955
973
  type: 'string',
956
- default: 'sqlite'
974
+ default: 'hybrid'
957
975
  },
958
976
  {
959
977
  name: 'path',
@@ -967,191 +985,177 @@ const initMemoryCommand = {
967
985
  description: 'Overwrite existing database',
968
986
  type: 'boolean',
969
987
  default: false
988
+ },
989
+ {
990
+ name: 'verbose',
991
+ description: 'Show detailed initialization output',
992
+ type: 'boolean',
993
+ default: false
994
+ },
995
+ {
996
+ name: 'verify',
997
+ description: 'Run verification tests after initialization',
998
+ type: 'boolean',
999
+ default: true
1000
+ },
1001
+ {
1002
+ name: 'load-embeddings',
1003
+ description: 'Pre-load ONNX embedding model (lazy by default)',
1004
+ type: 'boolean',
1005
+ default: false
970
1006
  }
971
1007
  ],
972
1008
  examples: [
973
- { command: 'claude-flow memory init', description: 'Initialize default SQLite database' },
974
- { command: 'claude-flow memory init -b hybrid', description: 'Initialize hybrid backend' },
975
- { command: 'claude-flow memory init -p ./data/memory.db', description: 'Custom path' }
1009
+ { command: 'claude-flow memory init', description: 'Initialize hybrid backend with all features' },
1010
+ { command: 'claude-flow memory init -b agentdb', description: 'Initialize AgentDB backend' },
1011
+ { command: 'claude-flow memory init -p ./data/memory.db --force', description: 'Reinitialize at custom path' },
1012
+ { command: 'claude-flow memory init --verbose --verify', description: 'Initialize with full verification' }
976
1013
  ],
977
1014
  action: async (ctx) => {
978
- const backend = ctx.flags.backend || 'sqlite';
1015
+ const backend = ctx.flags.backend || 'hybrid';
979
1016
  const customPath = ctx.flags.path;
980
1017
  const force = ctx.flags.force;
981
- const fs = await import('fs');
982
- const path = await import('path');
983
- // Determine database paths
984
- const swarmDir = path.join(process.cwd(), '.swarm');
985
- const claudeDir = path.join(process.cwd(), '.claude');
986
- const dbPath = customPath || path.join(swarmDir, 'memory.db');
987
- const dbDir = path.dirname(dbPath);
988
- // Check if already exists
989
- if (fs.existsSync(dbPath) && !force) {
990
- output.printWarning(`Memory database already exists at ${dbPath}`);
991
- output.printInfo('Use --force to reinitialize');
992
- return { success: false, exitCode: 1 };
993
- }
994
- output.printInfo(`Initializing ${backend} memory backend...`);
1018
+ const verbose = ctx.flags.verbose;
1019
+ const verify = ctx.flags.verify !== false; // Default true
1020
+ const loadEmbeddings = ctx.flags.loadEmbeddings;
1021
+ output.writeln();
1022
+ output.writeln(output.bold('Initializing Memory Database'));
1023
+ output.writeln(output.dim('─'.repeat(50)));
1024
+ const spinner = output.createSpinner({ text: 'Initializing schema...', spinner: 'dots' });
1025
+ spinner.start();
995
1026
  try {
996
- // Create directories
997
- if (!fs.existsSync(dbDir)) {
998
- fs.mkdirSync(dbDir, { recursive: true });
999
- output.writeln(output.dim(` Created directory: ${dbDir}`));
1027
+ // Import the memory initializer
1028
+ const { initializeMemoryDatabase, loadEmbeddingModel, verifyMemoryInit } = await import('../memory/memory-initializer.js');
1029
+ const result = await initializeMemoryDatabase({
1030
+ backend,
1031
+ dbPath: customPath,
1032
+ force,
1033
+ verbose
1034
+ });
1035
+ if (!result.success) {
1036
+ spinner.fail('Initialization failed');
1037
+ output.printError(result.error || 'Unknown error');
1038
+ return { success: false, exitCode: 1 };
1039
+ }
1040
+ spinner.succeed('Schema initialized');
1041
+ // Lazy load or pre-load embedding model
1042
+ if (loadEmbeddings) {
1043
+ const embeddingSpinner = output.createSpinner({ text: 'Loading embedding model...', spinner: 'dots' });
1044
+ embeddingSpinner.start();
1045
+ const embeddingResult = await loadEmbeddingModel({ verbose });
1046
+ if (embeddingResult.success) {
1047
+ embeddingSpinner.succeed(`Embedding model loaded: ${embeddingResult.modelName} (${embeddingResult.dimensions}-dim, ${embeddingResult.loadTime}ms)`);
1048
+ }
1049
+ else {
1050
+ embeddingSpinner.stop(output.warning(`Embedding model: ${embeddingResult.error || 'Using fallback'}`));
1051
+ }
1000
1052
  }
1001
- // Initialize database using sql.js (WASM SQLite)
1002
- output.writeln(output.dim(' Using sql.js (WASM SQLite - cross-platform, no native compilation)'));
1003
- // Create basic schema
1004
- const schema = `
1005
- -- Claude Flow V3 Memory Database
1006
- -- Backend: ${backend}
1007
- -- Created: ${new Date().toISOString()}
1008
-
1009
- -- Core memory entries
1010
- CREATE TABLE IF NOT EXISTS memory_entries (
1011
- id INTEGER PRIMARY KEY AUTOINCREMENT,
1012
- key TEXT NOT NULL UNIQUE,
1013
- value TEXT NOT NULL,
1014
- namespace TEXT DEFAULT 'default',
1015
- type TEXT DEFAULT 'text',
1016
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
1017
- updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
1018
- expires_at DATETIME,
1019
- metadata TEXT
1020
- );
1021
-
1022
- -- Vector embeddings for semantic search
1023
- CREATE TABLE IF NOT EXISTS vectors (
1024
- id INTEGER PRIMARY KEY AUTOINCREMENT,
1025
- entry_id INTEGER REFERENCES memory_entries(id),
1026
- embedding BLOB NOT NULL,
1027
- dimension INTEGER NOT NULL,
1028
- model TEXT DEFAULT 'local',
1029
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP
1030
- );
1031
-
1032
- -- Patterns for learning
1033
- CREATE TABLE IF NOT EXISTS patterns (
1034
- id INTEGER PRIMARY KEY AUTOINCREMENT,
1035
- pattern_type TEXT NOT NULL,
1036
- pattern_data TEXT NOT NULL,
1037
- confidence REAL DEFAULT 0.5,
1038
- usage_count INTEGER DEFAULT 0,
1039
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
1040
- last_used_at DATETIME
1041
- );
1042
-
1043
- -- Sessions for context persistence
1044
- CREATE TABLE IF NOT EXISTS sessions (
1045
- id TEXT PRIMARY KEY,
1046
- state TEXT NOT NULL,
1047
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
1048
- updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
1049
- );
1050
-
1051
- -- Learning trajectories
1052
- CREATE TABLE IF NOT EXISTS trajectories (
1053
- id INTEGER PRIMARY KEY AUTOINCREMENT,
1054
- session_id TEXT,
1055
- action TEXT NOT NULL,
1056
- outcome TEXT,
1057
- reward REAL DEFAULT 0,
1058
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP
1059
- );
1060
-
1061
- -- Indexes for performance
1062
- CREATE INDEX IF NOT EXISTS idx_memory_namespace ON memory_entries(namespace);
1063
- CREATE INDEX IF NOT EXISTS idx_memory_key ON memory_entries(key);
1064
- CREATE INDEX IF NOT EXISTS idx_patterns_type ON patterns(pattern_type);
1065
- CREATE INDEX IF NOT EXISTS idx_trajectories_session ON trajectories(session_id);
1066
-
1067
- -- Metadata table
1068
- CREATE TABLE IF NOT EXISTS metadata (
1069
- key TEXT PRIMARY KEY,
1070
- value TEXT NOT NULL
1071
- );
1072
-
1073
- INSERT OR REPLACE INTO metadata (key, value) VALUES
1074
- ('version', '3.0.0'),
1075
- ('backend', '${backend}'),
1076
- ('created_at', '${new Date().toISOString()}'),
1077
- ('sql_js', 'true');
1078
- `;
1079
- // Write schema to temp file for initialization
1080
- const schemaPath = path.join(dbDir, 'schema.sql');
1081
- fs.writeFileSync(schemaPath, schema);
1082
- // Create empty database file (sql.js will initialize it on first use)
1083
- if (force && fs.existsSync(dbPath)) {
1084
- fs.unlinkSync(dbPath);
1053
+ output.writeln();
1054
+ // Show features enabled with detailed capabilities
1055
+ const featureLines = [
1056
+ `Backend: ${result.backend}`,
1057
+ `Schema Version: ${result.schemaVersion}`,
1058
+ `Database Path: ${result.dbPath}`,
1059
+ '',
1060
+ output.bold('Features:'),
1061
+ ` Vector Embeddings: ${result.features.vectorEmbeddings ? output.success('✓ Enabled') : output.dim('✗ Disabled')}`,
1062
+ ` Pattern Learning: ${result.features.patternLearning ? output.success('✓ Enabled') : output.dim('✗ Disabled')}`,
1063
+ ` Temporal Decay: ${result.features.temporalDecay ? output.success('✓ Enabled') : output.dim('✗ Disabled')}`,
1064
+ ` HNSW Indexing: ${result.features.hnswIndexing ? output.success('✓ Enabled') : output.dim('✗ Disabled')}`,
1065
+ ` Migration Tracking: ${result.features.migrationTracking ? output.success('✓ Enabled') : output.dim('✗ Disabled')}`
1066
+ ];
1067
+ if (verbose) {
1068
+ featureLines.push('', output.bold('HNSW Configuration:'), ` M (connections): 16`, ` ef (construction): 200`, ` ef (search): 100`, ` Metric: cosine`, '', output.bold('Pattern Learning:'), ` Confidence scoring: 0.0 - 1.0`, ` Temporal decay: Half-life 30 days`, ` Pattern versioning: Enabled`, ` Types: task-routing, error-recovery, optimization, coordination, prediction`);
1069
+ }
1070
+ output.printBox(featureLines.join('\n'), 'Configuration');
1071
+ output.writeln();
1072
+ // Show tables created
1073
+ if (verbose && result.tablesCreated.length > 0) {
1074
+ output.writeln(output.bold('Tables Created:'));
1075
+ output.printTable({
1076
+ columns: [
1077
+ { key: 'table', header: 'Table', width: 22 },
1078
+ { key: 'purpose', header: 'Purpose', width: 38 }
1079
+ ],
1080
+ data: [
1081
+ { table: 'memory_entries', purpose: 'Core memory storage with embeddings' },
1082
+ { table: 'patterns', purpose: 'Learned patterns with confidence scores' },
1083
+ { table: 'pattern_history', purpose: 'Pattern versioning and evolution' },
1084
+ { table: 'trajectories', purpose: 'SONA learning trajectories' },
1085
+ { table: 'trajectory_steps', purpose: 'Individual trajectory steps' },
1086
+ { table: 'migration_state', purpose: 'Migration progress tracking' },
1087
+ { table: 'sessions', purpose: 'Context persistence' },
1088
+ { table: 'vector_indexes', purpose: 'HNSW index configuration' },
1089
+ { table: 'metadata', purpose: 'System metadata' }
1090
+ ]
1091
+ });
1092
+ output.writeln();
1093
+ output.writeln(output.bold('Indexes Created:'));
1094
+ output.printList(result.indexesCreated.slice(0, 8).map(idx => output.dim(idx)));
1095
+ if (result.indexesCreated.length > 8) {
1096
+ output.writeln(output.dim(` ... and ${result.indexesCreated.length - 8} more`));
1097
+ }
1098
+ output.writeln();
1099
+ }
1100
+ // Run verification if enabled
1101
+ if (verify) {
1102
+ const verifySpinner = output.createSpinner({ text: 'Verifying initialization...', spinner: 'dots' });
1103
+ verifySpinner.start();
1104
+ const verification = await verifyMemoryInit(result.dbPath, { verbose });
1105
+ if (verification.success) {
1106
+ verifySpinner.succeed(`Verification passed (${verification.summary.passed}/${verification.summary.total} tests)`);
1107
+ }
1108
+ else {
1109
+ verifySpinner.fail(`Verification failed (${verification.summary.failed}/${verification.summary.total} tests failed)`);
1110
+ }
1111
+ if (verbose || !verification.success) {
1112
+ output.writeln();
1113
+ output.writeln(output.bold('Verification Results:'));
1114
+ output.printTable({
1115
+ columns: [
1116
+ { key: 'status', header: '', width: 3 },
1117
+ { key: 'name', header: 'Test', width: 22 },
1118
+ { key: 'details', header: 'Details', width: 30 },
1119
+ { key: 'duration', header: 'Time', width: 8, align: 'right' }
1120
+ ],
1121
+ data: verification.tests.map(t => ({
1122
+ status: t.passed ? output.success('✓') : output.error('✗'),
1123
+ name: t.name,
1124
+ details: t.details || '',
1125
+ duration: t.duration ? `${t.duration}ms` : '-'
1126
+ }))
1127
+ });
1128
+ }
1129
+ output.writeln();
1085
1130
  }
1086
- // Write minimal SQLite header to create valid empty database
1087
- // sql.js will properly initialize the schema on first connection
1088
- const sqliteHeader = Buffer.from([
1089
- 0x53, 0x51, 0x4C, 0x69, 0x74, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x20, 0x33, 0x00, // "SQLite format 3\0"
1090
- 0x10, 0x00, // page size: 4096 bytes
1091
- 0x01, // file format write version
1092
- 0x01, // file format read version
1093
- 0x00, // reserved space
1094
- 0x40, // max embedded payload fraction
1095
- 0x20, // min embedded payload fraction
1096
- 0x20, // leaf payload fraction
1097
- 0x00, 0x00, 0x00, 0x01, // file change counter
1098
- 0x00, 0x00, 0x00, 0x01, // database size in pages
1099
- 0x00, 0x00, 0x00, 0x00, // first freelist trunk page
1100
- 0x00, 0x00, 0x00, 0x00, // total freelist pages
1101
- 0x00, 0x00, 0x00, 0x01, // schema cookie
1102
- 0x00, 0x00, 0x00, 0x04, // schema format number
1103
- 0x00, 0x00, 0x00, 0x00, // default page cache size
1104
- 0x00, 0x00, 0x00, 0x00, // largest root btree page
1105
- 0x00, 0x00, 0x00, 0x01, // text encoding (1=UTF-8)
1106
- 0x00, 0x00, 0x00, 0x00, // user version
1107
- 0x00, 0x00, 0x00, 0x00, // incremental vacuum mode
1108
- 0x00, 0x00, 0x00, 0x00, // application id
1109
- ...Array(20).fill(0x00), // reserved for expansion
1110
- 0x00, 0x00, 0x00, 0x01, // version-valid-for number
1111
- 0x00, 0x2E, 0x32, 0x8F, // SQLite version number (3.46.1)
1131
+ // Show next steps
1132
+ output.writeln(output.bold('Next Steps:'));
1133
+ output.printList([
1134
+ `Store data: ${output.highlight('claude-flow memory store -k "key" --value "data"')}`,
1135
+ `Search: ${output.highlight('claude-flow memory search -q "query"')}`,
1136
+ `Train patterns: ${output.highlight('claude-flow neural train -p coordination')}`,
1137
+ `View stats: ${output.highlight('claude-flow memory stats')}`
1112
1138
  ]);
1113
- // Pad to 4096 bytes (one page)
1114
- const page = Buffer.alloc(4096, 0);
1115
- sqliteHeader.copy(page);
1116
- fs.writeFileSync(dbPath, page);
1117
- // Also create in .claude directory for compatibility
1139
+ // Also sync to .claude directory
1140
+ const fs = await import('fs');
1141
+ const path = await import('path');
1142
+ const claudeDir = path.join(process.cwd(), '.claude');
1118
1143
  const claudeDbPath = path.join(claudeDir, 'memory.db');
1119
1144
  if (!fs.existsSync(claudeDir)) {
1120
1145
  fs.mkdirSync(claudeDir, { recursive: true });
1121
1146
  }
1122
- if (!fs.existsSync(claudeDbPath)) {
1123
- fs.copyFileSync(dbPath, claudeDbPath);
1124
- output.writeln(output.dim(` Synced to: ${claudeDbPath}`));
1147
+ if (fs.existsSync(result.dbPath) && (!fs.existsSync(claudeDbPath) || force)) {
1148
+ fs.copyFileSync(result.dbPath, claudeDbPath);
1149
+ output.writeln();
1150
+ output.writeln(output.dim(`Synced to: ${claudeDbPath}`));
1125
1151
  }
1126
- output.writeln();
1127
- output.printSuccess('Memory database initialized');
1128
- output.writeln();
1129
- output.printTable({
1130
- columns: [
1131
- { key: 'property', header: 'Property', width: 15 },
1132
- { key: 'value', header: 'Value', width: 40 }
1133
- ],
1134
- data: [
1135
- { property: 'Backend', value: backend },
1136
- { property: 'Path', value: dbPath },
1137
- { property: 'Engine', value: 'sql.js (WASM SQLite)' },
1138
- { property: 'Schema', value: schemaPath },
1139
- { property: 'Tables', value: '6 (memory_entries, vectors, patterns, sessions, trajectories, metadata)' }
1140
- ]
1141
- });
1142
- output.writeln();
1143
- output.printInfo('Ready for use. Store data with: claude-flow memory store -k "key" --value "data"');
1144
1152
  return {
1145
1153
  success: true,
1146
- data: {
1147
- backend,
1148
- path: dbPath,
1149
- schemaPath,
1150
- engine: 'sql.js'
1151
- }
1154
+ data: result
1152
1155
  };
1153
1156
  }
1154
1157
  catch (error) {
1158
+ spinner.fail('Initialization failed');
1155
1159
  output.printError(`Failed to initialize memory: ${error instanceof Error ? error.message : String(error)}`);
1156
1160
  return { success: false, exitCode: 1 };
1157
1161
  }