File size: 3,501 Bytes
65ef364
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
"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>
  );
}