fix(model): the chat model is deepseek-flash; the hunter reaches DeepSeek

Every model call has failed since 2026-09-10 (83ab533):
- The default detector and judge model was `deepseek-v4.1-flash`, the product name.
  The API rejects it with HTTP 400 ("The supported API model names are
  deepseek-flash, deepseek-v4-pro"). The judge and pipeline record an endpoint
  failure as a degradation, never a verdict, so nothing failed loudly.
- `tool_hunter.resolve_hunter_client` resolved OpenRouter only. In this project
  DeepSeek is the chat provider and the OpenRouter key is scoped to embeddings, so
  the hunter could not reach a chat model at all; the call came back 401.

The defaults are now `deepseek-flash` (priced). The hunter resolves DeepSeek first
when its key is set, and OpenRouter stays as the explicit or fallback route.
Verified live: plain completion and a tool call through both the endpoint resolver
and the hunter client.

Not affected: the independent evaluations (finding_dump runs with
max_model_calls=0) and the 2026-09-06 hunter measurement, which predates the id.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
Marius Ciepluch
2026-09-28 09:01:14 +02:00
co-authored by Claude Opus 5.5
parent 5835239808
commit cf579956d5
3 changed files with 42 additions and 4 deletions
+12 -1
View File
@@ -237,7 +237,12 @@ def scripted_hunter_client(mode: str = "scripted") -> ScriptedChatClient:
def resolve_hunter_client() -> ChatClient | None:
"""Return a hunter client from env, or OpenRouter when an API key is present."""
"""Return a hunter client: scripted when asked, DeepSeek when its key is set, else OpenRouter.
DeepSeek is the chat provider; OpenRouter carries embeddings. This resolved OpenRouter only, so with the
project's keys the hunter could not reach the chat model at all -- every call went to an endpoint whose key
is scoped to embeddings and came back 401.
"""
flag = os.environ.get(CLIENT_ENV, "").strip().lower()
if flag in _SCRIPTED_FLAGS:
return scripted_hunter_client("scripted")
@@ -245,6 +250,12 @@ def resolve_hunter_client() -> ChatClient | None:
return scripted_hunter_client("dump-only")
if flag in _UNSAFE_FLAGS:
return scripted_hunter_client("unsafe-snippet")
if flag not in _OPENROUTER_FLAGS and os.environ.get("DEEPSEEK_API_KEY"):
from .model.endpoint import DEEPSEEK_BASE_ENV, DEEPSEEK_BASE_URL, ChatEndpoint, DeepSeekChatClient
base_url = os.environ.get(DEEPSEEK_BASE_ENV, DEEPSEEK_BASE_URL).rstrip("/")
endpoint = ChatEndpoint(provider="deepseek", base_url=base_url, thinking=False)
return DeepSeekChatClient(OpenRouterChatClient(api_key=os.environ["DEEPSEEK_API_KEY"], base_url=base_url), endpoint=endpoint)
if flag in _OPENROUTER_FLAGS or (not flag and os.environ.get("OPENROUTER_API_KEY")):
try:
return OpenRouterHunterClient.from_env()