mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
refactor: migrate tool progress configuration from environment variables to config.yaml
This commit is contained in:
parent
0862fa96fd
commit
de5a88bd97
9 changed files with 114 additions and 52 deletions
|
|
@ -248,9 +248,7 @@ DISCORD_ALLOWED_USERS=123456789012345678 # Comma-separated user IDs
|
|||
HERMES_MAX_ITERATIONS=60 # Max tool-calling iterations
|
||||
MESSAGING_CWD=/home/myuser # Terminal working directory for messaging
|
||||
|
||||
# Tool Progress (optional)
|
||||
HERMES_TOOL_PROGRESS=true # Send progress messages
|
||||
HERMES_TOOL_PROGRESS_MODE=new # "new" or "all"
|
||||
# Tool progress is configured in config.yaml (display.tool_progress: off|new|all|verbose)
|
||||
```
|
||||
|
||||
### Working Directory Behavior
|
||||
|
|
@ -301,7 +299,7 @@ Files: `gateway/hooks.py`
|
|||
|
||||
### Tool Progress Notifications
|
||||
|
||||
When `HERMES_TOOL_PROGRESS=true`, the bot sends status messages as it works:
|
||||
When `tool_progress` is enabled in `config.yaml`, the bot sends status messages as it works:
|
||||
- `💻 \`ls -la\`...` (terminal commands show the actual command)
|
||||
- `🔍 web_search...`
|
||||
- `📄 web_extract...`
|
||||
|
|
@ -411,8 +409,7 @@ Terminal tool configuration (in `~/.hermes/config.yaml`):
|
|||
Agent behavior (in `~/.hermes/.env`):
|
||||
- `HERMES_MAX_ITERATIONS` - Max tool-calling iterations (default: 60)
|
||||
- `MESSAGING_CWD` - Working directory for messaging platforms (default: ~)
|
||||
- `HERMES_TOOL_PROGRESS` - Enable tool progress messages (`true`/`false`)
|
||||
- `HERMES_TOOL_PROGRESS_MODE` - Progress mode: `new` (tool changes) or `all`
|
||||
- `display.tool_progress` in config.yaml - Tool progress: `off`, `new`, `all`, `verbose`
|
||||
- `OPENAI_API_KEY` - Voice transcription (Whisper STT)
|
||||
- `SLACK_BOT_TOKEN` / `SLACK_APP_TOKEN` - Slack integration (Socket Mode)
|
||||
- `SLACK_ALLOWED_USERS` - Comma-separated Slack user IDs
|
||||
|
|
|
|||
20
README.md
20
README.md
|
|
@ -325,14 +325,22 @@ TERMINAL_CWD=/workspace # All terminal sessions (local or contain
|
|||
|
||||
### Tool Progress Notifications
|
||||
|
||||
Get real-time updates as the agent works:
|
||||
Control how much tool activity is displayed. Set in `~/.hermes/config.yaml`:
|
||||
|
||||
```bash
|
||||
# Enable in ~/.hermes/.env
|
||||
HERMES_TOOL_PROGRESS=true
|
||||
HERMES_TOOL_PROGRESS_MODE=all # or "new" for only when tool changes
|
||||
```yaml
|
||||
display:
|
||||
tool_progress: all # off | new | all | verbose
|
||||
```
|
||||
|
||||
| Mode | What you see |
|
||||
|------|-------------|
|
||||
| `off` | Silent — just the final response |
|
||||
| `new` | Tool indicator only when the tool changes (skip repeats) |
|
||||
| `all` | Every tool call with a short preview (default) |
|
||||
| `verbose` | Full args, results, and debug logs |
|
||||
|
||||
Toggle at runtime in the CLI with `/verbose` (cycles through all four modes).
|
||||
|
||||
---
|
||||
|
||||
## Commands
|
||||
|
|
@ -1568,8 +1576,6 @@ All variables go in `~/.hermes/.env`. Run `hermes config set VAR value` to set t
|
|||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `HERMES_MAX_ITERATIONS` | Max tool-calling iterations per conversation (default: 60) |
|
||||
| `HERMES_TOOL_PROGRESS` | Send progress messages when using tools (`true`/`false`) |
|
||||
| `HERMES_TOOL_PROGRESS_MODE` | `all` (every call, default) or `new` (only when tool changes) |
|
||||
|
||||
**Context Compression:**
|
||||
| Variable | Description |
|
||||
|
|
|
|||
|
|
@ -487,3 +487,11 @@ delegation:
|
|||
display:
|
||||
# Use compact banner mode
|
||||
compact: false
|
||||
|
||||
# Tool progress display level (CLI and gateway)
|
||||
# off: Silent — no tool activity shown, just the final response
|
||||
# new: Show a tool indicator only when the tool changes (skip repeats)
|
||||
# all: Show every tool call with a short preview (default)
|
||||
# verbose: Full args, results, and debug logs (same as /verbose)
|
||||
# Toggle at runtime with /verbose in the CLI
|
||||
tool_progress: all
|
||||
|
|
|
|||
25
cli.py
25
cli.py
|
|
@ -793,7 +793,9 @@ class HermesCLI:
|
|||
# Initialize Rich console
|
||||
self.console = Console()
|
||||
self.compact = compact if compact is not None else CLI_CONFIG["display"].get("compact", False)
|
||||
self.verbose = verbose if verbose is not None else CLI_CONFIG["agent"].get("verbose", False)
|
||||
# tool_progress: "off", "new", "all", "verbose" (from config.yaml display section)
|
||||
self.tool_progress_mode = CLI_CONFIG["display"].get("tool_progress", "all")
|
||||
self.verbose = verbose if verbose is not None else (self.tool_progress_mode == "verbose")
|
||||
|
||||
# Configuration - priority: CLI args > env vars > config file
|
||||
# Model can come from: CLI arg, LLM_MODEL env, OPENAI_MODEL env (custom endpoint), or config
|
||||
|
|
@ -1697,24 +1699,35 @@ class HermesCLI:
|
|||
return True
|
||||
|
||||
def _toggle_verbose(self):
|
||||
"""Toggle verbose mode on/off at runtime."""
|
||||
self.verbose = not self.verbose
|
||||
"""Cycle tool progress mode: off → new → all → verbose → off."""
|
||||
cycle = ["off", "new", "all", "verbose"]
|
||||
try:
|
||||
idx = cycle.index(self.tool_progress_mode)
|
||||
except ValueError:
|
||||
idx = 2 # default to "all"
|
||||
self.tool_progress_mode = cycle[(idx + 1) % len(cycle)]
|
||||
self.verbose = self.tool_progress_mode == "verbose"
|
||||
|
||||
if self.agent:
|
||||
self.agent.verbose_logging = self.verbose
|
||||
self.agent.quiet_mode = not self.verbose
|
||||
|
||||
# Reconfigure logging level to match new state
|
||||
labels = {
|
||||
"off": "[dim]Tool progress: OFF[/] — silent mode, just the final response.",
|
||||
"new": "[yellow]Tool progress: NEW[/] — show each new tool (skip repeats).",
|
||||
"all": "[green]Tool progress: ALL[/] — show every tool call.",
|
||||
"verbose": "[bold green]Tool progress: VERBOSE[/] — full args, results, and debug logs.",
|
||||
}
|
||||
self.console.print(labels.get(self.tool_progress_mode, ""))
|
||||
|
||||
if self.verbose:
|
||||
logging.getLogger().setLevel(logging.DEBUG)
|
||||
for noisy in ('openai', 'openai._base_client', 'httpx', 'httpcore', 'asyncio', 'hpack', 'grpc', 'modal'):
|
||||
logging.getLogger(noisy).setLevel(logging.WARNING)
|
||||
self.console.print("[bold green]Verbose mode ON[/] — tool calls, parameters, and results will be shown.")
|
||||
else:
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
for quiet_logger in ('tools', 'minisweagent', 'run_agent', 'trajectory_compressor', 'cron', 'hermes_cli'):
|
||||
logging.getLogger(quiet_logger).setLevel(logging.ERROR)
|
||||
self.console.print("[dim]Verbose mode OFF[/] — returning to normal display.")
|
||||
|
||||
def _clarify_callback(self, question, choices):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -223,11 +223,9 @@ MESSAGING_CWD=/home/myuser
|
|||
# TOOL PROGRESS NOTIFICATIONS
|
||||
# =============================================================================
|
||||
|
||||
# Show progress messages as agent uses tools
|
||||
HERMES_TOOL_PROGRESS=true
|
||||
|
||||
# Mode: "new" (only when tool changes) or "all" (every tool call)
|
||||
HERMES_TOOL_PROGRESS_MODE=new
|
||||
# Tool progress is now configured in config.yaml:
|
||||
# display:
|
||||
# tool_progress: all # off | new | all | verbose
|
||||
|
||||
# =============================================================================
|
||||
# SESSION SETTINGS
|
||||
|
|
@ -301,7 +299,7 @@ The gateway keeps the "typing..." indicator active throughout processing, refres
|
|||
|
||||
### Tool Progress Notifications
|
||||
|
||||
When `HERMES_TOOL_PROGRESS=true`, the bot sends status messages as it works:
|
||||
When `tool_progress` is enabled in `config.yaml`, the bot sends status messages as it works:
|
||||
|
||||
```text
|
||||
💻 `ls -la`...
|
||||
|
|
|
|||
|
|
@ -1462,9 +1462,24 @@ class GatewayRunner:
|
|||
default_toolset = default_toolset_map.get(source.platform, "hermes-telegram")
|
||||
enabled_toolsets = [default_toolset]
|
||||
|
||||
# Check if tool progress notifications are enabled
|
||||
tool_progress_enabled = os.getenv("HERMES_TOOL_PROGRESS", "true").lower() in ("1", "true", "yes")
|
||||
progress_mode = os.getenv("HERMES_TOOL_PROGRESS_MODE", "all") # "all" or "new" (only new tools)
|
||||
# Tool progress mode from config.yaml: "all", "new", "verbose", "off"
|
||||
# Falls back to env vars for backward compatibility
|
||||
_progress_cfg = {}
|
||||
try:
|
||||
_tp_cfg_path = _hermes_home / "config.yaml"
|
||||
if _tp_cfg_path.exists():
|
||||
import yaml as _tp_yaml
|
||||
with open(_tp_cfg_path) as _tp_f:
|
||||
_tp_data = _tp_yaml.safe_load(_tp_f) or {}
|
||||
_progress_cfg = _tp_data.get("display", {})
|
||||
except Exception:
|
||||
pass
|
||||
progress_mode = (
|
||||
_progress_cfg.get("tool_progress")
|
||||
or os.getenv("HERMES_TOOL_PROGRESS_MODE")
|
||||
or "all"
|
||||
)
|
||||
tool_progress_enabled = progress_mode != "off"
|
||||
|
||||
# Queue for progress messages (thread-safe)
|
||||
progress_queue = queue.Queue() if tool_progress_enabled else None
|
||||
|
|
@ -1627,6 +1642,7 @@ class GatewayRunner:
|
|||
base_url=base_url,
|
||||
max_iterations=max_iterations,
|
||||
quiet_mode=True,
|
||||
verbose_logging=False,
|
||||
enabled_toolsets=enabled_toolsets,
|
||||
ephemeral_system_prompt=combined_ephemeral or None,
|
||||
prefill_messages=self._prefill_messages or None,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ COMMANDS = {
|
|||
"/cron": "Manage scheduled tasks (list, add, remove)",
|
||||
"/skills": "Search, install, inspect, or manage skills from online registries",
|
||||
"/platforms": "Show gateway/messaging platform status",
|
||||
"/verbose": "Toggle verbose mode (show tool calls, parameters, and results)",
|
||||
"/verbose": "Cycle tool progress display: off → new → all → verbose",
|
||||
"/quit": "Exit the CLI (also: /exit, /q)",
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ DEFAULT_CONFIG = {
|
|||
"command_allowlist": [],
|
||||
|
||||
# Config schema version - bump this when adding new required fields
|
||||
"_config_version": 3,
|
||||
"_config_version": 4,
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
|
|
@ -318,16 +318,19 @@ OPTIONAL_ENV_VARS = {
|
|||
"password": False,
|
||||
"category": "setting",
|
||||
},
|
||||
# HERMES_TOOL_PROGRESS and HERMES_TOOL_PROGRESS_MODE are deprecated —
|
||||
# now configured via display.tool_progress in config.yaml (off|new|all|verbose).
|
||||
# Gateway falls back to these env vars for backward compatibility.
|
||||
"HERMES_TOOL_PROGRESS": {
|
||||
"description": "Send tool progress messages in messaging channels (true/false)",
|
||||
"prompt": "Enable tool progress messages",
|
||||
"description": "(deprecated) Use display.tool_progress in config.yaml instead",
|
||||
"prompt": "Tool progress (deprecated — use config.yaml)",
|
||||
"url": None,
|
||||
"password": False,
|
||||
"category": "setting",
|
||||
},
|
||||
"HERMES_TOOL_PROGRESS_MODE": {
|
||||
"description": "Progress mode: 'all' (every tool) or 'new' (only when tool changes)",
|
||||
"prompt": "Progress mode (all/new)",
|
||||
"description": "(deprecated) Use display.tool_progress in config.yaml instead",
|
||||
"prompt": "Progress mode (deprecated — use config.yaml)",
|
||||
"url": None,
|
||||
"password": False,
|
||||
"category": "setting",
|
||||
|
|
@ -442,6 +445,29 @@ def migrate_config(interactive: bool = True, quiet: bool = False) -> Dict[str, A
|
|||
# Check config version
|
||||
current_ver, latest_ver = check_config_version()
|
||||
|
||||
# ── Version 3 → 4: migrate tool progress from .env to config.yaml ──
|
||||
if current_ver < 4:
|
||||
config = load_config()
|
||||
display = config.get("display", {})
|
||||
if not isinstance(display, dict):
|
||||
display = {}
|
||||
if "tool_progress" not in display:
|
||||
old_enabled = get_env_value("HERMES_TOOL_PROGRESS")
|
||||
old_mode = get_env_value("HERMES_TOOL_PROGRESS_MODE")
|
||||
if old_enabled and old_enabled.lower() in ("false", "0", "no"):
|
||||
display["tool_progress"] = "off"
|
||||
results["config_added"].append("display.tool_progress=off (from HERMES_TOOL_PROGRESS=false)")
|
||||
elif old_mode and old_mode.lower() in ("new", "all"):
|
||||
display["tool_progress"] = old_mode.lower()
|
||||
results["config_added"].append(f"display.tool_progress={old_mode.lower()} (from HERMES_TOOL_PROGRESS_MODE)")
|
||||
else:
|
||||
display["tool_progress"] = "all"
|
||||
results["config_added"].append("display.tool_progress=all (default)")
|
||||
config["display"] = display
|
||||
save_config(config)
|
||||
if not quiet:
|
||||
print(f" ✓ Migrated tool progress to config.yaml: {display['tool_progress']}")
|
||||
|
||||
if current_ver < latest_ver and not quiet:
|
||||
print(f"Config version: {current_ver} → {latest_ver}")
|
||||
|
||||
|
|
|
|||
|
|
@ -1044,27 +1044,25 @@ def run_setup_wizard(args):
|
|||
except ValueError:
|
||||
print_warning("Invalid number, keeping current value")
|
||||
|
||||
# Tool progress notifications (for messaging)
|
||||
# Tool progress notifications
|
||||
print_info("")
|
||||
print_info("Tool Progress Notifications (Messaging only)")
|
||||
print_info("Send status messages when the agent uses tools.")
|
||||
print_info("Example: '💻 ls -la...' or '🔍 web_search...'")
|
||||
print_info("Tool Progress Display")
|
||||
print_info("Controls how much tool activity is shown (CLI and messaging).")
|
||||
print_info(" off — Silent, just the final response")
|
||||
print_info(" new — Show tool name only when it changes (less noise)")
|
||||
print_info(" all — Show every tool call with a short preview")
|
||||
print_info(" verbose — Full args, results, and debug logs")
|
||||
|
||||
current_progress = get_env_value('HERMES_TOOL_PROGRESS') or 'true'
|
||||
if prompt_yes_no("Enable tool progress messages?", current_progress.lower() in ('1', 'true', 'yes')):
|
||||
save_env_value("HERMES_TOOL_PROGRESS", "true")
|
||||
|
||||
# Progress mode
|
||||
current_mode = get_env_value('HERMES_TOOL_PROGRESS_MODE') or 'all'
|
||||
print_info(" Mode options:")
|
||||
print_info(" 'new' - Only when switching tools (less spam)")
|
||||
print_info(" 'all' - Every tool call")
|
||||
mode = prompt(" Progress mode", current_mode)
|
||||
if mode.lower() in ('all', 'new'):
|
||||
save_env_value("HERMES_TOOL_PROGRESS_MODE", mode.lower())
|
||||
print_success("Tool progress enabled")
|
||||
current_mode = config.get("display", {}).get("tool_progress", "all")
|
||||
mode = prompt("Tool progress mode", current_mode)
|
||||
if mode.lower() in ("off", "new", "all", "verbose"):
|
||||
if "display" not in config:
|
||||
config["display"] = {}
|
||||
config["display"]["tool_progress"] = mode.lower()
|
||||
save_config(config)
|
||||
print_success(f"Tool progress set to: {mode.lower()}")
|
||||
else:
|
||||
save_env_value("HERMES_TOOL_PROGRESS", "false")
|
||||
print_warning(f"Unknown mode '{mode}', keeping '{current_mode}'")
|
||||
|
||||
# =========================================================================
|
||||
# Step 6: Context Compression
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue