Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
const presets = getAllPresets();

const resolveDefaultModel = (tiers: ComplexityTiers): string | undefined =>
tiers.MEDIUM[0] || tiers.SIMPLE[0] || tiers.COMPLEX[0] || tiers.REASONING[0];

Check warning on line 87 in ui/litellm-dashboard/src/components/add_model/add_auto_router_tab.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Boolean expression combines 4 conditions; extract it into a named variable

// A one-line summary of what's configured, shown when the detailed section is collapsed so a
// caller can see the shape of the config without opening it.
Expand All @@ -102,6 +102,21 @@
return parts.length > 0 ? parts.join(" · ") : "No tiers configured yet";
};

// Why the submit is unavailable, or null when it is available. The button reads this to disable
// itself and to say what is missing, so the two can never give different answers. Checks the
// config actually being built, not which preset (if any) it came from: a preset only ever
// prefills once (handlePresetChange), and everything after that is edited exactly like Custom.
const getSubmitBlockedReason = (
config: ComplexityRouterConfigValue,
keywordTierRules: KeywordTierRule[],
referencedModelsParams: Parameters<typeof getReferencedModelsError>[0],
availableModelSet: Set<string>,
): string | null =>
getMissingTiersError(config.tiers) ??
getTierLabelsError(config.tier_labels) ??
getKeywordTierRulesError(keywordTierRules) ??
getReferencedModelsError(referencedModelsParams, availableModelSet);

const AddAutoRouterTab: React.FC<AddAutoRouterTabProps> = ({
handleOk,
accessToken,
Expand Down Expand Up @@ -141,7 +156,7 @@
useEffect(() => {
const fetchModelAccessGroups = async () => {
const response = await modelAvailableCall(accessToken, "", "", false, null, true, true);
setModelAccessGroups(response["data"].map((model: any) => model["id"]));

Check warning on line 159 in ui/litellm-dashboard/src/components/add_model/add_auto_router_tab.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Unexpected any. Specify a different type
};
fetchModelAccessGroups();
}, [accessToken]);
Expand Down Expand Up @@ -222,15 +237,12 @@
embeddingModel,
};

// Why the submit is unavailable, or null when it is available. The button reads this to disable
// itself and to say what is missing, so the two can never give different answers. Checks the
// config actually being built, not which preset (if any) it came from: a preset only ever
// prefills once (handlePresetChange), and everything after that is edited exactly like Custom.
const submitBlockedReason =
getMissingTiersError(complexityRouterConfig.tiers) ??
getTierLabelsError(complexityRouterConfig.tier_labels) ??
getKeywordTierRulesError(keywordTierRules) ??
getReferencedModelsError(referencedModelsParams, availableModelSet);
const submitBlockedReason = getSubmitBlockedReason(
complexityRouterConfig,
keywordTierRules,
referencedModelsParams,
availableModelSet,
);

const complexityRouterConfigParams: BuildComplexityRouterConfigParams = {
tiers: complexityRouterConfig.tiers,
Expand Down Expand Up @@ -304,7 +316,7 @@

const defaultModel = resolveDefaultModel(tiers);

form.setFieldsValue({

Check warning on line 319 in ui/litellm-dashboard/src/components/add_model/add_auto_router_tab.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Object literal with 4 properties passed inline as an argument; assign it to a named variable first
custom_llm_provider: "auto_router",
model: name,
api_key: "not_required_for_auto_router",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
describe("buildComplexityRouterConfig", () => {
it("emits tiers, classifier_type, and escalation_keywords when nothing else is configured", () => {
const config = buildComplexityRouterConfig(baseParams);
expect(config).toEqual({

Check warning on line 43 in ui/litellm-dashboard/src/components/add_model/build_complexity_router_config.test.ts

View workflow job for this annotation

GitHub Actions / frontend-lint

Object literal with 4 properties passed inline as an argument; assign it to a named variable first
tiers,
classifier_type: "heuristic",
session_affinity: false,
Expand Down Expand Up @@ -207,7 +207,7 @@
});

it("omits adaptive fields when adaptive is disabled even if weights linger in state", () => {
const config = buildComplexityRouterConfig({

Check warning on line 210 in ui/litellm-dashboard/src/components/add_model/build_complexity_router_config.test.ts

View workflow job for this annotation

GitHub Actions / frontend-lint

Object literal with 5 properties passed inline as an argument; assign it to a named variable first
...baseParams,
adaptive: false,
adaptiveWeights: { quality: 0.9, cost: 0.1 },
Expand Down Expand Up @@ -241,7 +241,7 @@
});

it("includes tier_distance_penalty when adaptive is enabled with eligible='all'", () => {
const config = buildComplexityRouterConfig({

Check warning on line 244 in ui/litellm-dashboard/src/components/add_model/build_complexity_router_config.test.ts

View workflow job for this annotation

GitHub Actions / frontend-lint

Object literal with 5 properties passed inline as an argument; assign it to a named variable first
...baseParams,
adaptive: true,
adaptiveWeights: { quality: 0.6, cost: 0.4 },
Expand All @@ -255,7 +255,7 @@
});

it("omits tier_distance_penalty when eligible='classified_tier', since the penalty doesn't apply there", () => {
const config = buildComplexityRouterConfig({

Check warning on line 258 in ui/litellm-dashboard/src/components/add_model/build_complexity_router_config.test.ts

View workflow job for this annotation

GitHub Actions / frontend-lint

Object literal with 5 properties passed inline as an argument; assign it to a named variable first
...baseParams,
adaptive: true,
adaptiveWeights: { quality: 0.6, cost: 0.4 },
Expand Down Expand Up @@ -437,9 +437,8 @@
});

it("accepts a full distinct rename", () => {
expect(
getTierLabelsError({ SIMPLE: "Cheap", MEDIUM: "Standard", COMPLEX: "Premium", REASONING: "Deep" }),
).toBeNull();
const fullRename = { SIMPLE: "Cheap", MEDIUM: "Standard", COMPLEX: "Premium", REASONING: "Deep" };
expect(getTierLabelsError(fullRename)).toBeNull();
});

it("rejects two tiers sharing a name, which would be ambiguous in the logs", () => {
Expand Down Expand Up @@ -473,9 +472,8 @@
});

it("drops non-string and blank values a hand-edited config could hold", () => {
expect(hydrateTierLabels({ SIMPLE: 7, MEDIUM: " ", COMPLEX: null, REASONING: "Deep" })).toEqual({
REASONING: "Deep",
});
const handEdited = { SIMPLE: 7, MEDIUM: " ", COMPLEX: null, REASONING: "Deep" };
expect(hydrateTierLabels(handEdited)).toEqual({ REASONING: "Deep" });
});

it("ignores keys that are not tiers", () => {
Expand Down
Loading