main
py 247 lines 10.6 KB
Raw
1 from pathlib import Path
2
3 import yaml
4
5 PROJECT_ROOT = Path(__file__).resolve().parents[1]
6
7
8 def test_onboarding_contains_unified_provider_step():
9 html = (PROJECT_ROOT / "plugins/_onboarding/webui/onboarding.html").read_text(encoding="utf-8")
10 store = (PROJECT_ROOT / "plugins/_onboarding/webui/onboarding-store.js").read_text(encoding="utf-8")
11 gate_store = (PROJECT_ROOT / "webui/components/chat/model-gate-store.js").read_text(encoding="utf-8")
12
13 assert "Cloud" in html
14 assert "Local" in html
15 assert "Welcome to Agent Zero" in html
16 assert "Choose your AI provider" in store
17
18 # The illustrated Cloud/Local path screen is gone: one merged provider step.
19 assert "Choose how to use AI models in Agent Zero" not in html + store
20 assert "path-card" not in html
21 assert "cloud-card.webp" not in html
22 assert "local-card.webp" not in html
23 assert not (PROJECT_ROOT / "plugins/_onboarding/webui/assets/cloud-card.webp").exists()
24 assert not (PROJECT_ROOT / "plugins/_onboarding/webui/assets/local-card.webp").exists()
25 assert "choosePath" not in html + store + gate_store
26 assert "isStep('connect')" in html
27 assert "isStep('path')" not in html
28 assert "isStep('cloud')" not in html
29 assert "isStep('local')" not in html
30
31 # Cloud/Account/Local segmented switch on the merged step.
32 assert "mode-switch" in html
33 assert "setProviderMode('cloud')" in html
34 assert "setProviderMode('account')" in html
35 assert "setProviderMode('local')" in html
36 assert "providerMode === 'cloud'" in html
37 assert "providerMode === 'account'" in html
38 assert "providerMode === 'local'" in html
39 assert html.index("setProviderMode('cloud')") < html.index("setProviderMode('account')") < html.index("setProviderMode('local')")
40 assert '{ step: "connect", label: "Choose provider" }' in store
41
42 # Cloud pane lists every provider directly and only mentions API keys;
43 # accounts live in their own pane.
44 assert "Connect with an API key" in html
45 assert "cloudProviders()" in html
46 assert "Click here if you don't see your provider" not in html
47 assert "moreCloudOpen" not in html + store
48 assert "API key or account connection" not in html
49
50 # The chat model gate presets the mode before the modal opens (no flash).
51 assert "presetMode" in store
52 assert "onboardingStore.presetMode = this.choice;" in gate_store
53 assert "applyOnboardingChoice" not in gate_store
54
55 assert "oauthProviderCards()" in html + store
56 assert "selectOAuthProvider(provider.provider_id)" in html
57 assert "Connect one or more account-backed providers." not in html
58 assert "Connect ChatGPT/Codex Account" not in html
59 assert "Main model" in html
60 assert "Refresh model list" in html
61 assert "Search or enter Utility Model" in html
62
63 # The utility model is an intentional choice: no "same as main" shortcut.
64 assert "Use same as Main Model" not in html
65 assert "sameAsMain" not in html + store
66 assert "Advanced Settings" in html
67 assert "selectedProviderName() + ' Docs'" in html
68 assert "openSelectedProviderDocs" in html + store
69 assert "Connect account" in html + store
70 assert "oauthAccountActionLabel" in html + store
71 assert "connectOAuth" in html + store
72 assert "submitOAuthManualCallback" in html + store
73 assert 'const OAUTH_START_API = "/plugins/_oauth/start_login";' in store
74 assert "/plugins/_oauth/start_device_login" not in store
75 assert "provider-description" not in html
76 assert "main-model-field" in html
77 assert "wide-inline-field" in html
78 assert "utility-panel" in html
79 assert "showApiBaseField()" in html + store
80 assert "localGuidance()" in html + store
81
82
83 def test_onboarding_closes_before_opening_advanced_model_settings():
84 store = (PROJECT_ROOT / "plugins/_onboarding/webui/onboarding-store.js").read_text(
85 encoding="utf-8"
86 )
87 method = store.split(" async openAdvancedSettings() {", 1)[1].split("\n },", 1)[0]
88
89 close_call = "await window.closeModal?.();"
90 open_call = "await modelConfigStore.openPresetEditor("
91
92 assert close_call in method
93 assert open_call in method
94 assert method.index(close_call) < method.index(open_call)
95
96
97 def test_onboarding_provider_grid_names_are_present_in_metadata():
98 provider_yaml = (PROJECT_ROOT / "conf/model_providers.yaml").read_text(encoding="utf-8")
99 provider_ui = (PROJECT_ROOT / "plugins/_onboarding/webui/onboarding-providers.js").read_text(encoding="utf-8")
100 model_metadata = (PROJECT_ROOT / "plugins/_model_config/provider_metadata.yaml").read_text(encoding="utf-8")
101
102 assert "TOP_CLOUD_PROVIDER_IDS" in provider_ui
103 assert '"venice"' in provider_ui
104 assert '"xai"' in provider_ui
105 assert '"nebius"' in provider_ui
106 assert provider_ui.index('"venice"') < provider_ui.index('"zai"')
107 assert provider_ui.index('"xai"') > provider_ui.index("MORE_CLOUD_PROVIDER_IDS")
108 assert 'name: "Google"' in provider_ui
109 assert 'docs_url: "https://openrouter.ai/workspaces/default/keys"' in provider_ui
110 assert 'docs_url: "https://ai.google.dev/gemini-api/docs/api-key"' in provider_ui
111 assert 'docs_url: "https://docs.venice.ai/guides/getting-started/generating-api-key"' in provider_ui
112 assert 'docs_url: "https://docs.tokenfactory.nebius.com/api-reference/introduction"' in provider_ui
113 assert 'docs_url: "https://lmstudio.ai/docs/developer/core/authentication"' in provider_ui
114 assert 'logo: "/plugins/_onboarding/webui/assets/provider-logos/llama-cpp.svg"' in provider_ui
115 assert 'docs_url: "https://github.com/ggml-org/llama.cpp/blob/master/tools/server/README.md"' in provider_ui
116 assert 'default_api_base: "http://host.docker.internal:8080/v1"' in provider_ui
117 assert 'logo: "/plugins/_onboarding/webui/assets/provider-logos/omlx.svg"' in provider_ui
118 assert 'docs_url: "https://github.com/jundot/omlx#readme"' in provider_ui
119 assert 'default_api_base: "http://host.docker.internal:8000/v1"' in provider_ui
120 assert 'logo: "/plugins/_onboarding/webui/assets/provider-logos/vllm.svg"' in provider_ui
121 assert 'docs_url: "https://docs.vllm.ai/en/stable/serving/online_serving/"' in provider_ui
122 assert 'logo: "/plugins/_onboarding/webui/assets/provider-logos/cerebras.svg"' in provider_ui
123 assert 'docs_url: "https://inference-docs.cerebras.ai/quickstart"' in provider_ui
124 assert 'default_chat_model: "gpt-oss-120b"' in provider_ui
125 assert 'docs_url: ""' in provider_ui
126 assert "api_key_mode: none" in model_metadata
127 assert "api_key_mode: optional" in model_metadata
128 assert "Ollama Cloud" in provider_yaml
129 assert "https://ollama.com/v1" in provider_yaml
130 assert "llama.cpp" in provider_yaml
131 assert "http://host.docker.internal:8080/v1" in provider_yaml
132 assert "oMLX" in provider_yaml
133 assert "http://host.docker.internal:8000/v1" in provider_yaml
134 assert "vLLM" in provider_yaml
135 assert "Nebius Token Factory" in provider_yaml
136 assert "https://api.tokenfactory.nebius.com/v1" in provider_yaml
137 assert not (PROJECT_ROOT / "plugins/_model_config/conf/model_providers.yaml").exists()
138
139 for name in [
140 "OpenRouter",
141 "Agent Zero API",
142 "OpenAI",
143 "Anthropic",
144 "Google",
145 "DeepSeek",
146 "xAI",
147 "Moonshot AI",
148 "Nebius Token Factory",
149 "Z.AI",
150 "Mistral AI",
151 "Azure OpenAI",
152 "llama.cpp",
153 "oMLX",
154 "vLLM",
155 ]:
156 assert name in provider_yaml + provider_ui
157
158 for name in ["Ollama Cloud", "AWS Bedrock", "Groq", "Cerebras"]:
159 assert name in provider_yaml + provider_ui
160
161 for forbidden in [
162 "onboarding_category",
163 "onboarding_rank",
164 "short_description",
165 "setup_url",
166 "api_key_url",
167 "docs_url",
168 "logo:",
169 "api_key_mode",
170 "model_list_autoload",
171 "default_chat_model",
172 "default_utility_model",
173 "default_api_base",
174 ]:
175 assert forbidden not in provider_yaml
176
177 for logo in [
178 "deepseek.svg",
179 "google-gemini.svg",
180 "groq.svg",
181 "sambanova.png",
182 "cometapi.ico",
183 "cerebras.svg",
184 "github-copilot.svg",
185 "llama-cpp.svg",
186 "zai-logo.svg",
187 "omlx.svg",
188 "vllm.svg",
189 ]:
190 assert logo in provider_ui
191
192 assert (PROJECT_ROOT / "plugins/_onboarding/webui/assets/provider-logos/llama-cpp.svg").exists()
193 assert (PROJECT_ROOT / "plugins/_onboarding/webui/assets/provider-logos/cerebras.svg").exists()
194 assert (PROJECT_ROOT / "plugins/_onboarding/webui/assets/provider-logos/omlx.svg").exists()
195 assert (PROJECT_ROOT / "plugins/_onboarding/webui/assets/provider-logos/vllm.svg").exists()
196
197
198 def test_nebius_provider_config_uses_openai_compatible_token_factory_endpoint():
199 provider_path = PROJECT_ROOT / "conf/model_providers.yaml"
200 provider_config = yaml.safe_load(provider_path.read_text(encoding="utf-8"))
201 nebius = provider_config["chat"]["nebius"]
202
203 assert nebius["name"] == "Nebius Token Factory"
204 assert nebius["litellm_provider"] == "openai"
205 assert nebius["kwargs"]["api_base"] == "https://api.tokenfactory.nebius.com/v1"
206 assert nebius["models_list"]["endpoint_url"] == "/models"
207 assert "api_key_mode" not in nebius
208
209
210 def test_nvidia_nim_is_a_first_class_provider():
211 provider_config = yaml.safe_load(
212 (PROJECT_ROOT / "conf/model_providers.yaml").read_text(encoding="utf-8")
213 )
214 provider_ui = (PROJECT_ROOT / "plugins/_onboarding/webui/onboarding-providers.js").read_text(
215 encoding="utf-8"
216 )
217
218 for model_type in ("chat", "embedding"):
219 provider = provider_config[model_type]["nvidia_nim"]
220 assert provider["litellm_provider"] == "nvidia_nim"
221 assert provider["models_list"]["endpoint_url"] == (
222 "https://integrate.api.nvidia.com/v1/models"
223 )
224
225 assert '"nvidia_nim"' in provider_ui
226 assert "https://docs.api.nvidia.com/nim/reference/llm-apis" in provider_ui
227
228
229 def test_discovery_auto_modal_extension_contains_required_guards():
230 content = (PROJECT_ROOT / "plugins/_discovery/extensions/webui/initFw_end/auto-modal.js").read_text(encoding="utf-8")
231
232 assert "auto_modal_path" in content
233 assert "chat-created" in content
234 assert "modalAlreadyOpen" in content
235 assert "discovery_auto_modal_closed" in content
236 assert "auto_modal_surfaces" in content
237
238
239 def test_onboarding_success_filters_oauth_discovery_cards():
240 content = (
241 PROJECT_ROOT
242 / "plugins/_discovery/extensions/webui/onboarding-success-end/discovery-cards.html"
243 ).read_text(encoding="utf-8")
244
245 assert "discovery-codex-oauth" in content
246 assert "discovery-oauth-accounts" in content
247 assert "includes(card.id)" in content