Z User commited on
Commit
f0b15e1
·
1 Parent(s): 7bfa1b4

feat: pin hermes-agent v0.12.0 + runtime auto-update

Browse files

Dockerfile:
- Pin hermes-agent to v2026.4.30 (v0.12.0) release tag
- Write /app/hermes-agent.version for runtime tracking

start.sh: update_hermes_agent_background()
- Queries GitHub releases/latest for newest tag
- Date-style version comparison (2026.4.30 format)
- 5-phase safe update: fetch → checkout → pip install → re-patch → reload signal
- Rollback on failure: git checkout old tag + pip reinstall
- Re-applies Hermes Bot patches (prompt_builder, send_message_tool, etc.)
- Signals entry.py via SIGUSR1 for gateway restart
- Version tracked in /data/hermes/agent.version (persistent)
- Set AGENT_AUTO_UPDATE=false to disable

Files changed (2) hide show
  1. Dockerfile +4 -2
  2. start.sh +126 -0
Dockerfile CHANGED
@@ -11,8 +11,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
11
 
12
  WORKDIR /app
13
 
14
- # Clone hermes-agent
15
- RUN git clone --depth 1 https://github.com/NousResearch/hermes-agent.git /app/hermes-agent
 
 
16
 
17
  # Build venv
18
  RUN python3 -m venv /app/venv
 
11
 
12
  WORKDIR /app
13
 
14
+ # Clone hermes-agent (pinned to v2026.4.30 = v0.12.0)
15
+ # Runtime auto-update will pull newer releases transparently
16
+ RUN git clone --depth 1 --branch v2026.4.30 https://github.com/NousResearch/hermes-agent.git /app/hermes-agent && \
17
+ echo "v2026.4.30" > /app/hermes-agent.version
18
 
19
  # Build venv
20
  RUN python3 -m venv /app/venv
start.sh CHANGED
@@ -444,6 +444,129 @@ for i in $(seq 1 60); do
444
  sleep 2
445
  done
446
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  # ── Auto-update hermes-web-ui if newer release exists ──
448
  # Runs asynchronously so it doesn't block startup.
449
  # Check: GitHub releases/latest → compare with saved version → build if newer.
@@ -585,6 +708,9 @@ node index.js >> /data/hermes/logs/webui.log 2>&1 &
585
  WEBUI_PID=$!
586
  echo "[$(date)] WebUI BFF PID: $WEBUI_PID"
587
 
 
 
 
588
  # Trigger WebUI auto-update in background (non-blocking)
589
  # Will check GitHub, build if newer, and hot-swap
590
  update_webui_background &
 
444
  sleep 2
445
  done
446
 
447
+ # ── Auto-update hermes-agent if newer release exists ──
448
+ # hermes-agent is pip install -e (editable), so git pull + pip upgrade = instant.
449
+ # Safety: update runs in background; if pip fails, old code stays intact.
450
+ # Set AGENT_AUTO_UPDATE=false to disable.
451
+ update_hermes_agent_background() {
452
+ [ "${AGENT_AUTO_UPDATE}" = "false" ] && return
453
+
454
+ AGENT_REPO="NousResearch/hermes-agent"
455
+ AGENT_DIR="/app/hermes-agent"
456
+ VERSION_FILE="/data/hermes/agent.version"
457
+ API_URL="https://api.github.com/repos/${AGENT_REPO}/releases/latest"
458
+ EXTRAS="feishu,mcp,cron,pty"
459
+
460
+ # Current version (from Dockerfile build or previous update)
461
+ CURRENT_VERSION="$(cat "$VERSION_FILE" 2>/dev/null | head -1)"
462
+ if [ -z "$CURRENT_VERSION" ]; then
463
+ # Try build-time version file
464
+ CURRENT_VERSION="$(cat /app/hermes-agent.version 2>/dev/null | head -1)"
465
+ [ -z "$CURRENT_VERSION" ] && CURRENT_VERSION="v2026.4.30"
466
+ echo "$CURRENT_VERSION" > "$VERSION_FILE"
467
+ fi
468
+
469
+ # Version comparison helper: strip leading 'v', compare date-style like 2026.4.30
470
+ compare_date_versions() {
471
+ local a="${1#v}" b="${2#v}"
472
+ IFS='.' read -ra A <<< "$a"
473
+ IFS='.' read -ra B <<< "$b"
474
+ for i in 0 1 2; do
475
+ local ai=${A[$i]:-0} bi=${B[$i]:-0}
476
+ if [ "$bi" -gt "$ai" ] 2>/dev/null; then return 0; fi
477
+ if [ "$bi" -lt "$ai" ] 2>/dev/null; then return 1; fi
478
+ done
479
+ return 1 # equal or older
480
+ }
481
+
482
+ echo "[$(date)] Agent auto-update: checking (current: $CURRENT_VERSION)..."
483
+
484
+ # Query GitHub API
485
+ LATEST_JSON=$(curl -sf --connect-timeout 10 --max-time 20 "$API_URL" 2>/dev/null)
486
+ if [ $? -ne 0 ] || [ -z "$LATEST_JSON" ]; then
487
+ echo "[$(date)] Agent auto-update: failed to reach GitHub API, skipping"
488
+ return
489
+ fi
490
+
491
+ LATEST_TAG=$(echo "$LATEST_JSON" | python3 -c "import json,sys; print(json.load(sys.stdin).get('tag_name',''))" 2>/dev/null)
492
+ if [ -z "$LATEST_TAG" ]; then
493
+ echo "[$(date)] Agent auto-update: could not parse latest tag, skipping"
494
+ return
495
+ fi
496
+
497
+ echo "[$(date)] Agent auto-update: latest release is $LATEST_TAG"
498
+
499
+ # Compare
500
+ if compare_date_versions "$CURRENT_VERSION" "$LATEST_TAG"; then
501
+ echo "[$(date)] Agent auto-update: upgrading $CURRENT_VERSION → $LATEST_TAG ..."
502
+ else
503
+ echo "[$(date)] Agent auto-update: $CURRENT_VERSION is up to date"
504
+ return
505
+ fi
506
+
507
+ # Phase 1: git fetch + checkout new tag (non-destructive)
508
+ cd "$AGENT_DIR"
509
+ if ! git fetch --tags origin 2>&1 | tail -3; then
510
+ echo "[$(date)] Agent auto-update: git fetch failed, aborting"
511
+ return
512
+ fi
513
+
514
+ # Verify tag exists
515
+ if ! git rev-parse "$LATEST_TAG" >/dev/null 2>&1; then
516
+ echo "[$(date)] Agent auto-update: tag $LATEST_TAG not found, aborting"
517
+ return
518
+ fi
519
+
520
+ # Phase 2: checkout new version
521
+ if ! git checkout "$LATEST_TAG" 2>&1 | tail -3; then
522
+ echo "[$(date)] Agent auto-update: git checkout failed, aborting"
523
+ # Try to recover to previous version
524
+ git checkout "$CURRENT_VERSION" 2>/dev/null
525
+ return
526
+ fi
527
+
528
+ # Phase 3: update pip dependencies (editable install)
529
+ echo "[$(date)] Agent auto-update: updating pip dependencies..."
530
+ if ! pip install --quiet -e "/app/hermes-agent[${EXTRAS}]" 2>&1 | tail -10; then
531
+ echo "[$(date)] Agent auto-update: pip install failed, rolling back"
532
+ git checkout "$CURRENT_VERSION" 2>/dev/null
533
+ pip install --quiet -e "/app/hermes-agent[${EXTRAS}]" 2>/dev/null
534
+ return
535
+ fi
536
+
537
+ # Phase 4: reinstall our patches on top of new version
538
+ echo "[$(date)] Agent auto-update: re-applying Hermes Bot patches..."
539
+ if [ -f "/app/scripts/patch_file_delivery.py" ]; then
540
+ python3 /app/scripts/patch_file_delivery.py 2>/dev/null
541
+ fi
542
+ if [ -f "/app/scripts/patch_auto_media.py" ]; then
543
+ python3 /app/scripts/patch_auto_media.py 2>/dev/null
544
+ fi
545
+ if [ -f "/app/scripts/patch_resolve_media_paths.py" ]; then
546
+ python3 /app/scripts/patch_resolve_media_paths.py 2>/dev/null
547
+ fi
548
+ # Copy patch files if they exist
549
+ for patch_file in prompt_builder.py send_message_tool.py; do
550
+ if [ -f "/app/patches/hermes-agent/agent/$patch_file" ] && [ -f "$AGENT_DIR/agent/$patch_file" ]; then
551
+ cp "/app/patches/hermes-agent/agent/$patch_file" "$AGENT_DIR/agent/$patch_file" 2>/dev/null
552
+ fi
553
+ done
554
+
555
+ # Save new version
556
+ echo "$LATEST_TAG" > "$VERSION_FILE"
557
+ echo "$(date '+%Y-%m-%d %H:%M:%S')" >> "$VERSION_FILE"
558
+ echo "[$(date)] Agent auto-update: upgraded to $LATEST_TAG ✓ (restart needed for full effect)"
559
+
560
+ # Phase 5: schedule gateway restart for clean reload
561
+ # Send SIGUSR1 to entry.py to trigger gateway restart cycle
562
+ ENTRY_PID=$(pgrep -f "python3 /app/entry.py" 2>/dev/null | head -1)
563
+ if [ -n "$ENTRY_PID" ]; then
564
+ kill -USR1 "$ENTRY_PID" 2>/dev/null && \
565
+ echo "[$(date)] Agent auto-update: sent reload signal to entry.py (PID: $ENTRY_PID)" || \
566
+ echo "[$(date)] Agent auto-update: gateway will use new code on next conversation"
567
+ fi
568
+ }
569
+
570
  # ── Auto-update hermes-web-ui if newer release exists ──
571
  # Runs asynchronously so it doesn't block startup.
572
  # Check: GitHub releases/latest → compare with saved version → build if newer.
 
708
  WEBUI_PID=$!
709
  echo "[$(date)] WebUI BFF PID: $WEBUI_PID"
710
 
711
+ # Trigger hermes-agent auto-update in background (framework first, then UI)
712
+ update_hermes_agent_background &
713
+
714
  # Trigger WebUI auto-update in background (non-blocking)
715
  # Will check GitHub, build if newer, and hot-swap
716
  update_webui_background &