refactor: remove browser model, use chat model for browser; update extension references

keyboardstaff committed Mar 14, 2026 at 20:06 UTC 8d33cae0e1eb42f08550ef72bc0c474f650ae021
5 files changed +37 -32
extensions/python/banners/_20_missing_api_key.py
+17 -25
@@ -1,45 +1,37 @@
1 from helpers.extension import Extension
2 -from helpers import settings as settings_helper
2 +from helpers import plugins
3 import models
4
5
6 class MissingApiKeyCheck(Extension):
7 """Check if API keys are configured for selected model providers."""
8
9 - LOCAL_PROVIDERS = ["ollama", "lm_studio"]
10 - LOCAL_EMBEDDING = ["huggingface"]
11 - MODEL_TYPE_NAMES = {
12 - "chat": "Chat Model",
13 - "utility": "Utility Model",
14 - "browser": "Web Browser Model",
15 - "embedding": "Embedding Model",
16 - }
9 + LOCAL_PROVIDERS = {"ollama", "lm_studio"}
10 + LOCAL_EMBEDDING = {"huggingface"}
11
12 async def execute(self, banners: list = [], frontend_context: dict = {}, **kwargs):
19 - current_settings = settings_helper.get_settings()
20 - model_providers = {
21 - "chat": current_settings.get("chat_model_provider", ""),
22 - "utility": current_settings.get("util_model_provider", ""),
23 - "browser": current_settings.get("browser_model_provider", ""),
24 - "embedding": current_settings.get("embed_model_provider", ""),
25 - }
26 -
13 + cfg = plugins.get_plugin_config("_model_config") or {}
14 missing_providers = []
28 -
29 - for model_type, provider in model_providers.items():
15 + checks = [
16 + ("Chat Model", cfg.get("chat_model", {})),
17 + ("Utility Model", cfg.get("utility_model", {})),
18 + ("Embedding Model", cfg.get("embedding_model", {})),
19 + ]
20 +
21 + for label, model_cfg in checks:
22 + provider = model_cfg.get("provider", "")
23 if not provider:
24 continue
32 -
25 provider_lower = provider.lower()
26 if provider_lower in self.LOCAL_PROVIDERS:
27 continue
36 - if model_type == "embedding" and provider_lower in self.LOCAL_EMBEDDING:
28 + if label == "Embedding Model" and provider_lower in self.LOCAL_EMBEDDING:
29 continue
38 -
30 +
31 api_key = models.get_api_key(provider_lower)
32 if not (api_key and api_key.strip() and api_key != "None"):
33 missing_providers.append({
42 - "model_type": self.MODEL_TYPE_NAMES.get(model_type, model_type),
34 + "model_type": label,
35 "provider": provider,
36 })
37
@@ -57,8 +49,8 @@ class MissingApiKeyCheck(Extension):
49 "title": "Missing LLM API Key for current settings",
50 "html": f"""No API key configured for: {model_list}.<br>
51 Agent Zero will not be able to function properly unless you provide an API key or change your settings.<br>
60 - <a href="#" onclick="document.getElementById('settings').click(); return false;">
61 - Add your API key</a> in Settings → External Services → API Keys.""",
52 + <a href="#" onclick="(async()=>{{await import('/components/plugins/plugin-settings-store.js');const s=Alpine.store('pluginSettingsPrototype');if(s&amp;&amp;s.open){{await s.open('_model_config',{{perProjectConfig:true,perAgentConfig:true}});}}openModal('components/plugins/plugin-settings.html');}})();return false;">
53 + Configure model settings</a>""",
54 "dismissible": False,
55 "source": "backend"
56 })
extensions/python/message_loop_prompts_after/_70_include_agent_info.py
+3 -3
@@ -8,13 +8,13 @@ class IncludeAgentInfo(Extension):
8 return
9
10 # read prompt
11 + from plugins._model_config.helpers.model_config import get_chat_model_config
12 + chat_cfg = get_chat_model_config(self.agent)
13 agent_info_prompt = self.agent.read_prompt(
14 "agent.extras.agent_info.md",
15 number=self.agent.number,
16 profile=self.agent.config.profile or "Default",
15 - llm=self.agent.config.chat_model.provider
16 - + "/"
17 - + self.agent.config.chat_model.name,
17 + llm=chat_cfg.get("provider", "") + "/" + chat_cfg.get("name", ""),
18 )
19
20 # add agent info to the prompt
extensions/python/monologue_start/_60_rename_chat.py
+3 -1
@@ -15,9 +15,11 @@ class RenameChat(Extension):
15
16 try:
17 # prepare history
18 + from plugins._model_config.helpers.model_config import get_utility_model_config
19 + util_cfg = get_utility_model_config(self.agent)
20 history_text = self.agent.history.output_text()
21 ctx_length = min(
20 - int(self.agent.config.utility_model.ctx_length * 0.7), 5000
22 + int(util_cfg.get("ctx_length", 128000) * 0.7), 5000
23 )
24 history_text = tokens.trim_to_tokens(history_text, ctx_length, "start")
25 # prepare system and user prompt
extensions/python/system_prompt/_10_system_prompt.py
+3 -1
@@ -42,8 +42,10 @@ def get_main_prompt(agent: Agent):
42
43
44 def get_tools_prompt(agent: Agent):
45 + from plugins._model_config.helpers.model_config import get_chat_model_config
46 prompt = agent.read_prompt("agent.system.tools.md")
46 - if agent.config.chat_model.vision:
47 + chat_cfg = get_chat_model_config(agent)
48 + if chat_cfg.get("vision", False):
49 prompt += "\n\n" + agent.read_prompt("agent.system.tools_vision.md")
50 return prompt
51
tools/browser_agent.py
+11 -2
@@ -43,6 +43,15 @@ class State:
43 / f"agent_{self.agent.context.id}"
44 )
45
46 + def _get_browser_http_headers(self):
47 + from plugins._model_config.helpers.model_config import get_browser_http_headers
48 + return get_browser_http_headers(self.agent) or {}
49 +
50 + def _get_browser_vision(self):
51 + from plugins._model_config.helpers.model_config import get_chat_model_config
52 + cfg = get_chat_model_config(self.agent)
53 + return cfg.get("vision", False)
54 +
55 async def _initialize(self):
56 if self.browser_session:
57 return
@@ -70,7 +79,7 @@ class State:
79 args=["--headless=new"],
80 # Use a unique user data directory to avoid conflicts
81 user_data_dir=self.get_user_data_dir(),
73 - extra_http_headers=self.agent.config.browser_http_headers or {},
82 + extra_http_headers=self._get_browser_http_headers(),
83 )
84 )
85
@@ -160,7 +169,7 @@ class State:
169 task=task,
170 browser_session=self.browser_session,
171 llm=model,
163 - use_vision=self.agent.config.browser_model.vision,
172 + use_vision=self._get_browser_vision(),
173 extend_system_message=self.agent.read_prompt(
174 "prompts/browser_agent.system.md"
175 ),