Skip to content

fix(llm): only attach prompt-cache points on routes LiteLLM serves - #1186

Merged
0xallam merged 1 commit into
mainfrom
devin/1787930171-llm-cache-route
Aug 28, 2026
Merged

fix(llm): only attach prompt-cache points on routes LiteLLM serves#1186
0xallam merged 1 commit into
mainfrom
devin/1787930171-llm-cache-route

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Summary

cache_control_injection_points is LiteLLM's own request field, consumed by its Anthropic transform — but _prompt_cache_extra_args() attached it to any model name containing "claude", conflating model identity with provider routing. A bare claude-sonnet-4-5 with LLM_API_BASE set (i.e. Claude behind an OpenAI-compatible gateway) is served by the SDK's own OpenAI client, which forwards unknown request kwargs straight into AsyncCompletions.create(), so every turn dies before the first token:

TypeError: AsyncCompletions.create() got an unexpected keyword argument 'cache_control_injection_points'

The gate now asks who actually serves the request, mirroring StrixProvider._resolve_prefixed_model() (bare names and openai//any-llm/ → SDK clients; anything else prefixed → LiteLLM fallback):

-if not is_claude_model(model_name):
+if not is_claude_model(model_name) or not routes_through_litellm(model_name):
     return None
def routes_through_litellm(model_name: str | None) -> bool:
    name = (model_name or "").strip()
    if not name or codex.subscription_model(name):
        return False
    prefix, _, rest = name.partition("/")
    return bool(rest) and prefix.lower() not in {"openai", "any-llm"}

So anthropic/…, litellm/…, vertex_ai/… and the mapped Bedrock routes keep prompt caching unchanged; only the routes that would have crashed lose the field (they never cached anyway — the gateway decides caching there).

tests/test_models.py pins the helper against the provider itself: for each name it builds StrixProvider().get_model(...), unwraps the _NonStreamingModel/_TurnGuardModel wrappers, and asserts isinstance(inner, LitellmModel) is routes_through_litellm(name) — otherwise drift between the two makes every request on a route fail mid-turn, which is exactly the bug above.

Testing

  • uv run pytest tests/test_models.py tests/test_inputs.py → 123 passed. Full suite passes except a pre-existing, unrelated tests/test_pricing.py::test_resolves_common_bare_model_names failure (resolve_litellm_model("MiniMax-M3") is None on main too); 1186 passed with it deselected.
  • ruff check, ruff format --check, mypy, bandit on the changed files: clean.
  • Runtime check against a packaged build with these two files in place, dispatching a real turn at an unreachable base URL: bare claude-sonnet-4-5 and openai/claude-sonnet-4-5 now reach the transport (APIConnectionError) instead of raising the TypeError, while anthropic/…, litellm/anthropic/… and bedrock/… still send the cache points.

Link to Devin session: https://app.devin.ai/sessions/54414ea3ecb34ade9189534e5c690969
Open in Devin Desktop: https://app.devin.ai/desktop/session/54414ea3ecb34ade9189534e5c690969?variant=devin

cache_control_injection_points is LiteLLM's own request field, but it was added
for any model name containing "claude". A bare claude-* name with LLM_API_BASE
set (an OpenAI-compatible gateway in front of Claude) is served by the SDK's
own OpenAI client, which rejects request kwargs it does not know, so every turn
died with:

    TypeError: AsyncCompletions.create() got an unexpected keyword argument
    'cache_control_injection_points'

routes_through_litellm() mirrors StrixProvider's routing, so the field only
goes where it is understood; explicit anthropic//litellm//bedrock routes keep
prompt caching.
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@greptile-apps

greptile-apps Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR prevents LiteLLM-specific prompt-cache arguments from being attached to model requests served by native SDK clients.

  • Adds a shared helper that classifies whether a model name routes through LiteLLM.
  • Uses that classification when constructing prompt-cache request arguments.
  • Adds coverage for native SDK, LiteLLM, Anthropic, Bedrock, Ollama, and compatible gateway routes.

Confidence Score: 5/5

The PR appears safe to merge, with no actionable correctness or security issues identified.

The new gate follows the provider-routing boundary and preserves prompt-cache arguments on LiteLLM-backed Claude routes while removing an unsupported argument from native SDK requests.

Important Files Changed

Filename Overview
strix/config/models.py Adds model-route classification aligned with provider construction, including native SDK and subscription exclusions.
strix/core/inputs.py Restricts LiteLLM prompt-cache injection arguments to requests actually served through LiteLLM.
tests/test_inputs.py Verifies that native SDK Claude routes no longer receive LiteLLM-only cache arguments.
tests/test_models.py Cross-checks the new classification helper against the concrete model type built by StrixProvider.

Reviews (1): Last reviewed commit: "fix(llm): only attach prompt-cache point..." | Re-trigger Greptile

@0xallam
0xallam merged commit 583af23 into main Aug 28, 2026
2 checks passed
alexzerabr pushed a commit to alexzerabr/strix that referenced this pull request Aug 31, 2026
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.

1 participant