(id: string)
| 211 | * always spinning up a separate vision sub-agent. |
| 212 | */ |
| 213 | export function looksVisionCapable(id: string): boolean { |
| 214 | const lower = id.toLowerCase(); |
| 215 | if (/gemma-?4/.test(lower)) return true; // Gemma 4 — multimodal (incl. 31B) |
| 216 | // "vl" not surrounded by other letters: qwen2.5vl, qwen3-vl, qwen3vl, ...-vl-32b |
| 217 | if (/(^|[^a-z])vl([^a-z]|$)/.test(lower)) return true; |
| 218 | if (/vision/.test(lower)) return true; // llama3.2-vision, etc. |
| 219 | if (/llava|minicpm-?v|pixtral|moondream|internvl|cogvlm/.test(lower)) return true; |
| 220 | // Cloud multimodal: GPT-4o family, Gemini, and every modern Claude (3.x AND 4.x — |
| 221 | // sonnet/opus/haiku are all image-capable; the old `claude-3`-only test missed claude-4). |
| 222 | if (/gpt-?4o|gemini/.test(lower)) return true; |
| 223 | if (/claude-(3|4|5|sonnet|opus|haiku)/.test(lower)) return true; |
| 224 | return false; |
| 225 | } |
| 226 | |
| 227 | /** |
| 228 | * Family/size heuristic for context window when the live API doesn't report one. |
no outgoing calls
no test coverage detected