fix: Windows/Termux compatibility, comic theme fonts, and UI fixes (#630)
* fix: comprehensive Windows compatibility and gateway management improvements This commit addresses multiple Windows compatibility issues and improves gateway management across all platforms. ## Windows Compatibility Fixes - Add hermes-path.ts with cross-platform Hermes home/bin detection - Fix Windows native installation paths (%LOCALAPPDATA%\hermes) - Update terminal.ts to use PowerShell instead of /bin/bash on Windows - Fix upload.ts path construction to use path.join() for cross-platform paths - Fix download.ts to use isAbsolute() for Windows absolute path detection - Update auth.ts to skip file mode 0o600 on Windows (unsupported) - Add nodemon.json for cross-platform environment variable handling ## Gateway Management Improvements - Simplify gateway startup: all platforms use 'run' mode uniformly - Remove complex init system detection and platform-specific code paths - Improve PID file validation: use health check instead of port detection - Remove getPortByPid() method (too complex and error-prone) - Remove checkPortAvailable() TCP bind test (TIME_WAIT false positives) - Trust gateway --replace flag to handle real port conflicts - Add smart PID validation: check if stale process via health check - Fix port allocation to avoid incrementing when gateway restarts - Add allocatedPorts.clear() on each startAll() call - Add clearPidFile() method to clean up stale PID files ## Process Management - Remove detached:true and unref() from gateway spawn - Gateway processes now follow parent process lifecycle - Add process reference storage in ManagedGateway interface - Improve shutdown logic: call gatewayManager.stopAll() before exit - Fix Windows process killing: use process.kill(pid) for Windows - Remove PowerShell command for lock file cleanup (use Node.js fs.unlinkSync) ## Frontend Theme Fixes - Fix main.ts localStorage key mismatch (hermes_theme → hermes_brightness) - Add inline script in index.html to prevent FOUC (Flash of Unstyled Content) - Apply theme classes before Vue mount to avoid visual glitches ## Developer Experience - Fix nodemon windows-kill popup on Windows by removing signal config - Add delay and environment variables to nodemon.json - Add windowsHide: true to all child process spawns ## Breaking Changes - Gateway management now exclusively uses 'run' mode on all platforms - systemd/launchd integration removed (use --replace flag instead) This fix ensures hermes-web-ui works correctly on Windows native installations while maintaining compatibility with Linux/macOS/WSL2. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix gateway lifecycle port handling * fix: comprehensive Windows compatibility and gateway management improvements - Simplified hermes CLI binary resolution logic - Fixed Windows line ending compatibility in profile list parsing - Migrated gateway restart logic from CLI to GatewayManager - Added gateway restart to updateCredentials method - Removed unnecessary gateway restarts from provider operations - Fixed configuration preservation when switching profiles - Added nodemon quiet mode and legacy watch to reduce Windows popups Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * revert: change back to nodemon due to tsx compatibility issues - tsx has compatibility issues with Koa generator functions - Restored nodemon with simplified configuration - Added cross-env package for future Windows environment variable needs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: replace nodemon with ts-node-dev to eliminate Windows popup windows - Installed ts-node-dev as nodemon replacement - ts-node-dev has better Windows compatibility without console popups - Supports respawning, inspector debugging, and TypeScript compilation - Uses cross-env for Windows environment variable support - Removed nodemon.json configuration file (no longer needed) Benefits: - No more Windows console popup windows during development - Faster restart times compared to nodemon - Built-in TypeScript compilation without ts-node overhead Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: improve log parsing and Windows compatibility for agent/error logs - Fixed Pino JSON log parsing bug where logger field incorrectly used obj.msg - Changed logger field to use obj.name to properly display log source - Added Windows line ending support (\r\n) for log file listing - Added support for 'error' log type in addition to 'errors' - Improved error message extraction from obj.err when available This fixes the missing agent and error logs issue on Windows. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix gateway health checks and shutdown ownership * Refine auth lock window and dev shutdown * fix: improve Hermes plugin discovery on Windows by fixing Python path resolution - Added support for Windows venv Scripts directory structure - Fixed Python executable path detection for hermes.exe in venv/Scripts/ - Added Windows LOCALAPPDATA hermes-agent directory to search paths - Improved cross-platform compatibility for plugin discovery This fixes the "No module named 'hermes_cli'" error on Windows by correctly locating the Python virtual environment that contains the Hermes modules. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: improve cross-platform compatibility for Hermes plugin discovery - Added platform detection to only add Windows-specific paths on Windows - Prevents potential issues on Unix/Linux/macOS systems - Ensures LOCALAPPDATA path is only used when available on Windows - Maintains existing behavior for all platforms This makes the Windows plugin discovery fix safer for cross-platform usage. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: remove unused development dependencies - Removed nodemon (replaced by ts-node-dev) - Removed tsx (had compatibility issues with Koa) - Removed nodemon.json configuration file - Cleaned up development tools to only what's actually used This reduces dependency size and eliminates the windows-kill popup source that was part of nodemon. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: remove memory system files - Removed MEMORY.md index file - Removed memory/ directory and windows-compatibility.md - Cleaned up unused memory persistence system Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: resolve TypeScript compilation error in plugins.ts - Added type assertion 'as string[]' after filter(Boolean) - Fixes TS2769 error: No overload matches this call - Ensures type compatibility with hasHermesPluginModule function Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: comprehensive Windows compatibility and gateway management improvements - Fix gateway detection after nodemon restart by adding health check-based detection - Prevent port conflicts by detecting already-running gateways without PID files - Switch to serial gateway startup to avoid lock file race conditions - Return to nodemon from ts-node-dev for development stability - Always stop gateways on shutdown to prevent orphan processes - Prevent project root config files from being committed to git - Fix syntax issues in plugins.ts Resolves issues where default profile gateway failed to start after nodemon restart and gateways were incorrectly marked as stopped despite running on correct ports. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: comic theme multilingual fonts, sidebar collapse fix, plugin discovery for Termux, and cron history - Add Chinese (ZCOOL KuaiLe), Japanese (Zen Maru Gothic), Korean (Gaegu) handwritten fonts for Comic theme - Fix collapsed sidebar: hide language switch, stack theme icons vertically - Add hermes shebang parsing as fallback Python discovery for Termux - Remove cron source filter from history sessions - Add 0.5.17 changelog entries for all 8 locales Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: tolerate duplicate YAML keys in config parsing (closes #628) Add `{ json: true }` to all 7 `yaml.load()` calls so duplicated mapping keys (e.g. multiple `mcp_servers:` blocks) no longer crash the API. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: gateway ownership check requires PID file to prevent cross-profile port hijacking Remove fallback that assumed ownership of healthy gateways without PID verification. Now only claims a gateway if PID file exists and process is alive, preventing one profile from hijacking another's port. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { execFile } from 'child_process'
|
||||
import { existsSync } from 'fs'
|
||||
import { existsSync, readFileSync } from 'fs'
|
||||
import { dirname, join, resolve } from 'path'
|
||||
import { homedir } from 'os'
|
||||
import { promisify } from 'util'
|
||||
|
||||
const execFileAsync = promisify(execFile)
|
||||
@@ -230,29 +231,68 @@ function maybeRootFromHermesBin(): string[] {
|
||||
return candidates.filter((candidate, index) => candidates.indexOf(candidate) === index)
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the shebang of the hermes binary to extract the Python interpreter path.
|
||||
* Works with pip-installed launchers, uv tool launchers, and manual venv installs.
|
||||
* e.g. "#!/Users/ekko/.hermes/hermes-agent/venv/bin/python3" -> that path
|
||||
*/
|
||||
function pythonFromHermesShebang(): string | undefined {
|
||||
const hermesBin = process.env.HERMES_BIN?.trim() || 'hermes'
|
||||
try {
|
||||
const resolved = resolve(hermesBin)
|
||||
if (!existsSync(resolved)) return undefined
|
||||
const head = readFileSync(resolved, 'utf8').slice(0, 256)
|
||||
const match = head.match(/^#!\s*(\/[^\s\n]+)/)
|
||||
return match ? match[1] : undefined
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
function resolveHermesAgentRoot(): string {
|
||||
const candidates = [
|
||||
process.env.HERMES_AGENT_ROOT?.trim(),
|
||||
...maybeRootFromHermesBin(),
|
||||
'/opt/hermes',
|
||||
join(process.env.HOME || '', '.hermes', 'hermes-agent'),
|
||||
].filter(Boolean) as string[]
|
||||
join(homedir(), '.hermes', 'hermes-agent'), // Unix/Linux/macOS
|
||||
]
|
||||
|
||||
// Windows specific path
|
||||
if (process.platform === 'win32' && process.env.LOCALAPPDATA) {
|
||||
candidates.push(join(process.env.LOCALAPPDATA, 'hermes', 'hermes-agent'))
|
||||
}
|
||||
|
||||
return candidates.find(hasHermesPluginModule) || ''
|
||||
return (candidates.filter(Boolean) as string[]).find(hasHermesPluginModule) || ''
|
||||
}
|
||||
|
||||
|
||||
function pythonCandidates(agentRoot: string): string[] {
|
||||
const hermesBin = process.env.HERMES_BIN?.trim()
|
||||
const hermesBinPython = hermesBin && hermesBin.includes('/bin/') ? join(dirname(hermesBin), 'python') : undefined
|
||||
const rootPythons = agentRoot
|
||||
? [join(agentRoot, '.venv', 'bin', 'python'), join(agentRoot, 'venv', 'bin', 'python')]
|
||||
: []
|
||||
let hermesBinPython: string | undefined
|
||||
if (hermesBin) {
|
||||
// Windows: hermes -> venv\Scripts\python.exe
|
||||
// Unix: hermes -> venv/bin/python
|
||||
if (hermesBin.includes('\\Scripts\\') || hermesBin.includes('/Scripts/')) {
|
||||
hermesBinPython = join(dirname(hermesBin), 'python.exe')
|
||||
} else if (hermesBin.includes('/bin/') || hermesBin.includes('\\bin\\')) {
|
||||
hermesBinPython = join(dirname(hermesBin), 'python')
|
||||
}
|
||||
}
|
||||
|
||||
const rootPythons = agentRoot ? [
|
||||
join(agentRoot, 'venv', 'bin', 'python'), // Unix
|
||||
join(agentRoot, 'venv', 'Scripts', 'python.exe'), // Windows
|
||||
join(agentRoot, '.venv', 'bin', 'python'), // Unix (alternative)
|
||||
join(agentRoot, '.venv', 'Scripts', 'python.exe'), // Windows (alternative)
|
||||
] : []
|
||||
|
||||
const candidates = [
|
||||
process.env.HERMES_PYTHON?.trim(),
|
||||
hermesBinPython,
|
||||
...rootPythons,
|
||||
'python3',
|
||||
'python',
|
||||
pythonFromHermesShebang(),
|
||||
].filter(Boolean) as string[]
|
||||
|
||||
return candidates.filter((candidate) => {
|
||||
|
||||
Reference in New Issue
Block a user