feat(stats): wire stats server, overlay, and CLI into main process

- Stats server auto-start on immersion tracker init
- Stats overlay toggle via keybinding and IPC
- Stats CLI command (subminer stats) with cleanup mode
- mpv plugin menu integration for stats toggle
- CLI args for --stats, --stats-cleanup, --stats-response-path
This commit is contained in:
2026-03-14 22:14:32 -07:00
parent ffe5c6e1c6
commit 26fb5b4162
37 changed files with 374 additions and 23 deletions

View File

@@ -29,6 +29,10 @@ export interface CliArgs {
anilistRetryQueue: boolean;
dictionary: boolean;
dictionaryTarget?: string;
stats: boolean;
statsCleanup?: boolean;
statsCleanupVocab?: boolean;
statsResponsePath?: string;
jellyfin: boolean;
jellyfinLogin: boolean;
jellyfinLogout: boolean;
@@ -97,6 +101,9 @@ export function parseArgs(argv: string[]): CliArgs {
anilistSetup: false,
anilistRetryQueue: false,
dictionary: false,
stats: false,
statsCleanup: false,
statsCleanupVocab: false,
jellyfin: false,
jellyfinLogin: false,
jellyfinLogout: false,
@@ -162,6 +169,15 @@ export function parseArgs(argv: string[]): CliArgs {
} else if (arg === '--dictionary-target') {
const value = readValue(argv[i + 1]);
if (value) args.dictionaryTarget = value;
} else if (arg === '--stats') args.stats = true;
else if (arg === '--stats-cleanup') args.statsCleanup = true;
else if (arg === '--stats-cleanup-vocab') args.statsCleanupVocab = true;
else if (arg.startsWith('--stats-response-path=')) {
const value = arg.split('=', 2)[1];
if (value) args.statsResponsePath = value;
} else if (arg === '--stats-response-path') {
const value = readValue(argv[i + 1]);
if (value) args.statsResponsePath = value;
} else if (arg === '--jellyfin') args.jellyfin = true;
else if (arg === '--jellyfin-login') args.jellyfinLogin = true;
else if (arg === '--jellyfin-logout') args.jellyfinLogout = true;
@@ -331,6 +347,7 @@ export function hasExplicitCommand(args: CliArgs): boolean {
args.anilistSetup ||
args.anilistRetryQueue ||
args.dictionary ||
args.stats ||
args.jellyfin ||
args.jellyfinLogin ||
args.jellyfinLogout ||
@@ -367,6 +384,7 @@ export function shouldStartApp(args: CliArgs): boolean {
args.markAudioCard ||
args.openRuntimeOptions ||
args.dictionary ||
args.stats ||
args.jellyfin ||
args.jellyfinPlay ||
args.texthooker
@@ -408,6 +426,7 @@ export function shouldRunSettingsOnlyStartup(args: CliArgs): boolean {
!args.anilistSetup &&
!args.anilistRetryQueue &&
!args.dictionary &&
!args.stats &&
!args.jellyfin &&
!args.jellyfinLogin &&
!args.jellyfinLogout &&