fix: harden cross-platform paths and child-process handling

Replace process.env.HOME fallbacks with os.homedir() in dashboard usage
probes and the hermes plugin profile resolver so unset HOME no longer
yields literal "~" paths. Skip POSIX process-group semantics on Windows
in engine/merger and dashboard-tui's pgrep-based vitest killer. Add
shell: true to npx spawns in CLI skills/extension so .cmd shims resolve
on Windows, and route test:build-exe through cross-env.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-27 23:27:27 -07:00
parent f1bef9e422
commit 4e2131f444
8 changed files with 41 additions and 11 deletions

View File

@@ -1,3 +1,4 @@
import * as os from "node:os";
import * as path from "node:path";
import { readFile } from "node:fs/promises";
import * as https from "node:https";
@@ -845,8 +846,8 @@ async function fetchClaudeUsage(): Promise<ProviderUsage> {
// ── Credential reading for plan detection & auth check ──────────────
const credPaths = [
path.join(process.env.HOME || "~", ".claude", ".credentials.json"),
path.join(process.env.HOME || "~", ".config", "claude", ".credentials.json"),
path.join(os.homedir(), ".claude", ".credentials.json"),
path.join(os.homedir(), ".config", "claude", ".credentials.json"),
];
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- untyped credentials JSON
@@ -1066,7 +1067,7 @@ async function fetchCodexUsage(): Promise<ProviderUsage> {
};
// Load Codex auth
const codexHome = process.env.CODEX_HOME || path.join(process.env.HOME || "~", ".codex");
const codexHome = process.env.CODEX_HOME || path.join(os.homedir(), ".codex");
const authPath = path.join(codexHome, "auth.json");
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- untyped auth JSON
@@ -1181,7 +1182,7 @@ async function fetchGeminiUsage(): Promise<ProviderUsage> {
};
// Load Gemini OAuth credentials
const oauthPath = path.join(process.env.HOME || "~", ".gemini", "oauth_creds.json");
const oauthPath = path.join(os.homedir(), ".gemini", "oauth_creds.json");
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- untyped OAuth JSON
let oauthCreds: any = null;
try {
@@ -1203,7 +1204,7 @@ async function fetchGeminiUsage(): Promise<ProviderUsage> {
}
// Check auth type from settings
const settingsPath = path.join(process.env.HOME || "~", ".gemini", "settings.json");
const settingsPath = path.join(os.homedir(), ".gemini", "settings.json");
try {
const settings = JSON.parse(await readFile(settingsPath, "utf-8"));
const authType = settings?.security?.auth?.selectedType;