mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-22 21:28:12 +02:00
feat(database-migrations): add migration to remove legacy model config tables and remove stale model connection code
This commit is contained in:
parent
50668775f8
commit
bd4a04f2e7
93 changed files with 956 additions and 11442 deletions
|
|
@ -1,96 +0,0 @@
|
|||
import { atomWithMutation } from "jotai-tanstack-query";
|
||||
import { toast } from "sonner";
|
||||
import type {
|
||||
CreateImageGenConfigRequest,
|
||||
CreateImageGenConfigResponse,
|
||||
DeleteImageGenConfigResponse,
|
||||
GetImageGenConfigsResponse,
|
||||
UpdateImageGenConfigRequest,
|
||||
UpdateImageGenConfigResponse,
|
||||
} from "@/contracts/types/new-llm-config.types";
|
||||
import { imageGenConfigApiService } from "@/lib/apis/image-gen-config-api.service";
|
||||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||
import { queryClient } from "@/lib/query-client/client";
|
||||
import { activeSearchSpaceIdAtom } from "../search-spaces/search-space-query.atoms";
|
||||
|
||||
/**
|
||||
* Mutation atom for creating a new ImageGenerationConfig
|
||||
*/
|
||||
export const createImageGenConfigMutationAtom = atomWithMutation((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
mutationKey: ["image-gen-configs", "create"],
|
||||
meta: { suppressGlobalErrorToast: true },
|
||||
enabled: !!searchSpaceId,
|
||||
mutationFn: async (request: CreateImageGenConfigRequest) => {
|
||||
return imageGenConfigApiService.createConfig(request);
|
||||
},
|
||||
onSuccess: (_: CreateImageGenConfigResponse, request: CreateImageGenConfigRequest) => {
|
||||
toast.success(`${request.name} created`);
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: cacheKeys.imageGenConfigs.all(Number(searchSpaceId)),
|
||||
});
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(error.message || "Failed to create image model");
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Mutation atom for updating an existing ImageGenerationConfig
|
||||
*/
|
||||
export const updateImageGenConfigMutationAtom = atomWithMutation((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
mutationKey: ["image-gen-configs", "update"],
|
||||
meta: { suppressGlobalErrorToast: true },
|
||||
enabled: !!searchSpaceId,
|
||||
mutationFn: async (request: UpdateImageGenConfigRequest) => {
|
||||
return imageGenConfigApiService.updateConfig(request);
|
||||
},
|
||||
onSuccess: (_: UpdateImageGenConfigResponse, request: UpdateImageGenConfigRequest) => {
|
||||
toast.success(`${request.data.name ?? "Configuration"} updated`);
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: cacheKeys.imageGenConfigs.all(Number(searchSpaceId)),
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: cacheKeys.imageGenConfigs.byId(request.id),
|
||||
});
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(error.message || "Failed to update image model");
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Mutation atom for deleting an ImageGenerationConfig
|
||||
*/
|
||||
export const deleteImageGenConfigMutationAtom = atomWithMutation((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
mutationKey: ["image-gen-configs", "delete"],
|
||||
meta: { suppressGlobalErrorToast: true },
|
||||
enabled: !!searchSpaceId,
|
||||
mutationFn: async (request: { id: number; name: string }) => {
|
||||
return imageGenConfigApiService.deleteConfig(request.id);
|
||||
},
|
||||
onSuccess: (_: DeleteImageGenConfigResponse, request: { id: number; name: string }) => {
|
||||
toast.success(`${request.name} deleted`);
|
||||
queryClient.setQueryData(
|
||||
cacheKeys.imageGenConfigs.all(Number(searchSpaceId)),
|
||||
(oldData: GetImageGenConfigsResponse | undefined) => {
|
||||
if (!oldData) return oldData;
|
||||
return oldData.filter((config) => config.id !== request.id);
|
||||
}
|
||||
);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(error.message || "Failed to delete image model");
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import { atomWithQuery } from "jotai-tanstack-query";
|
||||
import { imageGenConfigApiService } from "@/lib/apis/image-gen-config-api.service";
|
||||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||
import { activeSearchSpaceIdAtom } from "../search-spaces/search-space-query.atoms";
|
||||
|
||||
/**
|
||||
* Query atom for fetching user-created image gen configs for the active search space
|
||||
*/
|
||||
export const imageGenConfigsAtom = atomWithQuery((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
queryKey: cacheKeys.imageGenConfigs.all(Number(searchSpaceId)),
|
||||
enabled: !!searchSpaceId,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
queryFn: async () => {
|
||||
return imageGenConfigApiService.getConfigs(Number(searchSpaceId));
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Query atom for fetching global image gen configs (from YAML, negative IDs)
|
||||
*/
|
||||
export const globalImageGenConfigsAtom = atomWithQuery(() => {
|
||||
return {
|
||||
queryKey: cacheKeys.imageGenConfigs.global(),
|
||||
staleTime: 10 * 60 * 1000, // 10 minutes - global configs rarely change
|
||||
queryFn: async () => {
|
||||
return imageGenConfigApiService.getGlobalConfigs();
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
import { atomWithMutation } from "jotai-tanstack-query";
|
||||
import { toast } from "sonner";
|
||||
import type {
|
||||
CreateNewLLMConfigRequest,
|
||||
CreateNewLLMConfigResponse,
|
||||
DeleteNewLLMConfigRequest,
|
||||
DeleteNewLLMConfigResponse,
|
||||
GetNewLLMConfigsResponse,
|
||||
UpdateLLMPreferencesRequest,
|
||||
UpdateNewLLMConfigRequest,
|
||||
UpdateNewLLMConfigResponse,
|
||||
} from "@/contracts/types/new-llm-config.types";
|
||||
import { newLLMConfigApiService } from "@/lib/apis/new-llm-config-api.service";
|
||||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||
import { queryClient } from "@/lib/query-client/client";
|
||||
import { activeSearchSpaceIdAtom } from "../search-spaces/search-space-query.atoms";
|
||||
|
||||
/**
|
||||
* Mutation atom for creating a new NewLLMConfig
|
||||
*/
|
||||
export const createNewLLMConfigMutationAtom = atomWithMutation((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
mutationKey: ["new-llm-configs", "create"],
|
||||
meta: { suppressGlobalErrorToast: true },
|
||||
enabled: !!searchSpaceId,
|
||||
mutationFn: async (request: CreateNewLLMConfigRequest) => {
|
||||
return newLLMConfigApiService.createConfig(request);
|
||||
},
|
||||
onSuccess: (_: CreateNewLLMConfigResponse, request: CreateNewLLMConfigRequest) => {
|
||||
toast.success(`${request.name} created`);
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: cacheKeys.newLLMConfigs.all(Number(searchSpaceId)),
|
||||
});
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(error.message || "Failed to create model");
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Mutation atom for updating an existing NewLLMConfig
|
||||
*/
|
||||
export const updateNewLLMConfigMutationAtom = atomWithMutation((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
mutationKey: ["new-llm-configs", "update"],
|
||||
meta: { suppressGlobalErrorToast: true },
|
||||
enabled: !!searchSpaceId,
|
||||
mutationFn: async (request: UpdateNewLLMConfigRequest) => {
|
||||
return newLLMConfigApiService.updateConfig(request);
|
||||
},
|
||||
onSuccess: (_: UpdateNewLLMConfigResponse, request: UpdateNewLLMConfigRequest) => {
|
||||
toast.success(`${request.data.name ?? "Configuration"} updated`);
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: cacheKeys.newLLMConfigs.all(Number(searchSpaceId)),
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: cacheKeys.newLLMConfigs.byId(request.id),
|
||||
});
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(error.message || "Failed to update");
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Mutation atom for deleting a NewLLMConfig
|
||||
*/
|
||||
export const deleteNewLLMConfigMutationAtom = atomWithMutation((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
mutationKey: ["new-llm-configs", "delete"],
|
||||
meta: { suppressGlobalErrorToast: true },
|
||||
enabled: !!searchSpaceId,
|
||||
mutationFn: async (request: DeleteNewLLMConfigRequest & { name: string }) => {
|
||||
return newLLMConfigApiService.deleteConfig({ id: request.id });
|
||||
},
|
||||
onSuccess: (
|
||||
_: DeleteNewLLMConfigResponse,
|
||||
request: DeleteNewLLMConfigRequest & { name: string }
|
||||
) => {
|
||||
toast.success(`${request.name} deleted`);
|
||||
queryClient.setQueryData(
|
||||
cacheKeys.newLLMConfigs.all(Number(searchSpaceId)),
|
||||
(oldData: GetNewLLMConfigsResponse | undefined) => {
|
||||
if (!oldData) return oldData;
|
||||
return oldData.filter((config) => config.id !== request.id);
|
||||
}
|
||||
);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(error.message || "Failed to delete");
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Mutation atom for updating LLM preferences (role assignments)
|
||||
*/
|
||||
export const updateLLMPreferencesMutationAtom = atomWithMutation((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
mutationKey: ["llm-preferences", "update"],
|
||||
meta: { suppressGlobalErrorToast: true },
|
||||
enabled: !!searchSpaceId,
|
||||
mutationFn: async (request: UpdateLLMPreferencesRequest) => {
|
||||
return newLLMConfigApiService.updateLLMPreferences(request);
|
||||
},
|
||||
onSuccess: (_data, request: UpdateLLMPreferencesRequest) => {
|
||||
queryClient.setQueryData(
|
||||
cacheKeys.newLLMConfigs.preferences(Number(searchSpaceId)),
|
||||
(old: Record<string, unknown> | undefined) => ({ ...old, ...request.data })
|
||||
);
|
||||
// Automation eligibility is derived from these model preferences
|
||||
// (agent/image/vision). Invalidate it so the automations gate alert
|
||||
// reflects the new selection without a manual refresh.
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: cacheKeys.automations.modelEligibility(Number(searchSpaceId)),
|
||||
});
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(error.message || "Failed to update LLM preferences");
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
import { atomWithQuery } from "jotai-tanstack-query";
|
||||
import type { LLMModel } from "@/contracts/enums/llm-models";
|
||||
import { LLM_MODELS } from "@/contracts/enums/llm-models";
|
||||
import { newLLMConfigApiService } from "@/lib/apis/new-llm-config-api.service";
|
||||
import { getBearerToken } from "@/lib/auth-utils";
|
||||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||
import { activeSearchSpaceIdAtom } from "../search-spaces/search-space-query.atoms";
|
||||
|
||||
/**
|
||||
* Query atom for fetching all NewLLMConfigs for the active search space
|
||||
*/
|
||||
export const newLLMConfigsAtom = atomWithQuery((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
queryKey: cacheKeys.newLLMConfigs.all(Number(searchSpaceId)),
|
||||
enabled: !!searchSpaceId,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
queryFn: async () => {
|
||||
return newLLMConfigApiService.getConfigs({
|
||||
search_space_id: Number(searchSpaceId),
|
||||
});
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Query atom for fetching global NewLLMConfigs (from YAML, negative IDs)
|
||||
*/
|
||||
export const globalNewLLMConfigsAtom = atomWithQuery(() => {
|
||||
return {
|
||||
queryKey: cacheKeys.newLLMConfigs.global(),
|
||||
staleTime: 10 * 60 * 1000, // 10 minutes - global configs rarely change
|
||||
enabled: !!getBearerToken(),
|
||||
queryFn: async () => {
|
||||
return newLLMConfigApiService.getGlobalConfigs();
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Query atom for fetching LLM preferences (role assignments) for the active search space
|
||||
*/
|
||||
export const llmPreferencesAtom = atomWithQuery((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
queryKey: cacheKeys.newLLMConfigs.preferences(Number(searchSpaceId)),
|
||||
enabled: !!searchSpaceId,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
queryFn: async () => {
|
||||
return newLLMConfigApiService.getLLMPreferences(Number(searchSpaceId));
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Query atom for fetching default system instructions template
|
||||
*/
|
||||
export const defaultSystemInstructionsAtom = atomWithQuery(() => {
|
||||
return {
|
||||
queryKey: cacheKeys.newLLMConfigs.defaultInstructions(),
|
||||
staleTime: 60 * 60 * 1000, // 1 hour - this rarely changes
|
||||
queryFn: async () => {
|
||||
return newLLMConfigApiService.getDefaultSystemInstructions();
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Query atom for the dynamic model catalogue.
|
||||
* Fetched from the backend (which proxies OpenRouter's public API).
|
||||
* Falls back to the static hardcoded list on error.
|
||||
*/
|
||||
export const modelListAtom = atomWithQuery(() => {
|
||||
return {
|
||||
queryKey: cacheKeys.newLLMConfigs.modelList(),
|
||||
staleTime: 60 * 60 * 1000, // 1 hour - models don't change often
|
||||
placeholderData: LLM_MODELS,
|
||||
queryFn: async (): Promise<LLMModel[]> => {
|
||||
const data = await newLLMConfigApiService.getModels();
|
||||
const dynamicModels = data.map((m) => ({
|
||||
value: m.value,
|
||||
label: m.label,
|
||||
provider: m.provider,
|
||||
contextWindow: m.context_window ?? undefined,
|
||||
}));
|
||||
|
||||
// Providers covered by the dynamic API (from OpenRouter mapping).
|
||||
// For uncovered providers (Ollama, Groq, Bedrock, etc.) keep the
|
||||
// hand-curated static suggestions so users still see model options.
|
||||
const coveredProviders = new Set(dynamicModels.map((m) => m.provider));
|
||||
const staticFallbacks = LLM_MODELS.filter((m) => !coveredProviders.has(m.provider));
|
||||
|
||||
return [...dynamicModels, ...staticFallbacks];
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
import { atomWithMutation } from "jotai-tanstack-query";
|
||||
import { toast } from "sonner";
|
||||
import type {
|
||||
CreateVisionLLMConfigRequest,
|
||||
CreateVisionLLMConfigResponse,
|
||||
DeleteVisionLLMConfigResponse,
|
||||
GetVisionLLMConfigsResponse,
|
||||
UpdateVisionLLMConfigRequest,
|
||||
UpdateVisionLLMConfigResponse,
|
||||
} from "@/contracts/types/new-llm-config.types";
|
||||
import { visionLLMConfigApiService } from "@/lib/apis/vision-llm-config-api.service";
|
||||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||
import { queryClient } from "@/lib/query-client/client";
|
||||
import { activeSearchSpaceIdAtom } from "../search-spaces/search-space-query.atoms";
|
||||
|
||||
export const createVisionLLMConfigMutationAtom = atomWithMutation((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
mutationKey: ["vision-llm-configs", "create"],
|
||||
meta: { suppressGlobalErrorToast: true },
|
||||
enabled: !!searchSpaceId,
|
||||
mutationFn: async (request: CreateVisionLLMConfigRequest) => {
|
||||
return visionLLMConfigApiService.createConfig(request);
|
||||
},
|
||||
onSuccess: (_: CreateVisionLLMConfigResponse, request: CreateVisionLLMConfigRequest) => {
|
||||
toast.success(`${request.name} created`);
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: cacheKeys.visionLLMConfigs.all(Number(searchSpaceId)),
|
||||
});
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(error.message || "Failed to create vision model");
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const updateVisionLLMConfigMutationAtom = atomWithMutation((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
mutationKey: ["vision-llm-configs", "update"],
|
||||
meta: { suppressGlobalErrorToast: true },
|
||||
enabled: !!searchSpaceId,
|
||||
mutationFn: async (request: UpdateVisionLLMConfigRequest) => {
|
||||
return visionLLMConfigApiService.updateConfig(request);
|
||||
},
|
||||
onSuccess: (_: UpdateVisionLLMConfigResponse, request: UpdateVisionLLMConfigRequest) => {
|
||||
toast.success(`${request.data.name ?? "Configuration"} updated`);
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: cacheKeys.visionLLMConfigs.all(Number(searchSpaceId)),
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: cacheKeys.visionLLMConfigs.byId(request.id),
|
||||
});
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(error.message || "Failed to update vision model");
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const deleteVisionLLMConfigMutationAtom = atomWithMutation((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
mutationKey: ["vision-llm-configs", "delete"],
|
||||
meta: { suppressGlobalErrorToast: true },
|
||||
enabled: !!searchSpaceId,
|
||||
mutationFn: async (request: { id: number; name: string }) => {
|
||||
return visionLLMConfigApiService.deleteConfig(request.id);
|
||||
},
|
||||
onSuccess: (_: DeleteVisionLLMConfigResponse, request: { id: number; name: string }) => {
|
||||
toast.success(`${request.name} deleted`);
|
||||
queryClient.setQueryData(
|
||||
cacheKeys.visionLLMConfigs.all(Number(searchSpaceId)),
|
||||
(oldData: GetVisionLLMConfigsResponse | undefined) => {
|
||||
if (!oldData) return oldData;
|
||||
return oldData.filter((config) => config.id !== request.id);
|
||||
}
|
||||
);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(error.message || "Failed to delete vision model");
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
import { atomWithQuery } from "jotai-tanstack-query";
|
||||
import type { LLMModel } from "@/contracts/enums/llm-models";
|
||||
import { VISION_MODELS } from "@/contracts/enums/vision-providers";
|
||||
import { visionLLMConfigApiService } from "@/lib/apis/vision-llm-config-api.service";
|
||||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||
import { activeSearchSpaceIdAtom } from "../search-spaces/search-space-query.atoms";
|
||||
|
||||
export const visionLLMConfigsAtom = atomWithQuery((get) => {
|
||||
const searchSpaceId = get(activeSearchSpaceIdAtom);
|
||||
|
||||
return {
|
||||
queryKey: cacheKeys.visionLLMConfigs.all(Number(searchSpaceId)),
|
||||
enabled: !!searchSpaceId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
queryFn: async () => {
|
||||
return visionLLMConfigApiService.getConfigs(Number(searchSpaceId));
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const globalVisionLLMConfigsAtom = atomWithQuery(() => {
|
||||
return {
|
||||
queryKey: cacheKeys.visionLLMConfigs.global(),
|
||||
staleTime: 10 * 60 * 1000,
|
||||
queryFn: async () => {
|
||||
return visionLLMConfigApiService.getGlobalConfigs();
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const visionModelListAtom = atomWithQuery(() => {
|
||||
return {
|
||||
queryKey: cacheKeys.visionLLMConfigs.modelList(),
|
||||
staleTime: 60 * 60 * 1000,
|
||||
placeholderData: VISION_MODELS,
|
||||
queryFn: async (): Promise<LLMModel[]> => {
|
||||
const data = await visionLLMConfigApiService.getModels();
|
||||
const dynamicModels = data.map((m) => ({
|
||||
value: m.value,
|
||||
label: m.label,
|
||||
provider: m.provider,
|
||||
contextWindow: m.context_window ?? undefined,
|
||||
}));
|
||||
|
||||
const coveredProviders = new Set(dynamicModels.map((m) => m.provider));
|
||||
const staticFallbacks = VISION_MODELS.filter((m) => !coveredProviders.has(m.provider));
|
||||
|
||||
return [...dynamicModels, ...staticFallbacks];
|
||||
},
|
||||
};
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue