mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-02 02:01:47 +00:00
fix: remove ANSI codes and em dashes from menu labels
simple_term_menu miscalculates string widths when labels contain ANSI escape codes (from color()) or em dashes, causing duplicated and garbled lines on arrow key navigation. Replace color() status indicators with plain text [configured]/[active] and em dashes with regular dashes in all prompt_choice/prompt_checklist labels.
This commit is contained in:
parent
ab9cadfeee
commit
0111c9848d
1 changed files with 26 additions and 22 deletions
|
|
@ -475,13 +475,13 @@ TOOL_CATEGORIES = [
|
|||
"providers": [
|
||||
{
|
||||
"name": "Microsoft Edge TTS",
|
||||
"tag": "Free — no API key needed",
|
||||
"tag": "Free - no API key needed",
|
||||
"env_vars": [],
|
||||
"tts_provider": "edge",
|
||||
},
|
||||
{
|
||||
"name": "OpenAI TTS",
|
||||
"tag": "Premium — high quality voices",
|
||||
"tag": "Premium - high quality voices",
|
||||
"env_vars": [
|
||||
{"key": "VOICE_TOOLS_OPENAI_KEY", "prompt": "OpenAI API key", "url": "https://platform.openai.com/api-keys"},
|
||||
],
|
||||
|
|
@ -489,7 +489,7 @@ TOOL_CATEGORIES = [
|
|||
},
|
||||
{
|
||||
"name": "ElevenLabs",
|
||||
"tag": "Premium — most natural voices",
|
||||
"tag": "Premium - most natural voices",
|
||||
"env_vars": [
|
||||
{"key": "ELEVENLABS_API_KEY", "prompt": "ElevenLabs API key", "url": "https://elevenlabs.io/app/settings/api-keys"},
|
||||
],
|
||||
|
|
@ -504,14 +504,14 @@ TOOL_CATEGORIES = [
|
|||
"providers": [
|
||||
{
|
||||
"name": "Firecrawl Cloud",
|
||||
"tag": "Recommended — hosted service",
|
||||
"tag": "Recommended - hosted service",
|
||||
"env_vars": [
|
||||
{"key": "FIRECRAWL_API_KEY", "prompt": "Firecrawl API key", "url": "https://firecrawl.dev"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Firecrawl Self-Hosted",
|
||||
"tag": "Free — run your own instance",
|
||||
"tag": "Free - run your own instance",
|
||||
"env_vars": [
|
||||
{"key": "FIRECRAWL_API_URL", "prompt": "Your Firecrawl instance URL (e.g., http://localhost:3002)"},
|
||||
],
|
||||
|
|
@ -1136,30 +1136,30 @@ def setup_terminal_backend(config: dict):
|
|||
|
||||
# Build backend choices with descriptions
|
||||
terminal_choices = [
|
||||
"Local — run directly on this machine (default)",
|
||||
"Docker — isolated container with configurable resources",
|
||||
"Local - run directly on this machine (default)",
|
||||
"Docker - isolated container with configurable resources",
|
||||
]
|
||||
idx_to_backend = {0: "local", 1: "docker"}
|
||||
backend_to_idx = {"local": 0, "docker": 1}
|
||||
|
||||
next_idx = 2
|
||||
if is_linux:
|
||||
terminal_choices.append("Singularity/Apptainer — HPC-friendly container")
|
||||
terminal_choices.append("Singularity/Apptainer - HPC-friendly container")
|
||||
idx_to_backend[next_idx] = "singularity"
|
||||
backend_to_idx["singularity"] = next_idx
|
||||
next_idx += 1
|
||||
|
||||
terminal_choices.append("Modal — serverless cloud sandbox")
|
||||
terminal_choices.append("Modal - serverless cloud sandbox")
|
||||
idx_to_backend[next_idx] = "modal"
|
||||
backend_to_idx["modal"] = next_idx
|
||||
next_idx += 1
|
||||
|
||||
terminal_choices.append("Daytona — persistent cloud development environment")
|
||||
terminal_choices.append("Daytona - persistent cloud development environment")
|
||||
idx_to_backend[next_idx] = "daytona"
|
||||
backend_to_idx["daytona"] = next_idx
|
||||
next_idx += 1
|
||||
|
||||
terminal_choices.append("SSH — run on a remote machine")
|
||||
terminal_choices.append("SSH - run on a remote machine")
|
||||
idx_to_backend[next_idx] = "ssh"
|
||||
backend_to_idx["ssh"] = next_idx
|
||||
next_idx += 1
|
||||
|
|
@ -1478,7 +1478,7 @@ def setup_agent_settings(config: dict):
|
|||
print_info("")
|
||||
|
||||
reset_choices = [
|
||||
"Inactivity + daily reset (recommended — reset whichever comes first)",
|
||||
"Inactivity + daily reset (recommended - reset whichever comes first)",
|
||||
"Inactivity only (reset after N minutes of no messages)",
|
||||
"Daily only (reset at a fixed hour each day)",
|
||||
"Never auto-reset (context lives until /reset or context compression)",
|
||||
|
|
@ -1822,17 +1822,19 @@ def setup_tools(config: dict):
|
|||
print()
|
||||
|
||||
# Build checklist from TOOL_CATEGORIES
|
||||
# NOTE: Do NOT use color() / ANSI codes in menu labels —
|
||||
# simple_term_menu miscalculates widths and causes garbled redraws.
|
||||
checklist_labels = []
|
||||
for cat in TOOL_CATEGORIES:
|
||||
icon = cat.get("icon", "")
|
||||
name = cat["name"]
|
||||
desc = cat.get("description", "")
|
||||
|
||||
# Check if already configured
|
||||
# Check if already configured — plain text only (no ANSI codes)
|
||||
configured = _is_tool_configured(cat)
|
||||
status = color(" ✓", Colors.GREEN) if configured else ""
|
||||
status = " [configured]" if configured else ""
|
||||
|
||||
checklist_labels.append(f"{icon} {name} — {desc}{status}")
|
||||
checklist_labels.append(f"{icon} {name} - {desc}{status}")
|
||||
|
||||
# Pre-select tools that are already configured
|
||||
pre_selected = [i for i, cat in enumerate(TOOL_CATEGORIES) if _is_tool_configured(cat)]
|
||||
|
|
@ -1901,6 +1903,8 @@ def _configure_tool_category(cat: dict, config: dict):
|
|||
print(color(f" ─── {icon} {name} — Choose a provider ───", Colors.CYAN))
|
||||
print()
|
||||
|
||||
# NOTE: Do NOT use color() / ANSI codes in menu labels —
|
||||
# simple_term_menu miscalculates widths and causes garbled redraws.
|
||||
provider_choices = []
|
||||
for p in providers:
|
||||
tag = f" ({p['tag']})" if p.get("tag") else ""
|
||||
|
|
@ -1910,11 +1914,11 @@ def _configure_tool_category(cat: dict, config: dict):
|
|||
# Check TTS provider match for edge
|
||||
if p.get("tts_provider"):
|
||||
if config.get("tts", {}).get("provider") == p["tts_provider"]:
|
||||
configured = color(" ✓ active", Colors.GREEN)
|
||||
configured = " [active]"
|
||||
elif not env_vars:
|
||||
configured = color(" ✓ active", Colors.GREEN)
|
||||
configured = " [active]"
|
||||
else:
|
||||
configured = color(" ✓ configured", Colors.GREEN)
|
||||
configured = " [configured]"
|
||||
provider_choices.append(f"{p['name']}{tag}{configured}")
|
||||
|
||||
# Detect current provider as default
|
||||
|
|
@ -2057,15 +2061,15 @@ def run_setup_wizard(args):
|
|||
print()
|
||||
|
||||
menu_choices = [
|
||||
"Quick Setup — configure missing items only",
|
||||
"Full Setup — reconfigure everything",
|
||||
"─────────────────────────────",
|
||||
"Quick Setup - configure missing items only",
|
||||
"Full Setup - reconfigure everything",
|
||||
"---",
|
||||
"Model & Provider",
|
||||
"Terminal Backend",
|
||||
"Messaging Platforms (Gateway)",
|
||||
"Tools",
|
||||
"Agent Settings",
|
||||
"─────────────────────────────",
|
||||
"---",
|
||||
"Exit",
|
||||
]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue