Merge branch 'main' of github.com:NousResearch/hermes-agent into bb/gui

This commit is contained in:
Brooklyn Nicholson
2026-05-30 23:10:43 -05:00
19 changed files with 1079 additions and 286 deletions
+47 -2
View File
@@ -9776,16 +9776,61 @@ def _cmd_update_impl(args, gateway_mode: bool):
missing_config = get_missing_config_fields()
current_ver, latest_ver = check_config_version()
needs_migration = missing_env or missing_config or current_ver < latest_ver
has_new_options = bool(missing_env or missing_config)
version_bump_only = (
not has_new_options and current_ver < latest_ver
)
needs_migration = has_new_options or current_ver < latest_ver
if needs_migration:
if version_bump_only:
# Nothing for the user to fill in — only the config format version
# changed (new defaults already merge in transparently). Asking
# "configure new options now?" here is misleading: saying yes just
# bumps the version and looks like a no-op (issue: ScottFive /
# Tt2021). Apply it silently and say what actually happened.
print()
print(
f" Updating config format (v{current_ver} → v{latest_ver})…"
)
try:
migrate_config(interactive=False, quiet=True)
print(" ✓ Config format updated (no new settings to configure)")
except Exception as _mig_err:
print(f" ⚠️ Config format update failed: {_mig_err}")
print(" Run 'hermes config migrate' to retry.")
elif needs_migration:
print()
# Show WHAT changed, not just a count, so the user can make an
# informed yes/no decision (previously the prompt named nothing).
def _print_items(items, label, key, fallback_key=None):
if not items:
return
print(f" {label}:")
shown = items[:8]
for it in shown:
if isinstance(it, dict):
name = it.get(key) or (fallback_key and it.get(fallback_key)) or "?"
desc = (it.get("description") or "").strip()
else:
# Defensive: some callers/mocks pass bare name strings.
name = str(it)
desc = ""
if desc:
print(f"{name}{desc}")
else:
print(f"{name}")
extra = len(items) - len(shown)
if extra > 0:
print(f" … and {extra} more")
if missing_env:
print(
f" ⚠️ {len(missing_env)} new required setting(s) need configuration"
)
_print_items(missing_env, "New settings", "name")
if missing_config:
print(f" {len(missing_config)} new config option(s) available")
_print_items(missing_config, "New options", "key")
print()
if assume_yes:
+51 -33
View File
@@ -32,34 +32,43 @@ COPILOT_REASONING_EFFORTS_O_SERIES = ["low", "medium", "high"]
# Fallback OpenRouter snapshot used when the live catalog is unavailable.
# (model_id, display description shown in menus)
OPENROUTER_MODELS: list[tuple[str, str]] = [
# Anthropic
("anthropic/claude-opus-4.8", ""),
("anthropic/claude-opus-4.8-fast", "2x price, higher output speed"),
("anthropic/claude-opus-4.7", ""),
("anthropic/claude-opus-4.6", ""),
("anthropic/claude-sonnet-4.6", ""),
("moonshotai/kimi-k2.6", "recommended"),
("openrouter/pareto-code", "auto-routes to cheapest coder meeting openrouter.min_coding_score"),
("qwen/qwen3.7-max", ""),
("anthropic/claude-haiku-4.5", ""),
# OpenAI
("openai/gpt-5.5", ""),
("openai/gpt-5.5-pro", ""),
("openai/gpt-5.4-mini", ""),
("openai/gpt-5.4-nano", ""),
("openai/gpt-5.3-codex", ""),
("xiaomi/mimo-v2.5-pro", ""),
("tencent/hy3-preview", ""),
("google/gemini-3-pro-image-preview", ""),
("google/gemini-3.5-flash", ""),
# Google
("google/gemini-3-pro-preview", ""),
("google/gemini-3.1-pro-preview", ""),
("google/gemini-3.1-flash-lite-preview", ""),
("qwen/qwen3.6-35b-a3b", ""),
("stepfun/step-3.7-flash", ""),
("minimax/minimax-m2.7", ""),
("z-ai/glm-5.1", ""),
("x-ai/grok-4.20", ""),
("google/gemini-3.5-flash", ""),
# xAI
("x-ai/grok-4.3", ""),
("nvidia/nemotron-3-super-120b-a12b", ""),
# DeepSeek
("deepseek/deepseek-v4-pro", ""),
("deepseek/deepseek-v4-flash", ""),
# Qwen
("qwen/qwen3.7-max", ""),
("qwen/qwen3.6-35b-a3b", ""),
# MoonshotAI
("moonshotai/kimi-k2.6", "recommended"),
# MiniMax
("minimax/minimax-m2.7", ""),
# Z-AI
("z-ai/glm-5.1", ""),
# Xiaomi
("xiaomi/mimo-v2.5-pro", ""),
# Tencent
("tencent/hy3-preview", ""),
# StepFun
("stepfun/step-3.7-flash", ""),
# NVIDIA
("nvidia/nemotron-3-super-120b-a12b", ""),
# OpenRouter routers
("openrouter/pareto-code", "auto-routes to cheapest coder meeting openrouter.min_coding_score"),
# Free tier
("openrouter/elephant-alpha", "free"),
("openrouter/owl-alpha", "free"),
@@ -141,31 +150,40 @@ def _xai_curated_models() -> list[str]:
_PROVIDER_MODELS: dict[str, list[str]] = {
"nous": [
# Anthropic
"anthropic/claude-opus-4.8",
"anthropic/claude-opus-4.7",
"anthropic/claude-opus-4.6",
"anthropic/claude-sonnet-4.6",
"moonshotai/kimi-k2.6",
"qwen/qwen3.7-max",
"anthropic/claude-haiku-4.5",
# OpenAI
"openai/gpt-5.5",
"openai/gpt-5.5-pro",
"openai/gpt-5.4-mini",
"openai/gpt-5.4-nano",
"openai/gpt-5.3-codex",
"xiaomi/mimo-v2.5-pro",
"tencent/hy3-preview",
# Google
"google/gemini-3-pro-preview",
"google/gemini-3.5-flash",
"google/gemini-3.1-pro-preview",
"google/gemini-3.1-flash-lite-preview",
"qwen/qwen3.6-35b-a3b",
"stepfun/step-3.7-flash",
"minimax/minimax-m2.7",
"z-ai/glm-5.1",
"google/gemini-3.5-flash",
# xAI
"x-ai/grok-4.3",
"nvidia/nemotron-3-super-120b-a12b",
# DeepSeek
"deepseek/deepseek-v4-pro",
"deepseek/deepseek-v4-flash",
# Qwen
"qwen/qwen3.7-max",
"qwen/qwen3.6-35b-a3b",
# MoonshotAI
"moonshotai/kimi-k2.6",
# MiniMax
"minimax/minimax-m2.7",
# Z-AI
"z-ai/glm-5.1",
# Xiaomi
"xiaomi/mimo-v2.5-pro",
# Tencent
"tencent/hy3-preview",
# StepFun
"stepfun/step-3.7-flash",
# NVIDIA
"nvidia/nemotron-3-super-120b-a12b",
],
# Native OpenAI Chat Completions (api.openai.com). Used by /model counts and
# provider_model_ids fallback when /v1/models is unavailable.
+3 -4
View File
@@ -215,7 +215,7 @@ TIPS = [
# --- Context & Compression ---
"Context auto-compresses when it reaches the threshold — memories are flushed and history summarized.",
"The status bar turns yellow, then orange, then red as context fills up.",
"SOUL.md at ~/.hermes/SOUL.md is the agent's primary identity — customize it to shape behavior.",
"SOUL.md is the agent's primary identity file — customize it to shape behavior.",
"Hermes loads project context from .hermes.md, AGENTS.md, CLAUDE.md, or .cursorrules (first match).",
"Subdirectory AGENTS.md files are discovered progressively as the agent navigates into folders.",
"Context files are capped at 20,000 characters with smart head/tail truncation.",
@@ -273,7 +273,7 @@ TIPS = [
"Cron scripts live in ~/.hermes/scripts/ and run before the agent — perfect for data collection pipelines.",
"prefill_messages_file in config.yaml injects few-shot examples into every API call, never saved to history.",
"SOUL.md completely replaces the agent's default identity — rewrite it to make Hermes your own.",
"SOUL.md is auto-seeded with a default personality on first run. Edit ~/.hermes/SOUL.md to customize.",
"SOUL.md is auto-seeded with a default personality on first run. Edit it to customize.",
"/compress <focus topic> allocates 60-70% of the summary budget to your topic and aggressively trims the rest.",
"On second+ compression, the compressor updates the previous summary instead of starting from scratch.",
"Before a gateway session reset, Hermes auto-flushes important facts to memory in the background.",
@@ -430,7 +430,7 @@ TIPS = [
'hermes -z "<prompt>" is the purest one-shot: final answer on stdout, nothing else — ideal for piping in scripts.',
'hermes chat --pass-session-id injects the session ID into the system prompt so the agent can self-reference it.',
'hermes chat --image path/to/pic.png attaches a local image to a single -q query without a separate upload step.',
'hermes chat --ignore-user-config skips ~/.hermes/config.yaml — reproducible bug reports and CI runs.',
'hermes chat --ignore-user-config skips the active user config — reproducible bug reports and CI runs.',
"hermes chat --source tool tags programmatic chats so they don't clutter hermes sessions list.",
'hermes dump --show-keys includes redacted API key fingerprints for deeper support debugging.',
'hermes sessions rename <ID> "new title" renames any past session; hermes sessions delete <ID> removes one.',
@@ -485,4 +485,3 @@ def get_random_tip(exclude_recent: int = 0) -> str:
"""
return random.choice(TIPS)