|
| 1 | +import { describe, expect, test } from "bun:test" |
| 2 | + |
| 3 | +// Mirror the NATIVE_VISION regex from the plugin so we can test the matching logic |
| 4 | +// without importing the plugin module (which has side effects on load). |
| 5 | +const NATIVE_VISION = /gpt-|o[0-9]|claude-|gemini-|pixtral|llama-3\.2.*vision|nova-.*vision|qwen3\.[56](?!-max)|qwen(?:-vl|2[._-]?5?[._-]?vl)|qwen2-vl|qwen3-vl|qwen-omni|qvq-max|kimi-k2\.(5|6)|minimax-m3|minimax-vl|glm-[0-9.]+v|mimo-v2-omni|mimo-v2\.5$|yi-vl|deepseek-vl2|doubao-.*vision|seed-.*vision|internvl/i |
| 6 | + |
| 7 | +describe("NATIVE_VISION regex", () => { |
| 8 | + // Should match (native multimodal) |
| 9 | + const yesCases: Array<[string, string]> = [ |
| 10 | + ["gpt-5.4", "OpenAI latest"], |
| 11 | + ["gpt-4o", "OpenAI 4o"], |
| 12 | + ["gpt-4o-mini", "OpenAI 4o mini"], |
| 13 | + ["gpt-5-codex", "OpenAI codex"], |
| 14 | + ["o4-mini", "OpenAI o-series"], |
| 15 | + ["o1", "OpenAI o1"], |
| 16 | + ["claude-sonnet-4-6", "Anthropic sonnet"], |
| 17 | + ["claude-3-5-sonnet", "Anthropic 3.5"], |
| 18 | + ["claude-opus-4-6", "Anthropic opus"], |
| 19 | + ["gemini-2.5-pro", "Google gemini"], |
| 20 | + ["gemini-3-pro", "Google gemini 3"], |
| 21 | + ["pixtral-12b", "Mistral pixtral"], |
| 22 | + ["llama-3.2-90b-vision", "Meta llama 3.2 vision"], |
| 23 | + ["llama-3.2-11b-vision", "Meta llama 3.2 vision"], |
| 24 | + ["nova-pro-vision", "AWS nova vision"], |
| 25 | + ["qwen3.5-plus", "Qwen 3.5 plus"], |
| 26 | + ["qwen3.6-flash", "Qwen 3.6 flash"], |
| 27 | + ["qwen-vl-max", "Qwen VL max"], |
| 28 | + ["qwen2-5-vl-72b-instruct", "Qwen 2.5 VL"], |
| 29 | + ["qwen2-vl-7b", "Qwen 2 VL"], |
| 30 | + ["qwen3-vl-30b", "Qwen 3 VL"], |
| 31 | + ["qwen-omni-turbo", "Qwen omni"], |
| 32 | + ["qvq-max", "Qwen QVQ"], |
| 33 | + ["kimi-k2.5", "Kimi 2.5"], |
| 34 | + ["kimi-k2.6", "Kimi 2.6"], |
| 35 | + ["moonshotai/Kimi-K2.5", "Kimi prefixed"], |
| 36 | + ["MiniMax-M3", "MiniMax M3 (case-insensitive)"], |
| 37 | + ["minimax-m3", "MiniMax M3 lower"], |
| 38 | + ["minimax-vl-01", "MiniMax VL"], |
| 39 | + ["glm-4.5v", "GLM 4.5 vision"], |
| 40 | + ["glm-4.6v", "GLM 4.6 vision"], |
| 41 | + ["glm-5v-turbo", "GLM 5 vision turbo"], |
| 42 | + ["mimo-v2-omni", "Xiaomi MiMo omni"], |
| 43 | + ["mimo-v2.5", "Xiaomi MiMo 2.5"], |
| 44 | + ["yi-vl-6b", "Yi VL"], |
| 45 | + ["deepseek-vl2", "DeepSeek VL2"], |
| 46 | + ["Qwen/Qwen2.5-VL-72B-Instruct", "Qwen with org prefix"], |
| 47 | + ["doubao-1-5-vision-pro", "Doubao vision"], |
| 48 | + ["seed-1-6-vision", "Seed vision"], |
| 49 | + ["internvl2.5", "InternVL"], |
| 50 | + ] |
| 51 | + |
| 52 | + for (const [id, desc] of yesCases) { |
| 53 | + test(`matches native vision: ${id} (${desc})`, () => { |
| 54 | + expect(NATIVE_VISION.test(id.toLowerCase())).toBe(true) |
| 55 | + }) |
| 56 | + } |
| 57 | + |
| 58 | + // Should NOT match (text-only, fall back to vision tool) |
| 59 | + const noCases: Array<[string, string]> = [ |
| 60 | + ["deepseek-v4-flash", "DeepSeek V4 Flash"], |
| 61 | + ["deepseek-v4-pro", "DeepSeek V4 Pro"], |
| 62 | + ["deepseek-r1", "DeepSeek R1"], |
| 63 | + ["deepseek-chat", "DeepSeek chat"], |
| 64 | + ["MiniMax-M2.7", "MiniMax M2.7"], |
| 65 | + ["MiniMax-M2.5", "MiniMax M2.5"], |
| 66 | + ["MiniMax-M2", "MiniMax M2"], |
| 67 | + ["qwen3-max", "Qwen 3 max"], |
| 68 | + ["qwen3.7-max", "Qwen 3.7 max"], |
| 69 | + ["qwen3.6-max-preview", "Qwen 3.6 max preview"], |
| 70 | + ["qwen-plus", "Qwen plus"], |
| 71 | + ["qwen-flash", "Qwen flash"], |
| 72 | + ["qwen-turbo", "Qwen turbo"], |
| 73 | + ["qwen3-32b", "Qwen 3 32B"], |
| 74 | + ["qwen3-235b-a22b", "Qwen 3 235B"], |
| 75 | + ["qwen3-coder-plus", "Qwen coder"], |
| 76 | + ["glm-4.5", "GLM 4.5"], |
| 77 | + ["glm-4.6", "GLM 4.6"], |
| 78 | + ["glm-4.7", "GLM 4.7"], |
| 79 | + ["glm-5", "GLM 5"], |
| 80 | + ["glm-5.1", "GLM 5.1"], |
| 81 | + ["mimo-v2-flash", "MiMo 2 flash"], |
| 82 | + ["mimo-v2-pro", "MiMo 2 pro"], |
| 83 | + ["mimo-v2.5-pro", "MiMo 2.5 pro"], |
| 84 | + ["kimi-k2-thinking", "Kimi thinking"], |
| 85 | + ["kimi-k2-turbo", "Kimi turbo"], |
| 86 | + ["step-1-32k", "Step 1"], |
| 87 | + ["step-3.5-flash", "Step 3.5"], |
| 88 | + ] |
| 89 | + |
| 90 | + for (const [id, desc] of noCases) { |
| 91 | + test(`does NOT match (text-only): ${id} (${desc})`, () => { |
| 92 | + expect(NATIVE_VISION.test(id.toLowerCase())).toBe(false) |
| 93 | + }) |
| 94 | + } |
| 95 | +}) |
0 commit comments