diff --git a/app/api/projects/[id]/tasks/route.ts b/app/api/projects/[id]/tasks/route.ts index b53c766..c1c3c70 100644 --- a/app/api/projects/[id]/tasks/route.ts +++ b/app/api/projects/[id]/tasks/route.ts @@ -1,3 +1,61 @@ +// import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs"; +// import { Database } from "@/types/supabase"; +// import prisma from "@/lib/prisma"; +// import { NextRequest, NextResponse } from "next/server"; +// import { revalidatePath } from "next/cache"; +// import { cookies } from "next/headers"; + +// export async function POST( +// req: NextRequest, +// { params }: { params: { id: string } } +// ) { +// try { +// const supabase = createRouteHandlerClient({ cookies }); + +// const { +// data: { session }, +// } = await supabase.auth.getSession(); + +// if (!session) { +// throw new Error("Unauthorized"); +// } + +// const { description, status, priority, dueDate, tags } = await req.json(); + +// const newTask = await prisma.task.create({ +// data: { +// description, +// status, +// priority, +// dueDate, +// tags, +// projectId: Number(params.id), +// }, +// }); + +// await prisma.userProfile_Task.create({ +// data: { +// userProfileId: session.user.id, +// taskId: newTask.id, +// }, +// }); + +// const res = { +// ...newTask, +// id: String(newTask.id), +// projectId: String(newTask.projectId), +// }; + +// const path = req.nextUrl.searchParams.get("path") || "/"; +// revalidatePath(path); + +// return NextResponse.json(res, { status: 201 }); +// } catch (err: any) { +// return NextResponse.json({ message: err.message }, { status: 500 }); +// } finally { +// await prisma.$disconnect(); +// } +// } import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs"; import { Database } from "@/types/supabase"; import prisma from "@/lib/prisma"; @@ -20,36 +78,51 @@ export async function POST( throw new Error("Unauthorized"); } - const { description, status, priority, dueDate, tags } = await req.json(); + const input = await req.json(); + console.log(input); + let newTasks = []; - const newTask = await prisma.task.create({ - data: { - description, - status, - priority, - dueDate, - tags, - projectId: Number(params.id), - }, - }); + if (Array.isArray(input)) { + // Handle multiple tasks + for (const task of input) { + const newTask = await prisma.task.create({ + data: { + description: task.task, + projectId: Number(params.id), + }, + }); + newTasks.push({ + ...newTask, + id: String(newTask.id), + projectId: String(newTask.projectId), + }); + } + const path = req.nextUrl.searchParams.get("path") || "/"; + revalidatePath(path); - await prisma.userProfile_Task.create({ - data: { - userProfileId: session.user.id, - taskId: newTask.id, - }, - }); + return NextResponse.json(newTasks, { status: 201 }); + } else { + // Handle single task + const newTask = await prisma.task.create({ + data: { + description: input.description, + projectId: Number(params.id), + }, + }); - const res = { - ...newTask, - id: String(newTask.id), - projectId: String(newTask.projectId), - }; + const res = { + ...newTask, + id: String(newTask?.id), + projectId: String(newTask?.projectId), + }; - const path = req.nextUrl.searchParams.get("path") || "/"; - revalidatePath(path); + console.log(res); - return NextResponse.json(res, { status: 201 }); + const path = req.nextUrl.searchParams.get("path") || "/"; + revalidatePath(path); + + return NextResponse.json(res, { status: 201 }); + } } catch (err: any) { return NextResponse.json({ message: err.message }, { status: 500 }); } finally { diff --git a/app/projects/[id]/page.tsx b/app/projects/[id]/page.tsx index 1a49e6e..8243708 100644 --- a/app/projects/[id]/page.tsx +++ b/app/projects/[id]/page.tsx @@ -11,6 +11,14 @@ import { DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; +import { + Sheet, + SheetContent, + SheetDescription, + SheetHeader, + SheetTitle, + SheetTrigger, +} from "@/components/ui/sheet"; import { Form, FormControl, @@ -34,7 +42,8 @@ const taskSchema = z.object({ export default function Project({ params }: { params: { id: string } }) { const [project, setProject] = useState(); const [loading, setLoading] = useState(true); - const [taskOpen, setTaskOpen] = useState(false); + const [open, setOpen] = useState(false); + const [task, setTask] = useState(); const form = useForm>({ resolver: zodResolver(taskSchema), defaultValues: { @@ -82,7 +91,7 @@ export default function Project({ params }: { params: { id: string } }) { }; }); - setTaskOpen(false); + setOpen(false); } catch (err) { console.error("Failed to create task:", err); } @@ -92,75 +101,86 @@ export default function Project({ params }: { params: { id: string } }) { if (!project) return

No project found.

; return ( -
-

{project.title}

-

{project.description}

+

{project.title}

{project.description}

- - - Add Task - - - - Add Task - -
- - ( - - Task Description - - - - - - )} - /> - ( - - Task Status - - - - - - )} - /> - ( - - Task Priority - - - - - - )} - /> - - - -
-
-
-
-

Tasks

- {project.tasks?.map((task: Task) => ( -
-

{task.description}

-
- ))} +
+ + + Add Task + + + + Add Task + +
+ + ( + + Task Description + + + + + + )} + /> + ( + + Task Status + + + + + + )} + /> + ( + + Task Priority + + + + + + )} + /> + + + +
+
+
+
+

Tasks

+ {project.tasks?.map((task: Task) => ( +
+ console.log("hey")}> + {task.description} + +
+ ))} +
+ + + Are you sure absolutely sure? + + This action cannot be undone. This will permanently delete your + account and remove your data from our servers. + + +
-
+ ); } diff --git a/app/projects/page.tsx b/app/projects/page.tsx index 8c99303..17db7c7 100644 --- a/app/projects/page.tsx +++ b/app/projects/page.tsx @@ -5,6 +5,7 @@ import { Project } from "@/types/models"; import { Button, buttonVariants } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; +import { Progress } from "@/components/ui/progress"; import { X } from "lucide-react"; import { Dialog, @@ -26,6 +27,8 @@ import { import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import * as z from "zod"; +import { OpenAIChatApi } from "llm-api"; +import { completion } from "zod-gpt"; const projectSchema = z.object({ title: z.string().min(3, "Title must be at least 3 characters"), @@ -39,6 +42,9 @@ export default function Projects() { const [stackInput, setStackInput] = useState(""); const [loading, setLoading] = useState(true); const [open, setOpen] = useState(false); + const [features, setFeatures] = useState([]); + const [step, setStep] = useState(0); + const [progress, setProgress] = useState(0); const form = useForm>({ resolver: zodResolver(projectSchema), defaultValues: { @@ -70,23 +76,100 @@ export default function Projects() { async function handleSubmit(values: z.infer) { try { + // 1. Create a new project const res = await fetch("/api/projects", { method: "POST", - headers: { - "Content-Type": "application/json", - }, + headers: { "Content-Type": "application/json" }, body: JSON.stringify(values), }); - if (!res.ok) throw new Error("HTTP status " + res.status); const newProject = await res.json(); setProjects([...projects, newProject]); - setOpen(false); + + // 2. Initialize OpenAI client + setStep(1); + const openai = new OpenAIChatApi( + { + apiKey: "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", + }, + { model: "gpt-3.5-turbo-16k" } + ); + + // 3. Generate features + const prompt = `Based on the following project information, generate features for this tech project: + Project Description: ${newProject.description} + Tech Stack: ${newProject.stack.join(", ")}`; + const featuresRes = await completion(openai, prompt, { + schema: z.object({ + features: z.array(z.object({ feature: z.string() })), + }), + }); + const features = featuresRes.data.features.map((f) => f.feature); + setFeatures(features); + setStep(2); } catch (err) { console.error("Failed to create project:", err); } } + async function handleGenerateTasks() { + try { + // Move to the task generation step and reset progress + setStep(3); + setProgress(0); + + // Get the newly created project + const newProject = projects[projects.length - 1]; + + // Initialize OpenAI client + const openai = new OpenAIChatApi( + { + apiKey: "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", + }, + { model: "gpt-3.5-turbo-16k" } + ); + + // Generate tasks for each feature + const taskList = []; + for (let i = 0; i < features.length; i++) { + const feature = features[i]; + const taskPrompt = ` + Given the following project description, feature description, and tech stack, generate a list of tasks needed to implement the feature: + Project: ${newProject.title} + Feature: ${feature} + Tech Stack: ${newProject.stack.join(", ")}`; + + // Get tasks for the current feature + const tasksRes = await completion(openai, taskPrompt, { + schema: z.object({ tasks: z.array(z.object({ task: z.string() })) }), + }); + + // Add the tasks to the task list + taskList.push(...tasksRes.data.tasks); + + // Update the progress + setProgress(((i + 1) / features.length) * 100); + } + + // Post the generated tasks to the project + const taskRes = await fetch(`/api/projects/${newProject.id}/tasks`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(taskList), + }); + if (!taskRes.ok) throw new Error("HTTP status " + taskRes.status); + + // Log the created tasks + const createdTasks = await taskRes.json(); + console.log("Tasks created:", createdTasks); + + // Close the dialog + setOpen(false); + } catch (err) { + console.error("Failed to generate tasks:", err); + } + } + const keyHandler = (e: React.KeyboardEvent) => { if (e.key === "Enter" || e.key === "Tab") { e.preventDefault(); @@ -102,100 +185,145 @@ export default function Projects() { Open - - - Add Project - -
- - ( - - Project Title - - - - - - )} - /> - ( - - Project Description - - - - - - )} - /> - ( - - Github Repository URL - - - - - - )} - /> - ( - - Tech Stack - - setStackInput(e.target.value)} - onKeyDown={keyHandler} - /> - - - {form.getValues("stack").map((stack) => ( - - {stack}{" "} - - setValue( - "stack", - form - .getValues("stack") - .filter((s) => s !== stack) - ) - } - /> - - ))} - - - - )} - /> - - - -
-
-
+ {step === 0 && ( + + + Add Project + +
+ + ( + + Project Title + + + + + + )} + /> + ( + + Project Description + + + + + + )} + /> + ( + + Github Repository URL + + + + + + )} + /> + ( + + Tech Stack + + setStackInput(e.target.value)} + onKeyDown={keyHandler} + /> + + + {form.getValues("stack").map((stack) => ( + + {stack}{" "} + + setValue( + "stack", + form + .getValues("stack") + .filter((s) => s !== stack) + ) + } + /> + + ))} + + + + )} + /> + + + +
+
+
+ )} + {step === 1 && ( + + + Generating Features + +

Generating features for your project...

+
+
+
+ )} + {step === 2 && ( + + + Features Generated + +
+ {features.map((feature, index) => ( + + {feature}{" "} + + setFeatures(features.filter((_, i) => i !== index)) + } + /> + + ))} +
+ +
+
+
+ )} + {step === 3 && ( + + + Generating Tasks + + + + + + )} {loading ? (

Loading...

diff --git a/components/ui/progress.tsx b/components/ui/progress.tsx new file mode 100644 index 0000000..5c87ea4 --- /dev/null +++ b/components/ui/progress.tsx @@ -0,0 +1,28 @@ +"use client" + +import * as React from "react" +import * as ProgressPrimitive from "@radix-ui/react-progress" + +import { cn } from "@/lib/utils" + +const Progress = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, value, ...props }, ref) => ( + + + +)) +Progress.displayName = ProgressPrimitive.Root.displayName + +export { Progress } diff --git a/components/ui/sheet.tsx b/components/ui/sheet.tsx new file mode 100644 index 0000000..98cdd40 --- /dev/null +++ b/components/ui/sheet.tsx @@ -0,0 +1,144 @@ +"use client" + +import * as React from "react" +import * as SheetPrimitive from "@radix-ui/react-dialog" +import { cva, type VariantProps } from "class-variance-authority" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Sheet = SheetPrimitive.Root + +const SheetTrigger = SheetPrimitive.Trigger + +const SheetClose = SheetPrimitive.Close + +const SheetPortal = ({ + className, + ...props +}: SheetPrimitive.DialogPortalProps) => ( + +) +SheetPortal.displayName = SheetPrimitive.Portal.displayName + +const SheetOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetOverlay.displayName = SheetPrimitive.Overlay.displayName + +const sheetVariants = cva( + "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500", + { + variants: { + side: { + top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top", + bottom: + "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", + left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm", + right: + "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm", + }, + }, + defaultVariants: { + side: "right", + }, + } +) + +interface SheetContentProps + extends React.ComponentPropsWithoutRef, + VariantProps {} + +const SheetContent = React.forwardRef< + React.ElementRef, + SheetContentProps +>(({ side = "right", className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +SheetContent.displayName = SheetPrimitive.Content.displayName + +const SheetHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +SheetHeader.displayName = "SheetHeader" + +const SheetFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +SheetFooter.displayName = "SheetFooter" + +const SheetTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetTitle.displayName = SheetPrimitive.Title.displayName + +const SheetDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetDescription.displayName = SheetPrimitive.Description.displayName + +export { + Sheet, + SheetTrigger, + SheetClose, + SheetContent, + SheetHeader, + SheetFooter, + SheetTitle, + SheetDescription, +} diff --git a/package.json b/package.json index 4f88710..643fe55 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@prisma/client": "5.0.0", "@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-progress": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", "@supabase/auth-helpers-nextjs": "^0.7.3", "@supabase/supabase-js": "^2.31.0", @@ -24,6 +25,7 @@ "clsx": "^2.0.0", "eslint": "8.45.0", "eslint-config-next": "13.4.12", + "llm-api": "^0.9.5", "lucide-react": "^0.263.1", "next": "13.4.12", "postcss": "8.4.27", @@ -35,7 +37,8 @@ "tailwindcss": "3.3.3", "tailwindcss-animate": "^1.0.6", "typescript": "5.1.6", - "zod": "^3.21.4" + "zod": "^3.21.4", + "zod-gpt": "^0.7.2" }, "devDependencies": { "encoding": "^0.1.13", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a36b6c4..bb67ad6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ dependencies: '@radix-ui/react-label': specifier: ^2.0.2 version: 2.0.2(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-progress': + specifier: ^1.0.3 + version: 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-slot': specifier: ^1.0.2 version: 1.0.2(@types/react@18.2.16)(react@18.2.0) @@ -50,6 +53,9 @@ dependencies: eslint-config-next: specifier: 13.4.12 version: 13.4.12(eslint@8.45.0)(typescript@5.1.6) + llm-api: + specifier: ^0.9.5 + version: 0.9.5(encoding@0.1.13) lucide-react: specifier: ^0.263.1 version: 0.263.1(react@18.2.0) @@ -86,6 +92,9 @@ dependencies: zod: specifier: ^3.21.4 version: 3.21.4 + zod-gpt: + specifier: ^0.7.2 + version: 0.7.2(llm-api@0.9.5)(zod@3.21.4) devDependencies: encoding: @@ -107,6 +116,22 @@ packages: engines: {node: '>=10'} dev: false + /@anthropic-ai/sdk@0.5.8(encoding@0.1.13): + resolution: {integrity: sha512-iHenjcE2Q/az6VZiP1DueOSvKNRmxsly6Rx2yjJBoy7OBYVFGVjEdgs2mPQHtTX0ibKAR7tPq6F6MQbKDPWcKg==} + dependencies: + '@types/node': 18.17.1 + '@types/node-fetch': 2.6.4 + abort-controller: 3.0.0 + agentkeepalive: 4.3.0 + digest-fetch: 1.3.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.6.12(encoding@0.1.13) + transitivePeerDependencies: + - encoding + - supports-color + dev: false + /@babel/runtime@7.22.6: resolution: {integrity: sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==} engines: {node: '>=6.9.0'} @@ -589,6 +614,28 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-progress@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-5G6Om/tYSxjSeEdrb1VfKkfZfn/1IlPWd731h2RfPuSbIfNUgfqAwbKfJCg/PP6nuUCTrYzalwHSpSinoWoCag==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.22.6 + '@radix-ui/react-context': 1.0.1(@types/react@18.2.16)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.16)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.16 + '@types/react-dom': 18.2.7 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-slot@1.0.2(@types/react@18.2.16)(react@18.2.0): resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==} peerDependencies: @@ -751,6 +798,17 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: false + /@types/node-fetch@2.6.4: + resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==} + dependencies: + '@types/node': 20.4.5 + form-data: 3.0.1 + dev: false + + /@types/node@18.17.1: + resolution: {integrity: sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw==} + dev: false + /@types/node@20.4.5: resolution: {integrity: sha512-rt40Nk13II9JwQBdeYqmbn2Q6IVTA5uPhvSO+JVqdXw/6/4glI6oR9ezty/A9Hg5u7JH4OmYmuQ+XvjKm0Datg==} dev: false @@ -849,6 +907,13 @@ packages: eslint-visitor-keys: 3.4.1 dev: false + /abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + dependencies: + event-target-shim: 5.0.1 + dev: false + /acorn-jsx@5.3.2(acorn@8.10.0): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -863,6 +928,17 @@ packages: hasBin: true dev: false + /agentkeepalive@4.3.0: + resolution: {integrity: sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==} + engines: {node: '>= 8.0.0'} + dependencies: + debug: 4.3.4 + depd: 2.0.0 + humanize-ms: 1.2.1 + transitivePeerDependencies: + - supports-color + dev: false + /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: @@ -986,6 +1062,10 @@ packages: resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} dev: false + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + /autoprefixer@10.4.14(postcss@8.4.27): resolution: {integrity: sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==} engines: {node: ^10 || ^12 || >=14} @@ -1022,6 +1102,14 @@ packages: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: false + /base-64@0.1.0: + resolution: {integrity: sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==} + dev: false + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + /big-integer@1.6.51: resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} engines: {node: '>=0.6'} @@ -1115,6 +1203,10 @@ packages: supports-color: 7.2.0 dev: false + /charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + dev: false + /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -1156,6 +1248,13 @@ packages: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} dev: false + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -1182,6 +1281,10 @@ packages: which: 2.0.2 dev: false + /crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + dev: false + /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -1272,6 +1375,16 @@ packages: object-keys: 1.1.1 dev: false + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + /dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -1285,6 +1398,13 @@ packages: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} dev: false + /digest-fetch@1.3.0: + resolution: {integrity: sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==} + dependencies: + base-64: 0.1.0 + md5: 2.3.0 + dev: false + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -1707,6 +1827,11 @@ packages: engines: {node: '>=0.10.0'} dev: false + /event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + dev: false + /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -1812,6 +1937,27 @@ packages: is-callable: 1.2.7 dev: false + /form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + dev: false + + /form-data@3.0.1: + resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + dev: false + /fraction.js@4.2.0: resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} dev: false @@ -2030,6 +2176,12 @@ packages: engines: {node: '>=14.18.0'} dev: false + /humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + dependencies: + ms: 2.1.3 + dev: false + /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -2109,6 +2261,10 @@ packages: has-tostringtag: 1.0.0 dev: false + /is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + dev: false + /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -2260,6 +2416,12 @@ packages: resolution: {integrity: sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==} dev: false + /js-tiktoken@1.0.7: + resolution: {integrity: sha512-biba8u/clw7iesNEWLOLwrNGoBP2lA+hTaBLs/D45pJdUPFXyxD6nhcDVtADChghv4GgyAiMKYMiRx7x6h7Biw==} + dependencies: + base64-js: 1.5.1 + dev: false + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: false @@ -2286,6 +2448,15 @@ packages: minimist: 1.2.8 dev: false + /jsonic@1.0.1: + resolution: {integrity: sha512-6GitEN4plTuB/I1o9kDZl7Pgc+DvFG1BG88IqaUz4eQglCA1uAgxWdXhLNA6ffaYsmzPjOysDpp6CYTwRiuXLw==} + dev: false + + /jsonrepair@3.2.0: + resolution: {integrity: sha512-6eHBc2z5vipym4S8rzTcCXQBLWpkSzi9bk7I3xTdUxRzXyYvfjoVZzJ97N4C/9vcKI9NgNp3slPwHufDr0rFYw==} + hasBin: true + dev: false + /jsx-ast-utils@3.3.4: resolution: {integrity: sha512-fX2TVdCViod6HwKEtSWGHs57oFhVfCMwieb9PuRDgjDPh5XeqJiHFFFJCHxU5cnTc3Bu/GRL+kPiFmw8XWOfKw==} engines: {node: '>=4.0'} @@ -2323,6 +2494,22 @@ packages: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: false + /llm-api@0.9.5(encoding@0.1.13): + resolution: {integrity: sha512-4BgWU+DwC8zuNKyeCWu/z35ogce2+46zzqm2qBStVJBkLJLp+LaiiNUIlb1pxW/2gMW4kJ1g/WEKqRgkVuyjIw==} + dependencies: + '@anthropic-ai/sdk': 0.5.8(encoding@0.1.13) + debug: 4.3.4 + js-tiktoken: 1.0.7 + jsonic: 1.0.1 + jsonrepair: 3.2.0 + lodash: 4.17.21 + openai-edge: 1.2.2 + type-fest: 3.13.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -2334,6 +2521,10 @@ packages: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: false + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -2356,6 +2547,14 @@ packages: react: 18.2.0 dev: false + /md5@2.3.0: + resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + is-buffer: 1.1.6 + dev: false + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: false @@ -2373,6 +2572,18 @@ packages: picomatch: 2.3.1 dev: false + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + /mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -2470,6 +2681,11 @@ packages: - babel-plugin-macros dev: false + /node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + dev: false + /node-fetch@2.6.12(encoding@0.1.13): resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==} engines: {node: 4.x || >=6.0.0} @@ -2609,6 +2825,11 @@ packages: is-wsl: 2.2.0 dev: false + /openai-edge@1.2.2: + resolution: {integrity: sha512-C3/Ao9Hkx5uBPv9YFBpX/x59XMPgPUU4dyGg/0J2sOJ7O9D98kD+lfdOc7v/60oYo5xzMGct80uFkYLH+X2qgw==} + engines: {node: '>=18'} + dev: false + /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} @@ -3296,6 +3517,11 @@ packages: engines: {node: '>=10'} dev: false + /type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + dev: false + /type@1.2.0: resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} dev: false @@ -3444,6 +3670,11 @@ packages: graceful-fs: 4.2.11 dev: false + /web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + dev: false + /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} dev: false @@ -3521,6 +3752,32 @@ packages: engines: {node: '>=10'} dev: false + /zod-gpt@0.7.2(llm-api@0.9.5)(zod@3.21.4): + resolution: {integrity: sha512-Ak2nmlR2a6xnPcm3JauwQJnTETg47H3Kca065sFuhTH6v6rVk+yOIuM0rFxZimDvz73T0oCX4NnVUT2Zzio0pw==} + peerDependencies: + llm-api: ^0.9.5 + zod: ^3.21.4 + dependencies: + debug: 4.3.4 + jsonic: 1.0.1 + jsonrepair: 3.2.0 + llm-api: 0.9.5(encoding@0.1.13) + lodash: 4.17.21 + type-fest: 3.13.1 + zod: 3.21.4 + zod-to-json-schema: 3.21.4(zod@3.21.4) + transitivePeerDependencies: + - supports-color + dev: false + + /zod-to-json-schema@3.21.4(zod@3.21.4): + resolution: {integrity: sha512-fjUZh4nQ1s6HMccgIeE0VP4QG/YRGPmyjO9sAh890aQKPEk3nqbfUXhMFaC+Dr5KvYBm8BCyvfpZf2jY9aGSsw==} + peerDependencies: + zod: ^3.21.4 + dependencies: + zod: 3.21.4 + dev: false + /zod@3.21.4: resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==} dev: false