Files
2026-07-13 13:12:33 +08:00

282 lines
9.5 KiB
Python

"""Parity proof for the spec-carried ProviderContextProfile extraction.
Every expected value below is a literal transcribed from the pre-extraction
``provider_context_capabilities`` if-ladder (openrouter / anthropic / gemini /
openai_responses / openai branches plus the default). The sweep covers every
registered provider id at its default base URL, the host-guarded cases that
deliberately stayed code (gemini-by-host, openai-by-host, openai-custom-host),
and the OpenRouter per-model-prefix prompt-cache table. Any assertion change
here means the extraction changed behavior and must be reviewed as such.
"""
from __future__ import annotations
import pytest
from opensquilla.provider.context_capabilities import (
NativeCompactionSupport,
PromptCacheSupport,
ProviderContextCapabilities,
provider_context_capabilities,
supports_openrouter_explicit_prompt_cache,
)
from opensquilla.provider.registry import get_provider_spec, list_provider_names
# Neutral model id: matches no OpenRouter prefix and no gemini flash/pro
# marker, so it exercises each branch's fallback shape.
_SWEEP_MODEL = "parity-sweep-model"
def _default_caps(provider: str, model: str = _SWEEP_MODEL) -> ProviderContextCapabilities:
return ProviderContextCapabilities(provider=provider, model=model)
def _anthropic_caps(provider: str, model: str = _SWEEP_MODEL) -> ProviderContextCapabilities:
return ProviderContextCapabilities(
provider=provider,
model=model,
prompt_cache=PromptCacheSupport.EXPLICIT,
native_compaction=NativeCompactionSupport.NONE,
supports_cache_breakpoints=True,
state_portable_across_providers=False,
)
def _gemini_caps(
provider: str,
model: str = _SWEEP_MODEL,
min_cache_tokens: int | None = None,
) -> ProviderContextCapabilities:
return ProviderContextCapabilities(
provider=provider,
model=model,
prompt_cache=PromptCacheSupport.IMPLICIT,
native_compaction=NativeCompactionSupport.NONE,
min_cache_tokens=min_cache_tokens,
state_portable_across_providers=False,
)
def _responses_caps(provider: str, model: str = _SWEEP_MODEL) -> ProviderContextCapabilities:
return ProviderContextCapabilities(
provider=provider,
model=model,
prompt_cache=PromptCacheSupport.AUTOMATIC,
native_compaction=NativeCompactionSupport.STANDALONE,
native_compaction_state_kind="openai_responses_compacted_window",
state_portable_across_providers=False,
)
def _openai_host_caps(provider: str, model: str = _SWEEP_MODEL) -> ProviderContextCapabilities:
return ProviderContextCapabilities(
provider=provider,
model=model,
prompt_cache=PromptCacheSupport.AUTOMATIC,
state_portable_across_providers=False,
)
def _openrouter_caps(model: str, prompt_cache: PromptCacheSupport) -> ProviderContextCapabilities:
return ProviderContextCapabilities(
provider="openrouter",
model=model,
prompt_cache=prompt_cache,
supports_cache_breakpoints=prompt_cache == PromptCacheSupport.EXPLICIT,
state_portable_across_providers=False,
)
# Provider ids whose pre-extraction output differed from the all-defaults
# capability record when called with the spec's default base URL.
_EXPECTED_BY_PROVIDER_ID: dict[str, ProviderContextCapabilities] = {
"anthropic": _anthropic_caps("anthropic"),
"gemini": _gemini_caps("gemini"),
"openai": _openai_host_caps("openai"), # default base URL is api.openai.com
"openai_responses": _responses_caps("openai_responses"),
"openrouter": _openrouter_caps(_SWEEP_MODEL, PromptCacheSupport.IMPLICIT),
}
@pytest.mark.parametrize("provider_id", list_provider_names())
def test_registered_provider_matches_pre_extraction_output(provider_id: str) -> None:
spec = get_provider_spec(provider_id)
caps = provider_context_capabilities(
provider_kind=provider_id,
model=_SWEEP_MODEL,
base_url=spec.default_base_url,
)
expected = _EXPECTED_BY_PROVIDER_ID.get(provider_id, _default_caps(provider_id))
assert caps == expected
_TARGETED_CASES: list[tuple[str, str, str, str, ProviderContextCapabilities]] = [
# OpenRouter model-prefix table (per-model prompt-cache resolution).
(
"openrouter-anthropic-prefix",
"openrouter",
"anthropic/claude-sonnet-4-6",
"https://openrouter.ai/api/v1",
_openrouter_caps("anthropic/claude-sonnet-4-6", PromptCacheSupport.EXPLICIT),
),
(
"openrouter-google-prefix",
"openrouter",
"google/gemini-2.5-pro",
"https://openrouter.ai/api/v1",
_openrouter_caps("google/gemini-2.5-pro", PromptCacheSupport.EXPLICIT),
),
(
"openrouter-deepseek-prefix",
"openrouter",
"deepseek/deepseek-v4-pro",
"https://openrouter.ai/api/v1",
_openrouter_caps("deepseek/deepseek-v4-pro", PromptCacheSupport.EXPLICIT),
),
(
"openrouter-x-ai-prefix",
"openrouter",
"x-ai/grok-4",
"https://openrouter.ai/api/v1",
_openrouter_caps("x-ai/grok-4", PromptCacheSupport.EXPLICIT),
),
(
"openrouter-z-ai-prefix",
"openrouter",
"z-ai/glm-5.1",
"https://openrouter.ai/api/v1",
_openrouter_caps("z-ai/glm-5.1", PromptCacheSupport.IMPLICIT),
),
(
"openrouter-unmatched-prefix",
"openrouter",
"qwen/qwen3-max",
"https://openrouter.ai/api/v1",
_openrouter_caps("qwen/qwen3-max", PromptCacheSupport.IMPLICIT),
),
# Whitespace/case normalization flows through the new lookup path.
(
"openrouter-normalized-input",
" OpenRouter ",
"Anthropic/Claude-Sonnet-4-6",
"",
_openrouter_caps("Anthropic/Claude-Sonnet-4-6", PromptCacheSupport.EXPLICIT),
),
# Anthropic is provider-keyed: a custom base URL keeps the profile.
(
"anthropic-custom-host",
"anthropic",
"claude-opus-4-6",
"https://anthropic-proxy.example.com",
_anthropic_caps("anthropic", "claude-opus-4-6"),
),
# Gemini by provider kind: flash/pro minimum cache-token ladder.
(
"gemini-flash-min-tokens",
"gemini",
"gemini-2.5-flash",
"https://generativelanguage.googleapis.com/v1beta/openai",
_gemini_caps("gemini", "gemini-2.5-flash", min_cache_tokens=1024),
),
(
"gemini-pro-min-tokens",
"gemini",
"gemini-2.5-pro",
"https://generativelanguage.googleapis.com/v1beta/openai",
_gemini_caps("gemini", "gemini-2.5-pro", min_cache_tokens=4096),
),
(
"gemini-kind-custom-host",
"gemini",
"gemini-2.5-flash",
"https://gemini-proxy.example.com/v1",
_gemini_caps("gemini", "gemini-2.5-flash", min_cache_tokens=1024),
),
# Gemini by host: a non-gemini kind pointed at generativelanguage still
# resolves the gemini cache behavior (host guard stayed code).
(
"gemini-by-host-openai-kind",
"openai",
"gemini-2.5-flash",
"https://generativelanguage.googleapis.com/v1beta/openai",
_gemini_caps("openai", "gemini-2.5-flash", min_cache_tokens=1024),
),
(
"gemini-by-host-azure-kind",
"azure",
"gemini-2.5-pro",
"https://generativelanguage.googleapis.com/v1beta/openai",
_gemini_caps("azure", "gemini-2.5-pro", min_cache_tokens=4096),
),
# OpenAI host guard: automatic caching only on the official host.
(
"openai-by-host",
"openai",
"gpt-5.4",
"https://api.openai.com/v1",
_openai_host_caps("openai", "gpt-5.4"),
),
(
"openai-custom-host",
"openai",
"gpt-5.4",
"https://openai-compat.example.com/v1",
_default_caps("openai", "gpt-5.4"),
),
(
"openai-empty-base-url",
"openai",
"gpt-5.4",
"",
_default_caps("openai", "gpt-5.4"),
),
# openai_responses is provider-keyed: no host requirement.
(
"openai-responses-no-base-url",
"openai_responses",
"gpt-5.5",
"",
_responses_caps("openai_responses", "gpt-5.5"),
),
# Anthropic-shaped MiniMax kinds never had the anthropic cache profile.
(
"minimax-kind-stays-default",
"minimax",
"minimax-m2.5",
"https://api.minimaxi.com/anthropic",
_default_caps("minimax", "minimax-m2.5"),
),
# Unregistered kinds fall through to the all-defaults record.
(
"unknown-kind",
"totally-unknown-kind",
_SWEEP_MODEL,
"https://example.com/v1",
_default_caps("totally-unknown-kind"),
),
]
@pytest.mark.parametrize(
("provider_kind", "model", "base_url", "expected"),
[case[1:] for case in _TARGETED_CASES],
ids=[case[0] for case in _TARGETED_CASES],
)
def test_host_guard_and_prefix_cases_match_pre_extraction_output(
provider_kind: str,
model: str,
base_url: str,
expected: ProviderContextCapabilities,
) -> None:
caps = provider_context_capabilities(
provider_kind=provider_kind, model=model, base_url=base_url
)
assert caps == expected
def test_openrouter_explicit_prompt_cache_wrapper_unchanged() -> None:
assert supports_openrouter_explicit_prompt_cache("anthropic/claude-sonnet-4-6") is True
assert supports_openrouter_explicit_prompt_cache("x-ai/grok-4") is True
assert supports_openrouter_explicit_prompt_cache("z-ai/glm-5.1") is False
assert supports_openrouter_explicit_prompt_cache("qwen/qwen3-max") is False