can-algorithm
Version:
Cortex Algorithm Numeral - Intelligent development automation tool
219 lines (182 loc) • 7.11 kB
JavaScript
import { promises as fs } from 'fs';
import path from 'path';
import crypto from 'crypto';
import { encrypt, decrypt } from '../lib/encryption.js';
import { validateLicense } from './license.js';
import axios from 'axios';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const CORTEX_API = 'http://localhost:3001/cortex';
const ESP_API = 'http://localhost:3002/esp';
let activeProcesses = new Map();
export async function verifyLicense() {
try {
const configPath = path.join(process.cwd(), '.can', '.config.encrypted');
const configData = await fs.readFile(configPath, 'utf8');
const config = JSON.parse(decrypt(configData));
return await validateLicense(config.license_key);
} catch (error) {
return { valid: false };
}
}
export async function checkProtection() {
const protectionFile = path.join(process.cwd(), '.can', '.protection');
try {
const data = await fs.readFile(protectionFile, 'utf8');
const hash = crypto.createHash('sha256').update('can-algorithm-protection').digest('hex');
return { valid: data === hash };
} catch {
return { valid: false };
}
}
export async function scanProject() {
const results = {
project_info: {
total_files: 0,
total_size: 0,
languages: new Set(),
frameworks: []
},
file_details: []
};
async function scanDir(dir) {
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.name === 'node_modules' || entry.name === '.git') continue;
if (entry.isDirectory()) {
await scanDir(fullPath);
} else {
const stats = await fs.stat(fullPath);
const ext = path.extname(entry.name);
results.project_info.total_files++;
results.project_info.total_size += stats.size;
if (ext) results.project_info.languages.add(ext);
const content = await fs.readFile(fullPath, 'utf8').catch(() => '');
const lines = content.split('\n').length;
results.file_details.push({
path: fullPath,
type: ext,
size: `${(stats.size / 1024).toFixed(2)} KB`,
lines: lines,
last_modified: stats.mtime
});
}
}
}
await scanDir(process.cwd());
results.project_info.languages = Array.from(results.project_info.languages);
results.project_info.total_size = `${(results.project_info.total_size / (1024 * 1024)).toFixed(2)} MB`;
return results;
}
export async function processAsk(request) {
const config = await getConfig();
const response = await axios.post(`${CORTEX_API}/ask`, {
request: request,
context: await scanProject(),
license_key: config.license_key,
language: 'en'
});
if (response.data.action) {
await executeAction(response.data.action);
}
return response.data.message;
}
export async function processProject(request) {
const taskId = crypto.randomUUID();
const config = await getConfig();
activeProcesses.set(taskId, {
type: 'project',
request: request,
status: 'initializing',
started: new Date()
});
const response = await axios.post(`${CORTEX_API}/project`, {
request: request,
context: await scanProject(),
license_key: config.license_key,
task_id: taskId
});
activeProcesses.set(taskId, {
...activeProcesses.get(taskId),
status: 'processing',
estimated_time: response.data.estimated_time
});
pollTaskStatus(taskId);
console.log(`Task ${taskId} started. Check status with 'can status'`);
}
async function pollTaskStatus(taskId) {
const interval = setInterval(async () => {
try {
const response = await axios.get(`${CORTEX_API}/task/${taskId}`);
if (response.data.status === 'completed') {
clearInterval(interval);
await executeProjectActions(response.data.actions);
activeProcesses.delete(taskId);
} else if (response.data.status === 'failed') {
clearInterval(interval);
activeProcesses.delete(taskId);
}
} catch (error) {
console.error('Task polling error:', error.message);
}
}, 30000);
}
async function executeAction(action) {
switch (action.type) {
case 'create_file':
await fs.mkdir(path.dirname(action.path), { recursive: true });
await fs.writeFile(action.path, action.content);
break;
case 'modify_file':
const content = await fs.readFile(action.path, 'utf8');
const newContent = content.replace(action.search, action.replace);
await fs.writeFile(action.path, newContent);
break;
case 'rename_file':
await fs.rename(action.oldPath, action.newPath);
break;
case 'delete_file':
await fs.unlink(action.path);
break;
}
}
async function executeProjectActions(actions) {
for (const action of actions) {
await executeAction(action);
}
}
export async function cryptFile(filePath) {
const content = await fs.readFile(filePath, 'utf8');
const encrypted = encrypt(content);
await fs.writeFile(`${filePath}.encrypted`, encrypted);
console.log(`File encrypted: ${filePath}.encrypted`);
}
export async function executeCustom(id) {
const config = await getConfig();
if (config.custom_commands && config.custom_commands[id]) {
await executeAction(config.custom_commands[id]);
} else {
console.error('Custom command not found');
}
}
export async function getStatus() {
const tasks = Array.from(activeProcesses.entries()).map(([id, task]) => ({
id: id,
...task,
duration: `${Math.round((new Date() - task.started) / 60000)} minutes`
}));
return {
active_tasks: tasks.length,
tasks: tasks,
system_status: 'healthy',
protection: await checkProtection()
};
}
async function getConfig() {
const configPath = path.join(process.cwd(), '.can', '.config.encrypted');
const configData = await fs.readFile(configPath, 'utf8');
return JSON.parse(decrypt(configData));
}