Files
EveFlow/electron/ipc/telemetry.ts
T
Claude 127a2083a1 feat!: rebuild EveFlow as a JARVIS-style voice HUD for Hermes Agent (v2.0.0)
Complete rewrite of the application:

- Toolchain: Electron 44, Vite 8, React 19, TypeScript 5.9, Zustand, Vitest;
  main process rewritten in TypeScript (electron/), typed IPC contract (shared/),
  sandboxed renderer with webSecurity on and an HTTP/SSE proxy in the main process.
- Voice: AudioWorklet microphone capture at 16 kHz with adaptive energy VAD and
  auto-stop, WAV encoder, OpenAI-compatible STT, TTS queue with sentence-level
  streaming, prefetch and Web Audio playback feeding an analyser; hands-free mode,
  global push-to-talk hotkey, system-voice fallback.
- Hermes: full API client (capabilities, health, models, skills, toolsets,
  sessions, jobs) with automatic transport selection: runs API (SSE lifecycle,
  approvals, steer, stop) > sessions stream > chat completions with local tools;
  tolerant event normalisation; webhook receiver hardened (secret, size limit).
- UI: JARVIS arc-reactor core on Canvas 2D reacting to the real audio signal,
  holographic HUD layout (transcript, core, Hermes ops panel with tools/crons/
  skills/sessions/link tabs, telemetry), settings drawer, approval modals,
  compact floating widget, four themes, tray icon and global shortcuts.
- Removed the 3D Eve robot, three.js and legacy assets; migrated 1.x settings.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y
2026-09-03 13:40:59 +00:00

52 lines
1.4 KiB
TypeScript

import { ipcMain } from 'electron';
import os from 'node:os';
import { IPC, type SystemMetrics } from '../../shared/ipc';
interface CpuSnapshot {
idle: number;
total: number;
}
function snapshot(): CpuSnapshot {
let idle = 0;
let total = 0;
for (const cpu of os.cpus()) {
const t = cpu.times;
idle += t.idle;
total += t.user + t.nice + t.sys + t.idle + t.irq;
}
return { idle, total };
}
let last = snapshot();
function cpuLoadPct(): number {
const now = snapshot();
const idleDiff = now.idle - last.idle;
const totalDiff = now.total - last.total;
last = now;
if (totalDiff <= 0) return 0;
return Math.max(0, Math.min(100, 100 * (1 - idleDiff / totalDiff)));
}
export function collectMetrics(): SystemMetrics {
const cpus = os.cpus();
const totalMem = os.totalmem();
const freeMem = os.freemem();
return {
hostname: os.hostname().toUpperCase(),
platform: `${os.platform()} ${os.release()}`,
cpuModel: cpus[0]?.model?.trim() ?? 'CPU',
cpuCores: cpus.length,
cpuLoad: Math.round(cpuLoadPct() * 10) / 10,
cpuFreqMhz: cpus[0]?.speed ?? 0,
memUsedPct: totalMem > 0 ? Math.round(((totalMem - freeMem) / totalMem) * 1000) / 10 : 0,
memTotalGb: Math.round((totalMem / 1024 ** 3) * 10) / 10,
uptimeSec: Math.round(os.uptime())
};
}
export function registerTelemetryIpc(): void {
ipcMain.handle(IPC.metrics, () => collectMetrics());
}