From e62516364cf270c2e4d53cc1a37b7b4054eb5653 Mon Sep 17 00:00:00 2001 From: backryun Date: Sat, 8 Aug 2026 08:54:08 +0900 Subject: [PATCH] fix(types): validate Vision Bridge combo names (#9565) Merge-train validated (tip 6ce4effef8). Vitest failures confirmed as base-red (#9679). --- src/lib/guardrails/visionBridge.ts | 7 ++++++- tests/unit/guardrails/visionBridge.test.ts | 11 ++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/lib/guardrails/visionBridge.ts b/src/lib/guardrails/visionBridge.ts index 34fa2f10bd..33801b4810 100644 --- a/src/lib/guardrails/visionBridge.ts +++ b/src/lib/guardrails/visionBridge.ts @@ -28,6 +28,11 @@ export { isProviderConnectionUsable, hasUsableCredentialsForModel }; type ComboVisionBridgeDecision = "process" | "skip" | "not-combo"; +export function resolveVisionComboName(mapping: Record): string | null { + const comboName = mapping.comboName ?? mapping.name ?? null; + return typeof comboName === "string" && comboName.length > 0 ? comboName : null; +} + /// Check if a combo model should trigger vision bridge processing. /// Resolves combo targets and returns: /// - "process" if any target cannot be proven vision-capable @@ -45,7 +50,7 @@ async function getComboVisionBridgeDecision(model: string): Promise { assert.strictEqual(guardrail.enabled, false); }); +test("resolveVisionComboName accepts only non-empty string mapping names", () => { + assert.equal(resolveVisionComboName({ comboName: "vision-fallback" }), "vision-fallback"); + assert.equal(resolveVisionComboName({ name: "legacy-fallback" }), "legacy-fallback"); + assert.equal(resolveVisionComboName({ comboName: { nested: true } }), null); + assert.equal(resolveVisionComboName({ comboName: 42 }), null); + assert.equal(resolveVisionComboName({ comboName: "" }), null); +}); + // ── VB-S05: Vision Bridge disabled via settings ──────────────────────────── test("VB-S05: passthroughs when visionBridgeEnabled is false", async () => {