Files
Hermes-ui/packages/server/src/services/hermes/hermes-path.ts
T
ekko c27a12f56c [codex] fix Windows desktop browser packaging (#1219)
* fix windows hermes home fallback

* bundle Hermes desktop browser runtime

* bundle desktop channel dependencies

* avoid matrix e2ee build dependency

* fix windows npm shim execution

* fix bundled agent-browser chrome packaging

* fix agent-browser chrome fallback copy

* fix windows agent-browser home lookup

* copy agent-browser chrome after install

* fix browser output decoding on windows

---------

Co-authored-by: xingzhi <chuzihao.czh@alibaba-inc.com>
2026-06-01 21:35:26 +08:00

92 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Hermes 路径检测工具 - 跨平台兼容
*
* Hermes 数据目录在不同平台上的位置:
* - Windows 原生安装: %LOCALAPPDATA%\hermes when it exists
* - Linux/macOS/WSL2: ~/.hermes
* - 用户自定义: HERMES_HOME 环境变量
*/
import { existsSync } from 'fs'
import { basename, dirname, isAbsolute, relative, resolve, join } from 'path'
import { homedir } from 'os'
/**
* 智能检测 Hermes 数据目录
*
* 检测优先级:
* 1. HERMES_HOME 环境变量(用户自定义)
* 2. Windows: existing %LOCALAPPDATA%\hermes or %APPDATA%\hermes
* 3. 默认: ~/.hermesLinux/macOS/WSL2
*
* @returns Hermes 数据目录的绝对路径
*/
export function detectHermesHome(): string {
// 1. 用户自定义的环境变量(最高优先级)
if (process.env.HERMES_HOME) {
return resolve(process.env.HERMES_HOME)
}
const defaultHome = resolve(homedir(), '.hermes')
// 2. Windows:优先使用存在的原生安装数据目录;不存在时回退到 ~/.hermes。
if (process.platform === 'win32') {
const candidates = [
process.env.LOCALAPPDATA,
process.env.APPDATA,
]
.map(value => value?.trim())
.filter((value): value is string => !!value)
.map(value => resolve(value, 'hermes'))
for (const candidate of candidates) {
if (existsSync(candidate)) return candidate
}
}
// 3. Linux/macOS~/.hermes
return defaultHome
}
/**
* Detect the Hermes root data directory.
*
* `HERMES_HOME` may intentionally point at a profile directory when launching a
* specific gateway (`<root>/profiles/<name>`). Web UI profile management needs
* the root directory so it can read `active_profile` and enumerate profiles.
*/
export function detectHermesRootHome(): string {
const home = detectHermesHome()
const parent = dirname(home)
if (basename(parent) === 'profiles') return dirname(parent)
return home
}
/**
* 获取 Hermes CLI 二进制文件路径
* @param customBin 自定义的 hermes 二进制路径
* @returns hermes 命令名称或路径
*/
export function getHermesBin(customBin?: string): string {
if (customBin?.trim()) return customBin.trim()
if (process.env.HERMES_BIN?.trim()) return process.env.HERMES_BIN.trim()
return 'hermes'
}
function comparablePath(path: string): string {
return process.platform === 'win32' ? path.toLowerCase() : path
}
export function isPathWithin(targetPath: string, basePath: string): boolean {
const base = resolve(basePath)
const target = resolve(targetPath)
const rel = relative(comparablePath(base), comparablePath(target))
return rel === '' || (!!rel && !rel.startsWith('..') && !isAbsolute(rel))
}
export function relativePathFromBase(targetPath: string, basePath: string): string | null {
if (!isPathWithin(targetPath, basePath)) return null
const rel = relative(resolve(basePath), resolve(targetPath))
return rel.replace(/\\/g, '/')
}