'use client' import { useState, useRef, useEffect } from 'react' import { useAgentStore } from '@/hooks/useAgentStore' import { fetchAPI } from '@/lib/api' const sandboxExecute = (cmd: string, sid: string) => fetchAPI('/api/v1/spaces/sandbox-worker-space/execute', { method: 'POST', body: JSON.stringify({ task: cmd, role: 'execution', session_id: sid }) }) const sandboxWriteFile = (path: string, content: string) => fetchAPI('/api/v1/files/write', { method: 'POST', body: JSON.stringify({ path, content }) }) const getWorkspaceInfo = () => fetchAPI('/api/v1/files/workspace') import { Terminal, Play, FolderOpen, File, RefreshCw, ChevronRight, Zap, ExternalLink, Code2 } from 'lucide-react' const VSCODE_HF_URL = 'https://pyae1994-god-agent-vscode.hf.space' interface TerminalLine { type: 'input' | 'output' | 'error' text: string time: string } export default function SandboxPanel() { const { locale } = useAgentStore() const [cmd, setCmd] = useState('') const [lines, setLines] = useState([ { type: 'output', text: '🚀 God Mode+ Sandbox — Persistent VS Code Workspace', time: '' }, { type: 'output', text: 'Type commands to execute in the sandbox...', time: '' }, ]) const [loading, setLoading] = useState(false) const [workspace, setWorkspace] = useState(null) const [tab, setTab] = useState<'terminal' | 'files' | 'vscode'>('terminal') const endRef = useRef(null) const inputRef = useRef(null) const [history, setHistory] = useState([]) const [histIdx, setHistIdx] = useState(-1) useEffect(() => { endRef.current?.scrollIntoView({ behavior: 'smooth' }) }, [lines]) const loadWorkspace = async () => { try { const data = await getWorkspaceInfo(); setWorkspace(data) } catch {} } useEffect(() => { loadWorkspace() }, []) const run = async () => { const c = cmd.trim() if (!c || loading) return const now = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' }) setLines(lines => [...lines, { type: 'input', text: `$ ${c}`, time: now }]) setHistory(history => [c, ...history.slice(0, 49)]) setHistIdx(-1) setCmd('') setLoading(true) try { const res = await sandboxExecute(c, 'sandbox_panel') const output = res.result || '' output.split('\n').forEach((line: string) => setLines(lines => [...lines, { type: 'output', text: line, time: '' }])) } catch (e: any) { setLines(lines => [...lines, { type: 'error', text: `❌ ${e.message}`, time: '' }]) } setLoading(false) if (tab === 'files') loadWorkspace() } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { run(); return } if (e.key === 'ArrowUp') { const idx = Math.min(histIdx + 1, history.length - 1) setHistIdx(idx) setCmd(history[idx] || '') } if (e.key === 'ArrowDown') { const idx = Math.max(histIdx - 1, -1) setHistIdx(idx) setCmd(idx === -1 ? '' : history[idx]) } } const QUICK_CMDS = ['ls -la', 'pwd', 'python3 --version', 'node --version', 'git status', 'pip list | head -10'] return (
{locale === 'my' ? 'Sandbox' : 'Sandbox'}
{(['terminal', 'files', 'vscode'] as const).map(t => ( ))}
{tab === 'terminal' ? ( <>
{QUICK_CMDS.map(q => )}
{lines.map((line, i) =>
{line.text}
)} {loading &&
Running...
}
setCmd(e.target.value)} onKeyDown={handleKeyDown} placeholder="Enter command..." className="flex-1 bg-transparent outline-none text-sm text-slate-100" />
) : tab === 'files' ? (
Workspace: {workspace?.workspace || '/tmp/god_workspace'}
) : (
VS Code Space: Open
)}
) }