From 2a14e8957d7552631b4e33611a828e63f773449a Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Sun, 14 Jun 2026 14:01:03 -0700 Subject: [PATCH] fix(kimi): surface K2.7 Code in native picker (#46309) --- hermes_cli/model_setup_flows.py | 13 +----- hermes_cli/models.py | 10 +++++ .../test_models_dev_preferred_merge.py | 41 +++++++++++++++++++ 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/hermes_cli/model_setup_flows.py b/hermes_cli/model_setup_flows.py index 83e60fc20a2..203f48d739d 100644 --- a/hermes_cli/model_setup_flows.py +++ b/hermes_cli/model_setup_flows.py @@ -1853,18 +1853,7 @@ def _model_flow_kimi(config, current_model=""): print() # Step 3: Model selection — show appropriate models for the endpoint - if is_coding_plan: - # Coding Plan models (kimi-k2.6 first) - model_list = [ - "kimi-k2.6", - "kimi-k2.5", - "kimi-for-coding", - "kimi-k2-thinking", - "kimi-k2-thinking-turbo", - ] - else: - # Legacy Moonshot models (excludes Coding Plan-only models) - model_list = _PROVIDER_MODELS.get("moonshot", []) + model_list = _PROVIDER_MODELS.get("kimi-coding" if is_coding_plan else "moonshot", []) if model_list: selected = _prompt_model_selection( diff --git a/hermes_cli/models.py b/hermes_cli/models.py index ffdc370cb33..becfd96e418 100644 --- a/hermes_cli/models.py +++ b/hermes_cli/models.py @@ -282,6 +282,7 @@ _PROVIDER_MODELS: dict[str, list[str]] = { "openai/gpt-oss-120b", ], "kimi-coding": [ + "kimi-k2.7-code", "kimi-k2.6", "kimi-k2.5", "kimi-for-coding", @@ -2369,6 +2370,15 @@ def provider_model_ids(provider: Optional[str], *, force_refresh: bool = False) if api_key: live = _p.fetch_models(api_key=api_key) if live: + if normalized in {"kimi-coding", "kimi-coding-cn"}: + curated = list(_PROVIDER_MODELS.get(normalized, [])) + merged = list(curated) + merged_lower = {m.lower() for m in curated} + for m in live: + if m.lower() not in merged_lower: + merged.append(m) + merged_lower.add(m.lower()) + return merged return live # Use profile's fallback_models if defined if _p.fallback_models: diff --git a/tests/hermes_cli/test_models_dev_preferred_merge.py b/tests/hermes_cli/test_models_dev_preferred_merge.py index c760f0da39f..a9ffc8fb975 100644 --- a/tests/hermes_cli/test_models_dev_preferred_merge.py +++ b/tests/hermes_cli/test_models_dev_preferred_merge.py @@ -22,6 +22,7 @@ from unittest.mock import patch from hermes_cli.models import ( _MODELS_DEV_PREFERRED, + _PROVIDER_MODELS, _merge_with_models_dev, provider_model_ids, ) @@ -96,6 +97,46 @@ class TestProviderModelIdsPreferred: assert "claude-opus-4-7" in out assert "kimi-k2.6" in out + def test_kimi_coding_offline_catalog_includes_k2_7_code(self): + """Native Kimi users must see the newest Code model without live catalog help.""" + assert "kimi-coding" not in _MODELS_DEV_PREFERRED + with patch("agent.models_dev.list_agentic_models", return_value=[]): + out = provider_model_ids("kimi-coding") + assert "kimi-k2.7-code" in out + + def test_kimi_coding_live_catalog_does_not_hide_curated_k2_7_code(self): + """Kimi /models can lag inference; live results must not replace curated.""" + with ( + patch( + "hermes_cli.auth.resolve_api_key_provider_credentials", + return_value={"api_key": "sk-test", "base_url": "https://api.moonshot.ai/v1"}, + ), + patch("providers.base.ProviderProfile.fetch_models", return_value=["kimi-k2.6"]), + ): + out = provider_model_ids("kimi-coding") + assert out[:2] == ["kimi-k2.7-code", "kimi-k2.6"] + + def test_kimi_setup_flow_uses_same_coding_plan_catalog(self): + """The setup wizard must not carry a stale duplicate Kimi model list.""" + from hermes_cli.model_setup_flows import _model_flow_kimi + + captured = {} + + def fake_select(model_list, **_kwargs): + captured["models"] = model_list + return None + + with ( + patch("hermes_cli.main._prompt_api_key", return_value=("sk-kimi-test", False)), + patch("hermes_cli.auth._prompt_model_selection", side_effect=fake_select), + patch("hermes_cli.config.get_env_value", return_value=""), + patch("hermes_cli.config.save_env_value"), + ): + _model_flow_kimi({}, current_model="") + + assert captured["models"] == _PROVIDER_MODELS["kimi-coding"] + assert captured["models"][0] == "kimi-k2.7-code" + class TestOpenRouterAndNousUnchanged: """Per Teknium: openrouter and nous are NEVER merged with models.dev."""