hermes-hub/installer/install-linux.sh
Hermes Team 290e23070e feat(installer): самодостаточный установщик для Linux, без копирования репозитория
install-linux.sh читал исходники из $REPO_ROOT, поэтому на каждую машину
приходилось приносить весь клон git. Добавлен build_installer_linux.sh: он
собирает один файл dist/hermes-hub-setup.sh — пролог на shell, строка-маркер
и tar.gz побайтово следом. Пролог обрезает себя по маркеру, распаковывает
хвост во временный каталог и запускает оттуда install-linux.sh. Состав
поставки тот же, что у виндового payload, плюс installer/; виндовые .exe и
__pycache__ из линуксовой поставки вычищаются.

Убран запасной коммит-литерал 'fb23bff' в манифесте: при сборке без git он
подставлял чужой номер сборки, из-за чего установленная версия выглядела
определённой, не будучи ею. Теперь коммит берётся из BUILD_COMMIT, который
кладёт сборщик, иначе — 'не определён'.

Проверено: распаковка проходит, в поставке лежат свежие server.py и app.js,
секретов, ключей и почт в ней нет.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 09:10:32 +07:00

198 lines
7.3 KiB
Bash
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.

#!/usr/bin/env bash
# ==============================================================================
# Hermes Hub — Linux Installation Script
# Mirrors plugin files, registers .desktop entry, creates application launcher,
# and supports both desktop and headless server environments.
# ==============================================================================
set -e
HUB_VERSION="0.1.1"
DEFAULT_HERMES_HOME="$HOME/.hermes"
HERMES_HOME="${HERMES_HOME:-$DEFAULT_HERMES_HOME}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
echo "======================================================================"
echo " HERMES HUB INSTALLER (Linux / POSIX) "
echo "======================================================================"
echo "Version : $HUB_VERSION"
echo "Hermes Home : $HERMES_HOME"
echo "Source Root : $REPO_ROOT"
echo ""
# 1. Check / Discover Python Runtime and Hermes Environment
echo "[1/6] Checking Python and Hermes environment..."
PYTHON_BIN=""
if [ -f "$HERMES_HOME/hermes-agent/venv/bin/python3" ]; then
PYTHON_BIN="$HERMES_HOME/hermes-agent/venv/bin/python3"
elif [ -f "$HERMES_HOME/hermes-agent/venv/bin/python" ]; then
PYTHON_BIN="$HERMES_HOME/hermes-agent/venv/bin/python"
elif command -v python3 >/dev/null 2>&1; then
PYTHON_BIN="$(command -v python3)"
elif command -v python >/dev/null 2>&1; then
PYTHON_BIN="$(command -v python)"
fi
if [ -z "$PYTHON_BIN" ]; then
echo "❌ Error: Python 3 not found on system. Please install Python 3.9+." >&2
exit 10
fi
PY_VER="$("$PYTHON_BIN" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')"
echo " Using Python: $PYTHON_BIN (v$PY_VER)"
# Ensure Hermes Home Directory Structure
mkdir -p "$HERMES_HOME"
mkdir -p "$HERMES_HOME/config"
mkdir -p "$HERMES_HOME/plugins/antigravity-provider/src"
mkdir -p "$HERMES_HOME/plugins/antigravity-provider/assets"
mkdir -p "$HOME/.local/bin"
mkdir -p "$HOME/.local/share/applications"
# 2. Check and Install Dependencies
echo "[2/6] Verifying Python dependencies..."
DEPS_OK=true
"$PYTHON_BIN" -c "import fastapi, uvicorn, pydantic, psutil, yaml; print('DEPS_OK')" >/dev/null 2>&1 || DEPS_OK=false
if [ "$DEPS_OK" != "true" ]; then
echo " Installing required packages (fastapi, uvicorn, pydantic, psutil, pyyaml)..."
"$PYTHON_BIN" -m pip install --no-warn-script-location -q fastapi uvicorn pydantic psutil pyyaml || {
echo "⚠️ Warning: pip install returned non-zero code. Trying with --user..."
"$PYTHON_BIN" -m pip install --user --no-warn-script-location -q fastapi uvicorn pydantic psutil pyyaml || true
}
fi
# 3. Mirror Plugin Files to ~/.hermes/plugins/antigravity-provider (with cleanup of stale files)
echo "[3/6] Deploying plugin source files (mirrored)..."
PLUGIN_SRC="$REPO_ROOT/src/antigravity_provider"
PLUGIN_DST="$HERMES_HOME/plugins/antigravity-provider/src/antigravity_provider"
if [ -d "$PLUGIN_SRC" ]; then
mkdir -p "$PLUGIN_DST"
# Use rsync with --delete if available, or python mirroring
if command -v rsync >/dev/null 2>&1; then
rsync -a --delete --exclude='__pycache__' --exclude='*.pyc' "$PLUGIN_SRC/" "$PLUGIN_DST/"
else
"$PYTHON_BIN" -c "
import os, shutil
src = r'$PLUGIN_SRC'
dst = r'$PLUGIN_DST'
if os.path.exists(dst):
shutil.rmtree(dst)
shutil.copytree(src, dst, ignore=shutil.ignore_patterns('__pycache__', '*.pyc'))
"
fi
else
echo "❌ Error: Source directory $PLUGIN_SRC not found!" >&2
exit 12
fi
# Deploy Assets
if [ -d "$REPO_ROOT/assets" ]; then
mkdir -p "$HERMES_HOME/plugins/antigravity-provider/assets"
cp -r "$REPO_ROOT/assets/"* "$HERMES_HOME/plugins/antigravity-provider/assets/" 2>/dev/null || true
fi
# 4. Write Deployment Manifest
echo "[4/6] Writing deployment manifest..."
MANIFEST_FILE="$HERMES_HOME/plugins/antigravity-provider/deployment_manifest.json"
# Коммит берётся из BUILD_COMMIT (кладёт сборщик самораспаковывающегося
# установщика, где git недоступен), иначе — из репозитория. Запасного
# литерала нет намеренно: неизвестный коммит должен читаться как неизвестный,
# а не как чужой чужой номер сборки.
if [ -f "$REPO_ROOT/BUILD_COMMIT" ]; then
GIT_COMMIT="$(tr -d '
' < "$REPO_ROOT/BUILD_COMMIT")"
else
GIT_COMMIT="$(cd "$REPO_ROOT" 2>/dev/null && git rev-parse --short HEAD 2>/dev/null || echo 'не определён')"
fi
TIMESTAMP="$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u)"
cat <<EOF > "$MANIFEST_FILE"
{
"version": "$HUB_VERSION",
"deployed_at": "$TIMESTAMP",
"git_commit": "$GIT_COMMIT",
"platform": "linux"
}
EOF
# Deploy Template Config only if not existing
if [ ! -f "$HERMES_HOME/config/router_profiles.yaml" ] && [ -f "$REPO_ROOT/config/router_profiles.example.yaml" ]; then
echo " Installing default router_profiles.yaml from template..."
cp "$REPO_ROOT/config/router_profiles.example.yaml" "$HERMES_HOME/config/router_profiles.yaml"
else
echo " Preserving existing user router_profiles.yaml."
fi
# 5. Deploy Launcher Executable and .desktop Entry
echo "[5/6] Creating application launcher and .desktop entry..."
LAUNCHER_SRC="$REPO_ROOT/launcher/hermes-hub-web.sh"
if [ ! -f "$LAUNCHER_SRC" ]; then
LAUNCHER_SRC="$SCRIPT_DIR/hermes-hub-web.sh"
fi
LAUNCHER_BIN="$HOME/.local/bin/hermes-hub-web"
cp "$LAUNCHER_SRC" "$LAUNCHER_BIN"
chmod +x "$LAUNCHER_BIN"
# Also place in ~/.hermes/bin for convenience
mkdir -p "$HERMES_HOME/bin"
cp "$LAUNCHER_SRC" "$HERMES_HOME/bin/hermes-hub-web"
chmod +x "$HERMES_HOME/bin/hermes-hub-web"
# Create .desktop file
DESKTOP_FILE="$HOME/.local/share/applications/hermes-hub-web.desktop"
ICON_PATH="$HERMES_HOME/plugins/antigravity-provider/assets/branding/app/HermesHub.ico"
if [ ! -f "$ICON_PATH" ]; then
ICON_PATH="utilities-terminal"
fi
cat <<EOF > "$DESKTOP_FILE"
[Desktop Entry]
Version=1.0
Type=Application
Name=Hermes Hub Web
GenericName=Multi-Agent & Multi-Provider Control Hub
Comment=Multi-Agent & Multi-Provider Control Hub for Hermes Agent
Exec=$LAUNCHER_BIN
Icon=$ICON_PATH
Terminal=false
Categories=Development;Utility;
StartupNotify=true
StartupWMClass=hermes-hub-web
EOF
chmod +x "$DESKTOP_FILE"
if command -v update-desktop-database >/dev/null 2>&1; then
update-desktop-database "$HOME/.local/share/applications" 2>/dev/null || true
fi
# 6. Post-install Smoke Test Verification
echo "[6/6] Running post-install verification smoke test..."
"$PYTHON_BIN" -c "
import sys
sys.path.insert(0, '$HERMES_HOME/plugins/antigravity-provider/src')
import antigravity_provider.router.web.server
print('HERMES_HUB_LINUX_VERIFY_OK')
" || {
echo "❌ Error: Post-install verification failed!" >&2
exit 14
}
echo ""
echo "======================================================================"
echo " HERMES HUB SUCCESSFULLY INSTALLED ON LINUX! "
echo "======================================================================"
echo "Application Launcher : $LAUNCHER_BIN"
echo "Desktop Shortcut : $DESKTOP_FILE"
echo ""
echo "To launch the Web Application window:"
echo " $LAUNCHER_BIN"
echo ""
echo "Or open 'Hermes Hub Web' from your Applications menu."
echo "======================================================================"
exit 0