finish generate logic

This commit is contained in:
Ishaan Dey
2024-05-03 00:52:01 -07:00
parent e6cf993b6a
commit 2bfaf428d9
5 changed files with 189 additions and 75 deletions

View File

@ -1,33 +1,41 @@
"use client"
import { useEffect, useRef, useState } from "react"
import { Input } from "../ui/input"
import { Button } from "../ui/button"
import { Check, Loader2, RotateCw, Sparkles, X } from "lucide-react"
import { Socket } from "socket.io-client"
import { Editor } from "@monaco-editor/react"
// import monaco from "monaco-editor"
export default function GenerateInput({
cancel,
submit,
socket,
width,
data,
editor,
onExpand,
onAccept,
}: {
cancel: () => void
submit: (input: string) => void
socket: Socket
width: number
data: {
fileName: string
code: string
line: number
}
editor: {
language: string
}
onExpand: () => void
onAccept: (code: string) => void
}) {
const inputRef = useRef<HTMLInputElement>(null)
const [code, setCode] = useState(`function add(a: number, b: number): number {
return a + b;
}
const result = add(2, 3);
console.log(result);`)
const [code, setCode] = useState("")
const [expanded, setExpanded] = useState(false)
const [loading, setLoading] = useState(false)
const [loading, setLoading] = useState({
generate: false,
regenerate: false,
})
const [input, setInput] = useState("")
const [currentPrompt, setCurrentPrompt] = useState("")
@ -37,17 +45,45 @@ export default function GenerateInput({
}, 0)
}, [])
const handleGenerate = async () => {
setLoading(true)
const handleGenerate = async ({
regenerate = false,
}: {
regenerate?: boolean
}) => {
setLoading({ generate: !regenerate, regenerate })
setCurrentPrompt(input)
// const res = await generateCode()
await new Promise((resolve) => setTimeout(resolve, 1000))
socket.emit(
"generateCode",
data.fileName,
data.code,
data.line,
regenerate ? currentPrompt : input,
(res: {
result: {
response: string
}
success: boolean
errors: any[]
messages: any[]
}) => {
if (!res.success) {
console.error(res.errors)
return
}
setExpanded(true)
onExpand()
setLoading(false)
setCode(res.result.response)
}
)
}
useEffect(() => {
if (code) {
setExpanded(true)
onExpand()
setLoading({ generate: false, regenerate: false })
}
}, [code])
return (
<div className="w-full pr-4 space-y-2">
<div className="flex items-center font-sans space-x-2">
@ -64,10 +100,10 @@ export default function GenerateInput({
<Button
size="sm"
disabled={loading || input === ""}
onClick={handleGenerate}
disabled={loading.generate || loading.regenerate || input === ""}
onClick={() => handleGenerate({})}
>
{loading ? (
{loading.generate ? (
<>
<Loader2 className="animate-spin h-3 w-3 mr-2" />
Generating...
@ -83,20 +119,55 @@ export default function GenerateInput({
{expanded ? (
<>
<div className="rounded-md border border-muted-foreground w-full h-28 overflow-y-scroll p-2">
<pre>{code}</pre>
<Editor
height="100%"
defaultLanguage={editor.language}
value={code}
options={{
minimap: {
enabled: false,
},
scrollBeyondLastLine: false,
fontFamily: "var(--font-geist-mono)",
domReadOnly: true,
readOnly: true,
lineNumbers: "off",
glyphMargin: false,
folding: false,
// Undocumented see https://github.com/Microsoft/vscode/issues/30795#issuecomment-410998882
lineDecorationsWidth: 0,
lineNumbersMinChars: 0,
}}
theme="vs-dark"
/>
</div>
<div className="flex space-x-2">
<Button onClick={() => onAccept(code)} size="sm">
<div className="flex space-x-2 font-sans">
<Button
disabled={loading.generate || loading.regenerate}
onClick={() => onAccept(code)}
size="sm"
>
<Check className="h-3 w-3 mr-2" />
Accept
</Button>
<Button
onClick={() => handleGenerate({ regenerate: true })}
disabled={loading.generate || loading.regenerate}
variant="outline"
size="sm"
className="bg-transparent border-muted-foreground"
>
<RotateCw className="h-3 w-3 mr-2" />
Re-Generate
{loading.regenerate ? (
<>
<Loader2 className="animate-spin h-3 w-3 mr-2" />
Generating...
</>
) : (
<>
<RotateCw className="h-3 w-3 mr-2" />
Re-Generate
</>
)}
</Button>
</div>
</>

View File

@ -2,7 +2,7 @@
import Editor, { BeforeMount, OnMount } from "@monaco-editor/react"
import monaco from "monaco-editor"
import { use, useEffect, useRef, useState } from "react"
import { useEffect, useRef, useState } from "react"
// import theme from "./theme.json"
import {
@ -372,9 +372,16 @@ export default function CodeEditor({
<div className="z-50 p-1" ref={generateWidgetRef}>
{generate.show ? (
<GenerateInput
cancel={() => {}}
submit={(str: string) => {}}
socket={socket}
width={generate.width - 90}
data={{
fileName: tabs.find((t) => t.id === activeId)?.name ?? "",
code: editorRef.current?.getValue() ?? "",
line: generate.line,
}}
editor={{
language: editorLanguage,
}}
onExpand={() => {
editorRef.current?.changeViewZones(function (changeAccessor) {
changeAccessor.removeZone(generate.id)
@ -391,13 +398,19 @@ export default function CodeEditor({
})
}}
onAccept={(code: string) => {
const line = generate.line
setGenerate((prev) => {
return {
...prev,
show: !prev.show,
}
})
console.log("accepted:", code)
const file = editorRef.current?.getValue()
const lines = file?.split("\n") || []
lines.splice(line - 1, 0, code)
const updatedFile = lines.join("\n")
editorRef.current?.setValue(updatedFile)
}}
/>
) : null}

View File

@ -24,7 +24,7 @@ export async function updateSandbox(body: {
name?: string
visibility?: "public" | "private"
}) {
const res = await fetch("http://localhost:8787/api/sandbox", {
await fetch("http://localhost:8787/api/sandbox", {
method: "POST",
headers: {
"Content-Type": "application/json",
@ -36,7 +36,7 @@ export async function updateSandbox(body: {
}
export async function deleteSandbox(id: string) {
const res = await fetch(`http://localhost:8787/api/sandbox?id=${id}`, {
await fetch(`http://localhost:8787/api/sandbox?id=${id}`, {
method: "DELETE",
})
@ -62,7 +62,7 @@ export async function shareSandbox(sandboxId: string, email: string) {
}
export async function unshareSandbox(sandboxId: string, userId: string) {
const res = await fetch("http://localhost:8787/api/sandbox/share", {
await fetch("http://localhost:8787/api/sandbox/share", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
@ -72,29 +72,3 @@ export async function unshareSandbox(sandboxId: string, userId: string) {
revalidatePath(`/code/${sandboxId}`)
}
export async function generateCode(code: string, line: number) {
const res = await fetch(
"https://api.cloudflare.com/client/v4/accounts/d18f2f848da38e37adc9a34eab3d5ae2/ai/run/@cf/meta/llama-3-8b-instruct",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.CF_API_TOKEN}`,
},
body: JSON.stringify({
messages: [
{
role: "system",
content:
"You are an expert coding assistant who reads from an existing code file, and suggests code to add to the file.",
},
{
role: "user",
content: "", //todo
},
],
}),
}
)
}