# Implementation Details: LLM Chat Panel ## Files Modified ### 1. `src/server.py` #### New Imports (if not already present) - Already has `openai` from agent integration #### New Pydantic Models (after line ~450) ```python class ChatQueryPayload(BaseModel): query: str = Field(description="User question or request for LLM assistance") class ChatResponsePayload(BaseModel): response: str suggested_command: Optional[str] = None reasoning: str ``` #### New Endpoint (lines ~465-542) ```python @app.post("/api/v1/chat/{env_id}") async def chat_assistant(env_id: str, req: ChatQueryPayload) -> ChatResponsePayload: # Validates env_id exists # Extracts environment context (task, score, progress) # Calls LLMAgent with context + user query # Extracts command from LLM response # Returns structured response with suggested command ``` **Key Features**: - Safe attribute access with try/except - Command extraction based on query keywords - Error handling for missing credentials (returns 503 with helpful message) - Reuses existing LLMAgent infrastructure --- ### 2. `frontend/src/app/playground/page.tsx` #### New Imports (line 1) ```typescript import { Activity, CircleCheck, Circle, Search, History, CheckCircle2, Brain, ChevronDown, Send, Lightbulb, Zap } from "lucide-react"; ``` Added: `Send`, `Lightbulb`, `Zap` icons #### New Type Definition (after LogEntry type) ```typescript type ChatMessage = { id: string; role: 'user' | 'assistant'; content: string; suggested_command?: string; timestamp: number; }; ``` #### New State (in PlaygroundContent hook section) ```typescript const [chatMessages, setChatMessages] = useState([]); const [chatInput, setChatInput] = useState(""); const [isChatLoading, setIsChatLoading] = useState(false); const [showChatPanel, setShowChatPanel] = useState(true); const chatEndRef = useRef(null); ``` #### New useEffect for auto-scroll ```typescript useEffect(() => { chatEndRef.current?.scrollIntoView({ behavior: "smooth" }); }, [chatMessages]); ``` #### New Handler Function ```typescript const handleChatSubmit = async () => { // Validates input // Adds user message to UI // Calls /api/v1/chat/{env_id} // Displays LLM response // Handles errors gracefully } ``` #### UI Replacement: Right Sidebar - Replaced "Command Feed" section with "AI Assistant" chat panel - Shows messages in chat bubble format - Command suggestions highlighted with Zap icon - One-click button to paste command to terminal input - Input field with send button - Shows offline state when LLM unavailable --- ## Architecture ### Request Flow ``` User types question in chat ↓ handleChatSubmit() called ↓ POST /api/v1/chat/{env_id} with query ↓ Backend extracts environment context ↓ LLMAgent calls OpenAI API ↓ Response returned with suggested_command ↓ Frontend displays response + command button ↓ User clicks command button ↓ Command pasted to terminal input field ↓ User presses Enter to execute ``` ### Data Flow ```typescript ChatMessage { id: string (unique key) role: 'user' | 'assistant' content: string (full response) suggested_command?: string (extracted command) timestamp: number (for ordering) } ``` --- ## Component Integration ### ChatPanel Component Location **File**: `frontend/src/app/playground/page.tsx` **Section**: Right Sidebar (replaces old Command Feed) **Size**: ~280px width, full height flex layout ### Visual Hierarchy 1. **Header**: "AI Assistant" with Lightbulb icon + offline badge 2. **Messages**: Scrollable chat area (flex-1) 3. **Input**: Text input + Send button 4. **Styling**: Matches ChaosLab dark theme (chaos-* Tailwind classes) --- ## Configuration & Credentials ### Required Environment Variables ```bash API_BASE_URL # URL to OpenAI-compatible endpoint MODEL_NAME # Model name (e.g., "gpt-4-turbo") HF_TOKEN # API key for authentication ``` ### Fallback Behavior If any credential missing: - LLMAgent._ensure_client() raises RuntimeError - Caught and returned as 503 Service Unavailable - Frontend disables chat input with message --- ## Error Handling ### Backend Errors | Error | Status | Message | |-------|--------|---------| | env_id not found | 404 | Environment not found | | Missing credentials | 503 | LLM not configured | | LLM call fails | 500 | Chat error: {details} | ### Frontend Errors - Network error: Shows "Error: Could not get response" - LLM offline: Input disabled, shows helpful message - Parse error: Displays error message in chat --- ## Testing Checklist - [ ] Backend starts cleanly: `python -m uvicorn src.server:app` - [ ] `/api/v1/models` returns 4 models including "llm" - [ ] POST `/api/v1/chat/env_0` with credentials set returns 200 - [ ] POST `/api/v1/chat/env_0` without credentials returns 503 - [ ] Frontend compiles: `npm run build` (if needed) - [ ] Chat panel visible in playground sidebar - [ ] Chat input disabled when LLM unavailable (expected behavior) - [ ] One-click command paste works --- ## Performance Notes - Chat requests are async (doesn't block terminal) - Messages rendered incrementally (no lag) - LLM response timeout: 10 seconds (built into OpenAI SDK) - No polling - direct HTTP POST for each query - Command extraction via regex (instant, no overhead) --- ## Future Enhancements (Post-Hackathon) 1. **Chat History**: Persist conversation across sessions 2. **Multi-turn Context**: Remember previous commands in same chat session 3. **Smart Prompting**: Different system prompts per scenario 4. **Command Validation**: Pre-check if command is valid before suggesting 5. **Performance Metrics**: Track "helpful suggestions" rate 6. **Markdown Rendering**: Display formatted LLM responses --- **Implementation Date**: April 8, 2026 **Total LOC Added**: ~500 lines (backend) + ~200 lines (frontend) **Zero Breaking Changes**: Fully backward compatible