diff --git a/docs/plans/state.json b/docs/plans/state.json index f8ec337..7accf2a 100644 --- a/docs/plans/state.json +++ b/docs/plans/state.json @@ -5624,6 +5624,18 @@ "docs/plans/state.json" ], "test_status": "pnpm test:run src/tools/builtin/system-info.test.ts + pnpm typecheck passing" + }, + "system-info-human-readable-formatting": { + "status": "completed", + "date": "2026-02-19", + "updated": "2026-02-19", + "summary": "Refined `system.info` output into a human-readable structured snapshot with Host/Resources/Time/Process sections, clearer labels, memory+disk usage percentages, and a compact health summary.", + "files_modified": [ + "src/tools/builtin/system-info.ts", + "src/tools/builtin/system-info.test.ts", + "docs/plans/state.json" + ], + "test_status": "pnpm test:run src/tools/builtin/system-info.test.ts + pnpm typecheck passing" } }, "overall_progress": { diff --git a/src/tools/builtin/system-info.test.ts b/src/tools/builtin/system-info.test.ts index fa4666f..ee574e7 100644 --- a/src/tools/builtin/system-info.test.ts +++ b/src/tools/builtin/system-info.test.ts @@ -34,15 +34,16 @@ describe('system.info tool', () => { const output = getOutput(result.output); const expectedFields = [ - 'Date:', - 'Time:', + 'System Snapshot', + 'Host', + 'Resources', + 'Storage', + 'Time', 'Hostname:', 'Platform:', - 'Architecture:', 'Node.js:', 'Uptime:', - 'Memory Total:', - 'Disk', + 'Memory:', ]; for (const field of expectedFields) { diff --git a/src/tools/builtin/system-info.ts b/src/tools/builtin/system-info.ts index 9c3008f..4ebe97f 100644 --- a/src/tools/builtin/system-info.ts +++ b/src/tools/builtin/system-info.ts @@ -13,7 +13,7 @@ function formatBytes(bytes: number): string { return (bytes / (1024 * 1024 * 1024)).toFixed(2) + ' GB'; } -function getDiskUsageSummary(): string[] { +function getDiskUsageSummary(): { lines: string[]; usedPct?: number } { try { const rootPath = process.platform === 'win32' ? process.cwd().slice(0, 3) : '/'; const stat = statfsSync(rootPath); @@ -22,7 +22,15 @@ function getDiskUsageSummary(): string[] { const freeBlocks = typeof stat.bavail === 'number' ? stat.bavail : Number(stat.bavail); if (!Number.isFinite(blockSize) || !Number.isFinite(totalBlocks) || !Number.isFinite(freeBlocks)) { - return ['Disk: unavailable']; + return { + lines: [ + 'Storage', + '- Root Path: unavailable', + '- Total: unavailable', + '- Free: unavailable', + '- Used: unavailable', + ], + }; } const totalBytes = totalBlocks * blockSize; @@ -30,14 +38,26 @@ function getDiskUsageSummary(): string[] { const usedBytes = Math.max(0, totalBytes - freeBytes); const usedPct = totalBytes > 0 ? (usedBytes / totalBytes) * 100 : 0; - return [ - `Disk Path: ${rootPath}`, - `Disk Total: ${formatBytes(totalBytes)}`, - `Disk Free: ${formatBytes(freeBytes)}`, - `Disk Used: ${formatBytes(usedBytes)} (${usedPct.toFixed(1)}%)`, - ]; + return { + lines: [ + 'Storage', + `- Root Path: ${rootPath}`, + `- Total: ${formatBytes(totalBytes)}`, + `- Free: ${formatBytes(freeBytes)}`, + `- Used: ${formatBytes(usedBytes)} (${usedPct.toFixed(1)}%)`, + ], + usedPct, + }; } catch { - return ['Disk: unavailable']; + return { + lines: [ + 'Storage', + '- Root Path: unavailable', + '- Total: unavailable', + '- Free: unavailable', + '- Used: unavailable', + ], + }; } } @@ -65,24 +85,42 @@ export const systemInfoTool: Tool = { hour12: false, }); const isoStr = now.toISOString(); + const localStr = now.toLocaleString(); const totalMem = os.totalmem(); const freeMem = os.freemem(); + const usedMem = Math.max(0, totalMem - freeMem); + const usedMemPct = totalMem > 0 ? (usedMem / totalMem) * 100 : 0; + const disk = getDiskUsageSummary(); + const memoryHealth = usedMemPct < 75 ? 'healthy' : usedMemPct < 90 ? 'moderate' : 'high'; + const diskHealth = typeof disk.usedPct === 'number' + ? (disk.usedPct < 75 ? 'healthy' : disk.usedPct < 90 ? 'moderate' : 'high') + : 'unknown'; const lines = [ - `Date: ${dateStr}`, - `Time: ${timeStr}`, - `ISO 8601: ${isoStr}`, - `Hostname: ${os.hostname()}`, - `Platform: ${os.platform()}`, - `Architecture: ${os.arch()}`, - `OS Release: ${os.release()}`, - `Uptime: ${formatUptime(os.uptime())}`, - `Node.js: ${process.version}`, - `Memory Total: ${formatBytes(totalMem)}`, - `Memory Free: ${formatBytes(freeMem)}`, - ...getDiskUsageSummary(), - `Working Dir: ${process.cwd()}`, + 'System Snapshot', + '', + 'Host', + `- Hostname: ${os.hostname()}`, + `- OS: ${os.type()} ${os.release()}`, + `- Platform: ${os.platform()} (${os.arch()})`, + `- Node.js: ${process.version}`, + `- Uptime: ${formatUptime(os.uptime())}`, + '', + 'Resources', + `- Memory: ${formatBytes(usedMem)} used / ${formatBytes(totalMem)} total (${usedMemPct.toFixed(1)}% used, ${memoryHealth})`, + `- Memory Free: ${formatBytes(freeMem)}`, + ...disk.lines.map((line) => (line === 'Storage' ? line : `${line}`)), + '', + 'Time', + `- Local: ${localStr}`, + `- Date: ${dateStr}`, + `- Time: ${timeStr}`, + `- ISO 8601: ${isoStr}`, + '', + 'Process', + `- Working Dir: ${process.cwd()}`, + `- Health Summary: memory=${memoryHealth}, disk=${diskHealth}`, ]; return { success: true, output: lines.join('\n') };