Remove obsolete preset API key warning
Stop scanning every global model preset for missing credentials when building Welcome banners. Keep readiness scoped to the effective model configuration so first-send setup remains in the deferred chat gate. Add regression coverage for unused OpenRouter presets and document the boundary.
Alessandro committed
Jul 28, 2026 at 21:28 UTC
4b906561cd19ab6b625c69d814ad550b49afe6f3
3 files changed
+9
-52
plugins/_model_config/AGENTS.md
+1
@@ -19,6 +19,7 @@
19
- Preserve scoped plugin resolution order and fall back invalid or missing scope/chat references to `Default`.
20
- Project Settings `llm` payloads are owned here through the generic `helpers.projects` project extension-data hooks; keep project helper code agnostic to `_model_config` paths, presets, and inheritance rules.
21
- Keep provider metadata and API-key checks safe around secrets.
22
+- Check API-key readiness only for the effective model configuration; unused global presets must not produce Welcome-screen warnings.
23
- Coordinate OAuth-backed providers with `_oauth` instead of hardcoding provider-specific auth here.
24
- `model_config_get` exposes `model_configured` as a derived chat-model readiness flag from provider, model name, and API-key availability.
25
- Non-default presets may inherit omitted slots or durable tuning from `Default`, but must replace or clear per-slot `kwargs` so provider-specific extra params never leak across model providers.
plugins/_model_config/extensions/python/banners/_20_missing_api_key.py
-48
@@ -5,7 +5,6 @@ from plugins._model_config.helpers import model_config
5
class MissingApiKeyCheck(Extension):
6
"""Check if API keys are configured for selected model providers."""
7
8
- LOCAL_PROVIDERS = {"ollama", "lm_studio", "llama_cpp", "omlx", "vllm"}
8
ONBOARDING_MODAL_PATH = "/plugins/_onboarding/webui/onboarding.html"
9
ONBOARDING_CTA_TEXT = "Start Onboarding"
10
@@ -27,50 +26,3 @@ class MissingApiKeyCheck(Extension):
26
# For programmatic clients (e.g. chat composer) reusing this banner pipeline
27
"missing_providers": missing_providers,
28
})
30
-
31
- # Check preset providers for missing API keys (warning level)
32
- preset_missing = []
33
- seen = set()
34
- for preset in model_config.get_presets():
35
- preset_name = preset.get("name", "Unnamed")
36
- for slot_key, slot_label, model_type in [
37
- ("chat", "Main", "chat"),
38
- ("utility", "Utility", "chat"),
39
- ("embedding", "Embedding", "embedding"),
40
- ]:
41
- slot = preset.get(slot_key, {})
42
- provider = slot.get("provider", "")
43
- if not provider:
44
- continue
45
- provider_lower = provider.lower()
46
- identity = (provider_lower, model_type)
47
- if (
48
- provider_lower in self.LOCAL_PROVIDERS
49
- or model_type == "embedding"
50
- and provider_lower in model_config.LOCAL_EMBEDDING
51
- or identity in seen
52
- ):
53
- continue
54
- if slot.get("api_key", "").strip():
55
- continue
56
- if not model_config.has_provider_api_key(
57
- provider_lower,
58
- model_type=model_type,
59
- ):
60
- seen.add(identity)
61
- preset_missing.append(f"{preset_name}/{slot_label} ({provider})")
62
-
63
- if preset_missing:
64
- preset_list = ", ".join(preset_missing)
65
- banners.append({
66
- "id": "missing-preset-api-key",
67
- "type": "warning",
68
- "priority": 90,
69
- "title": "Missing API Key for model presets",
70
- "html": f"""No API key configured for preset models: {preset_list}.<br>
71
- These presets will not work until you provide the required API keys.""",
72
- "cta_text": self.ONBOARDING_CTA_TEXT,
73
- "cta_action": f"open-modal:{self.ONBOARDING_MODAL_PATH}",
74
- "dismissible": True,
75
- "source": "backend"
76
- })
tests/test_model_config_api_keys.py
+8
-4
@@ -90,16 +90,23 @@ def test_chat_model_configured_requires_identity_and_key(monkeypatch):
90
91
92
@pytest.mark.asyncio
93
-async def test_missing_api_key_banner_exposes_missing_providers(monkeypatch):
93
+async def test_missing_api_key_banner_exposes_only_effective_missing_providers(monkeypatch):
94
from plugins._model_config.helpers import model_config
95
96
fake = [{"model_type": "Chat Model", "provider": "openai"}]
97
monkeypatch.setattr(model_config, "get_missing_api_key_providers", lambda: fake)
98
+ monkeypatch.setattr(
99
+ model_config,
100
+ "get_presets",
101
+ lambda: [{"name": "Efficiency", "chat": {"provider": "openrouter"}}],
102
+ )
103
+ monkeypatch.setattr(model_config, "has_provider_api_key", lambda *args, **kwargs: False)
104
105
banners = []
106
await missing_key_banner.MissingApiKeyCheck(agent=None).execute(
107
banners=banners, frontend_context={}
108
)
109
+ assert [banner["id"] for banner in banners] == ["missing-api-key"]
110
row = next(b for b in banners if b.get("id") == "missing-api-key")
111
assert row.get("missing_providers") == fake
112
assert row["cta_text"] == "Start Onboarding"
@@ -515,9 +522,6 @@ def test_provider_key_modes_for_local_and_ollama_cloud():
522
assert model_config.provider_requires_api_key("vllm") is False
523
assert model_config.provider_requires_api_key("other") is False
524
assert model_config.provider_requires_api_key("ollama_cloud") is True
518
- assert "llama_cpp" in missing_key_banner.MissingApiKeyCheck.LOCAL_PROVIDERS
519
- assert "omlx" in missing_key_banner.MissingApiKeyCheck.LOCAL_PROVIDERS
520
- assert "vllm" in missing_key_banner.MissingApiKeyCheck.LOCAL_PROVIDERS
525
526
527
def test_local_provider_defaults_are_docker_friendly():