Files
OmniRoute/tests/unit/modality-bridge-settings.test.ts
Praveen K Palaniswamy 65e81158ab fix(ollama): route models by advertised capability (#11088)
Landed with the design call resolved per the owner's pick — **option 1**: the synced store is now endpoint-agnostic (persistDiscoveredModels and managedModelImport no longer drop non-chat models at write time), and chat selectability moved to read time (auto-pool expansion in autoStrategy applies filterChatSelectableModels; the models-route projection already had its chatOnly filter). Your discovery test now passes end-to-end (3/3): /api/show capabilities persist per connection and image/embedding requests route through the advertising host.

Reconciliation notes: conflicted areas merged onto the current tip (adobe discovery import, requestedModel preflight signature, resolvedProvider fast-path coexists with the synced-route override — explicit resolution wins); carried base-red drains (#10055 memoization, #11071 test variants) dropped as already-landed; the managed-model-import exclusion test was propagated to the new contract (image/video models persist; the read filter still hides them from chat pickers — pinned by a new assertion). Full battery: 205/206 focused (the one red is a confirmed periodic-timer timing flake on the loaded devbox — 20/20 isolated), autoCombo vitest 30/30, combo suites 46/46, gates + typecheck clean.

Thank you @yourspraveen — the capability probe + routing design was right; it just needed the store contract opened up. Fixes #11087.
2026-08-23 11:45:01 -03:00

97 lines
3.6 KiB
TypeScript

import { test } from "node:test";
import assert from "node:assert";
import {
resolveVisionBridgeRuntimeSettings,
MODALITY_BRIDGE_DEFAULTS,
} from "../../src/shared/constants/modalityBridgeDefaults.ts";
import { updateSettingsSchema } from "../../src/shared/validation/settingsSchemas.ts";
test("new keys win over legacy keys", () => {
const s = resolveVisionBridgeRuntimeSettings({
modalityBridgeVisionEnabled: false,
visionBridgeEnabled: true,
modalityBridgeVisionModel: "gemini/gemini-2.5-flash",
visionBridgeModel: "openai/gpt-4o-mini",
});
assert.equal(s.enabled, false);
assert.equal(s.model, "gemini/gemini-2.5-flash");
});
test("legacy keys used as fallback when new keys absent (rollback 1 ciclo)", () => {
const s = resolveVisionBridgeRuntimeSettings({
visionBridgeEnabled: false,
visionBridgePrompt: "legacy prompt",
});
assert.equal(s.enabled, false);
assert.equal(s.prompt, "legacy prompt");
});
test("defaults: mode auto, taskAware true, cache on", () => {
const s = resolveVisionBridgeRuntimeSettings({});
assert.equal(s.mode, "auto");
assert.equal(s.taskAware, true);
assert.equal(s.cacheEnabled, true);
assert.equal(s.cacheTtlMinutes, MODALITY_BRIDGE_DEFAULTS.cacheTtlMinutes);
});
test("wrong-typed stored values are skipped in favor of the next candidate/default", () => {
const s = resolveVisionBridgeRuntimeSettings({
modalityBridgeVisionEnabled: "off", // string in a boolean field
modalityBridgeVisionTimeout: "9000", // string in a number field
modalityBridgeVisionModel: 42, // number in a string field
});
assert.equal(s.enabled, true); // falls through to VISION_BRIDGE_DEFAULTS.enabled
assert.equal(s.timeoutMs, 30000);
assert.equal(s.model, "openai/gpt-4o-mini");
// A wrong-typed NEW key must still fall through to a well-typed LEGACY key.
const fallback = resolveVisionBridgeRuntimeSettings({
modalityBridgeVisionEnabled: "off",
visionBridgeEnabled: false,
});
assert.equal(fallback.enabled, false);
});
test("Modality Bridge settings are accepted by the settings PATCH schema", () => {
const validation = updateSettingsSchema.safeParse({
modalityBridgeVisionEnabled: true,
modalityBridgeVisionMode: "describe",
modalityBridgeVisionModel: "gemini/gemini-2.5-flash",
modalityBridgeVisionTaskAware: false,
modalityBridgeVisionPrompt: "Describe the image contents briefly.",
modalityBridgeVisionTimeout: 45000,
modalityBridgeVisionMaxImages: 6,
modalityBridgeAudioEnabled: true,
modalityBridgeAudioModel: "openai/gpt-4o-mini-transcribe",
modalityBridgeAudioTimeout: 60000,
modalityBridgeAudioMaxClips: 3,
modalityBridgeCacheEnabled: true,
modalityBridgeCacheTtlMinutes: 60,
modalityBridgeCacheMaxEntries: 200,
});
assert.equal(validation.success, true);
});
test("Modality Bridge settings keep numeric bounds enforced (each field individually)", () => {
const invalidByField: Record<string, number> = {
modalityBridgeVisionTimeout: 999999,
modalityBridgeVisionMaxImages: 0,
modalityBridgeAudioMaxClips: 11,
modalityBridgeCacheTtlMinutes: 0,
modalityBridgeCacheMaxEntries: 9,
};
for (const [field, value] of Object.entries(invalidByField)) {
const validation = updateSettingsSchema.safeParse({ [field]: value });
assert.equal(validation.success, false, `${field}=${value} should be rejected`);
}
});
test("Modality Bridge vision mode rejects values outside the enum", () => {
const validation = updateSettingsSchema.safeParse({
modalityBridgeVisionMode: "invalid-mode",
});
assert.equal(validation.success, false);
});