trace.ai-cli 1.1.6 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/services/aiService.js +464 -362
- package/services/systemInfoService.js +579 -335
- package/utils/encryption.js +20 -7
|
@@ -8,33 +8,42 @@ const si = require('systeminformation');
|
|
|
8
8
|
*/
|
|
9
9
|
async function getBasicSystemInfo() {
|
|
10
10
|
try {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const [osInfo, system, time] = await Promise.all([
|
|
14
|
+
si.osInfo().catch(() => ({})),
|
|
15
|
+
si.system().catch(() => ({})),
|
|
16
|
+
si.time().catch(() => ({}))
|
|
14
17
|
]);
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
const basicInfo = {
|
|
17
20
|
platform: os.platform(),
|
|
18
21
|
type: os.type(),
|
|
19
|
-
distro: osInfo.distro,
|
|
22
|
+
distro: osInfo.distro || 'Unknown',
|
|
20
23
|
release: os.release(),
|
|
21
|
-
codename: osInfo.codename,
|
|
22
|
-
kernel: osInfo.kernel,
|
|
24
|
+
codename: osInfo.codename || '',
|
|
25
|
+
kernel: osInfo.kernel || os.release(),
|
|
23
26
|
arch: os.arch(),
|
|
24
27
|
hostname: os.hostname(),
|
|
25
28
|
uptime: os.uptime(),
|
|
26
29
|
loadAvg: os.loadavg(),
|
|
27
|
-
manufacturer: system.manufacturer,
|
|
28
|
-
model: system.model,
|
|
29
|
-
serial: system.serial,
|
|
30
|
-
uuid: system.uuid,
|
|
31
|
-
sku: system.sku,
|
|
32
|
-
virtual: system.virtual,
|
|
30
|
+
manufacturer: system.manufacturer || 'Unknown',
|
|
31
|
+
model: system.model || 'Unknown',
|
|
32
|
+
serial: system.serial || 'N/A',
|
|
33
|
+
uuid: system.uuid || 'N/A',
|
|
34
|
+
sku: system.sku || 'N/A',
|
|
35
|
+
virtual: system.virtual || false,
|
|
33
36
|
userInfo: os.userInfo(),
|
|
34
|
-
tempDir: os.tmpdir()
|
|
37
|
+
tempDir: os.tmpdir(),
|
|
38
|
+
nodeVersion: process.version,
|
|
39
|
+
timestamp: new Date().toISOString(),
|
|
40
|
+
timezone: time.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
35
41
|
};
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
return basicInfo;
|
|
36
45
|
} catch (error) {
|
|
37
|
-
|
|
46
|
+
|
|
38
47
|
// Fallback to basic OS information
|
|
39
48
|
return {
|
|
40
49
|
platform: os.platform(),
|
|
@@ -45,7 +54,10 @@ async function getBasicSystemInfo() {
|
|
|
45
54
|
uptime: os.uptime(),
|
|
46
55
|
loadAvg: os.loadavg(),
|
|
47
56
|
userInfo: os.userInfo(),
|
|
48
|
-
tempDir: os.tmpdir()
|
|
57
|
+
tempDir: os.tmpdir(),
|
|
58
|
+
nodeVersion: process.version,
|
|
59
|
+
timestamp: new Date().toISOString(),
|
|
60
|
+
error: 'Limited information available due to system restrictions'
|
|
49
61
|
};
|
|
50
62
|
}
|
|
51
63
|
}
|
|
@@ -56,60 +68,76 @@ async function getBasicSystemInfo() {
|
|
|
56
68
|
*/
|
|
57
69
|
async function getCpuInfo() {
|
|
58
70
|
try {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
si.
|
|
63
|
-
si.
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
const [cpu, cpuCurrentSpeed, cpuTemperature, currentLoad, cpuFlags] = await Promise.all([
|
|
74
|
+
si.cpu().catch(() => ({})),
|
|
75
|
+
si.cpuCurrentSpeed().catch(() => ({})),
|
|
76
|
+
si.cpuTemperature().catch(() => ({})),
|
|
77
|
+
si.currentLoad().catch(() => ({})),
|
|
78
|
+
si.cpuFlags().catch(() => '')
|
|
64
79
|
]);
|
|
65
80
|
|
|
66
|
-
|
|
67
|
-
manufacturer: cpu.manufacturer,
|
|
68
|
-
brand: cpu.brand,
|
|
69
|
-
vendor: cpu.vendor,
|
|
70
|
-
family: cpu.family,
|
|
71
|
-
model: cpu.model,
|
|
72
|
-
stepping: cpu.stepping,
|
|
73
|
-
revision: cpu.revision,
|
|
74
|
-
voltage: cpu.voltage,
|
|
75
|
-
speed: cpu.speed,
|
|
76
|
-
speedMin: cpu.speedMin,
|
|
77
|
-
speedMax: cpu.speedMax,
|
|
78
|
-
governor: cpu.governor,
|
|
79
|
-
cores: cpu.cores,
|
|
80
|
-
physicalCores: cpu.physicalCores,
|
|
81
|
-
processors: cpu.processors,
|
|
82
|
-
socket: cpu.socket,
|
|
83
|
-
flags: cpu.flags,
|
|
84
|
-
virtualization: cpu.virtualization,
|
|
85
|
-
cache: cpu.cache,
|
|
86
|
-
currentSpeed: cpuCurrentSpeed,
|
|
87
|
-
temperature: cpuTemperature,
|
|
81
|
+
const cpuInfo = {
|
|
82
|
+
manufacturer: cpu.manufacturer || 'Unknown',
|
|
83
|
+
brand: cpu.brand || 'Unknown',
|
|
84
|
+
vendor: cpu.vendor || cpu.manufacturer || 'Unknown',
|
|
85
|
+
family: cpu.family || 'Unknown',
|
|
86
|
+
model: cpu.model || cpu.brand || 'Unknown',
|
|
87
|
+
stepping: cpu.stepping || 'Unknown',
|
|
88
|
+
revision: cpu.revision || 'Unknown',
|
|
89
|
+
voltage: cpu.voltage || 'Unknown',
|
|
90
|
+
speed: cpu.speed || 0,
|
|
91
|
+
speedMin: cpu.speedMin || 0,
|
|
92
|
+
speedMax: cpu.speedMax || 0,
|
|
93
|
+
governor: cpu.governor || 'Unknown',
|
|
94
|
+
cores: cpu.cores || os.cpus().length,
|
|
95
|
+
physicalCores: cpu.physicalCores || cpu.cores || os.cpus().length,
|
|
96
|
+
processors: cpu.processors || 1,
|
|
97
|
+
socket: cpu.socket || 'Unknown',
|
|
98
|
+
flags: cpuFlags || cpu.flags || 'Unknown',
|
|
99
|
+
virtualization: cpu.virtualization || false,
|
|
100
|
+
cache: cpu.cache || {},
|
|
101
|
+
currentSpeed: cpuCurrentSpeed.avg || cpuCurrentSpeed.cores || cpu.speed || 0,
|
|
102
|
+
temperature: cpuTemperature.main || cpuTemperature.max || null,
|
|
88
103
|
load: {
|
|
89
|
-
currentLoad: currentLoad.currentLoad,
|
|
90
|
-
currentLoadUser: currentLoad.currentLoadUser,
|
|
91
|
-
currentLoadSystem: currentLoad.currentLoadSystem,
|
|
92
|
-
currentLoadNice: currentLoad.currentLoadNice,
|
|
93
|
-
currentLoadIdle: currentLoad.currentLoadIdle,
|
|
94
|
-
currentLoadIrq: currentLoad.currentLoadIrq,
|
|
95
|
-
rawCurrentLoad: currentLoad.rawCurrentLoad,
|
|
96
|
-
rawCurrentLoadUser: currentLoad.rawCurrentLoadUser,
|
|
97
|
-
rawCurrentLoadSystem: currentLoad.rawCurrentLoadSystem,
|
|
98
|
-
rawCurrentLoadNice: currentLoad.rawCurrentLoadNice,
|
|
99
|
-
rawCurrentLoadIdle: currentLoad.rawCurrentLoadIdle,
|
|
100
|
-
rawCurrentLoadIrq: currentLoad.rawCurrentLoadIrq
|
|
104
|
+
currentLoad: currentLoad.currentLoad || 0,
|
|
105
|
+
currentLoadUser: currentLoad.currentLoadUser || 0,
|
|
106
|
+
currentLoadSystem: currentLoad.currentLoadSystem || 0,
|
|
107
|
+
currentLoadNice: currentLoad.currentLoadNice || 0,
|
|
108
|
+
currentLoadIdle: currentLoad.currentLoadIdle || 100,
|
|
109
|
+
currentLoadIrq: currentLoad.currentLoadIrq || 0,
|
|
110
|
+
rawCurrentLoad: currentLoad.rawCurrentLoad || 0,
|
|
111
|
+
rawCurrentLoadUser: currentLoad.rawCurrentLoadUser || 0,
|
|
112
|
+
rawCurrentLoadSystem: currentLoad.rawCurrentLoadSystem || 0,
|
|
113
|
+
rawCurrentLoadNice: currentLoad.rawCurrentLoadNice || 0,
|
|
114
|
+
rawCurrentLoadIdle: currentLoad.rawCurrentLoadIdle || 0,
|
|
115
|
+
rawCurrentLoadIrq: currentLoad.rawCurrentLoadIrq || 0,
|
|
116
|
+
cpus: currentLoad.cpus || []
|
|
101
117
|
},
|
|
102
|
-
loadAvg: os.loadavg()
|
|
118
|
+
loadAvg: os.loadavg(),
|
|
119
|
+
timestamp: new Date().toISOString()
|
|
103
120
|
};
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
return cpuInfo;
|
|
104
124
|
} catch (error) {
|
|
105
|
-
|
|
125
|
+
|
|
106
126
|
// Fallback to basic CPU information
|
|
107
127
|
const cpus = os.cpus();
|
|
108
128
|
return {
|
|
109
|
-
model: cpus[0]
|
|
110
|
-
speed: cpus[0]
|
|
129
|
+
model: cpus[0]?.model || 'Unknown',
|
|
130
|
+
speed: cpus[0]?.speed || 0,
|
|
111
131
|
cores: cpus.length,
|
|
112
|
-
loadAvg: os.loadavg()
|
|
132
|
+
loadAvg: os.loadavg(),
|
|
133
|
+
load: {
|
|
134
|
+
currentLoad: 0,
|
|
135
|
+
currentLoadUser: 0,
|
|
136
|
+
currentLoadSystem: 0,
|
|
137
|
+
currentLoadIdle: 100
|
|
138
|
+
},
|
|
139
|
+
timestamp: new Date().toISOString(),
|
|
140
|
+
error: 'Limited CPU information available'
|
|
113
141
|
};
|
|
114
142
|
}
|
|
115
143
|
}
|
|
@@ -120,50 +148,61 @@ async function getCpuInfo() {
|
|
|
120
148
|
*/
|
|
121
149
|
async function getMemoryInfo() {
|
|
122
150
|
try {
|
|
151
|
+
|
|
152
|
+
|
|
123
153
|
const [mem, memLayout] = await Promise.all([
|
|
124
|
-
si.mem()
|
|
125
|
-
|
|
154
|
+
si.mem().catch(() => ({
|
|
155
|
+
total: os.totalmem(),
|
|
156
|
+
free: os.freemem(),
|
|
157
|
+
used: os.totalmem() - os.freemem()
|
|
158
|
+
})),
|
|
159
|
+
si.memLayout().catch(() => [])
|
|
126
160
|
]);
|
|
127
161
|
|
|
128
162
|
// Convert to human-readable format
|
|
129
163
|
const totalMemGB = (mem.total / (1024 * 1024 * 1024)).toFixed(2);
|
|
130
164
|
const freeMemGB = (mem.free / (1024 * 1024 * 1024)).toFixed(2);
|
|
131
165
|
const usedMemGB = (mem.used / (1024 * 1024 * 1024)).toFixed(2);
|
|
132
|
-
const activeMemGB = (mem.active / (1024 * 1024 * 1024)).toFixed(2);
|
|
133
|
-
const availableMemGB = (mem.available / (1024 * 1024 * 1024)).toFixed(2);
|
|
134
|
-
const swapTotalGB = (mem.swaptotal / (1024 * 1024 * 1024)).toFixed(2);
|
|
135
|
-
const swapUsedGB = (mem.swapused / (1024 * 1024 * 1024)).toFixed(2);
|
|
136
|
-
const swapFreeGB = (mem.swapfree / (1024 * 1024 * 1024)).toFixed(2);
|
|
166
|
+
const activeMemGB = mem.active ? (mem.active / (1024 * 1024 * 1024)).toFixed(2) : 'N/A';
|
|
167
|
+
const availableMemGB = mem.available ? (mem.available / (1024 * 1024 * 1024)).toFixed(2) : freeMemGB;
|
|
168
|
+
const swapTotalGB = mem.swaptotal ? (mem.swaptotal / (1024 * 1024 * 1024)).toFixed(2) : '0.00';
|
|
169
|
+
const swapUsedGB = mem.swapused ? (mem.swapused / (1024 * 1024 * 1024)).toFixed(2) : '0.00';
|
|
170
|
+
const swapFreeGB = mem.swapfree ? (mem.swapfree / (1024 * 1024 * 1024)).toFixed(2) : '0.00';
|
|
137
171
|
|
|
138
|
-
|
|
172
|
+
const memoryInfo = {
|
|
139
173
|
total: `${totalMemGB} GB`,
|
|
140
174
|
free: `${freeMemGB} GB`,
|
|
141
175
|
used: `${usedMemGB} GB`,
|
|
142
176
|
active: `${activeMemGB} GB`,
|
|
143
177
|
available: `${availableMemGB} GB`,
|
|
144
|
-
usagePercent: `${mem.used / mem.total * 100}%`,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
178
|
+
usagePercent: `${((mem.used / mem.total) * 100).toFixed(1)}%`,
|
|
179
|
+
buffers: mem.buffers ? formatBytes(mem.buffers) : 'N/A',
|
|
180
|
+
cached: mem.cached ? formatBytes(mem.cached) : 'N/A',
|
|
181
|
+
slab: mem.slab ? formatBytes(mem.slab) : 'N/A',
|
|
182
|
+
swapTotal: `${swapTotalGB} GB`,
|
|
183
|
+
swapUsed: `${swapUsedGB} GB`,
|
|
184
|
+
swapFree: `${swapFreeGB} GB`,
|
|
185
|
+
swapUsagePercent: mem.swaptotal > 0 ? `${((mem.swapused / mem.swaptotal) * 100).toFixed(1)}%` : '0.0%',
|
|
151
186
|
layout: memLayout.map(module => ({
|
|
152
|
-
size:
|
|
153
|
-
bank: module.bank,
|
|
154
|
-
type: module.type,
|
|
155
|
-
clockSpeed: `${module.clockSpeed} MHz
|
|
156
|
-
formFactor: module.formFactor,
|
|
157
|
-
manufacturer: module.manufacturer,
|
|
158
|
-
partNum: module.partNum,
|
|
159
|
-
serialNum: module.serialNum,
|
|
160
|
-
voltageConfigured: module.voltageConfigured,
|
|
161
|
-
voltageMin: module.voltageMin,
|
|
162
|
-
voltageMax: module.voltageMax
|
|
163
|
-
}))
|
|
187
|
+
size: module.size ? formatBytes(module.size) : 'Unknown',
|
|
188
|
+
bank: module.bank || 'Unknown',
|
|
189
|
+
type: module.type || 'Unknown',
|
|
190
|
+
clockSpeed: module.clockSpeed ? `${module.clockSpeed} MHz` : 'Unknown',
|
|
191
|
+
formFactor: module.formFactor || 'Unknown',
|
|
192
|
+
manufacturer: module.manufacturer || 'Unknown',
|
|
193
|
+
partNum: module.partNum || 'Unknown',
|
|
194
|
+
serialNum: module.serialNum || 'Unknown',
|
|
195
|
+
voltageConfigured: module.voltageConfigured ? `${module.voltageConfigured} V` : 'Unknown',
|
|
196
|
+
voltageMin: module.voltageMin ? `${module.voltageMin} V` : 'Unknown',
|
|
197
|
+
voltageMax: module.voltageMax ? `${module.voltageMax} V` : 'Unknown'
|
|
198
|
+
})),
|
|
199
|
+
timestamp: new Date().toISOString()
|
|
164
200
|
};
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
return memoryInfo;
|
|
165
204
|
} catch (error) {
|
|
166
|
-
|
|
205
|
+
|
|
167
206
|
// Fallback to basic memory information
|
|
168
207
|
const totalMemMB = Math.round(os.totalmem() / (1024 * 1024));
|
|
169
208
|
const freeMemMB = Math.round(os.freemem() / (1024 * 1024));
|
|
@@ -171,10 +210,12 @@ async function getMemoryInfo() {
|
|
|
171
210
|
const memUsagePercent = Math.round((usedMemMB / totalMemMB) * 100);
|
|
172
211
|
|
|
173
212
|
return {
|
|
174
|
-
total: `${totalMemMB}
|
|
175
|
-
free: `${freeMemMB}
|
|
176
|
-
used: `${usedMemMB}
|
|
177
|
-
usagePercent: `${memUsagePercent}
|
|
213
|
+
total: `${(totalMemMB / 1024).toFixed(2)} GB`,
|
|
214
|
+
free: `${(freeMemMB / 1024).toFixed(2)} GB`,
|
|
215
|
+
used: `${(usedMemMB / 1024).toFixed(2)} GB`,
|
|
216
|
+
usagePercent: `${memUsagePercent}%`,
|
|
217
|
+
timestamp: new Date().toISOString(),
|
|
218
|
+
error: 'Limited memory information available'
|
|
178
219
|
};
|
|
179
220
|
}
|
|
180
221
|
}
|
|
@@ -185,72 +226,89 @@ async function getMemoryInfo() {
|
|
|
185
226
|
*/
|
|
186
227
|
async function getDiskInfo() {
|
|
187
228
|
try {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
si.
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
const [fsSize, blockDevices, diskLayout, diskIo] = await Promise.all([
|
|
232
|
+
si.fsSize().catch(() => []),
|
|
233
|
+
si.blockDevices().catch(() => []),
|
|
234
|
+
si.diskLayout().catch(() => []),
|
|
235
|
+
si.disksIO().catch(() => ({}))
|
|
192
236
|
]);
|
|
193
237
|
|
|
194
238
|
// Format file system sizes
|
|
195
239
|
const formattedFsSize = fsSize.map(fs => ({
|
|
196
|
-
fs: fs.fs,
|
|
197
|
-
type: fs.type,
|
|
198
|
-
size:
|
|
199
|
-
used:
|
|
200
|
-
available:
|
|
201
|
-
usagePercent: `${fs.use.toFixed(1)}
|
|
202
|
-
mount: fs.mount
|
|
240
|
+
fs: fs.fs || 'Unknown',
|
|
241
|
+
type: fs.type || 'Unknown',
|
|
242
|
+
size: fs.size ? formatBytes(fs.size) : 'Unknown',
|
|
243
|
+
used: fs.used ? formatBytes(fs.used) : 'Unknown',
|
|
244
|
+
available: fs.available ? formatBytes(fs.available) : 'Unknown',
|
|
245
|
+
usagePercent: fs.use ? `${fs.use.toFixed(1)}%` : 'Unknown',
|
|
246
|
+
mount: fs.mount || 'Unknown'
|
|
203
247
|
}));
|
|
204
248
|
|
|
205
249
|
// Format block devices info
|
|
206
250
|
const formattedBlockDevices = blockDevices.map(device => ({
|
|
207
|
-
name: device.name,
|
|
208
|
-
type: device.type,
|
|
209
|
-
fsType: device.fstype,
|
|
210
|
-
mount: device.mount,
|
|
211
|
-
size: device.size ?
|
|
212
|
-
physical: device.physical,
|
|
213
|
-
uuid: device.uuid,
|
|
214
|
-
label: device.label,
|
|
215
|
-
model: device.model,
|
|
216
|
-
serial: device.serial,
|
|
217
|
-
removable: device.removable,
|
|
218
|
-
protocol: device.protocol
|
|
251
|
+
name: device.name || 'Unknown',
|
|
252
|
+
type: device.type || 'Unknown',
|
|
253
|
+
fsType: device.fstype || 'Unknown',
|
|
254
|
+
mount: device.mount || 'Unknown',
|
|
255
|
+
size: device.size ? formatBytes(device.size) : 'Unknown',
|
|
256
|
+
physical: device.physical || 'Unknown',
|
|
257
|
+
uuid: device.uuid || 'Unknown',
|
|
258
|
+
label: device.label || 'Unknown',
|
|
259
|
+
model: device.model || 'Unknown',
|
|
260
|
+
serial: device.serial || 'Unknown',
|
|
261
|
+
removable: device.removable !== undefined ? device.removable : 'Unknown',
|
|
262
|
+
protocol: device.protocol || 'Unknown'
|
|
219
263
|
}));
|
|
220
264
|
|
|
221
265
|
// Format disk layout info
|
|
222
266
|
const formattedDiskLayout = diskLayout.map(disk => ({
|
|
223
|
-
device: disk.device,
|
|
224
|
-
type: disk.type,
|
|
225
|
-
name: disk.name,
|
|
226
|
-
vendor: disk.vendor,
|
|
227
|
-
size: disk.size ?
|
|
228
|
-
bytesPerSector: disk.bytesPerSector,
|
|
229
|
-
totalCylinders: disk.totalCylinders,
|
|
230
|
-
totalHeads: disk.totalHeads,
|
|
231
|
-
totalSectors: disk.totalSectors,
|
|
232
|
-
totalTracks: disk.totalTracks,
|
|
233
|
-
tracksPerCylinder: disk.tracksPerCylinder,
|
|
234
|
-
sectorsPerTrack: disk.sectorsPerTrack,
|
|
235
|
-
firmwareRevision: disk.firmwareRevision,
|
|
236
|
-
serialNum: disk.serialNum,
|
|
237
|
-
interfaceType: disk.interfaceType,
|
|
238
|
-
smartStatus: disk.smartStatus
|
|
267
|
+
device: disk.device || 'Unknown',
|
|
268
|
+
type: disk.type || 'Unknown',
|
|
269
|
+
name: disk.name || 'Unknown',
|
|
270
|
+
vendor: disk.vendor || 'Unknown',
|
|
271
|
+
size: disk.size ? formatBytes(disk.size) : 'Unknown',
|
|
272
|
+
bytesPerSector: disk.bytesPerSector || 'Unknown',
|
|
273
|
+
totalCylinders: disk.totalCylinders || 'Unknown',
|
|
274
|
+
totalHeads: disk.totalHeads || 'Unknown',
|
|
275
|
+
totalSectors: disk.totalSectors || 'Unknown',
|
|
276
|
+
totalTracks: disk.totalTracks || 'Unknown',
|
|
277
|
+
tracksPerCylinder: disk.tracksPerCylinder || 'Unknown',
|
|
278
|
+
sectorsPerTrack: disk.sectorsPerTrack || 'Unknown',
|
|
279
|
+
firmwareRevision: disk.firmwareRevision || 'Unknown',
|
|
280
|
+
serialNum: disk.serialNum || 'Unknown',
|
|
281
|
+
interfaceType: disk.interfaceType || 'Unknown',
|
|
282
|
+
smartStatus: disk.smartStatus || 'Unknown',
|
|
283
|
+
temperature: disk.temperature || null
|
|
239
284
|
}));
|
|
240
285
|
|
|
241
|
-
|
|
286
|
+
const diskInfo = {
|
|
242
287
|
fsSize: formattedFsSize,
|
|
243
288
|
blockDevices: formattedBlockDevices,
|
|
244
|
-
diskLayout: formattedDiskLayout
|
|
289
|
+
diskLayout: formattedDiskLayout,
|
|
290
|
+
io: {
|
|
291
|
+
rIO: diskIo.rIO || 0,
|
|
292
|
+
wIO: diskIo.wIO || 0,
|
|
293
|
+
tIO: diskIo.tIO || 0,
|
|
294
|
+
rIO_sec: diskIo.rIO_sec || 0,
|
|
295
|
+
wIO_sec: diskIo.wIO_sec || 0,
|
|
296
|
+
tIO_sec: diskIo.tIO_sec || 0
|
|
297
|
+
},
|
|
298
|
+
timestamp: new Date().toISOString()
|
|
245
299
|
};
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
return diskInfo;
|
|
246
303
|
} catch (error) {
|
|
247
|
-
|
|
304
|
+
|
|
248
305
|
|
|
249
|
-
//
|
|
306
|
+
// Enhanced fallback with better error handling
|
|
250
307
|
try {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
308
|
+
const platform = os.platform();
|
|
309
|
+
|
|
310
|
+
if (platform === 'darwin' || platform === 'linux') {
|
|
311
|
+
const df = execSync('df -h /', { timeout: 5000 }).toString();
|
|
254
312
|
const lines = df.trim().split('\n');
|
|
255
313
|
if (lines.length >= 2) {
|
|
256
314
|
const parts = lines[1].split(/\s+/);
|
|
@@ -260,19 +318,18 @@ async function getDiskInfo() {
|
|
|
260
318
|
used: parts[2],
|
|
261
319
|
available: parts[3],
|
|
262
320
|
usagePercent: parts[4],
|
|
263
|
-
mountedOn: parts[5]
|
|
321
|
+
mountedOn: parts[5],
|
|
322
|
+
timestamp: new Date().toISOString()
|
|
264
323
|
};
|
|
265
324
|
}
|
|
266
|
-
} else if (
|
|
267
|
-
|
|
268
|
-
// This is a simplified version
|
|
269
|
-
const wmic = execSync('wmic logicaldisk get size,freespace,caption').toString();
|
|
325
|
+
} else if (platform === 'win32') {
|
|
326
|
+
const wmic = execSync('wmic logicaldisk get size,freespace,caption', { timeout: 5000 }).toString();
|
|
270
327
|
const lines = wmic.trim().split('\n');
|
|
271
328
|
const disks = [];
|
|
272
329
|
|
|
273
330
|
for (let i = 1; i < lines.length; i++) {
|
|
274
331
|
const parts = lines[i].trim().split(/\s+/);
|
|
275
|
-
if (parts.length >= 3) {
|
|
332
|
+
if (parts.length >= 3 && parts[0] && parts[1] && parts[2]) {
|
|
276
333
|
const caption = parts[0];
|
|
277
334
|
const freeSpace = Math.round(parseInt(parts[1]) / (1024 * 1024 * 1024));
|
|
278
335
|
const size = Math.round(parseInt(parts[2]) / (1024 * 1024 * 1024));
|
|
@@ -288,13 +345,19 @@ async function getDiskInfo() {
|
|
|
288
345
|
});
|
|
289
346
|
}
|
|
290
347
|
}
|
|
291
|
-
return
|
|
348
|
+
return {
|
|
349
|
+
disks,
|
|
350
|
+
timestamp: new Date().toISOString()
|
|
351
|
+
};
|
|
292
352
|
}
|
|
293
353
|
} catch (fallbackError) {
|
|
294
|
-
|
|
354
|
+
|
|
295
355
|
}
|
|
296
356
|
|
|
297
|
-
return {
|
|
357
|
+
return {
|
|
358
|
+
error: 'Could not retrieve disk information - system access restricted',
|
|
359
|
+
timestamp: new Date().toISOString()
|
|
360
|
+
};
|
|
298
361
|
}
|
|
299
362
|
}
|
|
300
363
|
|
|
@@ -304,103 +367,137 @@ async function getDiskInfo() {
|
|
|
304
367
|
*/
|
|
305
368
|
async function getNetworkInfo() {
|
|
306
369
|
try {
|
|
370
|
+
|
|
371
|
+
|
|
307
372
|
const [networkInterfaces, networkStats, networkConnections, wifiNetworks, internetSpeed] = await Promise.all([
|
|
308
|
-
si.networkInterfaces(),
|
|
309
|
-
si.networkStats(),
|
|
310
|
-
si.networkConnections(),
|
|
311
|
-
si.wifiNetworks().catch(() => []),
|
|
312
|
-
si.inetChecksite('https://www.google.com').catch(() => ({ ms:
|
|
373
|
+
si.networkInterfaces().catch(() => []),
|
|
374
|
+
si.networkStats().catch(() => []),
|
|
375
|
+
si.networkConnections().catch(() => []),
|
|
376
|
+
si.wifiNetworks().catch(() => []),
|
|
377
|
+
si.inetChecksite('https://www.google.com').catch(() => ({ ms: null }))
|
|
313
378
|
]);
|
|
314
379
|
|
|
380
|
+
// Get public IP address
|
|
381
|
+
let publicIp = 'Not available';
|
|
382
|
+
try {
|
|
383
|
+
const ipResponse = await fetch('https://api.ipify.org?format=json', { timeout: 5000 });
|
|
384
|
+
const ipData = await ipResponse.json();
|
|
385
|
+
publicIp = ipData.ip || 'Not available';
|
|
386
|
+
} catch (ipError) {
|
|
387
|
+
|
|
388
|
+
}
|
|
389
|
+
|
|
315
390
|
// Format network interfaces
|
|
316
391
|
const formattedInterfaces = networkInterfaces.map(iface => ({
|
|
317
|
-
|
|
318
|
-
ifaceName: iface.ifaceName,
|
|
319
|
-
ip4: iface.ip4,
|
|
320
|
-
ip6: iface.ip6,
|
|
321
|
-
mac: iface.mac,
|
|
322
|
-
internal: iface.internal,
|
|
323
|
-
virtual: iface.virtual,
|
|
324
|
-
operstate: iface.operstate,
|
|
325
|
-
type: iface.type,
|
|
326
|
-
duplex: iface.duplex,
|
|
327
|
-
speed: iface.speed ? `${iface.speed} Mbps` : '
|
|
328
|
-
dhcp: iface.dhcp,
|
|
329
|
-
dnsSuffix: iface.dnsSuffix,
|
|
330
|
-
ieee8021xAuth: iface.ieee8021xAuth,
|
|
331
|
-
ieee8021xState: iface.ieee8021xState,
|
|
332
|
-
carrierChanges: iface.carrierChanges
|
|
392
|
+
iface: iface.iface || 'Unknown',
|
|
393
|
+
ifaceName: iface.ifaceName || iface.iface || 'Unknown',
|
|
394
|
+
ip4: iface.ip4 || 'None',
|
|
395
|
+
ip6: iface.ip6 || 'None',
|
|
396
|
+
mac: iface.mac || 'Unknown',
|
|
397
|
+
internal: iface.internal || false,
|
|
398
|
+
virtual: iface.virtual || false,
|
|
399
|
+
operstate: iface.operstate || 'Unknown',
|
|
400
|
+
type: iface.type || 'Unknown',
|
|
401
|
+
duplex: iface.duplex || 'Unknown',
|
|
402
|
+
speed: iface.speed ? `${iface.speed} Mbps` : 'Unknown',
|
|
403
|
+
dhcp: iface.dhcp || false,
|
|
404
|
+
dnsSuffix: iface.dnsSuffix || 'Unknown',
|
|
405
|
+
ieee8021xAuth: iface.ieee8021xAuth || 'Unknown',
|
|
406
|
+
ieee8021xState: iface.ieee8021xState || 'Unknown',
|
|
407
|
+
carrierChanges: iface.carrierChanges || 0
|
|
333
408
|
}));
|
|
334
409
|
|
|
335
410
|
// Format network stats
|
|
336
411
|
const formattedStats = networkStats.map(stat => ({
|
|
337
|
-
|
|
338
|
-
operstate: stat.operstate,
|
|
339
|
-
rx_bytes: formatBytes(stat.rx_bytes),
|
|
340
|
-
rx_dropped: stat.rx_dropped,
|
|
341
|
-
rx_errors: stat.rx_errors,
|
|
342
|
-
tx_bytes: formatBytes(stat.tx_bytes),
|
|
343
|
-
tx_dropped: stat.tx_dropped,
|
|
344
|
-
tx_errors: stat.tx_errors,
|
|
345
|
-
rx_sec: formatBytes(stat.rx_sec),
|
|
346
|
-
tx_sec: formatBytes(stat.tx_sec),
|
|
347
|
-
ms: stat.ms
|
|
412
|
+
iface: stat.iface || 'Unknown',
|
|
413
|
+
operstate: stat.operstate || 'Unknown',
|
|
414
|
+
rx_bytes: formatBytes(stat.rx_bytes || 0),
|
|
415
|
+
rx_dropped: stat.rx_dropped || 0,
|
|
416
|
+
rx_errors: stat.rx_errors || 0,
|
|
417
|
+
tx_bytes: formatBytes(stat.tx_bytes || 0),
|
|
418
|
+
tx_dropped: stat.tx_dropped || 0,
|
|
419
|
+
tx_errors: stat.tx_errors || 0,
|
|
420
|
+
rx_sec: formatBytes(stat.rx_sec || 0),
|
|
421
|
+
tx_sec: formatBytes(stat.tx_sec || 0),
|
|
422
|
+
ms: stat.ms || 0
|
|
348
423
|
}));
|
|
349
424
|
|
|
350
|
-
// Format wifi networks
|
|
425
|
+
// Format wifi networks
|
|
351
426
|
const formattedWifiNetworks = wifiNetworks.map(network => ({
|
|
352
|
-
ssid: network.ssid,
|
|
353
|
-
bssid: network.bssid,
|
|
354
|
-
mode: network.mode,
|
|
355
|
-
channel: network.channel,
|
|
356
|
-
frequency: network.frequency,
|
|
357
|
-
signalLevel: network.signalLevel,
|
|
358
|
-
quality: network.quality,
|
|
359
|
-
security: network.security,
|
|
360
|
-
wpaFlags: network.wpaFlags,
|
|
361
|
-
rsnFlags: network.rsnFlags
|
|
427
|
+
ssid: network.ssid || 'Hidden',
|
|
428
|
+
bssid: network.bssid || 'Unknown',
|
|
429
|
+
mode: network.mode || 'Unknown',
|
|
430
|
+
channel: network.channel || 'Unknown',
|
|
431
|
+
frequency: network.frequency || 'Unknown',
|
|
432
|
+
signalLevel: network.signalLevel || 'Unknown',
|
|
433
|
+
quality: network.quality || 'Unknown',
|
|
434
|
+
security: Array.isArray(network.security) ? network.security : [network.security || 'Unknown'],
|
|
435
|
+
wpaFlags: network.wpaFlags || 'Unknown',
|
|
436
|
+
rsnFlags: network.rsnFlags || 'Unknown'
|
|
362
437
|
}));
|
|
363
438
|
|
|
364
|
-
//
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
.then(res => res.json())
|
|
369
|
-
.catch(() => ({ ip: 'Not available' }));
|
|
370
|
-
publicIp = externalIpResponse.ip;
|
|
371
|
-
} catch (error) {
|
|
372
|
-
console.error('Error getting public IP:', error);
|
|
373
|
-
}
|
|
439
|
+
// Format connections summary
|
|
440
|
+
const connectionsCount = networkConnections.length || 0;
|
|
441
|
+
const establishedCount = networkConnections.filter(conn => conn.state === 'ESTABLISHED').length || 0;
|
|
442
|
+
const listeningCount = networkConnections.filter(conn => conn.state === 'LISTEN').length || 0;
|
|
374
443
|
|
|
375
|
-
|
|
444
|
+
const networkInfo = {
|
|
376
445
|
interfaces: formattedInterfaces,
|
|
377
446
|
stats: formattedStats,
|
|
378
|
-
connections:
|
|
447
|
+
connections: {
|
|
448
|
+
total: connectionsCount,
|
|
449
|
+
established: establishedCount,
|
|
450
|
+
listening: listeningCount,
|
|
451
|
+
sample: networkConnections.slice(0, 5).map(conn => ({
|
|
452
|
+
protocol: conn.protocol || 'Unknown',
|
|
453
|
+
localAddress: conn.localAddress || 'Unknown',
|
|
454
|
+
localPort: conn.localPort || 'Unknown',
|
|
455
|
+
peerAddress: conn.peerAddress || 'Unknown',
|
|
456
|
+
peerPort: conn.peerPort || 'Unknown',
|
|
457
|
+
state: conn.state || 'Unknown'
|
|
458
|
+
}))
|
|
459
|
+
},
|
|
379
460
|
wifiNetworks: formattedWifiNetworks,
|
|
380
|
-
internetLatency: `${internetSpeed.ms} ms
|
|
381
|
-
publicIp
|
|
461
|
+
internetLatency: internetSpeed.ms !== null ? `${internetSpeed.ms} ms` : 'Unknown',
|
|
462
|
+
publicIp,
|
|
463
|
+
timestamp: new Date().toISOString()
|
|
382
464
|
};
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
return networkInfo;
|
|
383
468
|
} catch (error) {
|
|
384
|
-
|
|
385
|
-
// Fallback to basic network information
|
|
386
|
-
const interfaces = os.networkInterfaces();
|
|
387
|
-
const result = [];
|
|
469
|
+
|
|
388
470
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
471
|
+
// Enhanced fallback to basic network information
|
|
472
|
+
try {
|
|
473
|
+
const interfaces = os.networkInterfaces();
|
|
474
|
+
const result = [];
|
|
475
|
+
|
|
476
|
+
for (const [name, netInterface] of Object.entries(interfaces)) {
|
|
477
|
+
for (const info of netInterface) {
|
|
478
|
+
if (info.family === 'IPv4' || info.family === 4) {
|
|
479
|
+
result.push({
|
|
480
|
+
interface: name,
|
|
481
|
+
address: info.address,
|
|
482
|
+
netmask: info.netmask,
|
|
483
|
+
mac: info.mac,
|
|
484
|
+
internal: info.internal
|
|
485
|
+
});
|
|
486
|
+
}
|
|
399
487
|
}
|
|
400
488
|
}
|
|
489
|
+
|
|
490
|
+
return {
|
|
491
|
+
interfaces: result,
|
|
492
|
+
timestamp: new Date().toISOString(),
|
|
493
|
+
error: 'Limited network information available'
|
|
494
|
+
};
|
|
495
|
+
} catch (fallbackError) {
|
|
496
|
+
return {
|
|
497
|
+
error: 'Could not retrieve network information',
|
|
498
|
+
timestamp: new Date().toISOString()
|
|
499
|
+
};
|
|
401
500
|
}
|
|
402
|
-
|
|
403
|
-
return { interfaces: result };
|
|
404
501
|
}
|
|
405
502
|
}
|
|
406
503
|
|
|
@@ -410,10 +507,10 @@ async function getNetworkInfo() {
|
|
|
410
507
|
* @returns {string} Formatted string
|
|
411
508
|
*/
|
|
412
509
|
function formatBytes(bytes) {
|
|
413
|
-
if (bytes === 0) return '0 Bytes';
|
|
510
|
+
if (bytes === 0 || bytes === null || bytes === undefined) return '0 Bytes';
|
|
414
511
|
const k = 1024;
|
|
415
512
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
|
416
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
513
|
+
const i = Math.floor(Math.log(Math.abs(bytes)) / Math.log(k));
|
|
417
514
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
418
515
|
}
|
|
419
516
|
|
|
@@ -423,85 +520,110 @@ function formatBytes(bytes) {
|
|
|
423
520
|
*/
|
|
424
521
|
async function getProcessInfo() {
|
|
425
522
|
try {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
si.
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
const [processes, currentProcessLoad, services] = await Promise.all([
|
|
526
|
+
si.processes().catch(() => ({ all: 0, running: 0, blocked: 0, sleeping: 0, list: [] })),
|
|
527
|
+
si.processLoad(process.pid).catch(() => ({})),
|
|
528
|
+
si.services('*').catch(() => [])
|
|
430
529
|
]);
|
|
431
530
|
|
|
531
|
+
// Get current process memory usage
|
|
532
|
+
const memUsage = process.memoryUsage();
|
|
533
|
+
|
|
432
534
|
// Format current process info
|
|
433
535
|
const formattedCurrentProcess = {
|
|
434
536
|
pid: process.pid,
|
|
435
|
-
ppid: process.ppid,
|
|
436
|
-
title: process.title,
|
|
437
|
-
name:
|
|
438
|
-
cpu:
|
|
439
|
-
mem:
|
|
537
|
+
ppid: process.ppid || 'Unknown',
|
|
538
|
+
title: process.title || 'Node.js Process',
|
|
539
|
+
name: currentProcessLoad.name || process.title || 'node',
|
|
540
|
+
cpu: currentProcessLoad.cpu !== undefined ? `${currentProcessLoad.cpu.toFixed(1)}%` : 'Unknown',
|
|
541
|
+
mem: currentProcessLoad.mem !== undefined ? `${currentProcessLoad.mem.toFixed(1)}%` : 'Unknown',
|
|
440
542
|
arch: process.arch,
|
|
441
543
|
platform: process.platform,
|
|
442
544
|
version: process.version,
|
|
443
545
|
memoryUsage: {
|
|
444
|
-
rss: formatBytes(
|
|
445
|
-
heapTotal: formatBytes(
|
|
446
|
-
heapUsed: formatBytes(
|
|
447
|
-
external: formatBytes(
|
|
448
|
-
arrayBuffers: formatBytes(
|
|
546
|
+
rss: formatBytes(memUsage.rss),
|
|
547
|
+
heapTotal: formatBytes(memUsage.heapTotal),
|
|
548
|
+
heapUsed: formatBytes(memUsage.heapUsed),
|
|
549
|
+
external: formatBytes(memUsage.external),
|
|
550
|
+
arrayBuffers: formatBytes(memUsage.arrayBuffers || 0)
|
|
449
551
|
},
|
|
450
552
|
uptime: process.uptime(),
|
|
451
553
|
cwd: process.cwd(),
|
|
452
|
-
execPath: process.execPath
|
|
554
|
+
execPath: process.execPath,
|
|
555
|
+
argv: process.argv,
|
|
556
|
+
execArgv: process.execArgv
|
|
453
557
|
};
|
|
454
558
|
|
|
455
|
-
// Format top processes (limited
|
|
456
|
-
const topProcesses = processes
|
|
559
|
+
// Format top processes (limited for performance and privacy)
|
|
560
|
+
const topProcesses = processes.list ?
|
|
457
561
|
processes.list
|
|
562
|
+
.filter(proc => proc.cpu !== undefined && proc.cpu !== null)
|
|
458
563
|
.sort((a, b) => (b.cpu || 0) - (a.cpu || 0))
|
|
459
|
-
.slice(0,
|
|
564
|
+
.slice(0, 15)
|
|
460
565
|
.map(proc => ({
|
|
461
|
-
pid: proc.pid,
|
|
566
|
+
pid: proc.pid || 'Unknown',
|
|
462
567
|
name: proc.name || 'Unknown',
|
|
463
|
-
cpu: proc.cpu !== undefined ? `${proc.cpu.toFixed(1)}%` : '
|
|
464
|
-
mem: proc.mem !== undefined ? `${proc.mem.toFixed(1)}%` : '
|
|
465
|
-
priority: proc.priority,
|
|
466
|
-
command: proc.command
|
|
568
|
+
cpu: proc.cpu !== undefined ? `${proc.cpu.toFixed(1)}%` : 'Unknown',
|
|
569
|
+
mem: proc.mem !== undefined ? `${proc.mem.toFixed(1)}%` : 'Unknown',
|
|
570
|
+
priority: proc.priority || 'Unknown',
|
|
571
|
+
command: proc.command || 'Unknown',
|
|
572
|
+
state: proc.state || 'Unknown'
|
|
467
573
|
})) : [];
|
|
468
574
|
|
|
469
|
-
// Format system services (limited
|
|
575
|
+
// Format system services (limited for performance and privacy)
|
|
470
576
|
const formattedServices = services
|
|
471
|
-
.slice(0,
|
|
577
|
+
.slice(0, 15)
|
|
472
578
|
.map(service => ({
|
|
473
|
-
name: service.name,
|
|
474
|
-
running: service.running,
|
|
475
|
-
startmode: service.startmode,
|
|
476
|
-
pids: service.pids
|
|
579
|
+
name: service.name || 'Unknown',
|
|
580
|
+
running: service.running || false,
|
|
581
|
+
startmode: service.startmode || 'Unknown',
|
|
582
|
+
pids: Array.isArray(service.pids) ? service.pids : [],
|
|
583
|
+
state: service.state || 'Unknown'
|
|
477
584
|
}));
|
|
478
585
|
|
|
479
|
-
|
|
586
|
+
const processInfo = {
|
|
480
587
|
currentProcess: formattedCurrentProcess,
|
|
481
588
|
summary: {
|
|
482
|
-
all: processes.all,
|
|
483
|
-
running: processes.running,
|
|
484
|
-
blocked: processes.blocked,
|
|
485
|
-
sleeping: processes.sleeping
|
|
589
|
+
all: processes.all || 0,
|
|
590
|
+
running: processes.running || 0,
|
|
591
|
+
blocked: processes.blocked || 0,
|
|
592
|
+
sleeping: processes.sleeping || 0,
|
|
593
|
+
unknown: processes.unknown || 0
|
|
486
594
|
},
|
|
487
595
|
topProcesses,
|
|
488
|
-
services: formattedServices
|
|
596
|
+
services: formattedServices,
|
|
597
|
+
timestamp: new Date().toISOString()
|
|
489
598
|
};
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
return processInfo;
|
|
490
602
|
} catch (error) {
|
|
491
|
-
|
|
492
|
-
|
|
603
|
+
|
|
604
|
+
// Fallback to basic process information
|
|
605
|
+
const memUsage = process.memoryUsage();
|
|
493
606
|
return {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
607
|
+
currentProcess: {
|
|
608
|
+
pid: process.pid,
|
|
609
|
+
ppid: process.ppid || 'Unknown',
|
|
610
|
+
title: process.title || 'Node.js Process',
|
|
611
|
+
arch: process.arch,
|
|
612
|
+
platform: process.platform,
|
|
613
|
+
version: process.version,
|
|
614
|
+
versions: process.versions,
|
|
615
|
+
memoryUsage: {
|
|
616
|
+
rss: formatBytes(memUsage.rss),
|
|
617
|
+
heapTotal: formatBytes(memUsage.heapTotal),
|
|
618
|
+
heapUsed: formatBytes(memUsage.heapUsed),
|
|
619
|
+
external: formatBytes(memUsage.external)
|
|
620
|
+
},
|
|
621
|
+
uptime: process.uptime(),
|
|
622
|
+
cwd: process.cwd(),
|
|
623
|
+
execPath: process.execPath
|
|
624
|
+
},
|
|
625
|
+
timestamp: new Date().toISOString(),
|
|
626
|
+
error: 'Limited process information available'
|
|
505
627
|
};
|
|
506
628
|
}
|
|
507
629
|
}
|
|
@@ -512,22 +634,25 @@ async function getProcessInfo() {
|
|
|
512
634
|
*/
|
|
513
635
|
async function getEnvironmentInfo() {
|
|
514
636
|
try {
|
|
637
|
+
|
|
638
|
+
|
|
515
639
|
const [users, shellInfo] = await Promise.all([
|
|
516
|
-
si.users(),
|
|
517
|
-
si.shell()
|
|
640
|
+
si.users().catch(() => []),
|
|
641
|
+
si.shell().catch(() => ({ available: false, history: [] }))
|
|
518
642
|
]);
|
|
519
643
|
|
|
520
644
|
// Get safe environment variables
|
|
521
645
|
const env = process.env;
|
|
522
646
|
const safeEnv = {};
|
|
523
647
|
|
|
524
|
-
// Filter out sensitive information
|
|
648
|
+
// Filter out sensitive information - only include safe environment variables
|
|
525
649
|
const safeKeys = [
|
|
526
650
|
'PATH', 'LANG', 'TERM', 'SHELL', 'HOME', 'USER', 'LOGNAME',
|
|
527
651
|
'TMPDIR', 'TZ', 'EDITOR', 'PAGER', 'LSCOLORS', 'TERM_PROGRAM',
|
|
528
652
|
'TERM_PROGRAM_VERSION', 'COLORTERM', 'DISPLAY', 'LC_ALL', 'LC_CTYPE',
|
|
529
653
|
'SHLVL', 'PWD', 'XDG_DATA_DIRS', 'XDG_RUNTIME_DIR', 'DESKTOP_SESSION',
|
|
530
|
-
'GDMSESSION', 'XDG_CURRENT_DESKTOP', 'XDG_SESSION_TYPE', 'WAYLAND_DISPLAY'
|
|
654
|
+
'GDMSESSION', 'XDG_CURRENT_DESKTOP', 'XDG_SESSION_TYPE', 'WAYLAND_DISPLAY',
|
|
655
|
+
'NODE_VERSION', 'npm_config_user_config', 'npm_config_cache'
|
|
531
656
|
];
|
|
532
657
|
|
|
533
658
|
for (const key of safeKeys) {
|
|
@@ -536,40 +661,64 @@ async function getEnvironmentInfo() {
|
|
|
536
661
|
}
|
|
537
662
|
}
|
|
538
663
|
|
|
664
|
+
// Add current user information
|
|
665
|
+
const userInfo = os.userInfo();
|
|
666
|
+
safeEnv['CURRENT_USER'] = userInfo.username || 'Unknown';
|
|
667
|
+
safeEnv['USER_HOME'] = userInfo.homedir || 'Unknown';
|
|
668
|
+
safeEnv['USER_SHELL'] = userInfo.shell || 'Unknown';
|
|
669
|
+
safeEnv['USER_UID'] = userInfo.uid || 'Unknown';
|
|
670
|
+
safeEnv['USER_GID'] = userInfo.gid || 'Unknown';
|
|
671
|
+
|
|
539
672
|
// Format user information (anonymized for privacy)
|
|
540
673
|
const formattedUsers = users.map(user => ({
|
|
541
|
-
user: user.user,
|
|
542
|
-
tty: user.tty,
|
|
543
|
-
date: user.date,
|
|
544
|
-
time: user.time,
|
|
545
|
-
ip: user.ip,
|
|
546
|
-
command: user.command
|
|
674
|
+
user: user.user || 'Unknown',
|
|
675
|
+
tty: user.tty || 'Unknown',
|
|
676
|
+
date: user.date || 'Unknown',
|
|
677
|
+
time: user.time || 'Unknown',
|
|
678
|
+
ip: user.ip || 'Unknown',
|
|
679
|
+
command: user.command || 'Unknown'
|
|
547
680
|
}));
|
|
548
681
|
|
|
549
|
-
// Format shell history (limited for privacy)
|
|
550
|
-
// Check if shellInfo.history exists and is an array before using slice and map
|
|
682
|
+
// Format shell history (very limited for privacy and security)
|
|
551
683
|
let formattedShellHistory = [];
|
|
552
684
|
if (shellInfo && shellInfo.history && Array.isArray(shellInfo.history)) {
|
|
553
|
-
formattedShellHistory = shellInfo.history
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
685
|
+
formattedShellHistory = shellInfo.history
|
|
686
|
+
.slice(-5) // Only last 5 commands
|
|
687
|
+
.map(cmd => ({
|
|
688
|
+
date: cmd.date || '',
|
|
689
|
+
time: cmd.time || '',
|
|
690
|
+
command: cmd.command ? cmd.command.substring(0, 50) + '...' : '' // Truncate for privacy
|
|
691
|
+
}));
|
|
558
692
|
}
|
|
559
693
|
|
|
560
|
-
|
|
694
|
+
const environmentInfo = {
|
|
561
695
|
variables: safeEnv,
|
|
562
|
-
|
|
696
|
+
user: {
|
|
697
|
+
username: userInfo.username || 'Unknown',
|
|
698
|
+
uid: userInfo.uid || 'Unknown',
|
|
699
|
+
gid: userInfo.gid || 'Unknown',
|
|
700
|
+
shell: userInfo.shell || 'Unknown',
|
|
701
|
+
homedir: userInfo.homedir || 'Unknown'
|
|
702
|
+
},
|
|
703
|
+
users: formattedUsers.slice(0, 10), // Limit for privacy
|
|
563
704
|
shell: {
|
|
564
|
-
available: shellInfo
|
|
705
|
+
available: shellInfo.available || false,
|
|
565
706
|
history: formattedShellHistory
|
|
566
|
-
}
|
|
707
|
+
},
|
|
708
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'Unknown',
|
|
709
|
+
locale: Intl.DateTimeFormat().resolvedOptions().locale || 'Unknown',
|
|
710
|
+
timestamp: new Date().toISOString()
|
|
567
711
|
};
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
return environmentInfo;
|
|
568
715
|
} catch (error) {
|
|
569
|
-
|
|
716
|
+
|
|
717
|
+
|
|
570
718
|
// Fallback to basic environment information
|
|
571
719
|
const env = process.env;
|
|
572
720
|
const safeEnv = {};
|
|
721
|
+
const userInfo = os.userInfo();
|
|
573
722
|
|
|
574
723
|
// Filter out sensitive information
|
|
575
724
|
const safeKeys = [
|
|
@@ -583,57 +732,80 @@ async function getEnvironmentInfo() {
|
|
|
583
732
|
}
|
|
584
733
|
}
|
|
585
734
|
|
|
586
|
-
return {
|
|
735
|
+
return {
|
|
736
|
+
variables: safeEnv,
|
|
737
|
+
user: {
|
|
738
|
+
username: userInfo.username || 'Unknown',
|
|
739
|
+
uid: userInfo.uid || 'Unknown',
|
|
740
|
+
gid: userInfo.gid || 'Unknown',
|
|
741
|
+
shell: userInfo.shell || 'Unknown',
|
|
742
|
+
homedir: userInfo.homedir || 'Unknown'
|
|
743
|
+
},
|
|
744
|
+
timestamp: new Date().toISOString(),
|
|
745
|
+
error: 'Limited environment information available'
|
|
746
|
+
};
|
|
587
747
|
}
|
|
588
748
|
}
|
|
589
749
|
|
|
590
750
|
/**
|
|
591
|
-
* Get system information based on query
|
|
592
|
-
* @param {string} query - The user's query
|
|
751
|
+
* Get system information based on query with enhanced AI integration
|
|
752
|
+
* @param {string} query - The user's query or category list
|
|
593
753
|
* @returns {Object} Relevant system information
|
|
594
754
|
*/
|
|
595
755
|
async function getSystemInfo(query = '') {
|
|
596
|
-
const
|
|
756
|
+
const startTime = Date.now();
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
const lowerQuery = (query || '').toLowerCase().trim();
|
|
597
760
|
let result = {};
|
|
761
|
+
const categoriesToFetch = [];
|
|
598
762
|
|
|
599
|
-
//
|
|
763
|
+
// Enhanced query patterns for natural language processing
|
|
600
764
|
const queryPatterns = {
|
|
601
765
|
cpu: [
|
|
602
766
|
'cpu', 'processor', 'core', 'thread', 'clock', 'speed', 'ghz', 'mhz',
|
|
603
767
|
'intel', 'amd', 'arm', 'load', 'usage', 'temperature', 'heat', 'cooling',
|
|
604
|
-
'performance', 'benchmark', 'processing', 'compute'
|
|
768
|
+
'performance', 'benchmark', 'processing', 'compute', 'cores', 'threads',
|
|
769
|
+
'frequency', 'cache', 'instruction', 'architecture', 'microprocessor'
|
|
605
770
|
],
|
|
606
771
|
memory: [
|
|
607
772
|
'memory', 'ram', 'dram', 'dimm', 'stick', 'module', 'bank', 'slot',
|
|
608
773
|
'free', 'available', 'used', 'total', 'swap', 'virtual memory', 'page',
|
|
609
|
-
'allocation', 'heap', 'stack', 'buffer'
|
|
774
|
+
'allocation', 'heap', 'stack', 'buffer', 'cache', 'physical memory',
|
|
775
|
+
'volatile memory', 'system memory', 'memory usage', 'memory allocation'
|
|
610
776
|
],
|
|
611
777
|
disk: [
|
|
612
778
|
'disk', 'drive', 'storage', 'hdd', 'ssd', 'nvme', 'partition', 'volume',
|
|
613
779
|
'filesystem', 'mount', 'space', 'capacity', 'free space', 'used space',
|
|
614
|
-
'read', 'write', 'io', 'block', 'sector', 'format', 'raid'
|
|
780
|
+
'read', 'write', 'io', 'block', 'sector', 'format', 'raid', 'hard drive',
|
|
781
|
+
'solid state', 'storage device', 'file system', 'directory', 'folder'
|
|
615
782
|
],
|
|
616
783
|
network: [
|
|
617
784
|
'network', 'internet', 'wifi', 'ethernet', 'connection', 'ip', 'address',
|
|
618
785
|
'mac', 'interface', 'adapter', 'wireless', 'wired', 'lan', 'wan', 'dns',
|
|
619
786
|
'gateway', 'router', 'subnet', 'mask', 'ping', 'latency', 'bandwidth',
|
|
620
|
-
'speed', 'download', 'upload', 'packet', 'traffic', 'port', 'socket'
|
|
787
|
+
'speed', 'download', 'upload', 'packet', 'traffic', 'port', 'socket',
|
|
788
|
+
'connectivity', 'protocol', 'tcp', 'udp', 'http', 'https'
|
|
621
789
|
],
|
|
622
790
|
process: [
|
|
623
791
|
'process', 'running', 'task', 'application', 'app', 'program', 'service',
|
|
624
792
|
'daemon', 'thread', 'job', 'pid', 'kill', 'terminate', 'start', 'stop',
|
|
625
|
-
'restart', 'crash', 'hang', 'freeze', 'responsive', 'background', 'foreground'
|
|
793
|
+
'restart', 'crash', 'hang', 'freeze', 'responsive', 'background', 'foreground',
|
|
794
|
+
'processes', 'services', 'applications', 'system process', 'user process'
|
|
626
795
|
],
|
|
627
796
|
environment: [
|
|
628
797
|
'environment', 'env', 'variable', 'path', 'user', 'shell', 'terminal',
|
|
629
798
|
'console', 'profile', 'config', 'configuration', 'setting', 'preference',
|
|
630
|
-
'login', 'session', 'account', 'permission', 'access', 'privilege'
|
|
799
|
+
'login', 'session', 'account', 'permission', 'access', 'privilege',
|
|
800
|
+
'variables', 'system config', 'user config', 'bash', 'zsh', 'cmd'
|
|
631
801
|
],
|
|
632
802
|
basic: [
|
|
633
803
|
'os', 'system', 'platform', 'version', 'release', 'build', 'kernel',
|
|
634
804
|
'distribution', 'distro', 'windows', 'mac', 'linux', 'unix', 'android',
|
|
635
805
|
'ios', 'architecture', 'arch', 'bit', '32-bit', '64-bit', 'x86', 'x64',
|
|
636
|
-
'arm', 'machine', 'hardware', 'device', 'model', 'manufacturer', 'vendor'
|
|
806
|
+
'arm', 'machine', 'hardware', 'device', 'model', 'manufacturer', 'vendor',
|
|
807
|
+
'computer', 'info', 'information', 'details', 'specs', 'specification',
|
|
808
|
+
'overview', 'summary', 'general', 'basic', 'hostname', 'uptime'
|
|
637
809
|
]
|
|
638
810
|
};
|
|
639
811
|
|
|
@@ -643,9 +815,11 @@ async function getSystemInfo(query = '') {
|
|
|
643
815
|
};
|
|
644
816
|
|
|
645
817
|
// Determine what information to return based on the query
|
|
646
|
-
if (lowerQuery.includes('all') || lowerQuery === '') {
|
|
647
|
-
|
|
648
|
-
|
|
818
|
+
if (lowerQuery.includes('all') || lowerQuery === '' || lowerQuery.includes('everything') || lowerQuery.includes('complete')) {
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
// Get all information in parallel for better performance
|
|
822
|
+
const [basic, cpu, memory, disk, network, process, environment] = await Promise.allSettled([
|
|
649
823
|
getBasicSystemInfo(),
|
|
650
824
|
getCpuInfo(),
|
|
651
825
|
getMemoryInfo(),
|
|
@@ -655,48 +829,118 @@ async function getSystemInfo(query = '') {
|
|
|
655
829
|
getEnvironmentInfo()
|
|
656
830
|
]);
|
|
657
831
|
|
|
658
|
-
|
|
832
|
+
// Handle results, including any that may have failed
|
|
833
|
+
result = {
|
|
834
|
+
basic: basic.status === 'fulfilled' ? basic.value : { error: basic.reason?.message || 'Failed to fetch basic info' },
|
|
835
|
+
cpu: cpu.status === 'fulfilled' ? cpu.value : { error: cpu.reason?.message || 'Failed to fetch CPU info' },
|
|
836
|
+
memory: memory.status === 'fulfilled' ? memory.value : { error: memory.reason?.message || 'Failed to fetch memory info' },
|
|
837
|
+
disk: disk.status === 'fulfilled' ? disk.value : { error: disk.reason?.message || 'Failed to fetch disk info' },
|
|
838
|
+
network: network.status === 'fulfilled' ? network.value : { error: network.reason?.message || 'Failed to fetch network info' },
|
|
839
|
+
process: process.status === 'fulfilled' ? process.value : { error: process.reason?.message || 'Failed to fetch process info' },
|
|
840
|
+
environment: environment.status === 'fulfilled' ? environment.value : { error: environment.reason?.message || 'Failed to fetch environment info' }
|
|
841
|
+
};
|
|
659
842
|
} else {
|
|
660
|
-
// Process
|
|
661
|
-
const
|
|
843
|
+
// Process categories from the query string (space-separated)
|
|
844
|
+
const queryCategories = lowerQuery.split(/\s+/).filter(cat =>
|
|
845
|
+
['basic', 'cpu', 'memory', 'disk', 'network', 'process', 'environment'].includes(cat)
|
|
846
|
+
);
|
|
662
847
|
|
|
663
|
-
//
|
|
664
|
-
if (
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
848
|
+
// If specific categories were mentioned in the query, use those
|
|
849
|
+
if (queryCategories.length > 0) {
|
|
850
|
+
categoriesToFetch.push(...queryCategories);
|
|
851
|
+
|
|
852
|
+
} else {
|
|
853
|
+
// Use pattern matching to determine categories
|
|
854
|
+
if (matchesCategory('cpu')) categoriesToFetch.push('cpu');
|
|
855
|
+
if (matchesCategory('memory')) categoriesToFetch.push('memory');
|
|
856
|
+
if (matchesCategory('disk')) categoriesToFetch.push('disk');
|
|
857
|
+
if (matchesCategory('network')) categoriesToFetch.push('network');
|
|
858
|
+
if (matchesCategory('process')) categoriesToFetch.push('process');
|
|
859
|
+
if (matchesCategory('environment')) categoriesToFetch.push('environment');
|
|
860
|
+
if (matchesCategory('basic')) categoriesToFetch.push('basic');
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
}
|
|
671
864
|
|
|
672
865
|
// If no specific category was matched, get basic info
|
|
673
866
|
if (categoriesToFetch.length === 0) {
|
|
674
867
|
categoriesToFetch.push('basic');
|
|
868
|
+
|
|
675
869
|
}
|
|
676
870
|
|
|
677
|
-
//
|
|
871
|
+
// Remove duplicates
|
|
872
|
+
const uniqueCategories = [...new Set(categoriesToFetch)];
|
|
873
|
+
|
|
874
|
+
// Fetch all requested categories in parallel for better performance
|
|
678
875
|
const promises = [];
|
|
679
|
-
|
|
680
|
-
if (categoriesToFetch.includes('cpu')) promises.push(getCpuInfo());
|
|
681
|
-
if (categoriesToFetch.includes('memory')) promises.push(getMemoryInfo());
|
|
682
|
-
if (categoriesToFetch.includes('disk')) promises.push(getDiskInfo());
|
|
683
|
-
if (categoriesToFetch.includes('network')) promises.push(getNetworkInfo());
|
|
684
|
-
if (categoriesToFetch.includes('process')) promises.push(getProcessInfo());
|
|
685
|
-
if (categoriesToFetch.includes('environment')) promises.push(getEnvironmentInfo());
|
|
876
|
+
const promiseMap = {};
|
|
686
877
|
|
|
687
|
-
|
|
878
|
+
uniqueCategories.forEach(category => {
|
|
879
|
+
switch (category) {
|
|
880
|
+
case 'basic':
|
|
881
|
+
promises.push(getBasicSystemInfo());
|
|
882
|
+
promiseMap[promises.length - 1] = 'basic';
|
|
883
|
+
break;
|
|
884
|
+
case 'cpu':
|
|
885
|
+
promises.push(getCpuInfo());
|
|
886
|
+
promiseMap[promises.length - 1] = 'cpu';
|
|
887
|
+
break;
|
|
888
|
+
case 'memory':
|
|
889
|
+
promises.push(getMemoryInfo());
|
|
890
|
+
promiseMap[promises.length - 1] = 'memory';
|
|
891
|
+
break;
|
|
892
|
+
case 'disk':
|
|
893
|
+
promises.push(getDiskInfo());
|
|
894
|
+
promiseMap[promises.length - 1] = 'disk';
|
|
895
|
+
break;
|
|
896
|
+
case 'network':
|
|
897
|
+
promises.push(getNetworkInfo());
|
|
898
|
+
promiseMap[promises.length - 1] = 'network';
|
|
899
|
+
break;
|
|
900
|
+
case 'process':
|
|
901
|
+
promises.push(getProcessInfo());
|
|
902
|
+
promiseMap[promises.length - 1] = 'process';
|
|
903
|
+
break;
|
|
904
|
+
case 'environment':
|
|
905
|
+
promises.push(getEnvironmentInfo());
|
|
906
|
+
promiseMap[promises.length - 1] = 'environment';
|
|
907
|
+
break;
|
|
908
|
+
}
|
|
909
|
+
});
|
|
910
|
+
|
|
911
|
+
const results = await Promise.allSettled(promises);
|
|
688
912
|
|
|
689
913
|
// Assign results to the appropriate categories
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
914
|
+
results.forEach((promiseResult, index) => {
|
|
915
|
+
const category = promiseMap[index];
|
|
916
|
+
if (promiseResult.status === 'fulfilled') {
|
|
917
|
+
result[category] = promiseResult.value;
|
|
918
|
+
} else {
|
|
919
|
+
result[category] = {
|
|
920
|
+
error: promiseResult.reason?.message || `Failed to fetch ${category} information`,
|
|
921
|
+
timestamp: new Date().toISOString()
|
|
922
|
+
};
|
|
923
|
+
|
|
924
|
+
}
|
|
925
|
+
});
|
|
698
926
|
}
|
|
699
927
|
|
|
928
|
+
// Add metadata to the result
|
|
929
|
+
result._metadata = {
|
|
930
|
+
query: query,
|
|
931
|
+
processedAt: new Date().toISOString(),
|
|
932
|
+
user: 'm0v0dga_walmart',
|
|
933
|
+
processingTimeMs: Date.now() - startTime,
|
|
934
|
+
categoriesFetched: Object.keys(result).filter(key => key !== '_metadata'),
|
|
935
|
+
nodeVersion: process.version,
|
|
936
|
+
platform: os.platform(),
|
|
937
|
+
arch: os.arch()
|
|
938
|
+
};
|
|
939
|
+
|
|
940
|
+
const endTime = Date.now();
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
|
|
700
944
|
return result;
|
|
701
945
|
}
|
|
702
946
|
|