mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
fix(ui): make Restore defaults reset the tier set instead of stacking on it
Restore defaults re-added only the missing built-in tiers and kept every custom row, so a three-tier set became seven rather than four. That reads as a reset and is not one. It now does what the button beside it did: drop the edited set and rebuild the four built-in rows. The two buttons had the same destination, so the additive helper and its guard against overflowing the tier limit are gone with it, since a reset can never exceed four.
This commit is contained in:
parent
da80de7848
commit
bc7859bc9d
5 changed files with 10 additions and 78 deletions
|
|
@ -1142,7 +1142,7 @@ describe("ComplexityRouterConfig tier editing", () => {
|
|||
tier_model_params: { sec: { "gpt-4": { reasoning_effort: "high" } }, SIMPLE: { "gpt-3.5-turbo": {} } },
|
||||
};
|
||||
const { committed } = renderEditor(withEfforts);
|
||||
fireEvent.click(screen.getByRole("button", { name: "Use built-in tiers" }));
|
||||
fireEvent.click(screen.getByRole("button", { name: "Restore defaults" }));
|
||||
const next = committed();
|
||||
expect(next.custom_tier_set).toBeUndefined();
|
||||
expect(Object.keys(next.tier_model_params ?? {})).toEqual(["SIMPLE"]);
|
||||
|
|
@ -1161,13 +1161,13 @@ describe("ComplexityRouterConfig tier editing", () => {
|
|||
},
|
||||
};
|
||||
const { committed } = renderEditor(renamed);
|
||||
fireEvent.click(screen.getByRole("button", { name: "Use built-in tiers" }));
|
||||
fireEvent.click(screen.getByRole("button", { name: "Restore defaults" }));
|
||||
const next = committed();
|
||||
expect(next.tiers.COMPLEX).toEqual(["gpt-4"]);
|
||||
expect(next.tier_model_params).toEqual({ COMPLEX: { "gpt-4": { reasoning_effort: "high" } } });
|
||||
});
|
||||
|
||||
it("refuses to restore the built-in tiers when doing so would pass the tier limit", () => {
|
||||
it("resets a full tier set back to the four built-ins rather than stacking them on top", () => {
|
||||
const nearLimit: ComplexityRouterConfigValue = {
|
||||
...customValue,
|
||||
custom_tier_set: {
|
||||
|
|
@ -1180,8 +1180,11 @@ describe("ComplexityRouterConfig tier editing", () => {
|
|||
fallback_tier_id: "row-0",
|
||||
},
|
||||
};
|
||||
renderEditor(nearLimit);
|
||||
expect(screen.getByRole("button", { name: "Restore defaults" })).toBeDisabled();
|
||||
const { committed } = renderEditor(nearLimit);
|
||||
fireEvent.click(screen.getByRole("button", { name: "Restore defaults" }));
|
||||
const next = committed();
|
||||
expect(next.custom_tier_set).toBeUndefined();
|
||||
expect(Object.keys(next.tiers)).toEqual(["SIMPLE", "MEDIUM", "COMPLEX", "REASONING"]);
|
||||
});
|
||||
|
||||
it("stops describing the heuristic scorer once an edited tier set replaces it", () => {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ import {
|
|||
getCustomTierRowsError,
|
||||
isBuiltInTierName,
|
||||
resolveComplexityDefaultModel,
|
||||
restoredBuiltInRows,
|
||||
sameTierIdentity,
|
||||
tierRowById,
|
||||
tierRowByName,
|
||||
|
|
@ -406,10 +405,6 @@ const ComplexityRouterConfig: React.FC<ComplexityRouterConfigProps> = ({
|
|||
);
|
||||
};
|
||||
|
||||
const restorableRows = restoredBuiltInRows(tierRows, value.tiers);
|
||||
|
||||
const restoreDefaultTiers = () => commitTierRows(restorableRows, currentFallbackId);
|
||||
|
||||
// Models and params both come from these rows, so the two cannot be keyed differently.
|
||||
const exitToBuiltInTiers = () => {
|
||||
const { custom_tier_set: _dropped, ...rest } = value;
|
||||
|
|
@ -631,27 +626,9 @@ const ComplexityRouterConfig: React.FC<ComplexityRouterConfigProps> = ({
|
|||
Done
|
||||
</Button>
|
||||
</SimpleTooltip>
|
||||
{customTierSet && TIER_ORDER.some((tier) => !tierRows.some((row) => row.id === tier)) && (
|
||||
<SimpleTooltip
|
||||
content={
|
||||
restorableRows.length > MAX_TIER_COUNT
|
||||
? `Restoring the built-in tiers would make ${restorableRows.length} tiers, past the limit of ${MAX_TIER_COUNT}. Remove a tier first`
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
disabled={restorableRows.length > MAX_TIER_COUNT}
|
||||
onClick={restoreDefaultTiers}
|
||||
>
|
||||
Restore defaults
|
||||
</Button>
|
||||
</SimpleTooltip>
|
||||
)}
|
||||
{customTierSet && (
|
||||
<Button variant="outline" size="sm" onClick={exitToBuiltInTiers}>
|
||||
Use built-in tiers
|
||||
Restore defaults
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -936,7 +936,7 @@ describe("hydrateCustomTierSet", () => {
|
|||
expect(hydrated?.tiers.find((row) => row.id === hydrated.fallback_tier_id)?.name).toBe("SECURITY_REVIEW");
|
||||
});
|
||||
|
||||
it("mints the canonical key for a built-in name so Restore defaults recognises the row", () => {
|
||||
it("mints the canonical key for a built-in name so every pointer into the set is a row id", () => {
|
||||
const hydrated = hydrateCustomTierSet({
|
||||
tier_definitions: [{ name: "SIMPLE" }, { name: "AUDIT", description: "audits" }],
|
||||
tiers: { SIMPLE: ["a"], AUDIT: ["b"] },
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import {
|
|||
sameTierIdentity,
|
||||
tierRowById,
|
||||
getCustomTierRowsError,
|
||||
restoredBuiltInRows,
|
||||
tierParamsByRowId,
|
||||
tierRowByName,
|
||||
} from "./tier_rows";
|
||||
|
|
@ -117,42 +116,6 @@ describe("CUSTOM_TIER_RESTRICTIONS", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("restoredBuiltInRows", () => {
|
||||
it("brings missing built-ins back in canonical order and leaves custom rows after them", () => {
|
||||
const restored = restoredBuiltInRows([definedRow("AUDIT"), { ...definedRow("COMPLEX"), id: "COMPLEX" }], tiers);
|
||||
expect(restored.map((r) => r.id)).toEqual(["SIMPLE", "MEDIUM", "COMPLEX", "REASONING", "audit"]);
|
||||
});
|
||||
|
||||
it("keeps the models an already-present built-in row carries rather than the stale record", () => {
|
||||
const edited = { ...definedRow("SIMPLE", ["edited"]), id: "SIMPLE" };
|
||||
expect(restoredBuiltInRows([edited], tiers).find((r) => r.id === "SIMPLE")?.models).toEqual(["edited"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("restoredBuiltInRows name collisions", () => {
|
||||
it("does not restore a built-in slot whose name a custom row already answers to", () => {
|
||||
const custom: TierRow[] = [
|
||||
{ id: "uuid-1", name: "SIMPLE", definition: "operator took this name", models: ["a"] },
|
||||
{ id: "MEDIUM", name: "MEDIUM", definition: "", models: ["b"] },
|
||||
];
|
||||
const restored = restoredBuiltInRows(custom, tiers);
|
||||
const folded = restored.map((row) => row.name.toLowerCase());
|
||||
expect(new Set(folded).size).toBe(folded.length);
|
||||
expect(restored.filter((row) => row.name === "SIMPLE")).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("still restores the built-in slots nothing else claims", () => {
|
||||
const custom: TierRow[] = [{ id: "uuid-1", name: "AUDIT", definition: "d", models: ["a"] }];
|
||||
expect(restoredBuiltInRows(custom, tiers).map((row) => row.id)).toEqual([
|
||||
"SIMPLE",
|
||||
"MEDIUM",
|
||||
"COMPLEX",
|
||||
"REASONING",
|
||||
"uuid-1",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getCustomTierRowsError", () => {
|
||||
it("accepts a complete set", () => {
|
||||
expect(getCustomTierRowsError(set([definedRow("CASUAL"), definedRow("AUDIT")]))).toBeNull();
|
||||
|
|
|
|||
|
|
@ -55,17 +55,6 @@ export const activeTierRows = (value: ActiveTierSet): ActiveTierRow[] => {
|
|||
return rows.map((row) => ({ ...row, params: value.tier_model_params?.[row.id] ?? {} }));
|
||||
};
|
||||
|
||||
// A custom row can answer to a built-in name without carrying its id, and restoring the slot then
|
||||
// collides on the uniqueness rule, so a claimed name means that slot stays gone.
|
||||
export const restoredBuiltInRows = (rows: readonly TierRow[], tiers: ComplexityTiers): TierRow[] => [
|
||||
...TIER_ORDER.flatMap((tier) => {
|
||||
const slot = rows.find((row) => row.id === tier);
|
||||
if (slot) return [slot];
|
||||
return rows.some((row) => sameTierIdentity(row.name, tier)) ? [] : [builtInRow(tier, tiers)];
|
||||
}),
|
||||
...rows.filter((row) => !(TIER_ORDER as string[]).includes(row.id)),
|
||||
];
|
||||
|
||||
export const tierRowById = <T extends TierRow>(rows: readonly T[], id: string | undefined): T | undefined =>
|
||||
id === undefined ? undefined : rows.find((row) => row.id === id);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue