From f09f8f2b03d05f1fd38d5766596e0e0987de4420 Mon Sep 17 00:00:00 2001 From: kurihada Date: Mon, 15 Dec 2025 18:40:07 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fix(core): 修复 todoManager 未初始化导致待办工具无法使用 - fix(core): 为 LSP 初始化添加 10 秒超时,防止 write_file 卡住 - fix(ui): 停止对话时保留已流式输出的内容 --- packages/core/src/core/agent.ts | 3 +++ packages/core/src/lsp/client.ts | 11 ++++++++--- packages/ui/src/hooks/useChat.ts | 21 ++++++++++++++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/core/src/core/agent.ts b/packages/core/src/core/agent.ts index f37d4fb..6fd90ca 100644 --- a/packages/core/src/core/agent.ts +++ b/packages/core/src/core/agent.ts @@ -27,6 +27,7 @@ import { type DoomLoopDetector, DOOM_LOOP_WARNING, } from './doom-loop.js'; +import { todoManager } from '../tools/todo/todo-manager.js'; /** * 工具调用开始事件信息 @@ -166,6 +167,8 @@ export class Agent { */ setSessionManager(manager: SessionManager): void { this.sessionManager = manager; + // 初始化 todoManager,使其能够访问会话数据 + todoManager.setSessionManager(manager); // 从会话恢复状态 const session = manager.getSession(); if (session) { diff --git a/packages/core/src/lsp/client.ts b/packages/core/src/lsp/client.ts index 2bfdbdc..df08aba 100644 --- a/packages/core/src/lsp/client.ts +++ b/packages/core/src/lsp/client.ts @@ -157,7 +157,7 @@ export class LSPClientManager { } /** - * 初始化语言服务器 + * 初始化语言服务器(带超时) */ private async initializeServer(state: ClientState, config: ServerConfig): Promise { const initParams: InitializeParams = { @@ -189,8 +189,13 @@ export class LSPClientManager { initializationOptions: config.initializationOptions, }; - // 使用字符串方法名发送请求 - await state.connection.sendRequest('initialize', initParams); + // 使用字符串方法名发送请求,添加超时保护 + const initPromise = state.connection.sendRequest('initialize', initParams); + const timeoutPromise = new Promise((_, reject) => { + setTimeout(() => reject(new Error('LSP 初始化超时(10秒)')), 10000); + }); + + await Promise.race([initPromise, timeoutPromise]); await state.connection.sendNotification('initialized', {}); state.initialized = true; } diff --git a/packages/ui/src/hooks/useChat.ts b/packages/ui/src/hooks/useChat.ts index 7fab05b..65ef35b 100644 --- a/packages/ui/src/hooks/useChat.ts +++ b/packages/ui/src/hooks/useChat.ts @@ -341,7 +341,26 @@ export function useChat({ sessionId, onError, onSessionNotFound, onSessionUpdate }) ); - setState((prev) => ({ ...prev, isLoading: false, streamingMessage: null })); + // 保留已流式输出的内容作为消息 + setState((prev) => { + const streaming = prev.streamingMessage; + // 如果有流式消息且有内容,保存到 messages 中 + if (streaming && (streaming.content || streaming.parts.length > 0)) { + const cancelledMessage: Message = { + ...streaming, + id: streaming.id || `cancelled-${Date.now()}`, + // 标记为已取消(可选:在 content 末尾添加提示) + content: streaming.content || '', + }; + return { + ...prev, + messages: [...prev.messages, cancelledMessage], + isLoading: false, + streamingMessage: null, + }; + } + return { ...prev, isLoading: false, streamingMessage: null }; + }); }, [sessionId]); // 发送权限响应