mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-02 10:21:16 +08:00
feat: add session deletion with per-provider cleanup and path safety
Add delete_session Tauri command dispatching to provider-specific deletion logic for all 5 providers (Claude, Codex, Gemini, OpenCode, OpenClaw). Includes path traversal protection via canonicalize + starts_with validation, session ID verification against file contents, frontend confirmation dialog with optimistic cache updates, i18n keys (zh/en/ja), and component tests.
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { toast } from "sonner";
|
||||
import { providersApi, settingsApi, type AppId } from "@/lib/api";
|
||||
import { providersApi, sessionsApi, settingsApi, type AppId } from "@/lib/api";
|
||||
import type { DeleteSessionOptions } from "@/lib/api/sessions";
|
||||
import type { SwitchResult } from "@/lib/api/providers";
|
||||
import type { Provider, Settings } from "@/types";
|
||||
import type { Provider, SessionMeta, Settings } from "@/types";
|
||||
import { extractErrorMessage } from "@/utils/errorUtils";
|
||||
import { generateUUID } from "@/utils/uuid";
|
||||
import { openclawKeys } from "@/hooks/useOpenClaw";
|
||||
@@ -267,6 +268,50 @@ export const useSwitchProviderMutation = (appId: AppId) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteSessionMutation = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (input: DeleteSessionOptions) => {
|
||||
await sessionsApi.delete(input);
|
||||
return input;
|
||||
},
|
||||
onSuccess: async (input) => {
|
||||
queryClient.setQueryData<SessionMeta[]>(["sessions"], (current) =>
|
||||
(current ?? []).filter(
|
||||
(session) =>
|
||||
!(
|
||||
session.providerId === input.providerId &&
|
||||
session.sessionId === input.sessionId &&
|
||||
session.sourcePath === input.sourcePath
|
||||
),
|
||||
),
|
||||
);
|
||||
queryClient.removeQueries({
|
||||
queryKey: ["sessionMessages", input.providerId, input.sourcePath],
|
||||
});
|
||||
|
||||
await queryClient.invalidateQueries({ queryKey: ["sessions"] });
|
||||
|
||||
toast.success(
|
||||
t("sessionManager.sessionDeleted", {
|
||||
defaultValue: "会话已删除",
|
||||
}),
|
||||
);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
const detail = extractErrorMessage(error) || t("common.unknown");
|
||||
toast.error(
|
||||
t("sessionManager.deleteFailed", {
|
||||
defaultValue: "删除会话失败: {{error}}",
|
||||
error: detail,
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useSaveSettingsMutation = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user