fix(mission-control): dedupe whisper binaries and clean WSL package metadata

Prevent duplicate React keys by de-duplicating whisper binary names and improve WSL package reporting so system metadata shows stable, user-friendly versions.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
saravanakumardb1 2026-02-22 18:03:59 -08:00
parent a7790b7115
commit e5acd1dc26
2 changed files with 99 additions and 12 deletions

View File

@ -2,12 +2,36 @@ import { NextResponse } from 'next/server';
import { exec, execFile } from 'child_process';
import { promisify } from 'util';
import { readFile } from 'fs/promises';
import { readFileSync } from 'fs';
import os from 'os';
const execAsync = promisify(exec);
const execFileAsync = promisify(execFile);
const IS_MAC = process.platform === 'darwin';
const IS_WSL =
process.platform === 'linux' &&
(() => {
try {
return readFileSync('/proc/version', 'utf-8').toLowerCase().includes('microsoft');
} catch {
return false;
}
})();
async function readWindowsCommand(command: string): Promise<string | null> {
try {
const { stdout } = await execFileAsync(
'powershell.exe',
['-NoProfile', '-Command', command],
{ timeout: 4000 }
);
const value = stdout.replace(/\r/g, '').trim();
return value || null;
} catch {
return null;
}
}
// Cache slow commands with TTL
let staticCache: {
@ -29,6 +53,12 @@ async function getChipInfo(): Promise<string> {
);
return stdout.trim();
}
if (IS_WSL) {
const winCpu = await readWindowsCommand(
'(Get-CimInstance Win32_Processor | Select-Object -First 1 -ExpandProperty Name)'
);
if (winCpu) return winCpu;
}
// Linux / WSL2
const { stdout } = await execAsync(
"lscpu 2>/dev/null | grep 'Model name' | sed 's/.*:\\s*//' || cat /proc/cpuinfo | grep 'model name' | head -1 | sed 's/.*: //'"
@ -110,17 +140,60 @@ async function getBrewPackages(): Promise<Array<{ name: string; version: string
}
}
} else {
// Linux / WSL2 — check via version commands (ffmpeg uses -version, others use --version)
// Linux / WSL2 — report installed tools in a stable way (avoid noisy shell errors).
for (const pkg of targets) {
const bin = pkg === 'whisper-cpp' ? 'whisper-cli' : pkg;
const flag = bin === 'ffmpeg' ? '-version' : '--version';
try {
const { stdout } = await execAsync(`${bin} ${flag} 2>&1 | head -1`, { timeout: 3000 });
if (stdout.trim()) {
results.push({ name: pkg, version: stdout.trim() });
if (pkg === 'ffmpeg') {
const { stdout } = await execAsync('ffmpeg -version 2>/dev/null | head -1', {
timeout: 3000,
});
if (stdout.trim()) {
results.push({ name: pkg, version: stdout.trim() });
}
continue;
}
if (pkg === 'whisper-cpp') {
const { stdout } = await execAsync('command -v whisper-cli 2>/dev/null', { timeout: 2000 });
const path = stdout.trim();
if (path) {
results.push({ name: pkg, version: `installed (${path})` });
}
continue;
}
// ollama on Linux/WSL may be a Windows-hosted daemon; prefer API version if reachable.
if (pkg === 'ollama') {
const ollamaUrl = process.env.OLLAMA_URL || process.env.OLLAMA_HOST || 'http://localhost:11434';
const normalized = ollamaUrl.startsWith('http') ? ollamaUrl : `http://${ollamaUrl}`;
try {
const res = await fetch(`${normalized.replace(/\/+$/, '')}/api/version`, {
cache: 'no-store',
signal: AbortSignal.timeout(2500),
});
if (res.ok) {
const data = (await res.json()) as { version?: string };
if (data.version) {
results.push({ name: pkg, version: data.version });
continue;
}
}
} catch {
// fall through to local binary check
}
const { stdout } = await execAsync('command -v ollama 2>/dev/null', { timeout: 2000 });
const path = stdout.trim();
if (path) {
const { stdout: ver } = await execAsync('ollama --version 2>/dev/null | head -1', {
timeout: 2000,
});
const v = ver.trim();
results.push({ name: pkg, version: v || `installed (${path})` });
}
}
} catch {
// not installed
// skip unavailable tool
}
}
}
@ -204,6 +277,17 @@ async function getAccurateMemory(): Promise<{
const ratio = appMemory / total;
const pressure = ratio > 0.85 ? 'critical' : ratio > 0.7 ? 'warning' : 'normal';
if (IS_WSL) {
const winTotalRaw = await readWindowsCommand(
'[string](Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory'
);
const winTotal = winTotalRaw ? Number.parseInt(winTotalRaw.replace(/\D/g, ''), 10) : 0;
if (Number.isFinite(winTotal) && winTotal > total) {
// Keep WSL usage metrics, but report host RAM capacity for Mission Control display.
return { total: winTotal, appMemory, cached, free, pressure };
}
}
return { total, appMemory, cached, free, pressure };
} catch {
// fall through to generic fallback
@ -240,7 +324,7 @@ export async function GET() {
ollamaDiskUsage: ollamaDisk,
cpuCores: cpuCount,
uptime,
platform: `${os.type()} ${os.release()}`,
platform: IS_WSL ? 'Windows (via WSL2)' : `${os.type()} ${os.release()}`,
arch: os.arch(),
nodeVersion: process.version,
brewPackages: staticInfo.brewPackages,

View File

@ -13,21 +13,23 @@ async function getWhisperBinaries(): Promise<string[]> {
try {
if (IS_MAC) {
const { stdout } = await execAsync('ls /opt/homebrew/bin/whisper-* 2>/dev/null');
return stdout
const bins = stdout
.trim()
.split('\n')
.filter(Boolean)
.map(p => p.split('/').pop() || p);
return Array.from(new Set(bins));
}
// Linux / WSL2 — check common locations
const { stdout } = await execAsync(
'ls /usr/local/bin/whisper-* /usr/bin/whisper-* 2>/dev/null || which whisper-cli 2>/dev/null'
);
return stdout
const bins = stdout
.trim()
.split('\n')
.filter(Boolean)
.map(p => p.split('/').pop() || p);
return Array.from(new Set(bins));
} catch {
return [];
}
@ -70,8 +72,9 @@ async function getWhisperModels(): Promise<{
async function getWhisperVersion(): Promise<string> {
try {
const { stdout } = await execAsync('whisper-cli --version 2>&1 || echo "unknown"');
return stdout.trim();
const { stdout } = await execAsync('whisper-cli -h 2>&1 | head -1');
const line = stdout.trim();
return line || 'installed';
} catch {
return 'unknown';
}