UNPKG

trace.ai-cli

Version:

A powerful AI-powered CLI tool

652 lines (564 loc) 28.4 kB
const fetch = require('node-fetch'); const { encryptData, decryptData } = require('../utils/encryption'); const { getSystemInfo, formatBytes } = require('./systemInfoService'); // Mode selection helpers function getMode(mode) { switch (Number(mode)) { case 1: // Fast return 'fast'; case 2: // Balanced return 'balance'; case 3: // Think return 'think'; default: return 'balance'; } } /** * Use AI to determine what system information is being requested * @param {string} prompt - The user's prompt * @param {Object} basicInfo - Basic system information for context * @returns {Object} Object containing the determined query */ async function determineSystemInfoQuery(prompt, basicInfo) { try { // Create a more specific prompt for the AI to analyze the user's query const currentTimestamp = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, ''); // Format YYYY-MM-DD HH:MM:SS const analysisPrompt = `Current Date/Time: ${currentTimestamp} UTC User: ${basicInfo.user} Analyze this user query about system information: "${prompt}" Determine which categories of system information the user is asking about. Respond with one or more of these exact categories separated by spaces: - basic (for OS, platform, architecture, hostname, manufacturer, model, uptime info) - cpu (for processor, cores, speed, load, temperature, performance info) - memory (for RAM, swap, memory usage, available memory info) - disk (for storage, disk space, drives, file systems, partition info) - network (for network interfaces, IP addresses, connections, wifi, bandwidth info) - process (for running processes, services, applications, resource usage info) - environment (for environment variables, user info, shell info, system config) - all (for complete comprehensive system information) Examples: "What's my CPU usage?" -> cpu "How much RAM do I have?" -> memory "Show me my IP address" -> network "What processes are running?" -> process "System overview" -> basic "Complete system info" -> all "CPU and memory info" -> cpu memory "Network and disk status" -> network disk Only respond with the category names, nothing else. Be precise and focus on what the user actually needs.`; // Use AI to analyze the query with balanced mode const mode = getMode(2); // Balanced by default try { const response = await fetch('https://traceai.dukeindustries7.workers.dev/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: encryptData({ a: mode, q: analysisPrompt, i: [], c: JSON.stringify({ basicInfo, timestamp: currentTimestamp, user: basicInfo.user }) }) }); const text = await response.text(); const decrypted = decryptData(text); const responses = [decrypted]; // Filter out null responses and extract valid text const validResponses = responses .filter(r => r && r.text && typeof r.text === 'string') .map(r => r.text.toLowerCase().trim()); // Analyze responses to determine categories let categories = new Set(); const validCategories = ['basic', 'cpu', 'memory', 'disk', 'network', 'process', 'environment', 'all']; if (validResponses.length > 0) { // Process each response and count category occurrences const categoryCount = {}; for (const response of validResponses) { const words = response.split(/\s+/); for (const word of words) { if (validCategories.includes(word)) { categoryCount[word] = (categoryCount[word] || 0) + 1; categories.add(word); } } } // If we found 'all', that takes precedence if (categories.has('all')) { return { query: 'all' }; } // If we have valid categories, use the most commonly mentioned ones if (categories.size > 0) { // Sort categories by frequency and take top ones const sortedCategories = Object.entries(categoryCount) .sort(([, a], [, b]) => b - a) .map(([category]) => category); const query = sortedCategories.join(' '); return { query }; } } } catch (e) { // If API call fails, fall through to keyword matching } // Fallback: use keyword matching if AI didn't provide valid responses const fallbackCategories = determineCategoriesByKeywords(prompt); return { query: fallbackCategories }; } catch (error) { // Final fallback to basic info return { query: 'basic' }; } } /** * Fallback function to determine categories using keyword matching * @param {string} prompt - The user's prompt * @returns {string} Space-separated categories */ function determineCategoriesByKeywords(prompt) { const lowerPrompt = prompt.toLowerCase(); const categories = new Set(); // Define comprehensive keyword patterns for each category const patterns = { cpu: [ 'cpu', 'processor', 'core', 'thread', 'clock', 'speed', 'ghz', 'mhz', 'load', 'usage', 'temperature', 'intel', 'amd', 'arm', 'performance', 'benchmark', 'processing', 'compute', 'cores', 'threads', 'frequency' ], memory: [ 'memory', 'ram', 'swap', 'heap', 'free', 'available', 'used', 'total', 'dram', 'dimm', 'stick', 'module', 'allocation', 'buffer', 'cache', 'virtual memory', 'physical memory', 'memory usage' ], disk: [ 'disk', 'drive', 'storage', 'space', 'filesystem', 'mount', 'partition', 'volume', 'hdd', 'ssd', 'nvme', 'capacity', 'free space', 'used space', 'hard drive', 'solid state', 'storage device', 'file system' ], network: [ 'network', 'internet', 'wifi', 'ip', 'address', 'connection', 'interface', 'ethernet', 'wireless', 'lan', 'wan', 'dns', 'gateway', 'router', 'subnet', 'bandwidth', 'latency', 'ping', 'download', 'upload', 'mac address' ], process: [ 'process', 'running', 'task', 'application', 'service', 'pid', 'program', 'app', 'daemon', 'thread', 'job', 'kill', 'terminate', 'processes', 'services', 'applications', 'background', 'foreground' ], environment: [ 'environment', 'env', 'variable', 'path', 'user', 'shell', 'config', 'terminal', 'console', 'profile', 'configuration', 'setting', 'preference', 'login', 'session', 'account', 'variables' ], basic: [ 'system', 'os', 'platform', 'version', 'architecture', 'hostname', 'machine', 'overview', 'info', 'information', 'details', 'specs', 'specification', 'operating system', 'computer', 'device', 'hardware' ] }; // Check for 'all' keywords first const allKeywords = ['all', 'everything', 'complete', 'full', 'entire', 'comprehensive']; if (allKeywords.some(keyword => lowerPrompt.includes(keyword))) { return 'all'; } // Check each category and count matches const categoryMatches = {}; for (const [category, keywords] of Object.entries(patterns)) { const matches = keywords.filter(keyword => lowerPrompt.includes(keyword)); if (matches.length > 0) { categories.add(category); categoryMatches[category] = matches; } } // If no categories matched, default to basic if (categories.size === 0) { categories.add('basic'); } const result = Array.from(categories).join(' '); return result; } /** * Format system information into a readable response using AI * @param {Object} sysInfo - System information object * @param {string} prompt - The original prompt * @returns {string} Formatted response */ async function formatSystemInfoResponse(sysInfo, prompt) { try { // Check if we have any system information const hasInfo = Object.keys(sysInfo).length > 0; if (!hasInfo) { return getHelpMessage(prompt); } // Use AI to format the response based on the user's specific question const formattingPrompt = `Current Date/Time: 2025-07-09 10:45:40 UTC User: m0v0dga_walmart The user asked: "${prompt}" Here is the system information that was gathered: ${JSON.stringify(sysInfo, null, 2)} Please format this system information into a clear, readable response that directly answers the user's question. Focus on the most relevant information for their query. Formatting Guidelines: - Start with a brief intro addressing their specific question - Use bullet points and clear sections for organization - Include relevant technical details but keep it understandable - Use appropriate emojis for visual appeal: 💻 for CPU/Processor info 🧠 for Memory/RAM info 💾 for Disk/Storage info 🌐 for Network/Internet info ⚙️ for Process/Service info 🔧 for Environment/Config info 📱 for Basic/System info - Format bytes/numbers in human-readable format - Only include information that's directly relevant to their question - Keep it concise but comprehensive - Add context about what the numbers mean if helpful - Include timestamp: "System information as of 2025-07-09 10:45:40 UTC" Make the response helpful and easy to understand for the user.`; try { const response = await fetch('https://traceai.dukeindustries7.workers.dev/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: encryptData({ a: getMode(2), // Use balanced mode for formatting q: formattingPrompt, i: [], c: JSON.stringify({ timestamp: '2025-07-09 10:45:40', user: 'm0v0dga_walmart', originalPrompt: prompt }) }) }); const encryptedResult = await response.text(); const decryptedResult = decryptData(encryptedResult); if (decryptedResult.text && typeof decryptedResult.text === 'string') { return decryptedResult.text; } } catch (aiError) { } // Fallback to manual formatting if AI fails return formatSystemInfoManually(sysInfo, prompt); } catch (error) { // Fallback to manual formatting return formatSystemInfoManually(sysInfo, prompt); } } /** * Manual formatting fallback with enhanced output * @param {Object} sysInfo - System information object * @param {string} prompt - The original prompt * @returns {string} Formatted response */ function formatSystemInfoManually(sysInfo, prompt) { let response = `Here's the system information you requested:\n\n`; response += `*System information as of 2025-07-09 10:45:40 UTC*\n\n`; if (sysInfo.basic) { const basic = sysInfo.basic; response += `📱 **System Overview**\n`; response += `- Platform: ${basic.platform || 'Unknown'} (${basic.type || 'Unknown'} ${basic.release || 'Unknown'})\n`; response += `- Architecture: ${basic.arch || 'Unknown'}\n`; response += `- Hostname: ${basic.hostname || 'Unknown'}\n`; if (basic.manufacturer) response += `- Manufacturer: ${basic.manufacturer}\n`; if (basic.model) response += `- Model: ${basic.model}\n`; if (basic.distro) response += `- Distribution: ${basic.distro}\n`; if (basic.kernel) response += `- Kernel: ${basic.kernel}\n`; const uptimeHours = Math.floor((basic.uptime || 0) / 3600); const uptimeMinutes = Math.floor(((basic.uptime || 0) % 3600) / 60); response += `- Uptime: ${uptimeHours} hours ${uptimeMinutes} minutes\n`; if (basic.loadAvg && Array.isArray(basic.loadAvg)) { response += `- Load Average: ${basic.loadAvg.map(load => load.toFixed(2)).join(', ')}\n`; } response += `\n`; } if (sysInfo.cpu) { const cpu = sysInfo.cpu; response += `💻 **CPU Information**\n`; response += `- Model: ${cpu.model || cpu.brand || 'Unknown'}\n`; if (cpu.manufacturer) response += `- Manufacturer: ${cpu.manufacturer}\n`; response += `- Cores: ${cpu.cores || 'Unknown'}\n`; if (cpu.physicalCores) response += `- Physical Cores: ${cpu.physicalCores}\n`; if (cpu.speed) response += `- Base Speed: ${cpu.speed} MHz\n`; if (cpu.speedMax) response += `- Max Speed: ${cpu.speedMax} MHz\n`; if (cpu.load) { if (cpu.load.currentLoad !== undefined) response += `- Current Load: ${cpu.load.currentLoad.toFixed(2)}%\n`; if (cpu.load.currentLoadUser !== undefined) response += `- User Load: ${cpu.load.currentLoadUser.toFixed(2)}%\n`; if (cpu.load.currentLoadSystem !== undefined) response += `- System Load: ${cpu.load.currentLoadSystem.toFixed(2)}%\n`; } if (cpu.temperature && cpu.temperature.main) { response += `- Temperature: ${cpu.temperature.main}°C\n`; } if (cpu.loadAvg && Array.isArray(cpu.loadAvg)) { response += `- Load Average: ${cpu.loadAvg.map(load => load.toFixed(2)).join(', ')}\n`; } response += `\n`; } if (sysInfo.memory) { const memory = sysInfo.memory; response += `🧠 **Memory Information**\n`; response += `- Total: ${memory.total || 'Unknown'}\n`; response += `- Used: ${memory.used || 'Unknown'} (${memory.usagePercent || 'Unknown'})\n`; response += `- Free: ${memory.free || 'Unknown'}\n`; if (memory.available) response += `- Available: ${memory.available}\n`; if (memory.active) response += `- Active: ${memory.active}\n`; if (memory.swap) { response += `- Swap Total: ${memory.swap.total || 'Unknown'}\n`; response += `- Swap Used: ${memory.swap.used || 'Unknown'} (${memory.swap.usagePercent || 'Unknown'})\n`; response += `- Swap Free: ${memory.swap.free || 'Unknown'}\n`; } if (memory.layout && Array.isArray(memory.layout) && memory.layout.length > 0) { response += `- Memory Modules: ${memory.layout.length} installed\n`; memory.layout.forEach((module, index) => { if (module.size) { response += ` - Module ${index + 1}: ${module.size}`; if (module.type) response += ` ${module.type}`; if (module.clockSpeed) response += ` @ ${module.clockSpeed} MHz`; response += `\n`; } }); } response += `\n`; } if (sysInfo.disk) { response += `💾 **Disk Information**\n`; if (sysInfo.disk.fsSize && Array.isArray(sysInfo.disk.fsSize)) { response += `- File Systems:\n`; sysInfo.disk.fsSize.forEach(fs => { response += ` - ${fs.fs} (${fs.type || 'Unknown'}):\n`; response += ` - Mount: ${fs.mount || 'Unknown'}\n`; response += ` - Size: ${fs.size || 'Unknown'}\n`; response += ` - Used: ${fs.used || 'Unknown'} (${fs.usagePercent || 'Unknown'})\n`; response += ` - Available: ${fs.available || 'Unknown'}\n`; }); } else if (Array.isArray(sysInfo.disk)) { // Legacy Windows format sysInfo.disk.forEach(disk => { response += `- Drive ${disk.drive}:\n`; response += ` - Size: ${disk.size}\n`; response += ` - Used: ${disk.used} (${disk.usagePercent})\n`; response += ` - Free: ${disk.free}\n`; }); } else if (sysInfo.disk.filesystem) { // Legacy Unix format response += `- Filesystem: ${sysInfo.disk.filesystem}\n`; response += `- Size: ${sysInfo.disk.size}\n`; response += `- Used: ${sysInfo.disk.used} (${sysInfo.disk.usagePercent})\n`; response += `- Available: ${sysInfo.disk.available}\n`; response += `- Mounted on: ${sysInfo.disk.mountedOn}\n`; } else if (sysInfo.disk.error) { response += `- Error retrieving disk information: ${sysInfo.disk.error}\n`; } if (sysInfo.disk.diskLayout && Array.isArray(sysInfo.disk.diskLayout)) { response += `- Physical Disks: ${sysInfo.disk.diskLayout.length} detected\n`; sysInfo.disk.diskLayout.forEach((disk, index) => { response += ` - Disk ${index + 1}: ${disk.name || disk.device}\n`; if (disk.size) response += ` - Size: ${disk.size}\n`; if (disk.type) response += ` - Type: ${disk.type}\n`; if (disk.vendor) response += ` - Vendor: ${disk.vendor}\n`; }); } response += `\n`; } if (sysInfo.network) { response += `🌐 **Network Information**\n`; if (sysInfo.network.publicIp && sysInfo.network.publicIp !== 'Not available') { response += `- Public IP: ${sysInfo.network.publicIp}\n`; } if (sysInfo.network.interfaces && Array.isArray(sysInfo.network.interfaces)) { const activeInterfaces = sysInfo.network.interfaces.filter(iface => !iface.internal); if (activeInterfaces.length > 0) { response += `- Network Interfaces:\n`; activeInterfaces.forEach(iface => { response += ` - ${iface.interface || iface.ifaceName}:\n`; if (iface.ip4) response += ` - IPv4: ${iface.ip4}\n`; if (iface.ip6) response += ` - IPv6: ${iface.ip6}\n`; if (iface.mac) response += ` - MAC: ${iface.mac}\n`; if (iface.speed && iface.speed !== 'N/A') response += ` - Speed: ${iface.speed}\n`; if (iface.operstate) response += ` - State: ${iface.operstate}\n`; }); } } else if (Array.isArray(sysInfo.network)) { // Legacy format const externalInterfaces = sysInfo.network.filter(net => !net.internal); if (externalInterfaces.length > 0) { response += `- Network Interfaces:\n`; externalInterfaces.forEach(net => { response += ` - ${net.interface}: ${net.address}\n`; response += ` - Netmask: ${net.netmask}\n`; response += ` - MAC: ${net.mac}\n`; }); } } if (sysInfo.network.internetLatency && sysInfo.network.internetLatency !== 'N/A ms') { response += `- Internet Connectivity: ${sysInfo.network.internetLatency}\n`; } if (sysInfo.network.connections && typeof sysInfo.network.connections === 'number') { response += `- Active Connections: ${sysInfo.network.connections}\n`; } response += `\n`; } if (sysInfo.process) { response += `⚙️ **Process Information**\n`; if (sysInfo.process.currentProcess) { const current = sysInfo.process.currentProcess; response += `- Current Process:\n`; response += ` - PID: ${current.pid || 'Unknown'}\n`; if (current.name) response += ` - Name: ${current.name}\n`; if (current.cpu) response += ` - CPU Usage: ${current.cpu}\n`; if (current.mem) response += ` - Memory Usage: ${current.mem}\n`; if (current.uptime) response += ` - Uptime: ${Math.floor(current.uptime / 60)} minutes\n`; } else { // Legacy format response += `- Process ID: ${sysInfo.process.pid || 'Unknown'}\n`; if (sysInfo.process.version) response += `- Node.js Version: ${sysInfo.process.version}\n`; if (sysInfo.process.cwd) response += `- Working Directory: ${sysInfo.process.cwd}\n`; if (sysInfo.process.memoryUsage && sysInfo.process.memoryUsage.rss) { response += `- Memory Usage: ${Math.round(sysInfo.process.memoryUsage.rss / (1024 * 1024))} MB\n`; } } if (sysInfo.process.summary) { const summary = sysInfo.process.summary; response += `- Process Summary:\n`; if (summary.all) response += ` - Total: ${summary.all}\n`; if (summary.running) response += ` - Running: ${summary.running}\n`; if (summary.sleeping) response += ` - Sleeping: ${summary.sleeping}\n`; if (summary.blocked) response += ` - Blocked: ${summary.blocked}\n`; } if (sysInfo.process.topProcesses && Array.isArray(sysInfo.process.topProcesses) && sysInfo.process.topProcesses.length > 0) { response += `- Top Processes (by CPU):\n`; sysInfo.process.topProcesses.slice(0, 5).forEach((proc, index) => { response += ` - ${index + 1}: ${proc.name} (PID: ${proc.pid}) - CPU: ${proc.cpu}, Memory: ${proc.mem}\n`; }); } response += `\n`; } if (sysInfo.environment) { response += `🔧 **Environment Information**\n`; if (sysInfo.environment.variables) { const envVars = sysInfo.environment.variables; response += `- Key Environment Variables:\n`; const importantVars = ['PATH', 'HOME', 'USER', 'SHELL', 'LANG', 'TERM']; importantVars.forEach(varName => { if (envVars[varName]) { response += ` - ${varName}: ${envVars[varName]}\n`; } }); const otherVars = Object.keys(envVars).filter(key => !importantVars.includes(key)); if (otherVars.length > 0) { response += ` - Other variables: ${otherVars.length} additional environment variables\n`; } } if (sysInfo.environment.users && Array.isArray(sysInfo.environment.users) && sysInfo.environment.users.length > 0) { response += `- Active Users: ${sysInfo.environment.users.length}\n`; } response += `\n`; } response; return response; } /** * Get help message when no system info is available * @param {string} prompt - The original prompt * @returns {string} Help message */ function getHelpMessage(prompt) { return `I couldn't find specific system information for your query: "${prompt}"\n\n` + `*Available system information queries:*\n\n` + `📱 **Basic System Info:**\n` + `- "What's my system info?" - Platform, OS, architecture\n` + `- "System overview" - Complete basic information\n\n` + `💻 **CPU Information:**\n` + `- "What's my CPU usage?" - Processor load and performance\n` + `- "Show me processor info" - CPU specifications\n\n` + `🧠 **Memory Information:**\n` + `- "How much RAM do I have?" - Memory specifications\n` + `- "Memory usage" - Current memory utilization\n\n` + `💾 **Disk Information:**\n` + `- "How much disk space?" - Storage capacity and usage\n` + `- "Storage info" - Disk and filesystem details\n\n` + `🌐 **Network Information:**\n` + `- "What's my IP address?" - Network interface details\n` + `- "Network status" - Connection and interface info\n\n` + `⚙️ **Process Information:**\n` + `- "What processes are running?" - Active processes and services\n` + `- "Process info" - System process details\n\n` + `🔧 **Environment Variables:**\n` + `- "Show environment variables" - System configuration\n` + `- "User info" - User and shell information\n\n` + `📊 **Complete Information:**\n` + `- "Show me all system information" - Everything available\n` + `- "Complete system report" - Comprehensive overview\n\n` + `*System information as of 2025-07-09 10:45:40 UTC*\n` + `*User: m0v0dga_walmart*`; } async function processWithAI(prompt, context = '', mode = 2) { try { // Enhanced system query detection - but EXCLUDE file/folder analysis prompts const systemKeywords = [ 'system', 'cpu', 'memory', 'ram', 'disk', 'network', 'ip', 'process', 'environment', 'hardware', 'computer', 'machine', 'specs', 'info', 'information', 'status', 'usage', 'performance', 'storage', 'processor' ]; // Check if this is a file/folder analysis (these should NOT trigger system info) const isFileAnalysis = prompt.includes('File:') || prompt.includes('Analyze this') || prompt.includes('code file') || prompt.includes('Content:') || prompt.includes('User Question:'); const isSystemQuery = !isFileAnalysis && ( systemKeywords.some(keyword => prompt.toLowerCase().includes(keyword)) || prompt.toLowerCase().startsWith('get system information') || prompt.toLowerCase().includes('/system') ); if (isSystemQuery) { try { // First get basic system info to provide context const basicInfo = await getSystemInfo('basic'); // Use AI to determine what system information is being requested const aiResponse = await determineSystemInfoQuery(prompt, basicInfo); // Get the specific system information based on AI's determination const systemInfo = await getSystemInfo(aiResponse.query); // Format the response using AI const formattedResponse = await formatSystemInfoResponse(systemInfo, prompt); return formattedResponse; } catch (sysError) { console.error(`[${new Date().toISOString()}] ❌ System info error:`, sysError.message); // If system info fails, fall back to AI processing return `I encountered an error retrieving system information: ${sysError.message}\n\nPlease try a more specific query or check the system status.`; } } // Regular AI processing for non-system queries const selectedMode = getMode(mode); // Use selected mode try { const response = await fetch('https://traceai.dukeindustries7.workers.dev/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: encryptData({ a: selectedMode, q: prompt, i: [], c: context }) }); const text = await response.text(); const result = decryptData(text); // The worker now handles orchestration internally // It runs multiple models and synthesizes the response if (result && result.text && typeof result.text === 'string') { return result.text; } else { return 'I apologize, but I was unable to process your request at this time. Please try again.'; } } catch (error) { return 'I apologize, but I was unable to process your request at this time. Please try again.'; } } catch (error) { console.error(`[${new Date().toISOString()}] ❌ Processing error:`, error.message); throw error; } } module.exports = { processWithAI, determineSystemInfoQuery, formatSystemInfoResponse };