Files
lingxi-ai/packages/desktop/src/main/hermes-cli.ts
T

97 lines
3.1 KiB
TypeScript
Raw Normal View History

2026-06-05 11:29:11 +08:00
import { spawn } from 'node:child_process'
import { existsSync, mkdirSync } from 'node:fs'
import { delimiter, dirname, join } from 'node:path'
import {
bundledBrowserExecutable,
bundledGit,
bundledNode,
bundledPython,
gitPathDirs,
hermesBin,
hermesHome,
nodeBinDir,
pythonDir,
webUiHome,
} from './paths'
import { HERMES_CLI_ARG } from './cli-constants'
import { ensureDesktopRuntime } from './runtime-manager'
export function parseHermesCliArgs(argv: string[] = process.argv): string[] | null {
const index = argv.indexOf(HERMES_CLI_ARG)
if (index < 0) return null
return argv.slice(index + 1)
}
export async function runBundledHermesCli(args: string[]): Promise<number> {
try {
await ensureDesktopRuntime()
} catch (err) {
console.error(`Failed to prepare Hermes runtime: ${err instanceof Error ? err.message : String(err)}`)
return 1
}
const command = hermesBin()
if (!existsSync(command)) {
console.error(`hermes binary missing at ${command}`)
console.error('Run: npm run prepare:runtime (to build a local Hermes runtime)')
return 127
}
mkdirSync(webUiHome(), { recursive: true })
mkdirSync(hermesHome(), { recursive: true })
const binDir = dirname(command)
const bundledNodeBin = nodeBinDir()
const bundledAgentBrowserBin = process.platform === 'win32'
? join(pythonDir(), 'node')
: join(pythonDir(), 'node', 'bin')
const inheritedPath = process.env.PATH || process.env.Path || ''
const pathValue = [
binDir,
bundledAgentBrowserBin,
bundledNodeBin,
gitPathDirs().join(delimiter),
inheritedPath,
].filter(Boolean).join(delimiter)
const gitBin = bundledGit()
const browserExecutable = process.env.AGENT_BROWSER_EXECUTABLE_PATH?.trim() || bundledBrowserExecutable()
const env: NodeJS.ProcessEnv = {
...process.env,
HERMES_DESKTOP: 'true',
HERMES_BIN: command,
HERMES_AGENT_BRIDGE_PYTHON: bundledPython(),
HERMES_AGENT_CLI_PYTHON: bundledPython(),
HERMES_AGENT_ROOT: pythonDir(),
HERMES_AGENT_NODE: bundledNode(),
HERMES_AGENT_NODE_ROOT: process.platform === 'win32' ? bundledNodeBin : dirname(bundledNodeBin),
AGENT_BROWSER_HOME: process.env.AGENT_BROWSER_HOME?.trim() || join(hermesHome(), 'agent-browser'),
...(browserExecutable ? { AGENT_BROWSER_EXECUTABLE_PATH: browserExecutable } : {}),
PLAYWRIGHT_BROWSERS_PATH: process.env.PLAYWRIGHT_BROWSERS_PATH || join(pythonDir(), 'ms-playwright'),
...(gitBin ? { HERMES_AGENT_GIT: gitBin } : {}),
HERMES_HOME: hermesHome(),
HERMES_WEB_UI_HOME: webUiHome(),
HERMES_WEBUI_STATE_DIR: webUiHome(),
PATH: pathValue,
}
return await new Promise(resolve => {
const child = spawn(command, args, {
env,
stdio: 'inherit',
windowsHide: false,
})
child.once('error', (err) => {
console.error(`Failed to run bundled Hermes CLI: ${err.message}`)
resolve(1)
})
child.once('exit', (code, signal) => {
if (typeof code === 'number') {
resolve(code)
return
}
console.error(`Bundled Hermes CLI exited from signal ${signal || 'unknown'}`)
resolve(1)
})
})
}