Spaces:
Running
Running
| "use client"; | |
| import { useState } from "react"; | |
| import { Button } from "@/components/ui/button"; | |
| import { TextareaHTMLAttributes } from "react"; | |
| import { useAi } from "@/hooks/useAi"; | |
| export default function OmniConsole() { | |
| const [instruction, setInstruction] = useState(""); | |
| const [context, setContext] = useState("/frontend\n /src\n /components\n/backend\n /routes\n /controllers\n"); | |
| const [out, setOut] = useState<any>(null); | |
| const { model, provider } = useAi(); | |
| const [loading, setLoading] = useState(false); | |
| const [space, setSpace] = useState(""); | |
| const [commitTitle, setCommitTitle] = useState("OmniDev: Apply changes"); | |
| const run = async () => { | |
| setLoading(true); | |
| setOut(null); | |
| try { | |
| const res = await fetch('/api/augment', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ context, instruction, language: 'javascript', framework: 'express-react', response_type: 'file_updates', model, provider }), | |
| }); | |
| const data = await res.json(); | |
| setOut(data); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| const apply = async () => { | |
| if (!out?.files || !Array.isArray(out.files) || out.files.length === 0) return; | |
| if (!space.includes('/')) { | |
| alert('Specify target space as namespace/repoId'); | |
| return; | |
| } | |
| const [namespace, repoId] = space.split('/'); | |
| setLoading(true); | |
| try { | |
| const res = await fetch(`/api/me/projects/${namespace}/${repoId}/apply`, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ files: out.files, commitTitle }), | |
| }); | |
| const data = await res.json(); | |
| setOut((prev: any) => ({ ...prev, apply: data })); | |
| } finally { | |
| setLoading(false); | |
| } | |
| } | |
| return ( | |
| <div className="p-4 border border-neutral-800 bg-neutral-900 rounded-xl text-neutral-200"> | |
| <h2 className="text-xl font-semibold mb-2">Omni Console</h2> | |
| <p className="text-sm text-neutral-400 mb-4">Type engineering instructions; the engine returns structured file updates.</p> | |
| <div className="grid gap-2"> | |
| <label className="text-sm">Project Context</label> | |
| <textarea className="min-h-24 bg-neutral-800 rounded p-2 text-sm" value={context} onChange={(e) => setContext(e.target.value)} /> | |
| <label className="text-sm">Instruction</label> | |
| <textarea className="min-h-24 bg-neutral-800 rounded p-2 text-sm" placeholder="e.g., Add JWT auth with /auth/login route" value={instruction} onChange={(e) => setInstruction(e.target.value)} /> | |
| <label className="text-sm">Target Space (namespace/repoId)</label> | |
| <input className="bg-neutral-800 rounded p-2 text-sm" placeholder="yourname/your-space" value={space} onChange={(e) => setSpace(e.target.value)} /> | |
| <label className="text-sm">Commit Title</label> | |
| <input className="bg-neutral-800 rounded p-2 text-sm" value={commitTitle} onChange={(e) => setCommitTitle(e.target.value)} /> | |
| </div> | |
| <div className="flex items-center gap-2 mt-3"> | |
| <Button size="sm" onClick={run} disabled={loading || !instruction.trim()}>Run</Button> | |
| <Button size="sm" variant="outline" onClick={apply} disabled={loading || !out?.files?.length}>Apply Changes</Button> | |
| </div> | |
| {out && ( | |
| <pre className="mt-4 text-xs bg-neutral-950 p-3 rounded overflow-x-auto max-h-80">{JSON.stringify(out, null, 2)}</pre> | |
| )} | |
| </div> | |
| ); | |
| } | |