import { useEffect, useRef, useState } from 'react'; import { io, Socket } from 'socket.io-client'; const tools: string[] = [ 'get_health', 'get_build_status', 'get_state', 'get_telemetry', 'get_git_status', 'get_git_branch', 'get_git_log', 'get_git_diff', 'list_repo_files', 'read_repo_file', ]; interface User { email: string; name?: string; } export default function App() { const [user, setUser] = useState(null); const [output, setOutput] = useState(['OPAX Web TUI', 'Type tools or: mcp get_health', '']); const [input, setInput] = useState(''); const socketRef = useRef(null); useEffect(() => { fetch('/auth/me', { credentials: 'include' }) .then((r) => (r.ok ? r.json() : null)) .then(setUser); }, []); useEffect(() => { if (!user) return; const socket = io('/'); socketRef.current = socket; socket.on('mcp-result', (x) => { setOutput((a) => [...a, x.error ? 'ERROR ' + x.error : JSON.stringify(x.result, null, 2), '']); }); return () => { socket.close(); }; }, [user]); if (!user) { return (

OPAX

Continue with Google
); } function go(e: React.FormEvent) { e.preventDefault(); let v = input.trim(); setInput(''); setOutput((a) => [...a, '$ ' + v]); if (v === 'tools') { return setOutput((a) => [...a, ...tools, '']); } let m = v.match(/^mcp\s+(\S+)(?:\s+(.+))?$/); if (!m) { return setOutput((a) => [...a, 'Use mcp [JSON]', '']); } try { socketRef.current?.emit('mcp-call', { id: crypto.randomUUID(), tool: m[1], args: m[2] ? JSON.parse(m[2]) : {}, }); } catch { setOutput((a) => [...a, 'JSON arguments invalid', '']); } } return (
OPAX / Web TUI {user.email}
{output.join('\n')}
$ setInput(e.target.value)} />
); }