mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-09 00:12:15 +03:00
fix(guardrails): pass providerId to getResolvedModelCapabilities in checkComboVision (#12112) (#12169)
* fix(guardrails): pass providerId to getResolvedModelCapabilities in checkComboVision (#12112) Signed-off-by: Minxi Hou <houminxi@gmail.com> * chore(quality): register combo-vision providerId test in the stryker tap set --------- Signed-off-by: Minxi Hou <houminxi@gmail.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
This commit is contained in:
@@ -529,7 +529,10 @@ function hasKnownCompatibleContextLimit(
|
||||
requirements: RequestCompatibilityRequirements
|
||||
): boolean {
|
||||
if (requirements.requiredContextTokens <= 0) return false;
|
||||
const capabilities = getResolvedModelCapabilities(target.modelStr);
|
||||
const capabilities = getResolvedModelCapabilities({
|
||||
provider: target.providerId || target.provider || null,
|
||||
model: target.modelStr,
|
||||
});
|
||||
return evaluateContextLimit(capabilities, requirements, target.modelStr) === true;
|
||||
}
|
||||
|
||||
@@ -546,7 +549,10 @@ export function isVisionIncompatibleTarget(
|
||||
requirements: RequestCompatibilityRequirements
|
||||
): boolean {
|
||||
if (!requirements.requiresVision) return false;
|
||||
const capabilities = getResolvedModelCapabilities(target.modelStr);
|
||||
const capabilities = getResolvedModelCapabilities({
|
||||
provider: target.providerId || target.provider || null,
|
||||
model: target.modelStr,
|
||||
});
|
||||
return capabilities.supportsVision !== true;
|
||||
}
|
||||
|
||||
@@ -571,7 +577,10 @@ function getTargetCompatibilityFailures(
|
||||
target: ResolvedComboTarget,
|
||||
requirements: RequestCompatibilityRequirements
|
||||
): string[] {
|
||||
const capabilities = getResolvedModelCapabilities(target.modelStr);
|
||||
const capabilities = getResolvedModelCapabilities({
|
||||
provider: target.providerId || target.provider || null,
|
||||
model: target.modelStr,
|
||||
});
|
||||
const failures: string[] = [];
|
||||
|
||||
if (
|
||||
|
||||
@@ -89,7 +89,16 @@ export async function getComboVisionBridgeDecision(
|
||||
hasModelStep = true;
|
||||
const targetModel = s.model;
|
||||
if (typeof targetModel === "string") {
|
||||
const caps = getResolvedModelCapabilities(targetModel);
|
||||
const provider =
|
||||
typeof s.providerId === "string"
|
||||
? s.providerId
|
||||
: typeof s.provider === "string"
|
||||
? s.provider
|
||||
: null;
|
||||
const caps = getResolvedModelCapabilities({
|
||||
provider,
|
||||
model: targetModel,
|
||||
});
|
||||
if (caps.supportsVision === true) {
|
||||
hasVisionCapableStep = true;
|
||||
} else {
|
||||
|
||||
@@ -255,6 +255,7 @@
|
||||
"tests/unit/github-model-not-supported-lockout.test.ts",
|
||||
"tests/unit/grok-cli-oauth.test.ts",
|
||||
"tests/unit/guardrails-api-3496.test.ts",
|
||||
"tests/unit/guardrails/combo-vision-provider-id-12112.test.ts",
|
||||
"tests/unit/guardrails/visionBridge-responses-9597.test.ts",
|
||||
"tests/unit/headroom-codex-quota-snapshot-6379.test.ts",
|
||||
"tests/unit/headroom-proxy-lifecycle.test.ts",
|
||||
|
||||
69
tests/unit/guardrails/combo-vision-provider-id-12112.test.ts
Normal file
69
tests/unit/guardrails/combo-vision-provider-id-12112.test.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
process.env.DATA_DIR = `/tmp/omniroute-test-12112-${Date.now()}`;
|
||||
|
||||
const { getComboVisionBridgeDecision } = await import(
|
||||
"../../../src/lib/guardrails/visionBridge.ts"
|
||||
);
|
||||
const combosDb = await import("../../../src/lib/db/combos.ts");
|
||||
const core = await import("../../../src/lib/db/core.ts");
|
||||
const { isVisionIncompatibleTarget } = await import(
|
||||
"../../../open-sse/services/combo/comboStructure.ts"
|
||||
);
|
||||
import type { ResolvedComboTarget } from "../../../open-sse/services/combo/types.ts";
|
||||
|
||||
test.after(() => {
|
||||
core.resetDbInstance();
|
||||
});
|
||||
|
||||
test("#12112: checkComboVision respects providerId for namespaced vision models (e.g. nvidia/nemotron-nano-12b-v2-vl)", async () => {
|
||||
// Model 'nvidia/nemotron-nano-12b-v2-vl' is declared with supportsVision: true in nvidia provider registry.
|
||||
// It has a slash in model id and requires providerId="nvidia" to resolve capabilities.
|
||||
await combosDb.createCombo({
|
||||
name: "nvidia-vision-combo-12112",
|
||||
models: [
|
||||
{
|
||||
providerId: "nvidia",
|
||||
model: "nvidia/nemotron-nano-12b-v2-vl",
|
||||
weight: 1,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const decision = await getComboVisionBridgeDecision("nvidia-vision-combo-12112");
|
||||
assert.equal(
|
||||
decision,
|
||||
"skip",
|
||||
"Combo with explicit nvidia vision model must resolve as 'skip' (vision supported), not 'no-vision'"
|
||||
);
|
||||
});
|
||||
|
||||
test("#12112: isVisionIncompatibleTarget passes providerId to resolve vision capability", () => {
|
||||
const target: ResolvedComboTarget = {
|
||||
kind: "model",
|
||||
stepId: "step-1",
|
||||
executionKey: "step-1",
|
||||
modelStr: "nvidia/nemotron-nano-12b-v2-vl",
|
||||
provider: "nvidia",
|
||||
providerId: "nvidia",
|
||||
connectionId: "conn-1",
|
||||
weight: 1,
|
||||
label: null,
|
||||
};
|
||||
|
||||
const incompatible = isVisionIncompatibleTarget(target, {
|
||||
requiresTools: false,
|
||||
requiresVision: true,
|
||||
requiresStructuredOutput: false,
|
||||
estimatedInputTokens: 10,
|
||||
requestedOutputTokens: 10,
|
||||
requiredContextTokens: 10,
|
||||
});
|
||||
|
||||
assert.equal(
|
||||
incompatible,
|
||||
false,
|
||||
"Target with providerId='nvidia' and model='nvidia/nemotron-nano-12b-v2-vl' must be vision-compatible"
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user