import { useEffect, useMemo } from 'react' import { useTabStore } from '../stores/tabStore' import { useSessionStore } from '../stores/sessionStore' import { useChatStore } from '../stores/chatStore' import { useCLITaskStore } from '../stores/cliTaskStore' import { useTeamStore } from '../stores/teamStore' import { useTranslation } from '../i18n' import { MessageList } from '../components/chat/MessageList' import { ChatInput } from '../components/chat/ChatInput' import { TeamStatusBar } from '../components/teams/TeamStatusBar' import { SessionTaskBar } from '../components/chat/SessionTaskBar' const TASK_POLL_INTERVAL_MS = 1000 export function ActiveSession() { const activeTabId = useTabStore((s) => s.activeTabId) const sessions = useSessionStore((s) => s.sessions) const connectToSession = useChatStore((s) => s.connectToSession) const sessionState = useChatStore((s) => activeTabId ? s.sessions[activeTabId] : undefined) const fetchSessionTasks = useCLITaskStore((s) => s.fetchSessionTasks) const trackedTaskSessionId = useCLITaskStore((s) => s.sessionId) const hasIncompleteTasks = useCLITaskStore((s) => s.tasks.some((task) => task.status !== 'completed')) const chatState = sessionState?.chatState ?? 'idle' const tokenUsage = sessionState?.tokenUsage ?? { input_tokens: 0, output_tokens: 0 } const session = sessions.find((s) => s.id === activeTabId) const memberInfo = useTeamStore((s) => activeTabId ? s.getMemberBySessionId(activeTabId) : null) const activeTeam = useTeamStore((s) => s.activeTeam) const isMemberSession = !!memberInfo useEffect(() => { if (activeTabId && !isMemberSession) { connectToSession(activeTabId) } }, [activeTabId, isMemberSession, connectToSession]) useEffect(() => { if (!activeTabId || isMemberSession) return const shouldPollTasks = chatState !== 'idle' || (trackedTaskSessionId === activeTabId && hasIncompleteTasks) if (!shouldPollTasks) return void fetchSessionTasks(activeTabId) const timer = setInterval(() => { void fetchSessionTasks(activeTabId) }, TASK_POLL_INTERVAL_MS) return () => clearInterval(timer) }, [ activeTabId, isMemberSession, chatState, trackedTaskSessionId, hasIncompleteTasks, fetchSessionTasks, ]) const t = useTranslation() const messages = sessionState?.messages ?? [] const streamingText = sessionState?.streamingText ?? '' const isEmpty = messages.length === 0 && !streamingText const isActive = chatState !== 'idle' const totalTokens = tokenUsage.input_tokens + tokenUsage.output_tokens const lastUpdated = useMemo(() => { if (!session?.modifiedAt) return '' const diff = Date.now() - new Date(session.modifiedAt).getTime() if (diff < 60000) return t('session.timeJustNow') if (diff < 3600000) return t('session.timeMinutes', { n: Math.floor(diff / 60000) }) if (diff < 86400000) return t('session.timeHours', { n: Math.floor(diff / 3600000) }) return t('session.timeDays', { n: Math.floor(diff / 86400000) }) }, [session?.modifiedAt, t]) if (!activeTabId) return null return (
{isMemberSession && (
{memberInfo?.status === 'running' && ( )} {memberInfo?.status === 'completed' && ( check_circle )} smart_toy {memberInfo?.role} {activeTeam && ( @ {activeTeam.name} )}

{t('teams.memberSessionHint')}

)} {isEmpty ? (
{isMemberSession ? ( <> smart_toy

{memberInfo?.status === 'running' ? `${memberInfo.role} ${t('teams.working')}` : t('teams.noMessages')}

) : ( <> Claude Code Haha

{t('empty.title')}

{t('empty.subtitle')}

)}
) : ( <> {!isMemberSession && (

{session?.title || t('session.untitled')}

{isActive && ( {t('session.active')} )} {totalTokens > 0 && ( <> · {totalTokens.toLocaleString()} t )} {lastUpdated && ( <> · {t('session.lastUpdated', { time: lastUpdated })} )} {session?.messageCount !== undefined && session.messageCount > 0 && ( <> · {t('session.messages', { count: session.messageCount })} )}
{session?.workDirExists === false && (
warning {t('session.workspaceUnavailable', { dir: session.workDir || 'directory no longer exists' })}
)}
)} )} {!isMemberSession && }
) }