UNPKG

trace.ai-cli

Version:

A powerful AI-powered CLI tool

957 lines (846 loc) 38.7 kB
const os = require('os'); const { execSync } = require('child_process'); const si = require('systeminformation'); /** * Get basic system information * @returns {Object} System information object */ async function getBasicSystemInfo() { try { const [osInfo, system, time] = await Promise.all([ si.osInfo().catch(() => ({})), si.system().catch(() => ({})), si.time().catch(() => ({})) ]); const basicInfo = { platform: os.platform(), type: os.type(), distro: osInfo.distro || 'Unknown', release: os.release(), codename: osInfo.codename || '', kernel: osInfo.kernel || os.release(), arch: os.arch(), hostname: os.hostname(), uptime: os.uptime(), loadAvg: os.loadavg(), manufacturer: system.manufacturer || 'Unknown', model: system.model || 'Unknown', serial: system.serial || 'N/A', uuid: system.uuid || 'N/A', sku: system.sku || 'N/A', virtual: system.virtual || false, userInfo: os.userInfo(), tempDir: os.tmpdir(), nodeVersion: process.version, timestamp: new Date().toISOString(), timezone: time.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone }; return basicInfo; } catch (error) { // Fallback to basic OS information return { platform: os.platform(), type: os.type(), release: os.release(), arch: os.arch(), hostname: os.hostname(), uptime: os.uptime(), loadAvg: os.loadavg(), userInfo: os.userInfo(), tempDir: os.tmpdir(), nodeVersion: process.version, timestamp: new Date().toISOString(), error: 'Limited information available due to system restrictions' }; } } /** * Get detailed CPU information * @returns {Object} CPU information */ async function getCpuInfo() { try { const [cpu, cpuCurrentSpeed, cpuTemperature, currentLoad, cpuFlags] = await Promise.all([ si.cpu().catch(() => ({})), si.cpuCurrentSpeed().catch(() => ({})), si.cpuTemperature().catch(() => ({})), si.currentLoad().catch(() => ({})), si.cpuFlags().catch(() => '') ]); const cpuInfo = { manufacturer: cpu.manufacturer || 'Unknown', brand: cpu.brand || 'Unknown', vendor: cpu.vendor || cpu.manufacturer || 'Unknown', family: cpu.family || 'Unknown', model: cpu.model || cpu.brand || 'Unknown', stepping: cpu.stepping || 'Unknown', revision: cpu.revision || 'Unknown', voltage: cpu.voltage || 'Unknown', speed: cpu.speed || 0, speedMin: cpu.speedMin || 0, speedMax: cpu.speedMax || 0, governor: cpu.governor || 'Unknown', cores: cpu.cores || os.cpus().length, physicalCores: cpu.physicalCores || cpu.cores || os.cpus().length, processors: cpu.processors || 1, socket: cpu.socket || 'Unknown', flags: cpuFlags || cpu.flags || 'Unknown', virtualization: cpu.virtualization || false, cache: cpu.cache || {}, currentSpeed: cpuCurrentSpeed.avg || cpuCurrentSpeed.cores || cpu.speed || 0, temperature: cpuTemperature.main || cpuTemperature.max || null, load: { currentLoad: currentLoad.currentLoad || 0, currentLoadUser: currentLoad.currentLoadUser || 0, currentLoadSystem: currentLoad.currentLoadSystem || 0, currentLoadNice: currentLoad.currentLoadNice || 0, currentLoadIdle: currentLoad.currentLoadIdle || 100, currentLoadIrq: currentLoad.currentLoadIrq || 0, rawCurrentLoad: currentLoad.rawCurrentLoad || 0, rawCurrentLoadUser: currentLoad.rawCurrentLoadUser || 0, rawCurrentLoadSystem: currentLoad.rawCurrentLoadSystem || 0, rawCurrentLoadNice: currentLoad.rawCurrentLoadNice || 0, rawCurrentLoadIdle: currentLoad.rawCurrentLoadIdle || 0, rawCurrentLoadIrq: currentLoad.rawCurrentLoadIrq || 0, cpus: currentLoad.cpus || [] }, loadAvg: os.loadavg(), timestamp: new Date().toISOString() }; return cpuInfo; } catch (error) { // Fallback to basic CPU information const cpus = os.cpus(); return { model: cpus[0]?.model || 'Unknown', speed: cpus[0]?.speed || 0, cores: cpus.length, loadAvg: os.loadavg(), load: { currentLoad: 0, currentLoadUser: 0, currentLoadSystem: 0, currentLoadIdle: 100 }, timestamp: new Date().toISOString(), error: 'Limited CPU information available' }; } } /** * Get memory information in a human-readable format * @returns {Object} Memory information */ async function getMemoryInfo() { try { const [mem, memLayout] = await Promise.all([ si.mem().catch(() => ({ total: os.totalmem(), free: os.freemem(), used: os.totalmem() - os.freemem() })), si.memLayout().catch(() => []) ]); // Convert to human-readable format const totalMemGB = (mem.total / (1024 * 1024 * 1024)).toFixed(2); const freeMemGB = (mem.free / (1024 * 1024 * 1024)).toFixed(2); const usedMemGB = (mem.used / (1024 * 1024 * 1024)).toFixed(2); const activeMemGB = mem.active ? (mem.active / (1024 * 1024 * 1024)).toFixed(2) : 'N/A'; const availableMemGB = mem.available ? (mem.available / (1024 * 1024 * 1024)).toFixed(2) : freeMemGB; const swapTotalGB = mem.swaptotal ? (mem.swaptotal / (1024 * 1024 * 1024)).toFixed(2) : '0.00'; const swapUsedGB = mem.swapused ? (mem.swapused / (1024 * 1024 * 1024)).toFixed(2) : '0.00'; const swapFreeGB = mem.swapfree ? (mem.swapfree / (1024 * 1024 * 1024)).toFixed(2) : '0.00'; const memoryInfo = { total: `${totalMemGB} GB`, free: `${freeMemGB} GB`, used: `${usedMemGB} GB`, active: `${activeMemGB} GB`, available: `${availableMemGB} GB`, usagePercent: `${((mem.used / mem.total) * 100).toFixed(1)}%`, buffers: mem.buffers ? formatBytes(mem.buffers) : 'N/A', cached: mem.cached ? formatBytes(mem.cached) : 'N/A', slab: mem.slab ? formatBytes(mem.slab) : 'N/A', swapTotal: `${swapTotalGB} GB`, swapUsed: `${swapUsedGB} GB`, swapFree: `${swapFreeGB} GB`, swapUsagePercent: mem.swaptotal > 0 ? `${((mem.swapused / mem.swaptotal) * 100).toFixed(1)}%` : '0.0%', layout: memLayout.map(module => ({ size: module.size ? formatBytes(module.size) : 'Unknown', bank: module.bank || 'Unknown', type: module.type || 'Unknown', clockSpeed: module.clockSpeed ? `${module.clockSpeed} MHz` : 'Unknown', formFactor: module.formFactor || 'Unknown', manufacturer: module.manufacturer || 'Unknown', partNum: module.partNum || 'Unknown', serialNum: module.serialNum || 'Unknown', voltageConfigured: module.voltageConfigured ? `${module.voltageConfigured} V` : 'Unknown', voltageMin: module.voltageMin ? `${module.voltageMin} V` : 'Unknown', voltageMax: module.voltageMax ? `${module.voltageMax} V` : 'Unknown' })), timestamp: new Date().toISOString() }; return memoryInfo; } catch (error) { // Fallback to basic memory information const totalMemMB = Math.round(os.totalmem() / (1024 * 1024)); const freeMemMB = Math.round(os.freemem() / (1024 * 1024)); const usedMemMB = totalMemMB - freeMemMB; const memUsagePercent = Math.round((usedMemMB / totalMemMB) * 100); return { total: `${(totalMemMB / 1024).toFixed(2)} GB`, free: `${(freeMemMB / 1024).toFixed(2)} GB`, used: `${(usedMemMB / 1024).toFixed(2)} GB`, usagePercent: `${memUsagePercent}%`, timestamp: new Date().toISOString(), error: 'Limited memory information available' }; } } /** * Get disk space information * @returns {Object} Disk information */ async function getDiskInfo() { try { const [fsSize, blockDevices, diskLayout, diskIo] = await Promise.all([ si.fsSize().catch(() => []), si.blockDevices().catch(() => []), si.diskLayout().catch(() => []), si.disksIO().catch(() => ({})) ]); // Format file system sizes const formattedFsSize = fsSize.map(fs => ({ fs: fs.fs || 'Unknown', type: fs.type || 'Unknown', size: fs.size ? formatBytes(fs.size) : 'Unknown', used: fs.used ? formatBytes(fs.used) : 'Unknown', available: fs.available ? formatBytes(fs.available) : 'Unknown', usagePercent: fs.use ? `${fs.use.toFixed(1)}%` : 'Unknown', mount: fs.mount || 'Unknown' })); // Format block devices info const formattedBlockDevices = blockDevices.map(device => ({ name: device.name || 'Unknown', type: device.type || 'Unknown', fsType: device.fstype || 'Unknown', mount: device.mount || 'Unknown', size: device.size ? formatBytes(device.size) : 'Unknown', physical: device.physical || 'Unknown', uuid: device.uuid || 'Unknown', label: device.label || 'Unknown', model: device.model || 'Unknown', serial: device.serial || 'Unknown', removable: device.removable !== undefined ? device.removable : 'Unknown', protocol: device.protocol || 'Unknown' })); // Format disk layout info const formattedDiskLayout = diskLayout.map(disk => ({ device: disk.device || 'Unknown', type: disk.type || 'Unknown', name: disk.name || 'Unknown', vendor: disk.vendor || 'Unknown', size: disk.size ? formatBytes(disk.size) : 'Unknown', bytesPerSector: disk.bytesPerSector || 'Unknown', totalCylinders: disk.totalCylinders || 'Unknown', totalHeads: disk.totalHeads || 'Unknown', totalSectors: disk.totalSectors || 'Unknown', totalTracks: disk.totalTracks || 'Unknown', tracksPerCylinder: disk.tracksPerCylinder || 'Unknown', sectorsPerTrack: disk.sectorsPerTrack || 'Unknown', firmwareRevision: disk.firmwareRevision || 'Unknown', serialNum: disk.serialNum || 'Unknown', interfaceType: disk.interfaceType || 'Unknown', smartStatus: disk.smartStatus || 'Unknown', temperature: disk.temperature || null })); const diskInfo = { fsSize: formattedFsSize, blockDevices: formattedBlockDevices, diskLayout: formattedDiskLayout, io: { rIO: diskIo.rIO || 0, wIO: diskIo.wIO || 0, tIO: diskIo.tIO || 0, rIO_sec: diskIo.rIO_sec || 0, wIO_sec: diskIo.wIO_sec || 0, tIO_sec: diskIo.tIO_sec || 0 }, timestamp: new Date().toISOString() }; return diskInfo; } catch (error) { // Enhanced fallback with better error handling try { const platform = os.platform(); if (platform === 'darwin' || platform === 'linux') { const df = execSync('df -h /', { timeout: 5000 }).toString(); const lines = df.trim().split('\n'); if (lines.length >= 2) { const parts = lines[1].split(/\s+/); return { filesystem: parts[0], size: parts[1], used: parts[2], available: parts[3], usagePercent: parts[4], mountedOn: parts[5], timestamp: new Date().toISOString() }; } } else if (platform === 'win32') { const wmic = execSync('wmic logicaldisk get size,freespace,caption', { timeout: 5000 }).toString(); const lines = wmic.trim().split('\n'); const disks = []; for (let i = 1; i < lines.length; i++) { const parts = lines[i].trim().split(/\s+/); if (parts.length >= 3 && parts[0] && parts[1] && parts[2]) { const caption = parts[0]; const freeSpace = Math.round(parseInt(parts[1]) / (1024 * 1024 * 1024)); const size = Math.round(parseInt(parts[2]) / (1024 * 1024 * 1024)); const used = size - freeSpace; const usagePercent = Math.round((used / size) * 100); disks.push({ drive: caption, size: `${size} GB`, used: `${used} GB`, free: `${freeSpace} GB`, usagePercent: `${usagePercent}%` }); } } return { disks, timestamp: new Date().toISOString() }; } } catch (fallbackError) { } return { error: 'Could not retrieve disk information - system access restricted', timestamp: new Date().toISOString() }; } } /** * Get network information * @returns {Object} Network interfaces and connection information */ async function getNetworkInfo() { try { const [networkInterfaces, networkStats, networkConnections, wifiNetworks, internetSpeed] = await Promise.all([ si.networkInterfaces().catch(() => []), si.networkStats().catch(() => []), si.networkConnections().catch(() => []), si.wifiNetworks().catch(() => []), si.inetChecksite('https://www.google.com').catch(() => ({ ms: null })) ]); // Get public IP address let publicIp = 'Not available'; try { const ipResponse = await fetch('https://api.ipify.org?format=json', { timeout: 5000 }); const ipData = await ipResponse.json(); publicIp = ipData.ip || 'Not available'; } catch (ipError) { } // Format network interfaces const formattedInterfaces = networkInterfaces.map(iface => ({ iface: iface.iface || 'Unknown', ifaceName: iface.ifaceName || iface.iface || 'Unknown', ip4: iface.ip4 || 'None', ip6: iface.ip6 || 'None', mac: iface.mac || 'Unknown', internal: iface.internal || false, virtual: iface.virtual || false, operstate: iface.operstate || 'Unknown', type: iface.type || 'Unknown', duplex: iface.duplex || 'Unknown', speed: iface.speed ? `${iface.speed} Mbps` : 'Unknown', dhcp: iface.dhcp || false, dnsSuffix: iface.dnsSuffix || 'Unknown', ieee8021xAuth: iface.ieee8021xAuth || 'Unknown', ieee8021xState: iface.ieee8021xState || 'Unknown', carrierChanges: iface.carrierChanges || 0 })); // Format network stats const formattedStats = networkStats.map(stat => ({ iface: stat.iface || 'Unknown', operstate: stat.operstate || 'Unknown', rx_bytes: formatBytes(stat.rx_bytes || 0), rx_dropped: stat.rx_dropped || 0, rx_errors: stat.rx_errors || 0, tx_bytes: formatBytes(stat.tx_bytes || 0), tx_dropped: stat.tx_dropped || 0, tx_errors: stat.tx_errors || 0, rx_sec: formatBytes(stat.rx_sec || 0), tx_sec: formatBytes(stat.tx_sec || 0), ms: stat.ms || 0 })); // Format wifi networks const formattedWifiNetworks = wifiNetworks.map(network => ({ ssid: network.ssid || 'Hidden', bssid: network.bssid || 'Unknown', mode: network.mode || 'Unknown', channel: network.channel || 'Unknown', frequency: network.frequency || 'Unknown', signalLevel: network.signalLevel || 'Unknown', quality: network.quality || 'Unknown', security: Array.isArray(network.security) ? network.security : [network.security || 'Unknown'], wpaFlags: network.wpaFlags || 'Unknown', rsnFlags: network.rsnFlags || 'Unknown' })); // Format connections summary const connectionsCount = networkConnections.length || 0; const establishedCount = networkConnections.filter(conn => conn.state === 'ESTABLISHED').length || 0; const listeningCount = networkConnections.filter(conn => conn.state === 'LISTEN').length || 0; const networkInfo = { interfaces: formattedInterfaces, stats: formattedStats, connections: { total: connectionsCount, established: establishedCount, listening: listeningCount, sample: networkConnections.slice(0, 5).map(conn => ({ protocol: conn.protocol || 'Unknown', localAddress: conn.localAddress || 'Unknown', localPort: conn.localPort || 'Unknown', peerAddress: conn.peerAddress || 'Unknown', peerPort: conn.peerPort || 'Unknown', state: conn.state || 'Unknown' })) }, wifiNetworks: formattedWifiNetworks, internetLatency: internetSpeed.ms !== null ? `${internetSpeed.ms} ms` : 'Unknown', publicIp, timestamp: new Date().toISOString() }; return networkInfo; } catch (error) { // Enhanced fallback to basic network information try { const interfaces = os.networkInterfaces(); const result = []; for (const [name, netInterface] of Object.entries(interfaces)) { for (const info of netInterface) { if (info.family === 'IPv4' || info.family === 4) { result.push({ interface: name, address: info.address, netmask: info.netmask, mac: info.mac, internal: info.internal }); } } } return { interfaces: result, timestamp: new Date().toISOString(), error: 'Limited network information available' }; } catch (fallbackError) { return { error: 'Could not retrieve network information', timestamp: new Date().toISOString() }; } } } /** * Format bytes to human-readable format * @param {number} bytes - Bytes to format * @returns {string} Formatted string */ function formatBytes(bytes) { if (bytes === 0 || bytes === null || bytes === undefined) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB']; const i = Math.floor(Math.log(Math.abs(bytes)) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } /** * Get process information * @returns {Object} Process information */ async function getProcessInfo() { try { const [processes, currentProcessLoad, services] = await Promise.all([ si.processes().catch(() => ({ all: 0, running: 0, blocked: 0, sleeping: 0, list: [] })), si.processLoad(process.pid).catch(() => ({})), si.services('*').catch(() => []) ]); // Get current process memory usage const memUsage = process.memoryUsage(); // Format current process info const formattedCurrentProcess = { pid: process.pid, ppid: process.ppid || 'Unknown', title: process.title || 'Node.js Process', name: currentProcessLoad.name || process.title || 'node', cpu: currentProcessLoad.cpu !== undefined ? `${currentProcessLoad.cpu.toFixed(1)}%` : 'Unknown', mem: currentProcessLoad.mem !== undefined ? `${currentProcessLoad.mem.toFixed(1)}%` : 'Unknown', arch: process.arch, platform: process.platform, version: process.version, memoryUsage: { rss: formatBytes(memUsage.rss), heapTotal: formatBytes(memUsage.heapTotal), heapUsed: formatBytes(memUsage.heapUsed), external: formatBytes(memUsage.external), arrayBuffers: formatBytes(memUsage.arrayBuffers || 0) }, uptime: process.uptime(), cwd: process.cwd(), execPath: process.execPath, argv: process.argv, execArgv: process.execArgv }; // Format top processes (limited for performance and privacy) const topProcesses = processes.list ? processes.list .filter(proc => proc.cpu !== undefined && proc.cpu !== null) .sort((a, b) => (b.cpu || 0) - (a.cpu || 0)) .slice(0, 15) .map(proc => ({ pid: proc.pid || 'Unknown', name: proc.name || 'Unknown', cpu: proc.cpu !== undefined ? `${proc.cpu.toFixed(1)}%` : 'Unknown', mem: proc.mem !== undefined ? `${proc.mem.toFixed(1)}%` : 'Unknown', priority: proc.priority || 'Unknown', command: proc.command || 'Unknown', state: proc.state || 'Unknown' })) : []; // Format system services (limited for performance and privacy) const formattedServices = services .slice(0, 15) .map(service => ({ name: service.name || 'Unknown', running: service.running || false, startmode: service.startmode || 'Unknown', pids: Array.isArray(service.pids) ? service.pids : [], state: service.state || 'Unknown' })); const processInfo = { currentProcess: formattedCurrentProcess, summary: { all: processes.all || 0, running: processes.running || 0, blocked: processes.blocked || 0, sleeping: processes.sleeping || 0, unknown: processes.unknown || 0 }, topProcesses, services: formattedServices, timestamp: new Date().toISOString() }; return processInfo; } catch (error) { // Fallback to basic process information const memUsage = process.memoryUsage(); return { currentProcess: { pid: process.pid, ppid: process.ppid || 'Unknown', title: process.title || 'Node.js Process', arch: process.arch, platform: process.platform, version: process.version, versions: process.versions, memoryUsage: { rss: formatBytes(memUsage.rss), heapTotal: formatBytes(memUsage.heapTotal), heapUsed: formatBytes(memUsage.heapUsed), external: formatBytes(memUsage.external) }, uptime: process.uptime(), cwd: process.cwd(), execPath: process.execPath }, timestamp: new Date().toISOString(), error: 'Limited process information available' }; } } /** * Get environment variables and user information (filtered for security) * @returns {Object} Environment variables and user information */ async function getEnvironmentInfo() { try { const [users, shellInfo] = await Promise.all([ si.users().catch(() => []), si.shell().catch(() => ({ available: false, history: [] })) ]); // Get safe environment variables const env = process.env; const safeEnv = {}; // Filter out sensitive information - only include safe environment variables const safeKeys = [ 'PATH', 'LANG', 'TERM', 'SHELL', 'HOME', 'USER', 'LOGNAME', 'TMPDIR', 'TZ', 'EDITOR', 'PAGER', 'LSCOLORS', 'TERM_PROGRAM', 'TERM_PROGRAM_VERSION', 'COLORTERM', 'DISPLAY', 'LC_ALL', 'LC_CTYPE', 'SHLVL', 'PWD', 'XDG_DATA_DIRS', 'XDG_RUNTIME_DIR', 'DESKTOP_SESSION', 'GDMSESSION', 'XDG_CURRENT_DESKTOP', 'XDG_SESSION_TYPE', 'WAYLAND_DISPLAY', 'NODE_VERSION', 'npm_config_user_config', 'npm_config_cache' ]; for (const key of safeKeys) { if (env[key]) { safeEnv[key] = env[key]; } } // Add current user information const userInfo = os.userInfo(); safeEnv['CURRENT_USER'] = userInfo.username || 'Unknown'; safeEnv['USER_HOME'] = userInfo.homedir || 'Unknown'; safeEnv['USER_SHELL'] = userInfo.shell || 'Unknown'; safeEnv['USER_UID'] = userInfo.uid || 'Unknown'; safeEnv['USER_GID'] = userInfo.gid || 'Unknown'; // Format user information (anonymized for privacy) const formattedUsers = users.map(user => ({ user: user.user || 'Unknown', tty: user.tty || 'Unknown', date: user.date || 'Unknown', time: user.time || 'Unknown', ip: user.ip || 'Unknown', command: user.command || 'Unknown' })); // Format shell history (very limited for privacy and security) let formattedShellHistory = []; if (shellInfo && shellInfo.history && Array.isArray(shellInfo.history)) { formattedShellHistory = shellInfo.history .slice(-5) // Only last 5 commands .map(cmd => ({ date: cmd.date || '', time: cmd.time || '', command: cmd.command ? cmd.command.substring(0, 50) + '...' : '' // Truncate for privacy })); } const environmentInfo = { variables: safeEnv, user: { username: userInfo.username || 'Unknown', uid: userInfo.uid || 'Unknown', gid: userInfo.gid || 'Unknown', shell: userInfo.shell || 'Unknown', homedir: userInfo.homedir || 'Unknown' }, users: formattedUsers.slice(0, 10), // Limit for privacy shell: { available: shellInfo.available || false, history: formattedShellHistory }, timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'Unknown', locale: Intl.DateTimeFormat().resolvedOptions().locale || 'Unknown', timestamp: new Date().toISOString() }; return environmentInfo; } catch (error) { // Fallback to basic environment information const env = process.env; const safeEnv = {}; const userInfo = os.userInfo(); // Filter out sensitive information const safeKeys = [ 'PATH', 'LANG', 'TERM', 'SHELL', 'HOME', 'USER', 'LOGNAME', 'TMPDIR', 'TZ', 'EDITOR', 'PAGER', 'LSCOLORS', 'TERM_PROGRAM' ]; for (const key of safeKeys) { if (env[key]) { safeEnv[key] = env[key]; } } return { variables: safeEnv, user: { username: userInfo.username || 'Unknown', uid: userInfo.uid || 'Unknown', gid: userInfo.gid || 'Unknown', shell: userInfo.shell || 'Unknown', homedir: userInfo.homedir || 'Unknown' }, timestamp: new Date().toISOString(), error: 'Limited environment information available' }; } } /** * Get system information based on query with enhanced AI integration * @param {string} query - The user's query or category list * @returns {Object} Relevant system information */ async function getSystemInfo(query = '') { const startTime = Date.now(); const lowerQuery = (query || '').toLowerCase().trim(); let result = {}; const categoriesToFetch = []; // Enhanced query patterns for natural language processing const queryPatterns = { cpu: [ 'cpu', 'processor', 'core', 'thread', 'clock', 'speed', 'ghz', 'mhz', 'intel', 'amd', 'arm', 'load', 'usage', 'temperature', 'heat', 'cooling', 'performance', 'benchmark', 'processing', 'compute', 'cores', 'threads', 'frequency', 'cache', 'instruction', 'architecture', 'microprocessor' ], memory: [ 'memory', 'ram', 'dram', 'dimm', 'stick', 'module', 'bank', 'slot', 'free', 'available', 'used', 'total', 'swap', 'virtual memory', 'page', 'allocation', 'heap', 'stack', 'buffer', 'cache', 'physical memory', 'volatile memory', 'system memory', 'memory usage', 'memory allocation' ], disk: [ 'disk', 'drive', 'storage', 'hdd', 'ssd', 'nvme', 'partition', 'volume', 'filesystem', 'mount', 'space', 'capacity', 'free space', 'used space', 'read', 'write', 'io', 'block', 'sector', 'format', 'raid', 'hard drive', 'solid state', 'storage device', 'file system', 'directory', 'folder' ], network: [ 'network', 'internet', 'wifi', 'ethernet', 'connection', 'ip', 'address', 'mac', 'interface', 'adapter', 'wireless', 'wired', 'lan', 'wan', 'dns', 'gateway', 'router', 'subnet', 'mask', 'ping', 'latency', 'bandwidth', 'speed', 'download', 'upload', 'packet', 'traffic', 'port', 'socket', 'connectivity', 'protocol', 'tcp', 'udp', 'http', 'https' ], process: [ 'process', 'running', 'task', 'application', 'app', 'program', 'service', 'daemon', 'thread', 'job', 'pid', 'kill', 'terminate', 'start', 'stop', 'restart', 'crash', 'hang', 'freeze', 'responsive', 'background', 'foreground', 'processes', 'services', 'applications', 'system process', 'user process' ], environment: [ 'environment', 'env', 'variable', 'path', 'user', 'shell', 'terminal', 'console', 'profile', 'config', 'configuration', 'setting', 'preference', 'login', 'session', 'account', 'permission', 'access', 'privilege', 'variables', 'system config', 'user config', 'bash', 'zsh', 'cmd' ], basic: [ 'os', 'system', 'platform', 'version', 'release', 'build', 'kernel', 'distribution', 'distro', 'windows', 'mac', 'linux', 'unix', 'android', 'ios', 'architecture', 'arch', 'bit', '32-bit', '64-bit', 'x86', 'x64', 'arm', 'machine', 'hardware', 'device', 'model', 'manufacturer', 'vendor', 'computer', 'info', 'information', 'details', 'specs', 'specification', 'overview', 'summary', 'general', 'basic', 'hostname', 'uptime' ] }; // Function to check if query matches any pattern in a category const matchesCategory = (category) => { return queryPatterns[category].some(pattern => lowerQuery.includes(pattern)); }; // Determine what information to return based on the query if (lowerQuery.includes('all') || lowerQuery === '' || lowerQuery.includes('everything') || lowerQuery.includes('complete')) { // Get all information in parallel for better performance const [basic, cpu, memory, disk, network, process, environment] = await Promise.allSettled([ getBasicSystemInfo(), getCpuInfo(), getMemoryInfo(), getDiskInfo(), getNetworkInfo(), getProcessInfo(), getEnvironmentInfo() ]); // Handle results, including any that may have failed result = { basic: basic.status === 'fulfilled' ? basic.value : { error: basic.reason?.message || 'Failed to fetch basic info' }, cpu: cpu.status === 'fulfilled' ? cpu.value : { error: cpu.reason?.message || 'Failed to fetch CPU info' }, memory: memory.status === 'fulfilled' ? memory.value : { error: memory.reason?.message || 'Failed to fetch memory info' }, disk: disk.status === 'fulfilled' ? disk.value : { error: disk.reason?.message || 'Failed to fetch disk info' }, network: network.status === 'fulfilled' ? network.value : { error: network.reason?.message || 'Failed to fetch network info' }, process: process.status === 'fulfilled' ? process.value : { error: process.reason?.message || 'Failed to fetch process info' }, environment: environment.status === 'fulfilled' ? environment.value : { error: environment.reason?.message || 'Failed to fetch environment info' } }; } else { // Process categories from the query string (space-separated) const queryCategories = lowerQuery.split(/\s+/).filter(cat => ['basic', 'cpu', 'memory', 'disk', 'network', 'process', 'environment'].includes(cat) ); // If specific categories were mentioned in the query, use those if (queryCategories.length > 0) { categoriesToFetch.push(...queryCategories); } else { // Use pattern matching to determine categories if (matchesCategory('cpu')) categoriesToFetch.push('cpu'); if (matchesCategory('memory')) categoriesToFetch.push('memory'); if (matchesCategory('disk')) categoriesToFetch.push('disk'); if (matchesCategory('network')) categoriesToFetch.push('network'); if (matchesCategory('process')) categoriesToFetch.push('process'); if (matchesCategory('environment')) categoriesToFetch.push('environment'); if (matchesCategory('basic')) categoriesToFetch.push('basic'); } // If no specific category was matched, get basic info if (categoriesToFetch.length === 0) { categoriesToFetch.push('basic'); } // Remove duplicates const uniqueCategories = [...new Set(categoriesToFetch)]; // Fetch all requested categories in parallel for better performance const promises = []; const promiseMap = {}; uniqueCategories.forEach(category => { switch (category) { case 'basic': promises.push(getBasicSystemInfo()); promiseMap[promises.length - 1] = 'basic'; break; case 'cpu': promises.push(getCpuInfo()); promiseMap[promises.length - 1] = 'cpu'; break; case 'memory': promises.push(getMemoryInfo()); promiseMap[promises.length - 1] = 'memory'; break; case 'disk': promises.push(getDiskInfo()); promiseMap[promises.length - 1] = 'disk'; break; case 'network': promises.push(getNetworkInfo()); promiseMap[promises.length - 1] = 'network'; break; case 'process': promises.push(getProcessInfo()); promiseMap[promises.length - 1] = 'process'; break; case 'environment': promises.push(getEnvironmentInfo()); promiseMap[promises.length - 1] = 'environment'; break; } }); const results = await Promise.allSettled(promises); // Assign results to the appropriate categories results.forEach((promiseResult, index) => { const category = promiseMap[index]; if (promiseResult.status === 'fulfilled') { result[category] = promiseResult.value; } else { result[category] = { error: promiseResult.reason?.message || `Failed to fetch ${category} information`, timestamp: new Date().toISOString() }; } }); } // Add metadata to the result result._metadata = { query: query, processedAt: new Date().toISOString(), user: 'm0v0dga_walmart', processingTimeMs: Date.now() - startTime, categoriesFetched: Object.keys(result).filter(key => key !== '_metadata'), nodeVersion: process.version, platform: os.platform(), arch: os.arch() }; const endTime = Date.now(); return result; } module.exports = { getSystemInfo, getBasicSystemInfo, getCpuInfo, getMemoryInfo, getDiskInfo, getNetworkInfo, getProcessInfo, getEnvironmentInfo, formatBytes };