mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-14 23:21:35 +00:00
fix(ui): gate vector_store_ids on isFieldTouched too
Completing the send-only-what-changed audit: vector_store_ids was still
value-conditional, so a model that has vector stores re-sent them on every
save. It's now touch-gated like the other fields while preserving the
tri-state clear (a touched-but-emptied selection sends [] to clear on the
backend, an untouched one is omitted so the stored value is kept).
cache_control_injection_points is deliberately left ungated: CacheControlSettings
writes it through form.setFieldValue("litellm_extra_params", ...), which never
marks a field touched, so its real edits already ride the textarea value-diff;
an isFieldTouched gate there would silently drop cache-control changes.
This commit is contained in:
parent
807dde81d6
commit
0438b26a24
2 changed files with 41 additions and 7 deletions
|
|
@ -607,6 +607,45 @@ describe("ModelInfoView", () => {
|
|||
expect(updatePayload.litellm_params).not.toHaveProperty("vector_store_ids");
|
||||
});
|
||||
|
||||
it("does not re-send vector_store_ids when the user changes an unrelated field", async () => {
|
||||
const modelWithVectorStores = {
|
||||
...defaultModelData,
|
||||
litellm_params: {
|
||||
model: "gpt-4",
|
||||
api_base: "https://api.openai.com/v1",
|
||||
custom_llm_provider: "openai",
|
||||
vector_store_ids: ["vs_existing"],
|
||||
},
|
||||
};
|
||||
mockUseModelsInfo.mockReturnValue({
|
||||
data: { data: [modelWithVectorStores] },
|
||||
isLoading: false,
|
||||
error: null,
|
||||
});
|
||||
mockModelInfoV1Call.mockResolvedValue({ data: [modelWithVectorStores] });
|
||||
|
||||
const user = userEvent.setup();
|
||||
render(<ModelInfoView {...DEFAULT_ADMIN_PROPS} />, { wrapper });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole("button", { name: /edit settings/i })).toBeInTheDocument();
|
||||
});
|
||||
await user.click(screen.getByRole("button", { name: /edit settings/i }));
|
||||
|
||||
const tpmInput = await screen.findByPlaceholderText("Enter TPM");
|
||||
await user.type(tpmInput, "100");
|
||||
|
||||
await user.click(screen.getByRole("button", { name: /save changes/i }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockModelPatchUpdateCall).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
const updatePayload = mockModelPatchUpdateCall.mock.calls[0][1];
|
||||
expect(updatePayload.litellm_params).toHaveProperty("tpm");
|
||||
expect(updatePayload.litellm_params).not.toHaveProperty("vector_store_ids");
|
||||
});
|
||||
|
||||
it("should not include input_cost_per_token or output_cost_per_token in update payload when user does not touch cost fields", async () => {
|
||||
// Regression: editing a model without touching cost fields used to inject
|
||||
// input_cost_per_token: 0 and output_cost_per_token: 0 into litellm_params,
|
||||
|
|
|
|||
|
|
@ -477,13 +477,8 @@ export default function ModelInfoView({
|
|||
if (form.isFieldTouched("guardrails")) {
|
||||
updatedLitellmParams.guardrails = values.guardrails;
|
||||
}
|
||||
if (values.vector_store_ids?.length > 0) {
|
||||
updatedLitellmParams.vector_store_ids = values.vector_store_ids;
|
||||
} else if (values.vector_store_ids !== undefined) {
|
||||
// User explicitly cleared previously-set vector stores — send [] to clear on backend
|
||||
updatedLitellmParams.vector_store_ids = [];
|
||||
} else {
|
||||
delete updatedLitellmParams.vector_store_ids;
|
||||
if (form.isFieldTouched("vector_store_ids")) {
|
||||
updatedLitellmParams.vector_store_ids = values.vector_store_ids?.length > 0 ? values.vector_store_ids : [];
|
||||
}
|
||||
|
||||
// Handle cache control settings
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue