mira-consciousness
Version:
Memory & Intelligence Retention Archive - Preserving The Spark
153 lines • 6.75 kB
JavaScript
import chalk from 'chalk';
import ora from 'ora';
import { getDirectPythonInterface } from '../core/DirectPythonInterface.js';
import fs from 'fs-extra';
import * as path from 'path';
export async function exportCommand(options) {
const spinner = ora('Exporting MIRA memory data...').start();
try {
const pythonInterface = getDirectPythonInterface();
const memoryDir = process.env.MIRA_RESOLVED_MEMORY_DIR || process.cwd() + '/.mira';
// Collect all exportable data
spinner.text = 'Collecting memories...';
const memories = await pythonInterface.recallMemories('');
spinner.text = 'Collecting statistics...';
const stats = await pythonInterface.getStats();
spinner.text = 'Collecting identity...';
const identity = await pythonInterface.getIdentity();
// Read file-based data
spinner.text = 'Reading stored files...';
const fileData = await collectFileData(memoryDir);
const exportData = {
export_info: {
timestamp: new Date().toISOString(),
version: '1.0',
format: options.format || 'json'
},
system: identity.identity || {},
memories: memories.memories || [],
stats: stats.stats || {},
files: fileData
};
// Format and save the export
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const defaultFilename = `mira-export-${timestamp}.${options.format === 'csv' ? 'csv' : 'json'}`;
const outputPath = options.output || defaultFilename;
spinner.text = 'Writing export file...';
if (options.format === 'csv') {
const csvContent = convertToCSV(exportData);
await fs.writeFile(outputPath, csvContent);
}
else {
await fs.writeFile(outputPath, JSON.stringify(exportData, null, 2));
}
// Log the export
const reportsDir = path.join(memoryDir, 'reports');
await fs.ensureDir(reportsDir);
const exportLogEntry = {
timestamp: new Date().toISOString(),
type: 'export',
format: options.format || 'json',
output_file: outputPath,
memories_count: exportData.memories.length,
files_count: Object.keys(exportData.files).length
};
const exportLogFile = path.join(reportsDir, 'generated_reports.jsonl');
await fs.appendFile(exportLogFile, JSON.stringify(exportLogEntry) + '\n');
spinner.succeed(chalk.green(`Export completed: ${outputPath}`));
console.log(chalk.cyan('\n📦 Export Summary:'));
console.log(chalk.white(` Format: ${options.format || 'json'}`));
console.log(chalk.white(` Memories: ${exportData.memories.length}`));
console.log(chalk.white(` File data: ${Object.keys(exportData.files).length} directories`));
console.log(chalk.white(` Size: ${(await fs.stat(outputPath)).size} bytes`));
}
catch (error) {
spinner.fail('Export failed');
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
process.exit(1);
}
}
async function collectFileData(memoryDir) {
const fileData = {};
try {
const subdirs = await fs.readdir(memoryDir);
for (const subdir of subdirs) {
const subdirPath = path.join(memoryDir, subdir);
const stat = await fs.stat(subdirPath);
if (stat.isDirectory()) {
try {
const files = await fs.readdir(subdirPath);
fileData[subdir] = [];
for (const file of files) {
const filePath = path.join(subdirPath, file);
const fileStat = await fs.stat(filePath);
if (fileStat.isFile() && file.endsWith('.jsonl')) {
// Read JSONL files
const content = await fs.readFile(filePath, 'utf-8');
const lines = content.trim().split('\n').filter(line => line.trim());
const entries = lines.map(line => {
try {
return JSON.parse(line);
}
catch {
return { raw: line };
}
});
fileData[subdir].push({
file: file,
type: 'jsonl',
entries: entries
});
}
else if (fileStat.isFile() && file.endsWith('.json')) {
// Read JSON files
try {
const content = await fs.readJson(filePath);
fileData[subdir].push({
file: file,
type: 'json',
content: content
});
}
catch {
// Skip malformed JSON
}
}
}
}
catch {
// Skip directories that can't be read
}
}
}
}
catch (error) {
// Return empty if can't read memory directory
}
return fileData;
}
function convertToCSV(data) {
const lines = ['Type,Timestamp,Content,Extra'];
// Add memories
if (data.memories && Array.isArray(data.memories)) {
data.memories.forEach((memory) => {
const content = (memory.content || '').replace(/"/g, '""');
lines.push(`memory,${memory.timestamp || ''},${content},${memory.score || ''}`);
});
}
// Add file data
Object.entries(data.files).forEach(([dirName, files]) => {
if (Array.isArray(files)) {
files.forEach((fileData) => {
if (fileData.entries && Array.isArray(fileData.entries)) {
fileData.entries.forEach((entry) => {
const content = (entry.content || entry.query || JSON.stringify(entry)).replace(/"/g, '""');
lines.push(`${dirName},${entry.timestamp || ''},${content},${fileData.file}`);
});
}
});
}
});
return lines.join('\n');
}
//# sourceMappingURL=export.js.map