File size: 4,424 Bytes
f584dc8
 
 
 
 
 
 
 
 
 
 
 
a3c82d1
 
 
 
 
 
 
f584dc8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1166d78
 
 
 
 
 
 
 
f584dc8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6ffa5ff
 
 
 
 
 
 
 
 
 
 
 
 
3a186a3
6ffa5ff
 
 
 
8a530f3
 
 
 
1166d78
 
6ffa5ff
 
f584dc8
6ffa5ff
f584dc8
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/bin/bash
# Docker entrypoint: bootstrap config files into the mounted volume, then run hermes.
set -e

INSTALL_DIR="/opt/hermes"
RUNTIME_HELPER="$INSTALL_DIR/docker/space_runtime.py"
export HERMES_HOME="$(python3 "$RUNTIME_HELPER" home)"

# --- Privilege dropping via gosu ---
# When started as root (the default), optionally remap the hermes user/group
# to match host-side ownership, fix volume permissions, then re-exec as hermes.
if [ "$(id -u)" = "0" ]; then
    # HF Spaces run inside containers, but they don't always expose /.dockerenv.
    # hermes-web-ui uses that marker to choose detached "gateway run" mode
    # instead of system-service "gateway start", which times out in Spaces.
    if [ -n "${SPACE_ID:-}${SPACE_HOST:-}" ] && [ ! -e "/.dockerenv" ]; then
        touch "/.dockerenv" 2>/dev/null || true
    fi

    if [ -n "$HERMES_UID" ] && [ "$HERMES_UID" != "$(id -u hermes)" ]; then
        echo "Changing hermes UID to $HERMES_UID"
        usermod -u "$HERMES_UID" hermes
    fi

    if [ -n "$HERMES_GID" ] && [ "$HERMES_GID" != "$(id -g hermes)" ]; then
        echo "Changing hermes GID to $HERMES_GID"
        groupmod -g "$HERMES_GID" hermes
    fi

    mkdir -p "$HERMES_HOME"
    actual_hermes_uid=$(id -u hermes)
    if [ "$(stat -c %u "$HERMES_HOME" 2>/dev/null)" != "$actual_hermes_uid" ]; then
        echo "$HERMES_HOME is not owned by $actual_hermes_uid, fixing"
        chown -R hermes:hermes "$HERMES_HOME"
    fi

    echo "Dropping root privileges"
    exec gosu hermes env HERMES_HOME="$HERMES_HOME" "$0" "$@"
fi

# --- Running as hermes from here ---
export HERMES_HOME="$(python3 "$RUNTIME_HELPER" home)"
source "${INSTALL_DIR}/.venv/bin/activate"

# Create essential directory structure.  Cache and platform directories
# (cache/images, cache/audio, platforms/whatsapp, etc.) are created on
# demand by the application — don't pre-create them here so new installs
# get the consolidated layout from get_hermes_dir().
# The "home/" subdirectory is a per-profile HOME for subprocesses (git,
# ssh, gh, npm …).  Without it those tools write to /root which is
# ephemeral and shared across profiles.  See issue #4426.
mkdir -p "$HERMES_HOME"/{cron,sessions,logs,hooks,memories,skills,skins,plans,workspace,home}

# hermes-web-ui currently resolves runtime files via ~/.hermes.
# Mirror the active Hermes home into the hermes user's legacy home path
# so the external UI sees the same config/.env/session files.
LEGACY_HERMES_HOME="/opt/data/.hermes"
if [ ! -e "$LEGACY_HERMES_HOME" ]; then
    ln -s "$HERMES_HOME" "$LEGACY_HERMES_HOME"
fi

# .env
if [ ! -f "$HERMES_HOME/.env" ]; then
    cp "$INSTALL_DIR/.env.example" "$HERMES_HOME/.env"
fi

# config.yaml
if [ ! -f "$HERMES_HOME/config.yaml" ]; then
    cp "$INSTALL_DIR/cli-config.yaml.example" "$HERMES_HOME/config.yaml"
fi

# SOUL.md
if [ ! -f "$HERMES_HOME/SOUL.md" ]; then
    cp "$INSTALL_DIR/docker/SOUL.md" "$HERMES_HOME/SOUL.md"
fi

# Sync bundled skills (manifest-based so user edits are preserved)
if [ -d "$INSTALL_DIR/skills" ]; then
    python3 "$INSTALL_DIR/tools/skills_sync.py"
fi

if [ $# -eq 0 ] && [ -n "${SPACE_ID:-}${SPACE_HOST:-}" ]; then
    SHELL_EXEC="/bin/bash"
    if [ ! -x "$SHELL_EXEC" ]; then
        SHELL_EXEC="/bin/sh"
    fi

    UI_NODE="$(command -v node || command -v nodejs || true)"
    if [ -z "$UI_NODE" ]; then
        echo "Node.js runtime not found; hermes-web-ui cannot start"
        exit 1
    fi

    HERMES_WEB_UI_ROOT="$(npm root -g)/hermes-web-ui"
    HERMES_WEB_UI_ENTRY="$HERMES_WEB_UI_ROOT/dist/server/index.js"
    if [ ! -f "$HERMES_WEB_UI_ENTRY" ]; then
        echo "hermes-web-ui entrypoint missing at $HERMES_WEB_UI_ENTRY"
        exit 1
    fi

    HERMES_BIN="$INSTALL_DIR/.venv/bin/hermes"
    export HERMES_BIN

    export API_SERVER_ENABLED="${API_SERVER_ENABLED:-true}"
    export PORT="${PORT:-7860}"
    # Let hermes-web-ui's GatewayManager own port selection via config.yaml.
    # Exporting a default API_SERVER_PORT here forces child gateway processes
    # back onto 8642, which breaks health checks when the UI assigns 8643+.
    export UPSTREAM="${UPSTREAM:-$(python3 "$RUNTIME_HELPER" api-server-upstream)}"
    export AUTH_DISABLED="${AUTH_DISABLED:-false}"
    export AUTH_TOKEN="${AUTH_TOKEN:-wangjx0515}"

    WEB_UI_CMD="$UI_NODE \"$HERMES_WEB_UI_ENTRY\""

    exec $SHELL_EXEC -lc "$WEB_UI_CMD"
fi

exec python3 "$RUNTIME_HELPER" exec "$@"