├── .env.example ├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── bun.lockb ├── components.json ├── examples └── nextjs │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── app │ ├── components │ │ ├── chat.tsx │ │ ├── features.tsx │ │ ├── footer.tsx │ │ └── header.tsx │ ├── favicon.ico │ ├── globals.css │ ├── layout.tsx │ └── page.tsx │ ├── next.config.ts │ ├── package-lock.json │ ├── package.json │ ├── pnpm-lock.yaml │ ├── postcss.config.mjs │ ├── prettier.config.js │ ├── tailwind.config.ts │ ├── tsconfig.json │ └── vercel.json ├── index.ts ├── package.json ├── playground ├── .gitignore ├── README.md ├── eslint.config.mjs ├── next.config.ts ├── package-lock.json ├── package.json ├── postcss.config.mjs ├── public │ ├── file.svg │ ├── globe.svg │ ├── next.svg │ ├── vercel.svg │ └── window.svg ├── src │ └── app │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── layout.tsx │ │ └── page.tsx ├── tailwind.config.ts └── tsconfig.json ├── postcss.config.mjs ├── public └── images │ ├── vector-databrowser.png │ ├── widget-closed.png │ └── widget-open.png ├── src ├── client │ ├── components │ │ ├── chat-component.tsx │ │ ├── lib │ │ │ └── utils.ts │ │ ├── styles.css │ │ └── ui │ │ │ ├── button.tsx │ │ │ └── scroll-area.tsx │ └── index.ts └── server │ ├── actions │ ├── chat.ts │ └── history.ts │ ├── constants.ts │ ├── index.ts │ └── lib │ ├── history │ ├── get-client.ts │ ├── in-memory.ts │ └── redis.ts │ └── types.ts ├── tailwind.config.ts ├── tsconfig.json └── tsup.config.ts /.env.example: -------------------------------------------------------------------------------- 1 | UPSTASH_VECTOR_REST_URL= 2 | UPSTASH_VECTOR_REST_TOKEN= 3 | 4 | # Optional for persistent chat history 5 | UPSTASH_REDIS_REST_URL= 6 | UPSTASH_REDIS_REST_TOKEN= 7 | 8 | TOGETHER_API_KEY= 9 | # (Optional) Default = meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo 10 | TOGETHER_MODEL= 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore 2 | 3 | # Logs 4 | 5 | logs 6 | _.log 7 | npm-debug.log_ 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Caches 14 | 15 | .cache 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | 19 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 20 | 21 | # Runtime data 22 | 23 | pids 24 | _.pid 25 | _.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | 30 | lib-cov 31 | 32 | # Coverage directory used by tools like istanbul 33 | 34 | coverage 35 | *.lcov 36 | 37 | # nyc test coverage 38 | 39 | .nyc_output 40 | 41 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 42 | 43 | .grunt 44 | 45 | # Bower dependency directory (https://bower.io/) 46 | 47 | bower_components 48 | 49 | # node-waf configuration 50 | 51 | .lock-wscript 52 | 53 | # Compiled binary addons (https://nodejs.org/api/addons.html) 54 | 55 | build/Release 56 | 57 | # Dependency directories 58 | 59 | node_modules/ 60 | jspm_packages/ 61 | 62 | # Snowpack dependency directory (https://snowpack.dev/) 63 | 64 | web_modules/ 65 | 66 | # TypeScript cache 67 | 68 | *.tsbuildinfo 69 | 70 | # Optional npm cache directory 71 | 72 | .npm 73 | 74 | # Optional eslint cache 75 | 76 | .eslintcache 77 | 78 | # Optional stylelint cache 79 | 80 | .stylelintcache 81 | 82 | # Microbundle cache 83 | 84 | .rpt2_cache/ 85 | .rts2_cache_cjs/ 86 | .rts2_cache_es/ 87 | .rts2_cache_umd/ 88 | 89 | # Optional REPL history 90 | 91 | .node_repl_history 92 | 93 | # Output of 'npm pack' 94 | 95 | *.tgz 96 | 97 | # Yarn Integrity file 98 | 99 | .yarn-integrity 100 | 101 | # dotenv environment variable files 102 | 103 | .env 104 | .env.development.local 105 | .env.test.local 106 | .env.production.local 107 | .env.local 108 | 109 | # parcel-bundler cache (https://parceljs.org/) 110 | 111 | .parcel-cache 112 | 113 | # Next.js build output 114 | 115 | .next 116 | out 117 | 118 | # Nuxt.js build / generate output 119 | 120 | .nuxt 121 | dist 122 | 123 | # Gatsby files 124 | 125 | # Comment in the public line in if your project uses Gatsby and not Next.js 126 | 127 | # https://nextjs.org/blog/next-9-1#public-directory-support 128 | 129 | # public 130 | 131 | # vuepress build output 132 | 133 | .vuepress/dist 134 | 135 | # vuepress v2.x temp and cache directory 136 | 137 | .temp 138 | 139 | # Docusaurus cache and generated files 140 | 141 | .docusaurus 142 | 143 | # Serverless directories 144 | 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | 149 | .fusebox/ 150 | 151 | # DynamoDB Local files 152 | 153 | .dynamodb/ 154 | 155 | # TernJS port file 156 | 157 | .tern-port 158 | 159 | # Stores VSCode versions used for testing VSCode extensions 160 | 161 | .vscode-test 162 | 163 | # yarn v2 164 | 165 | .yarn/cache 166 | .yarn/unplugged 167 | .yarn/build-state.yml 168 | .yarn/install-state.gz 169 | .pnp.* 170 | 171 | # IntelliJ based IDEs 172 | .idea 173 | 174 | # Finder (MacOS) folder config 175 | .DS_Store 176 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSameLine": false, 4 | "bracketSpacing": true, 5 | "semi": true, 6 | "singleQuote": false, 7 | "jsxSingleQuote": false, 8 | "trailingComma": "all", 9 | "singleAttributePerLine": false, 10 | "importOrderSeparation": true, 11 | "importOrderSortSpecifiers": true, 12 | "importOrderBuiltinModulesToTop": true, 13 | "tailwindFunctions": ["clsx"], 14 | "plugins": ["prettier-plugin-tailwindcss"] 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Upstash 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RAG Chat Component 2 | 3 | A customizable Reach chat component that combines Upstash Vector for similarity search, Together AI for LLM, and Vercel AI SDK for streaming responses. This ready-to-use component provides an out of the box solution for adding RAG-Powered chat interfaces to your Next.js application. 4 | 5 | 6 | 7 | 11 | 15 | 16 |
8 | RAG Chat Component - Closed State
9 | Closed State 10 |
12 | RAG Chat Component - Open State
13 | Open State 14 |
17 | 18 | ## Features 19 | 20 | ⚡ Streaming responses support 21 | 22 | 💻 Server actions 23 | 24 | 📱 Responsive design 25 | 26 | 🔍 Real-time context retrieval 27 | 28 | 💾 Persistent chat history 29 | 30 | 🎨 Fully customizable UI components 31 | 32 | 🎨 Dark/light mode support 33 | 34 | ## Installation 35 | 36 | ```bash 37 | # Using npm 38 | npm install @upstash/rag-chat-component 39 | 40 | # Using pnpm 41 | pnpm add @upstash/rag-chat-component 42 | 43 | # Using yarn 44 | yarn add @upstash/rag-chat-component 45 | ``` 46 | 47 | ## Quick Start 48 | 49 | ### 1. Environment Variables 50 | 51 | Create an Upstash Vector database and set up the environment variables as below. If you don't have an account, you can start by going to [Upstash Console](https://console.upstash.com). 52 | 53 | Choose an embedding model when creating an index in Upstash Vector. 54 | 55 | ``` 56 | UPSTASH_VECTOR_REST_URL= 57 | UPSTASH_VECTOR_REST_TOKEN= 58 | 59 | # Optional for persistent chat history 60 | UPSTASH_REDIS_REST_URL= 61 | UPSTASH_REDIS_REST_TOKEN= 62 | 63 | OPENAI_API_KEY= 64 | 65 | TOGETHER_API_KEY= 66 | 67 | # Optional 68 | TOGETHER_MODEL= 69 | ``` 70 | 71 | ### 2. Configure Styles 72 | 73 | In your `tailwind.config.ts` file, add the configuration below: 74 | 75 | ```ts 76 | import type { Config } from "tailwindcss"; 77 | 78 | export default { 79 | content: ["./node_modules/@upstash/rag-chat-component/**/*.{js,mjs}"], 80 | } satisfies Config; 81 | ``` 82 | 83 | ### 3. Implementation 84 | 85 | The RAG Chat Component can be integrated into your application using two straightforward approaches. Choose the method that best fits your project structure: 86 | 87 | #### 1. Using a Dedicated Component File (Recommended) 88 | 89 | Create a seperate component file with the `use client` directive, then import and use it anywhere in your application. 90 | 91 | ```jsx 92 | // components/chat.tsx 93 | "use client"; 94 | 95 | import { ChatComponent } from "@upstash/rag-chat-component"; 96 | 97 | export const Chat = () => { 98 | return ; 99 | }; 100 | ``` 101 | 102 | ```jsx 103 | // page.tsx 104 | import { Chat } from "./components/chat"; 105 | 106 | export default function Home() { 107 | return ( 108 | <> 109 | 110 |

Home

111 | 112 | ); 113 | } 114 | ``` 115 | 116 | #### 2. Direct Integration in Client Components 117 | 118 | Alternatively, import and use the **ChatComponent** directly in your client-side pages. 119 | 120 | ```jsx 121 | // page.tsx 122 | "use client"; 123 | import { ChatComponent } from "@upstash/rag-chat-component"; 124 | 125 | export default function Home() { 126 | return ( 127 | <> 128 | 129 |

Home

130 | 131 | ); 132 | } 133 | ``` 134 | 135 | ### 4. Choosing Chat Model 136 | 137 | It's possible to choose one of the [together.ai](https://www.together.ai/) models for the chat. 138 | Default model is `meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo`. You can configure it in the environment variables. 139 | 140 | ``` 141 | TOGETHER_MODEL="deepseek-ai/DeepSeek-V3" 142 | ``` 143 | 144 | ### 5. Additional Notes 145 | 146 | If you're deploying on Vercel and experiencing timeout issues, you can increase the function execution time limit by adding the following configuration to your `vercel.json`: 147 | 148 | ``` 149 | { 150 | "functions": { 151 | "app/**/*": { 152 | "maxDuration": 30 153 | } 154 | } 155 | } 156 | ``` 157 | 158 | This extends the function timeout to 30 seconds, allowing more time for RAG operations to complete on serverless functions. 159 | 160 | 161 | 162 | ## Adding Content 163 | 164 | You can add content to your RAG Chat component in several ways: 165 | 166 |
167 | 1. Using Upstash Vector SDK 168 | 169 | Upstash has Vector SDKs in JS and Python. You can use those SDK to insert data to your Vector index. 170 | 171 | [Vector JS SDK](https://github.com/upstash/vector-js) 172 | 173 | [Vector Python SDK](https://github.com/upstash/vector-py) 174 | 175 | For other languages you can use [Vector REST API](https://upstash.com/docs/vector/api/get-started). 176 | 177 |
178 | 179 |
180 | 2. Using Upstash Vector UI 181 | 182 | For testing purpose, you can add your data directly through the Upstash Vector Console: 183 | 184 | 1. Navigate to [Upstash Console](http://console.upstash.com/vector). 185 | 2. Go to details page of the Vector database. 186 | 3. Navigate to **Data Browser Tab**. 187 | 4. Here, you can upsert data or upload a PDF. 188 | 189 | Vector Databrowser
190 | 191 |
192 | 193 |
194 | 3. docs2vector tool 195 | 196 | If you are planning to insert your documentation (markdown files) to your Vector index, then you can use [docs2vector](https://github.com/upstash/docs2vector/) tool. 197 | 198 |
199 | 200 | ## Development 201 | 202 | You can use the playground for development, by basically running the command in the root. 203 | 204 | ```bash 205 | bun run playground 206 | ``` 207 | 208 | ## Roadmap 209 | 210 | - Integration with [QStash](https://upstash.com/docs/qstash/overall/getstarted) for infinite timout for serverless functions 211 | 212 | ## Contributing 213 | 214 | We welcome contributions! Please see our contributing guidelines for more details. 215 | 216 | ## License 217 | 218 | MIT License - see the LICENSE file for details. 219 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/rag-chat-component/cd9ea021276dc5bf9f5cab9ab8770de858ba9bfd/bun.lockb -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/app/globals.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/nextjs/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next/core-web-vitals", "next/typescript"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/nextjs/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | 32 | # env files (can opt-in for committing if needed) 33 | .env* 34 | 35 | # vercel 36 | .vercel 37 | 38 | # typescript 39 | *.tsbuildinfo 40 | next-env.d.ts 41 | -------------------------------------------------------------------------------- /examples/nextjs/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. 37 | -------------------------------------------------------------------------------- /examples/nextjs/app/components/chat.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { ChatComponent } from "@upstash/rag-chat-component"; 4 | 5 | export const Chat = () => { 6 | return ; 7 | }; 8 | -------------------------------------------------------------------------------- /examples/nextjs/app/components/features.tsx: -------------------------------------------------------------------------------- 1 | export default function Features() { 2 | return ( 3 |
4 | 8 | 12 | 16 | 20 |
21 | ); 22 | } 23 | 24 | export function FeatureCard({ 25 | title, 26 | description, 27 | }: { 28 | title: string; 29 | description: string; 30 | }) { 31 | return ( 32 |
33 |

{title}

34 |

{description}

35 |
36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /examples/nextjs/app/components/footer.tsx: -------------------------------------------------------------------------------- 1 | import { ArrowUpRight } from "lucide-react"; 2 | 3 | export default function Footer() { 4 | return ( 5 | 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /examples/nextjs/app/components/header.tsx: -------------------------------------------------------------------------------- 1 | export default function Header() { 2 | return ( 3 |
4 |

5 | Powered by{" "} 6 | 11 | Upstash 12 | {" "} 13 | ,{" "} 14 | 19 | TogetherAI 20 | {" "} 21 | and{" "} 22 | 27 | Vercel AI SDK 28 | 29 |

30 | 31 |

32 | AI Chat Component for Next.js 33 |

34 | 35 |

36 | A modern, customizable chat interface with streaming responses and RAG 37 | capabilities 38 |

39 | 40 | 66 |
67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /examples/nextjs/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/rag-chat-component/cd9ea021276dc5bf9f5cab9ab8770de858ba9bfd/examples/nextjs/app/favicon.ico -------------------------------------------------------------------------------- /examples/nextjs/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @keyframes anim-zoom { 6 | 0% { 7 | width: 64px; 8 | height: 64px; 9 | opacity: 1; 10 | } 11 | 99% { 12 | width: 2000px; 13 | height: 2000px; 14 | opacity: 0; 15 | } 16 | 100% { 17 | width: 64px; 18 | height: 64px; 19 | opacity: 0; 20 | } 21 | } 22 | 23 | .pulse { 24 | @apply absolute left-0 right-0 size-16 -translate-x-1/2 -translate-y-1/2 rounded-full border-[60px] border-emerald-500/20 opacity-0; 25 | animation: anim-zoom 40s ease infinite; 26 | } 27 | -------------------------------------------------------------------------------- /examples/nextjs/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Inter, Inter_Tight } from "next/font/google"; 3 | import "./globals.css"; 4 | 5 | const defaultFont = Inter({ 6 | variable: "--font-sans", 7 | subsets: ["latin"], 8 | }); 9 | 10 | const displayFont = Inter_Tight({ 11 | variable: "--font-display", 12 | subsets: ["latin"], 13 | }); 14 | 15 | export const metadata: Metadata = { 16 | title: "RAG Component", 17 | description: "Streaming Chat Component with Persistent History", 18 | icons: { 19 | icon: [{ url: "upstash.png" }], 20 | }, 21 | }; 22 | 23 | export default function RootLayout({ 24 | children, 25 | }: Readonly<{ 26 | children: React.ReactNode; 27 | }>) { 28 | return ( 29 | 33 | 34 | {children} 35 | 36 | 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /examples/nextjs/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Features from "@/app/components/features"; 2 | import Footer from "@/app/components/footer"; 3 | import Header from "@/app/components/header"; 4 | import { Chat } from "./components/chat"; 5 | 6 | export default function Home() { 7 | return ( 8 |
9 | {/* page */} 10 |
11 |
12 | 13 |
14 |
15 | 16 | {/* chat */} 17 | 18 |
19 |
20 | {[0, 5, 10, 15, 20, 25, 30, 35].map((o) => ( 21 | 26 | ))} 27 |
28 |
29 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /examples/nextjs/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | }; 6 | 7 | export default nextConfig; 8 | -------------------------------------------------------------------------------- /examples/nextjs/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs", 3 | "version": "0.1.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "nextjs", 9 | "version": "0.1.0", 10 | "dependencies": { 11 | "@upstash/rag-chat-component": "^0.2.1", 12 | "next": "15.1.4", 13 | "react": "^19.0.0", 14 | "react-dom": "^19.0.0" 15 | }, 16 | "devDependencies": { 17 | "@ianvs/prettier-plugin-sort-imports": "^4.4.1", 18 | "@types/node": "^20", 19 | "@types/react": "^19", 20 | "@types/react-dom": "^19", 21 | "postcss": "^8", 22 | "prettier": "^3.4.2", 23 | "prettier-plugin-tailwindcss": "^0.6.9", 24 | "tailwindcss": "^3.4.1", 25 | "typescript": "^5" 26 | } 27 | }, 28 | "node_modules/@ai-sdk/openai": { 29 | "version": "1.0.18", 30 | "license": "Apache-2.0", 31 | "dependencies": { 32 | "@ai-sdk/provider": "1.0.4", 33 | "@ai-sdk/provider-utils": "2.0.7" 34 | }, 35 | "engines": { 36 | "node": ">=18" 37 | }, 38 | "peerDependencies": { 39 | "zod": "^3.0.0" 40 | } 41 | }, 42 | "node_modules/@ai-sdk/provider": { 43 | "version": "1.0.4", 44 | "license": "Apache-2.0", 45 | "dependencies": { 46 | "json-schema": "^0.4.0" 47 | }, 48 | "engines": { 49 | "node": ">=18" 50 | } 51 | }, 52 | "node_modules/@ai-sdk/provider-utils": { 53 | "version": "2.0.7", 54 | "license": "Apache-2.0", 55 | "dependencies": { 56 | "@ai-sdk/provider": "1.0.4", 57 | "eventsource-parser": "^3.0.0", 58 | "nanoid": "^3.3.8", 59 | "secure-json-parse": "^2.7.0" 60 | }, 61 | "engines": { 62 | "node": ">=18" 63 | }, 64 | "peerDependencies": { 65 | "zod": "^3.0.0" 66 | }, 67 | "peerDependenciesMeta": { 68 | "zod": { 69 | "optional": true 70 | } 71 | } 72 | }, 73 | "node_modules/@ai-sdk/react": { 74 | "version": "1.0.9", 75 | "license": "Apache-2.0", 76 | "dependencies": { 77 | "@ai-sdk/provider-utils": "2.0.7", 78 | "@ai-sdk/ui-utils": "1.0.8", 79 | "swr": "^2.2.5", 80 | "throttleit": "2.1.0" 81 | }, 82 | "engines": { 83 | "node": ">=18" 84 | }, 85 | "peerDependencies": { 86 | "react": "^18 || ^19 || ^19.0.0-rc", 87 | "zod": "^3.0.0" 88 | }, 89 | "peerDependenciesMeta": { 90 | "react": { 91 | "optional": true 92 | }, 93 | "zod": { 94 | "optional": true 95 | } 96 | } 97 | }, 98 | "node_modules/@ai-sdk/ui-utils": { 99 | "version": "1.0.8", 100 | "license": "Apache-2.0", 101 | "dependencies": { 102 | "@ai-sdk/provider": "1.0.4", 103 | "@ai-sdk/provider-utils": "2.0.7", 104 | "zod-to-json-schema": "^3.23.5" 105 | }, 106 | "engines": { 107 | "node": ">=18" 108 | }, 109 | "peerDependencies": { 110 | "zod": "^3.0.0" 111 | }, 112 | "peerDependenciesMeta": { 113 | "zod": { 114 | "optional": true 115 | } 116 | } 117 | }, 118 | "node_modules/@alloc/quick-lru": { 119 | "version": "5.2.0", 120 | "license": "MIT", 121 | "engines": { 122 | "node": ">=10" 123 | }, 124 | "funding": { 125 | "url": "https://github.com/sponsors/sindresorhus" 126 | } 127 | }, 128 | "node_modules/@babel/code-frame": { 129 | "version": "7.26.2", 130 | "dev": true, 131 | "license": "MIT", 132 | "dependencies": { 133 | "@babel/helper-validator-identifier": "^7.25.9", 134 | "js-tokens": "^4.0.0", 135 | "picocolors": "^1.0.0" 136 | }, 137 | "engines": { 138 | "node": ">=6.9.0" 139 | } 140 | }, 141 | "node_modules/@babel/generator": { 142 | "version": "7.26.5", 143 | "dev": true, 144 | "license": "MIT", 145 | "dependencies": { 146 | "@babel/parser": "^7.26.5", 147 | "@babel/types": "^7.26.5", 148 | "@jridgewell/gen-mapping": "^0.3.5", 149 | "@jridgewell/trace-mapping": "^0.3.25", 150 | "jsesc": "^3.0.2" 151 | }, 152 | "engines": { 153 | "node": ">=6.9.0" 154 | } 155 | }, 156 | "node_modules/@babel/helper-string-parser": { 157 | "version": "7.25.9", 158 | "dev": true, 159 | "license": "MIT", 160 | "engines": { 161 | "node": ">=6.9.0" 162 | } 163 | }, 164 | "node_modules/@babel/helper-validator-identifier": { 165 | "version": "7.25.9", 166 | "dev": true, 167 | "license": "MIT", 168 | "engines": { 169 | "node": ">=6.9.0" 170 | } 171 | }, 172 | "node_modules/@babel/parser": { 173 | "version": "7.26.5", 174 | "dev": true, 175 | "license": "MIT", 176 | "dependencies": { 177 | "@babel/types": "^7.26.5" 178 | }, 179 | "bin": { 180 | "parser": "bin/babel-parser.js" 181 | }, 182 | "engines": { 183 | "node": ">=6.0.0" 184 | } 185 | }, 186 | "node_modules/@babel/runtime": { 187 | "version": "7.26.0", 188 | "license": "MIT", 189 | "dependencies": { 190 | "regenerator-runtime": "^0.14.0" 191 | }, 192 | "engines": { 193 | "node": ">=6.9.0" 194 | } 195 | }, 196 | "node_modules/@babel/template": { 197 | "version": "7.25.9", 198 | "dev": true, 199 | "license": "MIT", 200 | "dependencies": { 201 | "@babel/code-frame": "^7.25.9", 202 | "@babel/parser": "^7.25.9", 203 | "@babel/types": "^7.25.9" 204 | }, 205 | "engines": { 206 | "node": ">=6.9.0" 207 | } 208 | }, 209 | "node_modules/@babel/traverse": { 210 | "version": "7.26.5", 211 | "dev": true, 212 | "license": "MIT", 213 | "dependencies": { 214 | "@babel/code-frame": "^7.26.2", 215 | "@babel/generator": "^7.26.5", 216 | "@babel/parser": "^7.26.5", 217 | "@babel/template": "^7.25.9", 218 | "@babel/types": "^7.26.5", 219 | "debug": "^4.3.1", 220 | "globals": "^11.1.0" 221 | }, 222 | "engines": { 223 | "node": ">=6.9.0" 224 | } 225 | }, 226 | "node_modules/@babel/types": { 227 | "version": "7.26.5", 228 | "dev": true, 229 | "license": "MIT", 230 | "dependencies": { 231 | "@babel/helper-string-parser": "^7.25.9", 232 | "@babel/helper-validator-identifier": "^7.25.9" 233 | }, 234 | "engines": { 235 | "node": ">=6.9.0" 236 | } 237 | }, 238 | "node_modules/@ianvs/prettier-plugin-sort-imports": { 239 | "version": "4.4.1", 240 | "dev": true, 241 | "license": "Apache-2.0", 242 | "dependencies": { 243 | "@babel/generator": "^7.26.2", 244 | "@babel/parser": "^7.26.2", 245 | "@babel/traverse": "^7.25.9", 246 | "@babel/types": "^7.26.0", 247 | "semver": "^7.5.2" 248 | }, 249 | "peerDependencies": { 250 | "@vue/compiler-sfc": "2.7.x || 3.x", 251 | "prettier": "2 || 3" 252 | }, 253 | "peerDependenciesMeta": { 254 | "@vue/compiler-sfc": { 255 | "optional": true 256 | } 257 | } 258 | }, 259 | "node_modules/@isaacs/cliui": { 260 | "version": "8.0.2", 261 | "license": "ISC", 262 | "dependencies": { 263 | "string-width": "^5.1.2", 264 | "string-width-cjs": "npm:string-width@^4.2.0", 265 | "strip-ansi": "^7.0.1", 266 | "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", 267 | "wrap-ansi": "^8.1.0", 268 | "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" 269 | }, 270 | "engines": { 271 | "node": ">=12" 272 | } 273 | }, 274 | "node_modules/@jridgewell/gen-mapping": { 275 | "version": "0.3.8", 276 | "license": "MIT", 277 | "dependencies": { 278 | "@jridgewell/set-array": "^1.2.1", 279 | "@jridgewell/sourcemap-codec": "^1.4.10", 280 | "@jridgewell/trace-mapping": "^0.3.24" 281 | }, 282 | "engines": { 283 | "node": ">=6.0.0" 284 | } 285 | }, 286 | "node_modules/@jridgewell/resolve-uri": { 287 | "version": "3.1.2", 288 | "license": "MIT", 289 | "engines": { 290 | "node": ">=6.0.0" 291 | } 292 | }, 293 | "node_modules/@jridgewell/set-array": { 294 | "version": "1.2.1", 295 | "license": "MIT", 296 | "engines": { 297 | "node": ">=6.0.0" 298 | } 299 | }, 300 | "node_modules/@jridgewell/sourcemap-codec": { 301 | "version": "1.5.0", 302 | "license": "MIT" 303 | }, 304 | "node_modules/@jridgewell/trace-mapping": { 305 | "version": "0.3.25", 306 | "license": "MIT", 307 | "dependencies": { 308 | "@jridgewell/resolve-uri": "^3.1.0", 309 | "@jridgewell/sourcemap-codec": "^1.4.14" 310 | } 311 | }, 312 | "node_modules/@next/env": { 313 | "version": "15.1.4", 314 | "license": "MIT" 315 | }, 316 | "node_modules/@next/swc-darwin-arm64": { 317 | "version": "15.1.4", 318 | "cpu": [ 319 | "arm64" 320 | ], 321 | "license": "MIT", 322 | "optional": true, 323 | "os": [ 324 | "darwin" 325 | ], 326 | "engines": { 327 | "node": ">= 10" 328 | } 329 | }, 330 | "node_modules/@next/swc-darwin-x64": { 331 | "version": "15.1.4", 332 | "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.4.tgz", 333 | "integrity": "sha512-7sgf5rM7Z81V9w48F02Zz6DgEJulavC0jadab4ZsJ+K2sxMNK0/BtF8J8J3CxnsJN3DGcIdC260wEKssKTukUw==", 334 | "cpu": [ 335 | "x64" 336 | ], 337 | "optional": true, 338 | "os": [ 339 | "darwin" 340 | ], 341 | "engines": { 342 | "node": ">= 10" 343 | } 344 | }, 345 | "node_modules/@next/swc-linux-arm64-gnu": { 346 | "version": "15.1.4", 347 | "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.4.tgz", 348 | "integrity": "sha512-JaZlIMNaJenfd55kjaLWMfok+vWBlcRxqnRoZrhFQrhM1uAehP3R0+Aoe+bZOogqlZvAz53nY/k3ZyuKDtT2zQ==", 349 | "cpu": [ 350 | "arm64" 351 | ], 352 | "optional": true, 353 | "os": [ 354 | "linux" 355 | ], 356 | "engines": { 357 | "node": ">= 10" 358 | } 359 | }, 360 | "node_modules/@next/swc-linux-arm64-musl": { 361 | "version": "15.1.4", 362 | "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.4.tgz", 363 | "integrity": "sha512-7EBBjNoyTO2ipMDgCiORpwwOf5tIueFntKjcN3NK+GAQD7OzFJe84p7a2eQUeWdpzZvhVXuAtIen8QcH71ZCOQ==", 364 | "cpu": [ 365 | "arm64" 366 | ], 367 | "optional": true, 368 | "os": [ 369 | "linux" 370 | ], 371 | "engines": { 372 | "node": ">= 10" 373 | } 374 | }, 375 | "node_modules/@next/swc-linux-x64-gnu": { 376 | "version": "15.1.4", 377 | "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.4.tgz", 378 | "integrity": "sha512-9TGEgOycqZFuADyFqwmK/9g6S0FYZ3tphR4ebcmCwhL8Y12FW8pIBKJvSwV+UBjMkokstGNH+9F8F031JZKpHw==", 379 | "cpu": [ 380 | "x64" 381 | ], 382 | "optional": true, 383 | "os": [ 384 | "linux" 385 | ], 386 | "engines": { 387 | "node": ">= 10" 388 | } 389 | }, 390 | "node_modules/@next/swc-linux-x64-musl": { 391 | "version": "15.1.4", 392 | "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.4.tgz", 393 | "integrity": "sha512-0578bLRVDJOh+LdIoKvgNDz77+Bd85c5JrFgnlbI1SM3WmEQvsjxTA8ATu9Z9FCiIS/AliVAW2DV/BDwpXbtiQ==", 394 | "cpu": [ 395 | "x64" 396 | ], 397 | "optional": true, 398 | "os": [ 399 | "linux" 400 | ], 401 | "engines": { 402 | "node": ">= 10" 403 | } 404 | }, 405 | "node_modules/@next/swc-win32-arm64-msvc": { 406 | "version": "15.1.4", 407 | "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.4.tgz", 408 | "integrity": "sha512-JgFCiV4libQavwII+kncMCl30st0JVxpPOtzWcAI2jtum4HjYaclobKhj+JsRu5tFqMtA5CJIa0MvYyuu9xjjQ==", 409 | "cpu": [ 410 | "arm64" 411 | ], 412 | "optional": true, 413 | "os": [ 414 | "win32" 415 | ], 416 | "engines": { 417 | "node": ">= 10" 418 | } 419 | }, 420 | "node_modules/@next/swc-win32-x64-msvc": { 421 | "version": "15.1.4", 422 | "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.4.tgz", 423 | "integrity": "sha512-xxsJy9wzq7FR5SqPCUqdgSXiNXrMuidgckBa8nH9HtjjxsilgcN6VgXF6tZ3uEWuVEadotQJI8/9EQ6guTC4Yw==", 424 | "cpu": [ 425 | "x64" 426 | ], 427 | "optional": true, 428 | "os": [ 429 | "win32" 430 | ], 431 | "engines": { 432 | "node": ">= 10" 433 | } 434 | }, 435 | "node_modules/@nodelib/fs.scandir": { 436 | "version": "2.1.5", 437 | "license": "MIT", 438 | "dependencies": { 439 | "@nodelib/fs.stat": "2.0.5", 440 | "run-parallel": "^1.1.9" 441 | }, 442 | "engines": { 443 | "node": ">= 8" 444 | } 445 | }, 446 | "node_modules/@nodelib/fs.stat": { 447 | "version": "2.0.5", 448 | "license": "MIT", 449 | "engines": { 450 | "node": ">= 8" 451 | } 452 | }, 453 | "node_modules/@nodelib/fs.walk": { 454 | "version": "1.2.8", 455 | "license": "MIT", 456 | "dependencies": { 457 | "@nodelib/fs.scandir": "2.1.5", 458 | "fastq": "^1.6.0" 459 | }, 460 | "engines": { 461 | "node": ">= 8" 462 | } 463 | }, 464 | "node_modules/@opentelemetry/api": { 465 | "version": "1.9.0", 466 | "license": "Apache-2.0", 467 | "engines": { 468 | "node": ">=8.0.0" 469 | } 470 | }, 471 | "node_modules/@pkgjs/parseargs": { 472 | "version": "0.11.0", 473 | "license": "MIT", 474 | "optional": true, 475 | "engines": { 476 | "node": ">=14" 477 | } 478 | }, 479 | "node_modules/@radix-ui/number": { 480 | "version": "1.1.0", 481 | "license": "MIT" 482 | }, 483 | "node_modules/@radix-ui/primitive": { 484 | "version": "1.1.1", 485 | "license": "MIT" 486 | }, 487 | "node_modules/@radix-ui/react-compose-refs": { 488 | "version": "1.1.1", 489 | "license": "MIT", 490 | "peerDependencies": { 491 | "@types/react": "*", 492 | "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 493 | }, 494 | "peerDependenciesMeta": { 495 | "@types/react": { 496 | "optional": true 497 | } 498 | } 499 | }, 500 | "node_modules/@radix-ui/react-context": { 501 | "version": "1.1.1", 502 | "license": "MIT", 503 | "peerDependencies": { 504 | "@types/react": "*", 505 | "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 506 | }, 507 | "peerDependenciesMeta": { 508 | "@types/react": { 509 | "optional": true 510 | } 511 | } 512 | }, 513 | "node_modules/@radix-ui/react-direction": { 514 | "version": "1.1.0", 515 | "license": "MIT", 516 | "peerDependencies": { 517 | "@types/react": "*", 518 | "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 519 | }, 520 | "peerDependenciesMeta": { 521 | "@types/react": { 522 | "optional": true 523 | } 524 | } 525 | }, 526 | "node_modules/@radix-ui/react-presence": { 527 | "version": "1.1.2", 528 | "license": "MIT", 529 | "dependencies": { 530 | "@radix-ui/react-compose-refs": "1.1.1", 531 | "@radix-ui/react-use-layout-effect": "1.1.0" 532 | }, 533 | "peerDependencies": { 534 | "@types/react": "*", 535 | "@types/react-dom": "*", 536 | "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 537 | "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 538 | }, 539 | "peerDependenciesMeta": { 540 | "@types/react": { 541 | "optional": true 542 | }, 543 | "@types/react-dom": { 544 | "optional": true 545 | } 546 | } 547 | }, 548 | "node_modules/@radix-ui/react-primitive": { 549 | "version": "2.0.1", 550 | "license": "MIT", 551 | "dependencies": { 552 | "@radix-ui/react-slot": "1.1.1" 553 | }, 554 | "peerDependencies": { 555 | "@types/react": "*", 556 | "@types/react-dom": "*", 557 | "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 558 | "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 559 | }, 560 | "peerDependenciesMeta": { 561 | "@types/react": { 562 | "optional": true 563 | }, 564 | "@types/react-dom": { 565 | "optional": true 566 | } 567 | } 568 | }, 569 | "node_modules/@radix-ui/react-scroll-area": { 570 | "version": "1.2.2", 571 | "license": "MIT", 572 | "dependencies": { 573 | "@radix-ui/number": "1.1.0", 574 | "@radix-ui/primitive": "1.1.1", 575 | "@radix-ui/react-compose-refs": "1.1.1", 576 | "@radix-ui/react-context": "1.1.1", 577 | "@radix-ui/react-direction": "1.1.0", 578 | "@radix-ui/react-presence": "1.1.2", 579 | "@radix-ui/react-primitive": "2.0.1", 580 | "@radix-ui/react-use-callback-ref": "1.1.0", 581 | "@radix-ui/react-use-layout-effect": "1.1.0" 582 | }, 583 | "peerDependencies": { 584 | "@types/react": "*", 585 | "@types/react-dom": "*", 586 | "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", 587 | "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 588 | }, 589 | "peerDependenciesMeta": { 590 | "@types/react": { 591 | "optional": true 592 | }, 593 | "@types/react-dom": { 594 | "optional": true 595 | } 596 | } 597 | }, 598 | "node_modules/@radix-ui/react-slot": { 599 | "version": "1.1.1", 600 | "license": "MIT", 601 | "dependencies": { 602 | "@radix-ui/react-compose-refs": "1.1.1" 603 | }, 604 | "peerDependencies": { 605 | "@types/react": "*", 606 | "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 607 | }, 608 | "peerDependenciesMeta": { 609 | "@types/react": { 610 | "optional": true 611 | } 612 | } 613 | }, 614 | "node_modules/@radix-ui/react-use-callback-ref": { 615 | "version": "1.1.0", 616 | "license": "MIT", 617 | "peerDependencies": { 618 | "@types/react": "*", 619 | "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 620 | }, 621 | "peerDependenciesMeta": { 622 | "@types/react": { 623 | "optional": true 624 | } 625 | } 626 | }, 627 | "node_modules/@radix-ui/react-use-layout-effect": { 628 | "version": "1.1.0", 629 | "license": "MIT", 630 | "peerDependencies": { 631 | "@types/react": "*", 632 | "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" 633 | }, 634 | "peerDependenciesMeta": { 635 | "@types/react": { 636 | "optional": true 637 | } 638 | } 639 | }, 640 | "node_modules/@swc/counter": { 641 | "version": "0.1.3", 642 | "license": "Apache-2.0" 643 | }, 644 | "node_modules/@swc/helpers": { 645 | "version": "0.5.15", 646 | "license": "Apache-2.0", 647 | "dependencies": { 648 | "tslib": "^2.8.0" 649 | } 650 | }, 651 | "node_modules/@types/diff-match-patch": { 652 | "version": "1.0.36", 653 | "license": "MIT" 654 | }, 655 | "node_modules/@types/node": { 656 | "version": "20.17.12", 657 | "license": "MIT", 658 | "dependencies": { 659 | "undici-types": "~6.19.2" 660 | } 661 | }, 662 | "node_modules/@types/node-fetch": { 663 | "version": "2.6.12", 664 | "license": "MIT", 665 | "dependencies": { 666 | "@types/node": "*", 667 | "form-data": "^4.0.0" 668 | } 669 | }, 670 | "node_modules/@types/node-int64": { 671 | "version": "0.4.32", 672 | "license": "MIT", 673 | "dependencies": { 674 | "@types/node": "*" 675 | } 676 | }, 677 | "node_modules/@types/parquetjs": { 678 | "version": "0.10.6", 679 | "license": "MIT", 680 | "dependencies": { 681 | "@types/node-int64": "*" 682 | } 683 | }, 684 | "node_modules/@types/progress-stream": { 685 | "version": "2.0.5", 686 | "license": "MIT", 687 | "dependencies": { 688 | "@types/node": "*" 689 | } 690 | }, 691 | "node_modules/@types/react": { 692 | "version": "19.0.6", 693 | "devOptional": true, 694 | "license": "MIT", 695 | "dependencies": { 696 | "csstype": "^3.0.2" 697 | } 698 | }, 699 | "node_modules/@types/react-dom": { 700 | "version": "19.0.3", 701 | "devOptional": true, 702 | "license": "MIT", 703 | "peerDependencies": { 704 | "@types/react": "^19.0.0" 705 | } 706 | }, 707 | "node_modules/@upstash/rag-chat-component": { 708 | "version": "0.2.1", 709 | "resolved": "https://registry.npmjs.org/@upstash/rag-chat-component/-/rag-chat-component-0.2.1.tgz", 710 | "integrity": "sha512-YsYTds0MTS85cpP9OreLQNnEFCaWv+rql+OHTd1ebnI+FNW3n2QhjNlvOuni6J15bL5xSe/Eaw5kPfzgUqEWeQ==", 711 | "dependencies": { 712 | "@ai-sdk/openai": "^1.0.18", 713 | "@radix-ui/react-scroll-area": "^1.2.2", 714 | "@radix-ui/react-slot": "^1.1.1", 715 | "@upstash/redis": "^1.34.3", 716 | "@upstash/vector": "^1.2.0", 717 | "ai": "^4.0.33", 718 | "class-variance-authority": "^0.7.1", 719 | "clsx": "^2.1.1", 720 | "lodash.debounce": "^4.0.8", 721 | "lucide-react": "^0.471.0", 722 | "react": "^19", 723 | "react-dom": "^19", 724 | "react-textarea-autosize": "^8.5.7", 725 | "tailwind-merge": "^2.6.0", 726 | "tailwindcss": "^3.4.1", 727 | "tailwindcss-animate": "^1.0.7", 728 | "together-ai": "^0.11.1" 729 | }, 730 | "peerDependencies": { 731 | "next": "^14 || ^15", 732 | "react": "^18 || ^19", 733 | "typescript": "^5" 734 | } 735 | }, 736 | "node_modules/@upstash/redis": { 737 | "version": "v1.34.3", 738 | "license": "MIT", 739 | "dependencies": { 740 | "crypto-js": "^4.2.0" 741 | } 742 | }, 743 | "node_modules/@upstash/vector": { 744 | "version": "v1.2.0", 745 | "license": "MIT" 746 | }, 747 | "node_modules/abort-controller": { 748 | "version": "3.0.0", 749 | "license": "MIT", 750 | "dependencies": { 751 | "event-target-shim": "^5.0.0" 752 | }, 753 | "engines": { 754 | "node": ">=6.5" 755 | } 756 | }, 757 | "node_modules/agentkeepalive": { 758 | "version": "4.6.0", 759 | "license": "MIT", 760 | "dependencies": { 761 | "humanize-ms": "^1.2.1" 762 | }, 763 | "engines": { 764 | "node": ">= 8.0.0" 765 | } 766 | }, 767 | "node_modules/ai": { 768 | "version": "4.0.33", 769 | "license": "Apache-2.0", 770 | "dependencies": { 771 | "@ai-sdk/provider": "1.0.4", 772 | "@ai-sdk/provider-utils": "2.0.7", 773 | "@ai-sdk/react": "1.0.9", 774 | "@ai-sdk/ui-utils": "1.0.8", 775 | "@opentelemetry/api": "1.9.0", 776 | "jsondiffpatch": "0.6.0", 777 | "zod-to-json-schema": "^3.23.5" 778 | }, 779 | "engines": { 780 | "node": ">=18" 781 | }, 782 | "peerDependencies": { 783 | "react": "^18 || ^19 || ^19.0.0-rc", 784 | "zod": "^3.0.0" 785 | }, 786 | "peerDependenciesMeta": { 787 | "react": { 788 | "optional": true 789 | }, 790 | "zod": { 791 | "optional": true 792 | } 793 | } 794 | }, 795 | "node_modules/ansi-regex": { 796 | "version": "6.1.0", 797 | "license": "MIT", 798 | "engines": { 799 | "node": ">=12" 800 | }, 801 | "funding": { 802 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 803 | } 804 | }, 805 | "node_modules/ansi-styles": { 806 | "version": "6.2.1", 807 | "license": "MIT", 808 | "engines": { 809 | "node": ">=12" 810 | }, 811 | "funding": { 812 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 813 | } 814 | }, 815 | "node_modules/any-promise": { 816 | "version": "1.3.0", 817 | "license": "MIT" 818 | }, 819 | "node_modules/anymatch": { 820 | "version": "3.1.3", 821 | "license": "ISC", 822 | "dependencies": { 823 | "normalize-path": "^3.0.0", 824 | "picomatch": "^2.0.4" 825 | }, 826 | "engines": { 827 | "node": ">= 8" 828 | } 829 | }, 830 | "node_modules/arg": { 831 | "version": "5.0.2", 832 | "license": "MIT" 833 | }, 834 | "node_modules/asynckit": { 835 | "version": "0.4.0", 836 | "license": "MIT" 837 | }, 838 | "node_modules/axios": { 839 | "version": "1.7.9", 840 | "license": "MIT", 841 | "dependencies": { 842 | "follow-redirects": "^1.15.6", 843 | "form-data": "^4.0.0", 844 | "proxy-from-env": "^1.1.0" 845 | } 846 | }, 847 | "node_modules/balanced-match": { 848 | "version": "1.0.2", 849 | "license": "MIT" 850 | }, 851 | "node_modules/base64-js": { 852 | "version": "1.5.1", 853 | "funding": [ 854 | { 855 | "type": "github", 856 | "url": "https://github.com/sponsors/feross" 857 | }, 858 | { 859 | "type": "patreon", 860 | "url": "https://www.patreon.com/feross" 861 | }, 862 | { 863 | "type": "consulting", 864 | "url": "https://feross.org/support" 865 | } 866 | ], 867 | "license": "MIT" 868 | }, 869 | "node_modules/binary-extensions": { 870 | "version": "2.3.0", 871 | "license": "MIT", 872 | "engines": { 873 | "node": ">=8" 874 | }, 875 | "funding": { 876 | "url": "https://github.com/sponsors/sindresorhus" 877 | } 878 | }, 879 | "node_modules/brace-expansion": { 880 | "version": "2.0.1", 881 | "license": "MIT", 882 | "dependencies": { 883 | "balanced-match": "^1.0.0" 884 | } 885 | }, 886 | "node_modules/braces": { 887 | "version": "3.0.3", 888 | "license": "MIT", 889 | "dependencies": { 890 | "fill-range": "^7.1.1" 891 | }, 892 | "engines": { 893 | "node": ">=8" 894 | } 895 | }, 896 | "node_modules/brotli": { 897 | "version": "1.3.3", 898 | "license": "MIT", 899 | "dependencies": { 900 | "base64-js": "^1.1.2" 901 | } 902 | }, 903 | "node_modules/bson": { 904 | "version": "1.1.6", 905 | "license": "Apache-2.0", 906 | "engines": { 907 | "node": ">=0.6.19" 908 | } 909 | }, 910 | "node_modules/busboy": { 911 | "version": "1.6.0", 912 | "dependencies": { 913 | "streamsearch": "^1.1.0" 914 | }, 915 | "engines": { 916 | "node": ">=10.16.0" 917 | } 918 | }, 919 | "node_modules/camelcase-css": { 920 | "version": "2.0.1", 921 | "license": "MIT", 922 | "engines": { 923 | "node": ">= 6" 924 | } 925 | }, 926 | "node_modules/caniuse-lite": { 927 | "version": "1.0.30001692", 928 | "funding": [ 929 | { 930 | "type": "opencollective", 931 | "url": "https://opencollective.com/browserslist" 932 | }, 933 | { 934 | "type": "tidelift", 935 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite" 936 | }, 937 | { 938 | "type": "github", 939 | "url": "https://github.com/sponsors/ai" 940 | } 941 | ], 942 | "license": "CC-BY-4.0" 943 | }, 944 | "node_modules/chalk": { 945 | "version": "5.4.1", 946 | "license": "MIT", 947 | "engines": { 948 | "node": "^12.17.0 || ^14.13 || >=16.0.0" 949 | }, 950 | "funding": { 951 | "url": "https://github.com/chalk/chalk?sponsor=1" 952 | } 953 | }, 954 | "node_modules/chokidar": { 955 | "version": "3.6.0", 956 | "license": "MIT", 957 | "dependencies": { 958 | "anymatch": "~3.1.2", 959 | "braces": "~3.0.2", 960 | "glob-parent": "~5.1.2", 961 | "is-binary-path": "~2.1.0", 962 | "is-glob": "~4.0.1", 963 | "normalize-path": "~3.0.0", 964 | "readdirp": "~3.6.0" 965 | }, 966 | "engines": { 967 | "node": ">= 8.10.0" 968 | }, 969 | "funding": { 970 | "url": "https://paulmillr.com/funding/" 971 | }, 972 | "optionalDependencies": { 973 | "fsevents": "~2.3.2" 974 | } 975 | }, 976 | "node_modules/chokidar/node_modules/glob-parent": { 977 | "version": "5.1.2", 978 | "license": "ISC", 979 | "dependencies": { 980 | "is-glob": "^4.0.1" 981 | }, 982 | "engines": { 983 | "node": ">= 6" 984 | } 985 | }, 986 | "node_modules/class-variance-authority": { 987 | "version": "0.7.1", 988 | "license": "Apache-2.0", 989 | "dependencies": { 990 | "clsx": "^2.1.1" 991 | }, 992 | "funding": { 993 | "url": "https://polar.sh/cva" 994 | } 995 | }, 996 | "node_modules/client-only": { 997 | "version": "0.0.1", 998 | "license": "MIT" 999 | }, 1000 | "node_modules/clsx": { 1001 | "version": "2.1.1", 1002 | "license": "MIT", 1003 | "engines": { 1004 | "node": ">=6" 1005 | } 1006 | }, 1007 | "node_modules/color-convert": { 1008 | "version": "2.0.1", 1009 | "license": "MIT", 1010 | "dependencies": { 1011 | "color-name": "~1.1.4" 1012 | }, 1013 | "engines": { 1014 | "node": ">=7.0.0" 1015 | } 1016 | }, 1017 | "node_modules/color-name": { 1018 | "version": "1.1.4", 1019 | "license": "MIT" 1020 | }, 1021 | "node_modules/combined-stream": { 1022 | "version": "1.0.8", 1023 | "license": "MIT", 1024 | "dependencies": { 1025 | "delayed-stream": "~1.0.0" 1026 | }, 1027 | "engines": { 1028 | "node": ">= 0.8" 1029 | } 1030 | }, 1031 | "node_modules/commander": { 1032 | "version": "4.1.1", 1033 | "license": "MIT", 1034 | "engines": { 1035 | "node": ">= 6" 1036 | } 1037 | }, 1038 | "node_modules/core-util-is": { 1039 | "version": "1.0.3", 1040 | "license": "MIT" 1041 | }, 1042 | "node_modules/cross-spawn": { 1043 | "version": "7.0.6", 1044 | "license": "MIT", 1045 | "dependencies": { 1046 | "path-key": "^3.1.0", 1047 | "shebang-command": "^2.0.0", 1048 | "which": "^2.0.1" 1049 | }, 1050 | "engines": { 1051 | "node": ">= 8" 1052 | } 1053 | }, 1054 | "node_modules/crypto-js": { 1055 | "version": "4.2.0", 1056 | "license": "MIT" 1057 | }, 1058 | "node_modules/cssesc": { 1059 | "version": "3.0.0", 1060 | "license": "MIT", 1061 | "bin": { 1062 | "cssesc": "bin/cssesc" 1063 | }, 1064 | "engines": { 1065 | "node": ">=4" 1066 | } 1067 | }, 1068 | "node_modules/csstype": { 1069 | "version": "3.1.3", 1070 | "devOptional": true, 1071 | "license": "MIT" 1072 | }, 1073 | "node_modules/debug": { 1074 | "version": "4.4.0", 1075 | "dev": true, 1076 | "license": "MIT", 1077 | "dependencies": { 1078 | "ms": "^2.1.3" 1079 | }, 1080 | "engines": { 1081 | "node": ">=6.0" 1082 | }, 1083 | "peerDependenciesMeta": { 1084 | "supports-color": { 1085 | "optional": true 1086 | } 1087 | } 1088 | }, 1089 | "node_modules/delayed-stream": { 1090 | "version": "1.0.0", 1091 | "license": "MIT", 1092 | "engines": { 1093 | "node": ">=0.4.0" 1094 | } 1095 | }, 1096 | "node_modules/dequal": { 1097 | "version": "2.0.3", 1098 | "license": "MIT", 1099 | "engines": { 1100 | "node": ">=6" 1101 | } 1102 | }, 1103 | "node_modules/didyoumean": { 1104 | "version": "1.2.2", 1105 | "license": "Apache-2.0" 1106 | }, 1107 | "node_modules/diff-match-patch": { 1108 | "version": "1.0.5", 1109 | "license": "Apache-2.0" 1110 | }, 1111 | "node_modules/dlv": { 1112 | "version": "1.1.3", 1113 | "license": "MIT" 1114 | }, 1115 | "node_modules/eastasianwidth": { 1116 | "version": "0.2.0", 1117 | "license": "MIT" 1118 | }, 1119 | "node_modules/emoji-regex": { 1120 | "version": "9.2.2", 1121 | "license": "MIT" 1122 | }, 1123 | "node_modules/event-target-shim": { 1124 | "version": "5.0.1", 1125 | "license": "MIT", 1126 | "engines": { 1127 | "node": ">=6" 1128 | } 1129 | }, 1130 | "node_modules/eventsource-parser": { 1131 | "version": "3.0.0", 1132 | "license": "MIT", 1133 | "engines": { 1134 | "node": ">=18.0.0" 1135 | } 1136 | }, 1137 | "node_modules/fast-glob": { 1138 | "version": "3.3.3", 1139 | "license": "MIT", 1140 | "dependencies": { 1141 | "@nodelib/fs.stat": "^2.0.2", 1142 | "@nodelib/fs.walk": "^1.2.3", 1143 | "glob-parent": "^5.1.2", 1144 | "merge2": "^1.3.0", 1145 | "micromatch": "^4.0.8" 1146 | }, 1147 | "engines": { 1148 | "node": ">=8.6.0" 1149 | } 1150 | }, 1151 | "node_modules/fast-glob/node_modules/glob-parent": { 1152 | "version": "5.1.2", 1153 | "license": "ISC", 1154 | "dependencies": { 1155 | "is-glob": "^4.0.1" 1156 | }, 1157 | "engines": { 1158 | "node": ">= 6" 1159 | } 1160 | }, 1161 | "node_modules/fastq": { 1162 | "version": "1.18.0", 1163 | "license": "ISC", 1164 | "dependencies": { 1165 | "reusify": "^1.0.4" 1166 | } 1167 | }, 1168 | "node_modules/fill-range": { 1169 | "version": "7.1.1", 1170 | "license": "MIT", 1171 | "dependencies": { 1172 | "to-regex-range": "^5.0.1" 1173 | }, 1174 | "engines": { 1175 | "node": ">=8" 1176 | } 1177 | }, 1178 | "node_modules/follow-redirects": { 1179 | "version": "1.15.9", 1180 | "funding": [ 1181 | { 1182 | "type": "individual", 1183 | "url": "https://github.com/sponsors/RubenVerborgh" 1184 | } 1185 | ], 1186 | "license": "MIT", 1187 | "engines": { 1188 | "node": ">=4.0" 1189 | }, 1190 | "peerDependenciesMeta": { 1191 | "debug": { 1192 | "optional": true 1193 | } 1194 | } 1195 | }, 1196 | "node_modules/foreground-child": { 1197 | "version": "3.3.0", 1198 | "license": "ISC", 1199 | "dependencies": { 1200 | "cross-spawn": "^7.0.0", 1201 | "signal-exit": "^4.0.1" 1202 | }, 1203 | "engines": { 1204 | "node": ">=14" 1205 | }, 1206 | "funding": { 1207 | "url": "https://github.com/sponsors/isaacs" 1208 | } 1209 | }, 1210 | "node_modules/form-data": { 1211 | "version": "4.0.1", 1212 | "license": "MIT", 1213 | "dependencies": { 1214 | "asynckit": "^0.4.0", 1215 | "combined-stream": "^1.0.8", 1216 | "mime-types": "^2.1.12" 1217 | }, 1218 | "engines": { 1219 | "node": ">= 6" 1220 | } 1221 | }, 1222 | "node_modules/form-data-encoder": { 1223 | "version": "1.7.2", 1224 | "license": "MIT" 1225 | }, 1226 | "node_modules/formdata-node": { 1227 | "version": "4.4.1", 1228 | "license": "MIT", 1229 | "dependencies": { 1230 | "node-domexception": "1.0.0", 1231 | "web-streams-polyfill": "4.0.0-beta.3" 1232 | }, 1233 | "engines": { 1234 | "node": ">= 12.20" 1235 | } 1236 | }, 1237 | "node_modules/fsevents": { 1238 | "version": "2.3.3", 1239 | "license": "MIT", 1240 | "optional": true, 1241 | "os": [ 1242 | "darwin" 1243 | ], 1244 | "engines": { 1245 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1246 | } 1247 | }, 1248 | "node_modules/function-bind": { 1249 | "version": "1.1.2", 1250 | "license": "MIT", 1251 | "funding": { 1252 | "url": "https://github.com/sponsors/ljharb" 1253 | } 1254 | }, 1255 | "node_modules/glob": { 1256 | "version": "10.4.5", 1257 | "license": "ISC", 1258 | "dependencies": { 1259 | "foreground-child": "^3.1.0", 1260 | "jackspeak": "^3.1.2", 1261 | "minimatch": "^9.0.4", 1262 | "minipass": "^7.1.2", 1263 | "package-json-from-dist": "^1.0.0", 1264 | "path-scurry": "^1.11.1" 1265 | }, 1266 | "bin": { 1267 | "glob": "dist/esm/bin.mjs" 1268 | }, 1269 | "funding": { 1270 | "url": "https://github.com/sponsors/isaacs" 1271 | } 1272 | }, 1273 | "node_modules/glob-parent": { 1274 | "version": "6.0.2", 1275 | "license": "ISC", 1276 | "dependencies": { 1277 | "is-glob": "^4.0.3" 1278 | }, 1279 | "engines": { 1280 | "node": ">=10.13.0" 1281 | } 1282 | }, 1283 | "node_modules/globals": { 1284 | "version": "11.12.0", 1285 | "dev": true, 1286 | "license": "MIT", 1287 | "engines": { 1288 | "node": ">=4" 1289 | } 1290 | }, 1291 | "node_modules/hasown": { 1292 | "version": "2.0.2", 1293 | "license": "MIT", 1294 | "dependencies": { 1295 | "function-bind": "^1.1.2" 1296 | }, 1297 | "engines": { 1298 | "node": ">= 0.4" 1299 | } 1300 | }, 1301 | "node_modules/humanize-ms": { 1302 | "version": "1.2.1", 1303 | "license": "MIT", 1304 | "dependencies": { 1305 | "ms": "^2.0.0" 1306 | } 1307 | }, 1308 | "node_modules/inherits": { 1309 | "version": "2.0.4", 1310 | "license": "ISC" 1311 | }, 1312 | "node_modules/int53": { 1313 | "version": "0.2.4", 1314 | "license": "BSD-3-Clause" 1315 | }, 1316 | "node_modules/is-binary-path": { 1317 | "version": "2.1.0", 1318 | "license": "MIT", 1319 | "dependencies": { 1320 | "binary-extensions": "^2.0.0" 1321 | }, 1322 | "engines": { 1323 | "node": ">=8" 1324 | } 1325 | }, 1326 | "node_modules/is-core-module": { 1327 | "version": "2.16.1", 1328 | "license": "MIT", 1329 | "dependencies": { 1330 | "hasown": "^2.0.2" 1331 | }, 1332 | "engines": { 1333 | "node": ">= 0.4" 1334 | }, 1335 | "funding": { 1336 | "url": "https://github.com/sponsors/ljharb" 1337 | } 1338 | }, 1339 | "node_modules/is-extglob": { 1340 | "version": "2.1.1", 1341 | "license": "MIT", 1342 | "engines": { 1343 | "node": ">=0.10.0" 1344 | } 1345 | }, 1346 | "node_modules/is-fullwidth-code-point": { 1347 | "version": "3.0.0", 1348 | "license": "MIT", 1349 | "engines": { 1350 | "node": ">=8" 1351 | } 1352 | }, 1353 | "node_modules/is-glob": { 1354 | "version": "4.0.3", 1355 | "license": "MIT", 1356 | "dependencies": { 1357 | "is-extglob": "^2.1.1" 1358 | }, 1359 | "engines": { 1360 | "node": ">=0.10.0" 1361 | } 1362 | }, 1363 | "node_modules/is-number": { 1364 | "version": "7.0.0", 1365 | "license": "MIT", 1366 | "engines": { 1367 | "node": ">=0.12.0" 1368 | } 1369 | }, 1370 | "node_modules/isarray": { 1371 | "version": "1.0.0", 1372 | "license": "MIT" 1373 | }, 1374 | "node_modules/isexe": { 1375 | "version": "2.0.0", 1376 | "license": "ISC" 1377 | }, 1378 | "node_modules/jackspeak": { 1379 | "version": "3.4.3", 1380 | "license": "BlueOak-1.0.0", 1381 | "dependencies": { 1382 | "@isaacs/cliui": "^8.0.2" 1383 | }, 1384 | "funding": { 1385 | "url": "https://github.com/sponsors/isaacs" 1386 | }, 1387 | "optionalDependencies": { 1388 | "@pkgjs/parseargs": "^0.11.0" 1389 | } 1390 | }, 1391 | "node_modules/jiti": { 1392 | "version": "1.21.7", 1393 | "license": "MIT", 1394 | "bin": { 1395 | "jiti": "bin/jiti.js" 1396 | } 1397 | }, 1398 | "node_modules/js-tokens": { 1399 | "version": "4.0.0", 1400 | "dev": true, 1401 | "license": "MIT" 1402 | }, 1403 | "node_modules/jsesc": { 1404 | "version": "3.1.0", 1405 | "dev": true, 1406 | "license": "MIT", 1407 | "bin": { 1408 | "jsesc": "bin/jsesc" 1409 | }, 1410 | "engines": { 1411 | "node": ">=6" 1412 | } 1413 | }, 1414 | "node_modules/json-schema": { 1415 | "version": "0.4.0", 1416 | "license": "(AFL-2.1 OR BSD-3-Clause)" 1417 | }, 1418 | "node_modules/jsondiffpatch": { 1419 | "version": "0.6.0", 1420 | "license": "MIT", 1421 | "dependencies": { 1422 | "@types/diff-match-patch": "^1.0.36", 1423 | "chalk": "^5.3.0", 1424 | "diff-match-patch": "^1.0.5" 1425 | }, 1426 | "bin": { 1427 | "jsondiffpatch": "bin/jsondiffpatch.js" 1428 | }, 1429 | "engines": { 1430 | "node": "^18.0.0 || >=20.0.0" 1431 | } 1432 | }, 1433 | "node_modules/lilconfig": { 1434 | "version": "3.1.3", 1435 | "license": "MIT", 1436 | "engines": { 1437 | "node": ">=14" 1438 | }, 1439 | "funding": { 1440 | "url": "https://github.com/sponsors/antonk52" 1441 | } 1442 | }, 1443 | "node_modules/lines-and-columns": { 1444 | "version": "1.2.4", 1445 | "license": "MIT" 1446 | }, 1447 | "node_modules/lodash.debounce": { 1448 | "version": "4.0.8", 1449 | "license": "MIT" 1450 | }, 1451 | "node_modules/lru-cache": { 1452 | "version": "10.4.3", 1453 | "license": "ISC" 1454 | }, 1455 | "node_modules/lucide-react": { 1456 | "version": "0.471.1", 1457 | "license": "ISC", 1458 | "peerDependencies": { 1459 | "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" 1460 | } 1461 | }, 1462 | "node_modules/merge2": { 1463 | "version": "1.4.1", 1464 | "license": "MIT", 1465 | "engines": { 1466 | "node": ">= 8" 1467 | } 1468 | }, 1469 | "node_modules/micromatch": { 1470 | "version": "4.0.8", 1471 | "license": "MIT", 1472 | "dependencies": { 1473 | "braces": "^3.0.3", 1474 | "picomatch": "^2.3.1" 1475 | }, 1476 | "engines": { 1477 | "node": ">=8.6" 1478 | } 1479 | }, 1480 | "node_modules/mime-db": { 1481 | "version": "1.52.0", 1482 | "license": "MIT", 1483 | "engines": { 1484 | "node": ">= 0.6" 1485 | } 1486 | }, 1487 | "node_modules/mime-types": { 1488 | "version": "2.1.35", 1489 | "license": "MIT", 1490 | "dependencies": { 1491 | "mime-db": "1.52.0" 1492 | }, 1493 | "engines": { 1494 | "node": ">= 0.6" 1495 | } 1496 | }, 1497 | "node_modules/minimatch": { 1498 | "version": "9.0.5", 1499 | "license": "ISC", 1500 | "dependencies": { 1501 | "brace-expansion": "^2.0.1" 1502 | }, 1503 | "engines": { 1504 | "node": ">=16 || 14 >=14.17" 1505 | }, 1506 | "funding": { 1507 | "url": "https://github.com/sponsors/isaacs" 1508 | } 1509 | }, 1510 | "node_modules/minipass": { 1511 | "version": "7.1.2", 1512 | "license": "ISC", 1513 | "engines": { 1514 | "node": ">=16 || 14 >=14.17" 1515 | } 1516 | }, 1517 | "node_modules/ms": { 1518 | "version": "2.1.3", 1519 | "license": "MIT" 1520 | }, 1521 | "node_modules/mz": { 1522 | "version": "2.7.0", 1523 | "license": "MIT", 1524 | "dependencies": { 1525 | "any-promise": "^1.0.0", 1526 | "object-assign": "^4.0.1", 1527 | "thenify-all": "^1.0.0" 1528 | } 1529 | }, 1530 | "node_modules/nanoid": { 1531 | "version": "3.3.8", 1532 | "funding": [ 1533 | { 1534 | "type": "github", 1535 | "url": "https://github.com/sponsors/ai" 1536 | } 1537 | ], 1538 | "license": "MIT", 1539 | "bin": { 1540 | "nanoid": "bin/nanoid.cjs" 1541 | }, 1542 | "engines": { 1543 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1544 | } 1545 | }, 1546 | "node_modules/next": { 1547 | "version": "15.1.4", 1548 | "license": "MIT", 1549 | "dependencies": { 1550 | "@next/env": "15.1.4", 1551 | "@swc/counter": "0.1.3", 1552 | "@swc/helpers": "0.5.15", 1553 | "busboy": "1.6.0", 1554 | "caniuse-lite": "^1.0.30001579", 1555 | "postcss": "8.4.31", 1556 | "styled-jsx": "5.1.6" 1557 | }, 1558 | "bin": { 1559 | "next": "dist/bin/next" 1560 | }, 1561 | "engines": { 1562 | "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" 1563 | }, 1564 | "optionalDependencies": { 1565 | "@next/swc-darwin-arm64": "15.1.4", 1566 | "@next/swc-darwin-x64": "15.1.4", 1567 | "@next/swc-linux-arm64-gnu": "15.1.4", 1568 | "@next/swc-linux-arm64-musl": "15.1.4", 1569 | "@next/swc-linux-x64-gnu": "15.1.4", 1570 | "@next/swc-linux-x64-musl": "15.1.4", 1571 | "@next/swc-win32-arm64-msvc": "15.1.4", 1572 | "@next/swc-win32-x64-msvc": "15.1.4", 1573 | "sharp": "^0.33.5" 1574 | }, 1575 | "peerDependencies": { 1576 | "@opentelemetry/api": "^1.1.0", 1577 | "@playwright/test": "^1.41.2", 1578 | "babel-plugin-react-compiler": "*", 1579 | "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", 1580 | "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", 1581 | "sass": "^1.3.0" 1582 | }, 1583 | "peerDependenciesMeta": { 1584 | "@opentelemetry/api": { 1585 | "optional": true 1586 | }, 1587 | "@playwright/test": { 1588 | "optional": true 1589 | }, 1590 | "babel-plugin-react-compiler": { 1591 | "optional": true 1592 | }, 1593 | "sass": { 1594 | "optional": true 1595 | } 1596 | } 1597 | }, 1598 | "node_modules/next/node_modules/postcss": { 1599 | "version": "8.4.31", 1600 | "funding": [ 1601 | { 1602 | "type": "opencollective", 1603 | "url": "https://opencollective.com/postcss/" 1604 | }, 1605 | { 1606 | "type": "tidelift", 1607 | "url": "https://tidelift.com/funding/github/npm/postcss" 1608 | }, 1609 | { 1610 | "type": "github", 1611 | "url": "https://github.com/sponsors/ai" 1612 | } 1613 | ], 1614 | "license": "MIT", 1615 | "dependencies": { 1616 | "nanoid": "^3.3.6", 1617 | "picocolors": "^1.0.0", 1618 | "source-map-js": "^1.0.2" 1619 | }, 1620 | "engines": { 1621 | "node": "^10 || ^12 || >=14" 1622 | } 1623 | }, 1624 | "node_modules/node-domexception": { 1625 | "version": "1.0.0", 1626 | "funding": [ 1627 | { 1628 | "type": "github", 1629 | "url": "https://github.com/sponsors/jimmywarting" 1630 | }, 1631 | { 1632 | "type": "github", 1633 | "url": "https://paypal.me/jimmywarting" 1634 | } 1635 | ], 1636 | "license": "MIT", 1637 | "engines": { 1638 | "node": ">=10.5.0" 1639 | } 1640 | }, 1641 | "node_modules/node-fetch": { 1642 | "version": "2.7.0", 1643 | "license": "MIT", 1644 | "dependencies": { 1645 | "whatwg-url": "^5.0.0" 1646 | }, 1647 | "engines": { 1648 | "node": "4.x || >=6.0.0" 1649 | }, 1650 | "peerDependencies": { 1651 | "encoding": "^0.1.0" 1652 | }, 1653 | "peerDependenciesMeta": { 1654 | "encoding": { 1655 | "optional": true 1656 | } 1657 | } 1658 | }, 1659 | "node_modules/node-int64": { 1660 | "version": "0.4.0", 1661 | "license": "MIT" 1662 | }, 1663 | "node_modules/normalize-path": { 1664 | "version": "3.0.0", 1665 | "license": "MIT", 1666 | "engines": { 1667 | "node": ">=0.10.0" 1668 | } 1669 | }, 1670 | "node_modules/object-assign": { 1671 | "version": "4.1.1", 1672 | "license": "MIT", 1673 | "engines": { 1674 | "node": ">=0.10.0" 1675 | } 1676 | }, 1677 | "node_modules/object-hash": { 1678 | "version": "3.0.0", 1679 | "license": "MIT", 1680 | "engines": { 1681 | "node": ">= 6" 1682 | } 1683 | }, 1684 | "node_modules/object-stream": { 1685 | "version": "0.0.1", 1686 | "engines": { 1687 | "node": ">=0.10" 1688 | } 1689 | }, 1690 | "node_modules/package-json-from-dist": { 1691 | "version": "1.0.1", 1692 | "license": "BlueOak-1.0.0" 1693 | }, 1694 | "node_modules/parquetjs": { 1695 | "version": "0.11.2", 1696 | "license": "MIT", 1697 | "dependencies": { 1698 | "brotli": "^1.3.0", 1699 | "bson": "^1.0.4", 1700 | "int53": "^0.2.4", 1701 | "object-stream": "0.0.1", 1702 | "snappyjs": "^0.6.0", 1703 | "thrift": "^0.11.0", 1704 | "varint": "^5.0.0" 1705 | }, 1706 | "engines": { 1707 | "node": ">=7.6" 1708 | }, 1709 | "optionalDependencies": { 1710 | "lzo": "^0.4.0" 1711 | } 1712 | }, 1713 | "node_modules/path-key": { 1714 | "version": "3.1.1", 1715 | "license": "MIT", 1716 | "engines": { 1717 | "node": ">=8" 1718 | } 1719 | }, 1720 | "node_modules/path-parse": { 1721 | "version": "1.0.7", 1722 | "license": "MIT" 1723 | }, 1724 | "node_modules/path-scurry": { 1725 | "version": "1.11.1", 1726 | "license": "BlueOak-1.0.0", 1727 | "dependencies": { 1728 | "lru-cache": "^10.2.0", 1729 | "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" 1730 | }, 1731 | "engines": { 1732 | "node": ">=16 || 14 >=14.18" 1733 | }, 1734 | "funding": { 1735 | "url": "https://github.com/sponsors/isaacs" 1736 | } 1737 | }, 1738 | "node_modules/picocolors": { 1739 | "version": "1.1.1", 1740 | "license": "ISC" 1741 | }, 1742 | "node_modules/picomatch": { 1743 | "version": "2.3.1", 1744 | "license": "MIT", 1745 | "engines": { 1746 | "node": ">=8.6" 1747 | }, 1748 | "funding": { 1749 | "url": "https://github.com/sponsors/jonschlinkert" 1750 | } 1751 | }, 1752 | "node_modules/pify": { 1753 | "version": "2.3.0", 1754 | "license": "MIT", 1755 | "engines": { 1756 | "node": ">=0.10.0" 1757 | } 1758 | }, 1759 | "node_modules/pirates": { 1760 | "version": "4.0.6", 1761 | "license": "MIT", 1762 | "engines": { 1763 | "node": ">= 6" 1764 | } 1765 | }, 1766 | "node_modules/postcss": { 1767 | "version": "8.4.49", 1768 | "funding": [ 1769 | { 1770 | "type": "opencollective", 1771 | "url": "https://opencollective.com/postcss/" 1772 | }, 1773 | { 1774 | "type": "tidelift", 1775 | "url": "https://tidelift.com/funding/github/npm/postcss" 1776 | }, 1777 | { 1778 | "type": "github", 1779 | "url": "https://github.com/sponsors/ai" 1780 | } 1781 | ], 1782 | "license": "MIT", 1783 | "dependencies": { 1784 | "nanoid": "^3.3.7", 1785 | "picocolors": "^1.1.1", 1786 | "source-map-js": "^1.2.1" 1787 | }, 1788 | "engines": { 1789 | "node": "^10 || ^12 || >=14" 1790 | } 1791 | }, 1792 | "node_modules/postcss-import": { 1793 | "version": "15.1.0", 1794 | "license": "MIT", 1795 | "dependencies": { 1796 | "postcss-value-parser": "^4.0.0", 1797 | "read-cache": "^1.0.0", 1798 | "resolve": "^1.1.7" 1799 | }, 1800 | "engines": { 1801 | "node": ">=14.0.0" 1802 | }, 1803 | "peerDependencies": { 1804 | "postcss": "^8.0.0" 1805 | } 1806 | }, 1807 | "node_modules/postcss-js": { 1808 | "version": "4.0.1", 1809 | "license": "MIT", 1810 | "dependencies": { 1811 | "camelcase-css": "^2.0.1" 1812 | }, 1813 | "engines": { 1814 | "node": "^12 || ^14 || >= 16" 1815 | }, 1816 | "funding": { 1817 | "type": "opencollective", 1818 | "url": "https://opencollective.com/postcss/" 1819 | }, 1820 | "peerDependencies": { 1821 | "postcss": "^8.4.21" 1822 | } 1823 | }, 1824 | "node_modules/postcss-load-config": { 1825 | "version": "4.0.2", 1826 | "funding": [ 1827 | { 1828 | "type": "opencollective", 1829 | "url": "https://opencollective.com/postcss/" 1830 | }, 1831 | { 1832 | "type": "github", 1833 | "url": "https://github.com/sponsors/ai" 1834 | } 1835 | ], 1836 | "license": "MIT", 1837 | "dependencies": { 1838 | "lilconfig": "^3.0.0", 1839 | "yaml": "^2.3.4" 1840 | }, 1841 | "engines": { 1842 | "node": ">= 14" 1843 | }, 1844 | "peerDependencies": { 1845 | "postcss": ">=8.0.9", 1846 | "ts-node": ">=9.0.0" 1847 | }, 1848 | "peerDependenciesMeta": { 1849 | "postcss": { 1850 | "optional": true 1851 | }, 1852 | "ts-node": { 1853 | "optional": true 1854 | } 1855 | } 1856 | }, 1857 | "node_modules/postcss-nested": { 1858 | "version": "6.2.0", 1859 | "funding": [ 1860 | { 1861 | "type": "opencollective", 1862 | "url": "https://opencollective.com/postcss/" 1863 | }, 1864 | { 1865 | "type": "github", 1866 | "url": "https://github.com/sponsors/ai" 1867 | } 1868 | ], 1869 | "license": "MIT", 1870 | "dependencies": { 1871 | "postcss-selector-parser": "^6.1.1" 1872 | }, 1873 | "engines": { 1874 | "node": ">=12.0" 1875 | }, 1876 | "peerDependencies": { 1877 | "postcss": "^8.2.14" 1878 | } 1879 | }, 1880 | "node_modules/postcss-selector-parser": { 1881 | "version": "6.1.2", 1882 | "license": "MIT", 1883 | "dependencies": { 1884 | "cssesc": "^3.0.0", 1885 | "util-deprecate": "^1.0.2" 1886 | }, 1887 | "engines": { 1888 | "node": ">=4" 1889 | } 1890 | }, 1891 | "node_modules/postcss-value-parser": { 1892 | "version": "4.2.0", 1893 | "license": "MIT" 1894 | }, 1895 | "node_modules/prettier": { 1896 | "version": "3.4.2", 1897 | "dev": true, 1898 | "license": "MIT", 1899 | "bin": { 1900 | "prettier": "bin/prettier.cjs" 1901 | }, 1902 | "engines": { 1903 | "node": ">=14" 1904 | }, 1905 | "funding": { 1906 | "url": "https://github.com/prettier/prettier?sponsor=1" 1907 | } 1908 | }, 1909 | "node_modules/prettier-plugin-tailwindcss": { 1910 | "version": "0.6.9", 1911 | "dev": true, 1912 | "license": "MIT", 1913 | "engines": { 1914 | "node": ">=14.21.3" 1915 | }, 1916 | "peerDependencies": { 1917 | "@ianvs/prettier-plugin-sort-imports": "*", 1918 | "@prettier/plugin-pug": "*", 1919 | "@shopify/prettier-plugin-liquid": "*", 1920 | "@trivago/prettier-plugin-sort-imports": "*", 1921 | "@zackad/prettier-plugin-twig-melody": "*", 1922 | "prettier": "^3.0", 1923 | "prettier-plugin-astro": "*", 1924 | "prettier-plugin-css-order": "*", 1925 | "prettier-plugin-import-sort": "*", 1926 | "prettier-plugin-jsdoc": "*", 1927 | "prettier-plugin-marko": "*", 1928 | "prettier-plugin-multiline-arrays": "*", 1929 | "prettier-plugin-organize-attributes": "*", 1930 | "prettier-plugin-organize-imports": "*", 1931 | "prettier-plugin-sort-imports": "*", 1932 | "prettier-plugin-style-order": "*", 1933 | "prettier-plugin-svelte": "*" 1934 | }, 1935 | "peerDependenciesMeta": { 1936 | "@ianvs/prettier-plugin-sort-imports": { 1937 | "optional": true 1938 | }, 1939 | "@prettier/plugin-pug": { 1940 | "optional": true 1941 | }, 1942 | "@shopify/prettier-plugin-liquid": { 1943 | "optional": true 1944 | }, 1945 | "@trivago/prettier-plugin-sort-imports": { 1946 | "optional": true 1947 | }, 1948 | "@zackad/prettier-plugin-twig-melody": { 1949 | "optional": true 1950 | }, 1951 | "prettier-plugin-astro": { 1952 | "optional": true 1953 | }, 1954 | "prettier-plugin-css-order": { 1955 | "optional": true 1956 | }, 1957 | "prettier-plugin-import-sort": { 1958 | "optional": true 1959 | }, 1960 | "prettier-plugin-jsdoc": { 1961 | "optional": true 1962 | }, 1963 | "prettier-plugin-marko": { 1964 | "optional": true 1965 | }, 1966 | "prettier-plugin-multiline-arrays": { 1967 | "optional": true 1968 | }, 1969 | "prettier-plugin-organize-attributes": { 1970 | "optional": true 1971 | }, 1972 | "prettier-plugin-organize-imports": { 1973 | "optional": true 1974 | }, 1975 | "prettier-plugin-sort-imports": { 1976 | "optional": true 1977 | }, 1978 | "prettier-plugin-style-order": { 1979 | "optional": true 1980 | }, 1981 | "prettier-plugin-svelte": { 1982 | "optional": true 1983 | } 1984 | } 1985 | }, 1986 | "node_modules/process-nextick-args": { 1987 | "version": "2.0.1", 1988 | "license": "MIT" 1989 | }, 1990 | "node_modules/progress-stream": { 1991 | "version": "2.0.0", 1992 | "license": "BSD-2-Clause", 1993 | "dependencies": { 1994 | "speedometer": "~1.0.0", 1995 | "through2": "~2.0.3" 1996 | } 1997 | }, 1998 | "node_modules/proxy-from-env": { 1999 | "version": "1.1.0", 2000 | "license": "MIT" 2001 | }, 2002 | "node_modules/q": { 2003 | "version": "1.5.1", 2004 | "license": "MIT", 2005 | "engines": { 2006 | "node": ">=0.6.0", 2007 | "teleport": ">=0.2.0" 2008 | } 2009 | }, 2010 | "node_modules/queue-microtask": { 2011 | "version": "1.2.3", 2012 | "funding": [ 2013 | { 2014 | "type": "github", 2015 | "url": "https://github.com/sponsors/feross" 2016 | }, 2017 | { 2018 | "type": "patreon", 2019 | "url": "https://www.patreon.com/feross" 2020 | }, 2021 | { 2022 | "type": "consulting", 2023 | "url": "https://feross.org/support" 2024 | } 2025 | ], 2026 | "license": "MIT" 2027 | }, 2028 | "node_modules/react": { 2029 | "version": "19.0.0", 2030 | "license": "MIT", 2031 | "engines": { 2032 | "node": ">=0.10.0" 2033 | } 2034 | }, 2035 | "node_modules/react-dom": { 2036 | "version": "19.0.0", 2037 | "license": "MIT", 2038 | "dependencies": { 2039 | "scheduler": "^0.25.0" 2040 | }, 2041 | "peerDependencies": { 2042 | "react": "^19.0.0" 2043 | } 2044 | }, 2045 | "node_modules/react-textarea-autosize": { 2046 | "version": "8.5.7", 2047 | "license": "MIT", 2048 | "dependencies": { 2049 | "@babel/runtime": "^7.20.13", 2050 | "use-composed-ref": "^1.3.0", 2051 | "use-latest": "^1.2.1" 2052 | }, 2053 | "engines": { 2054 | "node": ">=10" 2055 | }, 2056 | "peerDependencies": { 2057 | "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 2058 | } 2059 | }, 2060 | "node_modules/read-cache": { 2061 | "version": "1.0.0", 2062 | "license": "MIT", 2063 | "dependencies": { 2064 | "pify": "^2.3.0" 2065 | } 2066 | }, 2067 | "node_modules/readable-stream": { 2068 | "version": "2.3.8", 2069 | "license": "MIT", 2070 | "dependencies": { 2071 | "core-util-is": "~1.0.0", 2072 | "inherits": "~2.0.3", 2073 | "isarray": "~1.0.0", 2074 | "process-nextick-args": "~2.0.0", 2075 | "safe-buffer": "~5.1.1", 2076 | "string_decoder": "~1.1.1", 2077 | "util-deprecate": "~1.0.1" 2078 | } 2079 | }, 2080 | "node_modules/readdirp": { 2081 | "version": "3.6.0", 2082 | "license": "MIT", 2083 | "dependencies": { 2084 | "picomatch": "^2.2.1" 2085 | }, 2086 | "engines": { 2087 | "node": ">=8.10.0" 2088 | } 2089 | }, 2090 | "node_modules/regenerator-runtime": { 2091 | "version": "0.14.1", 2092 | "license": "MIT" 2093 | }, 2094 | "node_modules/resolve": { 2095 | "version": "1.22.10", 2096 | "license": "MIT", 2097 | "dependencies": { 2098 | "is-core-module": "^2.16.0", 2099 | "path-parse": "^1.0.7", 2100 | "supports-preserve-symlinks-flag": "^1.0.0" 2101 | }, 2102 | "bin": { 2103 | "resolve": "bin/resolve" 2104 | }, 2105 | "engines": { 2106 | "node": ">= 0.4" 2107 | }, 2108 | "funding": { 2109 | "url": "https://github.com/sponsors/ljharb" 2110 | } 2111 | }, 2112 | "node_modules/reusify": { 2113 | "version": "1.0.4", 2114 | "license": "MIT", 2115 | "engines": { 2116 | "iojs": ">=1.0.0", 2117 | "node": ">=0.10.0" 2118 | } 2119 | }, 2120 | "node_modules/run-parallel": { 2121 | "version": "1.2.0", 2122 | "funding": [ 2123 | { 2124 | "type": "github", 2125 | "url": "https://github.com/sponsors/feross" 2126 | }, 2127 | { 2128 | "type": "patreon", 2129 | "url": "https://www.patreon.com/feross" 2130 | }, 2131 | { 2132 | "type": "consulting", 2133 | "url": "https://feross.org/support" 2134 | } 2135 | ], 2136 | "license": "MIT", 2137 | "dependencies": { 2138 | "queue-microtask": "^1.2.2" 2139 | } 2140 | }, 2141 | "node_modules/safe-buffer": { 2142 | "version": "5.1.2", 2143 | "license": "MIT" 2144 | }, 2145 | "node_modules/scheduler": { 2146 | "version": "0.25.0", 2147 | "license": "MIT" 2148 | }, 2149 | "node_modules/secure-json-parse": { 2150 | "version": "2.7.0", 2151 | "license": "BSD-3-Clause" 2152 | }, 2153 | "node_modules/semver": { 2154 | "version": "7.6.3", 2155 | "dev": true, 2156 | "license": "ISC", 2157 | "bin": { 2158 | "semver": "bin/semver.js" 2159 | }, 2160 | "engines": { 2161 | "node": ">=10" 2162 | } 2163 | }, 2164 | "node_modules/shebang-command": { 2165 | "version": "2.0.0", 2166 | "license": "MIT", 2167 | "dependencies": { 2168 | "shebang-regex": "^3.0.0" 2169 | }, 2170 | "engines": { 2171 | "node": ">=8" 2172 | } 2173 | }, 2174 | "node_modules/shebang-regex": { 2175 | "version": "3.0.0", 2176 | "license": "MIT", 2177 | "engines": { 2178 | "node": ">=8" 2179 | } 2180 | }, 2181 | "node_modules/signal-exit": { 2182 | "version": "4.1.0", 2183 | "license": "ISC", 2184 | "engines": { 2185 | "node": ">=14" 2186 | }, 2187 | "funding": { 2188 | "url": "https://github.com/sponsors/isaacs" 2189 | } 2190 | }, 2191 | "node_modules/snappyjs": { 2192 | "version": "0.6.1", 2193 | "license": "MIT" 2194 | }, 2195 | "node_modules/source-map-js": { 2196 | "version": "1.2.1", 2197 | "license": "BSD-3-Clause", 2198 | "engines": { 2199 | "node": ">=0.10.0" 2200 | } 2201 | }, 2202 | "node_modules/speedometer": { 2203 | "version": "1.0.0", 2204 | "license": "MIT" 2205 | }, 2206 | "node_modules/streamsearch": { 2207 | "version": "1.1.0", 2208 | "engines": { 2209 | "node": ">=10.0.0" 2210 | } 2211 | }, 2212 | "node_modules/string_decoder": { 2213 | "version": "1.1.1", 2214 | "license": "MIT", 2215 | "dependencies": { 2216 | "safe-buffer": "~5.1.0" 2217 | } 2218 | }, 2219 | "node_modules/string-width": { 2220 | "version": "5.1.2", 2221 | "license": "MIT", 2222 | "dependencies": { 2223 | "eastasianwidth": "^0.2.0", 2224 | "emoji-regex": "^9.2.2", 2225 | "strip-ansi": "^7.0.1" 2226 | }, 2227 | "engines": { 2228 | "node": ">=12" 2229 | }, 2230 | "funding": { 2231 | "url": "https://github.com/sponsors/sindresorhus" 2232 | } 2233 | }, 2234 | "node_modules/string-width-cjs": { 2235 | "name": "string-width", 2236 | "version": "4.2.3", 2237 | "license": "MIT", 2238 | "dependencies": { 2239 | "emoji-regex": "^8.0.0", 2240 | "is-fullwidth-code-point": "^3.0.0", 2241 | "strip-ansi": "^6.0.1" 2242 | }, 2243 | "engines": { 2244 | "node": ">=8" 2245 | } 2246 | }, 2247 | "node_modules/string-width-cjs/node_modules/ansi-regex": { 2248 | "version": "5.0.1", 2249 | "license": "MIT", 2250 | "engines": { 2251 | "node": ">=8" 2252 | } 2253 | }, 2254 | "node_modules/string-width-cjs/node_modules/emoji-regex": { 2255 | "version": "8.0.0", 2256 | "license": "MIT" 2257 | }, 2258 | "node_modules/string-width-cjs/node_modules/strip-ansi": { 2259 | "version": "6.0.1", 2260 | "license": "MIT", 2261 | "dependencies": { 2262 | "ansi-regex": "^5.0.1" 2263 | }, 2264 | "engines": { 2265 | "node": ">=8" 2266 | } 2267 | }, 2268 | "node_modules/strip-ansi": { 2269 | "version": "7.1.0", 2270 | "license": "MIT", 2271 | "dependencies": { 2272 | "ansi-regex": "^6.0.1" 2273 | }, 2274 | "engines": { 2275 | "node": ">=12" 2276 | }, 2277 | "funding": { 2278 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 2279 | } 2280 | }, 2281 | "node_modules/strip-ansi-cjs": { 2282 | "name": "strip-ansi", 2283 | "version": "6.0.1", 2284 | "license": "MIT", 2285 | "dependencies": { 2286 | "ansi-regex": "^5.0.1" 2287 | }, 2288 | "engines": { 2289 | "node": ">=8" 2290 | } 2291 | }, 2292 | "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { 2293 | "version": "5.0.1", 2294 | "license": "MIT", 2295 | "engines": { 2296 | "node": ">=8" 2297 | } 2298 | }, 2299 | "node_modules/styled-jsx": { 2300 | "version": "5.1.6", 2301 | "license": "MIT", 2302 | "dependencies": { 2303 | "client-only": "0.0.1" 2304 | }, 2305 | "engines": { 2306 | "node": ">= 12.0.0" 2307 | }, 2308 | "peerDependencies": { 2309 | "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" 2310 | }, 2311 | "peerDependenciesMeta": { 2312 | "@babel/core": { 2313 | "optional": true 2314 | }, 2315 | "babel-plugin-macros": { 2316 | "optional": true 2317 | } 2318 | } 2319 | }, 2320 | "node_modules/sucrase": { 2321 | "version": "3.35.0", 2322 | "license": "MIT", 2323 | "dependencies": { 2324 | "@jridgewell/gen-mapping": "^0.3.2", 2325 | "commander": "^4.0.0", 2326 | "glob": "^10.3.10", 2327 | "lines-and-columns": "^1.1.6", 2328 | "mz": "^2.7.0", 2329 | "pirates": "^4.0.1", 2330 | "ts-interface-checker": "^0.1.9" 2331 | }, 2332 | "bin": { 2333 | "sucrase": "bin/sucrase", 2334 | "sucrase-node": "bin/sucrase-node" 2335 | }, 2336 | "engines": { 2337 | "node": ">=16 || 14 >=14.17" 2338 | } 2339 | }, 2340 | "node_modules/supports-preserve-symlinks-flag": { 2341 | "version": "1.0.0", 2342 | "license": "MIT", 2343 | "engines": { 2344 | "node": ">= 0.4" 2345 | }, 2346 | "funding": { 2347 | "url": "https://github.com/sponsors/ljharb" 2348 | } 2349 | }, 2350 | "node_modules/swr": { 2351 | "version": "2.3.0", 2352 | "license": "MIT", 2353 | "dependencies": { 2354 | "dequal": "^2.0.3", 2355 | "use-sync-external-store": "^1.4.0" 2356 | }, 2357 | "peerDependencies": { 2358 | "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 2359 | } 2360 | }, 2361 | "node_modules/tailwind-merge": { 2362 | "version": "2.6.0", 2363 | "license": "MIT", 2364 | "funding": { 2365 | "type": "github", 2366 | "url": "https://github.com/sponsors/dcastil" 2367 | } 2368 | }, 2369 | "node_modules/tailwindcss": { 2370 | "version": "3.4.17", 2371 | "license": "MIT", 2372 | "dependencies": { 2373 | "@alloc/quick-lru": "^5.2.0", 2374 | "arg": "^5.0.2", 2375 | "chokidar": "^3.6.0", 2376 | "didyoumean": "^1.2.2", 2377 | "dlv": "^1.1.3", 2378 | "fast-glob": "^3.3.2", 2379 | "glob-parent": "^6.0.2", 2380 | "is-glob": "^4.0.3", 2381 | "jiti": "^1.21.6", 2382 | "lilconfig": "^3.1.3", 2383 | "micromatch": "^4.0.8", 2384 | "normalize-path": "^3.0.0", 2385 | "object-hash": "^3.0.0", 2386 | "picocolors": "^1.1.1", 2387 | "postcss": "^8.4.47", 2388 | "postcss-import": "^15.1.0", 2389 | "postcss-js": "^4.0.1", 2390 | "postcss-load-config": "^4.0.2", 2391 | "postcss-nested": "^6.2.0", 2392 | "postcss-selector-parser": "^6.1.2", 2393 | "resolve": "^1.22.8", 2394 | "sucrase": "^3.35.0" 2395 | }, 2396 | "bin": { 2397 | "tailwind": "lib/cli.js", 2398 | "tailwindcss": "lib/cli.js" 2399 | }, 2400 | "engines": { 2401 | "node": ">=14.0.0" 2402 | } 2403 | }, 2404 | "node_modules/tailwindcss-animate": { 2405 | "version": "1.0.7", 2406 | "license": "MIT", 2407 | "peerDependencies": { 2408 | "tailwindcss": ">=3.0.0 || insiders" 2409 | } 2410 | }, 2411 | "node_modules/thenify": { 2412 | "version": "3.3.1", 2413 | "license": "MIT", 2414 | "dependencies": { 2415 | "any-promise": "^1.0.0" 2416 | } 2417 | }, 2418 | "node_modules/thenify-all": { 2419 | "version": "1.6.0", 2420 | "license": "MIT", 2421 | "dependencies": { 2422 | "thenify": ">= 3.1.0 < 4" 2423 | }, 2424 | "engines": { 2425 | "node": ">=0.8" 2426 | } 2427 | }, 2428 | "node_modules/thrift": { 2429 | "version": "0.11.0", 2430 | "license": "Apache-2.0", 2431 | "dependencies": { 2432 | "node-int64": "^0.4.0", 2433 | "q": "^1.5.0", 2434 | "ws": ">= 2.2.3" 2435 | }, 2436 | "engines": { 2437 | "node": ">= 4.1.0" 2438 | } 2439 | }, 2440 | "node_modules/throttleit": { 2441 | "version": "2.1.0", 2442 | "license": "MIT", 2443 | "engines": { 2444 | "node": ">=18" 2445 | }, 2446 | "funding": { 2447 | "url": "https://github.com/sponsors/sindresorhus" 2448 | } 2449 | }, 2450 | "node_modules/through2": { 2451 | "version": "2.0.5", 2452 | "license": "MIT", 2453 | "dependencies": { 2454 | "readable-stream": "~2.3.6", 2455 | "xtend": "~4.0.1" 2456 | } 2457 | }, 2458 | "node_modules/to-regex-range": { 2459 | "version": "5.0.1", 2460 | "license": "MIT", 2461 | "dependencies": { 2462 | "is-number": "^7.0.0" 2463 | }, 2464 | "engines": { 2465 | "node": ">=8.0" 2466 | } 2467 | }, 2468 | "node_modules/together-ai": { 2469 | "version": "0.11.1", 2470 | "license": "Apache-2.0", 2471 | "dependencies": { 2472 | "@types/node": "^18.11.18", 2473 | "@types/node-fetch": "^2.6.4", 2474 | "@types/parquetjs": "^0.10.6", 2475 | "@types/progress-stream": "^2.0.5", 2476 | "abort-controller": "^3.0.0", 2477 | "agentkeepalive": "^4.2.1", 2478 | "axios": "^1.7.7", 2479 | "form-data-encoder": "1.7.2", 2480 | "formdata-node": "^4.3.2", 2481 | "node-fetch": "^2.6.7", 2482 | "parquetjs": "^0.11.2", 2483 | "progress-stream": "^2.0.0" 2484 | } 2485 | }, 2486 | "node_modules/together-ai/node_modules/@types/node": { 2487 | "version": "18.19.70", 2488 | "license": "MIT", 2489 | "dependencies": { 2490 | "undici-types": "~5.26.4" 2491 | } 2492 | }, 2493 | "node_modules/together-ai/node_modules/undici-types": { 2494 | "version": "5.26.5", 2495 | "license": "MIT" 2496 | }, 2497 | "node_modules/tr46": { 2498 | "version": "0.0.3", 2499 | "license": "MIT" 2500 | }, 2501 | "node_modules/ts-interface-checker": { 2502 | "version": "0.1.13", 2503 | "license": "Apache-2.0" 2504 | }, 2505 | "node_modules/tslib": { 2506 | "version": "2.8.1", 2507 | "license": "0BSD" 2508 | }, 2509 | "node_modules/typescript": { 2510 | "version": "5.7.3", 2511 | "license": "Apache-2.0", 2512 | "bin": { 2513 | "tsc": "bin/tsc", 2514 | "tsserver": "bin/tsserver" 2515 | }, 2516 | "engines": { 2517 | "node": ">=14.17" 2518 | } 2519 | }, 2520 | "node_modules/undici-types": { 2521 | "version": "6.19.8", 2522 | "license": "MIT" 2523 | }, 2524 | "node_modules/use-composed-ref": { 2525 | "version": "1.4.0", 2526 | "license": "MIT", 2527 | "peerDependencies": { 2528 | "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 2529 | }, 2530 | "peerDependenciesMeta": { 2531 | "@types/react": { 2532 | "optional": true 2533 | } 2534 | } 2535 | }, 2536 | "node_modules/use-isomorphic-layout-effect": { 2537 | "version": "1.2.0", 2538 | "license": "MIT", 2539 | "peerDependencies": { 2540 | "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 2541 | }, 2542 | "peerDependenciesMeta": { 2543 | "@types/react": { 2544 | "optional": true 2545 | } 2546 | } 2547 | }, 2548 | "node_modules/use-latest": { 2549 | "version": "1.3.0", 2550 | "license": "MIT", 2551 | "dependencies": { 2552 | "use-isomorphic-layout-effect": "^1.1.1" 2553 | }, 2554 | "peerDependencies": { 2555 | "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 2556 | }, 2557 | "peerDependenciesMeta": { 2558 | "@types/react": { 2559 | "optional": true 2560 | } 2561 | } 2562 | }, 2563 | "node_modules/use-sync-external-store": { 2564 | "version": "1.4.0", 2565 | "license": "MIT", 2566 | "peerDependencies": { 2567 | "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 2568 | } 2569 | }, 2570 | "node_modules/util-deprecate": { 2571 | "version": "1.0.2", 2572 | "license": "MIT" 2573 | }, 2574 | "node_modules/varint": { 2575 | "version": "5.0.2", 2576 | "license": "MIT" 2577 | }, 2578 | "node_modules/web-streams-polyfill": { 2579 | "version": "4.0.0-beta.3", 2580 | "license": "MIT", 2581 | "engines": { 2582 | "node": ">= 14" 2583 | } 2584 | }, 2585 | "node_modules/webidl-conversions": { 2586 | "version": "3.0.1", 2587 | "license": "BSD-2-Clause" 2588 | }, 2589 | "node_modules/whatwg-url": { 2590 | "version": "5.0.0", 2591 | "license": "MIT", 2592 | "dependencies": { 2593 | "tr46": "~0.0.3", 2594 | "webidl-conversions": "^3.0.0" 2595 | } 2596 | }, 2597 | "node_modules/which": { 2598 | "version": "2.0.2", 2599 | "license": "ISC", 2600 | "dependencies": { 2601 | "isexe": "^2.0.0" 2602 | }, 2603 | "bin": { 2604 | "node-which": "bin/node-which" 2605 | }, 2606 | "engines": { 2607 | "node": ">= 8" 2608 | } 2609 | }, 2610 | "node_modules/wrap-ansi": { 2611 | "version": "8.1.0", 2612 | "license": "MIT", 2613 | "dependencies": { 2614 | "ansi-styles": "^6.1.0", 2615 | "string-width": "^5.0.1", 2616 | "strip-ansi": "^7.0.1" 2617 | }, 2618 | "engines": { 2619 | "node": ">=12" 2620 | }, 2621 | "funding": { 2622 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2623 | } 2624 | }, 2625 | "node_modules/wrap-ansi-cjs": { 2626 | "name": "wrap-ansi", 2627 | "version": "7.0.0", 2628 | "license": "MIT", 2629 | "dependencies": { 2630 | "ansi-styles": "^4.0.0", 2631 | "string-width": "^4.1.0", 2632 | "strip-ansi": "^6.0.0" 2633 | }, 2634 | "engines": { 2635 | "node": ">=10" 2636 | }, 2637 | "funding": { 2638 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2639 | } 2640 | }, 2641 | "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { 2642 | "version": "5.0.1", 2643 | "license": "MIT", 2644 | "engines": { 2645 | "node": ">=8" 2646 | } 2647 | }, 2648 | "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { 2649 | "version": "4.3.0", 2650 | "license": "MIT", 2651 | "dependencies": { 2652 | "color-convert": "^2.0.1" 2653 | }, 2654 | "engines": { 2655 | "node": ">=8" 2656 | }, 2657 | "funding": { 2658 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 2659 | } 2660 | }, 2661 | "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { 2662 | "version": "8.0.0", 2663 | "license": "MIT" 2664 | }, 2665 | "node_modules/wrap-ansi-cjs/node_modules/string-width": { 2666 | "version": "4.2.3", 2667 | "license": "MIT", 2668 | "dependencies": { 2669 | "emoji-regex": "^8.0.0", 2670 | "is-fullwidth-code-point": "^3.0.0", 2671 | "strip-ansi": "^6.0.1" 2672 | }, 2673 | "engines": { 2674 | "node": ">=8" 2675 | } 2676 | }, 2677 | "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { 2678 | "version": "6.0.1", 2679 | "license": "MIT", 2680 | "dependencies": { 2681 | "ansi-regex": "^5.0.1" 2682 | }, 2683 | "engines": { 2684 | "node": ">=8" 2685 | } 2686 | }, 2687 | "node_modules/ws": { 2688 | "version": "8.18.0", 2689 | "license": "MIT", 2690 | "engines": { 2691 | "node": ">=10.0.0" 2692 | }, 2693 | "peerDependencies": { 2694 | "bufferutil": "^4.0.1", 2695 | "utf-8-validate": ">=5.0.2" 2696 | }, 2697 | "peerDependenciesMeta": { 2698 | "bufferutil": { 2699 | "optional": true 2700 | }, 2701 | "utf-8-validate": { 2702 | "optional": true 2703 | } 2704 | } 2705 | }, 2706 | "node_modules/xtend": { 2707 | "version": "4.0.2", 2708 | "license": "MIT", 2709 | "engines": { 2710 | "node": ">=0.4" 2711 | } 2712 | }, 2713 | "node_modules/yaml": { 2714 | "version": "2.7.0", 2715 | "license": "ISC", 2716 | "bin": { 2717 | "yaml": "bin.mjs" 2718 | }, 2719 | "engines": { 2720 | "node": ">= 14" 2721 | } 2722 | }, 2723 | "node_modules/zod": { 2724 | "version": "3.24.1", 2725 | "license": "MIT", 2726 | "peer": true, 2727 | "funding": { 2728 | "url": "https://github.com/sponsors/colinhacks" 2729 | } 2730 | }, 2731 | "node_modules/zod-to-json-schema": { 2732 | "version": "3.24.1", 2733 | "license": "ISC", 2734 | "peerDependencies": { 2735 | "zod": "^3.24.1" 2736 | } 2737 | } 2738 | } 2739 | } 2740 | -------------------------------------------------------------------------------- /examples/nextjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint", 10 | "format": "pnpm prettier --write ." 11 | }, 12 | "dependencies": { 13 | "@upstash/rag-chat-component": "^0.2.2", 14 | "next": "15.1.4", 15 | "react": "^19.0.0", 16 | "react-dom": "^19.0.0" 17 | }, 18 | "devDependencies": { 19 | "@ianvs/prettier-plugin-sort-imports": "^4.4.1", 20 | "@types/node": "^20", 21 | "@types/react": "^19", 22 | "@types/react-dom": "^19", 23 | "postcss": "^8", 24 | "prettier": "^3.4.2", 25 | "prettier-plugin-tailwindcss": "^0.6.9", 26 | "tailwindcss": "^3.4.1", 27 | "typescript": "^5" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/nextjs/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /examples/nextjs/prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: "always", 3 | bracketSameLine: false, 4 | bracketSpacing: true, 5 | semi: true, 6 | singleQuote: false, 7 | jsxSingleQuote: false, 8 | trailingComma: "all", 9 | singleAttributePerLine: false, 10 | importOrderSeparation: true, 11 | importOrderSortSpecifiers: true, 12 | importOrderBuiltinModulesToTop: true, 13 | tailwindFunctions: ["clsx"], 14 | plugins: [ 15 | "@ianvs/prettier-plugin-sort-imports", 16 | "prettier-plugin-tailwindcss", 17 | ], 18 | }; 19 | -------------------------------------------------------------------------------- /examples/nextjs/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | export default { 4 | content: [ 5 | "./pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./app/**/*.{js,ts,jsx,tsx,mdx}", 8 | "./node_modules/@upstash/rag-chat-component/**/*.{js,mjs}", 9 | ], 10 | theme: { 11 | extend: { 12 | fontFamily: { 13 | sans: ["var(--font-sans)"], 14 | display: ["var(--font-display)"], 15 | }, 16 | }, 17 | }, 18 | } satisfies Config; 19 | -------------------------------------------------------------------------------- /examples/nextjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /examples/nextjs/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "functions": { 3 | "app/**/*": { 4 | "maxDuration": 30 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | console.log("Hello via Bun!"); 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@upstash/rag-chat-component", 3 | "description": "Streaming Chat Component with Persistent History", 4 | "version": "0.2.2", 5 | "module": "index.ts", 6 | "main": "./dist/client/index.mjs", 7 | "types": "./dist/client/index.d.ts", 8 | "exports": { 9 | ".": { 10 | "import": "./dist/client/index.mjs" 11 | }, 12 | "./styles.css": "./dist/client/styles.mjs" 13 | }, 14 | "files": [ 15 | "dist" 16 | ], 17 | "peerDependencies": { 18 | "next": "^14 || ^15", 19 | "react": "^18 || ^19", 20 | "typescript": "^5" 21 | }, 22 | "scripts": { 23 | "build": "tsup", 24 | "playground": "cd playground && npm run dev" 25 | }, 26 | "dependencies": { 27 | "@ai-sdk/openai": "^1.0.18", 28 | "@radix-ui/react-scroll-area": "^1.2.2", 29 | "@radix-ui/react-slot": "^1.1.1", 30 | "@upstash/redis": "^1.34.3", 31 | "@upstash/vector": "^1.2.0", 32 | "ai": "^4.0.33", 33 | "class-variance-authority": "^0.7.1", 34 | "clsx": "^2.1.1", 35 | "lodash.debounce": "^4.0.8", 36 | "lucide-react": "^0.471.0", 37 | "react": "^19", 38 | "react-dom": "^19", 39 | "react-textarea-autosize": "^8.5.7", 40 | "tailwind-merge": "^2.6.0", 41 | "tailwindcss": "^3.4.1", 42 | "tailwindcss-animate": "^1.0.7", 43 | "together-ai": "^0.11.1" 44 | }, 45 | "devDependencies": { 46 | "@types/bun": "latest", 47 | "@types/lodash.debounce": "^4.0.9", 48 | "@types/node": "^22", 49 | "@types/react": "^19", 50 | "@types/react-dom": "^19", 51 | "autoprefixer": "^10.4.20", 52 | "esbuild-fix-imports-plugin": "^1.0.10", 53 | "postcss": "^8", 54 | "postcss-prefix-selector": "^2.1.0", 55 | "prettier": "^3.4.2", 56 | "prettier-plugin-tailwindcss": "^0.6.9", 57 | "tsup": "^8.2.0" 58 | }, 59 | "homepage": "https://github.com/upstash/rag-chat-component#readme", 60 | "author": "Fahreddin Ozcan", 61 | "license": "MIT", 62 | "bugs": { 63 | "url": "https://github.com/upstash/rag-chat-component/issues" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /playground/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env* 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | -------------------------------------------------------------------------------- /playground/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. 37 | -------------------------------------------------------------------------------- /playground/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { dirname } from "path"; 2 | import { fileURLToPath } from "url"; 3 | import { FlatCompat } from "@eslint/eslintrc"; 4 | 5 | const __filename = fileURLToPath(import.meta.url); 6 | const __dirname = dirname(__filename); 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }); 11 | 12 | const eslintConfig = [ 13 | ...compat.extends("next/core-web-vitals", "next/typescript"), 14 | ]; 15 | 16 | export default eslintConfig; 17 | -------------------------------------------------------------------------------- /playground/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | }; 6 | 7 | export default nextConfig; 8 | -------------------------------------------------------------------------------- /playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playground", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "react": "^19.0.0", 13 | "react-dom": "^19.0.0", 14 | "next": "15.1.6" 15 | }, 16 | "exports": { 17 | ".": { 18 | "import": "./src/client/index.ts" 19 | } 20 | }, 21 | "devDependencies": { 22 | "typescript": "^5", 23 | "@types/node": "^20", 24 | "@types/react": "^19", 25 | "@types/react-dom": "^19", 26 | "postcss": "^8", 27 | "tailwindcss": "^3.4.1", 28 | "eslint": "^9", 29 | "eslint-config-next": "15.1.6", 30 | "@eslint/eslintrc": "^3" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /playground/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /playground/public/file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /playground/public/globe.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /playground/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /playground/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /playground/public/window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /playground/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/rag-chat-component/cd9ea021276dc5bf9f5cab9ab8770de858ba9bfd/playground/src/app/favicon.ico -------------------------------------------------------------------------------- /playground/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --background: #ffffff; 7 | --foreground: #171717; 8 | } 9 | 10 | @media (prefers-color-scheme: dark) { 11 | :root { 12 | --background: #0a0a0a; 13 | --foreground: #ededed; 14 | } 15 | } 16 | 17 | body { 18 | color: var(--foreground); 19 | background: var(--background); 20 | font-family: Arial, Helvetica, sans-serif; 21 | } 22 | -------------------------------------------------------------------------------- /playground/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Geist, Geist_Mono } from "next/font/google"; 3 | import "./globals.css"; 4 | 5 | const geistSans = Geist({ 6 | variable: "--font-geist-sans", 7 | subsets: ["latin"], 8 | }); 9 | 10 | const geistMono = Geist_Mono({ 11 | variable: "--font-geist-mono", 12 | subsets: ["latin"], 13 | }); 14 | 15 | export const metadata: Metadata = { 16 | title: "Create Next App", 17 | description: "Generated by create next app", 18 | }; 19 | 20 | export default function RootLayout({ 21 | children, 22 | }: Readonly<{ 23 | children: React.ReactNode; 24 | }>) { 25 | return ( 26 | 27 | 30 | {children} 31 | 32 | 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /playground/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import { ChatComponent } from "@/client/components/chat-component"; 2 | 3 | export default function Home() { 4 | return ( 5 |
6 |

Component Playground

7 |
8 | 9 |
10 |
11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /playground/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | export default { 4 | content: [ 5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}", 8 | '../src/**/*.{js,ts,jsx,tsx,mdx}', 9 | ], 10 | theme: { 11 | extend: { 12 | colors: { 13 | background: "var(--background)", 14 | foreground: "var(--foreground)", 15 | }, 16 | }, 17 | }, 18 | plugins: [], 19 | } satisfies Config; 20 | -------------------------------------------------------------------------------- /playground/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["../src/*"], 23 | "@playground/*": ["./src/*"] 24 | } 25 | }, 26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import("postcss-load-config").Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | autoprefixer: {}, 6 | "postcss-prefix-selector": { 7 | prefix: ".ups-chat", 8 | }, 9 | }, 10 | }; 11 | 12 | export default config; 13 | -------------------------------------------------------------------------------- /public/images/vector-databrowser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/rag-chat-component/cd9ea021276dc5bf9f5cab9ab8770de858ba9bfd/public/images/vector-databrowser.png -------------------------------------------------------------------------------- /public/images/widget-closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/rag-chat-component/cd9ea021276dc5bf9f5cab9ab8770de858ba9bfd/public/images/widget-closed.png -------------------------------------------------------------------------------- /public/images/widget-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upstash/rag-chat-component/cd9ea021276dc5bf9f5cab9ab8770de858ba9bfd/public/images/widget-open.png -------------------------------------------------------------------------------- /src/client/components/chat-component.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { ScrollArea } from "@radix-ui/react-scroll-area"; 4 | 5 | import * as React from "react"; 6 | import { useEffect, useRef, useState } from "react"; 7 | import { serverChat } from "../../server/actions/chat"; 8 | import { deleteHistory, getHistory } from "../../server/actions/history"; 9 | 10 | import type { Message } from "../../server/lib/types"; 11 | import { cn } from "./lib/utils"; 12 | import { Button } from "./ui/button"; 13 | import { ArrowUp, Bot, Loader2, X } from "lucide-react"; 14 | import TextareaAutosize from "react-textarea-autosize"; 15 | import { readStreamableValue } from "ai/rsc"; 16 | 17 | type ChatComponentProps = { 18 | theme?: { 19 | triggerButtonIcon?: React.ReactNode; 20 | triggerButtonColor?: string; 21 | }; 22 | }; 23 | 24 | export const ChatComponent = ({ theme }: ChatComponentProps) => { 25 | const [conversation, setConversation] = useState([]); 26 | const [sessionId, setSessionId] = useState(""); 27 | const [input, setInput] = useState(""); 28 | const [isLoading, setIsLoading] = useState(false); 29 | const [isOpen, setIsOpen] = useState(false); 30 | const [isStreaming, setIsStreaming] = useState(false); 31 | const scrollAreaRef = useRef(null); 32 | const lastMessageRef = useRef(null); 33 | const inputRef = useRef(null); 34 | 35 | const toggleChat = () => { 36 | setIsOpen(!isOpen); 37 | if (!isOpen) { 38 | setTimeout(() => inputRef.current?.focus(), 100); 39 | } 40 | }; 41 | 42 | const scrollToBottom = () => { 43 | if (lastMessageRef.current) { 44 | lastMessageRef.current.scrollIntoView({ behavior: "smooth" }); 45 | } 46 | }; 47 | 48 | useEffect(() => { 49 | let id = localStorage.getItem("chat_session_id"); 50 | if (!id) { 51 | id = "session_" + Math.random().toString(36).substr(2, 9); 52 | localStorage.setItem("chat_session_id", id); 53 | } 54 | setSessionId(id); 55 | 56 | const fetchHistory = async () => { 57 | try { 58 | setIsLoading(true); 59 | const { messages } = await getHistory(id); 60 | if (messages.length > 0) { 61 | setConversation(messages); 62 | } 63 | } catch (error) { 64 | console.error("Error fetching chat history:", error); 65 | } finally { 66 | setIsLoading(false); 67 | } 68 | }; 69 | 70 | fetchHistory(); 71 | }, []); 72 | 73 | useEffect(() => { 74 | scrollToBottom(); 75 | }, [conversation]); 76 | 77 | useEffect(() => { 78 | if (isStreaming) { 79 | const intervalId = setInterval(scrollToBottom, 100); 80 | return () => clearInterval(intervalId); 81 | } 82 | }, [isStreaming]); 83 | 84 | const handleSubmit = async (e: React.FormEvent) => { 85 | e.preventDefault(); 86 | if (!input.trim()) return; 87 | 88 | const userMessage: Message = { 89 | content: input, 90 | role: "user", 91 | id: Date.now().toString(), 92 | }; 93 | 94 | const newConversation = [...conversation, userMessage]; 95 | setConversation(newConversation); 96 | setInput(""); 97 | setIsLoading(true); 98 | 99 | try { 100 | const { output } = await serverChat({ 101 | messages: newConversation, 102 | sessionId, 103 | }); 104 | setIsStreaming(true); 105 | let aiMessage: Message = { 106 | content: "", 107 | role: "assistant", 108 | id: (Date.now() + 1).toString(), 109 | }; 110 | setConversation((prev) => [...prev, aiMessage]); 111 | 112 | let messageReceived = false; 113 | for await (const delta of readStreamableValue(output)) { 114 | if (delta) { 115 | messageReceived = true; 116 | } 117 | aiMessage.content += delta; 118 | setConversation((prev) => 119 | prev.map((msg) => 120 | msg.id === aiMessage.id 121 | ? { ...msg, content: aiMessage.content } 122 | : msg, 123 | ), 124 | ); 125 | } 126 | 127 | if (!messageReceived || !aiMessage.content.trim()) { 128 | setConversation((prev) => [ 129 | ...prev.slice(0, -1), 130 | { 131 | content: "No response received. Please try again.", 132 | role: "error", 133 | id: (Date.now() + 2).toString(), 134 | }, 135 | ]); 136 | } 137 | } catch (error) { 138 | console.error("Error in AI response:", error); 139 | setConversation((prev) => [ 140 | ...prev.slice(0, -1), 141 | { 142 | content: "An error occurred. Please try again.", 143 | role: "error", 144 | id: (Date.now() + 3).toString(), 145 | }, 146 | ]); 147 | } finally { 148 | setIsLoading(false); 149 | setIsStreaming(false); 150 | } 151 | }; 152 | 153 | const handleClearHistory = async () => { 154 | if (!sessionId || isLoading) return; 155 | 156 | setIsLoading(true); 157 | try { 158 | const { success } = await deleteHistory(sessionId); 159 | if (success) { 160 | setConversation([]); 161 | } 162 | } catch (error) { 163 | console.error("Error clearing chat history:", error); 164 | } finally { 165 | setIsLoading(false); 166 | } 167 | }; 168 | 169 | const renderMessage = (message: Message, index: number) => { 170 | const isLastMessage = index === conversation.length - 1; 171 | const showDots = isLastMessage && isStreaming; 172 | const isUser = message.role === "user"; 173 | const isError = message.role === "error"; 174 | 175 | return ( 176 |
181 | {isUser ? ( 182 | // User message 183 |
184 | {message.content} 185 |
186 | ) : isError ? ( 187 |
188 | 189 |
190 | 191 | {message.content} 192 |
193 |
194 | ) : ( 195 | // Assistant message 196 |
197 | 198 |
199 | 200 | {message.content} 201 | {showDots && ( 202 | 203 | ... 204 | 205 | )} 206 |
207 |
208 | )} 209 |
210 | ); 211 | }; 212 | 213 | const hasMessages = conversation.length > 0; 214 | 215 | return ( 216 |
217 | {/* >>> Trigger Button */} 218 | 233 | 234 | {/* >>> Chat Modal */} 235 |
251 | {/* Chat Header */} 252 |
253 |

Chat Assistant

254 | 255 |
256 | {/* clear button */} 257 | 268 | {/* close button */} 269 | 270 | 278 |
279 |
280 | 281 | {/* Chat Body */} 282 | 286 | {/* empty message */} 287 | {!hasMessages && !isLoading && ( 288 |
289 | 290 | Chat with the AI assistant 291 | 292 |
293 | )} 294 | 295 | {/* chat bubbles */} 296 |
297 | {conversation.map(renderMessage)} 298 | {isLoading && !isStreaming && ( 299 |
300 | 301 |
302 | )} 303 |
304 |
305 | 306 | {/* Chat Form */} 307 |
308 | setInput(e.target.value)} 319 | onKeyDown={(e) => { 320 | if (e.key === "Enter" && !e.shiftKey) { 321 | e.preventDefault(); 322 | handleSubmit(e); 323 | } 324 | }} 325 | placeholder="Ask a question..." 326 | disabled={isLoading || isStreaming} 327 | ref={inputRef} 328 | /> 329 | 330 | 345 | 346 |
347 |
348 | ); 349 | }; 350 | -------------------------------------------------------------------------------- /src/client/components/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } -------------------------------------------------------------------------------- /src/client/components/styles.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /src/client/components/ui/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Slot } from "@radix-ui/react-slot"; 3 | import { cva, type VariantProps } from "class-variance-authority"; 4 | import { cn } from "../lib/utils"; 5 | 6 | const buttonVariants = cva( 7 | "inline-flex items-center justify-center whitespace-nowrap rounded-md disabled:pointer-events-none disabled:opacity-50", 8 | { 9 | variants: { 10 | variant: { 11 | default: "bg-black text-white", 12 | secondary: "bg-black text-white", 13 | ghost: "", 14 | }, 15 | size: { 16 | default: "h-10 px-4 py-2", 17 | sm: "h-8 rounded-md px-3", 18 | icon: "size-8 rounded-full p-0", 19 | }, 20 | }, 21 | defaultVariants: { 22 | variant: "default", 23 | size: "default", 24 | }, 25 | }, 26 | ); 27 | 28 | export interface ButtonProps 29 | extends React.ButtonHTMLAttributes, 30 | VariantProps { 31 | asChild?: boolean; 32 | } 33 | 34 | const Button = React.forwardRef( 35 | ({ className, variant, size, asChild = false, ...props }, ref) => { 36 | const Comp = asChild ? Slot : "button"; 37 | return ( 38 | 43 | ); 44 | }, 45 | ); 46 | Button.displayName = "Button"; 47 | 48 | export { Button, buttonVariants }; 49 | -------------------------------------------------------------------------------- /src/client/components/ui/scroll-area.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"; 5 | 6 | import { cn } from "../lib/utils"; 7 | 8 | const ScrollArea = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, children, ...props }, ref) => ( 12 | 17 | 18 | {children} 19 | 20 | 21 | 22 | 23 | )); 24 | ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName; 25 | 26 | const ScrollBar = React.forwardRef< 27 | React.ElementRef, 28 | React.ComponentPropsWithoutRef 29 | >(({ className, orientation = "vertical", ...props }, ref) => ( 30 | 43 | 44 | 45 | )); 46 | ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName; 47 | 48 | export { ScrollArea, ScrollBar }; 49 | -------------------------------------------------------------------------------- /src/client/index.ts: -------------------------------------------------------------------------------- 1 | export { ChatComponent } from "./components/chat-component"; 2 | -------------------------------------------------------------------------------- /src/server/actions/chat.ts: -------------------------------------------------------------------------------- 1 | "use server"; 2 | 3 | import { Index } from "@upstash/vector" 4 | import { createOpenAI } from "@ai-sdk/openai" 5 | import { streamText } from "ai" 6 | import { createStreamableValue, type StreamableValue } from "ai/rsc"; 7 | import { DEFAULT_PROMPT } from "../constants"; 8 | import type { Message } from "../lib/types"; 9 | import { getHistoryClient } from "../lib/history/get-client"; 10 | 11 | type StreamMessage = { 12 | role: 'user' | 'assistant'; 13 | content: string; 14 | } 15 | 16 | const vectorIndex = new Index() 17 | 18 | const together = createOpenAI({ 19 | apiKey: process.env.TOGETHER_API_KEY ?? "", 20 | baseURL: "https://api.together.xyz/v1", 21 | 22 | }) 23 | 24 | const searchSimilarDocs = async (data: string, topK: number) => { 25 | const results = await vectorIndex.query({ 26 | data, 27 | topK: topK ? topK : 5, 28 | includeMetadata: true, 29 | includeData: true, 30 | }); 31 | 32 | return results 33 | } 34 | 35 | const history = getHistoryClient() 36 | 37 | export const serverChat = async ({ 38 | messages, 39 | sessionId, 40 | }: { 41 | messages: Message[]; 42 | sessionId: string; 43 | }): Promise<{ output: StreamableValue }> => { 44 | const userMessage = messages[messages.length - 1] 45 | 46 | await history.addMessage({ 47 | message: userMessage, 48 | sessionId 49 | }) 50 | 51 | const serverMessages = messages 52 | .filter(msg => msg.role !== 'error') 53 | .map(msg => ({ 54 | role: msg.role, 55 | content: msg.content 56 | })) as StreamMessage[]; 57 | 58 | const similarDocs = await searchSimilarDocs(userMessage.content, 5) 59 | 60 | const context = similarDocs.map(doc => doc.data).join("\n") 61 | 62 | const chatMessages = messages.map(message => message.content).join("\n") 63 | 64 | const system = DEFAULT_PROMPT({ context, question: userMessage.content, chatMessages }) 65 | 66 | const stream = createStreamableValue(""); 67 | 68 | (async () => { 69 | const { textStream } = streamText({ 70 | model: together(process.env.TOGETHER_MODEL ?? "deepseek-ai/DeepSeek-V3"), 71 | system, 72 | messages: serverMessages, 73 | 74 | async onFinish({ text }) { 75 | await history.addMessage({ 76 | message: { 77 | role: "assistant", 78 | content: text, 79 | id: Date.now().toString(), 80 | }, 81 | sessionId 82 | }) 83 | }, 84 | 85 | }) 86 | 87 | for await (const delta of textStream) { 88 | stream.update(delta); 89 | } 90 | 91 | stream.done(); 92 | })(); 93 | 94 | return { output: stream.value } 95 | }; 96 | -------------------------------------------------------------------------------- /src/server/actions/history.ts: -------------------------------------------------------------------------------- 1 | 'use server' 2 | 3 | import { getHistoryClient } from "../lib/history/get-client"; 4 | import type { Message } from "../lib/types"; 5 | 6 | const history = getHistoryClient(); 7 | 8 | export async function getHistory(sessionId: string): Promise<{ messages: Message[] }> { 9 | try { 10 | const messages = await history.getMessages({ sessionId }); 11 | return { messages }; 12 | } catch (error) { 13 | console.error("Failed to fetch chat history:", error); 14 | return { messages: [] }; 15 | } 16 | } 17 | 18 | export async function deleteHistory(sessionId: string): Promise<{ success: boolean }> { 19 | try { 20 | await history.deleteMessages({ sessionId }); 21 | return { success: true }; 22 | } catch (error) { 23 | console.error("Failed to delete chat history:", error); 24 | return { success: false }; 25 | } 26 | } -------------------------------------------------------------------------------- /src/server/constants.ts: -------------------------------------------------------------------------------- 1 | type PromptParameters = { 2 | chatMessages?: string; 3 | question: string; 4 | context: string; 5 | }; 6 | 7 | type Prompt = ({ question, chatMessages, context }: PromptParameters) => string; 8 | 9 | export const DEFAULT_PROMPT: Prompt = ({ context, question, chatMessages }) => 10 | `You are a concise AI assistant helping users on a website. Provide brief, clear answers in 1-2 sentences when possible. 11 | 12 | Context and chat history are provided to help you answer questions accurately. Only use information from these sources. 13 | 14 | ${context ? `Context: ${context}\n` : ''}${chatMessages ? `Previous messages: ${chatMessages}\n` : ''} 15 | Q: ${question} 16 | A:`; 17 | 18 | export const DEFAULT_CHAT_SESSION_ID = "upstash-rag-chat-session"; 19 | 20 | export const DEFAULT_HISTORY_LENGTH = 5; -------------------------------------------------------------------------------- /src/server/index.ts: -------------------------------------------------------------------------------- 1 | export { serverChat } from "./actions/chat"; 2 | -------------------------------------------------------------------------------- /src/server/lib/history/get-client.ts: -------------------------------------------------------------------------------- 1 | import type { BaseMessageHistory } from "../types"; 2 | import { RedisHistory } from "./redis"; 3 | import { InMemoryHistory } from "./in-memory"; 4 | 5 | export const getHistoryClient = (): BaseMessageHistory => { 6 | const redisUrl = process.env.UPSTASH_REDIS_REST_URL; 7 | const redisToken = process.env.UPSTASH_REDIS_REST_TOKEN; 8 | 9 | if (redisUrl && redisToken) { 10 | return new RedisHistory({ 11 | config: { 12 | url: redisUrl, 13 | token: redisToken, 14 | } 15 | }); 16 | } 17 | 18 | return new InMemoryHistory(); 19 | } -------------------------------------------------------------------------------- /src/server/lib/history/in-memory.ts: -------------------------------------------------------------------------------- 1 | import type { Message, BaseMessageHistory } from "../types"; 2 | import { DEFAULT_CHAT_SESSION_ID, DEFAULT_HISTORY_LENGTH } from "../../constants"; 3 | 4 | declare global { 5 | var store: Record; 6 | } 7 | export class InMemoryHistory implements BaseMessageHistory { 8 | constructor() { 9 | if (!global.store) global.store = {}; 10 | } 11 | 12 | async addMessage(params: { 13 | message: Message; 14 | sessionId: string; 15 | sessionTTL?: number; 16 | }): Promise { 17 | const { message, sessionId = DEFAULT_CHAT_SESSION_ID } = params; 18 | if (!global.store[sessionId]) { 19 | global.store[sessionId] = { messages: [] }; 20 | } 21 | 22 | const oldMessages = global.store[sessionId].messages || []; 23 | const newMessages = [message, ...oldMessages]; 24 | global.store[sessionId].messages = newMessages; 25 | } 26 | 27 | async deleteMessages({ sessionId }: { sessionId: string }): Promise { 28 | if (!global.store[sessionId]) { 29 | return; 30 | } 31 | global.store[sessionId].messages = []; 32 | } 33 | 34 | async getMessages({ 35 | sessionId = DEFAULT_CHAT_SESSION_ID, 36 | amount = DEFAULT_HISTORY_LENGTH, 37 | startIndex = 0, 38 | }): Promise { 39 | if (!global.store[sessionId]) { 40 | global.store[sessionId] = { messages: [] }; 41 | } 42 | 43 | const messages = global.store[sessionId]?.messages ?? []; 44 | const slicedMessages = messages.slice(startIndex, startIndex + amount); 45 | return slicedMessages.reverse(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/server/lib/history/redis.ts: -------------------------------------------------------------------------------- 1 | import { Redis, type RedisConfigNodejs } from "@upstash/redis"; 2 | import { DEFAULT_CHAT_SESSION_ID, DEFAULT_HISTORY_LENGTH } from "../../constants"; 3 | import type { Message, BaseMessageHistory } from "../types"; 4 | 5 | export type RedisHistoryConfig = { 6 | config?: RedisConfigNodejs; 7 | client?: Redis; 8 | }; 9 | 10 | export class RedisHistory implements BaseMessageHistory { 11 | public client: Redis; 12 | 13 | constructor(config: RedisHistoryConfig) { 14 | const { config: redisConfig, client } = config; 15 | 16 | if (client) { 17 | this.client = client; 18 | } else if (redisConfig) { 19 | this.client = new Redis(redisConfig); 20 | } else { 21 | throw new Error( 22 | "Redis message stores require either a config object or a pre-configured client." 23 | ); 24 | } 25 | } 26 | 27 | async addMessage(params: { 28 | message: Message; 29 | sessionId: string; 30 | sessionTTL?: number; 31 | }): Promise { 32 | const { message, sessionId = DEFAULT_CHAT_SESSION_ID, sessionTTL } = params; 33 | await this.client.lpush(sessionId, JSON.stringify(message)); 34 | if (sessionTTL) { 35 | await this.client.expire(sessionId, sessionTTL); 36 | } 37 | } 38 | 39 | async deleteMessages({ sessionId }: { sessionId: string }): Promise { 40 | await this.client.del(sessionId); 41 | } 42 | 43 | async getMessages({ 44 | sessionId = DEFAULT_CHAT_SESSION_ID, 45 | amount = DEFAULT_HISTORY_LENGTH, 46 | startIndex = 0, 47 | }): Promise { 48 | const endIndex = startIndex + amount - 1; 49 | const messages = await this.client.lrange( 50 | sessionId, 51 | startIndex, 52 | endIndex 53 | ); 54 | 55 | return messages.reverse(); 56 | } 57 | } -------------------------------------------------------------------------------- /src/server/lib/types.ts: -------------------------------------------------------------------------------- 1 | export type Message = { 2 | role: "user" | "assistant" | "error" 3 | content: string; 4 | id: string 5 | } 6 | 7 | export interface BaseMessageHistory { 8 | addMessage(params: { 9 | message: Message; 10 | sessionId: string; 11 | sessionTTL?: number; 12 | }): Promise; 13 | 14 | deleteMessages(params: { 15 | sessionId: string 16 | }): Promise; 17 | 18 | getMessages(params: { 19 | sessionId: string; 20 | amount?: number; 21 | startIndex?: number; 22 | }): Promise; 23 | } -------------------------------------------------------------------------------- /tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config = { 4 | content: ["./src/**/*.{ts,tsx}"], 5 | theme: { 6 | screens: { 7 | 'sm': '640px', 8 | 'md': '768px', 9 | 'lg': '1024px', 10 | 'xl': '1280px', 11 | '2xl': '1536px', 12 | }, 13 | extend: { 14 | animation: { 15 | "accordion-down": "accordion-down 0.2s ease-out", 16 | "accordion-up": "accordion-up 0.2s ease-out", 17 | }, 18 | }, 19 | }, 20 | plugins: [require("tailwindcss-animate")], 21 | } satisfies Config; 22 | 23 | export default config; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["ESNext", "DOM"], 4 | "declarationDir": "dist", 5 | "declaration": true, 6 | "target": "ESNext", 7 | "module": "ES2022", 8 | "moduleDetection": "force", 9 | "jsx": "react-jsx", 10 | "allowJs": true, 11 | "outDir": "./dist", 12 | "types": ["react/experimental", "node"], 13 | "jsxImportSource": "react", 14 | "allowSyntheticDefaultImports": true, 15 | "resolveJsonModule": true, 16 | "skipDefaultLibCheck": true, 17 | "moduleResolution": "Bundler", 18 | "allowImportingTsExtensions": true, 19 | "verbatimModuleSyntax": true, 20 | "noEmit": true, 21 | "strict": true, 22 | "skipLibCheck": true, 23 | "noFallthroughCasesInSwitch": true, 24 | "noUnusedLocals": false, 25 | "noUnusedParameters": false, 26 | "noPropertyAccessFromIndexSignature": false 27 | }, 28 | "include": ["src/**/*", "./package.json"], 29 | "exclude": ["node_modules"] 30 | } 31 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | import { fixExtensionsPlugin } from "esbuild-fix-imports-plugin"; 3 | 4 | export default defineConfig([ 5 | { 6 | entry: ["src/client"], 7 | outDir: "dist/client", 8 | external: ["react", "next"], 9 | 10 | // 👇 important: cjs doesn't work well 11 | format: "esm", 12 | splitting: false, 13 | sourcemap: false, 14 | clean: true, 15 | dts: true, 16 | 17 | // 👇 important: do not bundle 18 | bundle: false, 19 | minify: false, 20 | treeshake: false, 21 | injectStyle: true, 22 | esbuildPlugins: [fixExtensionsPlugin()], 23 | }, 24 | { 25 | entry: ["src/server"], 26 | outDir: "dist/server", 27 | external: ["react", "next"], 28 | 29 | // 👇 important: cjs doesn't work well 30 | format: "esm", 31 | splitting: false, 32 | sourcemap: false, 33 | clean: true, 34 | dts: true, 35 | 36 | // 👇 important: do not bundle 37 | bundle: false, 38 | minify: false, 39 | esbuildPlugins: [fixExtensionsPlugin()], 40 | }, 41 | ]); 42 | --------------------------------------------------------------------------------