import React from 'react'; import { useChatStore } from './stores/chatStore'; import { useNavigation } from './hooks/useNavigation'; type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'error'; function ConnectionStatusBanner({ status, error, onRetry }: { status: ConnectionStatus; error?: string; onRetry: () => void; }) { if (status === 'connected') return null; const messages: Record = { disconnected: 'Not connected to OpenCode API', connecting: 'Connecting...', connected: '', error: error || 'Connection error', }; return (
{status === 'connecting' && ( )} {messages[status]} {(status === 'disconnected' || status === 'error') && ( )}
); } function SessionsList() { const { sessions, currentSessionId, selectSession, createSession, isLoadingSessions } = useChatStore(); const { goToChat } = useNavigation(); const [isCreating, setIsCreating] = React.useState(false); const handleSelectSession = async (sessionId: string) => { await selectSession(sessionId); goToChat(); }; const handleNewSession = async () => { setIsCreating(true); const sessionId = await createSession(); setIsCreating(false); if (sessionId) { goToChat(); } }; const formatTime = (timestamp?: number) => { if (!timestamp) return ''; const date = new Date(timestamp); const now = new Date(); const diffDays = Math.floor((now.getTime() - date.getTime()) / 86400000); if (diffDays === 0) return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); if (diffDays === 1) return 'Yesterday'; return date.toLocaleDateString([], { month: 'short', day: 'numeric' }); }; return (

Sessions

{isLoadingSessions ? (
Loading...
) : sessions.length === 0 ? (
No sessions yet
) : (
{sessions.map((session) => ( ))}
)}
); } function ChatPanel() { const { currentSessionId, sessions, messages, sendMessage, abortMessage, isSending, streamingSessionId } = useChatStore(); const { goToSessions } = useNavigation(); const [input, setInput] = React.useState(''); const messagesEndRef = React.useRef(null); const currentSession = sessions.find((s) => s.id === currentSessionId); const sessionMessages = currentSessionId ? messages.get(currentSessionId) || [] : []; const isStreaming = streamingSessionId === currentSessionId; React.useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [sessionMessages.length]); const handleSend = async () => { if (!input.trim() || isSending) return; const text = input.trim(); setInput(''); await sendMessage(text); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); } }; return (

{currentSession?.title || 'New Chat'}

{sessionMessages.length === 0 ? (
Start a conversation
) : (
{sessionMessages.map((msg, idx) => ( ))} {isStreaming && (
)}
)}