Spaces:
Paused
Paused
| import React, { useState, useEffect } from 'react'; | |
| import { FaRobot, FaSpinner, FaCheck, FaTimes } from 'react-icons/fa'; | |
| import axios from 'axios'; | |
| const AgentPanel: React.FC<{ projectPath: string }> = ({ projectPath }) => { | |
| const [prompt, setPrompt] = useState(''); | |
| const [running, setRunning] = useState(false); | |
| const [taskId, setTaskId] = useState<string | null>(null); | |
| const [status, setStatus] = useState(''); | |
| const [logs, setLogs] = useState<string[]>([]); | |
| const [pendingChanges, setPendingChanges] = useState<any[]>([]); | |
| const [selectedModel, setSelectedModel] = useState('groq-llama-3.3-70b-versatile'); | |
| const [models, setModels] = useState<any[]>([]); | |
| useEffect(() => { | |
| axios.get('/api/models').then(res => setModels(res.data)); | |
| }, []); | |
| const startTask = async () => { | |
| setRunning(true); | |
| setLogs([]); | |
| setPendingChanges([]); | |
| setStatus('running'); | |
| try { | |
| const resp = await fetch('/api/agent/run', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ prompt, project_path: projectPath, model: selectedModel }), | |
| }); | |
| const data = await resp.json(); | |
| setTaskId(data.task_id); | |
| setStatus(data.status); | |
| setLogs(data.logs || []); | |
| setPendingChanges(data.pending_changes || []); | |
| } catch (e) { | |
| setLogs(['Error: ' + e]); | |
| } | |
| setRunning(false); | |
| }; | |
| const approve = async () => { | |
| if (!taskId) return; | |
| try { | |
| const resp = await fetch(`/api/agent/approve/${taskId}`, { method: 'POST' }); | |
| const data = await resp.json(); | |
| setStatus(data.status); | |
| setLogs(prev => [...prev, ...(data.logs || [])]); | |
| } catch (e) {} | |
| }; | |
| return ( | |
| <div style={{ height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--bg-primary)', padding: 12 }}> | |
| <div style={{ fontWeight: 600, marginBottom: 8 }}><FaRobot /> AI Agent</div> | |
| <select | |
| style={{ width: '100%', background: 'var(--bg-tertiary)', color: 'var(--text-primary)', border: '1px solid var(--border)', padding: '6px 8px', borderRadius: 6, marginBottom: 8 }} | |
| value={selectedModel} | |
| onChange={e => setSelectedModel(e.target.value)} | |
| > | |
| {models.map((m: any) => ( | |
| <option key={m.id} value={m.id}>{m.name}</option> | |
| ))} | |
| </select> | |
| <textarea | |
| style={{ width: '100%', height: 60, background: 'var(--bg-tertiary)', color: 'var(--text-primary)', border: '1px solid var(--border)', borderRadius: 6, padding: 8, resize: 'vertical', marginBottom: 8 }} | |
| value={prompt} | |
| onChange={e => setPrompt(e.target.value)} | |
| placeholder="E.g., 'Create a REST API for todos with a database'" | |
| /> | |
| <button | |
| onClick={startTask} | |
| disabled={running} | |
| style={{ background: 'var(--accent)', color: 'white', padding: '6px 16px', borderRadius: 6, fontWeight: 600, marginBottom: 8 }} | |
| > | |
| {running ? <><FaSpinner className="spin" /> Running...</> : 'Start Agent'} | |
| </button> | |
| {status === 'awaiting_approval' && pendingChanges.length > 0 && ( | |
| <div style={{ marginBottom: 8 }}> | |
| <div style={{ color: 'var(--warning)', marginBottom: 4 }}>Pending changes ({pendingChanges.length}):</div> | |
| {pendingChanges.map((c, i) => ( | |
| <div key={i} style={{ fontSize: 12, marginBottom: 2 }}> | |
| {c.action} – {c.filepath} | |
| </div> | |
| ))} | |
| <button onClick={approve} style={{ background: 'var(--success)', color: 'white', padding: '4px 12px', borderRadius: 4 }}> | |
| <FaCheck /> Approve & Apply All | |
| </button> | |
| </div> | |
| )} | |
| <div style={{ flex: 1, overflowY: 'auto', fontFamily: 'monospace', fontSize: 12, whiteSpace: 'pre-wrap', background: 'var(--bg-secondary)', padding: 8, borderRadius: 4 }}> | |
| {logs.map((log, i) => ( | |
| <div key={i}>• {log}</div> | |
| ))} | |
| {status === 'completed' && <div style={{ color: 'var(--success)' }}>✅ Task completed.</div>} | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default AgentPanel; |