import React, { useState, useEffect } from 'react'; import { getAgentTasks, getAgentTokenUsage } from '../../../api'; const STATUS_BADGE = { pending: { label: '대기', bg: '#92400e' }, approved: { label: '승인됨', bg: '#1e40af' }, working: { label: '진행중', bg: '#3730a3' }, succeeded: { label: '완료', bg: '#065f46' }, failed: { label: '실패', bg: '#7f1d1d' }, rejected: { label: '거절됨', bg: '#9a3412' }, }; const AGENT_COMMANDS = { stock: [ { action: 'fetch_news', label: '뉴스 수집', icon: '📰' }, { action: 'list_alerts', label: '알람 목록', icon: '🔔' }, { action: 'test_telegram', label: 'TG 테스트', icon: '📨' }, ], music: [ { action: 'compose', label: '작곡 시작', icon: '🎵', needsInput: true }, { action: 'credits', label: '크레딧', icon: '💳' }, ], blog: [ { action: 'research', label: '키워드 리서치', icon: '🔍', needsInput: true }, { action: 'list_trend_keywords', label: '트렌드 목록', icon: '📋' }, ], realestate: [ { action: 'fetch_matches', label: '매칭 리포트', icon: '🏢' }, { action: 'dashboard', label: '대시보드', icon: '📊' }, ], }; const AgentColumn = ({ agentId, meta, agentState, notification, onCommand, onApproval, onClearNotification }) => { const [tasks, setTasks] = useState([]); const [input, setInput] = useState(''); const [activeCommand, setActiveCommand] = useState(null); const [tokenUsage, setTokenUsage] = useState(null); const [expanded, setExpanded] = useState(false); const state = agentState || { state: 'offline' }; const commands = AGENT_COMMANDS[agentId] || []; const needsAttention = state.state === 'waiting' || notification > 0; const isOpen = expanded || needsAttention; useEffect(() => { getAgentTasks(agentId, 10) .then(d => setTasks(d.tasks || [])) .catch(() => setTasks([])); }, [agentId]); // Refresh tasks when state changes to idle (task likely completed) useEffect(() => { if (state.state === 'idle' && state.detail) { getAgentTasks(agentId, 10) .then(d => setTasks(d.tasks || [])) .catch(() => {}); } }, [agentId, state.state, state.detail]); // 오늘자 AI 토큰 사용량 폴링 (30초 간격 + 작업 완료 시 즉시 갱신) useEffect(() => { let cancelled = false; const fetchUsage = () => { getAgentTokenUsage(agentId, 1) .then(d => { if (!cancelled) setTokenUsage(d); }) .catch(() => {}); }; fetchUsage(); const interval = setInterval(fetchUsage, 30000); return () => { cancelled = true; clearInterval(interval); }; }, [agentId, state.state, state.detail]); const handleQuickAction = (cmd) => { if (cmd.needsInput) { setActiveCommand(cmd.action); } else { onCommand(agentId, cmd.action, {}); } onClearNotification(); }; const handleSend = () => { if (!input.trim() || !activeCommand) return; const params = activeCommand === 'compose' ? { prompt: input } : activeCommand === 'research' ? { keyword: input } : { message: input }; onCommand(agentId, activeCommand, params); setInput(''); setActiveCommand(null); }; const formatTaskTime = (task) => { const iso = task.completed_at || task.created_at; if (!iso) return ''; const d = new Date(iso); if (isNaN(d.getTime())) return ''; const now = new Date(); const pad = (n) => String(n).padStart(2, '0'); const hm = `${pad(d.getHours())}:${pad(d.getMinutes())}`; const sameDay = d.toDateString() === now.toDateString(); const yesterday = new Date(now); yesterday.setDate(now.getDate() - 1); const isYesterday = d.toDateString() === yesterday.toDateString(); if (sameDay) return `오늘 ${hm}`; if (isYesterday) return `어제 ${hm}`; return `${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${hm}`; }; const handleHeaderClick = (e) => { e.stopPropagation(); setExpanded(v => !v); onClearNotification(); }; return (
{JSON.stringify(task.result_data, null, 2)}