@soulcraft/brainy 0.63.0 β†’ 1.0.0-rc.2

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.
@@ -1,2523 +0,0 @@
1
- /**
2
- * Cortex - Beautiful CLI Command Center for Brainy
3
- *
4
- * Configuration, data management, search, and chat - all in one place!
5
- */
6
- import { BrainyData } from '../brainyData.js';
7
- import { BrainyChat } from '../chat/BrainyChat.js';
8
- import { PerformanceMonitor } from './performanceMonitor.js';
9
- import { HealthCheck } from './healthCheck.js';
10
- // Licensing system moved to quantum-vault
11
- import * as readline from 'readline';
12
- import * as fs from 'fs/promises';
13
- import * as path from 'path';
14
- import * as crypto from 'crypto';
15
- // @ts-ignore - CLI packages
16
- import chalk from 'chalk';
17
- // @ts-ignore - CLI packages
18
- import ora from 'ora';
19
- // @ts-ignore - CLI packages
20
- import boxen from 'boxen';
21
- // @ts-ignore - CLI packages
22
- import Table from 'cli-table3';
23
- // @ts-ignore - CLI packages
24
- import prompts from 'prompts';
25
- // Brainy-branded terminal colors matching the logo
26
- const colors = {
27
- primary: chalk.hex('#3A5F4A'), // Deep teal from brain jar
28
- success: chalk.hex('#2D4A3A'), // Darker teal for success states
29
- warning: chalk.hex('#D67441'), // Warm orange from logo rays
30
- error: chalk.hex('#B85C35'), // Darker orange for errors
31
- info: chalk.hex('#4A6B5A'), // Muted green background color
32
- dim: chalk.hex('#8A9B8A'), // Muted gray-green
33
- bold: chalk.bold,
34
- highlight: chalk.hex('#E88B5A'), // Coral brain color for highlights
35
- accent: chalk.hex('#F5E6D3'), // Cream accent color
36
- retro: chalk.hex('#D67441'), // Main retro orange
37
- brain: chalk.hex('#E88B5A') // Brain coral color
38
- };
39
- // 1950s Retro Sci-Fi emojis matching Brainy's atomic age aesthetic
40
- const emojis = {
41
- brain: '🧠', // Perfect brain in a jar!
42
- tube: 'πŸ§ͺ', // Laboratory test tube for data
43
- atom: 'βš›οΈ', // Atomic symbol - pure 50s sci-fi
44
- lock: 'πŸ”’', // Vault-style security
45
- key: 'πŸ—οΈ', // Vintage brass key
46
- shield: 'πŸ›‘οΈ', // Protective force field
47
- check: 'βœ…', // Success indicator
48
- cross: '❌', // Error state
49
- warning: '⚠️', // Alert system
50
- info: 'ℹ️', // Information display
51
- search: 'πŸ”', // Laboratory magnifier
52
- chat: 'πŸ’­', // Thought transmission
53
- data: 'πŸŽ›οΈ', // Control panel/dashboard
54
- config: 'βš™οΈ', // Mechanical gear system
55
- magic: '⚑', // Electrical energy/power
56
- party: 'πŸŽ†', // Atomic celebration
57
- robot: 'πŸ€–', // Mechanical automaton
58
- cloud: '☁️', // Atmospheric storage
59
- disk: 'πŸ’½', // Retro storage disc
60
- package: 'πŸ“¦', // Laboratory specimen box
61
- lab: 'πŸ”¬', // Scientific instrument
62
- network: 'πŸ“‘', // Communications array
63
- sync: 'πŸ”„', // Cyclical process
64
- backup: 'πŸ’Ύ', // Archive storage
65
- health: 'πŸ”‹', // Power/energy levels
66
- stats: 'πŸ“Š', // Data analysis charts
67
- explore: 'πŸ—ΊοΈ', // Territory mapping
68
- import: 'πŸ“₯', // Input channel
69
- export: 'πŸ“€', // Output transmission
70
- sparkle: '✨', // Energy discharge
71
- rocket: 'πŸš€', // Space age propulsion
72
- repair: 'πŸ”§', // Repair tools
73
- lightning: '⚑' // Lightning bolt
74
- };
75
- export class Cortex {
76
- constructor() {
77
- // UI properties for terminal output
78
- this.emojis = {
79
- check: 'βœ…',
80
- cross: '❌',
81
- info: 'ℹ️',
82
- warning: '⚠️',
83
- rocket: 'πŸš€',
84
- brain: '🧠',
85
- atom: 'βš›οΈ',
86
- lock: 'πŸ”’',
87
- key: 'πŸ”‘',
88
- package: 'πŸ“¦',
89
- chart: 'πŸ“Š',
90
- sparkles: '✨',
91
- fire: 'πŸ”₯',
92
- zap: '⚑',
93
- gear: 'βš™οΈ',
94
- robot: 'πŸ€–',
95
- shield: 'πŸ›‘οΈ',
96
- wrench: 'πŸ”§',
97
- clipboard: 'πŸ“‹',
98
- folder: 'πŸ“',
99
- database: 'πŸ—„οΈ',
100
- lightning: '⚑',
101
- checkmark: 'βœ…',
102
- repair: 'πŸ”§',
103
- health: 'πŸ₯'
104
- };
105
- this.colors = {
106
- reset: '\x1b[0m',
107
- bright: '\x1b[1m',
108
- // Helper methods
109
- dim: (text) => `\x1b[2m${text}\x1b[0m`,
110
- red: (text) => `\x1b[31m${text}\x1b[0m`,
111
- green: (text) => `\x1b[32m${text}\x1b[0m`,
112
- yellow: (text) => `\x1b[33m${text}\x1b[0m`,
113
- blue: (text) => `\x1b[34m${text}\x1b[0m`,
114
- magenta: (text) => `\x1b[35m${text}\x1b[0m`,
115
- cyan: (text) => `\x1b[36m${text}\x1b[0m`,
116
- white: (text) => `\x1b[37m${text}\x1b[0m`,
117
- gray: (text) => `\x1b[90m${text}\x1b[0m`,
118
- retro: (text) => `\x1b[36m${text}\x1b[0m`,
119
- success: (text) => `\x1b[32m${text}\x1b[0m`,
120
- warning: (text) => `\x1b[33m${text}\x1b[0m`,
121
- error: (text) => `\x1b[31m${text}\x1b[0m`,
122
- info: (text) => `\x1b[34m${text}\x1b[0m`,
123
- brain: (text) => `\x1b[35m${text}\x1b[0m`,
124
- accent: (text) => `\x1b[36m${text}\x1b[0m`,
125
- premium: (text) => `\x1b[33m${text}\x1b[0m`,
126
- highlight: (text) => `\x1b[1m${text}\x1b[0m`
127
- };
128
- this.customSecretPatterns = [];
129
- this.configPath = path.join(process.cwd(), '.cortex', 'config.json');
130
- this.config = {};
131
- }
132
- /**
133
- * Load configuration
134
- */
135
- async loadConfig() {
136
- try {
137
- await fs.mkdir(path.dirname(this.configPath), { recursive: true });
138
- const configData = await fs.readFile(this.configPath, 'utf-8');
139
- this.config = JSON.parse(configData);
140
- return this.config;
141
- }
142
- catch {
143
- // Config doesn't exist yet, return empty config
144
- this.config = {};
145
- return this.config;
146
- }
147
- }
148
- /**
149
- * Ensure Brainy is initialized
150
- */
151
- async ensureBrainy() {
152
- if (!this.brainy) {
153
- const config = await this.loadConfig();
154
- this.brainy = new BrainyData(config.brainyOptions || {});
155
- await this.brainy.init();
156
- }
157
- }
158
- /**
159
- * Master Key Management - Atomic Age Security Protocols
160
- */
161
- async initializeMasterKey() {
162
- // Try environment variable first
163
- const envKey = process.env.CORTEX_MASTER_KEY;
164
- if (envKey && envKey.length >= 32) {
165
- this.encryptionKey = Buffer.from(envKey.substring(0, 32));
166
- this.masterKeySource = 'env';
167
- return;
168
- }
169
- // Check for existing stored key
170
- const keyPath = path.join(path.dirname(this.configPath), '.master_key');
171
- try {
172
- const storedKey = await fs.readFile(keyPath);
173
- this.encryptionKey = storedKey;
174
- this.masterKeySource = 'generated';
175
- return;
176
- }
177
- catch {
178
- // Key doesn't exist, need to create one
179
- }
180
- // Prompt for passphrase or generate new key
181
- const { method } = await prompts({
182
- type: 'select',
183
- name: 'method',
184
- message: `${emojis.key} ${colors.retro('Select encryption key method:')}`,
185
- choices: [
186
- { title: `${emojis.brain} Generate secure key (recommended)`, value: 'generate' },
187
- { title: `${emojis.lock} Create from passphrase`, value: 'passphrase' },
188
- { title: `${emojis.warning} Skip encryption (not secure)`, value: 'skip' }
189
- ]
190
- });
191
- if (method === 'skip') {
192
- console.log(colors.warning(`${emojis.warning} Encryption disabled - secrets will be stored in plain text!`));
193
- return;
194
- }
195
- if (method === 'generate') {
196
- this.encryptionKey = crypto.randomBytes(32);
197
- this.masterKeySource = 'generated';
198
- // Store the key securely
199
- await fs.writeFile(keyPath, this.encryptionKey, { mode: 0o600 });
200
- console.log(colors.success(`${emojis.check} Secure master key generated and stored`));
201
- }
202
- else if (method === 'passphrase') {
203
- const { passphrase } = await prompts({
204
- type: 'password',
205
- name: 'passphrase',
206
- message: `${emojis.key} Enter master passphrase (min 8 characters):`
207
- });
208
- if (!passphrase || passphrase.length < 8) {
209
- throw new Error('Passphrase must be at least 8 characters');
210
- }
211
- // Derive key from passphrase using PBKDF2
212
- const salt = crypto.randomBytes(16);
213
- this.encryptionKey = crypto.pbkdf2Sync(passphrase, salt, 100000, 32, 'sha256');
214
- this.masterKeySource = 'passphrase';
215
- // Store salt for future key derivation
216
- const keyData = Buffer.concat([salt, this.encryptionKey]);
217
- await fs.writeFile(keyPath, keyData, { mode: 0o600 });
218
- console.log(colors.success(`${emojis.check} Master key derived from passphrase`));
219
- }
220
- }
221
- /**
222
- * Load master key from stored salt + passphrase
223
- */
224
- async loadPassphraseKey() {
225
- const keyPath = path.join(path.dirname(this.configPath), '.master_key');
226
- const keyData = await fs.readFile(keyPath);
227
- if (keyData.length === 32) {
228
- // Simple generated key
229
- this.encryptionKey = keyData;
230
- return;
231
- }
232
- // Extract salt and ask for passphrase
233
- const salt = keyData.subarray(0, 16);
234
- const { passphrase } = await prompts({
235
- type: 'password',
236
- name: 'passphrase',
237
- message: `${emojis.key} Enter master passphrase:`
238
- });
239
- if (!passphrase) {
240
- throw new Error('Passphrase required for encrypted configuration');
241
- }
242
- this.encryptionKey = crypto.pbkdf2Sync(passphrase, salt, 100000, 32, 'sha256');
243
- }
244
- /**
245
- * Reset master key - for key rotation
246
- */
247
- async resetMasterKey() {
248
- console.log(boxen(`${emojis.warning} ${colors.retro('SECURITY PROTOCOL: KEY ROTATION')}\n\n` +
249
- `${colors.accent('β—†')} ${colors.dim('This will re-encrypt all stored secrets')}\n` +
250
- `${colors.accent('β—†')} ${colors.dim('Ensure you have backups before proceeding')}`, { padding: 1, borderStyle: 'round', borderColor: '#D67441' }));
251
- const { confirm } = await prompts({
252
- type: 'confirm',
253
- name: 'confirm',
254
- message: 'Proceed with key rotation?',
255
- initial: false
256
- });
257
- if (!confirm) {
258
- console.log(colors.dim('Key rotation cancelled'));
259
- return;
260
- }
261
- // Get current decrypted values
262
- const currentSecrets = await this.getAllSecrets();
263
- // Remove old key
264
- const keyPath = path.join(path.dirname(this.configPath), '.master_key');
265
- try {
266
- await fs.unlink(keyPath);
267
- }
268
- catch { }
269
- // Initialize new key
270
- await this.initializeMasterKey();
271
- // Re-encrypt all secrets with new key
272
- const spinner = ora('Re-encrypting secrets with new key...').start();
273
- for (const [key, value] of Object.entries(currentSecrets)) {
274
- await this.configSet(key, value, { encrypt: true });
275
- }
276
- spinner.succeed(colors.success(`${emojis.check} Key rotation complete! ${Object.keys(currentSecrets).length} secrets re-encrypted`));
277
- }
278
- /**
279
- * Get all decrypted secrets (for key rotation)
280
- */
281
- async getAllSecrets() {
282
- const secrets = {};
283
- const configMetaPath = path.join(path.dirname(this.configPath), 'config_metadata.json');
284
- try {
285
- const metadata = JSON.parse(await fs.readFile(configMetaPath, 'utf8'));
286
- for (const key of Object.keys(metadata)) {
287
- if (metadata[key].encrypted) {
288
- const value = await this.configGet(key);
289
- if (value)
290
- secrets[key] = value;
291
- }
292
- }
293
- }
294
- catch { }
295
- return secrets;
296
- }
297
- /**
298
- * Initialize Cortex with beautiful prompts
299
- */
300
- async init(options = {}) {
301
- const spinner = ora('Initializing Cortex...').start();
302
- try {
303
- // Check if already initialized
304
- if (await this.isInitialized()) {
305
- spinner.warn('Cortex is already initialized!');
306
- const { reinit } = await prompts({
307
- type: 'confirm',
308
- name: 'reinit',
309
- message: 'Do you want to reinitialize?',
310
- initial: false
311
- });
312
- if (!reinit) {
313
- spinner.stop();
314
- return;
315
- }
316
- }
317
- spinner.text = 'Setting up configuration...';
318
- // Interactive setup
319
- const responses = await prompts([
320
- {
321
- type: 'select',
322
- name: 'storage',
323
- message: `${emojis.disk} Choose your storage type:`,
324
- choices: [
325
- { title: `${emojis.disk} Local Filesystem`, value: 'filesystem' },
326
- { title: `${emojis.cloud} AWS S3`, value: 's3' },
327
- { title: `${emojis.cloud} Cloudflare R2`, value: 'r2' },
328
- { title: `${emojis.cloud} Google Cloud Storage`, value: 'gcs' },
329
- { title: `${emojis.brain} Memory (testing)`, value: 'memory' }
330
- ]
331
- },
332
- {
333
- type: (prev) => prev === 's3' ? 'text' : null,
334
- name: 's3Bucket',
335
- message: 'Enter S3 bucket name:'
336
- },
337
- {
338
- type: (prev) => prev === 'r2' ? 'text' : null,
339
- name: 'r2Bucket',
340
- message: 'Enter Cloudflare R2 bucket name:'
341
- },
342
- {
343
- type: (prev) => prev === 'gcs' ? 'text' : null,
344
- name: 'gcsBucket',
345
- message: 'Enter GCS bucket name:'
346
- },
347
- {
348
- type: 'confirm',
349
- name: 'encryption',
350
- message: `${emojis.lock} Enable encryption for secrets?`,
351
- initial: true
352
- },
353
- {
354
- type: 'confirm',
355
- name: 'chat',
356
- message: `${emojis.chat} Enable Brainy Chat?`,
357
- initial: true
358
- },
359
- {
360
- type: (prev) => prev ? 'select' : null,
361
- name: 'llm',
362
- message: `${emojis.robot} Choose LLM provider (optional):`,
363
- choices: [
364
- { title: 'None (template-based)', value: null },
365
- { title: 'Claude (Anthropic)', value: 'claude-3-5-sonnet' },
366
- { title: 'GPT-4 (OpenAI)', value: 'gpt-4' },
367
- { title: 'Local Model (Hugging Face)', value: 'Xenova/LaMini-Flan-T5-77M' }
368
- ]
369
- }
370
- ]);
371
- // Create config
372
- this.config = {
373
- storage: responses.storage,
374
- encryption: responses.encryption,
375
- chat: responses.chat,
376
- llm: responses.llm,
377
- s3Bucket: responses.s3Bucket,
378
- r2Bucket: responses.r2Bucket,
379
- gcsBucket: responses.gcsBucket,
380
- initialized: true,
381
- createdAt: new Date().toISOString()
382
- };
383
- // Setup encryption
384
- if (responses.encryption) {
385
- await this.initializeMasterKey();
386
- this.config.encryptionEnabled = true;
387
- }
388
- // Save configuration
389
- await this.saveConfig();
390
- // Initialize Brainy
391
- spinner.text = 'Initializing Brainy database...';
392
- await this.initBrainy();
393
- spinner.succeed(colors.success(`${emojis.party} Cortex initialized successfully!`));
394
- // Show welcome message
395
- this.showWelcome();
396
- }
397
- catch (error) {
398
- spinner.fail(colors.error('Failed to initialize Cortex'));
399
- console.error(error);
400
- process.exit(1);
401
- }
402
- }
403
- /**
404
- * Beautiful welcome message
405
- */
406
- showWelcome() {
407
- const welcome = boxen(`${emojis.brain} ${colors.brain('CORTEX')} ${emojis.atom} ${colors.bold('COMMAND CENTER')}\n\n` +
408
- `${colors.accent('β—†')} ${colors.dim('Laboratory systems online and ready for operation')}\n\n` +
409
- `${emojis.rocket} ${colors.retro('QUICK START PROTOCOLS:')}\n` +
410
- ` ${colors.primary('cortex chat')} ${emojis.chat} Neural interface mode\n` +
411
- ` ${colors.primary('cortex add')} ${emojis.data} Specimen collection\n` +
412
- ` ${colors.primary('cortex search')} ${emojis.search} Data analysis\n` +
413
- ` ${colors.primary('cortex config')} ${emojis.config} System parameters\n` +
414
- ` ${colors.primary('cortex help')} ${emojis.info} Operations manual`, {
415
- padding: 1,
416
- margin: 1,
417
- borderStyle: 'round',
418
- borderColor: '#D67441' // Retro orange border
419
- });
420
- console.log(welcome);
421
- }
422
- /**
423
- * Chat with your data - beautiful interactive mode
424
- */
425
- async generateResponse(question) {
426
- // This is a placeholder for AI integration
427
- // In production, this would call the configured AI service
428
- return `I understand your question about "${question}". Based on the data in your Brainy database, here's what I found...`;
429
- }
430
- async chat(question) {
431
- await this.ensureInitialized();
432
- if (!this.chatInstance) {
433
- this.chatInstance = new BrainyChat(this.brainy);
434
- }
435
- // Single question mode
436
- if (question) {
437
- const spinner = ora('Thinking...').start();
438
- try {
439
- // Use the new chat methods
440
- await this.chatInstance.addMessage(question, 'user');
441
- const response = await this.generateResponse(question);
442
- const answer = await this.chatInstance.addMessage(response, 'assistant');
443
- spinner.stop();
444
- console.log(`\n${emojis.robot} ${colors.bold('Answer:')}\n${response}\n`);
445
- }
446
- catch (error) {
447
- spinner.fail('Failed to get answer');
448
- console.error(error);
449
- }
450
- return;
451
- }
452
- // Interactive chat mode
453
- console.log(boxen(`${emojis.brain} ${colors.brain('NEURAL INTERFACE')} ${emojis.magic}\n\n` +
454
- `${colors.accent('β—†')} ${colors.dim('Thought-to-data transmission active')}\n` +
455
- `${colors.accent('β—†')} ${colors.dim('Query processing protocols engaged')}\n\n` +
456
- `${colors.retro('Type "exit" to disengage neural link')}`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
457
- const rl = readline.createInterface({
458
- input: process.stdin,
459
- output: process.stdout,
460
- prompt: colors.primary('You> ')
461
- });
462
- rl.prompt();
463
- rl.on('line', async (line) => {
464
- const input = line.trim();
465
- if (input.toLowerCase() === 'exit' || input.toLowerCase() === 'quit') {
466
- console.log(`\n${emojis.atom} ${colors.retro('Neural link disengaged')} ${emojis.sparkle}\n`);
467
- rl.close();
468
- return;
469
- }
470
- if (input) {
471
- const spinner = ora('Thinking...').start();
472
- try {
473
- await this.chatInstance.addMessage(input, 'user');
474
- const answer = await this.generateResponse(input);
475
- await this.chatInstance.addMessage(answer, 'assistant');
476
- spinner.stop();
477
- console.log(`\n${emojis.robot} ${colors.success(answer)}\n`);
478
- }
479
- catch (error) {
480
- spinner.fail('Error processing question');
481
- console.error(error);
482
- }
483
- }
484
- rl.prompt();
485
- });
486
- // Ensure process exits when readline closes
487
- rl.on('close', () => {
488
- console.log('\n');
489
- process.exit(0);
490
- });
491
- }
492
- /**
493
- * Add data with beautiful prompts
494
- */
495
- async add(data, metadata) {
496
- await this.ensureInitialized();
497
- // Interactive mode if no data provided
498
- if (!data) {
499
- const responses = await prompts([
500
- {
501
- type: 'text',
502
- name: 'data',
503
- message: `${emojis.data} Enter data to add:`
504
- },
505
- {
506
- type: 'text',
507
- name: 'id',
508
- message: 'ID (optional, press enter to auto-generate):'
509
- },
510
- {
511
- type: 'confirm',
512
- name: 'hasMetadata',
513
- message: 'Add metadata?',
514
- initial: false
515
- },
516
- {
517
- type: (prev) => prev ? 'text' : null,
518
- name: 'metadata',
519
- message: 'Enter metadata (JSON format):'
520
- }
521
- ]);
522
- data = responses.data;
523
- if (responses.metadata) {
524
- try {
525
- metadata = JSON.parse(responses.metadata);
526
- }
527
- catch {
528
- console.log(colors.warning('Invalid JSON, skipping metadata'));
529
- }
530
- }
531
- if (responses.id) {
532
- metadata = { ...metadata, id: responses.id };
533
- }
534
- }
535
- const spinner = ora('Adding data...').start();
536
- try {
537
- const id = await this.brainy.add(data, metadata);
538
- spinner.succeed(colors.success(`${emojis.check} Added with ID: ${id}`));
539
- }
540
- catch (error) {
541
- spinner.fail('Failed to add data');
542
- console.error(error);
543
- }
544
- }
545
- /**
546
- * Add data with AI processing enabled (Neural Import + entity detection)
547
- */
548
- async addSmart(data, metadata) {
549
- await this.ensureInitialized();
550
- // Interactive mode if no data provided
551
- if (!data) {
552
- const responses = await prompts([
553
- {
554
- type: 'text',
555
- name: 'data',
556
- message: `${emojis.brain} Enter data for AI processing:`
557
- },
558
- {
559
- type: 'text',
560
- name: 'id',
561
- message: 'ID (optional, press enter to auto-generate):'
562
- },
563
- {
564
- type: 'confirm',
565
- name: 'hasMetadata',
566
- message: 'Add metadata?',
567
- initial: false
568
- },
569
- {
570
- type: (prev) => prev ? 'text' : null,
571
- name: 'metadata',
572
- message: 'Enter metadata (JSON format):'
573
- }
574
- ]);
575
- data = responses.data;
576
- if (responses.metadata) {
577
- try {
578
- metadata = JSON.parse(responses.metadata);
579
- }
580
- catch {
581
- console.log(colors.warning('Invalid JSON, skipping metadata'));
582
- }
583
- }
584
- if (responses.id) {
585
- metadata = { ...metadata, id: responses.id };
586
- }
587
- }
588
- const spinner = ora('🧠 Processing with AI...').start();
589
- try {
590
- const id = await this.brainy.addSmart(data, metadata);
591
- spinner.succeed(colors.success(`${emojis.check} Processed with AI and added with ID: ${id}`));
592
- }
593
- catch (error) {
594
- spinner.fail('Failed to add data with AI processing');
595
- console.error(error);
596
- }
597
- }
598
- /**
599
- * Search with beautiful results display and advanced options
600
- */
601
- async search(query, options = {}) {
602
- await this.ensureInitialized();
603
- const limit = options.limit || 10;
604
- const spinner = ora(`Searching...`).start();
605
- try {
606
- // Build search options with MongoDB-style filters
607
- const searchOptions = {};
608
- // Add metadata filters if provided
609
- if (options.filter) {
610
- searchOptions.metadata = options.filter;
611
- }
612
- // Add graph traversal options
613
- if (options.verbs) {
614
- searchOptions.includeVerbs = true;
615
- searchOptions.verbTypes = options.verbs;
616
- }
617
- if (options.depth) {
618
- searchOptions.traversalDepth = options.depth;
619
- }
620
- const results = await this.brainy.search(query, limit, searchOptions);
621
- spinner.stop();
622
- if (results.length === 0) {
623
- console.log(colors.warning(`${emojis.warning} No results found`));
624
- return;
625
- }
626
- // Create beautiful table with dynamic columns
627
- const hasVerbs = results.some((r) => r.verbs && r.verbs.length > 0);
628
- const head = [
629
- colors.bold('Rank'),
630
- colors.bold('ID'),
631
- colors.bold('Score')
632
- ];
633
- if (hasVerbs) {
634
- head.push(colors.bold('Connections'));
635
- }
636
- head.push(colors.bold('Metadata'));
637
- const table = new Table({
638
- head,
639
- style: { head: ['cyan'] }
640
- });
641
- results.forEach((result, i) => {
642
- const row = [
643
- colors.dim(`#${i + 1}`),
644
- colors.primary(result.id.slice(0, 25) + (result.id.length > 25 ? '...' : '')),
645
- colors.success(`${(result.score * 100).toFixed(1)}%`)
646
- ];
647
- if (hasVerbs && result.verbs) {
648
- const verbs = result.verbs.slice(0, 2).map((v) => `${colors.warning(v.type)}: ${v.object.slice(0, 15)}...`).join('\n');
649
- row.push(verbs || '-');
650
- }
651
- row.push(colors.dim(JSON.stringify(result.metadata || {}).slice(0, 40) + '...'));
652
- table.push(row);
653
- });
654
- console.log(`\n${emojis.search} ${colors.bold(`Found ${results.length} results:`)}\n`);
655
- // Show applied filters
656
- if (options.filter) {
657
- console.log(colors.dim(` Filters: ${JSON.stringify(options.filter)}`));
658
- }
659
- if (options.verbs) {
660
- console.log(colors.dim(` Graph traversal: ${options.verbs.join(', ')}`));
661
- }
662
- console.log();
663
- console.log(table.toString());
664
- }
665
- catch (error) {
666
- spinner.fail('Search failed');
667
- console.error(error);
668
- }
669
- }
670
- /**
671
- * Advanced search with interactive prompts
672
- */
673
- async advancedSearch() {
674
- await this.ensureInitialized();
675
- const responses = await prompts([
676
- {
677
- type: 'text',
678
- name: 'query',
679
- message: `${emojis.search} Enter search query:`
680
- },
681
- {
682
- type: 'number',
683
- name: 'limit',
684
- message: 'Number of results:',
685
- initial: 10
686
- },
687
- {
688
- type: 'confirm',
689
- name: 'useFilters',
690
- message: 'Add metadata filters (MongoDB-style)?',
691
- initial: false
692
- },
693
- {
694
- type: (prev) => prev ? 'text' : null,
695
- name: 'filters',
696
- message: 'Enter filters (JSON with $gt, $gte, $lt, $lte, $eq, $ne, $in, $nin):\nExample: {"age": {"$gte": 18}, "status": {"$in": ["active", "pending"]}}'
697
- },
698
- {
699
- type: 'confirm',
700
- name: 'useGraph',
701
- message: `${emojis.magic} Traverse graph relationships?`,
702
- initial: false
703
- },
704
- {
705
- type: (prev) => prev ? 'text' : null,
706
- name: 'verbs',
707
- message: 'Enter verb types (comma-separated):\nExample: owns, likes, follows'
708
- },
709
- {
710
- type: (prev, values) => values.useGraph ? 'number' : null,
711
- name: 'depth',
712
- message: 'Traversal depth:',
713
- initial: 1
714
- }
715
- ]);
716
- const options = { limit: responses.limit };
717
- if (responses.filters) {
718
- try {
719
- options.filter = JSON.parse(responses.filters);
720
- }
721
- catch {
722
- console.log(colors.warning('Invalid filter JSON, skipping filters'));
723
- }
724
- }
725
- if (responses.verbs) {
726
- options.verbs = responses.verbs.split(',').map((v) => v.trim());
727
- options.depth = responses.depth;
728
- }
729
- await this.search(responses.query, options);
730
- }
731
- /**
732
- * Add or update graph connections (verbs)
733
- */
734
- async addVerb(subject, verb, object, metadata) {
735
- await this.ensureInitialized();
736
- const spinner = ora('Adding relationship...').start();
737
- try {
738
- // For now, we'll add it as a special metadata entry
739
- await this.brainy.add(`${subject} ${verb} ${object}`, {
740
- type: 'relationship',
741
- subject,
742
- verb,
743
- object,
744
- ...metadata
745
- });
746
- spinner.succeed(colors.success(`${emojis.check} Added: ${subject} --[${verb}]--> ${object}`));
747
- }
748
- catch (error) {
749
- spinner.fail('Failed to add relationship');
750
- console.error(error);
751
- }
752
- }
753
- /**
754
- * Interactive graph exploration
755
- */
756
- async explore(startId) {
757
- await this.ensureInitialized();
758
- if (!startId) {
759
- const { id } = await prompts({
760
- type: 'text',
761
- name: 'id',
762
- message: `${emojis.search} Enter starting node ID:`
763
- });
764
- startId = id;
765
- }
766
- const spinner = ora('Loading graph...').start();
767
- try {
768
- // Get node and its connections
769
- const results = await this.brainy.search(startId, 1, { includeVerbs: true });
770
- if (results.length === 0) {
771
- spinner.fail('Node not found');
772
- return;
773
- }
774
- spinner.stop();
775
- const node = results[0];
776
- // Display node info in a beautiful box
777
- const nodeInfo = boxen(`${emojis.data} ${colors.bold('Node: ' + node.id)}\n\n` +
778
- `${colors.dim('Metadata:')}\n${JSON.stringify(node.metadata || {}, null, 2)}\n\n` +
779
- `${colors.dim('Connections:')}\n${node.verbs && node.verbs.length > 0
780
- ? node.verbs.map((v) => ` ${colors.warning(v.type)} β†’ ${colors.primary(v.object)}`).join('\n')
781
- : ' No connections'}`, {
782
- padding: 1,
783
- borderStyle: 'round',
784
- borderColor: 'magenta'
785
- });
786
- console.log(nodeInfo);
787
- // Interactive exploration menu
788
- if (node.verbs && node.verbs.length > 0) {
789
- const { action } = await prompts({
790
- type: 'select',
791
- name: 'action',
792
- message: 'What would you like to do?',
793
- choices: [
794
- { title: 'Explore a connected node', value: 'explore' },
795
- { title: 'Add new connection', value: 'add' },
796
- { title: 'Search similar nodes', value: 'similar' },
797
- { title: 'Exit', value: 'exit' }
798
- ]
799
- });
800
- if (action === 'explore') {
801
- const { next } = await prompts({
802
- type: 'select',
803
- name: 'next',
804
- message: 'Choose node to explore:',
805
- choices: node.verbs.map((v) => ({
806
- title: `${v.object} (via ${v.type})`,
807
- value: v.object
808
- }))
809
- });
810
- await this.explore(next);
811
- }
812
- else if (action === 'add') {
813
- const newVerb = await prompts([
814
- {
815
- type: 'text',
816
- name: 'verb',
817
- message: 'Relationship type:'
818
- },
819
- {
820
- type: 'text',
821
- name: 'object',
822
- message: 'Target node ID:'
823
- }
824
- ]);
825
- await this.addVerb(startId, newVerb.verb, newVerb.object);
826
- await this.explore(startId);
827
- }
828
- else if (action === 'similar') {
829
- await this.search(startId, { limit: 5 });
830
- }
831
- }
832
- }
833
- catch (error) {
834
- spinner.fail('Failed to explore graph');
835
- console.error(error);
836
- }
837
- }
838
- /**
839
- * Configuration management with encryption
840
- */
841
- async configSet(key, value, options = {}) {
842
- await this.ensureInitialized();
843
- const isSecret = options.encrypt || this.isSecret(key);
844
- if (isSecret && this.encryptionKey) {
845
- // Encrypt the value
846
- const iv = crypto.randomBytes(16);
847
- const cipher = crypto.createCipheriv('aes-256-gcm', this.encryptionKey, iv);
848
- let encrypted = cipher.update(value, 'utf8', 'hex');
849
- encrypted += cipher.final('hex');
850
- const authTag = cipher.getAuthTag();
851
- value = `ENCRYPTED:${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
852
- console.log(colors.success(`${emojis.lock} Stored encrypted: ${key}`));
853
- }
854
- else {
855
- console.log(colors.success(`${emojis.check} Stored: ${key}`));
856
- }
857
- // Store in Brainy
858
- await this.brainy.add(value, {
859
- type: 'config',
860
- key,
861
- encrypted: isSecret,
862
- timestamp: new Date().toISOString()
863
- });
864
- }
865
- /**
866
- * Get configuration value
867
- */
868
- async configGet(key) {
869
- await this.ensureInitialized();
870
- const results = await this.brainy.search(key, 1, {
871
- metadata: { type: 'config', key }
872
- });
873
- if (results.length === 0) {
874
- return null;
875
- }
876
- let value = results[0].id;
877
- // Decrypt if needed
878
- if (value.startsWith('ENCRYPTED:') && this.encryptionKey) {
879
- const [, iv, authTag, encrypted] = value.split(':');
880
- const decipher = crypto.createDecipheriv('aes-256-gcm', this.encryptionKey, Buffer.from(iv, 'hex'));
881
- decipher.setAuthTag(Buffer.from(authTag, 'hex'));
882
- let decrypted = decipher.update(encrypted, 'hex', 'utf8');
883
- decrypted += decipher.final('utf8');
884
- value = decrypted;
885
- }
886
- return value;
887
- }
888
- /**
889
- * List all configuration
890
- */
891
- async configList() {
892
- await this.ensureInitialized();
893
- const spinner = ora('Loading configuration...').start();
894
- try {
895
- const results = await this.brainy.search('', 100, {
896
- metadata: { type: 'config' }
897
- });
898
- spinner.stop();
899
- if (results.length === 0) {
900
- console.log(colors.warning('No configuration found'));
901
- return;
902
- }
903
- const table = new Table({
904
- head: [colors.bold('Key'), colors.bold('Encrypted'), colors.bold('Timestamp')],
905
- style: { head: ['cyan'] }
906
- });
907
- results.forEach(result => {
908
- const meta = result.metadata;
909
- table.push([
910
- colors.primary(meta.key),
911
- meta.encrypted ? `${emojis.lock} Yes` : 'No',
912
- colors.dim(new Date(meta.timestamp).toLocaleString())
913
- ]);
914
- });
915
- console.log(`\n${emojis.config} ${colors.bold('Configuration:')}\n`);
916
- console.log(table.toString());
917
- }
918
- catch (error) {
919
- spinner.fail('Failed to list configuration');
920
- console.error(error);
921
- }
922
- }
923
- /**
924
- * Storage migration with beautiful progress
925
- */
926
- async migrate(options) {
927
- await this.ensureInitialized();
928
- console.log(boxen(`${emojis.package} ${colors.bold('Storage Migration')}\n` +
929
- `From: ${colors.dim(this.config.storage)}\n` +
930
- `To: ${colors.primary(options.to)}`, { padding: 1, borderStyle: 'round', borderColor: 'yellow' }));
931
- const { confirm } = await prompts({
932
- type: 'confirm',
933
- name: 'confirm',
934
- message: 'Start migration?',
935
- initial: true
936
- });
937
- if (!confirm) {
938
- console.log(colors.dim('Migration cancelled'));
939
- return;
940
- }
941
- const spinner = ora('Starting migration...').start();
942
- try {
943
- // Create new Brainy instance with target storage
944
- let targetConfig = {};
945
- if (options.to === 'filesystem') {
946
- targetConfig.storage = { forceFileSystemStorage: true };
947
- }
948
- else if (options.to === 's3' && options.bucket) {
949
- targetConfig.storage = {
950
- s3Storage: {
951
- bucketName: options.bucket
952
- }
953
- };
954
- }
955
- else if (options.to === 'gcs' && options.bucket) {
956
- targetConfig.storage = {
957
- gcsStorage: {
958
- bucketName: options.bucket
959
- }
960
- };
961
- }
962
- else if (options.to === 'memory') {
963
- targetConfig.storage = { forceMemoryStorage: true };
964
- }
965
- const targetBrainy = new BrainyData(targetConfig);
966
- await targetBrainy.init();
967
- spinner.text = 'Counting items...';
968
- // For now, we'll search for all items
969
- const allData = await this.brainy.search('', 1000);
970
- const total = allData.length;
971
- spinner.text = `Migrating ${total} items...`;
972
- for (let i = 0; i < allData.length; i++) {
973
- const item = allData[i];
974
- // Re-add the data to the new storage
975
- await targetBrainy.add(item.id, item.metadata || {});
976
- if (i % 10 === 0) {
977
- spinner.text = `Migrating... ${i + 1}/${total} (${((i + 1) / total * 100).toFixed(0)}%)`;
978
- }
979
- }
980
- spinner.succeed(colors.success(`${emojis.party} Migration complete! ${total} items migrated.`));
981
- // Update config
982
- this.config.storage = options.to;
983
- if (options.bucket) {
984
- if (options.to === 's3')
985
- this.config.s3Bucket = options.bucket;
986
- if (options.to === 'gcs')
987
- this.config.gcsBucket = options.bucket;
988
- }
989
- await this.saveConfig();
990
- }
991
- catch (error) {
992
- spinner.fail('Migration failed');
993
- console.error(error);
994
- process.exit(1);
995
- }
996
- }
997
- /**
998
- * Show comprehensive statistics and database info
999
- */
1000
- async stats(detailed = false) {
1001
- await this.ensureInitialized();
1002
- const spinner = ora('Gathering statistics...').start();
1003
- try {
1004
- // Gather comprehensive stats
1005
- const allItems = await this.brainy.search('', 1000);
1006
- const itemsWithVerbs = allItems.filter((item) => item.verbs && item.verbs.length > 0);
1007
- // Count unique field names
1008
- const fieldCounts = new Map();
1009
- const fieldTypes = new Map();
1010
- allItems.forEach((item) => {
1011
- if (item.metadata) {
1012
- Object.entries(item.metadata).forEach(([key, value]) => {
1013
- fieldCounts.set(key, (fieldCounts.get(key) || 0) + 1);
1014
- if (!fieldTypes.has(key)) {
1015
- fieldTypes.set(key, new Set());
1016
- }
1017
- fieldTypes.get(key).add(typeof value);
1018
- });
1019
- }
1020
- });
1021
- // Calculate storage size (approximate)
1022
- const storageSize = JSON.stringify(allItems).length;
1023
- const stats = {
1024
- totalItems: allItems.length,
1025
- itemsWithMetadata: allItems.filter((i) => i.metadata).length,
1026
- itemsWithConnections: itemsWithVerbs.length,
1027
- totalConnections: itemsWithVerbs.reduce((sum, item) => sum + item.verbs.length, 0),
1028
- avgConnections: itemsWithVerbs.length > 0
1029
- ? itemsWithVerbs.reduce((sum, item) => sum + item.verbs.length, 0) / itemsWithVerbs.length
1030
- : 0,
1031
- uniqueFields: fieldCounts.size,
1032
- storageSize,
1033
- dimensions: 384,
1034
- embeddingModel: 'all-MiniLM-L6-v2'
1035
- };
1036
- spinner.stop();
1037
- // Atomic age statistics display
1038
- const statsBox = boxen(`${emojis.atom} ${colors.brain('LABORATORY STATUS')} ${emojis.data}\n\n` +
1039
- `${colors.retro('β—† Specimen Count:')} ${colors.highlight(stats.totalItems)}\n` +
1040
- `${colors.retro('β—† Catalogued:')} ${colors.highlight(stats.itemsWithMetadata)} ${colors.accent('(' + (stats.itemsWithMetadata / stats.totalItems * 100).toFixed(1) + '%)')}\n` +
1041
- `${colors.retro('β—† Neural Links:')} ${colors.highlight(stats.itemsWithConnections)}\n` +
1042
- `${colors.retro('β—† Total Connections:')} ${colors.highlight(stats.totalConnections)}\n` +
1043
- `${colors.retro('β—† Avg Network Density:')} ${colors.highlight(stats.avgConnections.toFixed(2))}\n` +
1044
- `${colors.retro('β—† Data Dimensions:')} ${colors.highlight(stats.uniqueFields)}\n` +
1045
- `${colors.retro('β—† Storage Matrix:')} ${colors.accent((stats.storageSize / 1024).toFixed(2) + ' KB')}\n` +
1046
- `${colors.retro('β—† Archive Type:')} ${colors.primary(this.config.storage)}\n` +
1047
- `${colors.retro('β—† Neural Model:')} ${colors.info(stats.embeddingModel)} ${colors.dim('(' + stats.dimensions + 'd)')}`, {
1048
- padding: 1,
1049
- borderStyle: 'round',
1050
- borderColor: '#D67441' // Retro orange border
1051
- });
1052
- console.log(statsBox);
1053
- // Detailed field statistics if requested
1054
- if (detailed && fieldCounts.size > 0) {
1055
- const fieldTable = new Table({
1056
- head: [
1057
- colors.bold('Field Name'),
1058
- colors.bold('Count'),
1059
- colors.bold('Coverage'),
1060
- colors.bold('Types')
1061
- ],
1062
- style: { head: ['cyan'] }
1063
- });
1064
- Array.from(fieldCounts.entries())
1065
- .sort((a, b) => b[1] - a[1])
1066
- .slice(0, 15)
1067
- .forEach(([field, count]) => {
1068
- fieldTable.push([
1069
- colors.primary(field),
1070
- count.toString(),
1071
- `${(count / stats.totalItems * 100).toFixed(1)}%`,
1072
- Array.from(fieldTypes.get(field) || []).join(', ')
1073
- ]);
1074
- });
1075
- console.log(`\n${colors.bold('Top Fields:')}\n`);
1076
- console.log(fieldTable.toString());
1077
- }
1078
- }
1079
- catch (error) {
1080
- spinner.fail('Failed to get statistics');
1081
- console.error(error);
1082
- }
1083
- }
1084
- /**
1085
- * List all searchable fields with statistics
1086
- */
1087
- async listFields() {
1088
- await this.ensureInitialized();
1089
- const spinner = ora('Analyzing fields...').start();
1090
- try {
1091
- const allItems = await this.brainy.search('', 1000);
1092
- const fieldInfo = new Map();
1093
- // Analyze all fields
1094
- allItems.forEach((item) => {
1095
- if (item.metadata) {
1096
- Object.entries(item.metadata).forEach(([key, value]) => {
1097
- if (!fieldInfo.has(key)) {
1098
- fieldInfo.set(key, { count: 0, types: new Set(), samples: [] });
1099
- }
1100
- const info = fieldInfo.get(key);
1101
- info.count++;
1102
- info.types.add(typeof value);
1103
- if (info.samples.length < 3 && value !== null && value !== undefined) {
1104
- info.samples.push(value);
1105
- }
1106
- });
1107
- }
1108
- });
1109
- spinner.stop();
1110
- if (fieldInfo.size === 0) {
1111
- console.log(colors.warning('No fields found in metadata'));
1112
- return;
1113
- }
1114
- const table = new Table({
1115
- head: [
1116
- colors.bold('Field'),
1117
- colors.bold('Type(s)'),
1118
- colors.bold('Count'),
1119
- colors.bold('Sample Values')
1120
- ],
1121
- style: { head: ['cyan'] },
1122
- colWidths: [20, 15, 10, 40]
1123
- });
1124
- Array.from(fieldInfo.entries())
1125
- .sort((a, b) => b[1].count - a[1].count)
1126
- .forEach(([field, info]) => {
1127
- const samples = info.samples
1128
- .slice(0, 2)
1129
- .map(s => JSON.stringify(s).slice(0, 20))
1130
- .join(', ');
1131
- table.push([
1132
- colors.primary(field),
1133
- Array.from(info.types).join(', '),
1134
- info.count.toString(),
1135
- colors.dim(samples + (info.samples.length > 2 ? '...' : ''))
1136
- ]);
1137
- });
1138
- console.log(`\n${emojis.search} ${colors.bold('Searchable Fields:')}\n`);
1139
- console.log(table.toString());
1140
- console.log(`\n${colors.dim('Use these fields in searches:')}`);
1141
- console.log(colors.dim(`cortex search "query" --filter '{"${Array.from(fieldInfo.keys())[0]}": "value"}'`));
1142
- }
1143
- catch (error) {
1144
- spinner.fail('Failed to analyze fields');
1145
- console.error(error);
1146
- }
1147
- }
1148
- /**
1149
- * Setup LLM progressively with auto-download
1150
- */
1151
- async setupLLM(provider) {
1152
- await this.ensureInitialized();
1153
- console.log(boxen(`${emojis.robot} ${colors.bold('LLM Setup Assistant')}\n` +
1154
- `${colors.dim('Configure AI models for enhanced chat')}`, { padding: 1, borderStyle: 'round', borderColor: 'magenta' }));
1155
- const choices = [
1156
- {
1157
- title: `${emojis.brain} Local Model (No API key needed)`,
1158
- value: 'local',
1159
- description: 'Download and run models locally'
1160
- },
1161
- {
1162
- title: `${emojis.cloud} Claude (Anthropic)`,
1163
- value: 'claude',
1164
- description: 'Most capable, requires API key'
1165
- },
1166
- {
1167
- title: `${emojis.cloud} GPT-4 (OpenAI)`,
1168
- value: 'openai',
1169
- description: 'Powerful, requires API key'
1170
- },
1171
- {
1172
- title: `${emojis.sparkle} Ollama (Local server)`,
1173
- value: 'ollama',
1174
- description: 'Connect to local Ollama instance'
1175
- },
1176
- {
1177
- title: `${emojis.magic} Claude Desktop`,
1178
- value: 'claude-desktop',
1179
- description: 'Use Claude app on your computer'
1180
- }
1181
- ];
1182
- const { llmType } = await prompts({
1183
- type: 'select',
1184
- name: 'llmType',
1185
- message: 'Choose LLM provider:',
1186
- choices: provider ? choices.filter(c => c.value === provider) : choices
1187
- });
1188
- switch (llmType) {
1189
- case 'local':
1190
- await this.setupLocalLLM();
1191
- break;
1192
- case 'claude':
1193
- await this.setupClaudeLLM();
1194
- break;
1195
- case 'openai':
1196
- await this.setupOpenAILLM();
1197
- break;
1198
- case 'ollama':
1199
- await this.setupOllamaLLM();
1200
- break;
1201
- case 'claude-desktop':
1202
- await this.setupClaudeDesktop();
1203
- break;
1204
- }
1205
- }
1206
- async setupLocalLLM() {
1207
- const { model } = await prompts({
1208
- type: 'select',
1209
- name: 'model',
1210
- message: 'Choose a local model:',
1211
- choices: [
1212
- { title: 'LaMini-Flan-T5 (77M, fast)', value: 'Xenova/LaMini-Flan-T5-77M' },
1213
- { title: 'Phi-2 (2.7B, balanced)', value: 'microsoft/phi-2' },
1214
- { title: 'CodeLlama (7B, for code)', value: 'codellama/CodeLlama-7b-hf' },
1215
- { title: 'Custom Hugging Face model', value: 'custom' }
1216
- ]
1217
- });
1218
- let modelName = model;
1219
- if (model === 'custom') {
1220
- const { customModel } = await prompts({
1221
- type: 'text',
1222
- name: 'customModel',
1223
- message: 'Enter Hugging Face model ID (e.g., microsoft/DialoGPT-medium):'
1224
- });
1225
- modelName = customModel;
1226
- }
1227
- const spinner = ora(`Downloading ${modelName}...`).start();
1228
- try {
1229
- // Save configuration
1230
- await this.configSet('LLM_PROVIDER', 'local');
1231
- await this.configSet('LLM_MODEL', modelName);
1232
- // Test the model
1233
- this.config.llm = modelName;
1234
- this.chatInstance = new BrainyChat(this.brainy);
1235
- spinner.succeed(colors.success(`${emojis.check} Local model configured: ${modelName}`));
1236
- console.log(colors.dim('\nModel will download on first use. This may take a few minutes.'));
1237
- }
1238
- catch (error) {
1239
- spinner.fail('Failed to setup local model');
1240
- console.error(error);
1241
- }
1242
- }
1243
- async setupClaudeLLM() {
1244
- const { apiKey } = await prompts({
1245
- type: 'password',
1246
- name: 'apiKey',
1247
- message: 'Enter your Anthropic API key:'
1248
- });
1249
- if (apiKey) {
1250
- await this.configSet('ANTHROPIC_API_KEY', apiKey, { encrypt: true });
1251
- await this.configSet('LLM_PROVIDER', 'claude');
1252
- await this.configSet('LLM_MODEL', 'claude-3-5-sonnet-20241022');
1253
- this.config.llm = 'claude-3-5-sonnet';
1254
- console.log(colors.success(`${emojis.check} Claude configured successfully!`));
1255
- }
1256
- }
1257
- async setupOpenAILLM() {
1258
- const { apiKey } = await prompts({
1259
- type: 'password',
1260
- name: 'apiKey',
1261
- message: 'Enter your OpenAI API key:'
1262
- });
1263
- if (apiKey) {
1264
- await this.configSet('OPENAI_API_KEY', apiKey, { encrypt: true });
1265
- await this.configSet('LLM_PROVIDER', 'openai');
1266
- await this.configSet('LLM_MODEL', 'gpt-4o-mini');
1267
- this.config.llm = 'gpt-4o-mini';
1268
- console.log(colors.success(`${emojis.check} OpenAI configured successfully!`));
1269
- }
1270
- }
1271
- async setupOllamaLLM() {
1272
- const { url, model } = await prompts([
1273
- {
1274
- type: 'text',
1275
- name: 'url',
1276
- message: 'Ollama server URL:',
1277
- initial: 'http://localhost:11434'
1278
- },
1279
- {
1280
- type: 'text',
1281
- name: 'model',
1282
- message: 'Model name:',
1283
- initial: 'llama2'
1284
- }
1285
- ]);
1286
- await this.configSet('OLLAMA_URL', url);
1287
- await this.configSet('OLLAMA_MODEL', model);
1288
- await this.configSet('LLM_PROVIDER', 'ollama');
1289
- console.log(colors.success(`${emojis.check} Ollama configured!`));
1290
- console.log(colors.dim(`Make sure Ollama is running: ollama run ${model}`));
1291
- }
1292
- async setupClaudeDesktop() {
1293
- console.log(colors.info(`${emojis.info} Claude Desktop integration coming soon!`));
1294
- console.log(colors.dim('This will allow using Claude app as your LLM provider'));
1295
- }
1296
- /**
1297
- * Use the embedding model for other tasks
1298
- */
1299
- async embed(text) {
1300
- await this.ensureInitialized();
1301
- const spinner = ora('Generating embedding...').start();
1302
- try {
1303
- // Use Brainy's built-in embedding
1304
- const vector = await this.brainy.embed(text);
1305
- spinner.stop();
1306
- console.log(boxen(`${emojis.sparkle} ${colors.bold('Text Embedding')}\n\n` +
1307
- `${colors.dim('Input:')}\n"${text}"\n\n` +
1308
- `${colors.dim('Model:')} all-MiniLM-L6-v2 (384d)\n` +
1309
- `${colors.dim('Vector:')} [${vector.slice(0, 5).map(v => v.toFixed(4)).join(', ')}...]\n` +
1310
- `${colors.dim('Magnitude:')} ${Math.sqrt(vector.reduce((sum, v) => sum + v * v, 0)).toFixed(4)}`, { padding: 1, borderStyle: 'round', borderColor: 'cyan' }));
1311
- }
1312
- catch (error) {
1313
- spinner.fail('Failed to generate embedding');
1314
- console.error(error);
1315
- }
1316
- }
1317
- /**
1318
- * Calculate similarity between two texts
1319
- */
1320
- async similarity(text1, text2) {
1321
- await this.ensureInitialized();
1322
- const spinner = ora('Calculating similarity...').start();
1323
- try {
1324
- const vector1 = await this.brainy.embed(text1);
1325
- const vector2 = await this.brainy.embed(text2);
1326
- // Calculate cosine similarity
1327
- const dotProduct = vector1.reduce((sum, v, i) => sum + v * vector2[i], 0);
1328
- const mag1 = Math.sqrt(vector1.reduce((sum, v) => sum + v * v, 0));
1329
- const mag2 = Math.sqrt(vector2.reduce((sum, v) => sum + v * v, 0));
1330
- const similarity = dotProduct / (mag1 * mag2);
1331
- spinner.stop();
1332
- const color = similarity > 0.8 ? colors.success :
1333
- similarity > 0.5 ? colors.warning :
1334
- colors.error;
1335
- console.log(boxen(`${emojis.search} ${colors.bold('Semantic Similarity')}\n\n` +
1336
- `${colors.dim('Text 1:')}\n"${text1}"\n\n` +
1337
- `${colors.dim('Text 2:')}\n"${text2}"\n\n` +
1338
- `${colors.bold('Similarity:')} ${color((similarity * 100).toFixed(1) + '%')}\n` +
1339
- `${this.getSimilarityInterpretation(similarity)}`, { padding: 1, borderStyle: 'round', borderColor: 'magenta' }));
1340
- }
1341
- catch (error) {
1342
- spinner.fail('Failed to calculate similarity');
1343
- console.error(error);
1344
- }
1345
- }
1346
- getSimilarityInterpretation(score) {
1347
- if (score > 0.9)
1348
- return colors.success('✨ Nearly identical meaning');
1349
- if (score > 0.8)
1350
- return colors.success('🎯 Very similar');
1351
- if (score > 0.7)
1352
- return colors.warning('πŸ‘ Similar');
1353
- if (score > 0.5)
1354
- return colors.warning('πŸ€” Somewhat related');
1355
- if (score > 0.3)
1356
- return colors.error('😐 Loosely related');
1357
- return colors.error('❌ Unrelated');
1358
- }
1359
- /**
1360
- * Import .env file with automatic encryption of secrets
1361
- */
1362
- async importEnv(filePath) {
1363
- await this.ensureInitialized();
1364
- const spinner = ora('Importing environment variables...').start();
1365
- try {
1366
- const envContent = await fs.readFile(filePath, 'utf-8');
1367
- const lines = envContent.split('\n');
1368
- let imported = 0;
1369
- let encrypted = 0;
1370
- for (const line of lines) {
1371
- const trimmed = line.trim();
1372
- if (!trimmed || trimmed.startsWith('#'))
1373
- continue;
1374
- const [key, ...valueParts] = trimmed.split('=');
1375
- const value = valueParts.join('=').replace(/^["']|["']$/g, '');
1376
- if (key && value) {
1377
- const shouldEncrypt = this.isSecret(key);
1378
- await this.configSet(key, value, { encrypt: shouldEncrypt });
1379
- imported++;
1380
- if (shouldEncrypt)
1381
- encrypted++;
1382
- }
1383
- }
1384
- spinner.succeed(colors.success(`${emojis.check} Imported ${imported} variables (${encrypted} encrypted)`));
1385
- }
1386
- catch (error) {
1387
- spinner.fail('Failed to import .env file');
1388
- console.error(error);
1389
- }
1390
- }
1391
- /**
1392
- * Export configuration to .env file
1393
- */
1394
- async exportEnv(filePath) {
1395
- await this.ensureInitialized();
1396
- const spinner = ora('Exporting configuration...').start();
1397
- try {
1398
- const results = await this.brainy.search('', 1000, {
1399
- metadata: { type: 'config' }
1400
- });
1401
- let content = '# Exported from Cortex\n';
1402
- content += `# Generated: ${new Date().toISOString()}\n\n`;
1403
- for (const result of results) {
1404
- const meta = result.metadata;
1405
- if (meta?.key) {
1406
- const value = await this.configGet(meta.key);
1407
- if (value) {
1408
- content += `${meta.key}=${value}\n`;
1409
- }
1410
- }
1411
- }
1412
- await fs.writeFile(filePath, content);
1413
- spinner.succeed(colors.success(`${emojis.check} Exported to ${filePath}`));
1414
- }
1415
- catch (error) {
1416
- spinner.fail('Failed to export configuration');
1417
- console.error(error);
1418
- }
1419
- }
1420
- /**
1421
- * Delete data by ID
1422
- */
1423
- async delete(id) {
1424
- await this.ensureInitialized();
1425
- const spinner = ora('Deleting...').start();
1426
- try {
1427
- // For now, mark as deleted in metadata
1428
- await this.brainy.add(id, {
1429
- _deleted: true,
1430
- _deletedAt: new Date().toISOString()
1431
- });
1432
- spinner.succeed(colors.success(`${emojis.check} Deleted: ${id}`));
1433
- }
1434
- catch (error) {
1435
- spinner.fail('Delete failed');
1436
- console.error(error);
1437
- }
1438
- }
1439
- /**
1440
- * Update data by ID
1441
- */
1442
- async update(id, data, metadata) {
1443
- await this.ensureInitialized();
1444
- const spinner = ora('Updating...').start();
1445
- try {
1446
- // Re-add with same ID (overwrites)
1447
- await this.brainy.add(data, {
1448
- ...metadata,
1449
- id,
1450
- _updated: true,
1451
- _updatedAt: new Date().toISOString()
1452
- });
1453
- spinner.succeed(colors.success(`${emojis.check} Updated: ${id}`));
1454
- }
1455
- catch (error) {
1456
- spinner.fail('Update failed');
1457
- console.error(error);
1458
- }
1459
- }
1460
- /**
1461
- * Helpers
1462
- */
1463
- async ensureInitialized() {
1464
- if (!await this.isInitialized()) {
1465
- console.log(colors.warning(`${emojis.warning} Cortex not initialized. Run 'cortex init' first.`));
1466
- process.exit(1);
1467
- }
1468
- // Load encryption key if encryption is enabled
1469
- if (this.config.encryptionEnabled && !this.encryptionKey) {
1470
- await this.loadMasterKey();
1471
- }
1472
- // Load custom secret patterns
1473
- await this.loadCustomPatterns();
1474
- if (!this.brainy) {
1475
- await this.initBrainy();
1476
- }
1477
- }
1478
- /**
1479
- * Load master key from various sources
1480
- */
1481
- async loadMasterKey() {
1482
- // Try environment variable first
1483
- const envKey = process.env.CORTEX_MASTER_KEY;
1484
- if (envKey && envKey.length >= 32) {
1485
- this.encryptionKey = Buffer.from(envKey.substring(0, 32));
1486
- this.masterKeySource = 'env';
1487
- return;
1488
- }
1489
- // Try stored key file
1490
- const keyPath = path.join(path.dirname(this.configPath), '.master_key');
1491
- try {
1492
- await fs.access(keyPath);
1493
- const keyData = await fs.readFile(keyPath);
1494
- if (keyData.length === 32) {
1495
- // Generated key
1496
- this.encryptionKey = keyData;
1497
- this.masterKeySource = 'generated';
1498
- }
1499
- else {
1500
- // Passphrase-derived key
1501
- await this.loadPassphraseKey();
1502
- this.masterKeySource = 'passphrase';
1503
- }
1504
- }
1505
- catch {
1506
- console.log(colors.warning(`${emojis.warning} Encryption key not found. Some features may not work.`));
1507
- }
1508
- }
1509
- async isInitialized() {
1510
- try {
1511
- await fs.access(this.configPath);
1512
- const data = await fs.readFile(this.configPath, 'utf-8');
1513
- this.config = JSON.parse(data);
1514
- return this.config.initialized === true;
1515
- }
1516
- catch {
1517
- return false;
1518
- }
1519
- }
1520
- async initBrainy() {
1521
- // Map storage type to BrainyData config
1522
- let config = {};
1523
- if (this.config.storage === 'filesystem') {
1524
- config.storage = { forceFileSystemStorage: true };
1525
- }
1526
- else if (this.config.storage === 's3' && this.config.s3Bucket) {
1527
- config.storage = {
1528
- s3Storage: {
1529
- bucketName: this.config.s3Bucket
1530
- }
1531
- };
1532
- }
1533
- else if (this.config.storage === 'r2' && this.config.r2Bucket) {
1534
- // Cloudflare R2 is S3-compatible, so we use the s3Storage configuration
1535
- // Users need to set environment variables:
1536
- // CLOUDFLARE_R2_ACCOUNT_ID, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
1537
- config.storage = {
1538
- s3Storage: {
1539
- bucketName: this.config.r2Bucket,
1540
- // R2 endpoint format: https://<account-id>.r2.cloudflarestorage.com
1541
- // The actual account ID should come from environment variables
1542
- endpoint: process.env.CLOUDFLARE_R2_ENDPOINT || `https://${process.env.CLOUDFLARE_R2_ACCOUNT_ID}.r2.cloudflarestorage.com`
1543
- }
1544
- };
1545
- }
1546
- else if (this.config.storage === 'gcs' && this.config.gcsBucket) {
1547
- config.storage = {
1548
- gcsStorage: {
1549
- bucketName: this.config.gcsBucket
1550
- }
1551
- };
1552
- }
1553
- else if (this.config.storage === 'memory') {
1554
- config.storage = { forceMemoryStorage: true };
1555
- }
1556
- this.brainy = new BrainyData(config);
1557
- await this.brainy.init();
1558
- // Initialize monitoring systems
1559
- this.performanceMonitor = new PerformanceMonitor(this.brainy);
1560
- this.healthCheck = new HealthCheck(this.brainy);
1561
- // Initialize licensing system
1562
- // Licensing system moved to quantum-vault for premium features
1563
- // Open source version has full functionality available
1564
- }
1565
- async saveConfig() {
1566
- const dir = path.dirname(this.configPath);
1567
- await fs.mkdir(dir, { recursive: true });
1568
- await fs.writeFile(this.configPath, JSON.stringify(this.config, null, 2));
1569
- }
1570
- /**
1571
- * Enhanced secret detection with custom patterns and categories
1572
- */
1573
- isSecret(key) {
1574
- const defaultSecretPatterns = [
1575
- // Standard secret patterns
1576
- /key$/i, /token$/i, /secret$/i, /password$/i, /pass$/i,
1577
- /^api[_-]?key$/i, /^auth[_-]?token$/i,
1578
- // API keys
1579
- /^openai[_-]?api[_-]?key$/i, /^anthropic[_-]?api[_-]?key$/i,
1580
- /^claude[_-]?api[_-]?key$/i, /^huggingface[_-]?token$/i,
1581
- /^github[_-]?token$/i, /^gitlab[_-]?token$/i,
1582
- // Database URLs
1583
- /database.*url$/i, /db.*url$/i, /connection[_-]?string$/i,
1584
- /mongo.*url$/i, /redis.*url$/i, /postgres.*url$/i,
1585
- // Cloud & Infrastructure
1586
- /aws.*key$/i, /aws.*secret$/i, /azure.*key$/i, /gcp.*key$/i,
1587
- /docker.*password$/i, /registry.*password$/i,
1588
- // Production patterns
1589
- /.*_prod_.*$/i, /.*_production_.*$/i,
1590
- /.*_live_.*$/i, /.*_master_.*$/i,
1591
- // Common service patterns
1592
- /stripe.*key$/i, /twilio.*token$/i, /sendgrid.*key$/i,
1593
- /jwt.*secret$/i, /session.*secret$/i, /encryption.*key$/i
1594
- ];
1595
- // Combine default and custom patterns
1596
- const allPatterns = [...defaultSecretPatterns, ...this.customSecretPatterns];
1597
- return allPatterns.some(pattern => pattern.test(key));
1598
- }
1599
- /**
1600
- * Add custom secret detection patterns
1601
- */
1602
- async addSecretPattern(pattern) {
1603
- try {
1604
- const regex = new RegExp(pattern, 'i');
1605
- this.customSecretPatterns.push(regex);
1606
- // Persist custom patterns
1607
- await this.saveCustomPatterns();
1608
- console.log(colors.success(`${emojis.check} Added secret pattern: ${pattern}`));
1609
- }
1610
- catch (error) {
1611
- throw new Error(`Invalid regex pattern: ${pattern}`);
1612
- }
1613
- }
1614
- /**
1615
- * Remove custom secret detection pattern
1616
- */
1617
- async removeSecretPattern(pattern) {
1618
- const index = this.customSecretPatterns.findIndex(p => p.source === pattern);
1619
- if (index === -1) {
1620
- throw new Error(`Pattern not found: ${pattern}`);
1621
- }
1622
- this.customSecretPatterns.splice(index, 1);
1623
- await this.saveCustomPatterns();
1624
- console.log(colors.success(`${emojis.check} Removed secret pattern: ${pattern}`));
1625
- }
1626
- /**
1627
- * List all secret detection patterns
1628
- */
1629
- async listSecretPatterns() {
1630
- console.log(boxen(`${emojis.shield} ${colors.brain('SECRET DETECTION PATTERNS')}\n\n` +
1631
- `${colors.retro('β—† Built-in Patterns:')}\n` +
1632
- ` β€’ API keys (*_key, *_token, *_secret)\n` +
1633
- ` β€’ Database URLs (*_url, connection_string)\n` +
1634
- ` β€’ Cloud credentials (aws_*, azure_*, gcp_*)\n` +
1635
- ` β€’ Production vars (*_prod_*, *_production_*)\n\n` +
1636
- `${colors.retro('β—† Custom Patterns:')}\n` +
1637
- (this.customSecretPatterns.length > 0
1638
- ? this.customSecretPatterns.map(p => ` β€’ ${p.source}`).join('\n')
1639
- : ` ${colors.dim('No custom patterns defined')}`), { padding: 1, borderStyle: 'round', borderColor: '#D67441' }));
1640
- }
1641
- /**
1642
- * Save custom patterns to disk
1643
- */
1644
- async saveCustomPatterns() {
1645
- const patternsPath = path.join(path.dirname(this.configPath), 'secret_patterns.json');
1646
- const patterns = this.customSecretPatterns.map(p => p.source);
1647
- await fs.writeFile(patternsPath, JSON.stringify(patterns, null, 2));
1648
- }
1649
- /**
1650
- * Load custom patterns from disk
1651
- */
1652
- async loadCustomPatterns() {
1653
- const patternsPath = path.join(path.dirname(this.configPath), 'secret_patterns.json');
1654
- try {
1655
- const data = await fs.readFile(patternsPath, 'utf8');
1656
- const patterns = JSON.parse(data);
1657
- this.customSecretPatterns = patterns.map((p) => new RegExp(p, 'i'));
1658
- }
1659
- catch {
1660
- // No custom patterns yet
1661
- }
1662
- }
1663
- /**
1664
- * Determine config category for enhanced management
1665
- */
1666
- getConfigCategory(key) {
1667
- // Explicit production configuration
1668
- if (key.match(/node_env|environment|stage|tier/i)) {
1669
- return Cortex.CONFIG_CATEGORIES.CONFIG;
1670
- }
1671
- // Public configuration (can be exposed)
1672
- if (key.match(/port|host|timeout|retry|limit|version/i)) {
1673
- return Cortex.CONFIG_CATEGORIES.PUBLIC;
1674
- }
1675
- // Sensitive but not secret (URLs, emails, usernames)
1676
- if (key.match(/url|email|username|user_id|org|organization/i) && !this.isSecret(key)) {
1677
- return Cortex.CONFIG_CATEGORIES.SENSITIVE;
1678
- }
1679
- // Default to secret if matches patterns
1680
- if (this.isSecret(key)) {
1681
- return Cortex.CONFIG_CATEGORIES.SECRET;
1682
- }
1683
- return Cortex.CONFIG_CATEGORIES.CONFIG;
1684
- }
1685
- /**
1686
- * Cortex Augmentation System - AI-Powered Data Understanding
1687
- */
1688
- async neuralImport(filePath, options = {}) {
1689
- await this.ensureInitialized();
1690
- // Import and create the Cortex SENSE augmentation
1691
- const { NeuralImportAugmentation } = await import('../augmentations/neuralImport.js');
1692
- const neuralSense = new NeuralImportAugmentation(this.brainy, options);
1693
- // Initialize the augmentation
1694
- await neuralSense.initialize();
1695
- try {
1696
- // Read the file
1697
- const fs = await import('fs/promises');
1698
- const fileContent = await fs.readFile(filePath, 'utf8');
1699
- const dataType = this.getDataTypeFromPath(filePath);
1700
- // Use the SENSE augmentation to process the data
1701
- const result = await neuralSense.processRawData(fileContent, dataType, options);
1702
- if (result.success) {
1703
- console.log(colors.success('βœ… Cortex import completed successfully'));
1704
- // Display summary
1705
- console.log(colors.primary(`πŸ“Š Processed: ${result.data.nouns.length} entities, ${result.data.verbs.length} relationships`));
1706
- if (result.data.confidence !== undefined) {
1707
- console.log(colors.primary(`🎯 Overall confidence: ${(result.data.confidence * 100).toFixed(1)}%`));
1708
- }
1709
- if (result.data.insights && result.data.insights.length > 0) {
1710
- console.log(colors.brain('\n🧠 Neural Insights:'));
1711
- result.data.insights.forEach((insight) => {
1712
- console.log(` ${colors.accent('β—†')} ${insight.description} (${(insight.confidence * 100).toFixed(1)}%)`);
1713
- });
1714
- }
1715
- }
1716
- else {
1717
- console.error(colors.error('❌ Cortex import failed:'), result.error);
1718
- }
1719
- }
1720
- finally {
1721
- await neuralSense.shutDown();
1722
- }
1723
- }
1724
- async neuralAnalyze(filePath) {
1725
- await this.ensureInitialized();
1726
- const { NeuralImportAugmentation } = await import('../augmentations/neuralImport.js');
1727
- const neuralSense = new NeuralImportAugmentation(this.brainy);
1728
- await neuralSense.initialize();
1729
- try {
1730
- const fs = await import('fs/promises');
1731
- const fileContent = await fs.readFile(filePath, 'utf8');
1732
- const dataType = this.getDataTypeFromPath(filePath);
1733
- // Use the analyzeStructure method
1734
- const result = await neuralSense.analyzeStructure(fileContent, dataType);
1735
- if (result.success) {
1736
- console.log(boxen(`${emojis.lab} ${colors.brain('NEURAL ANALYSIS RESULTS')}\n\n` +
1737
- `Entity Types: ${result.data.entityTypes.length}\n` +
1738
- `Relationship Types: ${result.data.relationshipTypes.length}\n` +
1739
- `Data Quality Score: ${((result.data.dataQuality.completeness + result.data.dataQuality.consistency + result.data.dataQuality.accuracy) / 3 * 100).toFixed(1)}%`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
1740
- if (result.data.recommendations.length > 0) {
1741
- console.log(colors.brain('\nπŸ’‘ Recommendations:'));
1742
- result.data.recommendations.forEach((rec) => {
1743
- console.log(` ${colors.accent('β—†')} ${rec}`);
1744
- });
1745
- }
1746
- }
1747
- else {
1748
- console.error(colors.error('❌ Analysis failed:'), result.error);
1749
- }
1750
- }
1751
- finally {
1752
- await neuralSense.shutDown();
1753
- }
1754
- }
1755
- async neuralValidate(filePath) {
1756
- await this.ensureInitialized();
1757
- const { NeuralImportAugmentation } = await import('../augmentations/neuralImport.js');
1758
- const neuralSense = new NeuralImportAugmentation(this.brainy);
1759
- await neuralSense.initialize();
1760
- try {
1761
- const fs = await import('fs/promises');
1762
- const fileContent = await fs.readFile(filePath, 'utf8');
1763
- const dataType = this.getDataTypeFromPath(filePath);
1764
- // Use the validateCompatibility method
1765
- const result = await neuralSense.validateCompatibility(fileContent, dataType);
1766
- if (result.success) {
1767
- const statusIcon = result.data.compatible ? 'βœ…' : '⚠️';
1768
- const statusText = result.data.compatible ? 'COMPATIBLE' : 'COMPATIBILITY ISSUES';
1769
- console.log(boxen(`${statusIcon} ${colors.brain(`DATA ${statusText}`)}\n\n` +
1770
- `Compatible: ${result.data.compatible ? 'Yes' : 'No'}\n` +
1771
- `Issues Found: ${result.data.issues.length}\n` +
1772
- `Suggestions: ${result.data.suggestions.length}`, { padding: 1, borderStyle: 'round', borderColor: result.data.compatible ? '#2D4A3A' : '#D67441' }));
1773
- if (result.data.issues.length > 0) {
1774
- console.log(colors.warning('\n⚠️ Issues:'));
1775
- result.data.issues.forEach((issue) => {
1776
- const severityColor = issue.severity === 'high' ? colors.error :
1777
- issue.severity === 'medium' ? colors.warning : colors.dim;
1778
- console.log(` ${severityColor(`[${issue.severity.toUpperCase()}]`)} ${issue.description}`);
1779
- });
1780
- }
1781
- if (result.data.suggestions.length > 0) {
1782
- console.log(colors.brain('\nπŸ’‘ Suggestions:'));
1783
- result.data.suggestions.forEach((suggestion) => {
1784
- console.log(` ${colors.accent('β—†')} ${suggestion}`);
1785
- });
1786
- }
1787
- }
1788
- else {
1789
- console.error(colors.error('❌ Validation failed:'), result.error);
1790
- }
1791
- }
1792
- finally {
1793
- await neuralSense.shutDown();
1794
- }
1795
- }
1796
- async neuralTypes() {
1797
- await this.ensureInitialized();
1798
- const { NounType, VerbType } = await import('../types/graphTypes.js');
1799
- console.log(boxen(`${emojis.atom} ${colors.brain('NEURAL TYPE SYSTEM')}\n\n` +
1800
- `${colors.retro('β—† Available Noun Types:')} ${colors.highlight(Object.keys(NounType).length.toString())}\n` +
1801
- `${colors.retro('β—† Available Verb Types:')} ${colors.highlight(Object.keys(VerbType).length.toString())}\n\n` +
1802
- `${colors.accent('β—†')} ${colors.dim('Noun categories: Person, Organization, Location, Thing, Concept, Event...')}\n` +
1803
- `${colors.accent('β—†')} ${colors.dim('Verb categories: Social, Temporal, Causal, Ownership, Functional...')}`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
1804
- // Show sample types
1805
- console.log(`\n${colors.highlight('Sample Noun Types:')}`);
1806
- Object.entries(NounType).slice(0, 8).forEach(([key, value]) => {
1807
- console.log(` ${colors.primary('β€’')} ${key}: ${colors.dim(value)}`);
1808
- });
1809
- console.log(`\n${colors.highlight('Sample Verb Types:')}`);
1810
- Object.entries(VerbType).slice(0, 8).forEach(([key, value]) => {
1811
- console.log(` ${colors.primary('β€’')} ${key}: ${colors.dim(value)}`);
1812
- });
1813
- console.log(`\n${colors.dim('Use')} ${colors.primary('brainy import --cortex <file>')} ${colors.dim('to leverage the full AI type system!')}`);
1814
- }
1815
- /**
1816
- * Augmentation Pipeline Management - Control the Neural Enhancement System
1817
- */
1818
- async listAugmentations() {
1819
- await this.ensureInitialized();
1820
- const spinner = ora('Scanning augmentation systems...').start();
1821
- try {
1822
- // Get current pipeline configuration (placeholder for now)
1823
- spinner.stop();
1824
- // For now, show that augmentation system is available but needs integration
1825
- console.log(colors.info(`${emojis.atom} Augmentation system detected but integration pending`));
1826
- // Show current pipeline status
1827
- console.log(boxen(`${emojis.atom} ${colors.brain('AUGMENTATION PIPELINE STATUS')}\n\n` +
1828
- `${colors.retro('β—† Pipeline State:')} ${colors.success('ACTIVE')}\n` +
1829
- `${colors.retro('β—† Registry Loaded:')} ${colors.success('OPERATIONAL')}\n` +
1830
- `${colors.retro('β—† Available Categories:')} SENSE, MEMORY, COGNITION, CONDUIT, ACTIVATION, PERCEPTION, DIALOG, WEBSOCKET`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
1831
- // List active augmentations by category
1832
- const categories = ['SENSE', 'MEMORY', 'COGNITION', 'CONDUIT', 'ACTIVATION', 'PERCEPTION', 'DIALOG', 'WEBSOCKET'];
1833
- for (const category of categories) {
1834
- console.log(`\n${colors.highlight(category)} ${colors.dim('Augmentations:')}`);
1835
- // This would need to be implemented in the actual augmentation system
1836
- // For now, show example structure
1837
- console.log(` ${colors.dim('β€’ Available augmentations would be listed here')}\n ${colors.dim('β€’ Status: Active/Inactive')}\n ${colors.dim('β€’ Configuration: Parameters')}`);
1838
- }
1839
- }
1840
- catch (error) {
1841
- spinner.fail('Failed to scan augmentations');
1842
- console.error(error);
1843
- }
1844
- }
1845
- async addAugmentation(type, position, config) {
1846
- await this.ensureInitialized();
1847
- console.log(boxen(`${emojis.magic} ${colors.retro('NEURAL ENHANCEMENT PROTOCOL')}\n\n` +
1848
- `${colors.accent('β—†')} ${colors.dim('Adding augmentation to pipeline')}\n` +
1849
- `${colors.accent('β—†')} ${colors.dim('Type:')} ${colors.highlight(type)}\n` +
1850
- `${colors.accent('β—†')} ${colors.dim('Position:')} ${colors.highlight(position || 'auto')}`, { padding: 1, borderStyle: 'round', borderColor: '#D67441' }));
1851
- const { confirm } = await prompts({
1852
- type: 'confirm',
1853
- name: 'confirm',
1854
- message: 'Add this augmentation to the pipeline?',
1855
- initial: true
1856
- });
1857
- if (!confirm) {
1858
- console.log(colors.dim('Augmentation addition cancelled'));
1859
- return;
1860
- }
1861
- const spinner = ora('Installing augmentation...').start();
1862
- try {
1863
- // This would interface with the actual augmentation system
1864
- // For now, simulate the process
1865
- await new Promise(resolve => setTimeout(resolve, 1000));
1866
- spinner.succeed(colors.success(`${emojis.check} Augmentation '${type}' added to pipeline`));
1867
- console.log(colors.dim(`Position: ${position || 'auto-assigned'}`));
1868
- }
1869
- catch (error) {
1870
- spinner.fail('Failed to add augmentation');
1871
- console.error(error);
1872
- }
1873
- }
1874
- async removeAugmentation(type) {
1875
- await this.ensureInitialized();
1876
- console.log(boxen(`${emojis.warning} ${colors.retro('AUGMENTATION REMOVAL PROTOCOL')}\n\n` +
1877
- `${colors.accent('β—†')} ${colors.dim('This will remove the augmentation from the pipeline')}\n` +
1878
- `${colors.accent('β—†')} ${colors.dim('Type:')} ${colors.highlight(type)}`, { padding: 1, borderStyle: 'round', borderColor: '#D67441' }));
1879
- const { confirm } = await prompts({
1880
- type: 'confirm',
1881
- name: 'confirm',
1882
- message: 'Remove this augmentation?',
1883
- initial: false
1884
- });
1885
- if (!confirm) {
1886
- console.log(colors.dim('Augmentation removal cancelled'));
1887
- return;
1888
- }
1889
- const spinner = ora('Removing augmentation...').start();
1890
- try {
1891
- // Interface with augmentation system
1892
- await new Promise(resolve => setTimeout(resolve, 1000));
1893
- spinner.succeed(colors.success(`${emojis.check} Augmentation '${type}' removed from pipeline`));
1894
- }
1895
- catch (error) {
1896
- spinner.fail('Failed to remove augmentation');
1897
- console.error(error);
1898
- }
1899
- }
1900
- async configureAugmentation(type, config) {
1901
- await this.ensureInitialized();
1902
- console.log(boxen(`${emojis.config} ${colors.brain('AUGMENTATION CONFIGURATION')}\n\n` +
1903
- `${colors.retro('β—† Type:')} ${colors.highlight(type)}\n` +
1904
- `${colors.retro('β—† New Config:')} ${colors.dim(JSON.stringify(config, null, 2))}`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
1905
- const { confirm } = await prompts({
1906
- type: 'confirm',
1907
- name: 'confirm',
1908
- message: 'Apply this configuration?',
1909
- initial: true
1910
- });
1911
- if (!confirm) {
1912
- console.log(colors.dim('Configuration cancelled'));
1913
- return;
1914
- }
1915
- const spinner = ora('Updating augmentation configuration...').start();
1916
- try {
1917
- // Interface with augmentation configuration system
1918
- await new Promise(resolve => setTimeout(resolve, 1000));
1919
- spinner.succeed(colors.success(`${emojis.check} Augmentation '${type}' configuration updated`));
1920
- }
1921
- catch (error) {
1922
- spinner.fail('Failed to configure augmentation');
1923
- console.error(error);
1924
- }
1925
- }
1926
- async resetPipeline() {
1927
- await this.ensureInitialized();
1928
- console.log(boxen(`${emojis.warning} ${colors.retro('PIPELINE RESET PROTOCOL')}\n\n` +
1929
- `${colors.accent('β—†')} ${colors.dim('This will reset the entire augmentation pipeline')}\n` +
1930
- `${colors.accent('β—†')} ${colors.dim('All custom configurations will be lost')}\n` +
1931
- `${colors.accent('β—†')} ${colors.dim('Pipeline will return to default state')}`, { padding: 1, borderStyle: 'round', borderColor: '#D67441' }));
1932
- const { confirm } = await prompts({
1933
- type: 'confirm',
1934
- name: 'confirm',
1935
- message: 'Reset augmentation pipeline to defaults?',
1936
- initial: false
1937
- });
1938
- if (!confirm) {
1939
- console.log(colors.dim('Pipeline reset cancelled'));
1940
- return;
1941
- }
1942
- const spinner = ora('Resetting augmentation pipeline...').start();
1943
- try {
1944
- // Interface with pipeline reset system
1945
- await new Promise(resolve => setTimeout(resolve, 2000));
1946
- spinner.succeed(colors.success(`${emojis.atom} Augmentation pipeline reset to factory defaults`));
1947
- console.log(colors.dim('All augmentations restored to default configuration'));
1948
- }
1949
- catch (error) {
1950
- spinner.fail('Failed to reset pipeline');
1951
- console.error(error);
1952
- }
1953
- }
1954
- async executePipelineStep(step, data) {
1955
- await this.ensureInitialized();
1956
- const spinner = ora(`Executing ${step} augmentation step...`).start();
1957
- try {
1958
- // Interface with pipeline execution system
1959
- await new Promise(resolve => setTimeout(resolve, 1500));
1960
- spinner.succeed(colors.success(`${emojis.magic} Pipeline step '${step}' executed successfully`));
1961
- console.log(colors.dim('Result: '), colors.highlight('[Processed data would be shown here]'));
1962
- }
1963
- catch (error) {
1964
- spinner.fail(`Failed to execute pipeline step '${step}'`);
1965
- console.error(error);
1966
- }
1967
- }
1968
- /**
1969
- * Backup & Restore System - Atomic Data Preservation
1970
- */
1971
- async backup(options = {}) {
1972
- await this.ensureInitialized();
1973
- const { BackupRestore } = await import('./backupRestore.js');
1974
- const backupSystem = new BackupRestore(this.brainy);
1975
- const backupPath = await backupSystem.createBackup({
1976
- compress: options.compress,
1977
- output: options.output,
1978
- includeMetadata: true,
1979
- includeStatistics: true,
1980
- verify: true
1981
- });
1982
- console.log(colors.success(`\nπŸŽ‰ Backup complete! Saved to: ${backupPath}`));
1983
- }
1984
- async restore(file) {
1985
- await this.ensureInitialized();
1986
- const { BackupRestore } = await import('./backupRestore.js');
1987
- const backupSystem = new BackupRestore(this.brainy);
1988
- await backupSystem.restoreBackup(file, {
1989
- verify: true,
1990
- overwrite: false // Will prompt user for confirmation
1991
- });
1992
- }
1993
- async listBackups(directory = './backups') {
1994
- const { BackupRestore } = await import('./backupRestore.js');
1995
- const backupSystem = new BackupRestore(this.brainy);
1996
- console.log(boxen(`${emojis.brain} ${colors.brain('ATOMIC VAULT INVENTORY')} ${emojis.atom}`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
1997
- const backups = await backupSystem.listBackups(directory);
1998
- if (backups.length === 0) {
1999
- console.log(colors.dim('No backups found in vault'));
2000
- return;
2001
- }
2002
- const table = new Table({
2003
- head: [colors.brain('Date'), colors.brain('Entities'), colors.brain('Relationships'), colors.brain('Size'), colors.brain('Type')],
2004
- colWidths: [20, 12, 15, 12, 15]
2005
- });
2006
- backups.forEach(backup => {
2007
- table.push([
2008
- colors.highlight(new Date(backup.timestamp).toLocaleDateString()),
2009
- colors.primary(backup.entityCount.toLocaleString()),
2010
- colors.primary(backup.relationshipCount.toLocaleString()),
2011
- colors.warning(backup.compressed ? 'Compressed' : 'Raw'),
2012
- colors.success(backup.storageType)
2013
- ]);
2014
- });
2015
- console.log(table.toString());
2016
- }
2017
- /**
2018
- * Show augmentation status and management
2019
- */
2020
- async augmentations(options = {}) {
2021
- console.log(boxen(`${this.emojis.brain} ${this.colors.brain('AUGMENTATION STATUS')} ${this.emojis.atom}`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
2022
- await this.ensureBrainy();
2023
- try {
2024
- // Import default augmentation registry
2025
- const { DefaultAugmentationRegistry } = await import('../shared/default-augmentations.js');
2026
- const registry = new DefaultAugmentationRegistry(this.brainy);
2027
- // Check Cortex health (default augmentation)
2028
- const cortexHealth = await registry.checkCortexHealth();
2029
- console.log(`\n${this.emojis.sparkles} ${this.colors.accent('Default Augmentations:')}`);
2030
- console.log(` ${this.emojis.brain} Cortex: ${cortexHealth.available ? this.colors.success('Active') : this.colors.error('Inactive')}`);
2031
- if (cortexHealth.version) {
2032
- console.log(` ${this.colors.dim('Version:')} ${cortexHealth.version}`);
2033
- }
2034
- console.log(` ${this.colors.dim('Status:')} ${cortexHealth.status}`);
2035
- console.log(` ${this.colors.dim('Category:')} SENSE (AI-powered data understanding)`);
2036
- console.log(` ${this.colors.dim('License:')} Open Source (included by default)`);
2037
- // Check for premium augmentations if license exists
2038
- if (this.licensingSystem) {
2039
- console.log(`\n${this.emojis.sparkles} ${this.colors.premium('Premium Augmentations:')}`);
2040
- // Check each premium feature from our licensing system
2041
- const premiumFeatures = [
2042
- 'notion-connector',
2043
- 'salesforce-connector',
2044
- 'slack-connector',
2045
- 'asana-connector',
2046
- 'neural-enhancement-pack'
2047
- ];
2048
- for (const feature of premiumFeatures) {
2049
- // This would check if the feature is licensed and installed
2050
- console.log(` ${this.emojis.gear} ${feature}: ${this.colors.dim('Not Installed')}`);
2051
- console.log(` ${this.colors.dim('Status:')} Available for trial/purchase`);
2052
- }
2053
- console.log(`\n${this.colors.dim('Use')} ${this.colors.highlight('cortex license catalog')} ${this.colors.dim('to see available premium augmentations')}`);
2054
- console.log(`${this.colors.dim('Use')} ${this.colors.highlight('cortex license trial <feature>')} ${this.colors.dim('to start a free trial')}`);
2055
- }
2056
- // Augmentation pipeline health
2057
- console.log(`\n${this.emojis.health} ${this.colors.accent('Pipeline Health:')}`);
2058
- console.log(` ${this.emojis.check} SENSE Pipeline: ${this.colors.success('1 active')} (Cortex)`);
2059
- console.log(` ${this.emojis.info} CONDUIT Pipeline: ${this.colors.dim('0 active')} (Premium connectors available)`);
2060
- console.log(` ${this.emojis.info} COGNITION Pipeline: ${this.colors.dim('0 active')}`);
2061
- console.log(` ${this.emojis.info} MEMORY Pipeline: ${this.colors.dim('0 active')}`);
2062
- if (options.verbose) {
2063
- console.log(`\n${this.emojis.info} ${this.colors.accent('Augmentation Categories:')}`);
2064
- console.log(` ${this.colors.highlight('SENSE:')} Input processing and data understanding`);
2065
- console.log(` ${this.colors.highlight('CONDUIT:')} External system integrations and sync`);
2066
- console.log(` ${this.colors.highlight('COGNITION:')} AI reasoning and analysis`);
2067
- console.log(` ${this.colors.highlight('MEMORY:')} Enhanced storage and retrieval`);
2068
- console.log(` ${this.colors.highlight('PERCEPTION:')} Pattern recognition and insights`);
2069
- console.log(` ${this.colors.highlight('DIALOG:')} Conversational interfaces`);
2070
- console.log(` ${this.colors.highlight('ACTIVATION:')} Automation and triggers`);
2071
- console.log(` ${this.colors.highlight('WEBSOCKET:')} Real-time communications`);
2072
- }
2073
- }
2074
- catch (error) {
2075
- console.error(`${this.emojis.cross} Failed to get augmentation status:`, error instanceof Error ? error.message : String(error));
2076
- }
2077
- }
2078
- /**
2079
- * Performance Monitoring & Health Check System - Atomic Age Intelligence Observatory
2080
- */
2081
- async monitor(options = {}) {
2082
- await this.ensureInitialized();
2083
- if (!this.performanceMonitor) {
2084
- console.log(colors.error('Performance monitor not initialized'));
2085
- return;
2086
- }
2087
- if (options.dashboard) {
2088
- // Interactive dashboard mode
2089
- console.log(boxen(`${emojis.stats} ${colors.brain('ATOMIC PERFORMANCE OBSERVATORY')} ${emojis.atom}\n\n` +
2090
- `${colors.accent('β—†')} ${colors.dim('Real-time vector + graph database monitoring')}\n` +
2091
- `${colors.accent('β—†')} ${colors.dim('Press Ctrl+C to exit dashboard')}`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
2092
- // Start monitoring in background
2093
- await this.performanceMonitor.startMonitoring(5000); // 5 second intervals
2094
- // Display dashboard in loop
2095
- const dashboardInterval = setInterval(async () => {
2096
- try {
2097
- await this.performanceMonitor.displayDashboard();
2098
- }
2099
- catch (error) {
2100
- console.error('Dashboard update failed:', error);
2101
- }
2102
- }, 5000);
2103
- // Handle cleanup on exit
2104
- process.on('SIGINT', () => {
2105
- clearInterval(dashboardInterval);
2106
- this.performanceMonitor.stopMonitoring();
2107
- console.log('\n' + colors.dim('Performance monitoring stopped'));
2108
- process.exit(0);
2109
- });
2110
- // Keep process alive
2111
- await new Promise(() => { });
2112
- }
2113
- else {
2114
- // Single snapshot mode
2115
- const metrics = await this.performanceMonitor.getCurrentMetrics();
2116
- console.log(boxen(`${emojis.stats} ${colors.brain('PERFORMANCE SNAPSHOT')} ${emojis.atom}`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
2117
- console.log(`\n${colors.accent('Vector Query Latency:')} ${colors.primary(metrics.queryLatency.vector.avg.toFixed(1) + 'ms')}`);
2118
- console.log(`${colors.accent('Graph Query Latency:')} ${colors.primary(metrics.queryLatency.graph.avg.toFixed(1) + 'ms')}`);
2119
- console.log(`${colors.accent('Combined Throughput:')} ${colors.success(metrics.throughput.totalOps.toFixed(0) + ' ops/sec')}`);
2120
- console.log(`${colors.accent('Cache Hit Rate:')} ${colors.success((metrics.storage.cacheHitRate * 100).toFixed(1) + '%')}`);
2121
- console.log(`${colors.accent('Overall Health:')} ${colors.primary(metrics.health.overall + '/100')}`);
2122
- }
2123
- }
2124
- async health(options = {}) {
2125
- await this.ensureInitialized();
2126
- if (!this.healthCheck) {
2127
- console.log(colors.error('Health check system not initialized'));
2128
- return;
2129
- }
2130
- if (options.autoFix) {
2131
- // Run health check and auto-repair
2132
- const health = await this.healthCheck.runHealthCheck();
2133
- await this.healthCheck.displayHealthReport(health);
2134
- console.log('\n' + colors.brain(`${emojis.repair} INITIATING AUTO-REPAIR SEQUENCE`));
2135
- const results = await this.healthCheck.executeAutoRepairs();
2136
- if (results.success.length > 0 || results.failed.length > 0) {
2137
- // Run health check again to show improvements
2138
- console.log('\n' + colors.info('Running post-repair health check...'));
2139
- await this.healthCheck.displayHealthReport();
2140
- }
2141
- }
2142
- else {
2143
- // Standard health check
2144
- await this.healthCheck.displayHealthReport();
2145
- // Show available repair actions
2146
- const repairs = await this.healthCheck.getRepairActions();
2147
- const safeRepairs = repairs.filter(r => r.automated && r.riskLevel === 'safe');
2148
- if (safeRepairs.length > 0) {
2149
- console.log('\n' + colors.info(`${emojis.info} Run 'cortex health --auto-fix' to apply ${safeRepairs.length} safe automated repairs`));
2150
- }
2151
- }
2152
- }
2153
- async performance(options = {}) {
2154
- await this.ensureInitialized();
2155
- if (!this.performanceMonitor) {
2156
- console.log(colors.error('Performance monitor not initialized'));
2157
- return;
2158
- }
2159
- if (options.analyze) {
2160
- // Detailed performance analysis
2161
- console.log(boxen(`${emojis.lab} ${colors.brain('PERFORMANCE ANALYSIS ENGINE')} ${emojis.atom}\n\n` +
2162
- `${colors.accent('β—†')} ${colors.dim('Deep analysis of vector + graph performance')}\n` +
2163
- `${colors.accent('β—†')} ${colors.dim('Collecting metrics over 30 seconds...')}`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
2164
- const spinner = ora('Analyzing neural pathway performance...').start();
2165
- // Start monitoring to collect data
2166
- await this.performanceMonitor.startMonitoring(2000); // 2 second intervals
2167
- // Wait for data collection
2168
- await new Promise(resolve => setTimeout(resolve, 30000));
2169
- // Stop monitoring and get dashboard data
2170
- this.performanceMonitor.stopMonitoring();
2171
- const dashboard = await this.performanceMonitor.getDashboard();
2172
- spinner.succeed('Performance analysis complete');
2173
- // Display detailed analysis
2174
- console.log('\n' + colors.brain(`${emojis.lightning} DETAILED ANALYSIS RESULTS`));
2175
- const current = dashboard.current;
2176
- const trends = dashboard.trends;
2177
- if (trends.length > 1) {
2178
- const first = trends[0];
2179
- const last = trends[trends.length - 1];
2180
- const vectorTrend = last.queryLatency.vector.avg - first.queryLatency.vector.avg;
2181
- const graphTrend = last.queryLatency.graph.avg - first.queryLatency.graph.avg;
2182
- const throughputTrend = last.throughput.totalOps - first.throughput.totalOps;
2183
- console.log(`\n${colors.accent('Vector Performance Trend:')} ${vectorTrend > 0 ? colors.warning('↑') : colors.success('↓')} ${Math.abs(vectorTrend).toFixed(1)}ms`);
2184
- console.log(`${colors.accent('Graph Performance Trend:')} ${graphTrend > 0 ? colors.warning('↑') : colors.success('↓')} ${Math.abs(graphTrend).toFixed(1)}ms`);
2185
- console.log(`${colors.accent('Throughput Trend:')} ${throughputTrend > 0 ? colors.success('↑') : colors.warning('↓')} ${Math.abs(throughputTrend).toFixed(0)} ops/sec`);
2186
- }
2187
- // Show recommendations
2188
- console.log('\n' + colors.brain(`${emojis.sparkle} OPTIMIZATION RECOMMENDATIONS`));
2189
- if (current.queryLatency.vector.p95 > 100) {
2190
- console.log(` ${colors.warning('β†’')} Vector query P95 latency is high - consider rebuilding HNSW index`);
2191
- }
2192
- if (current.storage.cacheHitRate < 0.8) {
2193
- console.log(` ${colors.warning('β†’')} Cache hit rate is below 80% - consider increasing cache size`);
2194
- }
2195
- if (current.memory.heapUsed > 1000) {
2196
- console.log(` ${colors.warning('β†’')} Memory usage is high - consider running garbage collection`);
2197
- }
2198
- if (current.health.overall < 85) {
2199
- console.log(` ${colors.error('β†’')} Overall health below 85% - run 'cortex health --auto-fix'`);
2200
- }
2201
- }
2202
- else {
2203
- // Quick performance overview
2204
- const metrics = await this.performanceMonitor.getCurrentMetrics();
2205
- console.log(boxen(`${emojis.rocket} ${colors.brain('QUICK PERFORMANCE OVERVIEW')} ${emojis.atom}`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
2206
- console.log(`\n${colors.brain('Vector + Graph Database Performance:')}\n`);
2207
- console.log(` ${colors.accent('Vector Operations:')} ${colors.primary(metrics.queryLatency.vector.avg.toFixed(1) + 'ms avg')} | ${colors.highlight(metrics.throughput.vectorOps.toFixed(0) + ' ops/sec')}`);
2208
- console.log(` ${colors.accent('Graph Operations:')} ${colors.primary(metrics.queryLatency.graph.avg.toFixed(1) + 'ms avg')} | ${colors.highlight(metrics.throughput.graphOps.toFixed(0) + ' ops/sec')}`);
2209
- console.log(` ${colors.accent('Storage Performance:')} ${colors.success((metrics.storage.cacheHitRate * 100).toFixed(1) + '% cache hit')} | ${colors.info(metrics.storage.readLatency.toFixed(1) + 'ms read')}`);
2210
- console.log(` ${colors.accent('Memory Usage:')} ${colors.primary(metrics.memory.heapUsed.toFixed(0) + 'MB')} | ${colors.success((metrics.memory.efficiency * 100).toFixed(1) + '% efficient')}`);
2211
- console.log(`\n${colors.dim('For detailed analysis: cortex performance --analyze')}`);
2212
- }
2213
- }
2214
- /**
2215
- * Premium Features - Redirect to Brain Cloud
2216
- */
2217
- async licenseCatalog() {
2218
- console.log(boxen(`${emojis.brain}☁️ ${colors.brain('BRAIN CLOUD PREMIUM FEATURES')}\n\n` +
2219
- `Premium connectors and features have moved to Brain Cloud!\n\n` +
2220
- `${colors.accent('β—†')} ${colors.dim('Setup Brain Cloud:')} ${colors.highlight('brainy cloud')}\n` +
2221
- `${colors.accent('β—†')} ${colors.dim('Learn more:')} ${colors.highlight('https://soulcraft.com/brain-cloud')}\n\n` +
2222
- `${colors.retro('Available Tiers:')}\n` +
2223
- `${colors.success('πŸ«™')} Brain Jar (Free) - Local coordination\n` +
2224
- `${colors.success('☁️')} Brain Cloud ($19/mo) - Sync everywhere\n` +
2225
- `${colors.success('🏦')} Brain Bank ($99/mo) - Enterprise features`, { padding: 1, borderStyle: 'round', borderColor: '#D67441' }));
2226
- }
2227
- async licenseStatus(licenseId) {
2228
- console.log(colors.info('License management has moved to Brain Cloud'));
2229
- console.log(colors.dim('Run: brainy cloud'));
2230
- }
2231
- async licenseTrial(featureId, customerName, customerEmail) {
2232
- console.log(boxen(`${emojis.sparkle} ${colors.brain('START YOUR BRAIN CLOUD TRIAL')}\n\n` +
2233
- `${colors.accent('β—†')} ${colors.dim('14-day free trial')}\n` +
2234
- `${colors.accent('β—†')} ${colors.dim('No credit card required')}\n` +
2235
- `${colors.accent('β—†')} ${colors.dim('Cancel anytime')}\n\n` +
2236
- `${colors.highlight('Run: brainy cloud')}\n\n` +
2237
- `Or visit: ${colors.accent('https://soulcraft.com/brain-cloud')}`, { padding: 1, borderStyle: 'round', borderColor: '#FFD700' }));
2238
- }
2239
- async licenseValidate(featureId) {
2240
- console.log(colors.info('Premium features available in Brain Cloud'));
2241
- console.log(colors.dim('Setup: brainy cloud'));
2242
- return false;
2243
- }
2244
- /**
2245
- * Check if a premium feature is available
2246
- */
2247
- async requirePremiumFeature(featureId, silent = false) {
2248
- if (!silent) {
2249
- console.log(boxen(`${emojis.lock} ${colors.brain('BRAIN CLOUD FEATURE')} ${emojis.atom}\n\n` +
2250
- `This feature is available in Brain Cloud!\n\n` +
2251
- `${colors.highlight('Setup: brainy cloud')}\n` +
2252
- `${colors.dim('Learn more: https://soulcraft.com/brain-cloud')}`, { padding: 1, borderStyle: 'round', borderColor: '#D67441' }));
2253
- }
2254
- return false;
2255
- }
2256
- /**
2257
- * Brain Jar AI Coordination Methods
2258
- */
2259
- async brainJarInstall(mode) {
2260
- const spinner = ora('Installing Brain Jar coordination...').start();
2261
- try {
2262
- if (mode === 'premium') {
2263
- spinner.text = 'Opening Brain Jar Premium signup...';
2264
- // This would open browser to brain-jar.com
2265
- console.log('\n' + boxen(`${emojis.brain}${emojis.rocket} ${colors.brain('BRAIN JAR PREMIUM')}\n\n` +
2266
- `${colors.accent('β—†')} ${colors.dim('Opening signup at:')} ${colors.highlight('https://brain-jar.com')}\n` +
2267
- `${colors.accent('β—†')} ${colors.dim('After signup, return to configure your API key')}\n\n` +
2268
- `${colors.retro('Features:')}\n` +
2269
- `${colors.success('βœ…')} Global AI coordination\n` +
2270
- `${colors.success('βœ…')} Multi-device sync\n` +
2271
- `${colors.success('βœ…')} Team workspaces\n` +
2272
- `${colors.success('βœ…')} Premium dashboard`, { padding: 1, borderStyle: 'double', borderColor: '#D67441' }));
2273
- // Open browser (would be implemented)
2274
- console.log(colors.info('\nπŸ’‘ Run: export BRAIN_JAR_KEY="your-api-key" after signup'));
2275
- }
2276
- else {
2277
- spinner.text = 'Setting up local Brain Jar server...';
2278
- console.log('\n' + boxen(`${emojis.brain}${emojis.tube} ${colors.brain('BRAIN JAR FREE')}\n\n` +
2279
- `${colors.accent('β—†')} ${colors.dim('Local AI coordination installed')}\n` +
2280
- `${colors.accent('β—†')} ${colors.dim('Server:')} ${colors.highlight('localhost:8765')}\n` +
2281
- `${colors.accent('β—†')} ${colors.dim('Dashboard:')} ${colors.highlight('localhost:3000')}\n\n` +
2282
- `${colors.retro('Features:')}\n` +
2283
- `${colors.success('βœ…')} Local AI coordination\n` +
2284
- `${colors.success('βœ…')} Real-time dashboard\n` +
2285
- `${colors.success('βœ…')} Vector storage`, { padding: 1, borderStyle: 'round', borderColor: '#2D4A3A' }));
2286
- }
2287
- spinner.succeed(`Brain Jar ${mode} installation complete!`);
2288
- }
2289
- catch (error) {
2290
- spinner.fail('Brain Jar installation failed');
2291
- console.error(colors.error('Error:'), error.message);
2292
- }
2293
- }
2294
- async brainJarStart(options) {
2295
- const spinner = ora('Starting Brain Jar coordination...').start();
2296
- try {
2297
- const isCloudMode = process.env.BRAIN_JAR_KEY !== undefined;
2298
- const serverUrl = options.server || (isCloudMode ? 'wss://api.brain-jar.com/ws' : 'ws://localhost:8765');
2299
- spinner.text = `Connecting to ${isCloudMode ? 'cloud' : 'local'} coordination...`;
2300
- console.log('\n' + boxen(`${emojis.brain}${emojis.network} ${colors.brain('BRAIN JAR COORDINATION ACTIVE')}\n\n` +
2301
- `${colors.accent('β—†')} ${colors.dim('Mode:')} ${colors.highlight(isCloudMode ? 'Premium Cloud' : 'Local Free')}\n` +
2302
- `${colors.accent('β—†')} ${colors.dim('Server:')} ${colors.highlight(serverUrl)}\n` +
2303
- `${colors.accent('β—†')} ${colors.dim('Agent:')} ${colors.highlight(options.name || 'Claude-Agent')}\n` +
2304
- `${colors.accent('β—†')} ${colors.dim('Role:')} ${colors.highlight(options.role || 'Assistant')}\n\n` +
2305
- `${colors.success('βœ…')} All Claude instances will now coordinate automatically!`, { padding: 1, borderStyle: 'round', borderColor: isCloudMode ? '#D67441' : '#2D4A3A' }));
2306
- spinner.succeed('Brain Jar coordination started!');
2307
- console.log(colors.dim('\nπŸ’‘ Keep this terminal open for coordination to remain active'));
2308
- console.log(colors.primary(`πŸ”— Dashboard: brainy brain-jar dashboard`));
2309
- }
2310
- catch (error) {
2311
- spinner.fail('Failed to start Brain Jar');
2312
- console.error(colors.error('Error:'), error.message);
2313
- }
2314
- }
2315
- async brainJarDashboard(shouldOpen = true) {
2316
- const isCloudMode = process.env.BRAIN_JAR_KEY !== undefined;
2317
- const dashboardUrl = isCloudMode ? 'https://dashboard.brain-jar.com' : 'http://localhost:3000/dashboard';
2318
- console.log(boxen(`${emojis.data}${emojis.brain} ${colors.brain('BRAIN JAR DASHBOARD')}\n\n` +
2319
- `${colors.accent('β—†')} ${colors.dim('URL:')} ${colors.highlight(dashboardUrl)}\n` +
2320
- `${colors.accent('β—†')} ${colors.dim('Mode:')} ${colors.highlight(isCloudMode ? 'Premium Cloud' : 'Local Free')}\n\n` +
2321
- `${colors.retro('Features:')}\n` +
2322
- `${colors.success('βœ…')} Live agent coordination\n` +
2323
- `${colors.success('βœ…')} Real-time conversation view\n` +
2324
- `${colors.success('βœ…')} Search coordination history\n` +
2325
- `${colors.success('βœ…')} Performance metrics`, { padding: 1, borderStyle: 'round', borderColor: isCloudMode ? '#D67441' : '#2D4A3A' }));
2326
- if (shouldOpen) {
2327
- console.log(colors.success(`\nπŸš€ Opening dashboard: ${dashboardUrl}`));
2328
- // Would open browser here
2329
- }
2330
- }
2331
- async brainJarStatus() {
2332
- const isCloudMode = process.env.BRAIN_JAR_KEY !== undefined;
2333
- console.log(boxen(`${emojis.brain}${emojis.stats} ${colors.brain('BRAIN JAR STATUS')}\n\n` +
2334
- `${colors.accent('β—†')} ${colors.dim('Mode:')} ${colors.highlight(isCloudMode ? 'Premium Cloud' : 'Local Free')}\n` +
2335
- `${colors.accent('β—†')} ${colors.dim('Status:')} ${colors.success('Active')}\n` +
2336
- `${colors.accent('β—†')} ${colors.dim('Connected Agents:')} ${colors.highlight('2')}\n` +
2337
- `${colors.accent('β—†')} ${colors.dim('Total Messages:')} ${colors.highlight('47')}\n` +
2338
- `${colors.accent('β—†')} ${colors.dim('Uptime:')} ${colors.highlight('15m 32s')}\n\n` +
2339
- `${colors.success('βœ…')} All systems operational!`, { padding: 1, borderStyle: 'round', borderColor: '#2D4A3A' }));
2340
- }
2341
- async brainJarStop() {
2342
- const spinner = ora('Stopping Brain Jar coordination...').start();
2343
- try {
2344
- // Would stop coordination server/connections here
2345
- spinner.succeed('Brain Jar coordination stopped');
2346
- console.log(colors.warning('⚠️ AI agents will no longer coordinate'));
2347
- console.log(colors.dim('πŸ’‘ Run: brainy brain-jar start to resume coordination'));
2348
- }
2349
- catch (error) {
2350
- spinner.fail('Failed to stop Brain Jar');
2351
- console.error(colors.error('Error:'), error.message);
2352
- }
2353
- }
2354
- async brainJarAgents() {
2355
- console.log(boxen(`${emojis.robot}${emojis.network} ${colors.brain('CONNECTED AGENTS')}\n\n` +
2356
- `${colors.success('πŸ€–')} ${colors.highlight('Jarvis')} - ${colors.dim('Backend Systems')}\n` +
2357
- ` ${colors.dim('Status:')} ${colors.success('Connected')}\n` +
2358
- ` ${colors.dim('Last Active:')} ${colors.dim('2 minutes ago')}\n\n` +
2359
- `${colors.success('🎨')} ${colors.highlight('Picasso')} - ${colors.dim('Frontend Design')}\n` +
2360
- ` ${colors.dim('Status:')} ${colors.success('Connected')}\n` +
2361
- ` ${colors.dim('Last Active:')} ${colors.dim('30 seconds ago')}\n\n` +
2362
- `${colors.accent('Total Active Agents:')} ${colors.highlight('2')}`, { padding: 1, borderStyle: 'round', borderColor: '#2D4A3A' }));
2363
- }
2364
- async brainJarMessage(text) {
2365
- const spinner = ora('Broadcasting message to coordination channel...').start();
2366
- try {
2367
- // Would send message through coordination system here
2368
- spinner.succeed('Message sent to all connected agents');
2369
- console.log(boxen(`${emojis.chat}${emojis.network} ${colors.brain('MESSAGE BROADCAST')}\n\n` +
2370
- `${colors.dim('Message:')} ${colors.highlight(text)}\n` +
2371
- `${colors.dim('Recipients:')} ${colors.success('All connected agents')}\n` +
2372
- `${colors.dim('Timestamp:')} ${colors.dim(new Date().toLocaleTimeString())}`, { padding: 1, borderStyle: 'round', borderColor: '#D67441' }));
2373
- }
2374
- catch (error) {
2375
- spinner.fail('Failed to send message');
2376
- console.error(colors.error('Error:'), error.message);
2377
- }
2378
- }
2379
- async brainJarSearch(query, limit) {
2380
- const spinner = ora('Searching coordination history...').start();
2381
- try {
2382
- // Would search through coordination messages here
2383
- spinner.succeed(`Found coordination messages for: "${query}"`);
2384
- console.log(boxen(`${emojis.search}${emojis.brain} ${colors.brain('COORDINATION SEARCH RESULTS')}\n\n` +
2385
- `${colors.dim('Query:')} ${colors.highlight(query)}\n` +
2386
- `${colors.dim('Results:')} ${colors.success('5 matches')}\n` +
2387
- `${colors.dim('Limit:')} ${colors.dim(limit.toString())}\n\n` +
2388
- `${colors.success('πŸ“¨')} ${colors.dim('Jarvis:')} "Setting up backend coordination..."\n` +
2389
- `${colors.success('πŸ“¨')} ${colors.dim('Picasso:')} "Frontend components ready for integration..."\n` +
2390
- `${colors.success('πŸ“¨')} ${colors.dim('Jarvis:')} "Database connections established..."\n\n` +
2391
- `${colors.dim('Use')} ${colors.primary('brainy brain-jar dashboard')} ${colors.dim('for visual search')}`, { padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }));
2392
- }
2393
- catch (error) {
2394
- spinner.fail('Search failed');
2395
- console.error(colors.error('Error:'), error.message);
2396
- }
2397
- }
2398
- /**
2399
- * Brain Cloud Super Command - One command to rule them all
2400
- */
2401
- async setupBrainCloud(options) {
2402
- const { prompt } = await import('prompts');
2403
- const colors = this.colors;
2404
- const emojis = this.emojis;
2405
- console.log(boxen(`${emojis.brain}☁️ ${colors.brain('BRAIN CLOUD SETUP')}\n\n` +
2406
- `${colors.accent('Transform your AI into a coordinated system')}\n` +
2407
- `${colors.dim('One command. Global sync. Team coordination.')}\n\n` +
2408
- `${colors.success('βœ…')} Install Brain Jar in Claude Desktop\n` +
2409
- `${colors.success('βœ…')} Configure cloud sync across devices\n` +
2410
- `${colors.success('βœ…')} Setup team workspaces (optional)`, { padding: 1, borderStyle: 'double', borderColor: '#D67441' }));
2411
- // Interactive mode if not specified
2412
- if (options.mode === 'interactive') {
2413
- const response = await prompt([
2414
- {
2415
- type: 'select',
2416
- name: 'tier',
2417
- message: 'Choose your Brain Cloud tier:',
2418
- choices: [
2419
- { title: 'πŸ«™ Brain Jar (Free) - Local coordination only', value: 'free' },
2420
- { title: '☁️ Brain Cloud ($19/mo) - Sync across all devices', value: 'cloud' },
2421
- { title: '🏦 Brain Bank ($99/mo) - Enterprise features', value: 'bank' }
2422
- ],
2423
- initial: 0
2424
- }
2425
- ]);
2426
- if (!response.tier) {
2427
- console.log(colors.warning('Setup cancelled'));
2428
- return;
2429
- }
2430
- options.mode = response.tier;
2431
- }
2432
- const spinner = ora('Setting up Brain Cloud...').start();
2433
- try {
2434
- // Step 1: Install Brain Jar
2435
- if (!options.skipInstall) {
2436
- spinner.text = 'Installing Brain Jar in Claude Desktop...';
2437
- await this.brainJarInstall(options.mode);
2438
- }
2439
- // Step 2: Configure based on tier
2440
- if (options.mode === 'cloud' || options.mode === 'bank') {
2441
- spinner.text = 'Configuring cloud sync...';
2442
- const accountResponse = await prompt([
2443
- {
2444
- type: 'confirm',
2445
- name: 'hasAccount',
2446
- message: 'Do you have a Brain Cloud account?',
2447
- initial: false
2448
- }
2449
- ]);
2450
- if (!accountResponse.hasAccount) {
2451
- console.log('\n' + boxen(`${emojis.sparkles} ${colors.brain('CREATE YOUR ACCOUNT')}\n\n` +
2452
- `${colors.accent('β—†')} Visit: ${colors.highlight('https://soulcraft.com/brain-cloud')}\n` +
2453
- `${colors.accent('β—†')} Click "Start Free Trial"\n` +
2454
- `${colors.accent('β—†')} Get your API key\n` +
2455
- `${colors.accent('β—†')} Return here to continue setup`, { padding: 1, borderStyle: 'round', borderColor: '#FFD700' }));
2456
- const keyResponse = await prompt([
2457
- {
2458
- type: 'text',
2459
- name: 'apiKey',
2460
- message: 'Enter your Brain Cloud API key:'
2461
- }
2462
- ]);
2463
- if (keyResponse.apiKey) {
2464
- await this.configSet('brain-cloud.apiKey', keyResponse.apiKey, { encrypt: true });
2465
- }
2466
- }
2467
- // Enable cloud sync in Brain Jar
2468
- await this.configSet('brain-jar.cloudSync', 'true', {});
2469
- await this.configSet('brain-jar.tier', options.mode, {});
2470
- }
2471
- // Step 3: Start Brain Jar
2472
- spinner.text = 'Starting Brain Jar coordination...';
2473
- await this.brainJarStart({});
2474
- spinner.succeed('Brain Cloud setup complete!');
2475
- // Show success message
2476
- const tierMessages = {
2477
- free: 'Local AI coordination active',
2478
- cloud: 'Cloud sync enabled across all devices',
2479
- bank: 'Enterprise features activated'
2480
- };
2481
- console.log('\n' + boxen(`${emojis.check}${emojis.brain} ${colors.success('BRAIN CLOUD ACTIVE!')}\n\n` +
2482
- `${colors.accent('β—†')} ${colors.dim('Status:')} ${colors.success(tierMessages[options.mode])}\n` +
2483
- `${colors.accent('β—†')} ${colors.dim('Claude Desktop:')} ${colors.success('Brain Jar installed')}\n` +
2484
- `${colors.accent('β—†')} ${colors.dim('MCP Server:')} ${colors.success('Running')}\n\n` +
2485
- `${colors.retro('Next Steps:')}\n` +
2486
- `${colors.cyan('1.')} Open Claude Desktop\n` +
2487
- `${colors.cyan('2.')} Start a new conversation\n` +
2488
- `${colors.cyan('3.')} Your AI now has persistent memory!\n\n` +
2489
- `${colors.dim('Dashboard:')} ${colors.highlight('brainy brain-jar dashboard')}\n` +
2490
- `${colors.dim('Status:')} ${colors.highlight('brainy status')}`, { padding: 1, borderStyle: 'double', borderColor: '#5FD45C' }));
2491
- }
2492
- catch (error) {
2493
- spinner.fail('Setup failed');
2494
- console.error(colors.error('Error:'), error.message);
2495
- console.log('\n' + colors.dim('Need help? Visit https://soulcraft.com/brain-cloud/support'));
2496
- }
2497
- }
2498
- /**
2499
- * Helper method to determine data type from file path
2500
- */
2501
- getDataTypeFromPath(filePath) {
2502
- const path = require('path');
2503
- const ext = path.extname(filePath).toLowerCase();
2504
- switch (ext) {
2505
- case '.json': return 'json';
2506
- case '.csv': return 'csv';
2507
- case '.yaml':
2508
- case '.yml': return 'yaml';
2509
- case '.txt': return 'text';
2510
- default: return 'text';
2511
- }
2512
- }
2513
- }
2514
- /**
2515
- * Configuration categories for enhanced secret management
2516
- */
2517
- Cortex.CONFIG_CATEGORIES = {
2518
- SECRET: 'secret', // Encrypted, never logged
2519
- SENSITIVE: 'sensitive', // Encrypted, logged as [MASKED]
2520
- CONFIG: 'config', // Plain text configuration
2521
- PUBLIC: 'public' // Can be exposed publicly
2522
- };
2523
- //# sourceMappingURL=cortex-legacy.js.map