Skip to content

fix: drop incompatible model slugs on auxiliary client cache hit#5804

Closed
eddieran wants to merge 1 commit into
NousResearch:mainfrom
eddieran:fix/auxiliary-cache-model-compat
Closed

fix: drop incompatible model slugs on auxiliary client cache hit#5804
eddieran wants to merge 1 commit into
NousResearch:mainfrom
eddieran:fix/auxiliary-cache-model-compat

Conversation

@eddieran

@eddieran eddieran commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #5809

_get_cached_client() bypasses the model slug compatibility check in resolve_provider_client() on cache hits, allowing OpenRouter-format model slugs (e.g. google/gemini-3-flash-preview) to reach non-OpenRouter providers.

The bug

resolve_provider_client() has a guard (line ~1097) that drops model slugs containing / when the resolved provider is not OpenRouter:

if model and "/" in model and resolved and "/" not in resolved:
    model = None  # Drop incompatible slug

But _get_cached_client() returns model or cached_default on cache hits (lines 1665/1667) without ever calling resolve_provider_client(), so this guard is skipped.

Example: When provider=openai-codex, the first auxiliary call caches a CodexAuxiliaryClient under key ("auto", ...). A subsequent compression call with model="google/gemini-3-flash-preview" (from config.yaml compression.summary_model) hits the cache and passes the slug to the Codex API, which doesn't understand it.

Fix

Add _compat_model() helper that mirrors the /-check from resolve_provider_client(), called on both sync and async cache-hit return paths. When the cached client is not OpenRouter, model slugs containing / are dropped in favor of the cached default.

Testing

  • 96/96 tests pass in tests/agent/test_auxiliary_client.py
  • 5/5 tests pass in tests/test_crossloop_client_cache.py

`resolve_provider_client()` already drops OpenRouter-format model slugs
(containing "/") when the resolved provider is not OpenRouter (line 1097).
However, `_get_cached_client()` returns `model or cached_default` directly
on cache hits, bypassing this check entirely.

When the main provider is openai-codex, the auto-detection chain (Step 1
of `_resolve_auto`) caches a CodexAuxiliaryClient. Subsequent auxiliary
calls for different tasks (e.g. compression with `summary_model:
google/gemini-3-flash-preview`) hit the cache and pass the OpenRouter-
format model slug straight to the Codex Responses API, which does not
understand it and returns an empty `response.output`.

This causes two user-visible failures:
- "Invalid API response shape" (empty output after 3 retries)
- "Context length exceeded, cannot compress further" (compression itself
  fails through the same path)

Add `_compat_model()` helper that mirrors the "/" check from
`resolve_provider_client()` and call it on the cache-hit return path.
@eddieran eddieran force-pushed the fix/auxiliary-cache-model-compat branch from 17fbec8 to 2700df7 Compare April 7, 2026 10:28

@kshitijk4poor kshitijk4poor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests pass (96/96), reviewed — correctly adds _compat_model() guard on cache-hit paths. Fixes #5809.

@teknium1

Copy link
Copy Markdown
Contributor

Merged via #7647. Your commit was cherry-picked onto current main with your authorship preserved in git log. Thanks @eddieran!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Auxiliary client cache hit bypasses model slug compatibility check

3 participants