refactor: update LLM configuration terminology and enhance user feedback messages for improved clarity

This commit is contained in:
Anish Sarkar 2026-03-29 19:04:09 +05:30
parent ba926bbcc9
commit a5f41cfd8e
4 changed files with 53 additions and 59 deletions

View file

@ -24,7 +24,7 @@ SurfSense 现已支持以下国产 LLM
1. 登录 SurfSense Dashboard 1. 登录 SurfSense Dashboard
2. 进入 **Settings****API Keys** (或 **LLM Configurations**) 2. 进入 **Settings****API Keys** (或 **LLM Configurations**)
3. 点击 **Add New Configuration** 3. 点击 **Add LLM Model**
4. 从 **Provider** 下拉菜单中选择你的国产 LLM 提供商 4. 从 **Provider** 下拉菜单中选择你的国产 LLM 提供商
5. 填写必填字段(见下方各提供商详细配置) 5. 填写必填字段(见下方各提供商详细配置)
6. 点击 **Save** 6. 点击 **Save**

View file

@ -2,7 +2,9 @@ import { atomWithMutation } from "jotai-tanstack-query";
import { toast } from "sonner"; import { toast } from "sonner";
import type { import type {
CreateNewLLMConfigRequest, CreateNewLLMConfigRequest,
CreateNewLLMConfigResponse,
DeleteNewLLMConfigRequest, DeleteNewLLMConfigRequest,
DeleteNewLLMConfigResponse,
GetNewLLMConfigsResponse, GetNewLLMConfigsResponse,
UpdateLLMPreferencesRequest, UpdateLLMPreferencesRequest,
UpdateNewLLMConfigRequest, UpdateNewLLMConfigRequest,
@ -25,14 +27,14 @@ export const createNewLLMConfigMutationAtom = atomWithMutation((get) => {
mutationFn: async (request: CreateNewLLMConfigRequest) => { mutationFn: async (request: CreateNewLLMConfigRequest) => {
return newLLMConfigApiService.createConfig(request); return newLLMConfigApiService.createConfig(request);
}, },
onSuccess: () => { onSuccess: (_: CreateNewLLMConfigResponse, request: CreateNewLLMConfigRequest) => {
toast.success("LLM model created"); toast.success(`${request.name} created`);
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: cacheKeys.newLLMConfigs.all(Number(searchSpaceId)), queryKey: cacheKeys.newLLMConfigs.all(Number(searchSpaceId)),
}); });
}, },
onError: (error: Error) => { onError: (error: Error) => {
toast.error(error.message || "Failed to create configuration"); toast.error(error.message || "Failed to create LLM model");
}, },
}; };
}); });
@ -50,7 +52,7 @@ export const updateNewLLMConfigMutationAtom = atomWithMutation((get) => {
return newLLMConfigApiService.updateConfig(request); return newLLMConfigApiService.updateConfig(request);
}, },
onSuccess: (_: UpdateNewLLMConfigResponse, request: UpdateNewLLMConfigRequest) => { onSuccess: (_: UpdateNewLLMConfigResponse, request: UpdateNewLLMConfigRequest) => {
toast.success("LLM model updated"); toast.success(`${request.data.name ?? "Configuration"} updated`);
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: cacheKeys.newLLMConfigs.all(Number(searchSpaceId)), queryKey: cacheKeys.newLLMConfigs.all(Number(searchSpaceId)),
}); });
@ -59,7 +61,7 @@ export const updateNewLLMConfigMutationAtom = atomWithMutation((get) => {
}); });
}, },
onError: (error: Error) => { onError: (error: Error) => {
toast.error(error.message || "Failed to update configuration"); toast.error(error.message || "Failed to update");
}, },
}; };
}); });
@ -73,11 +75,11 @@ export const deleteNewLLMConfigMutationAtom = atomWithMutation((get) => {
return { return {
mutationKey: ["new-llm-configs", "delete"], mutationKey: ["new-llm-configs", "delete"],
enabled: !!searchSpaceId, enabled: !!searchSpaceId,
mutationFn: async (request: DeleteNewLLMConfigRequest) => { mutationFn: async (request: DeleteNewLLMConfigRequest & { name: string }) => {
return newLLMConfigApiService.deleteConfig(request); return newLLMConfigApiService.deleteConfig({ id: request.id });
}, },
onSuccess: (_, request: DeleteNewLLMConfigRequest) => { onSuccess: (_: DeleteNewLLMConfigResponse, request: DeleteNewLLMConfigRequest & { name: string }) => {
toast.success("LLM model deleted"); toast.success(`${request.name} deleted`);
queryClient.setQueryData( queryClient.setQueryData(
cacheKeys.newLLMConfigs.all(Number(searchSpaceId)), cacheKeys.newLLMConfigs.all(Number(searchSpaceId)),
(oldData: GetNewLLMConfigsResponse | undefined) => { (oldData: GetNewLLMConfigsResponse | undefined) => {
@ -87,7 +89,7 @@ export const deleteNewLLMConfigMutationAtom = atomWithMutation((get) => {
); );
}, },
onError: (error: Error) => { onError: (error: Error) => {
toast.error(error.message || "Failed to delete configuration"); toast.error(error.message || "Failed to delete");
}, },
}; };
}); });

View file

@ -116,7 +116,7 @@ export function ModelConfigManager({ searchSpaceId }: ModelConfigManagerProps) {
const handleDelete = async () => { const handleDelete = async () => {
if (!configToDelete) return; if (!configToDelete) return;
try { try {
await deleteConfig({ id: configToDelete.id }); await deleteConfig({ id: configToDelete.id, name: configToDelete.name });
setConfigToDelete(null); setConfigToDelete(null);
} catch { } catch {
// Error handled by mutation state // Error handled by mutation state
@ -431,12 +431,11 @@ export function ModelConfigManager({ searchSpaceId }: ModelConfigManagerProps) {
open={!!configToDelete} open={!!configToDelete}
onOpenChange={(open) => !open && setConfigToDelete(null)} onOpenChange={(open) => !open && setConfigToDelete(null)}
> >
<AlertDialogContent> <AlertDialogContent className="select-none">
<AlertDialogHeader> <AlertDialogHeader>
<AlertDialogTitle className="flex items-center gap-2"> <AlertDialogTitle>
<Trash2 className="h-5 w-5 text-destructive" /> Delete LLM Model
Delete Configuration </AlertDialogTitle>
</AlertDialogTitle>
<AlertDialogDescription> <AlertDialogDescription>
Are you sure you want to delete{" "} Are you sure you want to delete{" "}
<span className="font-semibold text-foreground">{configToDelete?.name}</span>? This <span className="font-semibold text-foreground">{configToDelete?.name}</span>? This
@ -450,17 +449,14 @@ export function ModelConfigManager({ searchSpaceId }: ModelConfigManagerProps) {
disabled={isDeleting} disabled={isDeleting}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90" className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
> >
{isDeleting ? ( {isDeleting ? (
<> <>
<Spinner size="sm" className="mr-2" /> <Spinner size="sm" className="mr-2" />
Deleting Deleting
</> </>
) : ( ) : (
<> "Delete"
<Trash2 className="mr-2 h-4 w-4" /> )}
Delete
</>
)}
</AlertDialogAction> </AlertDialogAction>
</AlertDialogFooter> </AlertDialogFooter>
</AlertDialogContent> </AlertDialogContent>

View file

@ -379,39 +379,35 @@ export function ModelConfigDialog({
Cancel Cancel
</Button> </Button>
{mode === "create" || (!isGlobal && !isAutoMode && config) ? ( {mode === "create" || (!isGlobal && !isAutoMode && config) ? (
<Button <Button
type="submit" type="submit"
form="model-config-form" form="model-config-form"
disabled={isSubmitting} disabled={isSubmitting}
className="text-sm h-9 min-w-[120px]" className="relative text-sm h-9 min-w-[120px]"
> >
{isSubmitting ? ( <span className={isSubmitting ? "opacity-0" : ""}>
<> {mode === "edit" ? "Save Changes" : "Create & Use"}
<Spinner size="sm" /> </span>
{mode === "edit" ? "Saving" : "Creating"} {isSubmitting && <Spinner size="sm" className="absolute" />}
</> </Button>
) : mode === "edit" ? (
"Save Changes"
) : (
"Create & Use"
)}
</Button>
) : isAutoMode ? ( ) : isAutoMode ? (
<Button <Button
className="text-sm h-9 gap-2 bg-gradient-to-r from-violet-500 to-purple-600 hover:from-violet-600 hover:to-purple-700" className="relative text-sm h-9 bg-gradient-to-r from-violet-500 to-purple-600 hover:from-violet-600 hover:to-purple-700"
onClick={handleUseGlobalConfig} onClick={handleUseGlobalConfig}
disabled={isSubmitting} disabled={isSubmitting}
> >
{isSubmitting ? "Loading..." : "Use Auto Mode"} <span className={isSubmitting ? "opacity-0" : ""}>Use Auto Mode</span>
</Button> {isSubmitting && <Spinner size="sm" className="absolute" />}
</Button>
) : isGlobal && config ? ( ) : isGlobal && config ? (
<Button <Button
className="text-sm h-9 gap-2" className="relative text-sm h-9"
onClick={handleUseGlobalConfig} onClick={handleUseGlobalConfig}
disabled={isSubmitting} disabled={isSubmitting}
> >
{isSubmitting ? "Loading..." : "Use This Model"} <span className={isSubmitting ? "opacity-0" : ""}>Use This Model</span>
</Button> {isSubmitting && <Spinner size="sm" className="absolute" />}
</Button>
) : null} ) : null}
</div> </div>
</DialogContent> </DialogContent>