From 15cc6234edea62517d7c0fd2137450a8ea21cc50 Mon Sep 17 00:00:00 2001 From: ibigio Date: Wed, 1 May 2024 17:36:43 -0400 Subject: [PATCH] Initial commit --- .env.example | 5 + .gitignore | 38 + LICENSE | 21 + README.md | 64 + app/api/assistants/files/route.tsx | 79 + app/api/assistants/route.ts | 39 + .../threads/[threadId]/actions/route.ts | 21 + .../threads/[threadId]/messages/route.ts | 23 + app/api/assistants/threads/route.ts | 10 + app/assistant-config.ts | 1 + app/components/chat.module.css | 89 + app/components/chat.tsx | 250 +++ app/components/file-viewer.module.css | 78 + app/components/file-viewer.tsx | 97 + app/components/warnings.module.css | 57 + app/components/warnings.tsx | 47 + app/components/weather-widget.module.css | 59 + app/components/weather-widget.tsx | 44 + app/examples/all/page.module.css | 44 + app/examples/all/page.tsx | 58 + app/examples/basic-chat/page.module.css | 13 + app/examples/basic-chat/page.tsx | 17 + app/examples/file-search/page.tsx | 25 + app/examples/function-calling/page.tsx | 49 + app/examples/shared/page.module.css | 43 + app/favicon.png | Bin 0 -> 7038 bytes app/globals.css | 73 + app/layout.tsx | 24 + app/page.module.css | 47 + app/page.tsx | 30 + app/utils/weather.ts | 15 + jsconfig.json | 7 + next.config.mjs | 4 + package-lock.json | 1791 +++++++++++++++++ package.json | 23 + public/openai.svg | 1 + tsconfig.json | 34 + 37 files changed, 3320 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 app/api/assistants/files/route.tsx create mode 100644 app/api/assistants/route.ts create mode 100644 app/api/assistants/threads/[threadId]/actions/route.ts create mode 100644 app/api/assistants/threads/[threadId]/messages/route.ts create mode 100644 app/api/assistants/threads/route.ts create mode 100644 app/assistant-config.ts create mode 100644 app/components/chat.module.css create mode 100644 app/components/chat.tsx create mode 100644 app/components/file-viewer.module.css create mode 100644 app/components/file-viewer.tsx create mode 100644 app/components/warnings.module.css create mode 100644 app/components/warnings.tsx create mode 100644 app/components/weather-widget.module.css create mode 100644 app/components/weather-widget.tsx create mode 100644 app/examples/all/page.module.css create mode 100644 app/examples/all/page.tsx create mode 100644 app/examples/basic-chat/page.module.css create mode 100644 app/examples/basic-chat/page.tsx create mode 100644 app/examples/file-search/page.tsx create mode 100644 app/examples/function-calling/page.tsx create mode 100644 app/examples/shared/page.module.css create mode 100644 app/favicon.png create mode 100644 app/globals.css create mode 100644 app/layout.tsx create mode 100644 app/page.module.css create mode 100644 app/page.tsx create mode 100644 app/utils/weather.ts create mode 100644 jsconfig.json create mode 100644 next.config.mjs create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/openai.svg create mode 100644 tsconfig.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..e0066fe --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +# DO NOT COMMIT THIS FILE - IT WILL CONTAIN YOUR SENSITIVE KEYS. +# Instead, rename this file to ".env" instead of ".env.example". (.env will not be committed) + +# Create an OpenAI API key at https://platform.openai.com/account/api-keys +OPENAI_API_KEY="sk-123..." \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b30eb37 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts +openai-v4.29.0-beta.1.tgz diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..91ba98f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 OpenAI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..72b8f52 --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# OpenAI Assistants API Quickstart +A quick-start template using the OpenAI [Assistants API](https://platform.openai.com/docs/assistants/overview) with [Next.js](https://nextjs.org/docs). +
+
+![openai_assistants_quickstart](https://github.com/openai/openai-assistants-quickstart-internal/assets/25421602/3ea9c3d9-2bc6-410a-a7bf-dcae03cae899) + + + +## Quickstart Setup + +### 1. Clone repo +```shell +git clone https://github.com/openai/openai-assistants-quickstart.git +cd openai-assistants-quickstart +``` + +### 2. Set your [OpenAI API key](https://platform.openai.com/api-keys) +```shell +export OPENAI_API_KEY="sk_..." +``` +(or in `.env.example` and rename it to `.env`). + +### 3. Install dependencies +```shell +npm install +``` + +### 4. Run +```shell +npm run dev +``` + +### 5. Navigate to [http://localhost:3000](http://localhost:3000). + +## Overview + +This project is intended to serve as a template for using the Assistants API in Next.js with [streaming](https://platform.openai.com/docs/assistants/overview/step-4-create-a-run), tool use ([code interpreter](https://platform.openai.com/docs/assistants/tools/code-interpreter) and [file search](https://platform.openai.com/docs/assistants/tools/file-search)), and [function calling](https://platform.openai.com/docs/assistants/tools/function-calling). While there are multiple pages to demonstrate each of these capabilities, they all use the same underlying assistant with all capabilities enabled. + +The main logic for chat will be found in the `Chat` component in `app/components/chat.tsx`, and the handlers starting with `api/assistants/threads` (found in `api/assistants/threads/...`). Feel free to start your own project and copy some of this logic in! The `Chat` component itself can be copied and used directly, provided you copy the styling from `app/components/chat.module.css` as well. + +### Pages + +- Basic Chat Example: [http://localhost:3000/examples/basic-chat](http://localhost:3000/examples/basic-chat) +- Function Calling Example: [http://localhost:3000/examples/function-calling](http://localhost:3000/examples/function-calling) +- File Search Example: [http://localhost:3000/examples/file-search](http://localhost:3000/examples/file-search) +- Full-featured Example: [http://localhost:3000/examples/all](http://localhost:3000/examples/all) + +### Main Components + +- `app/components/chat.tsx` - handles chat chat rendering, [streaming](https://platform.openai.com/docs/assistants/overview?context=with-streaming), and [function call](https://platform.openai.com/docs/assistants/tools/function-calling/quickstart?context=streaming&lang=node.js) forwarding +- `app/components/file-viewer.tsx` - handles uploading, fetching, and deleting files for [file search](https://platform.openai.com/docs/assistants/tools/file-search) + +### Endpoints + +- `api/assistants` - `POST`: create assistant (only used at startup) +- `api/assistants/threads` - `POST`: create new thread +- `api/assistants/threads/[threadId]/messages` - `POST`: send message to assistant +- `api/assistants/threads/[threadId]/actions` - `POST`: inform assistant of the result of a function it decided to call +- `api/assistants/files` - `GET`/`POST`/`DELETE`: fetch, upload, and delete assistant files for file search + +## Feedback + +Let us know if you have any thoughts, questions, or feedback in [this form](https://docs.google.com/forms/d/e/1FAIpQLSdquOq8U8cvqL4EVCXuJ3oPag2w7KySsC0PLxv6VAHon6smrw/viewform?usp=sf_link)! + diff --git a/app/api/assistants/files/route.tsx b/app/api/assistants/files/route.tsx new file mode 100644 index 0000000..03d0bdd --- /dev/null +++ b/app/api/assistants/files/route.tsx @@ -0,0 +1,79 @@ +import OpenAI from "openai"; +import { assistantId } from "../../../assistant-config"; + +const openai = new OpenAI(); + +// upload file to assistant's vector store +export async function POST(request) { + const formData = await request.formData(); // process file as FormData + const file = formData.get("file"); // retrieve the single file from FormData + const vectorStoreId = await getOrCreateVectorStore(); // get or create vector store + + // upload using the file stream + const openaiFile = await openai.files.create({ + file: file, + purpose: "assistants", + }); + + // add file to vector store + await openai.beta.vectorStores.files.create(vectorStoreId, { + file_id: openaiFile.id, + }); + return new Response(); +} + +// list files in assistant's vector store +export async function GET() { + const vectorStoreId = await getOrCreateVectorStore(); // get or create vector store + const fileList = await openai.beta.vectorStores.files.list(vectorStoreId); + + const filesArray = await Promise.all( + fileList.data.map(async (file) => { + const fileDetails = await openai.files.retrieve(file.id); + const vectorFileDetails = await openai.beta.vectorStores.files.retrieve( + vectorStoreId, + file.id + ); + return { + file_id: file.id, + filename: fileDetails.filename, + status: vectorFileDetails.status, + }; + }) + ); + return new Response(JSON.stringify(filesArray)); +} + +// delete file from assistant's vector store +export async function DELETE(request) { + const body = await request.json(); + const fileId = body.fileId; + + const vectorStoreId = await getOrCreateVectorStore(); // get or create vector store + await openai.beta.vectorStores.files.del(vectorStoreId, fileId); // delete file from vector store + + return new Response(); +} + +/* Helper functions */ + +const getOrCreateVectorStore = async () => { + const assistant = await openai.beta.assistants.retrieve(assistantId); + + // if the assistant already has a vector store, return it + if (assistant.tool_resources?.file_search?.vector_store_ids?.length > 0) { + return assistant.tool_resources.file_search.vector_store_ids[0]; + } + // otherwise, create a new vector store and attatch it to the assistant + const vectorStore = await openai.beta.vectorStores.create({ + name: "sample-assistant-vector-store", + }); + await openai.beta.assistants.update(assistantId, { + tool_resources: { + file_search: { + vector_store_ids: [vectorStore.id], + }, + }, + }); + return vectorStore.id; +}; diff --git a/app/api/assistants/route.ts b/app/api/assistants/route.ts new file mode 100644 index 0000000..6e9e8a5 --- /dev/null +++ b/app/api/assistants/route.ts @@ -0,0 +1,39 @@ +import OpenAI from "openai"; +const openai = new OpenAI(); + +export const runtime = "nodejs"; + +// Create a new assistant +export async function POST() { + const assistant = await openai.beta.assistants.create({ + instructions: "You are a helpful assistant.", + name: "Quickstart Assistant", + model: "gpt-4-turbo-preview", + tools: [ + { type: "code_interpreter" }, + { + type: "function", + function: { + name: "get_weather", + description: "Determine weather in my location", + parameters: { + type: "object", + properties: { + location: { + type: "string", + description: "The city and state e.g. San Francisco, CA", + }, + unit: { + type: "string", + enum: ["c", "f"], + }, + }, + required: ["location"], + }, + }, + }, + { type: "file_search" }, + ], + }); + return new Response(JSON.stringify({ assistantId: assistant.id })); +} diff --git a/app/api/assistants/threads/[threadId]/actions/route.ts b/app/api/assistants/threads/[threadId]/actions/route.ts new file mode 100644 index 0000000..740801c --- /dev/null +++ b/app/api/assistants/threads/[threadId]/actions/route.ts @@ -0,0 +1,21 @@ +import OpenAI from "openai"; +const openai = new OpenAI(); + +export const runtime = "nodejs"; + +// Send a new message to a thread +export async function POST(request, { params }) { + const body = await request.json(); + const toolCallOutputs = body.toolCallOutputs; + const runId = body.runId; + const threadId = params.threadId; + + const stream = openai.beta.threads.runs.submitToolOutputsStream( + threadId, + runId, + // { tool_outputs: [{ output: result, tool_call_id: toolCallId }] }, + { tool_outputs: toolCallOutputs } + ); + + return new Response(stream.toReadableStream()); +} diff --git a/app/api/assistants/threads/[threadId]/messages/route.ts b/app/api/assistants/threads/[threadId]/messages/route.ts new file mode 100644 index 0000000..977d0ed --- /dev/null +++ b/app/api/assistants/threads/[threadId]/messages/route.ts @@ -0,0 +1,23 @@ +import OpenAI from "openai"; +import { assistantId } from "../../../../../assistant-config"; +const openai = new OpenAI(); + +export const runtime = "nodejs"; + +// Send a new message to a thread +export async function POST(request, { params }) { + const body = await request.json(); + const content = body.content; + const threadId = params.threadId; + + await openai.beta.threads.messages.create(threadId, { + role: "user", + content: content, + }); + + const stream = openai.beta.threads.runs.createAndStream(threadId, { + assistant_id: assistantId, + }); + + return new Response(stream.toReadableStream()); +} diff --git a/app/api/assistants/threads/route.ts b/app/api/assistants/threads/route.ts new file mode 100644 index 0000000..125b32e --- /dev/null +++ b/app/api/assistants/threads/route.ts @@ -0,0 +1,10 @@ +import OpenAI from "openai"; +const openai = new OpenAI(); + +export const runtime = "nodejs"; + +// Create a new thread +export async function POST() { + const thread = await openai.beta.threads.create(); + return new Response(JSON.stringify({ threadId: thread.id })); +} diff --git a/app/assistant-config.ts b/app/assistant-config.ts new file mode 100644 index 0000000..e7f6633 --- /dev/null +++ b/app/assistant-config.ts @@ -0,0 +1 @@ +export const assistantId = ""; // set your assistant ID here diff --git a/app/components/chat.module.css b/app/components/chat.module.css new file mode 100644 index 0000000..87055f6 --- /dev/null +++ b/app/components/chat.module.css @@ -0,0 +1,89 @@ +.chatContainer { + display: flex; + flex-direction: column-reverse; + height: 100%; + width: 100%; +} + +.inputForm { + display: flex; + width: 100%; + padding: 10px; + padding-bottom: 40px; + order: 1; +} + +.input { + flex-grow: 1; + padding: 16px 24px; + margin-right: 10px; + border-radius: 60px; + border: 2px solid transparent; + font-size: 1em; + background-color: #efefef; +} + +.input:focus { + outline: none !important; + border-color: #000; + background-color: white; +} + +.button { + padding: 8px 24px; + background-color: #000; + color: white; + border: none; + font-size: 1em; + border-radius: 60px; /* Removed duplicate border-radius property */ +} + +.button:disabled { + background-color: lightgrey; +} + +.messages { + flex-grow: 1; + overflow-y: auto; + padding: 10px; + display: flex; + flex-direction: column; + order: 2; + white-space: pre-wrap; +} + +.userMessage, +.assistantMessage, +.codeMessage { + margin: 8px 0; + padding: 8px 16px; + align-self: flex-start; + border-radius: 15px; + max-width: 80%; +} + +.userMessage { + align-self: flex-end; + color: #fff; + background-color: #000; +} + +.assistantMessage { + background-color: #efefef; +} + +.codeMessage { + padding: 10px 16px; + background-color: #e9e9e9; + font-family: monospace; + counter-reset: line; +} + +.codeMessage > div { + margin-top: 4px; +} + +.codeMessage span { + color: #b8b8b8; + margin-right: 8px; +} diff --git a/app/components/chat.tsx b/app/components/chat.tsx new file mode 100644 index 0000000..4287177 --- /dev/null +++ b/app/components/chat.tsx @@ -0,0 +1,250 @@ +"use client"; + +import React, { useState, useEffect, useRef } from "react"; +import styles from "./chat.module.css"; +import { AssistantStream } from "openai/lib/AssistantStream"; +import Markdown from "react-markdown"; +// @ts-expect-error - no types for this yet +import { AssistantStreamEvent } from "openai/resources/beta/assistants/assistants"; +import { RequiredActionFunctionToolCall } from "openai/resources/beta/threads/runs/runs"; + +type MessageProps = { + role: "user" | "assistant" | "code"; + text: string; +}; + +const UserMessage = ({ text }: { text: string }) => { + return
{text}
; +}; + +const AssistantMessage = ({ text }: { text: string }) => { + return ( +
+ {text} +
+ ); +}; + +const CodeMessage = ({ text }: { text: string }) => { + return ( +
+ {text.split("\n").map((line, index) => ( +
+ {`${index + 1}. `} + {line} +
+ ))} +
+ ); +}; + +const Message = ({ role, text }: MessageProps) => { + switch (role) { + case "user": + return ; + case "assistant": + return ; + case "code": + return ; + default: + return null; + } +}; + +type ChatProps = { + functionCallHandler?: ( + toolCall: RequiredActionFunctionToolCall + ) => Promise; +}; + +const Chat = ({ + functionCallHandler = () => Promise.resolve(""), // default to return empty string +}: ChatProps) => { + const [userInput, setUserInput] = useState(""); + const [messages, setMessages] = useState([]); + const [inputDisabled, setInputDisabled] = useState(false); + const [threadId, setThreadId] = useState(""); + + // automitcally scroll to bottom of chat + const messagesEndRef = useRef(null); + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); + }; + useEffect(() => { + scrollToBottom(); + }, [messages]); + + // create a new threadID when chat component created + useEffect(() => { + const createThread = async () => { + const res = await fetch(`/api/assistants/threads`, { + method: "POST", + }); + const data = await res.json(); + setThreadId(data.threadId); + }; + createThread(); + }, []); + + const sendMessage = async (text) => { + const response = await fetch( + `/api/assistants/threads/${threadId}/messages`, + { + method: "POST", + body: JSON.stringify({ + content: text, + }), + } + ); + const stream = AssistantStream.fromReadableStream(response.body); + handleReadableStream(stream); + }; + + const submitActionResult = async (runId, toolCallOutputs) => { + const response = await fetch( + `/api/assistants/threads/${threadId}/actions`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + runId: runId, + toolCallOutputs: toolCallOutputs, + }), + } + ); + const stream = AssistantStream.fromReadableStream(response.body); + handleReadableStream(stream); + }; + + const handleSubmit = (e) => { + e.preventDefault(); + if (!userInput.trim()) return; + sendMessage(userInput); + setMessages((prevMessages) => [ + ...prevMessages, + { role: "user", text: userInput }, + ]); + setUserInput(""); + setInputDisabled(true); + scrollToBottom(); + }; + + /* Stream Event Handlers */ + + // textCreated - create new assistant message + const handleTextCreated = () => { + appendMessage("assistant", ""); + }; + + // textDelta - append text to last assistant message + const handleTextDelta = (delta) => { + appendToLastMessage(delta.value); + }; + + // toolCallCreated - log new tool call + const toolCallCreated = (toolCall) => { + if (toolCall.type != "code_interpreter") return; + appendMessage("code", ""); + }; + + // toolCallDelta - log delta and snapshot for the tool call + const toolCallDelta = (delta, snapshot) => { + if (delta.type != "code_interpreter") return; + if (!delta.code_interpreter.input) return; + appendToLastMessage(delta.code_interpreter.input); + }; + + // handleRequiresAction - handle function call + const handleRequiresAction = async ( + event: AssistantStreamEvent.ThreadRunRequiresAction + ) => { + const runId = event.data.id; + const toolCalls = event.data.required_action.submit_tool_outputs.tool_calls; + // loop over tool calls and call function handler + const toolCallOutputs = await Promise.all( + toolCalls.map(async (toolCall) => { + const result = await functionCallHandler(toolCall); + return { output: result, tool_call_id: toolCall.id }; + }) + ); + setInputDisabled(true); + submitActionResult(runId, toolCallOutputs); + }; + + // handleRunCompleted - re-enable the input form + const handleRunCompleted = () => { + setInputDisabled(false); + }; + + const handleReadableStream = (stream: AssistantStream) => { + // messages + stream.on("textCreated", handleTextCreated); + stream.on("textDelta", handleTextDelta); + + // code interpreter + stream.on("toolCallCreated", toolCallCreated); + stream.on("toolCallDelta", toolCallDelta); + + // events without helpers yet (e.g. requires_action and run.done) + stream.on("event", (event) => { + if (event.event === "thread.run.requires_action") + handleRequiresAction(event); + if (event.event === "thread.run.completed") handleRunCompleted(); + }); + }; + + /* + ======================= + === Utility Helpers === + ======================= + */ + + const appendToLastMessage = (text) => { + setMessages((prevMessages) => { + const lastMessage = prevMessages[prevMessages.length - 1]; + const updatedLastMessage = { + ...lastMessage, + text: lastMessage.text + text, + }; + return [...prevMessages.slice(0, -1), updatedLastMessage]; + }); + }; + + const appendMessage = (role, text) => { + setMessages((prevMessages) => [...prevMessages, { role, text }]); + }; + + return ( +
+
+ {messages.map((msg, index) => ( + + ))} +
+
+
+ setUserInput(e.target.value)} + placeholder="Enter your question" + /> + +
+
+ ); +}; + +export default Chat; diff --git a/app/components/file-viewer.module.css b/app/components/file-viewer.module.css new file mode 100644 index 0000000..1d2d766 --- /dev/null +++ b/app/components/file-viewer.module.css @@ -0,0 +1,78 @@ +.fileViewer { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + padding: 20px; + background-color: #efefef; + overflow: hidden; + border-radius: 16px; +} + +.filesList { + overflow-y: auto; + padding: 10px; + display: flex; + flex-direction: column; + gap: 12px; + align-items: center; + width: 100%; +} + +.grow { + flex-grow: 1; +} + +.fileEntry { + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid #ececf1; + gap: 16px; + width: 100%; +} + +.fileName { + flex-grow: 1; +} +.fileStatus { + font-size: 0.8em; + color: #666; +} + +.fileDeleteIcon { + cursor: pointer; +} + +.fileUploadContainer { + padding: 10px; + display: flex; + justify-content: center; +} + +.fileUploadBtn { + background-color: #000; + color: white; + padding: 8px 24px; + border-radius: 32px; + text-align: center; + display: inline-block; + cursor: pointer; +} + +.fileUploadInput { + display: none; +} + +.title { + font-size: 1.2em; + font-weight: 600; +} + +.fileName { + width: 100%; + display: flex; + flex-direction: column; +} diff --git a/app/components/file-viewer.tsx b/app/components/file-viewer.tsx new file mode 100644 index 0000000..b91db89 --- /dev/null +++ b/app/components/file-viewer.tsx @@ -0,0 +1,97 @@ +import React, { useState, useEffect } from "react"; +import styles from "./file-viewer.module.css"; + +const TrashIcon = () => ( + + + +); + +const FileViewer = () => { + const [files, setFiles] = useState([]); + + useEffect(() => { + const interval = setInterval(() => { + fetchFiles(); + }, 1000); + + return () => clearInterval(interval); + }, []); + + const fetchFiles = async () => { + const resp = await fetch("/api/assistants/files", { + method: "GET", + }); + const data = await resp.json(); + setFiles(data); + }; + + const handleFileDelete = async (fileId) => { + await fetch("/api/assistants/files", { + method: "DELETE", + body: JSON.stringify({ fileId }), + }); + }; + + const handleFileUpload = async (event) => { + const data = new FormData(); + if (event.target.files.length < 0) return; + data.append("file", event.target.files[0]); + await fetch("/api/assistants/files", { + method: "POST", + body: data, + }); + }; + + return ( +
+
+ {files.length === 0 ? ( +
Attach files to test file search
+ ) : ( + files.map((file) => ( +
+
+ {file.filename} + {file.status} +
+ handleFileDelete(file.file_id)}> + + +
+ )) + )} +
+
+ + +
+
+ ); +}; + +export default FileViewer; diff --git a/app/components/warnings.module.css b/app/components/warnings.module.css new file mode 100644 index 0000000..cab074a --- /dev/null +++ b/app/components/warnings.module.css @@ -0,0 +1,57 @@ +.container { + padding: 20px; + /* background-color: #d95c5c; */ + /* outline: 8px solid #4caf50; */ + background-color: #fff; + width: 100vw; + height: 100vh; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; + border-radius: 12px; + color: #000; +} + +.empty, +.assistantId { + background-color: #ffffff; + padding: 10px; + margin-bottom: 10px; + width: 80%; + border: 1px solid #ccc; +} + +.button { + padding: 8px 24px; + background-color: #000; + color: white; + border: none; + font-size: 1em; + border-radius: 60px; + cursor: pointer; +} +.container h1 { + font-size: 1.5em; + font-weight: 600; +} +.result { + border-radius: 8px; + padding: 0 8px; + padding: 8px 24px; + background-color: #000; + color: white; + font-size: 1em; + border-radius: 60px; +} + +.message { + margin: 20px 0; + font-size: 1em; +} +.message span { + background-color: #efefef; + border-radius: 8px; + padding: 0 8px; +} diff --git a/app/components/warnings.tsx b/app/components/warnings.tsx new file mode 100644 index 0000000..2d82363 --- /dev/null +++ b/app/components/warnings.tsx @@ -0,0 +1,47 @@ +"use client"; + +import React, { useState } from "react"; +import styles from "./warnings.module.css"; +import { assistantId } from "../assistant-config"; + +const Warnings = () => { + const [loading, setLoading] = useState(false); + const [newAssistantId, setNewAssistantId] = useState(""); + + const fetchAssistantId = async () => { + setLoading(true); + + const response = await fetch("/api/assistants", { method: "POST" }); + const data = await response.json(); + setNewAssistantId(data.assistantId); + + setLoading(false); + }; + + return ( + <> + {!assistantId && ( +
+

Start by creating your assistant

+
+ Create an assistant and set its ID in{" "} + app/assistant-config.ts +
+ {!newAssistantId ? ( + + ) : ( +
{newAssistantId}
+ )} +
+ )} + + ); +}; + +export default Warnings; diff --git a/app/components/weather-widget.module.css b/app/components/weather-widget.module.css new file mode 100644 index 0000000..1b1a621 --- /dev/null +++ b/app/components/weather-widget.module.css @@ -0,0 +1,59 @@ +.weatherBGCloudy { + background: linear-gradient(to top right, #b6c6c9, #8fa3ad); +} + +.weatherBGSunny { + background: linear-gradient(to bottom left, #ffffd0, #007cf0); +} + +.weatherBGRainy { + background: linear-gradient(to top, #647d8e, #a8c0c0); +} + +.weatherBGSnowy { + background: linear-gradient(to bottom, #ffffff, #acc2d9); +} + +.weatherBGWindy { + background: linear-gradient(to right, #c4e0e5, #4ca1af); +} + +.weatherWidget { + width: 100%; + height: 100%; + padding: 4px; + padding: 20px; + color: white; + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); + align-items: center; + justify-content: center; + display: flex; +} + +.weatherWidgetData { + display: flex; + gap: 4px; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.weatherEmptyState { + width: 100%; + height: 100%; + padding: 20px; + color: white; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background: var( + --emptyStateBackground, + linear-gradient(to top right, #b6c6c9, #8fa3ad) + ); +} + +.weatherWidgetData h2 { + font-size: 8em; + font-weight: 500; +} diff --git a/app/components/weather-widget.tsx b/app/components/weather-widget.tsx new file mode 100644 index 0000000..049091f --- /dev/null +++ b/app/components/weather-widget.tsx @@ -0,0 +1,44 @@ +import React from "react"; +import styles from "./weather-widget.module.css"; + +const WeatherWidget = ({ + location = "---", + temperature = "---", + conditions = "Sunny", + isEmpty = false, +}) => { + const conditionClassMap = { + Cloudy: styles.weatherBGCloudy, + Sunny: styles.weatherBGSunny, + Rainy: styles.weatherBGRainy, + Snowy: styles.weatherBGSnowy, + Windy: styles.weatherBGWindy, + }; + + if (isEmpty) { + return ( +
+
+

Enter a city to see local weather

+

try: what's the weather like in Berkeley?

+
+
+ ); + } + + const weatherClass = `${styles.weatherWidget} ${ + conditionClassMap[conditions] || styles.weatherBGSunny + }`; + + return ( +
+
+

{location}

+

{temperature !== "---" ? `${temperature}°F` : temperature}

+

{conditions}

+
+
+ ); +}; + +export default WeatherWidget; diff --git a/app/examples/all/page.module.css b/app/examples/all/page.module.css new file mode 100644 index 0000000..b3c260e --- /dev/null +++ b/app/examples/all/page.module.css @@ -0,0 +1,44 @@ +.main { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; +} + +.container { + display: flex; + width: 100%; + height: 100vh; +} + +.column { + display: flex; + flex-direction: column; + width: 50%; + height: calc(100% - 40px); + gap: 20px; + margin: 20px; + justify-content: space-between; +} + +.column > * { + border-radius: 16px; + overflow: hidden; + width: 100%; + height: 50%; + border-radius: 16px; +} +.chatContainer { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + background-color: white; +} + +.chat { + max-width: 600px; + width: 100%; + height: 100%; +} diff --git a/app/examples/all/page.tsx b/app/examples/all/page.tsx new file mode 100644 index 0000000..776f68b --- /dev/null +++ b/app/examples/all/page.tsx @@ -0,0 +1,58 @@ +"use client"; + +import React, { useState } from "react"; +import styles from "./page.module.css"; +import Chat from "../../components/chat"; +import WeatherWidget from "../../components/weather-widget"; +import { getWeather } from "../../utils/weather"; +import FileViewer from "../../components/file-viewer"; + +const FunctionCalling = () => { + const [weatherData, setWeatherData] = useState({}); + + const functionCallHandler = async (call) => { + if (call?.function?.name !== "get_weather") return; + const args = JSON.parse(call.function.arguments); + const data = getWeather(args.location); + setWeatherData(data); + return JSON.stringify(data); + }; + + // return ( + //
+ //
+ //
+ // + //
+ //
+ //
+ //
+ // + //
+ //
+ //
+ // + //
+ //
+ //
+ //
+ // ); + + return ( +
+
+
+ + +
+
+
+ +
+
+
+
+ ); +}; + +export default FunctionCalling; diff --git a/app/examples/basic-chat/page.module.css b/app/examples/basic-chat/page.module.css new file mode 100644 index 0000000..bd115ec --- /dev/null +++ b/app/examples/basic-chat/page.module.css @@ -0,0 +1,13 @@ +.main { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + background-color: white; +} + +.container { + max-width: 700px; + width: 100%; + height: 100%; +} diff --git a/app/examples/basic-chat/page.tsx b/app/examples/basic-chat/page.tsx new file mode 100644 index 0000000..25ef95a --- /dev/null +++ b/app/examples/basic-chat/page.tsx @@ -0,0 +1,17 @@ +"use client"; + +import React from "react"; +import styles from "./page.module.css"; // use simple styles for demonstration purposes +import Chat from "../../components/chat"; + +const Home = () => { + return ( +
+
+ +
+
+ ); +}; + +export default Home; diff --git a/app/examples/file-search/page.tsx b/app/examples/file-search/page.tsx new file mode 100644 index 0000000..4587081 --- /dev/null +++ b/app/examples/file-search/page.tsx @@ -0,0 +1,25 @@ +"use client"; +import React from "react"; +import styles from "../shared/page.module.css"; + +import Chat from "../../components/chat"; +import FileViewer from "../../components/file-viewer"; + +const FileSearchPage = () => { + return ( +
+
+
+ +
+
+
+ +
+
+
+
+ ); +}; + +export default FileSearchPage; diff --git a/app/examples/function-calling/page.tsx b/app/examples/function-calling/page.tsx new file mode 100644 index 0000000..0e66d6c --- /dev/null +++ b/app/examples/function-calling/page.tsx @@ -0,0 +1,49 @@ +"use client"; + +import React, { useState } from "react"; +import styles from "../shared/page.module.css"; +import Chat from "../../components/chat"; +import WeatherWidget from "../../components/weather-widget"; +import { getWeather } from "../../utils/weather"; +import { RequiredActionFunctionToolCall } from "openai/resources/beta/threads/runs/runs"; + +interface WeatherData { + location?: string; + temperature?: number; + conditions?: string; +} + +const FunctionCalling = () => { + const [weatherData, setWeatherData] = useState({}); + const isEmpty = Object.keys(weatherData).length === 0; + + const functionCallHandler = async (call: RequiredActionFunctionToolCall) => { + if (call?.function?.name !== "get_weather") return; + const args = JSON.parse(call.function.arguments); + const data = getWeather(args.location); + setWeatherData(data); + return JSON.stringify(data); + }; + + return ( +
+
+
+ +
+
+
+ +
+
+
+
+ ); +}; + +export default FunctionCalling; diff --git a/app/examples/shared/page.module.css b/app/examples/shared/page.module.css new file mode 100644 index 0000000..d0543c4 --- /dev/null +++ b/app/examples/shared/page.module.css @@ -0,0 +1,43 @@ +.main { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; +} + +.container { + display: flex; + width: 100%; + height: 100vh; +} + +.column { + display: flex; + flex-direction: column; + width: 50%; + height: calc(100% - 40px); + gap: 20px; + margin: 20px; +} + +.column > * { + border-radius: 16px; + overflow: hidden; + width: 100%; + flex: 1; +} + +.chatContainer { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + background-color: white; +} + +.chat { + max-width: 600px; + width: 100%; + height: 100%; +} diff --git a/app/favicon.png b/app/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..35d2833a24b9c2f0c2f97f48538a637c61ab5aa1 GIT binary patch literal 7038 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 Q8ZeiIsf|gw5i#a}0F#NK0RR91 literal 0 HcmV?d00001 diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..ac875f4 --- /dev/null +++ b/app/globals.css @@ -0,0 +1,73 @@ +:root { + --max-width: 1100px; + --border-radius: 12px; + --font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", + "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", + "Fira Mono", "Droid Sans Mono", "Courier New", monospace; +} + +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +html, +body { + max-width: 100vw; + overflow-x: hidden; +} + +body { + color: rgb(var(--foreground-rgb)); +} + +a { + color: inherit; + text-decoration: none; +} + +.warnings { + position: absolute; + top: 21%; + left: 50%; + transform: translate(-50%, -50%); + width: 700px; + height: 300px; + border-radius: 12px; + display: flex; + justify-content: center; + align-items: center; +} + +.logo { + width: 32px; + height: 32px; + position: absolute; + margin: 16px; + top: 0; + right: 0; +} + +@media (max-width: 1100px) { + .logo { + display: none; + } +} + +ul, +ol { + padding-left: 20px; +} + +a { + color: blue; +} + +pre { + margin: -4px -16px; + padding: 20px; + white-space: pre-wrap; + background-color: #e4e4e4; + color: black; +} diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..c60736e --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,24 @@ +import { Inter } from "next/font/google"; +import "./globals.css"; +import Warnings from "./components/warnings"; +import { assistantId } from "./assistant-config"; +const inter = Inter({ subsets: ["latin"] }); + +export const metadata = { + title: "Assistants API Quickstart", + description: "A quickstart template using the Assistants API with OpenAI", + icons: { + icon: "/openai.svg", + }, +}; + +export default function RootLayout({ children }) { + return ( + + + {assistantId ? children : } + OpenAI Logo + + + ); +} diff --git a/app/page.module.css b/app/page.module.css new file mode 100644 index 0000000..17fdd3f --- /dev/null +++ b/app/page.module.css @@ -0,0 +1,47 @@ +.main { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100vh; + background-color: white; +} +.title { + font-size: 1.5em; + margin-bottom: 20px; + font-weight: 600; +} + +.container { + display: flex; + flex-direction: row; + gap: 20px; + max-width: 1200px; + width: 100%; + padding: 20px; + box-sizing: border-box; + align-items: center; + justify-content: center; +} + +.category { + color: black; + display: flex; + font-size: 1em; + border-radius: 32px; + justify-content: center; + align-items: center; + text-align: center; + background-color: #efefef; + cursor: pointer; + max-width: 600px; + width: 120px; + height: 120px; + padding: 20px; + transition: background-color 0.3s ease; + font-weight: 500; +} + +.category:hover { + background-color: #e3e3eb; +} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..60c34a3 --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,30 @@ +"use client"; + +import React from "react"; +import styles from "./page.module.css"; + +const Home = () => { + const categories = { + "Basic chat": "basic-chat", + "Function calling": "function-calling", + "File search": "file-search", + All: "all", + }; + + return ( +
+
+ Explore sample apps built with Assistants API +
+
+ {Object.entries(categories).map(([name, url]) => ( + + {name} + + ))} +
+
+ ); +}; + +export default Home; diff --git a/app/utils/weather.ts b/app/utils/weather.ts new file mode 100644 index 0000000..26926d7 --- /dev/null +++ b/app/utils/weather.ts @@ -0,0 +1,15 @@ +const getWeather = (location) => { + // chose a random temperature and condition + const randomTemperature = Math.floor(Math.random() * (80 - 50 + 1)) + 50; + const randomConditionIndex = Math.floor(Math.random() * 5); + const conditions = ["Cloudy", "Sunny", "Rainy", "Snowy", "Windy"]; + + return { + location: location, + temperature: randomTemperature, + unit: "F", + conditions: conditions[randomConditionIndex], + }; +}; + +export { getWeather }; diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..2a2e4b3 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./*"] + } + } +} diff --git a/next.config.mjs b/next.config.mjs new file mode 100644 index 0000000..4678774 --- /dev/null +++ b/next.config.mjs @@ -0,0 +1,4 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +export default nextConfig; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7f8138e --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1791 @@ +{ + "name": "assistants-nextjs", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "assistants-nextjs", + "version": "0.1.0", + "dependencies": { + "next": "14.1.4", + "openai": "^4.38.1", + "react": "^18", + "react-dom": "^18", + "react-markdown": "^9.0.1" + }, + "devDependencies": { + "@types/node": "20.12.7", + "@types/react": "18.2.79", + "typescript": "5.4.5" + } + }, + "node_modules/@next/env": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.4.tgz", + "integrity": "sha512-e7X7bbn3Z6DWnDi75UWn+REgAbLEqxI8Tq2pkFOFAMpWAWApz/YCUhtWMWn410h8Q2fYiYL7Yg5OlxMOCfFjJQ==" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.4.tgz", + "integrity": "sha512-ubmUkbmW65nIAOmoxT1IROZdmmJMmdYvXIe8211send9ZYJu+SqxSnJM4TrPj9wmL6g9Atvj0S/2cFmMSS99jg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.4.tgz", + "integrity": "sha512-b0Xo1ELj3u7IkZWAKcJPJEhBop117U78l70nfoQGo4xUSvv0PJSTaV4U9xQBLvZlnjsYkc8RwQN1HoH/oQmLlQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.4.tgz", + "integrity": "sha512-457G0hcLrdYA/u1O2XkRMsDKId5VKe3uKPvrKVOyuARa6nXrdhJOOYU9hkKKyQTMru1B8qEP78IAhf/1XnVqKA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.4.tgz", + "integrity": "sha512-l/kMG+z6MB+fKA9KdtyprkTQ1ihlJcBh66cf0HvqGP+rXBbOXX0dpJatjZbHeunvEHoBBS69GYQG5ry78JMy3g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.4.tgz", + "integrity": "sha512-BapIFZ3ZRnvQ1uWbmqEGJuPT9cgLwvKtxhK/L2t4QYO7l+/DxXuIGjvp1x8rvfa/x1FFSsipERZK70pewbtJtw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.4.tgz", + "integrity": "sha512-mqVxTwk4XuBl49qn2A5UmzFImoL1iLm0KQQwtdRJRKl21ylQwwGCxJtIYo2rbfkZHoSKlh/YgztY0qH3wG1xIg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.4.tgz", + "integrity": "sha512-xzxF4ErcumXjO2Pvg/wVGrtr9QQJLk3IyQX1ddAC/fi6/5jZCZ9xpuL9Tzc4KPWMFq8GGWFVDMshZOdHGdkvag==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.4.tgz", + "integrity": "sha512-WZiz8OdbkpRw6/IU/lredZWKKZopUMhcI2F+XiMAcPja0uZYdMTZQRoQ0WZcvinn9xZAidimE7tN9W5v9Yyfyw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.4.tgz", + "integrity": "sha512-4Rto21sPfw555sZ/XNLqfxDUNeLhNYGO2dlPqsnuCg8N8a2a9u1ltqBOPQ4vj1Gf7eJC0W2hHG2eYUHuiXgY2w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", + "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.3.tgz", + "integrity": "sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, + "node_modules/@types/node": { + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" + }, + "node_modules/@types/react": { + "version": "18.2.79", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.79.tgz", + "integrity": "sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001599", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz", + "integrity": "sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==" + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, + "node_modules/formdata-node/node_modules/web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", + "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-url-attributes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.0.tgz", + "integrity": "sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/inline-style-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", + "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==" + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", + "integrity": "sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", + "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz", + "integrity": "sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-remove-position": "^5.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.1.0.tgz", + "integrity": "sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", + "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", + "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/next/-/next-14.1.4.tgz", + "integrity": "sha512-1WTaXeSrUwlz/XcnhGTY7+8eiaFvdet5z9u3V2jb+Ek1vFo0VhHKSAIJvDWfQpttWjnyw14kBeq28TPq7bTeEQ==", + "dependencies": { + "@next/env": "14.1.4", + "@swc/helpers": "0.5.2", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.1.4", + "@next/swc-darwin-x64": "14.1.4", + "@next/swc-linux-arm64-gnu": "14.1.4", + "@next/swc-linux-arm64-musl": "14.1.4", + "@next/swc-linux-x64-gnu": "14.1.4", + "@next/swc-linux-x64-musl": "14.1.4", + "@next/swc-win32-arm64-msvc": "14.1.4", + "@next/swc-win32-ia32-msvc": "14.1.4", + "@next/swc-win32-x64-msvc": "14.1.4" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/openai": { + "version": "4.38.1", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.38.1.tgz", + "integrity": "sha512-nmSKE9O2piuoh9+AgDqwGHojIFSxToQ2jJqwaxjbzz2ebdD5LYY9s+bMe25b18t4QEgvtgW70JfK8BU3xf5dRw==", + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7", + "web-streams-polyfill": "^3.2.1" + }, + "bin": { + "openai": "bin/cli" + } + }, + "node_modules/openai/node_modules/@types/node": { + "version": "18.19.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.31.tgz", + "integrity": "sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-markdown": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.1.tgz", + "integrity": "sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz", + "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/style-to-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", + "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", + "dependencies": { + "inline-style-parser": "0.2.3" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..e2cc563 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "assistants-nextjs", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "next": "14.1.4", + "openai": "^4.38.1", + "react": "^18", + "react-dom": "^18", + "react-markdown": "^9.0.1" + }, + "devDependencies": { + "@types/node": "20.12.7", + "@types/react": "18.2.79", + "typescript": "5.4.5" + } +} diff --git a/public/openai.svg b/public/openai.svg new file mode 100644 index 0000000..98d4edd --- /dev/null +++ b/public/openai.svg @@ -0,0 +1 @@ + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..14bd9ea --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "noEmit": true, + "incremental": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "plugins": [ + { + "name": "next" + } + ] + }, + "include": [ + "next-env.d.ts", + ".next/types/**/*.ts", + "**/*.ts", + "**/*.tsx" + ], + "exclude": [ + "node_modules" + ] +}