fix(auto-router compression): surface a stored model-only policy in the edit form

The backend treats either compression key on its own as an authoritative policy, but
hydrate returned the untouched inherit state whenever the routing key was absent. A
config carrying only auto_router_model_compression was therefore invisible in the
form, and picking a routing value then overwrote the stored model hop. Only neither
key set now reads as untouched, and an absent key on either hop hydrates as no
compression for that hop rather than same-as-the-other.
This commit is contained in:
moe-berri 2026-09-05 11:05:50 -07:00
parent 1c16a5910b
commit ff942c3a74
2 changed files with 28 additions and 7 deletions

View file

@ -96,6 +96,21 @@ describe("hydrateAutoRouterCompression", () => {
expect(rebuilt.auto_router_model_compression).not.toBe("headroom-a");
});
it("surfaces a stored model-only policy instead of reading as untouched", () => {
// Regression: the backend treats either key alone as an authoritative policy, so a
// model-only config that hydrated to the inherit state was invisible in the form,
// and the next save overwrote the stored model hop with the routing value.
const state = hydrateAutoRouterCompression({ auto_router_model_compression: "headroom-b" });
expect(state).toEqual({ routing: "none", sameAsRouting: false, model: "headroom-b" });
});
it("round-trips a model-only policy without changing either hop", () => {
const stored = { auto_router_model_compression: "headroom-b" };
const rebuilt = buildAutoRouterCompressionParams(hydrateAutoRouterCompression(stored));
expect(rebuilt.auto_router_model_compression).toBe("headroom-b");
expect(rebuilt.auto_router_routing_compression).toBe("none");
});
it("round-trips through buildAutoRouterCompressionParams", () => {
const original = { auto_router_routing_compression: "headroom-a", auto_router_model_compression: "none" };
const rebuilt = buildAutoRouterCompressionParams(hydrateAutoRouterCompression(original));

View file

@ -50,14 +50,20 @@ export const hydrateAutoRouterCompression = (litellmParams: {
auto_router_routing_compression?: string | null;
auto_router_model_compression?: string | null;
}): AutoRouterCompressionState => {
const routing = litellmParams.auto_router_routing_compression ?? undefined;
if (routing === undefined) return DEFAULT_AUTO_ROUTER_COMPRESSION;
const storedRouting = litellmParams.auto_router_routing_compression ?? undefined;
const storedModel = litellmParams.auto_router_model_compression ?? undefined;
// An absent model key is no model-hop compression, not same-as-routing: the backend
// reads it as None (policy_from_litellm_params). Hydrating it as same-as-routing
// would make re-saving an unrelated edit write the routing guardrail onto the model
// hop and silently start compressing the model call.
const model = litellmParams.auto_router_model_compression ?? NO_COMPRESSION;
// Only neither key set means the section was never touched. The backend treats
// either key on its own as an authoritative policy (policy_from_litellm_params), so
// reading a model-only config as untouched would hide it from the form and let the
// next save overwrite the stored model hop.
if (storedRouting === undefined && storedModel === undefined) return DEFAULT_AUTO_ROUTER_COMPRESSION;
// An absent key on either hop is no compression for that hop, not same-as-the-other:
// the backend reads it as None. Hydrating it as same-as-routing would make re-saving
// an unrelated edit write one hop's guardrail onto the other.
const routing = storedRouting ?? NO_COMPRESSION;
const model = storedModel ?? NO_COMPRESSION;
const sameAsRouting = model === routing;
return { routing, sameAsRouting, model: sameAsRouting ? undefined : model };
};