File size: 5,054 Bytes
0790cf1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d5d58fc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0790cf1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/bin/bash
set -e

BOOT_START=$(date +%s)

echo "[entrypoint] HermesFace β€” Hermes Agent on HuggingFace Spaces"
echo "[entrypoint] ===================================================="

HERMES_HOME="/opt/data"
INSTALL_DIR="/opt/hermes"

# ── DNS pre-resolution (background β€” non-blocking) ────────────────────────
# Resolves Telegram / WhatsApp / Discord domains via DoH when HF Spaces
# system DNS refuses them. Writes /tmp/dns-resolved.json for dns-fix.cjs
# and appends /etc/hosts for Python processes.
echo "[entrypoint] Starting DNS resolution in background..."
python3 /opt/data/scripts/dns-resolve.py /tmp/dns-resolved.json 2>&1 &
DNS_PID=$!
echo "[entrypoint] DNS resolver PID: $DNS_PID"

# Enable Node.js DNS fix preload for playwright / whatsapp-bridge / web build.
export NODE_OPTIONS="${NODE_OPTIONS:+$NODE_OPTIONS }--require /opt/data/scripts/dns-fix.cjs"

# ── Activate virtual environment ─────────────────────────────────────────
if [ -f "${INSTALL_DIR}/.venv/bin/activate" ]; then
  source "${INSTALL_DIR}/.venv/bin/activate"
  echo "[entrypoint] Activated venv: $(which python3)"
fi

# ── Ensure data directories ─────────────────────────────────────────────
mkdir -p "$HERMES_HOME"/{cron,sessions,logs,hooks,memories,skills,skins,plans,workspace,home}

# ── Bootstrap config files ───────────────────────────────────────────────
if [ ! -f "$HERMES_HOME/.env" ] && [ -f "$INSTALL_DIR/.env.example" ]; then
  cp "$INSTALL_DIR/.env.example" "$HERMES_HOME/.env"
  echo "[entrypoint] Created .env from example"
fi

if [ ! -f "$HERMES_HOME/config.yaml" ] && [ -f "$INSTALL_DIR/cli-config.yaml.example" ]; then
  cp "$INSTALL_DIR/cli-config.yaml.example" "$HERMES_HOME/config.yaml"
  echo "[entrypoint] Created config.yaml from example"
fi

if [ ! -f "$HERMES_HOME/SOUL.md" ] && [ -f "$INSTALL_DIR/docker/SOUL.md" ]; then
  cp "$INSTALL_DIR/docker/SOUL.md" "$HERMES_HOME/SOUL.md"
  echo "[entrypoint] Created SOUL.md from template"
fi

# ── Configure dashboard basic auth (required before binding 0.0.0.0) ─────
# Hermes Agent refuses to expose the dashboard publicly with no auth
# provider registered. If HERMES_ADMIN_PASSWORD is set as a Space secret,
# write it into config.yaml as a hashed basic_auth credential.
if [ -n "$HERMES_ADMIN_PASSWORD" ]; then
  python3 - <<'PYEOF' || echo "[entrypoint] WARNING: failed to configure dashboard auth (see error above) β€” dashboard may refuse to start"
import os, sys
import yaml

cfg_path = "/opt/data/config.yaml"
try:
    from plugins.dashboard_auth.basic import hash_password
except Exception as e:
    print(f"[entrypoint] Could not import hash_password: {e}")
    sys.exit(1)

with open(cfg_path) as f:
    cfg = yaml.safe_load(f) or {}

username = os.environ.get("HERMES_ADMIN_USERNAME", "admin")
password = os.environ["HERMES_ADMIN_PASSWORD"]

cfg.setdefault("dashboard", {})
cfg["dashboard"].setdefault("basic_auth", {})
cfg["dashboard"]["basic_auth"]["username"] = username
cfg["dashboard"]["basic_auth"]["password_hash"] = hash_password(password)

with open(cfg_path, "w") as f:
    yaml.safe_dump(cfg, f, default_flow_style=False)

print(f"[entrypoint] Dashboard basic auth configured for user '{username}'")
PYEOF
else
  echo "[entrypoint] WARNING: HERMES_ADMIN_PASSWORD not set as a Space secret β€” dashboard will refuse to bind to 0.0.0.0 and Hermes will exit."
fi

# ── Sync bundled skills ──────────────────────────────────────────────────
if [ -d "$INSTALL_DIR/skills" ] && [ -f "$INSTALL_DIR/tools/skills_sync.py" ]; then
  python3 "$INSTALL_DIR/tools/skills_sync.py" 2>&1 || echo "[entrypoint] Skills sync skipped"
fi

# ── Build artifacts check ───────────────────────────────────────────────
echo "[entrypoint] Build artifacts check:"
test -f "$INSTALL_DIR/run_agent.py" && echo "  OK run_agent.py" || echo "  INFO: run_agent.py not found"
test -f "$INSTALL_DIR/gateway/run.py" && echo "  OK gateway/run.py" || echo "  INFO: gateway/run.py not found"
test -d "$INSTALL_DIR/web" && echo "  OK web/ dashboard" || echo "  INFO: web/ not found"
command -v hermes >/dev/null 2>&1 && echo "  OK hermes CLI: $(which hermes)" || echo "  INFO: hermes CLI not in PATH"

# Create logs
mkdir -p /opt/data/logs
touch /opt/data/logs/app.log

ENTRYPOINT_END=$(date +%s)
echo "[TIMER] Entrypoint (before sync_hf.py): $((ENTRYPOINT_END - BOOT_START))s"

# ── Start Hermes via sync_hf.py (handles persistence + process management)
echo "[entrypoint] Starting Hermes Agent via sync_hf.py..."
exec python3 -u /opt/data/scripts/sync_hf.py