Codeki / frontend /src /components /AgentPanel.tsx
Mayank2027's picture
Update frontend/src/components/AgentPanel.tsx
c5a51e4 verified
Raw
History Blame Contribute Delete
4.11 kB
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;