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&&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
),