hermes-agent/hermes_cli
homelab-ha-agent a5ea9a6fd4 fix(model): don't misroute named custom providers to openrouter on save
_normalize_main_model_assignment() (POST /api/model/set, the endpoint
Desktop's Settings -> Model page uses to persist the main model slot) has
a fallback for a specific analytics bug: an older session row with no
billing_provider sends the model's bare vendor prefix as "provider"
(e.g. "anthropic" from "anthropic/claude-opus-4.6"), so the code detects
an unrecognized provider paired with a slash-bearing model and treats it
as that stray-vendor-prefix case.

Named custom providers are represented as "custom:<name>" slugs
everywhere else in the codebase (runtime_provider.py, model_switch.py),
but _KNOWN_PROVIDER_NAMES only lists the bare "custom" bucket. So picking
a named custom provider (e.g. "custom:litellm", a LiteLLM proxy fronting
Ollama) together with a slash-bearing model ("ollama/glm-5.2") looked
identical to the stray-vendor-prefix case and got silently rewritten to
provider: openrouter in config.yaml on save -- reassigning the provider
entirely, not just mangling the model id.

Exclude anything starting with "custom" from the fallback, matching the
guard the same function already applies later for the actual
normalize_model_for_provider call.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 19:32:12 +05:30
..
dashboard_auth fix(dashboard): add lightweight /api/health liveness endpoint 2026-07-24 19:43:44 -05:00
proxy rip out brew + pip/PyPI wheel support (#68217) 2026-07-22 16:51:01 -04:00
subcommands feat(approvals): hermes approvals suggest — mine approval history into allowlist proposals 2026-07-26 17:49:03 -07:00
__init__.py chore: release v0.19.0 (2026.7.20) (#68175) 2026-07-20 11:35:21 -07:00
_early_recovery.py fix(ssl): detect and repair a missing certifi cacert.pem via existing venv-repair infra 2026-07-24 15:53:38 -07:00
_parser.py feat: raise default tool-calling iteration limit from 90 to 500 2026-07-26 12:54:45 -07:00
_subprocess_compat.py fix(windows): suppress console window flashes in env probes, lazy installs, and platform.win32_ver() 2026-07-23 18:20:24 -07:00
active_sessions.py fix(tui): preserve live session identity across compression (#49041) 2026-06-24 00:54:18 +05:30
agent_import.py feat(cli): hermes import-agent — import Claude Code and Codex CLI setups 2026-07-26 17:47:07 -07:00
approval_mode.py feat(approvals): add cross-surface mode command 2026-07-26 21:13:03 -07:00
approvals_suggest.py feat(approvals): hermes approvals suggest — mine approval history into allowlist proposals 2026-07-26 17:49:03 -07:00
auth.py fix(models): match bare Kimi Coding k3 when searching kimi 2026-07-26 21:22:40 -07:00
auth_commands.py fix(auth): make xAI OAuth pools multi-account resilient 2026-07-17 11:37:25 +05:30
azure_detect.py fix(security): secure Azure catalog probes 2026-07-11 12:28:55 +05:30
backup.py fix(state): stop cancelling our own POSIX locks on live SQLite databases 2026-07-25 21:44:43 -07:00
banner.py fix(cli): add explicit encoding to read_text/write_text calls 2026-07-24 17:10:39 -07:00
blueprint_cmd.py refactor(cron): rebrand Cron Recipes -> Automation Blueprints 2026-06-11 10:49:47 -07:00
browser_connect.py fix: /browser connect times out when another app squats the CDP port 2026-07-18 02:49:28 -07:00
build_info.py
bundles.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
callbacks.py feat(clarify): add multi-select (checkbox) support to clarify tool 2026-07-26 17:46:55 -07:00
checkpoints.py fix(checkpoints): bind an empty orphan preview to an empty deletion allowlist 2026-07-24 16:01:06 -07:00
claw.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
cli_agent_setup_mixin.py fix(timeline): persist typed display events (#69771) 2026-07-23 14:46:24 -04:00
cli_billing_mixin.py feat(cli): plan catalog on Free + plan= deep link + top-up/auto-refill copy split (#68689) 2026-07-22 08:11:09 +05:30
cli_commands_mixin.py feat(approvals): add cross-surface mode command 2026-07-26 21:13:03 -07:00
cli_output.py
clipboard.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
codex_models.py fix(codex): send ChatGPT-Account-Id on /models probes 2026-07-21 05:27:13 -07:00
codex_runtime_plugin_migration.py
codex_runtime_switch.py refactor(codex-runtime): tidy reapply-migration control flow 2026-07-01 23:51:54 +05:30
colors.py
commands.py feat(approvals): add cross-surface mode command 2026-07-26 21:13:03 -07:00
completion.py fix: batch of small robustness/correctness fixes from @kyssta-exe 2026-06-01 19:51:03 -07:00
config.py refactor(guardrails): make runaway-loop caps per-turn, not session-total 2026-07-26 21:27:45 -07:00
console_engine.py rip out brew + pip/PyPI wheel support (#68217) 2026-07-22 16:51:01 -04:00
container_boot.py fix: add encoding="utf-8" to Path.write_text() calls (P1) 2026-07-24 17:10:39 -07:00
context_switch_guard.py fix(cli): honor custom_providers in preflight shrink warning 2026-07-22 21:17:21 -07:00
copilot_auth.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
credential_lifecycle.py fix(credentials): unified provider key delete/update across .env, auth.json, config.yaml (#67213) 2026-07-19 03:02:21 -07:00
cron.py fix(cron): preserve jobs.json ownership on root rewrite + surface failing-tick reason 2026-07-24 15:52:13 -07:00
curator.py fix(curator): make the autonomous write policy consistent (#67140) 2026-07-25 19:27:17 -07:00
curses_ui.py fix(models): match bare Kimi Coding k3 when searching kimi 2026-07-26 21:22:40 -07:00
dashboard_register.py fix(cli): correct stale hermes auth login nous hints to hermes auth add nous (#53929) 2026-06-27 21:30:37 -07:00
debug.py fix: remove dead f-string prefixes via ruff F541 (216 sites) (#52336) 2026-07-05 13:42:46 -07:00
default_soul.py fix(soul): installers seed the real default persona, upgrade legacy empty templates (#52246) 2026-06-24 18:56:26 -07:00
dep_ensure.py fix(security): centralize credential-safe subprocess env (#29157) 2026-06-27 20:45:31 -07:00
diagnostics_upload.py feat(debug): drop dead confirm step from --nous upload (stateless NAS) 2026-06-30 17:29:23 -07:00
dingtalk_auth.py refactor(setup): route dependency installs through the canonical uv→pip→ensurepip ladder 2026-07-07 04:09:35 -07:00
doctor.py fix(docker): ship a WAL-reset-safe SQLite runtime 2026-07-26 17:20:31 -07:00
dump.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
env_loader.py fix(config): preserve opaque .env values 2026-07-24 16:02:08 -07:00
fallback_cmd.py refactor(fallback): single owner for backend identity and failure-scoped skips 2026-07-26 23:41:54 -07:00
fallback_config.py fix(auth): honor per-entry key_env when resolving fallback providers 2026-07-16 07:19:36 -07:00
focus_view.py feat(cli): /focus — reduced-output view with hidden-line recovery and status indicator 2026-07-26 18:10:34 -07:00
gateway.py fix(setup): stop asking about self-configuring platform knobs 2026-07-26 08:43:24 -07:00
gateway_enroll.py feat(gateway): generic OIDC client-credentials relay provisioning (NAS-free) (#60730) 2026-07-08 16:55:32 +10:00
gateway_windows.py fix(update): migrate legacy pythonw Windows gateway launchers to the hidden-console design 2026-07-26 17:50:54 -07:00
goals.py fix(goals): auto-pause goal loop on consecutive transport failures 2026-07-20 05:38:25 -07:00
gui_uninstall.py feat: uninstall the Chat GUI without removing the agent (CLI + desktop UI) (#40355) 2026-06-06 18:22:38 -07:00
hooks.py feat(delegate): expose redacted child tool history 2026-07-26 20:36:47 -07:00
init_command.py feat(cli): /init — generate or update AGENTS.md from a project scan 2026-07-26 17:46:29 -07:00
input_sanitize.py fix(input): strip bracketed-paste leaks before prompt persistence (#62557) 2026-07-15 07:39:42 -07:00
inventory.py refactor(cli): route every aux picker through one provider-inventory seam 2026-07-25 22:47:12 -07:00
journey.py fix(cli): render /journey color instead of leaking raw ANSI 2026-07-01 16:25:48 -05:00
kanban.py fix(kanban): cover remaining add_notify_sub call sites for chat_type (#56580) 2026-07-26 13:42:33 -07:00
kanban_db.py fix(kanban): strip stale session routing from dispatched worker env 2026-07-26 16:27:52 -07:00
kanban_decompose.py fix(auxiliary): route direct-create aux callers through call_llm (#65029) 2026-07-15 07:39:17 -07:00
kanban_diagnostics.py fix(kanban): clear failure/crash diagnostics while a retry is in flight 2026-07-09 16:13:59 -05:00
kanban_specify.py fix(auxiliary): route direct-create aux callers through call_llm (#65029) 2026-07-15 07:39:17 -07:00
kanban_swarm.py refactor(kanban): fold worker/orchestrator skills into injected guidance (#50473) 2026-06-21 17:06:48 -07:00
logs.py fix: remove dead f-string prefixes via ruff F541 (216 sites) (#52336) 2026-07-05 13:42:46 -07:00
main.py fix(cli): scope -c/--resume to the current workspace 2026-07-27 01:26:34 -05:00
managed_scope.py fix(managed-scope): honor managed scope in all standalone config loaders 2026-06-19 07:46:33 -07:00
managed_uv.py fix(update): refresh stale managed-uv catalog so SQLite runtime repair can succeed 2026-07-26 17:20:27 -07:00
mcp_catalog.py feat(mcp): enforce exact version pins across the whole MCP catalog 2026-07-15 04:56:25 -07:00
mcp_config.py feat(mcp): fnmatch glob support in tools.include/exclude filters 2026-07-26 08:26:09 -07:00
mcp_picker.py
mcp_security.py fix(security): close hermes-0day MCP-persistence attack surface 2026-06-21 19:05:27 -07:00
mcp_startup.py fix(mcp): propagate profile HERMES_HOME override into shared discovery owner; restore stdio startup + WSTransport tests 2026-07-26 14:14:03 -07:00
memory_oauth.py feat(memory): Honcho OAuth connect — desktop and CLI flows + token refresh (#44335) 2026-06-22 19:16:47 -05:00
memory_setup.py fix(update): refresh active memory provider deps after venv rebuild 2026-07-26 19:29:18 -07:00
middleware.py fix(middleware): single-use next_call guard + deepcopy-safe request copies 2026-06-06 23:07:25 +05:30
migrate.py
moa_cmd.py feat(moa): add reference model toggles 2026-07-23 18:11:57 -07:00
moa_config.py feat(moa): default advisor fanout to user_turn — the cheapest cadence 2026-07-23 21:07:18 -07:00
model_catalog.py feat(models): catalog-labeled silent default — GLM-5.2 marked "default": true in the model catalog 2026-07-15 00:10:31 -07:00
model_cost_guard.py fix(model): require confirmation for expensive model selections 2026-06-10 00:24:06 -07:00
model_normalize.py fix(model): don't strip alias-derived prefixes for the custom provider bucket 2026-07-27 19:32:12 +05:30
model_search.py fix(picker): fold live bare k3 wire id into curated kimi-k3 row 2026-07-26 21:22:40 -07:00
model_setup_flows.py fix(cli): store custom endpoint API key in .env instead of config.yaml 2026-07-24 21:12:53 -05:00
model_switch.py fix(model): track explicit models: declarations in section 3 so a singular default_model doesn't suppress live discovery 2026-07-26 17:17:03 -07:00
models.py fix(picker): fold live bare k3 wire id into curated kimi-k3 row 2026-07-26 21:22:40 -07:00
nous_account.py feat(billing): /credits command — balance + portal top-up handoff (#44776) 2026-06-12 08:51:10 +00:00
nous_auth_keepalive.py fix Nous auth refresh for idle agents 2026-06-21 22:43:48 -07:00
nous_billing.py fix(billing): rename user-facing "terminal billing" copy to Remote Spending (#68355) 2026-07-21 12:20:25 +05:30
nous_subscription.py fix(browser): validate agent-browser is runnable, not just present (#51740) 2026-06-24 00:14:49 -07:00
onepassword_secrets_cli.py fix: extend UTF-8 encoding to _op_version probe (#53428) 2026-07-24 11:45:57 -07:00
oneshot.py feat(clarify): add multi-select (checkbox) support to clarify tool 2026-07-26 17:46:55 -07:00
pairing.py
partial_compress.py feat(commands): /compact alias + --preview/--dry-run flags for /compress (#3243 salvage) 2026-07-02 05:10:31 -07:00
pets.py feat(pets): generation RPCs, non-blocking gallery + gateway plumbing 2026-06-24 13:48:38 -05:00
platforms.py
plugins.py fix subagent lifecycle ownership invariants 2026-07-26 23:27:30 -07:00
plugins_cmd.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
portal_cli.py fix: remove dead f-string prefixes via ruff F541 (216 sites) (#52336) 2026-07-05 13:42:46 -07:00
profile_describer.py fix(auxiliary): route direct-create aux callers through call_llm (#65029) 2026-07-15 07:39:17 -07:00
profile_distribution.py revert(windows): roll back terminal-popup PRs #53791 #53810 #53829 (#53853) 2026-06-27 15:59:00 -07:00
profiles.py fix: add encoding="utf-8" to Path.write_text() calls (P1) 2026-07-24 17:10:39 -07:00
projects_cmd.py feat(projects): add per-profile project store 2026-06-25 16:40:26 -05:00
projects_db.py feat(desktop): configure repository discovery (supersedes #67630) (#68642) 2026-07-21 10:09:31 -04:00
prompt_size.py fix(prompt-size): include names-only skills in breakdown 2026-07-26 18:06:21 -07:00
provider_catalog.py feat(moa): expose MoA presets as selectable virtual models (#46081) 2026-06-25 13:52:06 -07:00
providers.py fix(vertex,moa): register vertex in PROVIDER_REGISTRY and HERMES_OVERLAYS 2026-07-23 16:55:41 -07:00
proxy_cli.py Reapply "Merge pull request #30179 from NousResearch/feat/iron-proxy" 2026-07-24 09:49:00 -07:00
psutil_android.py
pt_input_extras.py fix(cli): ignore terminal focus reports (salvage of #16780) 2026-05-29 00:31:44 -07:00
pty_bridge.py fix(pty-bridge): mark os.killpg/getpgid windows-footgun-ok (POSIX-only module) 2026-06-08 07:03:12 -07:00
pty_session.py feat(pty): periodic reaper wired into dashboard lifespan 2026-07-07 15:15:37 -07:00
relaunch.py revert(windows): roll back terminal-popup PRs #53791 #53810 #53829 (#53853) 2026-06-27 15:59:00 -07:00
route_identity.py fix: restore base_url rstrip, extract should_clear_context_pin helper 2026-07-22 11:19:37 +05:30
runtime_provider.py fix(tui_gateway): recover custom provider identity from the session's model name 2026-07-24 10:47:32 -07:00
secret_prompt.py feat(memory): improve OpenViking setup UX 2026-06-17 01:04:26 +08:00
secrets_cli.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
security_advisories.py fix(stt,tts): restore mistralai — 2.4.8 is clean, ban lifted (#34841) 2026-05-29 13:24:12 -07:00
security_audit.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
security_audit_startup.py style(security-audit): add explicit encoding to read_text calls (ruff PLW1514) 2026-06-21 19:05:27 -07:00
send_cmd.py fix(managed-scope): honor managed scope in config→env bridges too 2026-06-19 07:46:33 -07:00
service_manager.py fix(hermes_cli): drop privileges before clearing s6-log lock 2026-07-27 19:19:01 +05:30
session_export.py feat: add prompt-only session export 2026-07-07 13:29:58 -07:00
session_export_html.py fix(session-export): escape html tool call names 2026-07-09 19:54:02 -07:00
session_export_md.py feat(sessions): full prune-filter set + --redact on sessions export 2026-07-07 12:36:41 -07:00
session_filters.py fix(sessions): preserve recently active sessions during pruning 2026-07-26 19:30:21 -07:00
session_listing.py feat(gateway): add /sessions search <query> (#57685) 2026-07-03 13:44:00 -07:00
session_recap.py fix(cli): sanitize terminal escapes when replaying stored history (/resume recap, /status recap) 2026-07-17 04:53:38 -07:00
session_recovery.py fix(sessions): verify fully reconstructed recovery 2026-07-26 23:34:29 -07:00
setup.py fix(windows): sweep remaining unguarded text-mode subprocess sites codebase-wide 2026-07-24 11:45:57 -07:00
setup_hidden_env.py fix(setup): stop asking about self-configuring platform knobs 2026-07-26 08:43:24 -07:00
setup_whatsapp_cloud.py fix(whatsapp-cloud): review follow-ups for #43921 2026-06-11 07:51:01 -07:00
skills_config.py fix(cli): normalize malformed skills config in get_disabled_skills (#61797) 2026-07-09 19:57:54 -07:00
skills_hub.py fix(skills): never change a skill's source registry on update 2026-07-26 19:29:56 -07:00
skin_cmd.py feat(themes): hermes skin set — deterministic one-color tweak, bg untouched 2026-07-21 21:00:43 -05:00
skin_engine.py feat(themes): dedicated code-syntax palette keys 2026-07-21 21:00:43 -05:00
slack_cli.py feat(slack): support long app descriptions in the manifest generator 2026-07-23 12:01:24 -07:00
sqlite_runtime.py fix(runtime): repair vulnerable managed SQLite builds (E-949) 2026-07-24 16:00:03 -07:00
sqlite_safe_read.py fix(sessions): close the snapshot check/use race and guard damaged state_meta 2026-07-25 23:05:30 -07:00
sqlite_util.py feat(projects): add per-profile project store 2026-06-25 16:40:26 -05:00
status.py fix(cron): accept UTF-8 BOM when reading jobs.json 2026-07-18 02:31:20 -07:00
stdio.py chore: prune unused imports and duplicate import redefinitions 2026-05-28 22:26:25 -07:00
suggestions_cmd.py fix: remove dead f-string prefixes via ruff F541 (216 sites) (#52336) 2026-07-05 13:42:46 -07:00
telegram_managed_bot.py Add CLI Telegram QR onboarding 2026-06-05 03:20:10 -07:00
timeouts.py
tips.py feat: raise default tool-calling iteration limit from 90 to 500 2026-07-26 12:54:45 -07:00
tools_config.py fix(install): clear stale Windows cua lock 2026-07-26 16:01:54 -07:00
toolset_validation.py fix(config): surface invalid platform_toolsets instead of silently dropping tools (#38798) 2026-06-26 14:07:43 +05:30
uninstall.py fix: add encoding="utf-8" to Path.write_text() calls (P1) 2026-07-24 17:10:39 -07:00
urllib_security.py fix(security): order sanitizer after installed hooks 2026-07-11 12:28:55 +05:30
voice.py
web_git.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
web_server.py fix(model): don't misroute named custom providers to openrouter on save 2026-07-27 19:32:12 +05:30
webhook.py fix: repair sweep fallout — duplicate encoding kwargs, non-subprocess call sites, kwarg-snapshot tests 2026-07-24 11:45:57 -07:00
win_pty_bridge.py feat(windows): enable dashboard /chat tab via ConPTY (win_pty_bridge) + tests (#42251) 2026-06-08 11:32:43 -07:00
windows_ssh_runtime.py fix(windows): sweep remaining unguarded text-mode subprocess sites codebase-wide 2026-07-24 11:45:57 -07:00
write_approval_commands.py refactor(memory,skills): replace tri-state write_mode with boolean write_approval (default off) (#43354) 2026-06-09 23:21:14 -07:00
xai_retirement.py fix(config): guard xai migration writer + drop gratuitous annotation 2026-07-05 23:00:34 +05:30