From eb0eb26f4cefa4880c895ff017f312e8674f9b73 Mon Sep 17 00:00:00 2001 From: karpathy Date: Sat, 22 Nov 2025 14:27:53 -0800 Subject: v0 --- frontend/src/App.jsx | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 frontend/src/App.jsx (limited to 'frontend/src/App.jsx') diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx new file mode 100644 index 0000000..0396e3a --- /dev/null +++ b/frontend/src/App.jsx @@ -0,0 +1,120 @@ +import { useState, useEffect } from 'react'; +import Sidebar from './components/Sidebar'; +import ChatInterface from './components/ChatInterface'; +import { api } from './api'; +import './App.css'; + +function App() { + const [conversations, setConversations] = useState([]); + const [currentConversationId, setCurrentConversationId] = useState(null); + const [currentConversation, setCurrentConversation] = useState(null); + const [isLoading, setIsLoading] = useState(false); + + // Load conversations on mount + useEffect(() => { + loadConversations(); + }, []); + + // Load conversation details when selected + useEffect(() => { + if (currentConversationId) { + loadConversation(currentConversationId); + } + }, [currentConversationId]); + + const loadConversations = async () => { + try { + const convs = await api.listConversations(); + setConversations(convs); + } catch (error) { + console.error('Failed to load conversations:', error); + } + }; + + const loadConversation = async (id) => { + try { + const conv = await api.getConversation(id); + setCurrentConversation(conv); + } catch (error) { + console.error('Failed to load conversation:', error); + } + }; + + const handleNewConversation = async () => { + try { + const newConv = await api.createConversation(); + setConversations([ + { id: newConv.id, created_at: newConv.created_at, message_count: 0 }, + ...conversations, + ]); + setCurrentConversationId(newConv.id); + } catch (error) { + console.error('Failed to create conversation:', error); + } + }; + + const handleSelectConversation = (id) => { + setCurrentConversationId(id); + }; + + const handleSendMessage = async (content) => { + if (!currentConversationId) return; + + setIsLoading(true); + try { + // Optimistically add user message to UI + const userMessage = { role: 'user', content }; + setCurrentConversation((prev) => ({ + ...prev, + messages: [...prev.messages, userMessage], + })); + + // Send message and get council response + const response = await api.sendMessage(currentConversationId, content); + + // Add assistant message to UI + const assistantMessage = { + role: 'assistant', + stage1: response.stage1, + stage2: response.stage2, + stage3: response.stage3, + metadata: response.metadata, + }; + + setCurrentConversation((prev) => ({ + ...prev, + messages: [...prev.messages, assistantMessage], + })); + + // Reload conversations list to update message count + await loadConversations(); + } catch (error) { + console.error('Failed to send message:', error); + // Remove optimistic user message on error + setCurrentConversation((prev) => ({ + ...prev, + messages: prev.messages.slice(0, -1), + })); + } finally { + setIsLoading(false); + } + }; + + return ( +
+ + +
+ ); +} + +export default App; -- cgit v1.2.3