When the Codex CLI falls back from WebSocket to HTTP (after 1008 Policy
Violation or reconnect exhaustion), it POSTs to /v1/responses with the
bare model id it was configured with (e.g. "gpt-5.5") — never the
provider-prefixed form. OmniRoute's normal routing resolved that bare id
to openrouter, not codex, producing:
"No credentials for provider: openrouter"
Fix: add resolveResponsesApiModel() (extending modelResolution.ts) and
call it in /v1/responses before delegating to handleChat. The function
applies the same codex-preference logic as resolveCodexWsModelInfo:
bare "gpt-5.5" → codex/gpt-5.5 has a codex provider → rewrite ✅
bare "gpt-4o" → codex/gpt-4o not in registry → pass through ✅
"anthropic/x" → has "/" → skip resolution → pass through ✅
Errors are caught; original request is returned on any failure.
8 unit tests added (TDD — watched each fail before implementing).
Refs: openai/codex#15492, openai/codex#13041, openai/codex#13039