When typing /model deepseek-chat while on a different provider, the
model name now auto-resolves to the correct provider instead of
silently staying on the wrong one and causing API errors.
Detection priority:
1. Direct provider with credentials (e.g. DEEPSEEK_API_KEY set)
2. OpenRouter catalog match with proper slug remapping
3. Direct provider without creds (clear error beats silent failure)
Also adds DeepSeek as a first-class API-key provider — just set
DEEPSEEK_API_KEY and /model deepseek-chat routes directly.
Bare model names get remapped to proper OpenRouter slugs:
/model gpt-5.4 → openai/gpt-5.4
/model claude-opus-4.6 → anthropic/claude-opus-4.6
Salvages the concept from PR #1177 by @virtaava with credential
awareness and OpenRouter slug mapping added.
Co-authored-by: virtaava <virtaava@users.noreply.github.com>
Extend subprocess env sanitization beyond provider credentials by blocking Hermes-managed tool, messaging, and related gateway runtime vars. Reuse a shared sanitizer in LocalEnvironment and ProcessRegistry so background and PTY processes honor the same blocklist and _HERMES_FORCE_ escape hatch. Add regression coverage for local env execution and process_registry spawning.
The fake_popen mock used iter([]) for proc.stdout which doesn't
support .close(). Use MagicMock with __iter__ instead, since
_drain_stdout now calls proc.stdout.close() in its finally block.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Terminal subprocesses inherit OPENAI_BASE_URL and other provider env
vars loaded from ~/.hermes/.env, silently misrouting external CLIs
like codex. Build a blocklist dynamically from the provider registry
so new providers are automatically covered. Callers that truly need
a blocked var can opt in via the _HERMES_FORCE_ prefix.
Closes#1002
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>