Merge branch 'main' into bb/gui

This commit is contained in:
emozilla
2026-05-18 13:14:46 -04:00
62 changed files with 3494 additions and 1275 deletions
+160 -2
View File
@@ -1,4 +1,4 @@
# ============================================================================
# ============================================================================
# Hermes Agent Installer for Windows
# ============================================================================
# Installation script for Windows (PowerShell).
@@ -35,7 +35,11 @@ param(
[string]$Stage,
[switch]$ProtocolVersion,
[switch]$NonInteractive,
[switch]$Json
[switch]$Json,
# --- Ensure mode (dep_ensure.py entry point) ---
[string]$Ensure = "",
[switch]$PostInstall
)
$ErrorActionPreference = "Stop"
@@ -115,6 +119,105 @@ function Write-Err {
Write-Host "[X] $Message" -ForegroundColor Red
}
# --- Ensure-mode helpers ---
function Resolve-NpmCmd {
$npmCmd = Get-Command npm -ErrorAction SilentlyContinue
if (-not $npmCmd) { return $null }
$npmExe = $npmCmd.Source
if ($npmExe -like "*.ps1") {
$npmCmdSibling = Join-Path (Split-Path $npmExe -Parent) "npm.cmd"
if (Test-Path $npmCmdSibling) { return $npmCmdSibling }
}
return $npmExe
}
function Find-SystemBrowser {
$candidates = @(
"${env:ProgramFiles}\Google\Chrome\Application\chrome.exe",
"${env:ProgramFiles(x86)}\Google\Chrome\Application\chrome.exe",
"${env:LOCALAPPDATA}\Google\Chrome\Application\chrome.exe",
"${env:ProgramFiles}\Microsoft\Edge\Application\msedge.exe",
"${env:ProgramFiles(x86)}\Microsoft\Edge\Application\msedge.exe",
"${env:ProgramFiles}\Chromium\Application\chrome.exe",
"${env:LOCALAPPDATA}\Chromium\Application\chrome.exe"
)
foreach ($p in $candidates) {
if (Test-Path $p) { return $p }
}
return $null
}
function Write-BrowserEnv {
param([string]$BrowserPath)
if (-not (Test-Path $HermesHome)) {
New-Item -ItemType Directory -Force -Path $HermesHome | Out-Null
}
$envFile = Join-Path $HermesHome ".env"
if (-not (Test-Path $envFile)) {
Set-Content -Path $envFile -Value "AGENT_BROWSER_EXECUTABLE_PATH=$BrowserPath" -Encoding UTF8
return
}
$content = Get-Content $envFile -Raw -ErrorAction SilentlyContinue
if ($content -and $content -match "AGENT_BROWSER_EXECUTABLE_PATH=") { return }
Add-Content -Path $envFile -Value "AGENT_BROWSER_EXECUTABLE_PATH=$BrowserPath" -Encoding UTF8
}
function Install-AgentBrowser {
param([switch]$SkipChromium)
$npm = Resolve-NpmCmd
if (-not $npm) {
Write-Err "npm not found -- install Node.js first"
throw "npm not found"
}
Write-Info "Installing agent-browser via npm -g --prefix..."
$prefixDir = Join-Path $HermesHome "node"
if (-not (Test-Path $prefixDir)) {
New-Item -ItemType Directory -Path $prefixDir -Force | Out-Null
}
$npmLog = [System.IO.Path]::GetTempFileName()
$prevEAP = $ErrorActionPreference
$ErrorActionPreference = "Continue"
& $npm install -g --prefix $prefixDir --silent --ignore-scripts "agent-browser@^0.26.0" "@askjo/camofox-browser@^1.5.2" 2>&1 | Tee-Object -FilePath $npmLog | Out-Null
$npmExit = $LASTEXITCODE
$ErrorActionPreference = $prevEAP
if ($npmExit -ne 0) {
$npmDetail = Get-Content $npmLog -Raw -ErrorAction SilentlyContinue
Remove-Item $npmLog -Force -ErrorAction SilentlyContinue
Write-Err "npm install -g failed (exit $npmExit): $npmDetail"
throw "npm install failed"
}
Remove-Item $npmLog -Force -ErrorAction SilentlyContinue
if (-not $SkipChromium) {
$sysBrowser = Find-SystemBrowser
if ($sysBrowser) {
Write-BrowserEnv -BrowserPath $sysBrowser
Write-Info "System browser detected -- skipping Chromium download"
} else {
$abExe = Join-Path $prefixDir "agent-browser.cmd"
if (Test-Path $abExe) {
Write-Info "Installing Chromium via agent-browser install..."
$abLog = [System.IO.Path]::GetTempFileName()
$prevEAP = $ErrorActionPreference
$ErrorActionPreference = "Continue"
& $abExe install 2>&1 | Tee-Object -FilePath $abLog | Out-Null
$abExit = $LASTEXITCODE
$ErrorActionPreference = $prevEAP
if ($abExit -ne 0) {
$abDetail = Get-Content $abLog -Raw -ErrorAction SilentlyContinue
Write-Warn "Chromium install failed (exit $abExit): $abDetail"
}
Remove-Item $abLog -Force -ErrorAction SilentlyContinue
} else {
Write-Warn "agent-browser.cmd not found at $abExe"
}
}
}
Write-Success "Agent-browser ready"
}
# ============================================================================
# Dependency checks
# ============================================================================
@@ -2115,6 +2218,48 @@ function Invoke-AllStages {
}
}
function Invoke-EnsureMode {
param([string]$Deps)
$depList = $Deps -split ","
foreach ($dep in $depList) {
$dep = $dep.Trim()
switch ($dep) {
"node" {
[void](Test-Node)
if (-not $script:HasNode) {
Write-Err "Node.js could not be installed"
exit 1
}
}
"browser" {
[void](Test-Node)
if ($script:HasNode) {
Install-AgentBrowser
} else {
Write-Err "Node.js is required for browser tools but could not be installed"
exit 1
}
}
"ripgrep" {
Write-Info "ripgrep: install manually on Windows (scoop install ripgrep)"
}
"ffmpeg" {
Write-Info "ffmpeg: install manually on Windows (scoop install ffmpeg)"
}
default {
Write-Err "Unknown dependency: $dep"
exit 1
}
}
}
}
function Invoke-PostInstallMode {
Write-Info "Running post-install setup..."
Invoke-EnsureMode -Deps "node,browser"
Write-Info "Post-install complete"
}
function Main {
Write-Banner
Invoke-AllStages
@@ -2134,6 +2279,19 @@ function Main {
# structured JSON error frame instead of a bare exception.
try {
if ($Ensure -ne "") {
if ($PSBoundParameters.ContainsKey("Stage")) {
Write-Err "Cannot use -Ensure and -Stage simultaneously"
exit 1
}
Invoke-EnsureMode -Deps $Ensure
exit 0
}
if ($PostInstall) {
Invoke-PostInstallMode
exit 0
}
if ($ProtocolVersion) {
Write-Output $InstallStageProtocolVersion
exit 0
+88 -24
View File
@@ -1512,6 +1512,17 @@ find_system_browser() {
fi
done
if [ "$(uname)" = "Darwin" ]; then
for app in \
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
"/Applications/Chromium.app/Contents/MacOS/Chromium"; do
if [ -x "$app" ]; then
echo "$app"
return 0
fi
done
fi
return 1
}
@@ -1534,10 +1545,15 @@ configure_browser_env_from_system_browser() {
browser_path="$(find_system_browser 2>/dev/null || true)"
fi
if [ -z "$browser_path" ] || [ ! -f "$env_file" ]; then
if [ -z "$browser_path" ]; then
return 0
fi
mkdir -p "$HERMES_HOME"
if [ ! -f "$env_file" ]; then
touch "$env_file"
fi
if grep -q '^AGENT_BROWSER_EXECUTABLE_PATH=' "$env_file" 2>/dev/null; then
log_info "AGENT_BROWSER_EXECUTABLE_PATH already configured"
return 0
@@ -1888,6 +1904,73 @@ print_success() {
fi
}
ensure_browser() {
if ! command -v node >/dev/null 2>&1; then
local node_bin="$HERMES_HOME/node/bin/node"
if [ -x "$node_bin" ]; then
export PATH="$HERMES_HOME/node/bin:$PATH"
else
log_error "Node.js not found. Run with --ensure node first."
return 1
fi
fi
local npm_bin
npm_bin="$(command -v npm 2>/dev/null || echo "$HERMES_HOME/node/bin/npm")"
if [ ! -x "$npm_bin" ]; then
log_error "npm not found"
return 1
fi
log_info "Installing agent-browser..."
local log_file
log_file="$(mktemp)"
if ! "$npm_bin" install -g --prefix "$HERMES_HOME/node" --silent --ignore-scripts \
"agent-browser@^0.26.0" \
"@askjo/camofox-browser@^1.5.2" \
>"$log_file" 2>&1; then
log_error "npm install failed:"
cat "$log_file" >&2
rm -f "$log_file"
return 1
fi
rm -f "$log_file"
export PATH="$HERMES_HOME/node/bin:$PATH"
local sys_browser
sys_browser="$(find_system_browser 2>/dev/null || true)"
if [ -n "$sys_browser" ]; then
configure_browser_env_from_system_browser "$sys_browser"
log_info "System browser detected -- skipping Chromium download"
return 0
fi
log_info "Installing Chromium via agent-browser install..."
local ab_bin="$HERMES_HOME/node/bin/agent-browser"
if [ -x "$ab_bin" ]; then
"$ab_bin" install 2>/dev/null || {
log_warn "Chromium install failed. Browser tools may not work without a system browser."
# OS-specific hints (detect_os sets $DISTRO)
case "${DISTRO:-unknown}" in
ubuntu|debian)
log_info "Try: sudo apt-get install -y chromium-browser"
;;
arch)
log_info "Try: sudo pacman -S chromium"
;;
fedora|rhel|centos)
log_info "Try: sudo dnf install -y chromium"
;;
esac
}
else
log_warn "agent-browser not found at $ab_bin"
fi
return 0
}
ensure_mode() {
detect_os
@@ -1901,19 +1984,7 @@ ensure_mode() {
browser)
check_node
if [ "$HAS_NODE" = true ]; then
DETECTED_BROWSER_EXECUTABLE="$(find_system_browser 2>/dev/null || true)"
if [ -z "$DETECTED_BROWSER_EXECUTABLE" ]; then
log_info "Installing agent-browser + Chromium..."
npm_bin="$(command -v npm 2>/dev/null || echo "")"
if [ -n "$npm_bin" ]; then
local agent_browser_dir="$HERMES_HOME/node_modules"
mkdir -p "$agent_browser_dir"
"$npm_bin" install --prefix "$HERMES_HOME" agent-browser 2>/dev/null || true
npx playwright install chromium 2>/dev/null || true
fi
else
log_success "System browser found: $DETECTED_BROWSER_EXECUTABLE"
fi
ensure_browser
fi
;;
ripgrep)
@@ -1948,16 +2019,7 @@ postinstall_mode() {
install_system_packages
if [ "$HAS_NODE" = true ] && [ "$SKIP_BROWSER" = false ]; then
DETECTED_BROWSER_EXECUTABLE="$(find_system_browser 2>/dev/null || true)"
if [ -z "$DETECTED_BROWSER_EXECUTABLE" ]; then
log_info "Installing browser engine..."
npm_bin="$(command -v npm 2>/dev/null || echo "")"
if [ -n "$npm_bin" ]; then
npx playwright install chromium 2>/dev/null || true
fi
else
log_success "System browser found: $DETECTED_BROWSER_EXECUTABLE"
fi
ensure_browser
fi
HERMES_CMD="$(command -v hermes 2>/dev/null || echo "")"
@@ -1996,6 +2058,8 @@ main() {
maybe_start_gateway
print_success
echo "git" > "$HERMES_HOME/.install_method"
}
if [ -n "$ENSURE_DEPS" ]; then