diff --git a/src/pages/agent-office/hooks/useAgentManager.js b/src/pages/agent-office/hooks/useAgentManager.js index 1291a07..1bc4282 100644 --- a/src/pages/agent-office/hooks/useAgentManager.js +++ b/src/pages/agent-office/hooks/useAgentManager.js @@ -1,81 +1,84 @@ +// src/pages/agent-office/hooks/useAgentManager.js import { useState, useEffect, useRef, useCallback } from 'react'; +const WS_RECONNECT_DELAY = 3000; + export function useAgentManager() { - const [agents, setAgents] = useState({}); - const [pendingTasks, setPendingTasks] = useState([]); + const [agents, setAgents] = useState({}); // { agentId: { state, detail, task_id } } + const [pendingTasks, setPendingTasks] = useState([]); // [{id, agent_id, task_type, input_data}] + const [notifications, setNotifications] = useState({}); // { agentId: count } const [connected, setConnected] = useState(false); - const [notifications, setNotifications] = useState({}); + const [refreshTrigger, setRefreshTrigger] = useState(0); // 탭 데이터 리프레시용 + const wsRef = useRef(null); - const reconnectTimer = useRef(null); + const reconnectRef = useRef(null); const connect = useCallback(() => { - const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; - const wsUrl = `${protocol}//${window.location.host}/api/agent-office/ws`; - - const ws = new WebSocket(wsUrl); + const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws'; + const ws = new WebSocket(`${protocol}://${window.location.host}/api/agent-office/ws`); wsRef.current = ws; - ws.onopen = () => { - setConnected(true); - if (reconnectTimer.current) clearTimeout(reconnectTimer.current); - }; + ws.onopen = () => setConnected(true); - ws.onclose = () => { - setConnected(false); - reconnectTimer.current = setTimeout(connect, 3000); - }; - - ws.onerror = () => { ws.close(); }; - - ws.onmessage = (event) => { - const msg = JSON.parse(event.data); + ws.onmessage = (e) => { + const msg = JSON.parse(e.data); switch (msg.type) { case 'init': { + // 에이전트 초기 상태 세팅 const agentMap = {}; for (const a of msg.agents) { - agentMap[a.agent_id] = { state: a.state, detail: a.detail }; + agentMap[a.agent_id] = { state: a.state, detail: a.detail || '', task_id: a.task_id }; } setAgents(agentMap); setPendingTasks(msg.pending || []); break; } + case 'agent_state': setAgents(prev => ({ ...prev, - [msg.agent]: { state: msg.state, detail: msg.detail, taskId: msg.task_id }, + [msg.agent]: { state: msg.state, detail: msg.detail || '', task_id: msg.task_id } })); + // idle 전환 시 데이터 리프레시 + if (msg.state === 'idle') { + setRefreshTrigger(n => n + 1); + } break; + case 'task_complete': - setAgents(prev => ({ - ...prev, - [msg.agent]: { ...prev[msg.agent], lastResult: msg.result }, - })); - setPendingTasks(prev => prev.filter(id => id !== msg.task_id)); - break; - case 'command_result': - setAgents(prev => ({ - ...prev, - [msg.agent]: { ...prev[msg.agent], lastCommand: msg.result }, - })); + setRefreshTrigger(n => n + 1); break; + case 'notification': setNotifications(prev => ({ ...prev, - [msg.agent]: (prev[msg.agent] || 0) + 1, + [msg.agent]: (prev[msg.agent] || 0) + 1 })); break; + + case 'command_result': + // 사이드 패널에서 처리 + break; + default: break; } }; + + ws.onclose = () => { + setConnected(false); + reconnectRef.current = setTimeout(connect, WS_RECONNECT_DELAY); + }; + + ws.onerror = () => ws.close(); }, []); useEffect(() => { connect(); return () => { if (wsRef.current) wsRef.current.close(); - if (reconnectTimer.current) clearTimeout(reconnectTimer.current); + if (reconnectRef.current) clearTimeout(reconnectRef.current); }; }, [connect]); @@ -92,12 +95,17 @@ export function useAgentManager() { }, []); const clearNotifications = useCallback((agentId) => { - setNotifications(prev => { - const next = { ...prev }; - delete next[agentId]; - return next; - }); + setNotifications(prev => ({ ...prev, [agentId]: 0 })); }, []); - return { agents, pendingTasks, connected, notifications, sendCommand, sendApproval, clearNotifications }; + return { + agents, + pendingTasks, + notifications, + connected, + refreshTrigger, + sendCommand, + sendApproval, + clearNotifications + }; }