From be9b855783cfa2bac164620d426a06b3beb41f2b Mon Sep 17 00:00:00 2001 From: weichen Date: Fri, 18 Sep 2026 03:44:08 +0000 Subject: [PATCH] =?UTF-8?q?fix(web):=20=E7=99=BB=E5=87=BA=E4=B8=BB?= =?UTF-8?q?=E5=8A=A8=20abort=20=E6=89=80=E6=9C=89=E4=BC=9A=E8=AF=9D?= =?UTF-8?q?=E5=9C=A8=E9=80=94=E6=B5=81=EF=BC=88R-8=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 abortAllSessions;logout 先中止全会话再清 session。 Co-authored-by: Cursor --- web/src/App.tsx | 18 +++++++++++------- web/src/hooks/useTaskRunStream.ts | 10 ++++++++++ web/src/hooks/useTurnRuntime.ts | 13 +++++++++++++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 3df7ab6c..8fca6e4d 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -602,13 +602,7 @@ export default function App() { }; }, [session, sessionValidated, currentUser.id, projects]); - const handleLogout = () => { - void authClient.logout().finally(() => { - setSession(null); - setCapabilities([]); - setSessionValidated(false); - }); - }; + // handleLogout 定义在 turnRuntime/taskRunStream hook 之后,便于 abort 全会话在途流。 // 核心功能权限计算 const canCreateProject = useMemo(() => { @@ -2821,6 +2815,16 @@ export default function App() { } }; + const handleLogout = () => { + turnRuntime.abortAllSessions(); + taskRunStream.abortAllSessions(); + void authClient.logout().finally(() => { + setSession(null); + setCapabilities([]); + setSessionValidated(false); + }); + }; + // 发送消息与对话驱动双轨逻辑 const handleSendMessage = async ( text: string, diff --git a/web/src/hooks/useTaskRunStream.ts b/web/src/hooks/useTaskRunStream.ts index d919e95a..ba678491 100644 --- a/web/src/hooks/useTaskRunStream.ts +++ b/web/src/hooks/useTaskRunStream.ts @@ -89,6 +89,15 @@ export function useTaskRunStream(activeSessionId: string) { [getRuntime, notify], ); + const abortAllSessions = useCallback(() => { + for (const rt of storeRef.current.sessions.values()) { + rt.controller?.abort(); + rt.controller = null; + rt.thinking = false; + } + notify(); + }, [notify]); + return { runtime: snapshot, isThinking: snapshot.thinking, @@ -98,5 +107,6 @@ export function useTaskRunStream(activeSessionId: string) { setRunId, setController, abortSession, + abortAllSessions, }; } diff --git a/web/src/hooks/useTurnRuntime.ts b/web/src/hooks/useTurnRuntime.ts index cf66589e..7b95fc8e 100644 --- a/web/src/hooks/useTurnRuntime.ts +++ b/web/src/hooks/useTurnRuntime.ts @@ -108,6 +108,18 @@ export function useTurnRuntime(activeSessionId: string) { notify(); }, [activeSessionId, getSessionMap, notify]); + const abortAllSessions = useCallback(() => { + for (const sessionMap of storeRef.current.turns.values()) { + for (const rt of sessionMap.values()) { + if (rt.status === 'pending' || rt.status === 'streaming') { + rt.controller.abort(); + rt.status = 'cancelled'; + } + } + } + notify(); + }, [notify]); + const isSessionThinking = useCallback( (sessionId: string) => { const sessionMap = storeRef.current.turns.get(sessionId); @@ -138,6 +150,7 @@ export function useTurnRuntime(activeSessionId: string) { removeTurn, abortTurn, abortActiveSessionTurns, + abortAllSessions, isThinking, isSessionThinking, getTurn,