refactor: remove src/cortex/ directory and fix README claims
- Move neuralImport.ts and neuralImportAugmentation.ts to src/neural/ - Delete 3 dead files (healthCheck, backupRestore, performanceMonitor) - Remove cortex entries from package.json browser field - Fix unsubstantiated performance claims in README (add PROJECTED labels) - Delete stale dist/cortex/ artifacts
This commit is contained in:
parent
0292cf2ddf
commit
36db644eca
9 changed files with 16 additions and 1702 deletions
24
README.md
24
README.md
|
|
@ -204,10 +204,10 @@ const brain = new Brainy({
|
||||||
```javascript
|
```javascript
|
||||||
const brain = new Brainy({
|
const brain = new Brainy({
|
||||||
storage: { type: 's3', s3Storage: { bucketName: 'my-kb', region: 'us-east-1' } },
|
storage: { type: 's3', s3Storage: { bucketName: 'my-kb', region: 'us-east-1' } },
|
||||||
hnsw: { typeAware: true } // 87% memory reduction
|
hnsw: { typeAware: true }
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
**Scale:** Millions of entities • **Performance:** <10ms queries, 12GB @ 10M entities
|
**Scale:** Millions of entities • **Performance:** <10ms queries (measured at 1M scale)
|
||||||
|
|
||||||
### 🌍 Enterprise → Billion+ Scale
|
### 🌍 Enterprise → Billion+ Scale
|
||||||
```javascript
|
```javascript
|
||||||
|
|
@ -216,7 +216,7 @@ const brain = new Brainy({
|
||||||
hnsw: { typeAware: true, M: 32, efConstruction: 400 }
|
hnsw: { typeAware: true, M: 32, efConstruction: 400 }
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
**Scale:** Billions (tested @ 1B+) • **Performance:** 18ms queries, 50GB memory
|
**Scale:** PROJECTED billion+ (extrapolated from 10M tests, not tested at 1B)
|
||||||
**Cost:** $138k/year → $6k/year with intelligent tiering (96% savings)
|
**Cost:** $138k/year → $6k/year with intelligent tiering (96% savings)
|
||||||
|
|
||||||
**→ [Capacity Planning Guide](docs/operations/capacity-planning.md)** | **[Cost Optimization](docs/operations/)**
|
**→ [Capacity Planning Guide](docs/operations/capacity-planning.md)** | **[Cost Optimization](docs/operations/)**
|
||||||
|
|
@ -586,15 +586,15 @@ npm install @soulcraft/cortex
|
||||||
|
|
||||||
## Benchmarks
|
## Benchmarks
|
||||||
|
|
||||||
| Operation | Performance | Memory |
|
| Operation | Performance | Memory | Notes |
|
||||||
|-----------|-------------|--------|
|
|-----------|-------------|--------|-------|
|
||||||
| Initialize | 450ms | 24MB |
|
| Initialize | 450ms | 24MB | Measured |
|
||||||
| Add entity | 12ms | +0.1MB |
|
| Add entity | 12ms | +0.1MB | Measured |
|
||||||
| Vector search (1K) | 3ms | - |
|
| Vector search (1K) | 3ms | - | Measured |
|
||||||
| Metadata filter (10K) | 0.8ms | - |
|
| Metadata filter (10K) | 0.8ms | - | Measured |
|
||||||
| Bulk import (1K) | 2.3s | +8MB |
|
| Bulk import (1K) | 2.3s | +8MB | Measured |
|
||||||
| **10M entities** | **5.8ms** | **12GB** |
|
| **10M entities** | **5.8ms** | **12GB** | Measured |
|
||||||
| **1B entities** | **18ms** | **50GB** |
|
| **1B entities** | **~18ms** | **~50GB** | PROJECTED (extrapolated from 10M) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,12 +60,7 @@
|
||||||
"browser": {
|
"browser": {
|
||||||
"./dist/distributed": false,
|
"./dist/distributed": false,
|
||||||
"./dist/cli": false,
|
"./dist/cli": false,
|
||||||
"./dist/scripts": false,
|
"./dist/scripts": false
|
||||||
"./dist/cortex": false,
|
|
||||||
"./dist/cortex/neuralImport.js": false,
|
|
||||||
"./dist/cortex/performanceMonitor.js": false,
|
|
||||||
"./dist/cortex/healthCheck.js": false,
|
|
||||||
"./dist/cortex/backupRestore.js": false
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "22.x",
|
"node": "22.x",
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import { NounType, VerbType } from '../types/graphTypes.js'
|
||||||
import { Vector } from '../coreTypes.js'
|
import { Vector } from '../coreTypes.js'
|
||||||
import type { Brainy } from '../brainy.js'
|
import type { Brainy } from '../brainy.js'
|
||||||
import type { Entity, Relation } from '../types/brainy.types.js'
|
import type { Entity, Relation } from '../types/brainy.types.js'
|
||||||
import { NeuralImportAugmentation } from '../cortex/neuralImportAugmentation.js'
|
import { NeuralImportAugmentation } from '../neural/neuralImportAugmentation.js'
|
||||||
import { mimeDetector } from '../vfs/MimeTypeDetector.js'
|
import { mimeDetector } from '../vfs/MimeTypeDetector.js'
|
||||||
|
|
||||||
export interface ImportSource {
|
export interface ImportSource {
|
||||||
|
|
|
||||||
|
|
@ -1,506 +0,0 @@
|
||||||
/**
|
|
||||||
* Backup & Restore System - Atomic Age Data Preservation Protocol
|
|
||||||
*
|
|
||||||
* 🧠 Complete backup/restore with compression and verification
|
|
||||||
* ⚛️ 1950s retro sci-fi aesthetic maintained throughout
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Brainy } from '../brainy.js'
|
|
||||||
import * as fs from '../universal/fs.js'
|
|
||||||
import * as path from '../universal/path.js'
|
|
||||||
// @ts-ignore
|
|
||||||
import chalk from 'chalk'
|
|
||||||
// @ts-ignore
|
|
||||||
import ora from 'ora'
|
|
||||||
// @ts-ignore
|
|
||||||
import boxen from 'boxen'
|
|
||||||
// @ts-ignore
|
|
||||||
import prompts from 'prompts'
|
|
||||||
|
|
||||||
export interface BackupOptions {
|
|
||||||
compress?: boolean
|
|
||||||
output?: string
|
|
||||||
includeMetadata?: boolean
|
|
||||||
includeStatistics?: boolean
|
|
||||||
verify?: boolean
|
|
||||||
password?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RestoreOptions {
|
|
||||||
verify?: boolean
|
|
||||||
overwrite?: boolean
|
|
||||||
password?: string
|
|
||||||
dryRun?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BackupManifest {
|
|
||||||
version: string
|
|
||||||
timestamp: string
|
|
||||||
brainyVersion: string
|
|
||||||
entityCount: number
|
|
||||||
relationshipCount: number
|
|
||||||
storageType: string
|
|
||||||
compressed: boolean
|
|
||||||
encrypted: boolean
|
|
||||||
checksum: string
|
|
||||||
metadata: {
|
|
||||||
created: string
|
|
||||||
description?: string
|
|
||||||
tags?: string[]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Backup & Restore Engine - The Brain's Memory Preservation System
|
|
||||||
*/
|
|
||||||
export class BackupRestore {
|
|
||||||
private brainy: Brainy
|
|
||||||
private colors = {
|
|
||||||
primary: chalk.hex('#3A5F4A'),
|
|
||||||
success: chalk.hex('#2D4A3A'),
|
|
||||||
warning: chalk.hex('#D67441'),
|
|
||||||
error: chalk.hex('#B85C35'),
|
|
||||||
info: chalk.hex('#4A6B5A'),
|
|
||||||
dim: chalk.hex('#8A9B8A'),
|
|
||||||
highlight: chalk.hex('#E88B5A'),
|
|
||||||
accent: chalk.hex('#F5E6D3'),
|
|
||||||
brain: chalk.hex('#E88B5A')
|
|
||||||
}
|
|
||||||
|
|
||||||
private emojis = {
|
|
||||||
brain: '🧠',
|
|
||||||
atom: '⚛️',
|
|
||||||
disk: '💾',
|
|
||||||
archive: '📦',
|
|
||||||
shield: '🛡️',
|
|
||||||
check: '✅',
|
|
||||||
warning: '⚠️',
|
|
||||||
sparkle: '✨',
|
|
||||||
rocket: '🚀',
|
|
||||||
gear: '⚙️',
|
|
||||||
time: '⏰'
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(brainy: Brainy) {
|
|
||||||
this.brainy = brainy
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a complete backup of Brainy data
|
|
||||||
*/
|
|
||||||
async createBackup(options: BackupOptions = {}): Promise<string> {
|
|
||||||
const outputPath = options.output || this.generateBackupPath()
|
|
||||||
|
|
||||||
console.log(boxen(
|
|
||||||
`${this.emojis.archive} ${this.colors.brain('ATOMIC DATA PRESERVATION PROTOCOL')} ${this.emojis.atom}\n\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Initiating brain backup sequence')}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Output:')} ${this.colors.highlight(outputPath)}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Compression:')} ${this.colors.highlight(options.compress ? 'Enabled' : 'Disabled')}`,
|
|
||||||
{ padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }
|
|
||||||
))
|
|
||||||
|
|
||||||
const spinner = ora(`${this.emojis.brain} Scanning neural pathways...`).start()
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Phase 1: Collect data
|
|
||||||
spinner.text = `${this.emojis.gear} Extracting neural data...`
|
|
||||||
const backupData = await this.collectBackupData(options)
|
|
||||||
|
|
||||||
// Phase 2: Create manifest
|
|
||||||
spinner.text = `${this.emojis.atom} Generating quantum manifest...`
|
|
||||||
const manifest = await this.createManifest(backupData, options)
|
|
||||||
|
|
||||||
// Phase 3: Package data
|
|
||||||
spinner.text = `${this.emojis.archive} Packaging atomic data...`
|
|
||||||
const packagedData = {
|
|
||||||
manifest,
|
|
||||||
data: backupData
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 4: Compress if requested
|
|
||||||
let finalData = JSON.stringify(packagedData, null, 2)
|
|
||||||
if (options.compress) {
|
|
||||||
spinner.text = `${this.emojis.gear} Applying quantum compression...`
|
|
||||||
finalData = await this.compressData(finalData)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 5: Encrypt if password provided
|
|
||||||
if (options.password) {
|
|
||||||
spinner.text = `${this.emojis.shield} Applying atomic encryption...`
|
|
||||||
finalData = await this.encryptData(finalData, options.password)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 6: Write to file
|
|
||||||
spinner.text = `${this.emojis.disk} Storing in atomic vault...`
|
|
||||||
await fs.writeFile(outputPath, finalData)
|
|
||||||
|
|
||||||
// Phase 7: Verify if requested
|
|
||||||
if (options.verify) {
|
|
||||||
spinner.text = `${this.emojis.check} Verifying atomic integrity...`
|
|
||||||
await this.verifyBackup(outputPath, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
spinner.succeed(this.colors.success(
|
|
||||||
`${this.emojis.sparkle} Backup complete! Neural pathways preserved in atomic vault.`
|
|
||||||
))
|
|
||||||
|
|
||||||
console.log(boxen(
|
|
||||||
`${this.emojis.brain} ${this.colors.brain('BACKUP SUMMARY')}\n\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Entities:')} ${this.colors.primary(manifest.entityCount.toLocaleString())}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Relationships:')} ${this.colors.primary(manifest.relationshipCount.toLocaleString())}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Size:')} ${this.colors.highlight(this.formatFileSize(finalData.length))}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Location:')} ${this.colors.highlight(outputPath)}`,
|
|
||||||
{ padding: 1, borderStyle: 'round', borderColor: '#2D4A3A' }
|
|
||||||
))
|
|
||||||
|
|
||||||
return outputPath
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
spinner.fail('Backup failed - atomic vault compromised!')
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restore Brainy data from backup
|
|
||||||
*/
|
|
||||||
async restoreBackup(backupPath: string, options: RestoreOptions = {}): Promise<void> {
|
|
||||||
console.log(boxen(
|
|
||||||
`${this.emojis.rocket} ${this.colors.brain('ATOMIC RESTORATION PROTOCOL')} ${this.emojis.atom}\n\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Initiating neural restoration sequence')}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Source:')} ${this.colors.highlight(backupPath)}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Mode:')} ${this.colors.highlight(options.dryRun ? 'Simulation' : 'Full Restore')}`,
|
|
||||||
{ padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }
|
|
||||||
))
|
|
||||||
|
|
||||||
const spinner = ora(`${this.emojis.brain} Loading atomic vault...`).start()
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Phase 1: Load backup file
|
|
||||||
spinner.text = `${this.emojis.disk} Reading atomic data...`
|
|
||||||
let rawData = await fs.readFile(backupPath, 'utf8')
|
|
||||||
|
|
||||||
// Phase 2: Decrypt if needed
|
|
||||||
if (options.password) {
|
|
||||||
spinner.text = `${this.emojis.shield} Decrypting atomic data...`
|
|
||||||
rawData = await this.decryptData(rawData, options.password)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 3: Decompress if needed
|
|
||||||
spinner.text = `${this.emojis.gear} Decompressing quantum data...`
|
|
||||||
const decompressedData = await this.decompressData(rawData)
|
|
||||||
|
|
||||||
// Phase 4: Parse backup data
|
|
||||||
const backupPackage = JSON.parse(decompressedData)
|
|
||||||
const { manifest, data } = backupPackage
|
|
||||||
|
|
||||||
// Phase 5: Verify integrity
|
|
||||||
if (options.verify) {
|
|
||||||
spinner.text = `${this.emojis.check} Verifying atomic integrity...`
|
|
||||||
await this.verifyRestoreData(data, manifest)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 6: Display what will be restored
|
|
||||||
console.log('\n' + boxen(
|
|
||||||
`${this.emojis.brain} ${this.colors.brain('RESTORATION PREVIEW')}\n\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Backup Date:')} ${this.colors.highlight(new Date(manifest.timestamp).toLocaleString())}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Entities:')} ${this.colors.primary(manifest.entityCount.toLocaleString())}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Relationships:')} ${this.colors.primary(manifest.relationshipCount.toLocaleString())}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Storage Type:')} ${this.colors.highlight(manifest.storageType)}`,
|
|
||||||
{ padding: 1, borderStyle: 'round', borderColor: '#D67441' }
|
|
||||||
))
|
|
||||||
|
|
||||||
if (options.dryRun) {
|
|
||||||
spinner.succeed(this.colors.success('Dry run complete - restoration simulation successful'))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 7: Confirm restoration
|
|
||||||
if (!options.overwrite) {
|
|
||||||
const { confirm } = await prompts({
|
|
||||||
type: 'confirm',
|
|
||||||
name: 'confirm',
|
|
||||||
message: `${this.emojis.warning} This will replace current data. Continue?`,
|
|
||||||
initial: false
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!confirm) {
|
|
||||||
spinner.info('Restoration cancelled by user')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 8: Restore data
|
|
||||||
spinner.text = `${this.emojis.rocket} Restoring neural pathways...`
|
|
||||||
await this.executeRestore(data, manifest)
|
|
||||||
|
|
||||||
spinner.succeed(this.colors.success(
|
|
||||||
`${this.emojis.sparkle} Restoration complete! Neural pathways successfully reconstructed.`
|
|
||||||
))
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
spinner.fail('Restoration failed - atomic vault corrupted!')
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List available backups in a directory
|
|
||||||
*/
|
|
||||||
async listBackups(directory: string = './backups'): Promise<BackupManifest[]> {
|
|
||||||
try {
|
|
||||||
const files = await fs.readdir(directory)
|
|
||||||
const backupFiles = files.filter(f => f.endsWith('.brainy') || f.endsWith('.json'))
|
|
||||||
|
|
||||||
const manifests: BackupManifest[] = []
|
|
||||||
|
|
||||||
for (const file of backupFiles) {
|
|
||||||
try {
|
|
||||||
const filePath = path.join(directory, file)
|
|
||||||
const manifest = await this.getBackupManifest(filePath)
|
|
||||||
if (manifest) manifests.push(manifest)
|
|
||||||
} catch (error) {
|
|
||||||
// Skip invalid backup files
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return manifests.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get backup manifest without loading full backup
|
|
||||||
*/
|
|
||||||
private async getBackupManifest(backupPath: string): Promise<BackupManifest | null> {
|
|
||||||
try {
|
|
||||||
const rawData = await fs.readFile(backupPath, 'utf8')
|
|
||||||
const decompressedData = await this.decompressData(rawData)
|
|
||||||
const backupPackage = JSON.parse(decompressedData)
|
|
||||||
return backupPackage.manifest || null
|
|
||||||
} catch (error) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collect all data for backup
|
|
||||||
*/
|
|
||||||
private async collectBackupData(options: BackupOptions): Promise<any> {
|
|
||||||
const data: any = {
|
|
||||||
entities: [],
|
|
||||||
relationships: [],
|
|
||||||
metadata: {},
|
|
||||||
statistics: null
|
|
||||||
}
|
|
||||||
|
|
||||||
// For now, we'll create a simplified backup that just captures the current state
|
|
||||||
// In a full implementation, this would use internal storage methods
|
|
||||||
|
|
||||||
console.log(this.colors.warning('Note: Backup system is in beta - captures basic data only'))
|
|
||||||
|
|
||||||
// Placeholder data collection
|
|
||||||
data.entities = []
|
|
||||||
data.relationships = []
|
|
||||||
|
|
||||||
// Collect metadata if requested
|
|
||||||
if (options.includeMetadata) {
|
|
||||||
data.metadata = await this.collectMetadata()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Statistics not yet implemented
|
|
||||||
if (options.includeStatistics) {
|
|
||||||
console.warn('Statistics collection not yet implemented in backup')
|
|
||||||
}
|
|
||||||
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create backup manifest
|
|
||||||
*/
|
|
||||||
private async createManifest(data: any, options: BackupOptions): Promise<BackupManifest> {
|
|
||||||
return {
|
|
||||||
version: '1.0.0',
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
brainyVersion: '0.55.0', // Would come from package.json
|
|
||||||
entityCount: data.entities.length,
|
|
||||||
relationshipCount: data.relationships.length,
|
|
||||||
storageType: 'unknown', // Would detect from brainy instance
|
|
||||||
compressed: options.compress || false,
|
|
||||||
encrypted: !!options.password,
|
|
||||||
checksum: await this.calculateChecksum(JSON.stringify(data)),
|
|
||||||
metadata: {
|
|
||||||
created: new Date().toISOString(),
|
|
||||||
description: 'Atomic age brain backup',
|
|
||||||
tags: ['brainy', 'neural-backup', 'atomic-data']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper methods
|
|
||||||
*/
|
|
||||||
private generateBackupPath(): string {
|
|
||||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
|
|
||||||
return `./brainy-backup-${timestamp}.brainy`
|
|
||||||
}
|
|
||||||
|
|
||||||
private async compressData(data: string): Promise<string> {
|
|
||||||
// Use zlib gzip compression
|
|
||||||
const { gzip } = await import('node:zlib')
|
|
||||||
const { promisify } = await import('node:util')
|
|
||||||
const gzipAsync = promisify(gzip)
|
|
||||||
|
|
||||||
const compressed = await gzipAsync(Buffer.from(data, 'utf-8'))
|
|
||||||
return compressed.toString('base64')
|
|
||||||
}
|
|
||||||
|
|
||||||
private async decompressData(data: string): Promise<string> {
|
|
||||||
// Use zlib gunzip decompression
|
|
||||||
const { gunzip } = await import('node:zlib')
|
|
||||||
const { promisify } = await import('node:util')
|
|
||||||
const gunzipAsync = promisify(gunzip)
|
|
||||||
|
|
||||||
const compressed = Buffer.from(data, 'base64')
|
|
||||||
const decompressed = await gunzipAsync(compressed)
|
|
||||||
return decompressed.toString('utf-8')
|
|
||||||
}
|
|
||||||
|
|
||||||
private async encryptData(data: string, password: string): Promise<string> {
|
|
||||||
// Use crypto module for AES-256 encryption
|
|
||||||
const crypto = await import('node:crypto')
|
|
||||||
|
|
||||||
// Generate key from password
|
|
||||||
const key = crypto.createHash('sha256').update(password).digest()
|
|
||||||
const iv = crypto.randomBytes(16)
|
|
||||||
|
|
||||||
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv)
|
|
||||||
let encrypted = cipher.update(data, 'utf8', 'base64')
|
|
||||||
encrypted += cipher.final('base64')
|
|
||||||
|
|
||||||
// Prepend IV to encrypted data for decryption
|
|
||||||
return iv.toString('base64') + ':' + encrypted
|
|
||||||
}
|
|
||||||
|
|
||||||
private async decryptData(data: string, password: string): Promise<string> {
|
|
||||||
// Use crypto module for AES-256 decryption
|
|
||||||
const crypto = await import('node:crypto')
|
|
||||||
|
|
||||||
// Split IV and encrypted data
|
|
||||||
const [ivString, encrypted] = data.split(':')
|
|
||||||
const iv = Buffer.from(ivString, 'base64')
|
|
||||||
|
|
||||||
// Generate key from password
|
|
||||||
const key = crypto.createHash('sha256').update(password).digest()
|
|
||||||
|
|
||||||
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
|
|
||||||
let decrypted = decipher.update(encrypted, 'base64', 'utf8')
|
|
||||||
decrypted += decipher.final('utf8')
|
|
||||||
|
|
||||||
return decrypted
|
|
||||||
}
|
|
||||||
|
|
||||||
private async verifyBackup(backupPath: string, options: BackupOptions): Promise<void> {
|
|
||||||
// Placeholder - would verify backup integrity
|
|
||||||
}
|
|
||||||
|
|
||||||
private async verifyRestoreData(data: any, manifest: BackupManifest): Promise<void> {
|
|
||||||
const actualChecksum = await this.calculateChecksum(JSON.stringify(data))
|
|
||||||
if (actualChecksum !== manifest.checksum) {
|
|
||||||
throw new Error('Data integrity check failed - backup may be corrupted')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async executeRestore(data: any, manifest: BackupManifest): Promise<void> {
|
|
||||||
console.log(this.colors.info('🔄 Starting restore process...'))
|
|
||||||
|
|
||||||
// Phase 1: Validate data structure
|
|
||||||
if (!data.entities || !Array.isArray(data.entities)) {
|
|
||||||
throw new Error('Invalid backup data structure')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 2: Clear existing data if overwriting
|
|
||||||
console.log(this.colors.dim('Clearing existing data...'))
|
|
||||||
const dataAPI = await this.brainy.data()
|
|
||||||
await dataAPI.clear()
|
|
||||||
|
|
||||||
// Phase 3: Restore entities
|
|
||||||
console.log(this.colors.dim(`Restoring ${data.entities.length} entities...`))
|
|
||||||
const entityMap = new Map<string, string>() // old ID -> new ID mapping
|
|
||||||
|
|
||||||
for (const entity of data.entities) {
|
|
||||||
const newId = await this.brainy.add({
|
|
||||||
data: entity.metadata || entity.data,
|
|
||||||
type: entity.type,
|
|
||||||
metadata: entity.metadata,
|
|
||||||
vector: entity.vector, // Preserve original vectors if available
|
|
||||||
service: entity.service
|
|
||||||
})
|
|
||||||
entityMap.set(entity.id, newId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 4: Restore relationships if they exist
|
|
||||||
if (data.relationships && Array.isArray(data.relationships)) {
|
|
||||||
console.log(this.colors.dim(`Restoring ${data.relationships.length} relationships...`))
|
|
||||||
|
|
||||||
for (const rel of data.relationships) {
|
|
||||||
// Map old IDs to new IDs
|
|
||||||
const fromId = entityMap.get(rel.from) || rel.from
|
|
||||||
const toId = entityMap.get(rel.to) || rel.to
|
|
||||||
|
|
||||||
await this.brainy.relate({
|
|
||||||
from: fromId,
|
|
||||||
to: toId,
|
|
||||||
type: rel.type,
|
|
||||||
metadata: rel.metadata || {}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 5: Restore metadata if present
|
|
||||||
if (data.metadata) {
|
|
||||||
await this.restoreMetadata(data.metadata)
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(this.colors.success('✅ Restore completed successfully'))
|
|
||||||
}
|
|
||||||
|
|
||||||
private async collectMetadata(): Promise<any> {
|
|
||||||
// Collect global metadata like statistics, configuration, etc.
|
|
||||||
const dataApi = await this.brainy.data()
|
|
||||||
const stats = await dataApi.getStats()
|
|
||||||
return {
|
|
||||||
totalEntities: stats.entities || 0,
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
version: '3.0.0'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async restoreMetadata(metadata: any): Promise<void> {
|
|
||||||
// Store restored metadata for reference
|
|
||||||
// Could be saved to a config store or logged
|
|
||||||
console.log(this.colors.dim(`Restored from backup created at: ${metadata.timestamp}`))
|
|
||||||
}
|
|
||||||
|
|
||||||
private async calculateChecksum(data: string): Promise<string> {
|
|
||||||
// Use crypto module for SHA-256 checksum
|
|
||||||
const crypto = await import('node:crypto')
|
|
||||||
return crypto.createHash('sha256').update(data).digest('hex')
|
|
||||||
}
|
|
||||||
|
|
||||||
private formatFileSize(bytes: number): string {
|
|
||||||
const units = ['B', 'KB', 'MB', 'GB']
|
|
||||||
let size = bytes
|
|
||||||
let unitIndex = 0
|
|
||||||
|
|
||||||
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
||||||
size /= 1024
|
|
||||||
unitIndex++
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${size.toFixed(1)} ${units[unitIndex]}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,673 +0,0 @@
|
||||||
/**
|
|
||||||
* Health Check System - Atomic Age Diagnostic Engine
|
|
||||||
*
|
|
||||||
* 🧠 Comprehensive health diagnostics for vector + graph operations
|
|
||||||
* ⚛️ Auto-repair capabilities with 1950s retro sci-fi aesthetics
|
|
||||||
* 🚀 Scalable health monitoring for high-performance databases
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Brainy } from '../brainy.js'
|
|
||||||
// @ts-ignore
|
|
||||||
import chalk from 'chalk'
|
|
||||||
// @ts-ignore
|
|
||||||
import boxen from 'boxen'
|
|
||||||
// @ts-ignore
|
|
||||||
import ora from 'ora'
|
|
||||||
|
|
||||||
export interface HealthCheckResult {
|
|
||||||
component: string
|
|
||||||
status: 'healthy' | 'warning' | 'critical' | 'offline'
|
|
||||||
score: number // 0-100
|
|
||||||
message: string
|
|
||||||
details?: string[]
|
|
||||||
autoFixAvailable?: boolean
|
|
||||||
lastChecked: string
|
|
||||||
responseTime?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SystemHealth {
|
|
||||||
overall: HealthCheckResult
|
|
||||||
vector: HealthCheckResult
|
|
||||||
graph: HealthCheckResult
|
|
||||||
storage: HealthCheckResult
|
|
||||||
memory: HealthCheckResult
|
|
||||||
network: HealthCheckResult
|
|
||||||
embedding: HealthCheckResult
|
|
||||||
cache: HealthCheckResult
|
|
||||||
timestamp: string
|
|
||||||
recommendations: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RepairAction {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
severity: 'low' | 'medium' | 'high'
|
|
||||||
automated: boolean
|
|
||||||
estimatedTime: string
|
|
||||||
riskLevel: 'safe' | 'moderate' | 'high'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Comprehensive Health Check and Auto-Repair System
|
|
||||||
*/
|
|
||||||
export class HealthCheck {
|
|
||||||
private brainy: Brainy
|
|
||||||
|
|
||||||
private colors = {
|
|
||||||
primary: chalk.hex('#3A5F4A'),
|
|
||||||
success: chalk.hex('#2D4A3A'),
|
|
||||||
warning: chalk.hex('#D67441'),
|
|
||||||
error: chalk.hex('#B85C35'),
|
|
||||||
info: chalk.hex('#4A6B5A'),
|
|
||||||
dim: chalk.hex('#8A9B8A'),
|
|
||||||
highlight: chalk.hex('#E88B5A'),
|
|
||||||
accent: chalk.hex('#F5E6D3'),
|
|
||||||
brain: chalk.hex('#E88B5A')
|
|
||||||
}
|
|
||||||
|
|
||||||
private emojis = {
|
|
||||||
brain: '🧠',
|
|
||||||
atom: '⚛️',
|
|
||||||
health: '💚',
|
|
||||||
warning: '⚠️',
|
|
||||||
critical: '🔥',
|
|
||||||
offline: '💀',
|
|
||||||
repair: '🔧',
|
|
||||||
shield: '🛡️',
|
|
||||||
rocket: '🚀',
|
|
||||||
gear: '⚙️',
|
|
||||||
check: '✅',
|
|
||||||
cross: '❌',
|
|
||||||
lightning: '⚡',
|
|
||||||
sparkle: '✨'
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(brainy: Brainy) {
|
|
||||||
this.brainy = brainy
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run comprehensive system health check
|
|
||||||
*/
|
|
||||||
async runHealthCheck(): Promise<SystemHealth> {
|
|
||||||
console.log(boxen(
|
|
||||||
`${this.emojis.shield} ${this.colors.brain('ATOMIC DIAGNOSTIC ENGINE')} ${this.emojis.atom}\n\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Initiating comprehensive system diagnostics')}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Scanning vector + graph database health')}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Auto-repair recommendations included')}`,
|
|
||||||
{ padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }
|
|
||||||
))
|
|
||||||
|
|
||||||
const spinner = ora(`${this.emojis.brain} Running neural diagnostics...`).start()
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Run all health checks in parallel for speed
|
|
||||||
const [
|
|
||||||
vectorHealth,
|
|
||||||
graphHealth,
|
|
||||||
storageHealth,
|
|
||||||
memoryHealth,
|
|
||||||
networkHealth,
|
|
||||||
embeddingHealth,
|
|
||||||
cacheHealth
|
|
||||||
] = await Promise.all([
|
|
||||||
this.checkVectorOperations(spinner),
|
|
||||||
this.checkGraphOperations(spinner),
|
|
||||||
this.checkStorageHealth(spinner),
|
|
||||||
this.checkMemoryHealth(spinner),
|
|
||||||
this.checkNetworkHealth(spinner),
|
|
||||||
this.checkEmbeddingHealth(spinner),
|
|
||||||
this.checkCacheHealth(spinner)
|
|
||||||
])
|
|
||||||
|
|
||||||
// Calculate overall health
|
|
||||||
const components = [vectorHealth, graphHealth, storageHealth, memoryHealth, networkHealth, embeddingHealth, cacheHealth]
|
|
||||||
const averageScore = components.reduce((sum, c) => sum + c.score, 0) / components.length
|
|
||||||
const criticalIssues = components.filter(c => c.status === 'critical').length
|
|
||||||
const warnings = components.filter(c => c.status === 'warning').length
|
|
||||||
|
|
||||||
const overallStatus = criticalIssues > 0 ? 'critical' :
|
|
||||||
warnings > 2 ? 'warning' :
|
|
||||||
averageScore >= 90 ? 'healthy' : 'warning'
|
|
||||||
|
|
||||||
const overall: HealthCheckResult = {
|
|
||||||
component: 'System Overall',
|
|
||||||
status: overallStatus,
|
|
||||||
score: Math.floor(averageScore),
|
|
||||||
message: this.getOverallMessage(overallStatus, criticalIssues, warnings),
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
|
|
||||||
const health: SystemHealth = {
|
|
||||||
overall,
|
|
||||||
vector: vectorHealth,
|
|
||||||
graph: graphHealth,
|
|
||||||
storage: storageHealth,
|
|
||||||
memory: memoryHealth,
|
|
||||||
network: networkHealth,
|
|
||||||
embedding: embeddingHealth,
|
|
||||||
cache: cacheHealth,
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
recommendations: this.generateRecommendations(components)
|
|
||||||
}
|
|
||||||
|
|
||||||
spinner.succeed(this.colors.success(
|
|
||||||
`${this.emojis.sparkle} Health check complete - Neural pathways analyzed`
|
|
||||||
))
|
|
||||||
|
|
||||||
return health
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
spinner.fail('Health check failed - Diagnostic systems compromised!')
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display health check results in terminal
|
|
||||||
*/
|
|
||||||
async displayHealthReport(health?: SystemHealth): Promise<void> {
|
|
||||||
if (!health) {
|
|
||||||
health = await this.runHealthCheck()
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('\n' + boxen(
|
|
||||||
`${this.emojis.brain} ${this.colors.brain('SYSTEM HEALTH REPORT')} ${this.emojis.atom}\n` +
|
|
||||||
`${this.colors.dim('Comprehensive Vector + Graph Database Diagnostics')}\n` +
|
|
||||||
`${this.colors.accent('Overall Health:')} ${this.getHealthIcon(health.overall.status)} ${this.colors.primary(health.overall.score + '/100')}`,
|
|
||||||
{ padding: 1, borderStyle: 'double', borderColor: '#E88B5A', width: 80 }
|
|
||||||
))
|
|
||||||
|
|
||||||
// Component Health Status
|
|
||||||
const components = [
|
|
||||||
health.vector,
|
|
||||||
health.graph,
|
|
||||||
health.storage,
|
|
||||||
health.memory,
|
|
||||||
health.network,
|
|
||||||
health.embedding,
|
|
||||||
health.cache
|
|
||||||
]
|
|
||||||
|
|
||||||
console.log('\n' + this.colors.brain(`${this.emojis.gear} COMPONENT STATUS`))
|
|
||||||
components.forEach(component => {
|
|
||||||
const statusColor = this.getStatusColor(component.status)
|
|
||||||
const icon = this.getHealthIcon(component.status)
|
|
||||||
const timeStr = component.responseTime ? ` (${component.responseTime}ms)` : ''
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`${icon} ${statusColor(component.component.padEnd(20))} ` +
|
|
||||||
`${this.colors.primary((component.score + '/100').padEnd(8))} ` +
|
|
||||||
`${this.colors.dim(component.message)}${timeStr}`
|
|
||||||
)
|
|
||||||
|
|
||||||
if (component.details && component.details.length > 0) {
|
|
||||||
component.details.forEach(detail => {
|
|
||||||
console.log(` ${this.colors.dim('→')} ${this.colors.accent(detail)}`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Auto-repair recommendations
|
|
||||||
if (health.recommendations.length > 0) {
|
|
||||||
console.log('\n' + this.colors.warning(`${this.emojis.repair} AUTO-REPAIR RECOMMENDATIONS`))
|
|
||||||
console.log(boxen(
|
|
||||||
health.recommendations.map((rec, i) =>
|
|
||||||
`${this.colors.accent((i + 1) + '.')} ${this.colors.dim(rec)}`
|
|
||||||
).join('\n'),
|
|
||||||
{ padding: 1, borderStyle: 'round', borderColor: '#D67441' }
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Critical issues
|
|
||||||
const criticalComponents = components.filter(c => c.status === 'critical')
|
|
||||||
if (criticalComponents.length > 0) {
|
|
||||||
console.log('\n' + this.colors.error(`${this.emojis.critical} CRITICAL ISSUES REQUIRING ATTENTION`))
|
|
||||||
criticalComponents.forEach(component => {
|
|
||||||
console.log(this.colors.error(` ${this.emojis.cross} ${component.component}: ${component.message}`))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('\n' + this.colors.dim(`Report generated: ${new Date(health.timestamp).toLocaleString()}`))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get available repair actions
|
|
||||||
*/
|
|
||||||
async getRepairActions(): Promise<RepairAction[]> {
|
|
||||||
const health = await this.runHealthCheck()
|
|
||||||
const actions: RepairAction[] = []
|
|
||||||
|
|
||||||
// Vector operations repairs
|
|
||||||
if (health.vector.status !== 'healthy') {
|
|
||||||
actions.push({
|
|
||||||
id: 'rebuild-vector-index',
|
|
||||||
name: 'Rebuild Vector Index',
|
|
||||||
description: 'Reconstruct HNSW index for optimal vector search performance',
|
|
||||||
severity: 'medium',
|
|
||||||
automated: true,
|
|
||||||
estimatedTime: '2-5 minutes',
|
|
||||||
riskLevel: 'safe'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Graph operations repairs
|
|
||||||
if (health.graph.status !== 'healthy') {
|
|
||||||
actions.push({
|
|
||||||
id: 'optimize-graph-connections',
|
|
||||||
name: 'Optimize Graph Connections',
|
|
||||||
description: 'Clean up orphaned relationships and optimize graph traversal paths',
|
|
||||||
severity: 'medium',
|
|
||||||
automated: true,
|
|
||||||
estimatedTime: '1-3 minutes',
|
|
||||||
riskLevel: 'safe'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memory optimization
|
|
||||||
if (health.memory.score < 70) {
|
|
||||||
actions.push({
|
|
||||||
id: 'optimize-memory-usage',
|
|
||||||
name: 'Optimize Memory Usage',
|
|
||||||
description: 'Clear unused caches and optimize memory allocation',
|
|
||||||
severity: 'low',
|
|
||||||
automated: true,
|
|
||||||
estimatedTime: '30 seconds',
|
|
||||||
riskLevel: 'safe'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache optimization
|
|
||||||
if (health.cache.score < 80) {
|
|
||||||
actions.push({
|
|
||||||
id: 'rebuild-cache-indexes',
|
|
||||||
name: 'Rebuild Cache Indexes',
|
|
||||||
description: 'Optimize cache data structures for better hit rates',
|
|
||||||
severity: 'low',
|
|
||||||
automated: true,
|
|
||||||
estimatedTime: '1-2 minutes',
|
|
||||||
riskLevel: 'safe'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Storage optimization
|
|
||||||
if (health.storage.score < 75) {
|
|
||||||
actions.push({
|
|
||||||
id: 'compress-storage-data',
|
|
||||||
name: 'Compress Storage Data',
|
|
||||||
description: 'Apply compression to reduce storage size and improve I/O',
|
|
||||||
severity: 'medium',
|
|
||||||
automated: false,
|
|
||||||
estimatedTime: '5-15 minutes',
|
|
||||||
riskLevel: 'moderate'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return actions
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute automated repairs
|
|
||||||
*/
|
|
||||||
async executeAutoRepairs(): Promise<{ success: string[], failed: string[] }> {
|
|
||||||
const actions = await this.getRepairActions()
|
|
||||||
const automatedActions = actions.filter(a => a.automated && a.riskLevel === 'safe')
|
|
||||||
|
|
||||||
if (automatedActions.length === 0) {
|
|
||||||
console.log(this.colors.info('No safe automated repairs available'))
|
|
||||||
return { success: [], failed: [] }
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(boxen(
|
|
||||||
`${this.emojis.repair} ${this.colors.brain('AUTOMATED REPAIR SEQUENCE')} ${this.emojis.atom}\n\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Executing safe automated repairs')}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Actions:')} ${this.colors.highlight(automatedActions.length.toString())}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Risk Level:')} ${this.colors.success('Safe')}`,
|
|
||||||
{ padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }
|
|
||||||
))
|
|
||||||
|
|
||||||
const success: string[] = []
|
|
||||||
const failed: string[] = []
|
|
||||||
|
|
||||||
for (const action of automatedActions) {
|
|
||||||
const spinner = ora(`${this.emojis.gear} Executing: ${action.name}`).start()
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.executeRepairAction(action)
|
|
||||||
spinner.succeed(this.colors.success(`${action.name} completed successfully`))
|
|
||||||
success.push(action.name)
|
|
||||||
} catch (error) {
|
|
||||||
spinner.fail(this.colors.error(`${action.name} failed: ${error}`))
|
|
||||||
failed.push(action.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success.length > 0) {
|
|
||||||
console.log(this.colors.success(`\n${this.emojis.sparkle} Auto-repair complete: ${success.length} actions successful`))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failed.length > 0) {
|
|
||||||
console.log(this.colors.warning(`${this.emojis.warning} ${failed.length} actions failed - manual intervention required`))
|
|
||||||
}
|
|
||||||
|
|
||||||
return { success, failed }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Individual health check methods
|
|
||||||
*/
|
|
||||||
private async checkVectorOperations(spinner: any): Promise<HealthCheckResult> {
|
|
||||||
spinner.text = `${this.emojis.lightning} Checking vector operations...`
|
|
||||||
const startTime = Date.now()
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Simulate vector health check
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 200 + Math.random() * 300))
|
|
||||||
|
|
||||||
const responseTime = Date.now() - startTime
|
|
||||||
const score = Math.floor(85 + Math.random() * 15)
|
|
||||||
const status = score >= 90 ? 'healthy' : score >= 70 ? 'warning' : 'critical'
|
|
||||||
|
|
||||||
return {
|
|
||||||
component: 'Vector Operations',
|
|
||||||
status,
|
|
||||||
score,
|
|
||||||
message: status === 'healthy' ? 'Optimal vector search performance' :
|
|
||||||
status === 'warning' ? 'Vector search slower than optimal' :
|
|
||||||
'Vector search performance degraded',
|
|
||||||
details: [
|
|
||||||
`HNSW Index: ${score >= 85 ? 'Optimized' : 'Needs rebuilding'}`,
|
|
||||||
`Embedding Cache: ${score >= 80 ? 'Efficient' : 'Cache misses high'}`,
|
|
||||||
`Query Latency: ${responseTime}ms average`
|
|
||||||
],
|
|
||||||
autoFixAvailable: score < 85,
|
|
||||||
lastChecked: new Date().toISOString(),
|
|
||||||
responseTime
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
component: 'Vector Operations',
|
|
||||||
status: 'critical',
|
|
||||||
score: 0,
|
|
||||||
message: 'Vector operations failed',
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async checkGraphOperations(spinner: any): Promise<HealthCheckResult> {
|
|
||||||
spinner.text = `${this.emojis.gear} Checking graph operations...`
|
|
||||||
const startTime = Date.now()
|
|
||||||
|
|
||||||
try {
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 150 + Math.random() * 200))
|
|
||||||
|
|
||||||
const responseTime = Date.now() - startTime
|
|
||||||
const score = Math.floor(80 + Math.random() * 20)
|
|
||||||
const status = score >= 90 ? 'healthy' : score >= 70 ? 'warning' : 'critical'
|
|
||||||
|
|
||||||
return {
|
|
||||||
component: 'Graph Operations',
|
|
||||||
status,
|
|
||||||
score,
|
|
||||||
message: status === 'healthy' ? 'Graph traversal performing optimally' :
|
|
||||||
status === 'warning' ? 'Graph queries slower than expected' :
|
|
||||||
'Graph operations significantly degraded',
|
|
||||||
details: [
|
|
||||||
`Relationship Index: ${score >= 85 ? 'Optimized' : 'Fragmented'}`,
|
|
||||||
`Traversal Cache: ${score >= 75 ? 'Efficient' : 'Low hit rate'}`,
|
|
||||||
`Connection Health: ${score >= 80 ? 'Good' : 'Orphaned connections detected'}`
|
|
||||||
],
|
|
||||||
autoFixAvailable: score < 80,
|
|
||||||
lastChecked: new Date().toISOString(),
|
|
||||||
responseTime
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
component: 'Graph Operations',
|
|
||||||
status: 'critical',
|
|
||||||
score: 0,
|
|
||||||
message: 'Graph operations failed',
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async checkStorageHealth(spinner: any): Promise<HealthCheckResult> {
|
|
||||||
spinner.text = `${this.emojis.shield} Checking storage systems...`
|
|
||||||
|
|
||||||
try {
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 100 + Math.random() * 200))
|
|
||||||
|
|
||||||
const score = Math.floor(88 + Math.random() * 12)
|
|
||||||
const status = score >= 90 ? 'healthy' : score >= 75 ? 'warning' : 'critical'
|
|
||||||
|
|
||||||
return {
|
|
||||||
component: 'Storage Systems',
|
|
||||||
status,
|
|
||||||
score,
|
|
||||||
message: status === 'healthy' ? 'Storage operating at peak efficiency' :
|
|
||||||
status === 'warning' ? 'Storage performance below optimal' :
|
|
||||||
'Storage systems experiencing issues',
|
|
||||||
details: [
|
|
||||||
`I/O Performance: ${score >= 85 ? 'Excellent' : 'Needs optimization'}`,
|
|
||||||
`Data Integrity: ${score >= 90 ? 'Verified' : 'Minor inconsistencies'}`,
|
|
||||||
`Compression Ratio: ${score >= 80 ? 'Optimal' : 'Can be improved'}`
|
|
||||||
],
|
|
||||||
autoFixAvailable: score < 85,
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
component: 'Storage Systems',
|
|
||||||
status: 'offline',
|
|
||||||
score: 0,
|
|
||||||
message: 'Storage systems offline',
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async checkMemoryHealth(spinner: any): Promise<HealthCheckResult> {
|
|
||||||
spinner.text = `${this.emojis.brain} Analyzing memory usage...`
|
|
||||||
|
|
||||||
try {
|
|
||||||
const memUsage = process.memoryUsage()
|
|
||||||
const heapUsedMB = memUsage.heapUsed / (1024 * 1024)
|
|
||||||
const heapTotalMB = memUsage.heapTotal / (1024 * 1024)
|
|
||||||
const usage = (heapUsedMB / heapTotalMB) * 100
|
|
||||||
|
|
||||||
const score = usage < 70 ? 95 : usage < 85 ? 80 : usage < 95 ? 60 : 30
|
|
||||||
const status = score >= 80 ? 'healthy' : score >= 60 ? 'warning' : 'critical'
|
|
||||||
|
|
||||||
return {
|
|
||||||
component: 'Memory Management',
|
|
||||||
status,
|
|
||||||
score,
|
|
||||||
message: status === 'healthy' ? 'Memory usage within optimal range' :
|
|
||||||
status === 'warning' ? 'Memory usage elevated but stable' :
|
|
||||||
'Memory usage critically high',
|
|
||||||
details: [
|
|
||||||
`Heap Usage: ${heapUsedMB.toFixed(1)}MB / ${heapTotalMB.toFixed(1)}MB (${usage.toFixed(1)}%)`,
|
|
||||||
`Memory Efficiency: ${score >= 80 ? 'Excellent' : 'Needs optimization'}`,
|
|
||||||
`GC Pressure: ${usage < 70 ? 'Low' : usage < 85 ? 'Moderate' : 'High'}`
|
|
||||||
],
|
|
||||||
autoFixAvailable: score < 75,
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
component: 'Memory Management',
|
|
||||||
status: 'critical',
|
|
||||||
score: 0,
|
|
||||||
message: 'Memory analysis failed',
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async checkNetworkHealth(spinner: any): Promise<HealthCheckResult> {
|
|
||||||
spinner.text = `${this.emojis.rocket} Testing network connectivity...`
|
|
||||||
|
|
||||||
try {
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 50 + Math.random() * 100))
|
|
||||||
|
|
||||||
const score = Math.floor(90 + Math.random() * 10)
|
|
||||||
const status = 'healthy' // Assume healthy for local operations
|
|
||||||
|
|
||||||
return {
|
|
||||||
component: 'Network/Connectivity',
|
|
||||||
status,
|
|
||||||
score,
|
|
||||||
message: 'Network connectivity optimal',
|
|
||||||
details: [
|
|
||||||
'Local Operations: Excellent',
|
|
||||||
'API Endpoints: Responsive',
|
|
||||||
'Storage Access: Fast'
|
|
||||||
],
|
|
||||||
autoFixAvailable: false,
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
component: 'Network/Connectivity',
|
|
||||||
status: 'critical',
|
|
||||||
score: 0,
|
|
||||||
message: 'Network connectivity issues',
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async checkEmbeddingHealth(spinner: any): Promise<HealthCheckResult> {
|
|
||||||
spinner.text = `${this.emojis.atom} Verifying embedding system...`
|
|
||||||
|
|
||||||
try {
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 300 + Math.random() * 200))
|
|
||||||
|
|
||||||
const score = Math.floor(85 + Math.random() * 15)
|
|
||||||
const status = score >= 90 ? 'healthy' : score >= 75 ? 'warning' : 'critical'
|
|
||||||
|
|
||||||
return {
|
|
||||||
component: 'Embedding System',
|
|
||||||
status,
|
|
||||||
score,
|
|
||||||
message: status === 'healthy' ? 'Embedding generation optimal' :
|
|
||||||
status === 'warning' ? 'Embedding performance acceptable' :
|
|
||||||
'Embedding system issues detected',
|
|
||||||
details: [
|
|
||||||
`Model Loading: ${score >= 85 ? 'Cached' : 'Slow to load'}`,
|
|
||||||
`Generation Speed: ${score >= 80 ? 'Fast' : 'Slower than expected'}`,
|
|
||||||
`Quality Score: ${score >= 90 ? 'Excellent' : 'Good'}`
|
|
||||||
],
|
|
||||||
autoFixAvailable: score < 85,
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
component: 'Embedding System',
|
|
||||||
status: 'critical',
|
|
||||||
score: 0,
|
|
||||||
message: 'Embedding system failed',
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async checkCacheHealth(spinner: any): Promise<HealthCheckResult> {
|
|
||||||
spinner.text = `${this.emojis.lightning} Analyzing cache performance...`
|
|
||||||
|
|
||||||
try {
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 100 + Math.random() * 150))
|
|
||||||
|
|
||||||
const hitRate = 0.75 + Math.random() * 0.2
|
|
||||||
const score = Math.floor(hitRate * 100)
|
|
||||||
const status = score >= 85 ? 'healthy' : score >= 70 ? 'warning' : 'critical'
|
|
||||||
|
|
||||||
return {
|
|
||||||
component: 'Cache System',
|
|
||||||
status,
|
|
||||||
score,
|
|
||||||
message: status === 'healthy' ? 'Cache performance excellent' :
|
|
||||||
status === 'warning' ? 'Cache hit rate below optimal' :
|
|
||||||
'Cache system underperforming',
|
|
||||||
details: [
|
|
||||||
`Hit Rate: ${(hitRate * 100).toFixed(1)}%`,
|
|
||||||
`Memory Efficiency: ${score >= 80 ? 'Good' : 'Needs optimization'}`,
|
|
||||||
`Eviction Rate: ${score >= 85 ? 'Low' : 'High'}`
|
|
||||||
],
|
|
||||||
autoFixAvailable: score < 80,
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
component: 'Cache System',
|
|
||||||
status: 'critical',
|
|
||||||
score: 0,
|
|
||||||
message: 'Cache system failed',
|
|
||||||
lastChecked: new Date().toISOString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper methods
|
|
||||||
*/
|
|
||||||
private getOverallMessage(status: string, critical: number, warnings: number): string {
|
|
||||||
if (status === 'critical') return `${critical} critical issue${critical > 1 ? 's' : ''} detected`
|
|
||||||
if (status === 'warning') return `${warnings} warning${warnings > 1 ? 's' : ''} detected`
|
|
||||||
return 'All systems operating normally'
|
|
||||||
}
|
|
||||||
|
|
||||||
private generateRecommendations(components: HealthCheckResult[]): string[] {
|
|
||||||
const recommendations: string[] = []
|
|
||||||
|
|
||||||
components.forEach(component => {
|
|
||||||
if (component.status === 'critical') {
|
|
||||||
recommendations.push(`Immediate attention required for ${component.component}`)
|
|
||||||
} else if (component.status === 'warning' && component.autoFixAvailable) {
|
|
||||||
recommendations.push(`Run auto-repair for ${component.component} to improve performance`)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (recommendations.length === 0) {
|
|
||||||
recommendations.push('All systems healthy - no actions required')
|
|
||||||
}
|
|
||||||
|
|
||||||
return recommendations
|
|
||||||
}
|
|
||||||
|
|
||||||
private getHealthIcon(status: string): string {
|
|
||||||
switch (status) {
|
|
||||||
case 'healthy': return this.emojis.health
|
|
||||||
case 'warning': return this.emojis.warning
|
|
||||||
case 'critical': return this.emojis.critical
|
|
||||||
case 'offline': return this.emojis.offline
|
|
||||||
default: return this.emojis.gear
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private getStatusColor(status: string) {
|
|
||||||
switch (status) {
|
|
||||||
case 'healthy': return this.colors.success
|
|
||||||
case 'warning': return this.colors.warning
|
|
||||||
case 'critical': return this.colors.error
|
|
||||||
case 'offline': return this.colors.dim
|
|
||||||
default: return this.colors.info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async executeRepairAction(action: RepairAction): Promise<void> {
|
|
||||||
// Simulate repair execution
|
|
||||||
const delay = action.estimatedTime.includes('second') ? 1000 :
|
|
||||||
action.estimatedTime.includes('minute') ? 2000 : 3000
|
|
||||||
|
|
||||||
await new Promise(resolve => setTimeout(resolve, delay))
|
|
||||||
|
|
||||||
// Simulate occasional failure
|
|
||||||
if (Math.random() < 0.1) {
|
|
||||||
throw new Error('Repair action failed - manual intervention required')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,500 +0,0 @@
|
||||||
/**
|
|
||||||
* Performance Monitor - Atomic Age Intelligence Observatory
|
|
||||||
*
|
|
||||||
* 🧠 Real-time performance tracking for vector + graph operations
|
|
||||||
* ⚛️ Monitors query performance, storage usage, and system health
|
|
||||||
* 🚀 Scalable performance analytics with atomic age aesthetics
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Brainy } from '../brainy.js'
|
|
||||||
// @ts-ignore
|
|
||||||
import chalk from 'chalk'
|
|
||||||
// @ts-ignore
|
|
||||||
import boxen from 'boxen'
|
|
||||||
|
|
||||||
export interface PerformanceMetrics {
|
|
||||||
// Query Performance
|
|
||||||
queryLatency: {
|
|
||||||
vector: { avg: number; p50: number; p95: number; p99: number }
|
|
||||||
graph: { avg: number; p50: number; p95: number; p99: number }
|
|
||||||
combined: { avg: number; p50: number; p95: number; p99: number }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Throughput
|
|
||||||
throughput: {
|
|
||||||
vectorOps: number // Operations per second
|
|
||||||
graphOps: number // Relationships per second
|
|
||||||
totalOps: number // Combined ops per second
|
|
||||||
}
|
|
||||||
|
|
||||||
// Storage Performance
|
|
||||||
storage: {
|
|
||||||
readLatency: number // Average read latency (ms)
|
|
||||||
writeLatency: number // Average write latency (ms)
|
|
||||||
cacheHitRate: number // Percentage of cache hits
|
|
||||||
totalSize: number // Total storage size in bytes
|
|
||||||
growthRate: number // Storage growth rate per hour
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memory Usage
|
|
||||||
memory: {
|
|
||||||
heapUsed: number // Current heap usage in MB
|
|
||||||
heapTotal: number // Total heap size in MB
|
|
||||||
vectorCache: number // Vector cache size in MB
|
|
||||||
graphCache: number // Graph cache size in MB
|
|
||||||
efficiency: number // Memory efficiency percentage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error Rates
|
|
||||||
errors: {
|
|
||||||
total: number // Total error count
|
|
||||||
rate: number // Errors per minute
|
|
||||||
types: { [key: string]: number } // Error breakdown by type
|
|
||||||
}
|
|
||||||
|
|
||||||
// Health Score
|
|
||||||
health: {
|
|
||||||
overall: number // Overall health score (0-100)
|
|
||||||
vector: number // Vector operations health
|
|
||||||
graph: number // Graph operations health
|
|
||||||
storage: number // Storage system health
|
|
||||||
network: number // Network/connectivity health
|
|
||||||
}
|
|
||||||
|
|
||||||
timestamp: string
|
|
||||||
uptime: number // System uptime in seconds
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AlertRule {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
condition: string // e.g., "queryLatency.vector.p95 > 500"
|
|
||||||
threshold: number
|
|
||||||
severity: 'low' | 'medium' | 'high' | 'critical'
|
|
||||||
action?: string // Optional automated action
|
|
||||||
enabled: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PerformanceAlert {
|
|
||||||
id: string
|
|
||||||
rule: AlertRule
|
|
||||||
triggered: string // ISO timestamp
|
|
||||||
value: number
|
|
||||||
message: string
|
|
||||||
resolved?: string // ISO timestamp when resolved
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Real-time Performance Monitoring System
|
|
||||||
*/
|
|
||||||
export class PerformanceMonitor {
|
|
||||||
private brainy: Brainy
|
|
||||||
private metrics: PerformanceMetrics[] = []
|
|
||||||
private alerts: PerformanceAlert[] = []
|
|
||||||
private alertRules: AlertRule[] = []
|
|
||||||
private isMonitoring = false
|
|
||||||
private monitoringInterval?: NodeJS.Timeout
|
|
||||||
|
|
||||||
private colors = {
|
|
||||||
primary: chalk.hex('#3A5F4A'),
|
|
||||||
success: chalk.hex('#2D4A3A'),
|
|
||||||
warning: chalk.hex('#D67441'),
|
|
||||||
error: chalk.hex('#B85C35'),
|
|
||||||
info: chalk.hex('#4A6B5A'),
|
|
||||||
dim: chalk.hex('#8A9B8A'),
|
|
||||||
highlight: chalk.hex('#E88B5A'),
|
|
||||||
accent: chalk.hex('#F5E6D3'),
|
|
||||||
brain: chalk.hex('#E88B5A')
|
|
||||||
}
|
|
||||||
|
|
||||||
private emojis = {
|
|
||||||
brain: '🧠',
|
|
||||||
atom: '⚛️',
|
|
||||||
monitor: '📊',
|
|
||||||
alert: '🚨',
|
|
||||||
health: '💚',
|
|
||||||
warning: '⚠️',
|
|
||||||
critical: '🔥',
|
|
||||||
rocket: '🚀',
|
|
||||||
gear: '⚙️',
|
|
||||||
chart: '📈',
|
|
||||||
lightning: '⚡',
|
|
||||||
shield: '🛡️'
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(brainy: Brainy) {
|
|
||||||
this.brainy = brainy
|
|
||||||
this.initializeDefaultAlerts()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start real-time monitoring
|
|
||||||
*/
|
|
||||||
async startMonitoring(intervalMs: number = 30000): Promise<void> {
|
|
||||||
if (this.isMonitoring) {
|
|
||||||
console.log(this.colors.warning('Monitoring already running'))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(boxen(
|
|
||||||
`${this.emojis.monitor} ${this.colors.brain('ATOMIC PERFORMANCE OBSERVATORY')} ${this.emojis.atom}\n\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Initiating neural performance monitoring')}` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Monitoring Interval:')} ${this.colors.highlight(intervalMs + 'ms')}\n` +
|
|
||||||
`${this.colors.accent('◆')} ${this.colors.dim('Vector + Graph Analytics:')} ${this.colors.highlight('Enabled')}`,
|
|
||||||
{ padding: 1, borderStyle: 'round', borderColor: '#E88B5A' }
|
|
||||||
))
|
|
||||||
|
|
||||||
this.isMonitoring = true
|
|
||||||
this.monitoringInterval = setInterval(async () => {
|
|
||||||
try {
|
|
||||||
const metrics = await this.collectMetrics()
|
|
||||||
this.metrics.push(metrics)
|
|
||||||
|
|
||||||
// Keep only last 1000 metrics (rolling window)
|
|
||||||
if (this.metrics.length > 1000) {
|
|
||||||
this.metrics = this.metrics.slice(-1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check alerts
|
|
||||||
await this.checkAlerts(metrics)
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error collecting metrics:', error)
|
|
||||||
}
|
|
||||||
}, intervalMs)
|
|
||||||
|
|
||||||
console.log(this.colors.success(`${this.emojis.rocket} Performance monitoring started - neural pathways under observation`))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop monitoring
|
|
||||||
*/
|
|
||||||
stopMonitoring(): void {
|
|
||||||
if (!this.isMonitoring) {
|
|
||||||
console.log(this.colors.warning('Monitoring not running'))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.monitoringInterval) {
|
|
||||||
clearInterval(this.monitoringInterval)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isMonitoring = false
|
|
||||||
console.log(this.colors.info(`${this.emojis.gear} Performance monitoring stopped`))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get current performance metrics
|
|
||||||
*/
|
|
||||||
async getCurrentMetrics(): Promise<PerformanceMetrics> {
|
|
||||||
return await this.collectMetrics()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get performance dashboard data
|
|
||||||
*/
|
|
||||||
async getDashboard(): Promise<{
|
|
||||||
current: PerformanceMetrics
|
|
||||||
trends: PerformanceMetrics[]
|
|
||||||
alerts: PerformanceAlert[]
|
|
||||||
health: string
|
|
||||||
}> {
|
|
||||||
const current = await this.collectMetrics()
|
|
||||||
const activeAlerts = this.alerts.filter(a => !a.resolved)
|
|
||||||
|
|
||||||
return {
|
|
||||||
current,
|
|
||||||
trends: this.metrics.slice(-100), // Last 100 data points
|
|
||||||
alerts: activeAlerts,
|
|
||||||
health: this.getHealthStatus(current)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display performance dashboard in terminal
|
|
||||||
*/
|
|
||||||
async displayDashboard(): Promise<void> {
|
|
||||||
const dashboard = await this.getDashboard()
|
|
||||||
const metrics = dashboard.current
|
|
||||||
|
|
||||||
console.clear()
|
|
||||||
|
|
||||||
// Header
|
|
||||||
console.log(boxen(
|
|
||||||
`${this.emojis.brain} ${this.colors.brain('BRAINY PERFORMANCE DASHBOARD')} ${this.emojis.atom}\n` +
|
|
||||||
`${this.colors.dim('Real-time Vector + Graph Database Performance')}\n` +
|
|
||||||
`${this.colors.accent('Uptime:')} ${this.colors.highlight(this.formatUptime(metrics.uptime))} | ` +
|
|
||||||
`${this.colors.accent('Health:')} ${this.getHealthIcon(metrics.health.overall)} ${this.colors.primary(metrics.health.overall + '/100')}`,
|
|
||||||
{ padding: 1, borderStyle: 'double', borderColor: '#E88B5A', width: 80 }
|
|
||||||
))
|
|
||||||
|
|
||||||
// Query Performance Section
|
|
||||||
console.log('\n' + this.colors.brain(`${this.emojis.lightning} QUERY PERFORMANCE`))
|
|
||||||
console.log(boxen(
|
|
||||||
`${this.colors.accent('Vector Queries:')} ${this.colors.primary(metrics.queryLatency.vector.avg.toFixed(1) + 'ms avg')} | ` +
|
|
||||||
`${this.colors.accent('P95:')} ${this.colors.highlight(metrics.queryLatency.vector.p95.toFixed(1) + 'ms')}\n` +
|
|
||||||
`${this.colors.accent('Graph Queries:')} ${this.colors.primary(metrics.queryLatency.graph.avg.toFixed(1) + 'ms avg')} | ` +
|
|
||||||
`${this.colors.accent('P95:')} ${this.colors.highlight(metrics.queryLatency.graph.p95.toFixed(1) + 'ms')}\n` +
|
|
||||||
`${this.colors.accent('Combined Ops:')} ${this.colors.success(metrics.throughput.totalOps.toFixed(0) + ' ops/sec')}`,
|
|
||||||
{ padding: 1, borderStyle: 'round', borderColor: '#3A5F4A' }
|
|
||||||
))
|
|
||||||
|
|
||||||
// Storage & Memory Section
|
|
||||||
console.log('\n' + this.colors.brain(`${this.emojis.shield} STORAGE & MEMORY`))
|
|
||||||
console.log(boxen(
|
|
||||||
`${this.colors.accent('Storage Size:')} ${this.colors.primary(this.formatBytes(metrics.storage.totalSize))} | ` +
|
|
||||||
`${this.colors.accent('Growth:')} ${this.colors.highlight(metrics.storage.growthRate.toFixed(1) + '/hr')}\n` +
|
|
||||||
`${this.colors.accent('Cache Hit Rate:')} ${this.colors.success((metrics.storage.cacheHitRate * 100).toFixed(1) + '%')} | ` +
|
|
||||||
`${this.colors.accent('Memory:')} ${this.colors.primary(metrics.memory.heapUsed.toFixed(0) + 'MB')}\n` +
|
|
||||||
`${this.colors.accent('Vector Cache:')} ${this.colors.info(metrics.memory.vectorCache.toFixed(1) + 'MB')} | ` +
|
|
||||||
`${this.colors.accent('Graph Cache:')} ${this.colors.info(metrics.memory.graphCache.toFixed(1) + 'MB')}`,
|
|
||||||
{ padding: 1, borderStyle: 'round', borderColor: '#4A6B5A' }
|
|
||||||
))
|
|
||||||
|
|
||||||
// Health Scores Section
|
|
||||||
console.log('\n' + this.colors.brain(`${this.emojis.health} SYSTEM HEALTH`))
|
|
||||||
console.log(boxen(
|
|
||||||
`${this.colors.accent('Vector Operations:')} ${this.getHealthBar(metrics.health.vector)} ${this.colors.primary(metrics.health.vector + '/100')}\n` +
|
|
||||||
`${this.colors.accent('Graph Operations:')} ${this.getHealthBar(metrics.health.graph)} ${this.colors.primary(metrics.health.graph + '/100')}\n` +
|
|
||||||
`${this.colors.accent('Storage System:')} ${this.getHealthBar(metrics.health.storage)} ${this.colors.primary(metrics.health.storage + '/100')}\n` +
|
|
||||||
`${this.colors.accent('Network/Connectivity:')} ${this.getHealthBar(metrics.health.network)} ${this.colors.primary(metrics.health.network + '/100')}`,
|
|
||||||
{ padding: 1, borderStyle: 'round', borderColor: '#2D4A3A' }
|
|
||||||
))
|
|
||||||
|
|
||||||
// Active Alerts
|
|
||||||
if (dashboard.alerts.length > 0) {
|
|
||||||
console.log('\n' + this.colors.error(`${this.emojis.alert} ACTIVE ALERTS`))
|
|
||||||
dashboard.alerts.forEach(alert => {
|
|
||||||
const severityColor = alert.rule.severity === 'critical' ? this.colors.error :
|
|
||||||
alert.rule.severity === 'high' ? this.colors.warning :
|
|
||||||
this.colors.info
|
|
||||||
console.log(severityColor(` ${this.getSeverityIcon(alert.rule.severity)} ${alert.message}`))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Footer
|
|
||||||
console.log('\n' + this.colors.dim(`Last updated: ${new Date().toLocaleTimeString()} | Press Ctrl+C to exit`))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collect current performance metrics
|
|
||||||
*/
|
|
||||||
private async collectMetrics(): Promise<PerformanceMetrics> {
|
|
||||||
const now = Date.now()
|
|
||||||
const uptime = process.uptime()
|
|
||||||
|
|
||||||
// Simulate metrics collection (in real implementation, this would query actual systems)
|
|
||||||
const metrics: PerformanceMetrics = {
|
|
||||||
queryLatency: {
|
|
||||||
vector: {
|
|
||||||
avg: Math.random() * 50 + 10,
|
|
||||||
p50: Math.random() * 40 + 8,
|
|
||||||
p95: Math.random() * 100 + 30,
|
|
||||||
p99: Math.random() * 200 + 50
|
|
||||||
},
|
|
||||||
graph: {
|
|
||||||
avg: Math.random() * 30 + 5,
|
|
||||||
p50: Math.random() * 25 + 4,
|
|
||||||
p95: Math.random() * 80 + 15,
|
|
||||||
p99: Math.random() * 150 + 25
|
|
||||||
},
|
|
||||||
combined: {
|
|
||||||
avg: Math.random() * 40 + 7,
|
|
||||||
p50: Math.random() * 35 + 6,
|
|
||||||
p95: Math.random() * 90 + 20,
|
|
||||||
p99: Math.random() * 180 + 40
|
|
||||||
}
|
|
||||||
},
|
|
||||||
throughput: {
|
|
||||||
vectorOps: Math.random() * 1000 + 500,
|
|
||||||
graphOps: Math.random() * 800 + 300,
|
|
||||||
totalOps: Math.random() * 1500 + 800
|
|
||||||
},
|
|
||||||
storage: {
|
|
||||||
readLatency: Math.random() * 20 + 2,
|
|
||||||
writeLatency: Math.random() * 30 + 5,
|
|
||||||
cacheHitRate: 0.85 + Math.random() * 0.1,
|
|
||||||
totalSize: 1024 * 1024 * 1024 * (10 + Math.random() * 50), // 10-60 GB
|
|
||||||
growthRate: Math.random() * 100 + 10
|
|
||||||
},
|
|
||||||
memory: {
|
|
||||||
heapUsed: process.memoryUsage().heapUsed / (1024 * 1024),
|
|
||||||
heapTotal: process.memoryUsage().heapTotal / (1024 * 1024),
|
|
||||||
vectorCache: Math.random() * 500 + 100,
|
|
||||||
graphCache: Math.random() * 300 + 50,
|
|
||||||
efficiency: 0.75 + Math.random() * 0.2
|
|
||||||
},
|
|
||||||
errors: {
|
|
||||||
total: Math.floor(Math.random() * 10),
|
|
||||||
rate: Math.random() * 2,
|
|
||||||
types: {
|
|
||||||
'timeout': Math.floor(Math.random() * 3),
|
|
||||||
'network': Math.floor(Math.random() * 2),
|
|
||||||
'storage': Math.floor(Math.random() * 2)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
health: {
|
|
||||||
overall: Math.floor(85 + Math.random() * 15),
|
|
||||||
vector: Math.floor(80 + Math.random() * 20),
|
|
||||||
graph: Math.floor(85 + Math.random() * 15),
|
|
||||||
storage: Math.floor(90 + Math.random() * 10),
|
|
||||||
network: Math.floor(85 + Math.random() * 15)
|
|
||||||
},
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
uptime
|
|
||||||
}
|
|
||||||
|
|
||||||
return metrics
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize default alert rules
|
|
||||||
*/
|
|
||||||
private initializeDefaultAlerts(): void {
|
|
||||||
this.alertRules = [
|
|
||||||
{
|
|
||||||
id: 'vector-latency-high',
|
|
||||||
name: 'Vector Query Latency High',
|
|
||||||
condition: 'queryLatency.vector.p95 > 200',
|
|
||||||
threshold: 200,
|
|
||||||
severity: 'medium',
|
|
||||||
enabled: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'graph-latency-high',
|
|
||||||
name: 'Graph Query Latency High',
|
|
||||||
condition: 'queryLatency.graph.p95 > 150',
|
|
||||||
threshold: 150,
|
|
||||||
severity: 'medium',
|
|
||||||
enabled: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'memory-high',
|
|
||||||
name: 'Memory Usage High',
|
|
||||||
condition: 'memory.heapUsed > 1000',
|
|
||||||
threshold: 1000,
|
|
||||||
severity: 'high',
|
|
||||||
enabled: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'cache-hit-low',
|
|
||||||
name: 'Cache Hit Rate Low',
|
|
||||||
condition: 'storage.cacheHitRate < 0.7',
|
|
||||||
threshold: 0.7,
|
|
||||||
severity: 'medium',
|
|
||||||
enabled: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'error-rate-high',
|
|
||||||
name: 'Error Rate High',
|
|
||||||
condition: 'errors.rate > 5',
|
|
||||||
threshold: 5,
|
|
||||||
severity: 'high',
|
|
||||||
enabled: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check alerts against current metrics
|
|
||||||
*/
|
|
||||||
private async checkAlerts(metrics: PerformanceMetrics): Promise<void> {
|
|
||||||
for (const rule of this.alertRules) {
|
|
||||||
if (!rule.enabled) continue
|
|
||||||
|
|
||||||
const value = this.evaluateCondition(rule.condition, metrics)
|
|
||||||
const isTriggered = value > rule.threshold
|
|
||||||
|
|
||||||
const existingAlert = this.alerts.find(a => a.rule.id === rule.id && !a.resolved)
|
|
||||||
|
|
||||||
if (isTriggered && !existingAlert) {
|
|
||||||
// Trigger new alert
|
|
||||||
const alert: PerformanceAlert = {
|
|
||||||
id: `${rule.id}-${Date.now()}`,
|
|
||||||
rule,
|
|
||||||
triggered: new Date().toISOString(),
|
|
||||||
value,
|
|
||||||
message: `${rule.name}: ${value.toFixed(2)} > ${rule.threshold}`
|
|
||||||
}
|
|
||||||
this.alerts.push(alert)
|
|
||||||
console.log(this.colors.warning(`${this.emojis.alert} ALERT: ${alert.message}`))
|
|
||||||
} else if (!isTriggered && existingAlert) {
|
|
||||||
// Resolve existing alert
|
|
||||||
existingAlert.resolved = new Date().toISOString()
|
|
||||||
console.log(this.colors.success(`${this.emojis.health} RESOLVED: ${existingAlert.message}`))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluate alert condition against metrics
|
|
||||||
*/
|
|
||||||
private evaluateCondition(condition: string, metrics: PerformanceMetrics): number {
|
|
||||||
// Simple condition evaluation (in real implementation, use a proper expression parser)
|
|
||||||
const parts = condition.split(' ')
|
|
||||||
if (parts.length !== 3) return 0
|
|
||||||
|
|
||||||
const path = parts[0]
|
|
||||||
const value = this.getMetricValue(path, metrics)
|
|
||||||
return typeof value === 'number' ? value : 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get metric value by dot notation path
|
|
||||||
*/
|
|
||||||
private getMetricValue(path: string, metrics: PerformanceMetrics): any {
|
|
||||||
return path.split('.').reduce((obj: any, key: string) => obj?.[key], metrics as any)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper methods
|
|
||||||
*/
|
|
||||||
private getHealthStatus(metrics: PerformanceMetrics): string {
|
|
||||||
const score = metrics.health.overall
|
|
||||||
if (score >= 90) return 'excellent'
|
|
||||||
if (score >= 75) return 'good'
|
|
||||||
if (score >= 60) return 'fair'
|
|
||||||
return 'poor'
|
|
||||||
}
|
|
||||||
|
|
||||||
private getHealthIcon(score: number): string {
|
|
||||||
if (score >= 90) return this.emojis.health
|
|
||||||
if (score >= 75) return '💛'
|
|
||||||
if (score >= 60) return this.emojis.warning
|
|
||||||
return this.emojis.critical
|
|
||||||
}
|
|
||||||
|
|
||||||
private getHealthBar(score: number): string {
|
|
||||||
const filled = Math.floor(score / 10)
|
|
||||||
const empty = 10 - filled
|
|
||||||
return this.colors.success('█'.repeat(filled)) + this.colors.dim('░'.repeat(empty))
|
|
||||||
}
|
|
||||||
|
|
||||||
private getSeverityIcon(severity: string): string {
|
|
||||||
switch (severity) {
|
|
||||||
case 'critical': return this.emojis.critical
|
|
||||||
case 'high': return this.emojis.alert
|
|
||||||
case 'medium': return this.emojis.warning
|
|
||||||
default: return this.emojis.gear
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private formatUptime(seconds: number): string {
|
|
||||||
const hours = Math.floor(seconds / 3600)
|
|
||||||
const minutes = Math.floor((seconds % 3600) / 60)
|
|
||||||
return `${hours}h ${minutes}m`
|
|
||||||
}
|
|
||||||
|
|
||||||
private formatBytes(bytes: number): string {
|
|
||||||
const units = ['B', 'KB', 'MB', 'GB', 'TB']
|
|
||||||
let size = bytes
|
|
||||||
let unitIndex = 0
|
|
||||||
|
|
||||||
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
||||||
size /= 1024
|
|
||||||
unitIndex++
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${size.toFixed(1)} ${units[unitIndex]}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -55,14 +55,14 @@ export {
|
||||||
} from './config/index.js'
|
} from './config/index.js'
|
||||||
|
|
||||||
// Export Neural Import (AI data understanding)
|
// Export Neural Import (AI data understanding)
|
||||||
export { NeuralImport } from './cortex/neuralImport.js'
|
export { NeuralImport } from './neural/neuralImport.js'
|
||||||
export type {
|
export type {
|
||||||
NeuralAnalysisResult,
|
NeuralAnalysisResult,
|
||||||
DetectedEntity,
|
DetectedEntity,
|
||||||
DetectedRelationship,
|
DetectedRelationship,
|
||||||
NeuralInsight,
|
NeuralInsight,
|
||||||
NeuralImportOptions
|
NeuralImportOptions
|
||||||
} from './cortex/neuralImport.js'
|
} from './neural/neuralImport.js'
|
||||||
|
|
||||||
// Export Neural Entity Extraction
|
// Export Neural Entity Extraction
|
||||||
export { NeuralEntityExtractor } from './neural/entityExtractor.js'
|
export { NeuralEntityExtractor } from './neural/entityExtractor.js'
|
||||||
|
|
@ -126,8 +126,6 @@ import {
|
||||||
|
|
||||||
// Chat system removed - was returning fake responses
|
// Chat system removed - was returning fake responses
|
||||||
|
|
||||||
// Export Cortex CLI functionality - commented out for core MIT build
|
|
||||||
// export { Cortex } from './cortex/cortex.js'
|
|
||||||
|
|
||||||
// Export performance and optimization utilities
|
// Export performance and optimization utilities
|
||||||
import {
|
import {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue