c136400c9e
Rework of #68509 per triage: hoist the duplicated per-tool _resolve_provider_key helpers into one owner, tools.tool_backend_helpers.resolve_provider_secret(), and migrate every STT/TTS key lookup site to it. Resolution order: explicit config.yaml value > profile secret scope / env / ~/.hermes/.env > credential pool (checks both '<provider>' and 'custom:<provider>' pool keys, so keys added via 'hermes auth add mistral' or declared under providers.<name> both resolve). Under an active multiplex turn the profile scope stays authoritative — no pool or .env fallback that could borrow another profile's key (composes with the #69469 scope fix). Coverage now includes GROQ_API_KEY, MISTRAL_API_KEY, ELEVENLABS_API_KEY, DEEPINFRA_API_KEY, MINIMAX_API_KEY, GEMINI_API_KEY/GOOGLE_API_KEY, the XAI_API_KEY fallback in resolve_xai_http_credentials, and the OpenAI audio key (resolve_openai_audio_api_key now pool-aware for OPENAI_API_KEY via 'hermes auth add openai-api'). Unit tests: fake pool entry proves each provider resolves from the pool when env is empty; env still wins when set; config wins over both; a multiplex scope miss never borrows the pool; pool read failures never raise; tool-level wiring for STT, TTS, xAI, and OpenAI audio. Fixes #68003