diff --git a/site/src/pages/AISettingsPage/ModelsPage/components/ModelForm.stories.tsx b/site/src/pages/AISettingsPage/ModelsPage/components/ModelForm.stories.tsx index 53dc60d4e0..6af8ea1529 100644 --- a/site/src/pages/AISettingsPage/ModelsPage/components/ModelForm.stories.tsx +++ b/site/src/pages/AISettingsPage/ModelsPage/components/ModelForm.stories.tsx @@ -183,11 +183,33 @@ export const EditSaveSubmits: Story = { play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); const save = canvas.getByRole("button", { name: /^update model$/i }); + // Update is disabled until the user makes a change. + await expect(save).toBeDisabled(); + await userEvent.type(canvas.getByLabelText(/display name/i), " (updated)"); + await expect(save).toBeEnabled(); await userEvent.click(save); await expect(args.onUpdateModel).toHaveBeenCalledTimes(1); }, }; +export const EditUpdateDisabledUntilDirty: Story = { + args: { + editingModel: mockGPT5, + onDeleteModel: fn(async () => undefined), + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const save = canvas.getByRole("button", { name: /^update model$/i }); + await expect(save).toBeDisabled(); + const displayName = canvas.getByLabelText(/display name/i); + await userEvent.type(displayName, " (edited)"); + await expect(save).toBeEnabled(); + await userEvent.clear(displayName); + await userEvent.type(displayName, mockGPT5.display_name); + await expect(save).toBeDisabled(); + }, +}; + export const CostTrackingExpanded: Story = { args: { editingModel: mockGPT5, diff --git a/site/src/pages/AISettingsPage/ModelsPage/components/ModelForm.tsx b/site/src/pages/AISettingsPage/ModelsPage/components/ModelForm.tsx index e20ac5673d..1f16c44d31 100644 --- a/site/src/pages/AISettingsPage/ModelsPage/components/ModelForm.tsx +++ b/site/src/pages/AISettingsPage/ModelsPage/components/ModelForm.tsx @@ -235,7 +235,8 @@ export const ModelForm: FC = ({ !hasFieldErrors && form.values.model.trim().length > 0 && contextLimitValid && - compressionThresholdValid; + compressionThresholdValid && + (!isEditing || form.dirty); const handleConfirmReplaceDefault = () => { replaceDefaultConfirmedRef.current = true;