diff --git a/agent/model_metadata.py b/agent/model_metadata.py index 821a7ebe0..98a559bfd 100644 --- a/agent/model_metadata.py +++ b/agent/model_metadata.py @@ -319,7 +319,10 @@ DEFAULT_CONTEXT_LENGTHS = { "grok-3": 131072, # grok-3, grok-3-mini, grok-3-fast, grok-3-mini-fast "grok-2": 131072, # grok-2, grok-2-1212, grok-2-latest "grok": 131072, # catch-all (grok-beta, unknown grok-*) - # Kimi + # Kimi — K3 ships with a 1M context window (verified: platform.kimi.ai/docs/overview). + # Longest-key-first substring matching ensures "kimi-k3" resolves to 1M + # while older/unknown Kimi models still hit the generic 256K fallback. + "kimi-k3": 1_000_000, "kimi": 262144, # Upstage Solar — api.upstage.ai/v1/models does not return context_length, # so these fallbacks keep token budgeting / compression from probing down diff --git a/tests/agent/test_model_metadata.py b/tests/agent/test_model_metadata.py index ddd49834d..1789aa559 100644 --- a/tests/agent/test_model_metadata.py +++ b/tests/agent/test_model_metadata.py @@ -332,6 +332,31 @@ class TestDefaultContextLengths: assert get_model_context_length("glm-5") == 202752 assert get_model_context_length("glm-5.1") == 202752 + def test_kimi_k3_context_1m(self): + """Kimi K3 must resolve to 1M, not the generic Kimi fallback of 256K. + + Context window verified against platform.kimi.ai/docs/overview + (2026-07). Kimi K3 is the current flagship model with a 1M-token + context window. + """ + from agent.model_metadata import get_model_context_length + from unittest.mock import patch as mock_patch + + assert DEFAULT_CONTEXT_LENGTHS["kimi-k3"] == 1_000_000 + assert DEFAULT_CONTEXT_LENGTHS["kimi"] == 262144 + + with mock_patch("agent.model_metadata.fetch_model_metadata", return_value={}), \ + mock_patch("agent.model_metadata.fetch_endpoint_model_metadata", return_value={}), \ + mock_patch("agent.model_metadata.get_cached_context_length", return_value=None): + # Kimi K3 (1M) must NOT fall through to the generic 256K entry + assert get_model_context_length("kimi-k3") == 1_000_000 + # Vendor-prefixed forms (kimi provider, openrouter) + assert get_model_context_length("kimi/kimi-k3") == 1_000_000 + assert get_model_context_length("moonshotai/kimi-k3") == 1_000_000 + # Older/unknown Kimi models still resolve to 256K fallback + assert get_model_context_length("kimi-k2.6") == 262144 + assert get_model_context_length("kimi-k2") == 262144 + def test_openrouter_live_metadata_beats_hardcoded_catchall(self): """OpenRouter-routed slugs resolve via the live OR catalog before the hardcoded family catch-all.