112 lines
3.2 KiB
JavaScript
112 lines
3.2 KiB
JavaScript
// 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({}); // { 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 [refreshTrigger, setRefreshTrigger] = useState(0); // 탭 데이터 리프레시용
|
|
|
|
const wsRef = useRef(null);
|
|
const reconnectRef = useRef(null);
|
|
|
|
const connect = useCallback(() => {
|
|
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);
|
|
|
|
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 || '', 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 || '', task_id: msg.task_id }
|
|
}));
|
|
// idle 전환 시 데이터 리프레시
|
|
if (msg.state === 'idle') {
|
|
setRefreshTrigger(n => n + 1);
|
|
}
|
|
break;
|
|
|
|
case 'task_complete':
|
|
setRefreshTrigger(n => n + 1);
|
|
break;
|
|
|
|
case 'notification':
|
|
setNotifications(prev => ({
|
|
...prev,
|
|
[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 (reconnectRef.current) clearTimeout(reconnectRef.current);
|
|
};
|
|
}, [connect]);
|
|
|
|
const sendCommand = useCallback((agent, action, params = {}) => {
|
|
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
|
wsRef.current.send(JSON.stringify({ type: 'command', agent, action, params }));
|
|
}
|
|
}, []);
|
|
|
|
const sendApproval = useCallback((agent, taskId, approved) => {
|
|
if (wsRef.current?.readyState === WebSocket.OPEN) {
|
|
wsRef.current.send(JSON.stringify({ type: 'approval', agent, task_id: taskId, approved }));
|
|
}
|
|
}, []);
|
|
|
|
const clearNotifications = useCallback((agentId) => {
|
|
setNotifications(prev => ({ ...prev, [agentId]: 0 }));
|
|
}, []);
|
|
|
|
return {
|
|
agents,
|
|
pendingTasks,
|
|
notifications,
|
|
connected,
|
|
refreshTrigger,
|
|
sendCommand,
|
|
sendApproval,
|
|
clearNotifications
|
|
};
|
|
}
|