diff --git a/web/src/App.tsx b/web/src/App.tsx index 285dd24..67ae375 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -75,6 +75,7 @@ function App() { handleCommand, clearMessages, handleServerMessage, + setSendMessage, selectTopic, createTopic, switchTopic, @@ -92,6 +93,11 @@ function App() { onMessage: handleServerMessage, }) + // 将 sendMessage 注入到 useChat,供 handleServerMessage 内部发送命令 + useEffect(() => { + setSendMessage(sendMessage) + }, [setSendMessage, sendMessage]) + // ---- 主题状态 ---- const [memoryPanelOpen, setMemoryPanelOpen] = useState(() => { diff --git a/web/src/hooks/useChat.ts b/web/src/hooks/useChat.ts index 28063b8..d7321d1 100644 --- a/web/src/hooks/useChat.ts +++ b/web/src/hooks/useChat.ts @@ -29,6 +29,7 @@ import type { ChannelList, StreamDelta, StreamEnd, + WsInbound, } from '../types/protocol' // 简化后的层级状态 @@ -66,6 +67,7 @@ interface UseChatReturn { handleCommand: (command: Command) => void clearMessages: () => void handleServerMessage: (message: WsOutbound) => void + setSendMessage: (fn: (msg: WsInbound) => boolean) => void // Topic 方法 selectTopic: (topicId: string) => void @@ -171,6 +173,12 @@ export function useChat(): UseChatReturn { const selectedTopicRef = useRef(null) const pendingNewTopicRef = useRef(false) + // Ref to send commands from within handleServerMessage (set by App.tsx) + const sendMessageRef = useRef<((msg: WsInbound) => boolean) | null>(null) + const setSendMessage = useCallback((fn: (msg: WsInbound) => boolean) => { + sendMessageRef.current = fn + }, []) + const isConnected = useMemo(() => connectionId !== null, [connectionId]) const selectedSession = useMemo( () => sessions.find(s => s.session_id === selectedSessionId) ?? null, @@ -377,6 +385,11 @@ export function useChat(): UseChatReturn { const msgSubagentTaskId = getSubagentTaskId(message) if (msgSubagentTaskId && msgSubagentTaskId === currentSubAgentView.taskId) { appendToSubAgentViewMessage(message) + // 子代理 todo_write 完成后自动刷新待办列表 + if (message.type === 'tool_result' && (message as ToolResult).tool_name === 'todo_write') { + const refreshCmd = requestSubAgentTodoList(currentSubAgentView.taskId) + sendMessageRef.current?.({ type: 'command', payload: JSON.stringify(refreshCmd) }) + } return } // 丢弃其他子智能体的消息,避免 fall through 到主消息处理 @@ -694,6 +707,14 @@ export function useChat(): UseChatReturn { // 忽略这些消息 break } + + // 主视图 todo_write 完成后自动刷新待办列表 + if (message.type === 'tool_result' && (message as ToolResult).tool_name === 'todo_write') { + const refreshCmd = subAgentViewRef.current?.taskId + ? requestSubAgentTodoList(subAgentViewRef.current.taskId) + : requestTodoList() + sendMessageRef.current?.({ type: 'command', payload: JSON.stringify(refreshCmd) }) + } }, []) const handleMessage = useCallback((content: string, attachments?: Attachment[]) => { @@ -938,6 +959,7 @@ export function useChat(): UseChatReturn { handleCommand, clearMessages, handleServerMessage, + setSendMessage, selectTopic, createTopic, switchTopic,