Files
diegosouzapw--omniroute/tests/unit/vision-detection-consistency.test.ts
2026-07-13 13:39:12 +08:00

81 lines
3.2 KiB
TypeScript

/**
* #4072 — one shared vision-detection source.
*
* Three code paths kept independent vision-model lists and drifted apart, giving
* the same model id up to three different verdicts:
* - `src/lib/modelCapabilities.ts` (`modelIdLikelyVision`) — routing fallback (#4071)
* - `src/app/api/v1/models/catalog.ts` (`isVisionModelId`) — /v1/models listing
* - `open-sse/services/compression/lite.ts` (`replaceImageUrls`) — lite image strip
*
* The two concrete bugs:
* - lite stripped images for real vision models it didn't know (pixtral, llava,
* qwen-vl, glm-4v, kimi-vl, mistral-medium-3) → blinded them;
* - catalog flagged text models as vision (`gemma`, bare `kimi` like `kimi-k2`).
*
* After unification all three delegate to `@/shared/constants/visionModels`.
*/
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { isVisionModelId } from "../../src/shared/constants/visionModels.ts";
import { isVisionModelId as catalogIsVisionModelId } from "../../src/app/api/v1/models/catalog.ts";
import { modelIdLikelyVision } from "../../src/lib/modelCapabilities.ts";
import { replaceImageUrls } from "../../open-sse/services/compression/lite.ts";
const VISION = [
"mistral/pixtral-12b-latest",
"llava-1.5-7b",
"qwen-vl-max",
"gpt-4o",
"glm-4v",
"kimi-vl-a3b",
"mistral-medium-3",
];
const NOT_VISION = ["ministral-14b-latest", "mistral-large-latest", "gemma-2-9b", "kimi-k2"];
function imageBody() {
return {
messages: [
{
role: "user",
content: [
{ type: "image_url", image_url: { url: "data:image/png;base64,iVBOR" } },
],
},
],
};
}
// `replaceImageUrls` strips the image (applied=true) only when the model is NOT a
// vision model. So `applied === !isVision`.
function liteStripsImage(modelId: string): boolean {
return replaceImageUrls(imageBody(), modelId).applied;
}
describe("#4072 vision detection is consistent across all three sources", () => {
for (const id of VISION) {
it(`treats ${id} as vision everywhere`, () => {
assert.equal(isVisionModelId(id), true, `shared isVisionModelId(${id})`);
assert.equal(catalogIsVisionModelId(id), true, `catalog isVisionModelId(${id})`);
assert.equal(modelIdLikelyVision(id), true, `modelCapabilities modelIdLikelyVision(${id})`);
assert.equal(liteStripsImage(id), false, `lite must KEEP the image for ${id}`);
});
}
for (const id of NOT_VISION) {
it(`treats ${id} as non-vision everywhere`, () => {
assert.equal(isVisionModelId(id), false, `shared isVisionModelId(${id})`);
assert.equal(catalogIsVisionModelId(id), false, `catalog isVisionModelId(${id})`);
assert.equal(modelIdLikelyVision(id), false, `modelCapabilities modelIdLikelyVision(${id})`);
assert.equal(liteStripsImage(id), true, `lite must STRIP the image for ${id}`);
});
}
it("preserves the MiniMax M3 #3328 carve-out and Gemini 3 multimodal", () => {
for (const id of ["minimax-m3", "minimax-m3-free", "oc/minimax-m3-free", "gemini-3-pro"]) {
assert.equal(isVisionModelId(id), true, `${id} should be vision`);
assert.equal(liteStripsImage(id), false, `lite must keep the image for ${id}`);
}
});
});