diff --git a/README.md b/README.md index 03ffd09..0d51d97 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,209 @@ -# CoAgents Starter -This example contains a simple starter project. +# Learn Coding with CopilotKit, CoAgents, and LangGraphs 🚀 -**These instructions assume you are in the `coagents-starter/` directory** +[![CopilotKit](https://img.shields.io/badge/Powered%20By-CopilotKit-brightgreen)](https://github.com/copilotkit) +[![Frontend: Next.js](https://img.shields.io/badge/Frontend-Next.js-orange)](https://nextjs.org/) +[![Demo Video](https://img.shields.io/badge/Watch-Demo%20Video-red)](https://youtu.be/E1q67IDcdMU) +[![Website](https://img.shields.io/badge/Website-Live-brightgreen)](https://learn-coding-with-copilotkit.vercel.app/) -## Running the Agent +--- -First, install the dependencies: +## 📖 **About** -```sh -cd agent -poetry install -``` +**Not everyone can code, but everyone can learn.** -Then, create a `.env` file inside `./agent` with the following: +This project is an AI-powered **DSA/Competitive Programming Helper** with an inbuilt editor to help you: +- Prepare for **coding interviews** +- Start learning how to code from scratch +- **Visualize everything** with intuitive representations -``` -GROQ_API_KEY=... -``` +**Experience the future of coding education!** -IMPORTANT: -Make sure the OpenAI API Key you provide, supports gpt-4o. +🌐 Live Demo: [learn-coding-with-copilotkit.vercel.app](https://learn-coding-with-copilotkit.vercel.app/) -Then, run the demo: +--- -```sh -poetry run demo -``` +## 🌟 **Why CopilotKit?** -## Running the UI +- **Seamless Integration**: Build AI copilots that enhance user experiences effortlessly. +- **Open Source**: Join a thriving community of developers using and contributing to CopilotKit. +- **Future-Ready**: Perfect for in-app AI agents, context-aware chatbots, shared state and beyond! -First, install the dependencies: +Learn more about [CopilotKit](https://github.com/copilotkit). -```sh -cd ./ui -pnpm i -``` +--- -Then, create a `.env` file inside `./ui` with the following: -``` -GROQ_API_KEY=... -``` +## 🛠️ **Project Description** -Then, run the Next.js project: +Learn coding in a revolutionary way using **CopilotKit**, **CoAgents**, and **LangGraphs**! This project showcases how cutting-edge tools can simplify coding education through interactive UI and AI-driven technologies. -```sh -pnpm run dev -``` +### Key Features: +- **🌐 CopilotKit**: Effortlessly integrate AI copilots into your apps, enabling in-app chatbots, context-aware interactions, and more. +- **🤖 CoAgents**: A robust infrastructure for connecting LangGraph agents to humans in the loop, enabling seamless collaboration. +- **📊 LangGraphs**: Visual representations of programming languages to simplify understanding of their structure and syntax. +- **🖥️ Inbuilt Editor**: A powerful coding editor designed to boost productivity and learning. -## Usage +--- -Navigate to [http://localhost:3000](http://localhost:3000). -# LangGraph Studio +## Screenshots -Run LangGraph studio, then load the `./agent` folder into it. +
+ View Achieved Accuracy + +
+ Screenshot 1 + Screenshot 2 + Screenshot 3 + Screenshot 4 +
-Make sure to create teh `.env` mentioned above first! +
-# Troubleshooting -A few things to try if you are running into trouble: +## 🏗️ **Tech Stack** + +### Frontend: +- [Next.js](https://nextjs.org/) +- [ShadCN UI](https://shadcn.dev/) +- [Tailwind CSS](https://tailwindcss.com/) +- [CopilotKit-UI](https://github.com/copilotkit) + +### Backend: +- [Python](https://www.python.org/) +- [FastAPI](https://fastapi.tiangolo.com/) +- [LangGraphs](https://langgraphs.example) +- [CopilotKit](https://github.com/copilotkit) + +### APIs: +- [Groq](https://groq.com/) +- [Llama-70B](https://example.com/) + +--- + +## 📚 **Topics Covered** + +- **TypeScript** +- **Next.js** +- **Competitive Programming** +- **Tailwind CSS** +- **Render Deployment** +- **Koyeb API** +- **ShadCN-UI** +- **Llama-70B** +- **Groq AI** +- **CopilotKit** +- **LangGraph (Python)** +- **CoAgents** + +--- + +## ⚙️ **Installation** + +Clone the repository: + +```bash +git clone https://github.com/.git +``` + +--- + +### 🧩 **Configuration** + +1. Install the dependencies for the backend: + + ```bash + cd agent + poetry install + ``` + +2. Create a `.env` file in the `./agent` directory: + + ```plaintext + GROQ_API_KEY=your_groq_api_key_here + ``` + +3. Run the demo: + + ```bash + poetry run demo + ``` + +--- + +### 🖥️ **Running the UI** + +1. Install the dependencies for the frontend: + + ```bash + cd ./frontend-interface + npm i --legacy-peer-deps + ``` + +2. Create a `.env` file in the `./frontend-interface` directory: + + ```plaintext + GROQ_API_KEY=your_groq_api_key_here + ``` + +3. Run the Next.js project: + + ```bash + npm run dev + ``` + +4. Navigate to [http://localhost:3000](http://localhost:3000). + +--- + +### 🖥️ **Running the Backend** + +1. Install the dependencies for the backend: + + ```bash + cd ./backend + pip install -r -requirements.txt + ``` + +2. Create a `.env` file in the `./frontend-interface` directory: + + ```plaintext + GROQ_API_KEY=your_groq_api_key_here + ``` + +3. Run the FAST API server: + + ```bash + python run_agent.py + ``` + +--- + + +## 🧑‍💻 **Usage** + +1. **Launch LangGraph Studio**: + Run LangGraph Studio and load the `./agent` folder into it. + +2. **Ensure proper configuration**: Make sure the `.env` file is properly configured as mentioned in the setup steps. + +--- + +## 🔧 **Troubleshooting** + +If you encounter any issues, try the following: + +1. Ensure no other application is running on port `8000`. +2. In `/agent/dsa_agent/demo.py`, change `0.0.0.0` to `127.0.0.1` or `localhost`. + +--- + +## 📜 **License** + +This project is [UN Licensed](LICENSE). + +--- + +Give CopilotKit a ⭐ on [GitHub](https://github.com/copilotkit) if you love it! -1. Make sure there is no other local application server running on the 8000 port. -2. Under `/agent/my_agent/demo.py`, change `0.0.0.0` to `127.0.0.1` or to `localhost` diff --git a/agent/.langgraph_api/.langgraph_checkpoint.1.pckl b/agent/.langgraph_api/.langgraph_checkpoint.1.pckl index 07adc3a..53101f1 100644 Binary files a/agent/.langgraph_api/.langgraph_checkpoint.1.pckl and b/agent/.langgraph_api/.langgraph_checkpoint.1.pckl differ diff --git a/agent/.langgraph_api/.langgraph_checkpoint.2.pckl b/agent/.langgraph_api/.langgraph_checkpoint.2.pckl index f2b4bc0..c973a74 100644 Binary files a/agent/.langgraph_api/.langgraph_checkpoint.2.pckl and b/agent/.langgraph_api/.langgraph_checkpoint.2.pckl differ diff --git a/agent/.langgraph_api/.langgraph_ops.pckl b/agent/.langgraph_api/.langgraph_ops.pckl index cbfb18e..13cf20d 100644 Binary files a/agent/.langgraph_api/.langgraph_ops.pckl and b/agent/.langgraph_api/.langgraph_ops.pckl differ diff --git a/agent/.langgraph_api/.langgraph_retry_counter.pckl b/agent/.langgraph_api/.langgraph_retry_counter.pckl index 0a47446..6054584 100644 Binary files a/agent/.langgraph_api/.langgraph_retry_counter.pckl and b/agent/.langgraph_api/.langgraph_retry_counter.pckl differ diff --git a/agent/dsa_agent/edges/__init__.py b/agent/dsa_agent/edges/__init__.py index cf5b54b..230fe8c 100644 --- a/agent/dsa_agent/edges/__init__.py +++ b/agent/dsa_agent/edges/__init__.py @@ -7,8 +7,6 @@ def new_question(state): question = state["question"] - # last_message = messages[-1] - if ( isinstance(question, SystemMessage) and "QUESTION UPDATED" in question.content @@ -60,11 +58,10 @@ def decide_to_generate_visualisation(state): """ print("---ASSESS MERMAID VISUALISATION CODE---") - code = state["code"] - visualization = state["visualization"] + question = state["question"] print("---GRADE CODE---") - score = visualisation_verify.invoke({"code": code,"visualization": visualization}) + score = visualisation_verify.invoke({"question": question}) grade = score.binary_score if grade == "yes": diff --git a/agent/dsa_agent/edges/visualisation_verify.py b/agent/dsa_agent/edges/visualisation_verify.py index 7818efe..6672793 100644 --- a/agent/dsa_agent/edges/visualisation_verify.py +++ b/agent/dsa_agent/edges/visualisation_verify.py @@ -9,21 +9,21 @@ class VerifyVisualisation(BaseModel): """Binary output to verify the mermaid code generated to visualise the python code.""" binary_score: str = Field( - description="Python Code generated is correctly visualised by the mermaid code, 'yes' or 'no'" + description="Mermaid Code generated is correct, 'yes' or 'no'" ) llm = ChatGroq(model="llama-3.3-70b-versatile", temperature=0) viusalisation_verification = llm.with_structured_output(VerifyVisualisation) -system = """You a 4000 rated Competitive Programmer that visualises an optimised and fully detailed working code in python \n - Given a question and the generated code for it \n - You have to provide the appropriate mermaid code to visualise the code approach generated \n - Make sure that your output contains only mermaid code""" +system = """You provide visualisation of a complex problem by generating corresponding mermaid code\n + Given the question\n + You have to provide the appropriate mermaid code to visualise the solution\n + Make sure that your output contains only mermaid flowchart code in the format ```mermaid\nFLOWCHART...```\n""" visualisation_prompt = ChatPromptTemplate.from_messages( [ ("system", system), - ("human", "Python Code Generated: \n\n {code} \n\n Visualised Code Generated in Mermaid: {visualization}"), + ("human", "question: \n\n {question}"), ] ) diff --git a/agent/dsa_agent/nodes/visualiser.py b/agent/dsa_agent/nodes/visualiser.py index 5e2dfcc..f7821d5 100644 --- a/agent/dsa_agent/nodes/visualiser.py +++ b/agent/dsa_agent/nodes/visualiser.py @@ -8,15 +8,15 @@ llm = ChatGroq(model="llama-3.3-70b-versatile", temperature=0) -system = """You a 4000 rated Competitive Programmer that writes optimised and fully detailed working code in python \n - Given a question and the generated code for it \n - You have to provide the appropriate mermaid code to visualise the code approach generated \n - Make sure that your output contains only mermaid code""" +system = """You provide visualisation of a complex problem by generating corresponding mermaid flowchart code\n + Given the question\n + You have to provide the appropriate mermaid flowchart code to visualise the solution\n + Make sure that your output contains only mermaid flowchart code in the format ```mermaid\n{code}\n```\n""" visualisation_prompt = ChatPromptTemplate.from_messages( [ ("system", system), - ("human", "code: \n\n {code} \n\n User question: {question}"), + ("human", "question: \n\n {question}"), ] ) diff --git a/agent/dsa_agent/state.py b/agent/dsa_agent/state.py index 2d72231..e9a76f6 100644 --- a/agent/dsa_agent/state.py +++ b/agent/dsa_agent/state.py @@ -19,10 +19,11 @@ class AgentState(TypedDict): """ question: str - # testCases: Optional[List[str]] # type: ignore - # messages: Annotated[Sequence[BaseMessage], add_messages] + code: Optional[str] explanation: Optional[str] time_complexity: Optional[str] space_complexity: Optional[str] - visualization: Optional[str] \ No newline at end of file + visualization: Optional[str] + # testCases: Optional[List[str]] # type: ignore + # messages: Annotated[Sequence[BaseMessage], add_messages] \ No newline at end of file diff --git a/frontend-interface/README.md b/frontend-interface/README.md deleted file mode 100644 index e215bc4..0000000 --- a/frontend-interface/README.md +++ /dev/null @@ -1,36 +0,0 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). - -## Getting Started - -First, run the development server: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/frontend-interface/app/page.tsx b/frontend-interface/app/page.tsx index 60c5ce9..7fa9993 100644 --- a/frontend-interface/app/page.tsx +++ b/frontend-interface/app/page.tsx @@ -1,9 +1,9 @@ "use client"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { motion, AnimatePresence } from "framer-motion"; import dynamic from "next/dynamic"; -import { Loader2, ExternalLink, Cpu, MessageSquare } from "lucide-react"; +import { Loader2, ExternalLink, Cpu, MessageSquare, Play } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Role, TextMessage } from "@copilotkit/runtime-client-gql"; import ChatInterface from "@/components/ChatInterface"; @@ -12,8 +12,11 @@ import ProblemInput from "@/components/ProblemInput"; import TestCases from "@/components/TestCases"; import ComplexityInput from "@/components/ComplexityInput"; import SolutionDisplay from "@/components/SolutionDisplay"; -import { useCoAgent, useCopilotChat } from "@copilotkit/react-core"; +import { CopilotKit, useCoAgent, useCopilotChat } from "@copilotkit/react-core"; import GitHubStarButtons from "@/components/StarComponent"; +import Image from "next/image"; +import { CopilotPopup, CopilotSidebar } from "@copilotkit/react-ui"; +import "@copilotkit/react-ui/styles.css"; interface AgentState { question: string; @@ -38,14 +41,13 @@ const DSASolutionInterface = () => { const [question, setQuestion] = useState(""); const [loading, setLoading] = useState(false); const [showEditor, setShowEditor] = useState(false); + const [showChat, setShowChat] = useState(false); const [editorCode, setEditorCode] = useState(""); const [solution, setSolution] = useState(null); const [testCases, setTestCases] = useState([{ input: "", output: "" }]); const [timeComplexity, setTimeComplexity] = useState(""); const [spaceComplexity, setSpaceComplexity] = useState(""); const [activeStep, setActiveStep] = useState(0); - const [showChat, setShowChat] = useState(false); - // const [messages, setMessages] = useState([]); const handleOpenEditor = () => { if (solution?.code) { @@ -148,19 +150,11 @@ const DSASolutionInterface = () => { } }; - const handleRetry = () => { - setShowChat(true); - const initialMessage = ` - question: ${question}`; - - run(() => new TextMessage({ role: Role.System, content: initialMessage })); - }; - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { state, setState, run } = useCoAgent({ + const { state, setState } = useCoAgent({ name: "dsa_agent", initialState: { - question: "find greatest of 3 numbers", + question: "", timeComplexity: "", spaceComplexity: "", code: "", @@ -171,24 +165,197 @@ const DSASolutionInterface = () => { const { isLoading, appendMessage, visibleMessages } = useCopilotChat(); + + + const isStateEqual = (prevState: AgentState, newState: Partial) => { + return ( + prevState.question === newState.question && + JSON.stringify(prevState.testCases) === JSON.stringify(newState.testCases) && + prevState.timeComplexity === newState.timeComplexity && + prevState.spaceComplexity === newState.spaceComplexity + ); + }; + + // Modified useEffect + useEffect(() => { + const newState = { + question, + testCases, + timeComplexity, + spaceComplexity, + }; + + // Only update if the state has actually changed + if (!isStateEqual(state, newState)) { + setState((prevState = state) => ({ + ...prevState, + ...newState, + // Preserve other fields that aren't being updated + code: prevState.code, + explanation: prevState.explanation, + visualization: prevState.visualization, + })); + } + }, [question, testCases, timeComplexity, spaceComplexity]); + + + + + + + + + + // useEffect(() => { + // setState({ + // ...state, + // question: question, + // testCases: testCases, + // timeComplexity: timeComplexity, + // spaceComplexity: spaceComplexity, + // }); + // }, [question, testCases, timeComplexity, spaceComplexity]); + + const handleRetry = () => { + if (!question.trim()) { + console.error("Question is empty"); + return; + } + + setShowChat(true); + + // First, send the problem context + const contextMessage = new TextMessage({ + id: "context-" + Date.now().toString(), + role: Role.System, + content: ` + Language: Python + Status: New Problem + + Question: + ${question} + `, + }); + + // Then send the user's question + const userMessage = new TextMessage({ + id: "user-" + Date.now().toString(), + role: Role.User, + content: question, + }); + + // Send messages with a slight delay + setTimeout(() => { + appendMessage(contextMessage); + setTimeout(() => { + appendMessage(userMessage); + }, 100); + }, 100); + }; + + // Add this function to handle solution updates from chat + const handleSolutionUpdate = (content: string) => { + try { + // Extract code block + const codeMatch = content.match(/```python\n([\s\S]*?)```/); + const code = codeMatch ? codeMatch[1].trim() : ""; + + // Extract explanation (text before code block) + const explanation = content.split("```")[0].trim(); + + // Extract complexities + const timeMatch = content.match(/[Tt]ime [Cc]omplexity:?\s*(O\([^)]+\))/); + const spaceMatch = content.match( + /[Ss]pace [Cc]omplexity:?\s*(O\([^)]+\))/ + ); + + // // Extract visualization if present + // const visualMatch = content.match(/```mermaid\n([\s\S]*?)```/); + + // Update all states + setSolution(prevSolution => ({ + code: code, + explanation: explanation, + visualization: prevSolution?.visualization // Preserve existing visualization + })); + + if (timeMatch) setTimeComplexity(timeMatch[1]); + if (spaceMatch) setSpaceComplexity(spaceMatch[1]); + if (code) setEditorCode(code); + + setState({ + ...state, + code: code, + explanation: explanation, + visualization: state.visualization, // Preserve existing visualization + timeComplexity: timeMatch ? timeMatch[1] : state.timeComplexity, + spaceComplexity: spaceMatch ? spaceMatch[1] : state.spaceComplexity, + }); + } catch (error) { + console.error("Error parsing solution:", error); + } + }; + + useEffect(() => { + const lastMessage = visibleMessages[visibleMessages.length - 1]; + const textMessage = lastMessage as TextMessage; + if ( + textMessage?.role === Role.Assistant && + typeof textMessage.content === "string" + ) { + handleSolutionUpdate((lastMessage as TextMessage).content); + } + }, [visibleMessages]); + + + const [isPlaying, setIsPlaying] = useState(false); + const videoUrl = "https://vimeo.com/1044157863"; + + // Extract Vimeo video ID from the URL and generate embeddable URL + const getVimeoEmbedUrl = (url: string) => { + const videoId = url.split("vimeo.com/")[1]; + return `https://player.vimeo.com/video/${videoId}`; + }; + + const embedUrl = getVimeoEmbedUrl(videoUrl); + const handlePlayClick = () => { + setIsPlaying(true); + }; + return ( -
- +
+ +
+ + -

- Learn Coding with CopilotKit -

+ {/* Header */} + +

+ Learn Coding with +

+
+ CopilotKit Logo +
+
{
+ {/* Video Section */} + +
+ {isPlaying ? ( + + ) : ( + <> + CoAgents and Langgraph +
+
+
+
+ +
+
+

See A Full Fledged Demo

+

Watch the demo insight during development

+
+
+ +
+
+ + )} +
+
+ {!showChat && ( + + + + + + )} + + + {showChat && ( { animate={{ width: "50%", opacity: 1 }} exit={{ width: 0, opacity: 0 }} transition={{ duration: 0.3 }} - className="h-screen sticky top-0 right-0 bg-gray-100 dark:bg-gray-900 shadow-2xl" + className="h-screen sticky top-0 right-0 bg-white dark:bg-gray-800 shadow-2xl" >
-
+

Chat with AI

); }; diff --git a/frontend-interface/components/ChatInterface.tsx b/frontend-interface/components/ChatInterface.tsx index ae44d6d..f0f4708 100644 --- a/frontend-interface/components/ChatInterface.tsx +++ b/frontend-interface/components/ChatInterface.tsx @@ -1,4 +1,4 @@ -"use client" +// "use client" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" import { Button } from "@/components/ui/button" @@ -12,11 +12,13 @@ import { useEffect, useRef, useState } from "react" export default function ChatInterface({ isLoading, appendMessage, - visibleMessages + visibleMessages, + }: { isLoading: boolean appendMessage: (message: TextMessage) => void visibleMessages: TextMessage[] + }) { const messagesEndRef = useRef(null) const chatContainerRef = useRef(null) @@ -32,46 +34,68 @@ export default function ChatInterface({ scrollToBottom() }, [visibleMessages]) + useEffect(() => { + // Parse messages for solution content + const lastMessage = visibleMessages[visibleMessages.length - 1]; + if (lastMessage?.role === Role.Assistant) { + try { + const content = lastMessage.content; + if (typeof content === 'string' && content.includes('```python')) { + const solution = { + code: content.match(/```python\n([\s\S]*?)```/)?.[1] || '', + explanation: content.split('```')[0].trim(), + timeComplexity: content.match(/Time Complexity: (O\([^)]+\))/)?.[1] || '', + spaceComplexity: content.match(/Space Complexity: (O\([^)]+\))/)?.[1] || '' + }; + } + } catch (error) { + console.error('Error parsing solution:', error); + } + } + }, [visibleMessages]); + const [inputValue, setInputValue] = useState("") const handleSendMessage = () => { if (inputValue.trim()) { - appendMessage(new TextMessage({ + const message = new TextMessage({ content: inputValue, - role: Role.User - })) + role: Role.User, + id: Date.now().toString() + }); + appendMessage(message) setInputValue("") } } return ( - + - {(visibleMessages as TextMessage[]).map((message, index) => message.content && ( + {visibleMessages.map((message, index) => (
- {(message.role === "assistant") && ( + {message.role === Role.Assistant && ( AI )}
- {message.content} + {typeof message.content === 'string' ? message.content : ''}
- {(message.role === "user") && ( + {message.role === Role.User && ( ME @@ -85,28 +109,31 @@ export default function ChatInterface({ AI -
+
)}
- +
setInputValue(e.target.value)} - onKeyDown={(e) => e.key === 'Enter' && handleSendMessage()} + onKeyDown={(e) => e.key === 'Enter' && !e.shiftKey && handleSendMessage()} className="flex-1" /> -
) -} - +} \ No newline at end of file diff --git a/frontend-interface/package-lock.json b/frontend-interface/package-lock.json index 2007445..40e71fe 100644 --- a/frontend-interface/package-lock.json +++ b/frontend-interface/package-lock.json @@ -15,8 +15,10 @@ "@monaco-editor/react": "^4.6.0", "@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-avatar": "^1.1.2", + "@radix-ui/react-dialog": "^1.1.4", "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-select": "^2.1.4", + "@radix-ui/react-separator": "^1.1.1", "@radix-ui/react-slider": "^1.2.2", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tabs": "^1.1.2", @@ -2392,6 +2394,42 @@ } } }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.4.tgz", + "integrity": "sha512-Ur7EV1IwQGCyaAuyDRiOLA5JIUZxELJljF+MbM/2NC0BYwfuRrbpS30BiQBJrVruscgUkieKkqXYDOoByaxIoA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.3", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-portal": "1.1.3", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-slot": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "^2.6.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-direction": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", @@ -2678,6 +2716,29 @@ } } }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.1.tgz", + "integrity": "sha512-RRiNRSrD8iUiXriq/Y5n4/3iE8HzqgLHsusUSg5jVpU2+3tqcUFPJXHDymwEypunc2sWxDUS3UC+rkZRlHedsw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slider": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.2.2.tgz", diff --git a/frontend-interface/package.json b/frontend-interface/package.json index c01c575..a8b20c0 100644 --- a/frontend-interface/package.json +++ b/frontend-interface/package.json @@ -16,8 +16,10 @@ "@monaco-editor/react": "^4.6.0", "@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-avatar": "^1.1.2", + "@radix-ui/react-dialog": "^1.1.4", "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-select": "^2.1.4", + "@radix-ui/react-separator": "^1.1.1", "@radix-ui/react-slider": "^1.2.2", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tabs": "^1.1.2", diff --git a/frontend-interface/public/thumbnail.png b/frontend-interface/public/thumbnail.png new file mode 100644 index 0000000..227f138 Binary files /dev/null and b/frontend-interface/public/thumbnail.png differ