From 3dd41670ad1fac431a946a606c1579ecfe022ece Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Tue, 14 Jul 2026 00:15:21 +0530 Subject: [PATCH] feat(model-connections): warn when a mutation disables workspace chat --- .../model-connections-mutation.atoms.ts | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/surfsense_web/atoms/model-connections/model-connections-mutation.atoms.ts b/surfsense_web/atoms/model-connections/model-connections-mutation.atoms.ts index c30d65587..77fccc1d1 100644 --- a/surfsense_web/atoms/model-connections/model-connections-mutation.atoms.ts +++ b/surfsense_web/atoms/model-connections/model-connections-mutation.atoms.ts @@ -30,6 +30,24 @@ function invalidateModelConnections(workspaceId: number) { }); } +// After a mutation that can remove the workspace's last usable chat model, +// surface immediate feedback. The composer's inline notice covers the state on +// its own; this just makes the consequence obvious at the moment of the action. +async function warnIfWorkspaceChatDisabled(workspaceId: number) { + if (workspaceId <= 0) return; + try { + const status = await queryClient.fetchQuery({ + queryKey: cacheKeys.modelConnections.setupStatus(workspaceId), + queryFn: () => modelConnectionsApiService.getLlmSetupStatus(workspaceId), + }); + if (status?.status === "needs_setup") { + toast.warning("Chat is now disabled. Connect a language model to start chatting again."); + } + } catch { + // Non-fatal: the inline composer notice still reflects the state. + } +} + function upsertModelConnection(workspaceId: number, connection: ConnectionRead) { queryClient.setQueryData( cacheKeys.modelConnections.all(workspaceId), @@ -81,9 +99,10 @@ export const deleteModelConnectionMutationAtom = atomWithMutation((get) => { return { mutationKey: ["model-connections", "delete"], mutationFn: (id: number) => modelConnectionsApiService.deleteConnection(id), - onSuccess: () => { + onSuccess: async () => { toast.success("Connection deleted"); invalidateModelConnections(workspaceId); + await warnIfWorkspaceChatDisabled(workspaceId); }, onError: (error: Error) => toast.error(error.message || "Failed to delete connection"), }; @@ -182,7 +201,10 @@ export const bulkUpdateModelsMutationAtom = atomWithMutation((get) => { mutationKey: ["models", "bulk-update"], mutationFn: ({ connectionId, data }: { connectionId: number; data: ModelsBulkUpdateRequest }) => modelConnectionsApiService.bulkUpdateModels(connectionId, data), - onSuccess: () => invalidateModelConnections(workspaceId), + onSuccess: async () => { + invalidateModelConnections(workspaceId); + await warnIfWorkspaceChatDisabled(workspaceId); + }, onError: (error: Error) => toast.error(error.message || "Failed to update models"), }; });