Hermes Agent UX Improvements

This commit is contained in:
teknium1 2026-02-22 02:16:11 -08:00
parent b1f55e3ee5
commit ededaaa874
23 changed files with 945 additions and 1545 deletions

View file

@ -20,6 +20,7 @@ import re
import sys
import signal
import threading
from logging.handlers import RotatingFileHandler
from pathlib import Path
from datetime import datetime
from typing import Dict, Optional, Any, List
@ -402,9 +403,27 @@ class GatewayRunner:
# Build the context prompt to inject
context_prompt = build_session_context_prompt(context)
# If the previous session expired and was auto-reset, prepend a notice
# so the agent knows this is a fresh conversation (not an intentional /reset).
if getattr(session_entry, 'was_auto_reset', False):
context_prompt = (
"[System note: The user's previous session expired due to inactivity. "
"This is a fresh conversation with no prior context.]\n\n"
+ context_prompt
)
session_entry.was_auto_reset = False
# Load conversation history from transcript
history = self.session_store.load_transcript(session_entry.session_id)
# First-message onboarding for brand-new messaging platform users
if not history:
context_prompt += (
"\n\n[System note: This is the user's very first message in this session. "
"Briefly introduce yourself and mention that /help shows available commands. "
"Keep the introduction concise -- one or two sentences max.]"
)
# -----------------------------------------------------------------
# Auto-analyze images sent by the user
#
@ -1342,15 +1361,32 @@ def _start_cron_ticker(stop_event: threading.Event, interval: int = 60):
Runs inside the gateway process so cronjobs fire automatically without
needing a separate `hermes cron daemon` or system cron entry.
Every 60th tick (~once per hour) the image/audio cache is pruned so
stale temp files don't accumulate.
"""
from cron.scheduler import tick as cron_tick
from gateway.platforms.base import cleanup_image_cache
IMAGE_CACHE_EVERY = 60 # ticks — once per hour at default 60s interval
logger.info("Cron ticker started (interval=%ds)", interval)
tick_count = 0
while not stop_event.is_set():
try:
cron_tick(verbose=False)
except Exception as e:
logger.debug("Cron tick error: %s", e)
tick_count += 1
if tick_count % IMAGE_CACHE_EVERY == 0:
try:
removed = cleanup_image_cache(max_age_hours=24)
if removed:
logger.info("Image cache cleanup: removed %d stale file(s)", removed)
except Exception as e:
logger.debug("Image cache cleanup error: %s", e)
stop_event.wait(timeout=interval)
logger.info("Cron ticker stopped")
@ -1363,6 +1399,18 @@ async def start_gateway(config: Optional[GatewayConfig] = None) -> bool:
Returns True if the gateway ran successfully, False if it failed to start.
A False return causes a non-zero exit code so systemd can auto-restart.
"""
# Configure rotating file log so gateway output is persisted for debugging
log_dir = Path.home() / '.hermes' / 'logs'
log_dir.mkdir(parents=True, exist_ok=True)
file_handler = RotatingFileHandler(
log_dir / 'gateway.log',
maxBytes=5 * 1024 * 1024,
backupCount=3,
)
file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(name)s: %(message)s'))
logging.getLogger().addHandler(file_handler)
logging.getLogger().setLevel(logging.INFO)
runner = GatewayRunner(config)
# Set up signal handlers