From 59f5ae03ea618aecb6e9dd3ee4657b6dee35cff1 Mon Sep 17 00:00:00 2001 From: Alessandro <155005371+3clyp50@users.noreply.github.com> Date: Tue, 25 Aug 2026 15:14:03 +0200 Subject: [PATCH] Integrate vision sidecar routing with model presets Add a strict per-preset sidecar slot, Main-first routing, one-call multi-image analysis, parallel-worker image resolution, and inline model settings with focused regression coverage. --- .../python/system_prompt/_11_tools_prompt.py | 9 +- helpers/responses_tools.py | 7 +- helpers/responses_tools.py.dox.md | 6 +- plugins/_model_config/AGENTS.md | 9 +- .../model-switcher.html | 10 + plugins/_model_config/helpers/model_config.py | 53 ++- plugins/_model_config/webui/main.html | 21 +- .../_model_config/webui/model-config-store.js | 46 ++- plugins/_model_config/webui/model-field.html | 32 +- .../_model_config/webui/preset-overview.html | 30 +- prompts/AGENTS.md | 1 + prompts/agent.system.tools_vision_sidecar.md | 48 +++ tests/test_browser_agent_regressions.py | 20 +- tests/test_model_config_api_keys.py | 2 +- tests/test_model_config_project_presets.py | 38 ++ tests/test_model_config_ui.py | 43 +++ tests/test_parallel_tool.py | 36 ++ tests/test_tool_policy.py | 53 +++ tests/test_vision_load_image_refs.py | 230 ++++++++++++- tools/vision_load.py | 324 ++++++++++++------ tools/vision_load.py.dox.md | 12 +- 21 files changed, 880 insertions(+), 150 deletions(-) create mode 100644 prompts/agent.system.tools_vision_sidecar.md diff --git a/extensions/python/system_prompt/_11_tools_prompt.py b/extensions/python/system_prompt/_11_tools_prompt.py index 6349a862c..a395d6c3b 100644 --- a/extensions/python/system_prompt/_11_tools_prompt.py +++ b/extensions/python/system_prompt/_11_tools_prompt.py @@ -51,10 +51,15 @@ async def build_prompt(agent: Agent) -> str: prompt = agent.read_prompt("agent.system.tools.md", tools=tools_str) # vision support - from plugins._model_config.helpers.model_config import get_chat_model_config + from plugins._model_config.helpers.model_config import ( + get_chat_model_config, + use_vision_sidecar, + ) chat_cfg = get_chat_model_config(agent) - if chat_cfg.get("vision", False): + if use_vision_sidecar(agent): + prompt += "\n\n" + agent.read_prompt("agent.system.tools_vision_sidecar.md") + elif chat_cfg.get("vision", False): prompt += "\n\n" + agent.read_prompt("agent.system.tools_vision.md") return prompt diff --git a/helpers/responses_tools.py b/helpers/responses_tools.py index 93778d652..877f03d79 100644 --- a/helpers/responses_tools.py +++ b/helpers/responses_tools.py @@ -114,8 +114,13 @@ def _local_tool_prompts(agent: Any) -> list[tuple[str, str]]: def _vision_tool_prompt(agent: Any) -> str: try: - from plugins._model_config.helpers.model_config import get_chat_model_config + from plugins._model_config.helpers.model_config import ( + get_chat_model_config, + use_vision_sidecar, + ) + if use_vision_sidecar(agent): + return agent.read_prompt("agent.system.tools_vision_sidecar.md") if not get_chat_model_config(agent).get("vision", False): return "" return agent.read_prompt("agent.system.tools_vision.md") diff --git a/helpers/responses_tools.py.dox.md b/helpers/responses_tools.py.dox.md index 7c2631867..041919146 100644 --- a/helpers/responses_tools.py.dox.md +++ b/helpers/responses_tools.py.dox.md @@ -12,7 +12,7 @@ ## Local Contracts -- Build local function tools from enabled `agent.system.tool.*.md` prompt files and include `vision_load` only when the active chat model enables the matching vision prompt. +- Build local function tools from enabled `agent.system.tool.*.md` prompt files and include `vision_load` when either Main native vision or the effective preset's Vision Model enables the matching prompt. - Discover local prompt files through `helpers.subagents.get_paths`; this module owns the Responses-specific prompt-name compatibility rules. - Local prompt-derived function names use existing bullet declarations that pair a backticked name with `arg` or `args` for multi-tool prompt files, otherwise prefer explicit `"tool_name"` examples, then the first prompt heading, and finally the prompt filename. @@ -25,8 +25,8 @@ - Preserve original Agent Zero tool names through the native Responses name map. - Keep MCP tool schemas merged after local prompt-derived tools. - Apply `helpers.tool_policy` before emitting local or MCP schemas; a blocked - capability is absent from provider-native tool definitions. Vision remains - controlled solely by the active chat model configuration. + capability is absent from provider-native tool definitions. Vision routing + is controlled by the effective model preset rather than Agent Editor. - Connector remote tools are advertised only when `_a0_connector` runtime metadata says the matching connected CLI capability is currently available. ## Work Guidance diff --git a/plugins/_model_config/AGENTS.md b/plugins/_model_config/AGENTS.md index f3ba7d529..28ec60ee9 100644 --- a/plugins/_model_config/AGENTS.md +++ b/plugins/_model_config/AGENTS.md @@ -14,7 +14,7 @@ ## Local Contracts -- `Default` is the first global preset and cannot be deleted or renamed. It owns the complete main, utility, and embedding baseline. +- `Default` is the first global preset and cannot be deleted or renamed. It owns the complete main, utility, and embedding baseline; its Vision Model slot is optional. - Preset definitions are global. Global, project, agent-profile, and project/profile plugin configs persist only `model_preset`; chats may persist a preset reference as their explicit override. - Preserve scoped plugin resolution order and fall back invalid or missing scope/chat references to `Default`. - 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. @@ -22,7 +22,12 @@ - Check API-key readiness only for the effective model configuration; unused global presets must not produce Welcome-screen warnings. - Coordinate OAuth-backed providers with `_oauth` instead of hardcoding provider-specific auth here. - `model_config_get` exposes `model_configured` as a derived chat-model readiness flag from provider, model name, and API-key availability. -- 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. +- Non-default presets may inherit omitted main, utility, or embedding slots and durable tuning from `Default`, but must replace or clear per-slot `kwargs` so provider-specific extra params never leak across model providers. +- The optional `vision` slot is strictly per preset and never inherited from `Default`; an empty slot disables sidecar vision for that preset. +- Main native vision wins by default. A configured Vision Model handles `vision_load` when Main lacks vision, or when that preset explicitly enables `override_main`. +- Keep the optional Vision provider/model selector inside the Main Model card and flush with Main's field alignment, without a nested left inset. Show it only while Main vision is disabled or `override_main` is enabled; do not render a standalone Vision Model card. +- Show `Use separate Vision Model` immediately below `Supports Vision` while Main vision is enabled, not inside Advanced Settings; describe the disabled state as using Main's native vision. +- In model overviews, render the effective Vision Model as a text-only `Vision override / Provider / Model` child aligned with Main's provider column, not as an icon-bearing peer row. - Changing a model provider in the settings UI must clear `api_base` and `kwargs` because both may be provider-specific. - Repair provider-specific model-config aliases at the model-config read/build boundary; keep provider-specific repairs out of provider-agnostic core wrappers such as `models.py`. - `modelConfig.createPresetEditor()` owns local preset drafts, row actions, and stable UI-only row keys so deletion or renaming cannot rebind nested model fields. diff --git a/plugins/_model_config/extensions/webui/chat-input-progress-start/model-switcher.html b/plugins/_model_config/extensions/webui/chat-input-progress-start/model-switcher.html index 460bdfe72..0940d547f 100644 --- a/plugins/_model_config/extensions/webui/chat-input-progress-start/model-switcher.html +++ b/plugins/_model_config/extensions/webui/chat-input-progress-start/model-switcher.html @@ -65,6 +65,16 @@ + + + -