├── .env.example ├── .gitignore ├── .prettierignore ├── LICENSE ├── README.md ├── codeguide-backdrop.svg ├── package-lock.json ├── package.json ├── prettier.config.mjs ├── report.md ├── src ├── ai │ ├── providers.ts │ ├── text-splitter.test.ts │ └── text-splitter.ts ├── api │ ├── middleware │ │ └── auth.ts │ ├── server.ts │ └── swagger.ts ├── deep-research.ts ├── feedback.ts ├── prompt.ts └── run.ts └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | # Server Configuration 2 | PORT=3000 3 | 4 | # Authentication 5 | API_KEY=your-api-key-here 6 | CLERK_PUBLISHABLE_KEY=YOUR_PUBLISHABLE_KEY 7 | CLERK_SECRET_KEY=YOUR_SECRET_KEY 8 | 9 | # External Services 10 | FIRECRAWL_KEY=your-firecrawl-key 11 | FIRECRAWL_BASE_URL=your-firecrawl-url 12 | 13 | # OpenAI Configuration 14 | OPENAI_API_KEY=your-openai-key -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # Output files 4 | output.md 5 | 6 | # Dependencies 7 | node_modules 8 | .pnp 9 | .pnp.js 10 | 11 | # Local env files 12 | .env 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | # Testing 19 | coverage 20 | 21 | # Turbo 22 | .turbo 23 | 24 | # Vercel 25 | .vercel 26 | 27 | # Build Outputs 28 | .next/ 29 | out/ 30 | build 31 | dist 32 | 33 | 34 | # Debug 35 | npm-debug.log* 36 | yarn-debug.log* 37 | yarn-error.log* 38 | 39 | # Misc 40 | .DS_Store 41 | *.pem 42 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.hbs -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 David Zhang 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodeGuide Deep Research API 2 | 3 | [![CodeGuide](codeguide-backdrop.svg)](https://codeguide.dev) 4 | 5 | > This is a fork of [Open Deep Research](https://github.com/dzhng/deep-research) by [@dzhng](https://x.com/dzhng), enhanced with REST API implementation and integrated into the CodeGuide platform. 6 | 7 | An AI-powered research assistant that performs iterative, deep research on any topic by combining search engines, web scraping, and large language models. This enhanced version provides a REST API interface and is integrated into the [CodeGuide platform](https://app.codeguide.dev). 8 | 9 | The core functionality remains true to the original project's goal of providing a simple implementation of a deep research agent - one that can refine its research direction overtime and deep dive into a topic. 10 | 11 | ## Access 12 | Screenshot 2025-02-07 at 22 37 01 13 | 14 | This service is available to all CodeGuide members at [app.codeguide.dev](https://app.codeguide.dev). 15 | You'll have access to the following features: 16 | - User-friendly interface for conducting research 17 | - Real-time results and generated reports 18 | - Integrations with other CodeGuide features (coming soon) 19 | 20 | 21 | 22 | ## How It Works 23 | ```mermaid 24 | flowchart TB 25 | subgraph Input 26 | Q[User Query] 27 | B[Breadth Parameter] 28 | D[Depth Parameter] 29 | end 30 | 31 | DR[Deep Research] --> 32 | SQ[SERP Queries] --> 33 | PR[Process Results] 34 | 35 | subgraph Results[Results] 36 | direction TB 37 | NL((Learnings)) 38 | ND((Directions)) 39 | end 40 | 41 | PR --> NL 42 | PR --> ND 43 | 44 | DP{depth > 0?} 45 | 46 | RD["Next Direction: 47 | - Prior Goals 48 | - New Questions 49 | - Learnings"] 50 | 51 | MR[Markdown Report] 52 | 53 | %% Main Flow 54 | Q & B & D --> DR 55 | 56 | %% Results to Decision 57 | NL & ND --> DP 58 | 59 | %% Circular Flow 60 | DP -->|Yes| RD 61 | RD -->|New Context| DR 62 | 63 | %% Final Output 64 | DP -->|No| MR 65 | 66 | %% Styling 67 | classDef input fill:#7bed9f,stroke:#2ed573,color:black 68 | classDef process fill:#70a1ff,stroke:#1e90ff,color:black 69 | classDef recursive fill:#ffa502,stroke:#ff7f50,color:black 70 | classDef output fill:#ff4757,stroke:#ff6b81,color:black 71 | classDef results fill:#a8e6cf,stroke:#3b7a57,color:black 72 | 73 | class Q,B,D input 74 | class DR,SQ,PR process 75 | class DP,RD recursive 76 | class MR output 77 | class NL,ND results 78 | ``` 79 | 80 | ## Features 81 | 82 | - **REST API Implementation**: Full REST API support with comprehensive documentation 83 | - **CodeGuide Integration**: Seamlessly integrated with the CodeGuide platform 84 | - **API Documentation**: Interactive Swagger/OpenAPI documentation 85 | - **Iterative Research**: Performs deep research by iteratively generating search queries, processing results, and diving deeper based on findings 86 | - **Intelligent Query Generation**: Uses LLMs to generate targeted search queries based on research goals and previous findings 87 | - **Depth & Breadth Control**: Configurable parameters to control how wide (breadth) and deep (depth) the research goes 88 | - **Smart Follow-up**: Generates follow-up questions to better understand research needs 89 | - **Comprehensive Reports**: Produces detailed markdown reports with findings and sources 90 | - **Concurrent Processing**: Handles multiple searches and result processing in parallel for efficiency 91 | 92 | ## API Usage 93 | 94 | You can access the API locally or by self-hosting it. 95 | 96 | ### Authentication 97 | 98 | All API requests require authentication that will be defined in the `.env` file. 99 | 100 | ```bash 101 | # .env 102 | API_KEY="your_development_api_key" 103 | ``` 104 | 105 | ### Research Flow 106 | 107 | The research process consists of three main steps: 108 | 109 | 1. **Generate Clarifying Questions** 110 | ```bash 111 | # Step 1: Generate questions to better understand the research direction 112 | curl -X POST http://localhost:3000/api/research/questions \ 113 | -H "x-api-key: API_KEY" \ 114 | -H "Content-Type: application/json" \ 115 | -d '{ 116 | "query": "Your research query", 117 | "numQuestions": 3 118 | }' 119 | ``` 120 | 121 | 2. **Perform Deep Research** 122 | ```bash 123 | # Step 2: Conduct the research with your answers to the clarifying questions 124 | curl -X POST http://localhost:3000/api/research \ 125 | -H "x-api-key: API_KEY" \ 126 | -H "Content-Type: application/json" \ 127 | -d '{ 128 | "query": "Your research query", 129 | "breadth": 6, 130 | "depth": 3, 131 | "questionAnswers": [ 132 | { 133 | "question": "Question from step 1", 134 | "answer": "Your answer to the question" 135 | } 136 | ] 137 | }' 138 | ``` 139 | 140 | 3. **Generate Final Report** 141 | ```bash 142 | # Step 3: Generate a comprehensive report using the research results 143 | curl -X POST http://localhost:3000/api/report \ 144 | -H "x-api-key: API_KEY" \ 145 | -H "Content-Type: application/json" \ 146 | -d '{ 147 | "prompt": "Original research query", 148 | "learnings": ["Learning 1", "Learning 2"], # From research response 149 | "visitedUrls": ["url1", "url2"] # From research response 150 | }' 151 | ``` 152 | 153 | The flow allows for an iterative and thorough research process: 154 | 1. First, generate clarifying questions to better understand the research needs 155 | 2. Use these questions and your answers to guide the deep research process 156 | 3. Finally, generate a comprehensive report based on the research findings 157 | 158 | ## Local Development Setup 159 | 160 | 1. Clone the repository 161 | 2. Install dependencies: 162 | 163 | ```bash 164 | npm install 165 | ``` 166 | 167 | 3. Set up environment variables in a `.env` file: 168 | 169 | ```bash 170 | FIRECRAWL_KEY="your_firecrawl_key" 171 | # If you want to use your self-hosted Firecrawl, add the following below: 172 | # FIRECRAWL_BASE_URL="http://localhost:3002" 173 | 174 | OPENAI_KEY="your_openai_key" 175 | 176 | # API Configuration 177 | PORT=3000 178 | API_KEY="your_development_api_key" 179 | ``` 180 | 181 | ## Running Locally 182 | 183 | Start the API server: 184 | 185 | ```bash 186 | npm run dev 187 | ``` 188 | 189 | The API will be available at `http://localhost:3000` with documentation at `http://localhost:3000/api-docs`. 190 | 191 | ## License 192 | 193 | MIT License - feel free to use and modify as needed. 194 | 195 | ## Acknowledgments 196 | 197 | This project is a fork of [Open Deep Research](https://github.com/dzhng/deep-research) by [@dzhng](https://x.com/dzhng). We've extended it with REST API capabilities and integrated it into the CodeGuide platform while maintaining the core functionality of the original project. 198 | -------------------------------------------------------------------------------- /codeguide-backdrop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "open-deep-research-api", 3 | "version": "0.0.1", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "open-deep-research-api", 9 | "version": "0.0.1", 10 | "license": "ISC", 11 | "dependencies": { 12 | "@ai-sdk/openai": "^1.1.9", 13 | "@clerk/express": "^1.3.46", 14 | "@mendable/firecrawl-js": "^1.16.0", 15 | "@types/cors": "^2.8.17", 16 | "@types/express": "^5.0.0", 17 | "@types/lodash": "^4.17.15", 18 | "@types/swagger-jsdoc": "^6.0.4", 19 | "@types/swagger-ui-express": "^4.1.7", 20 | "ai": "^4.1.17", 21 | "cors": "^2.8.5", 22 | "dotenv": "^16.4.7", 23 | "express": "^4.21.2", 24 | "js-tiktoken": "^1.0.17", 25 | "lodash-es": "^4.17.21", 26 | "p-limit": "^6.2.0", 27 | "swagger-jsdoc": "^6.2.8", 28 | "swagger-ui-express": "^5.0.1", 29 | "zod": "^3.24.1" 30 | }, 31 | "devDependencies": { 32 | "@ianvs/prettier-plugin-sort-imports": "^4.4.1", 33 | "@types/lodash-es": "^4.17.12", 34 | "@types/node": "^22.13.0", 35 | "prettier": "^3.4.2", 36 | "tslib": "^2.8.1", 37 | "tsx": "^4.19.2", 38 | "typescript": "^5.7.3" 39 | }, 40 | "engines": { 41 | "node": "22.x" 42 | } 43 | }, 44 | "node_modules/@ai-sdk/openai": { 45 | "version": "1.1.9", 46 | "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-1.1.9.tgz", 47 | "integrity": "sha512-t/CpC4TLipdbgBJTMX/otzzqzCMBSPQwUOkYPGbT/jyuC86F+YO9o+LS0Ty2pGUE1kyT+B3WmJ318B16ZCg4hw==", 48 | "license": "Apache-2.0", 49 | "dependencies": { 50 | "@ai-sdk/provider": "1.0.7", 51 | "@ai-sdk/provider-utils": "2.1.6" 52 | }, 53 | "engines": { 54 | "node": ">=18" 55 | }, 56 | "peerDependencies": { 57 | "zod": "^3.0.0" 58 | } 59 | }, 60 | "node_modules/@ai-sdk/provider": { 61 | "version": "1.0.7", 62 | "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.0.7.tgz", 63 | "integrity": "sha512-q1PJEZ0qD9rVR+8JFEd01/QM++csMT5UVwYXSN2u54BrVw/D8TZLTeg2FEfKK00DgAx0UtWd8XOhhwITP9BT5g==", 64 | "license": "Apache-2.0", 65 | "dependencies": { 66 | "json-schema": "^0.4.0" 67 | }, 68 | "engines": { 69 | "node": ">=18" 70 | } 71 | }, 72 | "node_modules/@ai-sdk/provider-utils": { 73 | "version": "2.1.6", 74 | "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.1.6.tgz", 75 | "integrity": "sha512-Pfyaj0QZS22qyVn5Iz7IXcJ8nKIKlu2MeSAdKJzTwkAks7zdLaKVB+396Rqcp1bfQnxl7vaduQVMQiXUrgK8Gw==", 76 | "license": "Apache-2.0", 77 | "dependencies": { 78 | "@ai-sdk/provider": "1.0.7", 79 | "eventsource-parser": "^3.0.0", 80 | "nanoid": "^3.3.8", 81 | "secure-json-parse": "^2.7.0" 82 | }, 83 | "engines": { 84 | "node": ">=18" 85 | }, 86 | "peerDependencies": { 87 | "zod": "^3.0.0" 88 | }, 89 | "peerDependenciesMeta": { 90 | "zod": { 91 | "optional": true 92 | } 93 | } 94 | }, 95 | "node_modules/@ai-sdk/react": { 96 | "version": "1.1.8", 97 | "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-1.1.8.tgz", 98 | "integrity": "sha512-buHm7hP21xEOksnRQtJX9fKbi7cAUwanEBa5niddTDibCDKd+kIXP2vaJGy8+heB3rff+XSW3BWlA8pscK+n1g==", 99 | "license": "Apache-2.0", 100 | "dependencies": { 101 | "@ai-sdk/provider-utils": "2.1.6", 102 | "@ai-sdk/ui-utils": "1.1.8", 103 | "swr": "^2.2.5", 104 | "throttleit": "2.1.0" 105 | }, 106 | "engines": { 107 | "node": ">=18" 108 | }, 109 | "peerDependencies": { 110 | "react": "^18 || ^19 || ^19.0.0-rc", 111 | "zod": "^3.0.0" 112 | }, 113 | "peerDependenciesMeta": { 114 | "react": { 115 | "optional": true 116 | }, 117 | "zod": { 118 | "optional": true 119 | } 120 | } 121 | }, 122 | "node_modules/@ai-sdk/ui-utils": { 123 | "version": "1.1.8", 124 | "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-1.1.8.tgz", 125 | "integrity": "sha512-nbok53K1EalO2sZjBLFB33cqs+8SxiL6pe7ekZ7+5f2MJTwdvpShl6d9U4O8fO3DnZ9pYLzaVC0XNMxnJt030Q==", 126 | "license": "Apache-2.0", 127 | "dependencies": { 128 | "@ai-sdk/provider": "1.0.7", 129 | "@ai-sdk/provider-utils": "2.1.6", 130 | "zod-to-json-schema": "^3.24.1" 131 | }, 132 | "engines": { 133 | "node": ">=18" 134 | }, 135 | "peerDependencies": { 136 | "zod": "^3.0.0" 137 | }, 138 | "peerDependenciesMeta": { 139 | "zod": { 140 | "optional": true 141 | } 142 | } 143 | }, 144 | "node_modules/@apidevtools/json-schema-ref-parser": { 145 | "version": "9.1.2", 146 | "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", 147 | "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", 148 | "dependencies": { 149 | "@jsdevtools/ono": "^7.1.3", 150 | "@types/json-schema": "^7.0.6", 151 | "call-me-maybe": "^1.0.1", 152 | "js-yaml": "^4.1.0" 153 | } 154 | }, 155 | "node_modules/@apidevtools/openapi-schemas": { 156 | "version": "2.1.0", 157 | "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", 158 | "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", 159 | "engines": { 160 | "node": ">=10" 161 | } 162 | }, 163 | "node_modules/@apidevtools/swagger-methods": { 164 | "version": "3.0.2", 165 | "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", 166 | "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==" 167 | }, 168 | "node_modules/@apidevtools/swagger-parser": { 169 | "version": "10.0.3", 170 | "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", 171 | "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", 172 | "dependencies": { 173 | "@apidevtools/json-schema-ref-parser": "^9.0.6", 174 | "@apidevtools/openapi-schemas": "^2.0.4", 175 | "@apidevtools/swagger-methods": "^3.0.2", 176 | "@jsdevtools/ono": "^7.1.3", 177 | "call-me-maybe": "^1.0.1", 178 | "z-schema": "^5.0.1" 179 | }, 180 | "peerDependencies": { 181 | "openapi-types": ">=7" 182 | } 183 | }, 184 | "node_modules/@babel/code-frame": { 185 | "version": "7.26.2", 186 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", 187 | "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", 188 | "dev": true, 189 | "license": "MIT", 190 | "dependencies": { 191 | "@babel/helper-validator-identifier": "^7.25.9", 192 | "js-tokens": "^4.0.0", 193 | "picocolors": "^1.0.0" 194 | }, 195 | "engines": { 196 | "node": ">=6.9.0" 197 | } 198 | }, 199 | "node_modules/@babel/generator": { 200 | "version": "7.26.5", 201 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", 202 | "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", 203 | "dev": true, 204 | "license": "MIT", 205 | "dependencies": { 206 | "@babel/parser": "^7.26.5", 207 | "@babel/types": "^7.26.5", 208 | "@jridgewell/gen-mapping": "^0.3.5", 209 | "@jridgewell/trace-mapping": "^0.3.25", 210 | "jsesc": "^3.0.2" 211 | }, 212 | "engines": { 213 | "node": ">=6.9.0" 214 | } 215 | }, 216 | "node_modules/@babel/helper-string-parser": { 217 | "version": "7.25.9", 218 | "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", 219 | "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", 220 | "dev": true, 221 | "license": "MIT", 222 | "engines": { 223 | "node": ">=6.9.0" 224 | } 225 | }, 226 | "node_modules/@babel/helper-validator-identifier": { 227 | "version": "7.25.9", 228 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", 229 | "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", 230 | "dev": true, 231 | "license": "MIT", 232 | "engines": { 233 | "node": ">=6.9.0" 234 | } 235 | }, 236 | "node_modules/@babel/parser": { 237 | "version": "7.26.7", 238 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", 239 | "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==", 240 | "dev": true, 241 | "license": "MIT", 242 | "dependencies": { 243 | "@babel/types": "^7.26.7" 244 | }, 245 | "bin": { 246 | "parser": "bin/babel-parser.js" 247 | }, 248 | "engines": { 249 | "node": ">=6.0.0" 250 | } 251 | }, 252 | "node_modules/@babel/template": { 253 | "version": "7.25.9", 254 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", 255 | "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", 256 | "dev": true, 257 | "license": "MIT", 258 | "dependencies": { 259 | "@babel/code-frame": "^7.25.9", 260 | "@babel/parser": "^7.25.9", 261 | "@babel/types": "^7.25.9" 262 | }, 263 | "engines": { 264 | "node": ">=6.9.0" 265 | } 266 | }, 267 | "node_modules/@babel/traverse": { 268 | "version": "7.26.7", 269 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz", 270 | "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==", 271 | "dev": true, 272 | "license": "MIT", 273 | "dependencies": { 274 | "@babel/code-frame": "^7.26.2", 275 | "@babel/generator": "^7.26.5", 276 | "@babel/parser": "^7.26.7", 277 | "@babel/template": "^7.25.9", 278 | "@babel/types": "^7.26.7", 279 | "debug": "^4.3.1", 280 | "globals": "^11.1.0" 281 | }, 282 | "engines": { 283 | "node": ">=6.9.0" 284 | } 285 | }, 286 | "node_modules/@babel/types": { 287 | "version": "7.26.7", 288 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz", 289 | "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==", 290 | "dev": true, 291 | "license": "MIT", 292 | "dependencies": { 293 | "@babel/helper-string-parser": "^7.25.9", 294 | "@babel/helper-validator-identifier": "^7.25.9" 295 | }, 296 | "engines": { 297 | "node": ">=6.9.0" 298 | } 299 | }, 300 | "node_modules/@clerk/backend": { 301 | "version": "1.23.11", 302 | "resolved": "https://registry.npmjs.org/@clerk/backend/-/backend-1.23.11.tgz", 303 | "integrity": "sha512-N5CYCnVbSVXUkQg9oAAAf9r/kfPmBGxMqjzslDC9Tl3rkXFTkWjkBNnToB6We2ySdrmqiQGR/+/c4mS9XRbaOQ==", 304 | "dependencies": { 305 | "@clerk/shared": "^2.20.18", 306 | "@clerk/types": "^4.45.0", 307 | "cookie": "1.0.2", 308 | "snakecase-keys": "8.0.1", 309 | "tslib": "2.4.1" 310 | }, 311 | "engines": { 312 | "node": ">=18.17.0" 313 | } 314 | }, 315 | "node_modules/@clerk/backend/node_modules/cookie": { 316 | "version": "1.0.2", 317 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", 318 | "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", 319 | "engines": { 320 | "node": ">=18" 321 | } 322 | }, 323 | "node_modules/@clerk/backend/node_modules/tslib": { 324 | "version": "2.4.1", 325 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", 326 | "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" 327 | }, 328 | "node_modules/@clerk/express": { 329 | "version": "1.3.46", 330 | "resolved": "https://registry.npmjs.org/@clerk/express/-/express-1.3.46.tgz", 331 | "integrity": "sha512-mgwv4Ym4MX0jbuporPJvfgmDZRK5E9l8ExRFMx0rpX9JMaUyvHLsCgMIk7gFBJx1GdsiiD4wWZYhIoemEN2gdg==", 332 | "dependencies": { 333 | "@clerk/backend": "^1.23.11", 334 | "@clerk/shared": "^2.20.18", 335 | "@clerk/types": "^4.45.0", 336 | "tslib": "2.4.1" 337 | }, 338 | "engines": { 339 | "node": ">=18.17.0" 340 | }, 341 | "peerDependencies": { 342 | "express": "^4.17.0 || ^5.0.0" 343 | } 344 | }, 345 | "node_modules/@clerk/express/node_modules/tslib": { 346 | "version": "2.4.1", 347 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", 348 | "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" 349 | }, 350 | "node_modules/@clerk/shared": { 351 | "version": "2.20.18", 352 | "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-2.20.18.tgz", 353 | "integrity": "sha512-vSQLZSRFr62+YeE1KE/Xu/eWCrwYJRNA2KRyQYmb2VPleFNmOjtTNlO4xkMZ0eN6BLKxrBo9b0NVwu3L28FhKg==", 354 | "hasInstallScript": true, 355 | "dependencies": { 356 | "@clerk/types": "^4.45.0", 357 | "dequal": "2.0.3", 358 | "glob-to-regexp": "0.4.1", 359 | "js-cookie": "3.0.5", 360 | "std-env": "^3.7.0", 361 | "swr": "^2.2.0" 362 | }, 363 | "engines": { 364 | "node": ">=18.17.0" 365 | }, 366 | "peerDependencies": { 367 | "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", 368 | "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" 369 | }, 370 | "peerDependenciesMeta": { 371 | "react": { 372 | "optional": true 373 | }, 374 | "react-dom": { 375 | "optional": true 376 | } 377 | } 378 | }, 379 | "node_modules/@clerk/types": { 380 | "version": "4.45.0", 381 | "resolved": "https://registry.npmjs.org/@clerk/types/-/types-4.45.0.tgz", 382 | "integrity": "sha512-DSXPWq1xD01tzyHv7CugX2T/XfVUZX2xxQ92cs+JPTrGoqIYm+yjRWqOz1CVJ/76TbYMOrB0efCGOxEcNV/PQw==", 383 | "dependencies": { 384 | "csstype": "3.1.1" 385 | }, 386 | "engines": { 387 | "node": ">=18.17.0" 388 | } 389 | }, 390 | "node_modules/@esbuild/aix-ppc64": { 391 | "version": "0.23.1", 392 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", 393 | "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", 394 | "cpu": [ 395 | "ppc64" 396 | ], 397 | "dev": true, 398 | "optional": true, 399 | "os": [ 400 | "aix" 401 | ], 402 | "engines": { 403 | "node": ">=18" 404 | } 405 | }, 406 | "node_modules/@esbuild/android-arm": { 407 | "version": "0.23.1", 408 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", 409 | "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", 410 | "cpu": [ 411 | "arm" 412 | ], 413 | "dev": true, 414 | "optional": true, 415 | "os": [ 416 | "android" 417 | ], 418 | "engines": { 419 | "node": ">=18" 420 | } 421 | }, 422 | "node_modules/@esbuild/android-arm64": { 423 | "version": "0.23.1", 424 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", 425 | "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", 426 | "cpu": [ 427 | "arm64" 428 | ], 429 | "dev": true, 430 | "optional": true, 431 | "os": [ 432 | "android" 433 | ], 434 | "engines": { 435 | "node": ">=18" 436 | } 437 | }, 438 | "node_modules/@esbuild/android-x64": { 439 | "version": "0.23.1", 440 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", 441 | "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", 442 | "cpu": [ 443 | "x64" 444 | ], 445 | "dev": true, 446 | "optional": true, 447 | "os": [ 448 | "android" 449 | ], 450 | "engines": { 451 | "node": ">=18" 452 | } 453 | }, 454 | "node_modules/@esbuild/darwin-arm64": { 455 | "version": "0.23.1", 456 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", 457 | "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", 458 | "cpu": [ 459 | "arm64" 460 | ], 461 | "dev": true, 462 | "optional": true, 463 | "os": [ 464 | "darwin" 465 | ], 466 | "engines": { 467 | "node": ">=18" 468 | } 469 | }, 470 | "node_modules/@esbuild/darwin-x64": { 471 | "version": "0.23.1", 472 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", 473 | "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", 474 | "cpu": [ 475 | "x64" 476 | ], 477 | "dev": true, 478 | "optional": true, 479 | "os": [ 480 | "darwin" 481 | ], 482 | "engines": { 483 | "node": ">=18" 484 | } 485 | }, 486 | "node_modules/@esbuild/freebsd-arm64": { 487 | "version": "0.23.1", 488 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", 489 | "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", 490 | "cpu": [ 491 | "arm64" 492 | ], 493 | "dev": true, 494 | "optional": true, 495 | "os": [ 496 | "freebsd" 497 | ], 498 | "engines": { 499 | "node": ">=18" 500 | } 501 | }, 502 | "node_modules/@esbuild/freebsd-x64": { 503 | "version": "0.23.1", 504 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", 505 | "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", 506 | "cpu": [ 507 | "x64" 508 | ], 509 | "dev": true, 510 | "optional": true, 511 | "os": [ 512 | "freebsd" 513 | ], 514 | "engines": { 515 | "node": ">=18" 516 | } 517 | }, 518 | "node_modules/@esbuild/linux-arm": { 519 | "version": "0.23.1", 520 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", 521 | "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", 522 | "cpu": [ 523 | "arm" 524 | ], 525 | "dev": true, 526 | "optional": true, 527 | "os": [ 528 | "linux" 529 | ], 530 | "engines": { 531 | "node": ">=18" 532 | } 533 | }, 534 | "node_modules/@esbuild/linux-arm64": { 535 | "version": "0.23.1", 536 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", 537 | "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", 538 | "cpu": [ 539 | "arm64" 540 | ], 541 | "dev": true, 542 | "optional": true, 543 | "os": [ 544 | "linux" 545 | ], 546 | "engines": { 547 | "node": ">=18" 548 | } 549 | }, 550 | "node_modules/@esbuild/linux-ia32": { 551 | "version": "0.23.1", 552 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", 553 | "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", 554 | "cpu": [ 555 | "ia32" 556 | ], 557 | "dev": true, 558 | "optional": true, 559 | "os": [ 560 | "linux" 561 | ], 562 | "engines": { 563 | "node": ">=18" 564 | } 565 | }, 566 | "node_modules/@esbuild/linux-loong64": { 567 | "version": "0.23.1", 568 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", 569 | "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", 570 | "cpu": [ 571 | "loong64" 572 | ], 573 | "dev": true, 574 | "optional": true, 575 | "os": [ 576 | "linux" 577 | ], 578 | "engines": { 579 | "node": ">=18" 580 | } 581 | }, 582 | "node_modules/@esbuild/linux-mips64el": { 583 | "version": "0.23.1", 584 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", 585 | "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", 586 | "cpu": [ 587 | "mips64el" 588 | ], 589 | "dev": true, 590 | "optional": true, 591 | "os": [ 592 | "linux" 593 | ], 594 | "engines": { 595 | "node": ">=18" 596 | } 597 | }, 598 | "node_modules/@esbuild/linux-ppc64": { 599 | "version": "0.23.1", 600 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", 601 | "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", 602 | "cpu": [ 603 | "ppc64" 604 | ], 605 | "dev": true, 606 | "optional": true, 607 | "os": [ 608 | "linux" 609 | ], 610 | "engines": { 611 | "node": ">=18" 612 | } 613 | }, 614 | "node_modules/@esbuild/linux-riscv64": { 615 | "version": "0.23.1", 616 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", 617 | "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", 618 | "cpu": [ 619 | "riscv64" 620 | ], 621 | "dev": true, 622 | "optional": true, 623 | "os": [ 624 | "linux" 625 | ], 626 | "engines": { 627 | "node": ">=18" 628 | } 629 | }, 630 | "node_modules/@esbuild/linux-s390x": { 631 | "version": "0.23.1", 632 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", 633 | "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", 634 | "cpu": [ 635 | "s390x" 636 | ], 637 | "dev": true, 638 | "optional": true, 639 | "os": [ 640 | "linux" 641 | ], 642 | "engines": { 643 | "node": ">=18" 644 | } 645 | }, 646 | "node_modules/@esbuild/linux-x64": { 647 | "version": "0.23.1", 648 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", 649 | "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", 650 | "cpu": [ 651 | "x64" 652 | ], 653 | "dev": true, 654 | "optional": true, 655 | "os": [ 656 | "linux" 657 | ], 658 | "engines": { 659 | "node": ">=18" 660 | } 661 | }, 662 | "node_modules/@esbuild/netbsd-x64": { 663 | "version": "0.23.1", 664 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", 665 | "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", 666 | "cpu": [ 667 | "x64" 668 | ], 669 | "dev": true, 670 | "optional": true, 671 | "os": [ 672 | "netbsd" 673 | ], 674 | "engines": { 675 | "node": ">=18" 676 | } 677 | }, 678 | "node_modules/@esbuild/openbsd-arm64": { 679 | "version": "0.23.1", 680 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", 681 | "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", 682 | "cpu": [ 683 | "arm64" 684 | ], 685 | "dev": true, 686 | "optional": true, 687 | "os": [ 688 | "openbsd" 689 | ], 690 | "engines": { 691 | "node": ">=18" 692 | } 693 | }, 694 | "node_modules/@esbuild/openbsd-x64": { 695 | "version": "0.23.1", 696 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", 697 | "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", 698 | "cpu": [ 699 | "x64" 700 | ], 701 | "dev": true, 702 | "optional": true, 703 | "os": [ 704 | "openbsd" 705 | ], 706 | "engines": { 707 | "node": ">=18" 708 | } 709 | }, 710 | "node_modules/@esbuild/sunos-x64": { 711 | "version": "0.23.1", 712 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", 713 | "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", 714 | "cpu": [ 715 | "x64" 716 | ], 717 | "dev": true, 718 | "optional": true, 719 | "os": [ 720 | "sunos" 721 | ], 722 | "engines": { 723 | "node": ">=18" 724 | } 725 | }, 726 | "node_modules/@esbuild/win32-arm64": { 727 | "version": "0.23.1", 728 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", 729 | "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", 730 | "cpu": [ 731 | "arm64" 732 | ], 733 | "dev": true, 734 | "optional": true, 735 | "os": [ 736 | "win32" 737 | ], 738 | "engines": { 739 | "node": ">=18" 740 | } 741 | }, 742 | "node_modules/@esbuild/win32-ia32": { 743 | "version": "0.23.1", 744 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", 745 | "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", 746 | "cpu": [ 747 | "ia32" 748 | ], 749 | "dev": true, 750 | "optional": true, 751 | "os": [ 752 | "win32" 753 | ], 754 | "engines": { 755 | "node": ">=18" 756 | } 757 | }, 758 | "node_modules/@esbuild/win32-x64": { 759 | "version": "0.23.1", 760 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", 761 | "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", 762 | "cpu": [ 763 | "x64" 764 | ], 765 | "dev": true, 766 | "optional": true, 767 | "os": [ 768 | "win32" 769 | ], 770 | "engines": { 771 | "node": ">=18" 772 | } 773 | }, 774 | "node_modules/@ianvs/prettier-plugin-sort-imports": { 775 | "version": "4.4.1", 776 | "resolved": "https://registry.npmjs.org/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.4.1.tgz", 777 | "integrity": "sha512-F0/Hrcfpy8WuxlQyAWJTEren/uxKhYonOGY4OyWmwRdeTvkh9mMSCxowZLjNkhwi/2ipqCgtXwwOk7tW0mWXkA==", 778 | "dev": true, 779 | "license": "Apache-2.0", 780 | "dependencies": { 781 | "@babel/generator": "^7.26.2", 782 | "@babel/parser": "^7.26.2", 783 | "@babel/traverse": "^7.25.9", 784 | "@babel/types": "^7.26.0", 785 | "semver": "^7.5.2" 786 | }, 787 | "peerDependencies": { 788 | "@vue/compiler-sfc": "2.7.x || 3.x", 789 | "prettier": "2 || 3" 790 | }, 791 | "peerDependenciesMeta": { 792 | "@vue/compiler-sfc": { 793 | "optional": true 794 | } 795 | } 796 | }, 797 | "node_modules/@jridgewell/gen-mapping": { 798 | "version": "0.3.8", 799 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", 800 | "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", 801 | "dev": true, 802 | "license": "MIT", 803 | "dependencies": { 804 | "@jridgewell/set-array": "^1.2.1", 805 | "@jridgewell/sourcemap-codec": "^1.4.10", 806 | "@jridgewell/trace-mapping": "^0.3.24" 807 | }, 808 | "engines": { 809 | "node": ">=6.0.0" 810 | } 811 | }, 812 | "node_modules/@jridgewell/resolve-uri": { 813 | "version": "3.1.2", 814 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 815 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 816 | "dev": true, 817 | "license": "MIT", 818 | "engines": { 819 | "node": ">=6.0.0" 820 | } 821 | }, 822 | "node_modules/@jridgewell/set-array": { 823 | "version": "1.2.1", 824 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", 825 | "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", 826 | "dev": true, 827 | "license": "MIT", 828 | "engines": { 829 | "node": ">=6.0.0" 830 | } 831 | }, 832 | "node_modules/@jridgewell/sourcemap-codec": { 833 | "version": "1.5.0", 834 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 835 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 836 | "dev": true, 837 | "license": "MIT" 838 | }, 839 | "node_modules/@jridgewell/trace-mapping": { 840 | "version": "0.3.25", 841 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", 842 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 843 | "dev": true, 844 | "license": "MIT", 845 | "dependencies": { 846 | "@jridgewell/resolve-uri": "^3.1.0", 847 | "@jridgewell/sourcemap-codec": "^1.4.14" 848 | } 849 | }, 850 | "node_modules/@jsdevtools/ono": { 851 | "version": "7.1.3", 852 | "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", 853 | "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" 854 | }, 855 | "node_modules/@mendable/firecrawl-js": { 856 | "version": "1.16.0", 857 | "resolved": "https://registry.npmjs.org/@mendable/firecrawl-js/-/firecrawl-js-1.16.0.tgz", 858 | "integrity": "sha512-u5UVkgmR5yLRBVOaf8gnycAN1RyVHxqjpNkzYCeuCaqnWX7k6ad0OAUMSwf9DR8cPXuHw2/H0VPHqwMhBG/8Xw==", 859 | "license": "MIT", 860 | "dependencies": { 861 | "axios": "^1.6.8", 862 | "isows": "^1.0.4", 863 | "typescript-event-target": "^1.1.1", 864 | "zod": "^3.23.8", 865 | "zod-to-json-schema": "^3.23.0" 866 | } 867 | }, 868 | "node_modules/@opentelemetry/api": { 869 | "version": "1.9.0", 870 | "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", 871 | "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", 872 | "license": "Apache-2.0", 873 | "engines": { 874 | "node": ">=8.0.0" 875 | } 876 | }, 877 | "node_modules/@scarf/scarf": { 878 | "version": "1.4.0", 879 | "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", 880 | "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", 881 | "hasInstallScript": true 882 | }, 883 | "node_modules/@types/body-parser": { 884 | "version": "1.19.5", 885 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", 886 | "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", 887 | "dependencies": { 888 | "@types/connect": "*", 889 | "@types/node": "*" 890 | } 891 | }, 892 | "node_modules/@types/connect": { 893 | "version": "3.4.38", 894 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", 895 | "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", 896 | "dependencies": { 897 | "@types/node": "*" 898 | } 899 | }, 900 | "node_modules/@types/cors": { 901 | "version": "2.8.17", 902 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", 903 | "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", 904 | "dependencies": { 905 | "@types/node": "*" 906 | } 907 | }, 908 | "node_modules/@types/diff-match-patch": { 909 | "version": "1.0.36", 910 | "resolved": "https://registry.npmjs.org/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz", 911 | "integrity": "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==", 912 | "license": "MIT" 913 | }, 914 | "node_modules/@types/express": { 915 | "version": "5.0.0", 916 | "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", 917 | "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", 918 | "dependencies": { 919 | "@types/body-parser": "*", 920 | "@types/express-serve-static-core": "^5.0.0", 921 | "@types/qs": "*", 922 | "@types/serve-static": "*" 923 | } 924 | }, 925 | "node_modules/@types/express-serve-static-core": { 926 | "version": "5.0.6", 927 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz", 928 | "integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==", 929 | "dependencies": { 930 | "@types/node": "*", 931 | "@types/qs": "*", 932 | "@types/range-parser": "*", 933 | "@types/send": "*" 934 | } 935 | }, 936 | "node_modules/@types/http-errors": { 937 | "version": "2.0.4", 938 | "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", 939 | "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" 940 | }, 941 | "node_modules/@types/json-schema": { 942 | "version": "7.0.15", 943 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", 944 | "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" 945 | }, 946 | "node_modules/@types/lodash": { 947 | "version": "4.17.15", 948 | "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz", 949 | "integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==" 950 | }, 951 | "node_modules/@types/lodash-es": { 952 | "version": "4.17.12", 953 | "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", 954 | "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", 955 | "dev": true, 956 | "dependencies": { 957 | "@types/lodash": "*" 958 | } 959 | }, 960 | "node_modules/@types/mime": { 961 | "version": "1.3.5", 962 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", 963 | "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" 964 | }, 965 | "node_modules/@types/node": { 966 | "version": "22.13.0", 967 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.0.tgz", 968 | "integrity": "sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==", 969 | "license": "MIT", 970 | "dependencies": { 971 | "undici-types": "~6.20.0" 972 | } 973 | }, 974 | "node_modules/@types/qs": { 975 | "version": "6.9.18", 976 | "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", 977 | "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==" 978 | }, 979 | "node_modules/@types/range-parser": { 980 | "version": "1.2.7", 981 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", 982 | "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" 983 | }, 984 | "node_modules/@types/send": { 985 | "version": "0.17.4", 986 | "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", 987 | "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", 988 | "dependencies": { 989 | "@types/mime": "^1", 990 | "@types/node": "*" 991 | } 992 | }, 993 | "node_modules/@types/serve-static": { 994 | "version": "1.15.7", 995 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", 996 | "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", 997 | "dependencies": { 998 | "@types/http-errors": "*", 999 | "@types/node": "*", 1000 | "@types/send": "*" 1001 | } 1002 | }, 1003 | "node_modules/@types/swagger-jsdoc": { 1004 | "version": "6.0.4", 1005 | "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz", 1006 | "integrity": "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==" 1007 | }, 1008 | "node_modules/@types/swagger-ui-express": { 1009 | "version": "4.1.7", 1010 | "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.7.tgz", 1011 | "integrity": "sha512-ovLM9dNincXkzH4YwyYpll75vhzPBlWx6La89wwvYH7mHjVpf0X0K/vR/aUM7SRxmr5tt9z7E5XJcjQ46q+S3g==", 1012 | "dependencies": { 1013 | "@types/express": "*", 1014 | "@types/serve-static": "*" 1015 | } 1016 | }, 1017 | "node_modules/accepts": { 1018 | "version": "1.3.8", 1019 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 1020 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 1021 | "dependencies": { 1022 | "mime-types": "~2.1.34", 1023 | "negotiator": "0.6.3" 1024 | }, 1025 | "engines": { 1026 | "node": ">= 0.6" 1027 | } 1028 | }, 1029 | "node_modules/ai": { 1030 | "version": "4.1.17", 1031 | "resolved": "https://registry.npmjs.org/ai/-/ai-4.1.17.tgz", 1032 | "integrity": "sha512-5SW15tXDuxE/wlEOjRKxLxTOUIGD4C9bIee+FCFvXHTTAZhHiQjViC2s7RtMUW+hbFtGya302jUHY1Pe8A/YuQ==", 1033 | "license": "Apache-2.0", 1034 | "dependencies": { 1035 | "@ai-sdk/provider": "1.0.7", 1036 | "@ai-sdk/provider-utils": "2.1.6", 1037 | "@ai-sdk/react": "1.1.8", 1038 | "@ai-sdk/ui-utils": "1.1.8", 1039 | "@opentelemetry/api": "1.9.0", 1040 | "jsondiffpatch": "0.6.0" 1041 | }, 1042 | "engines": { 1043 | "node": ">=18" 1044 | }, 1045 | "peerDependencies": { 1046 | "react": "^18 || ^19 || ^19.0.0-rc", 1047 | "zod": "^3.0.0" 1048 | }, 1049 | "peerDependenciesMeta": { 1050 | "react": { 1051 | "optional": true 1052 | }, 1053 | "zod": { 1054 | "optional": true 1055 | } 1056 | } 1057 | }, 1058 | "node_modules/argparse": { 1059 | "version": "2.0.1", 1060 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 1061 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" 1062 | }, 1063 | "node_modules/array-flatten": { 1064 | "version": "1.1.1", 1065 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 1066 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 1067 | }, 1068 | "node_modules/asynckit": { 1069 | "version": "0.4.0", 1070 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 1071 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", 1072 | "license": "MIT" 1073 | }, 1074 | "node_modules/axios": { 1075 | "version": "1.7.9", 1076 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", 1077 | "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", 1078 | "license": "MIT", 1079 | "dependencies": { 1080 | "follow-redirects": "^1.15.6", 1081 | "form-data": "^4.0.0", 1082 | "proxy-from-env": "^1.1.0" 1083 | } 1084 | }, 1085 | "node_modules/balanced-match": { 1086 | "version": "1.0.2", 1087 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1088 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 1089 | }, 1090 | "node_modules/base64-js": { 1091 | "version": "1.5.1", 1092 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 1093 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 1094 | "funding": [ 1095 | { 1096 | "type": "github", 1097 | "url": "https://github.com/sponsors/feross" 1098 | }, 1099 | { 1100 | "type": "patreon", 1101 | "url": "https://www.patreon.com/feross" 1102 | }, 1103 | { 1104 | "type": "consulting", 1105 | "url": "https://feross.org/support" 1106 | } 1107 | ], 1108 | "license": "MIT" 1109 | }, 1110 | "node_modules/body-parser": { 1111 | "version": "1.20.3", 1112 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 1113 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 1114 | "dependencies": { 1115 | "bytes": "3.1.2", 1116 | "content-type": "~1.0.5", 1117 | "debug": "2.6.9", 1118 | "depd": "2.0.0", 1119 | "destroy": "1.2.0", 1120 | "http-errors": "2.0.0", 1121 | "iconv-lite": "0.4.24", 1122 | "on-finished": "2.4.1", 1123 | "qs": "6.13.0", 1124 | "raw-body": "2.5.2", 1125 | "type-is": "~1.6.18", 1126 | "unpipe": "1.0.0" 1127 | }, 1128 | "engines": { 1129 | "node": ">= 0.8", 1130 | "npm": "1.2.8000 || >= 1.4.16" 1131 | } 1132 | }, 1133 | "node_modules/body-parser/node_modules/debug": { 1134 | "version": "2.6.9", 1135 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1136 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1137 | "dependencies": { 1138 | "ms": "2.0.0" 1139 | } 1140 | }, 1141 | "node_modules/body-parser/node_modules/ms": { 1142 | "version": "2.0.0", 1143 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1144 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 1145 | }, 1146 | "node_modules/brace-expansion": { 1147 | "version": "1.1.11", 1148 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1149 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1150 | "dependencies": { 1151 | "balanced-match": "^1.0.0", 1152 | "concat-map": "0.0.1" 1153 | } 1154 | }, 1155 | "node_modules/bytes": { 1156 | "version": "3.1.2", 1157 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 1158 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 1159 | "engines": { 1160 | "node": ">= 0.8" 1161 | } 1162 | }, 1163 | "node_modules/call-bind-apply-helpers": { 1164 | "version": "1.0.1", 1165 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", 1166 | "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", 1167 | "dependencies": { 1168 | "es-errors": "^1.3.0", 1169 | "function-bind": "^1.1.2" 1170 | }, 1171 | "engines": { 1172 | "node": ">= 0.4" 1173 | } 1174 | }, 1175 | "node_modules/call-bound": { 1176 | "version": "1.0.3", 1177 | "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", 1178 | "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", 1179 | "dependencies": { 1180 | "call-bind-apply-helpers": "^1.0.1", 1181 | "get-intrinsic": "^1.2.6" 1182 | }, 1183 | "engines": { 1184 | "node": ">= 0.4" 1185 | }, 1186 | "funding": { 1187 | "url": "https://github.com/sponsors/ljharb" 1188 | } 1189 | }, 1190 | "node_modules/call-me-maybe": { 1191 | "version": "1.0.2", 1192 | "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", 1193 | "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" 1194 | }, 1195 | "node_modules/chalk": { 1196 | "version": "5.4.1", 1197 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", 1198 | "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", 1199 | "license": "MIT", 1200 | "engines": { 1201 | "node": "^12.17.0 || ^14.13 || >=16.0.0" 1202 | }, 1203 | "funding": { 1204 | "url": "https://github.com/chalk/chalk?sponsor=1" 1205 | } 1206 | }, 1207 | "node_modules/combined-stream": { 1208 | "version": "1.0.8", 1209 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 1210 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 1211 | "license": "MIT", 1212 | "dependencies": { 1213 | "delayed-stream": "~1.0.0" 1214 | }, 1215 | "engines": { 1216 | "node": ">= 0.8" 1217 | } 1218 | }, 1219 | "node_modules/commander": { 1220 | "version": "6.2.0", 1221 | "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", 1222 | "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", 1223 | "engines": { 1224 | "node": ">= 6" 1225 | } 1226 | }, 1227 | "node_modules/concat-map": { 1228 | "version": "0.0.1", 1229 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1230 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 1231 | }, 1232 | "node_modules/content-disposition": { 1233 | "version": "0.5.4", 1234 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 1235 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 1236 | "dependencies": { 1237 | "safe-buffer": "5.2.1" 1238 | }, 1239 | "engines": { 1240 | "node": ">= 0.6" 1241 | } 1242 | }, 1243 | "node_modules/content-type": { 1244 | "version": "1.0.5", 1245 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 1246 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 1247 | "engines": { 1248 | "node": ">= 0.6" 1249 | } 1250 | }, 1251 | "node_modules/cookie": { 1252 | "version": "0.7.1", 1253 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", 1254 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", 1255 | "engines": { 1256 | "node": ">= 0.6" 1257 | } 1258 | }, 1259 | "node_modules/cookie-signature": { 1260 | "version": "1.0.6", 1261 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 1262 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 1263 | }, 1264 | "node_modules/cors": { 1265 | "version": "2.8.5", 1266 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 1267 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 1268 | "dependencies": { 1269 | "object-assign": "^4", 1270 | "vary": "^1" 1271 | }, 1272 | "engines": { 1273 | "node": ">= 0.10" 1274 | } 1275 | }, 1276 | "node_modules/csstype": { 1277 | "version": "3.1.1", 1278 | "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", 1279 | "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" 1280 | }, 1281 | "node_modules/debug": { 1282 | "version": "4.4.0", 1283 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 1284 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 1285 | "dev": true, 1286 | "license": "MIT", 1287 | "dependencies": { 1288 | "ms": "^2.1.3" 1289 | }, 1290 | "engines": { 1291 | "node": ">=6.0" 1292 | }, 1293 | "peerDependenciesMeta": { 1294 | "supports-color": { 1295 | "optional": true 1296 | } 1297 | } 1298 | }, 1299 | "node_modules/delayed-stream": { 1300 | "version": "1.0.0", 1301 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 1302 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 1303 | "license": "MIT", 1304 | "engines": { 1305 | "node": ">=0.4.0" 1306 | } 1307 | }, 1308 | "node_modules/depd": { 1309 | "version": "2.0.0", 1310 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 1311 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 1312 | "engines": { 1313 | "node": ">= 0.8" 1314 | } 1315 | }, 1316 | "node_modules/dequal": { 1317 | "version": "2.0.3", 1318 | "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", 1319 | "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", 1320 | "license": "MIT", 1321 | "engines": { 1322 | "node": ">=6" 1323 | } 1324 | }, 1325 | "node_modules/destroy": { 1326 | "version": "1.2.0", 1327 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 1328 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 1329 | "engines": { 1330 | "node": ">= 0.8", 1331 | "npm": "1.2.8000 || >= 1.4.16" 1332 | } 1333 | }, 1334 | "node_modules/diff-match-patch": { 1335 | "version": "1.0.5", 1336 | "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", 1337 | "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", 1338 | "license": "Apache-2.0" 1339 | }, 1340 | "node_modules/doctrine": { 1341 | "version": "3.0.0", 1342 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 1343 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 1344 | "dependencies": { 1345 | "esutils": "^2.0.2" 1346 | }, 1347 | "engines": { 1348 | "node": ">=6.0.0" 1349 | } 1350 | }, 1351 | "node_modules/dot-case": { 1352 | "version": "3.0.4", 1353 | "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", 1354 | "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", 1355 | "dependencies": { 1356 | "no-case": "^3.0.4", 1357 | "tslib": "^2.0.3" 1358 | } 1359 | }, 1360 | "node_modules/dotenv": { 1361 | "version": "16.4.7", 1362 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", 1363 | "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", 1364 | "engines": { 1365 | "node": ">=12" 1366 | }, 1367 | "funding": { 1368 | "url": "https://dotenvx.com" 1369 | } 1370 | }, 1371 | "node_modules/dunder-proto": { 1372 | "version": "1.0.1", 1373 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 1374 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 1375 | "dependencies": { 1376 | "call-bind-apply-helpers": "^1.0.1", 1377 | "es-errors": "^1.3.0", 1378 | "gopd": "^1.2.0" 1379 | }, 1380 | "engines": { 1381 | "node": ">= 0.4" 1382 | } 1383 | }, 1384 | "node_modules/ee-first": { 1385 | "version": "1.1.1", 1386 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1387 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 1388 | }, 1389 | "node_modules/encodeurl": { 1390 | "version": "2.0.0", 1391 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 1392 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 1393 | "engines": { 1394 | "node": ">= 0.8" 1395 | } 1396 | }, 1397 | "node_modules/es-define-property": { 1398 | "version": "1.0.1", 1399 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 1400 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 1401 | "engines": { 1402 | "node": ">= 0.4" 1403 | } 1404 | }, 1405 | "node_modules/es-errors": { 1406 | "version": "1.3.0", 1407 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 1408 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 1409 | "engines": { 1410 | "node": ">= 0.4" 1411 | } 1412 | }, 1413 | "node_modules/es-object-atoms": { 1414 | "version": "1.1.1", 1415 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 1416 | "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 1417 | "dependencies": { 1418 | "es-errors": "^1.3.0" 1419 | }, 1420 | "engines": { 1421 | "node": ">= 0.4" 1422 | } 1423 | }, 1424 | "node_modules/esbuild": { 1425 | "version": "0.23.1", 1426 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", 1427 | "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", 1428 | "dev": true, 1429 | "hasInstallScript": true, 1430 | "bin": { 1431 | "esbuild": "bin/esbuild" 1432 | }, 1433 | "engines": { 1434 | "node": ">=18" 1435 | }, 1436 | "optionalDependencies": { 1437 | "@esbuild/aix-ppc64": "0.23.1", 1438 | "@esbuild/android-arm": "0.23.1", 1439 | "@esbuild/android-arm64": "0.23.1", 1440 | "@esbuild/android-x64": "0.23.1", 1441 | "@esbuild/darwin-arm64": "0.23.1", 1442 | "@esbuild/darwin-x64": "0.23.1", 1443 | "@esbuild/freebsd-arm64": "0.23.1", 1444 | "@esbuild/freebsd-x64": "0.23.1", 1445 | "@esbuild/linux-arm": "0.23.1", 1446 | "@esbuild/linux-arm64": "0.23.1", 1447 | "@esbuild/linux-ia32": "0.23.1", 1448 | "@esbuild/linux-loong64": "0.23.1", 1449 | "@esbuild/linux-mips64el": "0.23.1", 1450 | "@esbuild/linux-ppc64": "0.23.1", 1451 | "@esbuild/linux-riscv64": "0.23.1", 1452 | "@esbuild/linux-s390x": "0.23.1", 1453 | "@esbuild/linux-x64": "0.23.1", 1454 | "@esbuild/netbsd-x64": "0.23.1", 1455 | "@esbuild/openbsd-arm64": "0.23.1", 1456 | "@esbuild/openbsd-x64": "0.23.1", 1457 | "@esbuild/sunos-x64": "0.23.1", 1458 | "@esbuild/win32-arm64": "0.23.1", 1459 | "@esbuild/win32-ia32": "0.23.1", 1460 | "@esbuild/win32-x64": "0.23.1" 1461 | } 1462 | }, 1463 | "node_modules/escape-html": { 1464 | "version": "1.0.3", 1465 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 1466 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 1467 | }, 1468 | "node_modules/esutils": { 1469 | "version": "2.0.3", 1470 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 1471 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 1472 | "engines": { 1473 | "node": ">=0.10.0" 1474 | } 1475 | }, 1476 | "node_modules/etag": { 1477 | "version": "1.8.1", 1478 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 1479 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 1480 | "engines": { 1481 | "node": ">= 0.6" 1482 | } 1483 | }, 1484 | "node_modules/eventsource-parser": { 1485 | "version": "3.0.0", 1486 | "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.0.tgz", 1487 | "integrity": "sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==", 1488 | "license": "MIT", 1489 | "engines": { 1490 | "node": ">=18.0.0" 1491 | } 1492 | }, 1493 | "node_modules/express": { 1494 | "version": "4.21.2", 1495 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", 1496 | "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", 1497 | "dependencies": { 1498 | "accepts": "~1.3.8", 1499 | "array-flatten": "1.1.1", 1500 | "body-parser": "1.20.3", 1501 | "content-disposition": "0.5.4", 1502 | "content-type": "~1.0.4", 1503 | "cookie": "0.7.1", 1504 | "cookie-signature": "1.0.6", 1505 | "debug": "2.6.9", 1506 | "depd": "2.0.0", 1507 | "encodeurl": "~2.0.0", 1508 | "escape-html": "~1.0.3", 1509 | "etag": "~1.8.1", 1510 | "finalhandler": "1.3.1", 1511 | "fresh": "0.5.2", 1512 | "http-errors": "2.0.0", 1513 | "merge-descriptors": "1.0.3", 1514 | "methods": "~1.1.2", 1515 | "on-finished": "2.4.1", 1516 | "parseurl": "~1.3.3", 1517 | "path-to-regexp": "0.1.12", 1518 | "proxy-addr": "~2.0.7", 1519 | "qs": "6.13.0", 1520 | "range-parser": "~1.2.1", 1521 | "safe-buffer": "5.2.1", 1522 | "send": "0.19.0", 1523 | "serve-static": "1.16.2", 1524 | "setprototypeof": "1.2.0", 1525 | "statuses": "2.0.1", 1526 | "type-is": "~1.6.18", 1527 | "utils-merge": "1.0.1", 1528 | "vary": "~1.1.2" 1529 | }, 1530 | "engines": { 1531 | "node": ">= 0.10.0" 1532 | }, 1533 | "funding": { 1534 | "type": "opencollective", 1535 | "url": "https://opencollective.com/express" 1536 | } 1537 | }, 1538 | "node_modules/express/node_modules/debug": { 1539 | "version": "2.6.9", 1540 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1541 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1542 | "dependencies": { 1543 | "ms": "2.0.0" 1544 | } 1545 | }, 1546 | "node_modules/express/node_modules/ms": { 1547 | "version": "2.0.0", 1548 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1549 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 1550 | }, 1551 | "node_modules/finalhandler": { 1552 | "version": "1.3.1", 1553 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 1554 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 1555 | "dependencies": { 1556 | "debug": "2.6.9", 1557 | "encodeurl": "~2.0.0", 1558 | "escape-html": "~1.0.3", 1559 | "on-finished": "2.4.1", 1560 | "parseurl": "~1.3.3", 1561 | "statuses": "2.0.1", 1562 | "unpipe": "~1.0.0" 1563 | }, 1564 | "engines": { 1565 | "node": ">= 0.8" 1566 | } 1567 | }, 1568 | "node_modules/finalhandler/node_modules/debug": { 1569 | "version": "2.6.9", 1570 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1571 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1572 | "dependencies": { 1573 | "ms": "2.0.0" 1574 | } 1575 | }, 1576 | "node_modules/finalhandler/node_modules/ms": { 1577 | "version": "2.0.0", 1578 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1579 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 1580 | }, 1581 | "node_modules/follow-redirects": { 1582 | "version": "1.15.9", 1583 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", 1584 | "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", 1585 | "funding": [ 1586 | { 1587 | "type": "individual", 1588 | "url": "https://github.com/sponsors/RubenVerborgh" 1589 | } 1590 | ], 1591 | "license": "MIT", 1592 | "engines": { 1593 | "node": ">=4.0" 1594 | }, 1595 | "peerDependenciesMeta": { 1596 | "debug": { 1597 | "optional": true 1598 | } 1599 | } 1600 | }, 1601 | "node_modules/form-data": { 1602 | "version": "4.0.1", 1603 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", 1604 | "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", 1605 | "license": "MIT", 1606 | "dependencies": { 1607 | "asynckit": "^0.4.0", 1608 | "combined-stream": "^1.0.8", 1609 | "mime-types": "^2.1.12" 1610 | }, 1611 | "engines": { 1612 | "node": ">= 6" 1613 | } 1614 | }, 1615 | "node_modules/forwarded": { 1616 | "version": "0.2.0", 1617 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 1618 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 1619 | "engines": { 1620 | "node": ">= 0.6" 1621 | } 1622 | }, 1623 | "node_modules/fresh": { 1624 | "version": "0.5.2", 1625 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 1626 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 1627 | "engines": { 1628 | "node": ">= 0.6" 1629 | } 1630 | }, 1631 | "node_modules/fs.realpath": { 1632 | "version": "1.0.0", 1633 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1634 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" 1635 | }, 1636 | "node_modules/fsevents": { 1637 | "version": "2.3.3", 1638 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1639 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1640 | "dev": true, 1641 | "hasInstallScript": true, 1642 | "license": "MIT", 1643 | "optional": true, 1644 | "os": [ 1645 | "darwin" 1646 | ], 1647 | "engines": { 1648 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1649 | } 1650 | }, 1651 | "node_modules/function-bind": { 1652 | "version": "1.1.2", 1653 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 1654 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 1655 | "funding": { 1656 | "url": "https://github.com/sponsors/ljharb" 1657 | } 1658 | }, 1659 | "node_modules/get-intrinsic": { 1660 | "version": "1.2.7", 1661 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", 1662 | "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", 1663 | "dependencies": { 1664 | "call-bind-apply-helpers": "^1.0.1", 1665 | "es-define-property": "^1.0.1", 1666 | "es-errors": "^1.3.0", 1667 | "es-object-atoms": "^1.0.0", 1668 | "function-bind": "^1.1.2", 1669 | "get-proto": "^1.0.0", 1670 | "gopd": "^1.2.0", 1671 | "has-symbols": "^1.1.0", 1672 | "hasown": "^2.0.2", 1673 | "math-intrinsics": "^1.1.0" 1674 | }, 1675 | "engines": { 1676 | "node": ">= 0.4" 1677 | }, 1678 | "funding": { 1679 | "url": "https://github.com/sponsors/ljharb" 1680 | } 1681 | }, 1682 | "node_modules/get-proto": { 1683 | "version": "1.0.1", 1684 | "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 1685 | "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 1686 | "dependencies": { 1687 | "dunder-proto": "^1.0.1", 1688 | "es-object-atoms": "^1.0.0" 1689 | }, 1690 | "engines": { 1691 | "node": ">= 0.4" 1692 | } 1693 | }, 1694 | "node_modules/get-tsconfig": { 1695 | "version": "4.10.0", 1696 | "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", 1697 | "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", 1698 | "dev": true, 1699 | "dependencies": { 1700 | "resolve-pkg-maps": "^1.0.0" 1701 | }, 1702 | "funding": { 1703 | "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" 1704 | } 1705 | }, 1706 | "node_modules/glob": { 1707 | "version": "7.1.6", 1708 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 1709 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 1710 | "deprecated": "Glob versions prior to v9 are no longer supported", 1711 | "dependencies": { 1712 | "fs.realpath": "^1.0.0", 1713 | "inflight": "^1.0.4", 1714 | "inherits": "2", 1715 | "minimatch": "^3.0.4", 1716 | "once": "^1.3.0", 1717 | "path-is-absolute": "^1.0.0" 1718 | }, 1719 | "engines": { 1720 | "node": "*" 1721 | }, 1722 | "funding": { 1723 | "url": "https://github.com/sponsors/isaacs" 1724 | } 1725 | }, 1726 | "node_modules/glob-to-regexp": { 1727 | "version": "0.4.1", 1728 | "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", 1729 | "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" 1730 | }, 1731 | "node_modules/globals": { 1732 | "version": "11.12.0", 1733 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 1734 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 1735 | "dev": true, 1736 | "license": "MIT", 1737 | "engines": { 1738 | "node": ">=4" 1739 | } 1740 | }, 1741 | "node_modules/gopd": { 1742 | "version": "1.2.0", 1743 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 1744 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 1745 | "engines": { 1746 | "node": ">= 0.4" 1747 | }, 1748 | "funding": { 1749 | "url": "https://github.com/sponsors/ljharb" 1750 | } 1751 | }, 1752 | "node_modules/has-symbols": { 1753 | "version": "1.1.0", 1754 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 1755 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 1756 | "engines": { 1757 | "node": ">= 0.4" 1758 | }, 1759 | "funding": { 1760 | "url": "https://github.com/sponsors/ljharb" 1761 | } 1762 | }, 1763 | "node_modules/hasown": { 1764 | "version": "2.0.2", 1765 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 1766 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 1767 | "dependencies": { 1768 | "function-bind": "^1.1.2" 1769 | }, 1770 | "engines": { 1771 | "node": ">= 0.4" 1772 | } 1773 | }, 1774 | "node_modules/http-errors": { 1775 | "version": "2.0.0", 1776 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 1777 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 1778 | "dependencies": { 1779 | "depd": "2.0.0", 1780 | "inherits": "2.0.4", 1781 | "setprototypeof": "1.2.0", 1782 | "statuses": "2.0.1", 1783 | "toidentifier": "1.0.1" 1784 | }, 1785 | "engines": { 1786 | "node": ">= 0.8" 1787 | } 1788 | }, 1789 | "node_modules/iconv-lite": { 1790 | "version": "0.4.24", 1791 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 1792 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 1793 | "dependencies": { 1794 | "safer-buffer": ">= 2.1.2 < 3" 1795 | }, 1796 | "engines": { 1797 | "node": ">=0.10.0" 1798 | } 1799 | }, 1800 | "node_modules/inflight": { 1801 | "version": "1.0.6", 1802 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1803 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 1804 | "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", 1805 | "dependencies": { 1806 | "once": "^1.3.0", 1807 | "wrappy": "1" 1808 | } 1809 | }, 1810 | "node_modules/inherits": { 1811 | "version": "2.0.4", 1812 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1813 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1814 | }, 1815 | "node_modules/ipaddr.js": { 1816 | "version": "1.9.1", 1817 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1818 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 1819 | "engines": { 1820 | "node": ">= 0.10" 1821 | } 1822 | }, 1823 | "node_modules/isows": { 1824 | "version": "1.0.6", 1825 | "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", 1826 | "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", 1827 | "funding": [ 1828 | { 1829 | "type": "github", 1830 | "url": "https://github.com/sponsors/wevm" 1831 | } 1832 | ], 1833 | "license": "MIT", 1834 | "peerDependencies": { 1835 | "ws": "*" 1836 | } 1837 | }, 1838 | "node_modules/js-cookie": { 1839 | "version": "3.0.5", 1840 | "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", 1841 | "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", 1842 | "engines": { 1843 | "node": ">=14" 1844 | } 1845 | }, 1846 | "node_modules/js-tiktoken": { 1847 | "version": "1.0.17", 1848 | "resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.17.tgz", 1849 | "integrity": "sha512-Fzmf02RUP8lU6eAn0CtwWEr//mSVGOgj6lK6D++OF+ZVVtFVPnaBdSAN1P2QA0/q8IZOulhIOIjnlFy6QwYNBw==", 1850 | "license": "MIT", 1851 | "dependencies": { 1852 | "base64-js": "^1.5.1" 1853 | } 1854 | }, 1855 | "node_modules/js-tokens": { 1856 | "version": "4.0.0", 1857 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1858 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1859 | "dev": true, 1860 | "license": "MIT" 1861 | }, 1862 | "node_modules/js-yaml": { 1863 | "version": "4.1.0", 1864 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 1865 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1866 | "dependencies": { 1867 | "argparse": "^2.0.1" 1868 | }, 1869 | "bin": { 1870 | "js-yaml": "bin/js-yaml.js" 1871 | } 1872 | }, 1873 | "node_modules/jsesc": { 1874 | "version": "3.1.0", 1875 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", 1876 | "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", 1877 | "dev": true, 1878 | "license": "MIT", 1879 | "bin": { 1880 | "jsesc": "bin/jsesc" 1881 | }, 1882 | "engines": { 1883 | "node": ">=6" 1884 | } 1885 | }, 1886 | "node_modules/json-schema": { 1887 | "version": "0.4.0", 1888 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", 1889 | "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", 1890 | "license": "(AFL-2.1 OR BSD-3-Clause)" 1891 | }, 1892 | "node_modules/jsondiffpatch": { 1893 | "version": "0.6.0", 1894 | "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.6.0.tgz", 1895 | "integrity": "sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ==", 1896 | "license": "MIT", 1897 | "dependencies": { 1898 | "@types/diff-match-patch": "^1.0.36", 1899 | "chalk": "^5.3.0", 1900 | "diff-match-patch": "^1.0.5" 1901 | }, 1902 | "bin": { 1903 | "jsondiffpatch": "bin/jsondiffpatch.js" 1904 | }, 1905 | "engines": { 1906 | "node": "^18.0.0 || >=20.0.0" 1907 | } 1908 | }, 1909 | "node_modules/lodash-es": { 1910 | "version": "4.17.21", 1911 | "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", 1912 | "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" 1913 | }, 1914 | "node_modules/lodash.get": { 1915 | "version": "4.4.2", 1916 | "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", 1917 | "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", 1918 | "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead." 1919 | }, 1920 | "node_modules/lodash.isequal": { 1921 | "version": "4.5.0", 1922 | "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", 1923 | "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", 1924 | "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead." 1925 | }, 1926 | "node_modules/lodash.mergewith": { 1927 | "version": "4.6.2", 1928 | "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", 1929 | "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==" 1930 | }, 1931 | "node_modules/lower-case": { 1932 | "version": "2.0.2", 1933 | "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", 1934 | "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", 1935 | "dependencies": { 1936 | "tslib": "^2.0.3" 1937 | } 1938 | }, 1939 | "node_modules/map-obj": { 1940 | "version": "4.3.0", 1941 | "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", 1942 | "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", 1943 | "engines": { 1944 | "node": ">=8" 1945 | }, 1946 | "funding": { 1947 | "url": "https://github.com/sponsors/sindresorhus" 1948 | } 1949 | }, 1950 | "node_modules/math-intrinsics": { 1951 | "version": "1.1.0", 1952 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 1953 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 1954 | "engines": { 1955 | "node": ">= 0.4" 1956 | } 1957 | }, 1958 | "node_modules/media-typer": { 1959 | "version": "0.3.0", 1960 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1961 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 1962 | "engines": { 1963 | "node": ">= 0.6" 1964 | } 1965 | }, 1966 | "node_modules/merge-descriptors": { 1967 | "version": "1.0.3", 1968 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 1969 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", 1970 | "funding": { 1971 | "url": "https://github.com/sponsors/sindresorhus" 1972 | } 1973 | }, 1974 | "node_modules/methods": { 1975 | "version": "1.1.2", 1976 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1977 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 1978 | "engines": { 1979 | "node": ">= 0.6" 1980 | } 1981 | }, 1982 | "node_modules/mime": { 1983 | "version": "1.6.0", 1984 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1985 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 1986 | "bin": { 1987 | "mime": "cli.js" 1988 | }, 1989 | "engines": { 1990 | "node": ">=4" 1991 | } 1992 | }, 1993 | "node_modules/mime-db": { 1994 | "version": "1.52.0", 1995 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1996 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 1997 | "license": "MIT", 1998 | "engines": { 1999 | "node": ">= 0.6" 2000 | } 2001 | }, 2002 | "node_modules/mime-types": { 2003 | "version": "2.1.35", 2004 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 2005 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 2006 | "license": "MIT", 2007 | "dependencies": { 2008 | "mime-db": "1.52.0" 2009 | }, 2010 | "engines": { 2011 | "node": ">= 0.6" 2012 | } 2013 | }, 2014 | "node_modules/minimatch": { 2015 | "version": "3.1.2", 2016 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 2017 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 2018 | "dependencies": { 2019 | "brace-expansion": "^1.1.7" 2020 | }, 2021 | "engines": { 2022 | "node": "*" 2023 | } 2024 | }, 2025 | "node_modules/ms": { 2026 | "version": "2.1.3", 2027 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 2028 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 2029 | "license": "MIT" 2030 | }, 2031 | "node_modules/nanoid": { 2032 | "version": "3.3.8", 2033 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", 2034 | "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", 2035 | "funding": [ 2036 | { 2037 | "type": "github", 2038 | "url": "https://github.com/sponsors/ai" 2039 | } 2040 | ], 2041 | "license": "MIT", 2042 | "bin": { 2043 | "nanoid": "bin/nanoid.cjs" 2044 | }, 2045 | "engines": { 2046 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 2047 | } 2048 | }, 2049 | "node_modules/negotiator": { 2050 | "version": "0.6.3", 2051 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 2052 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 2053 | "engines": { 2054 | "node": ">= 0.6" 2055 | } 2056 | }, 2057 | "node_modules/no-case": { 2058 | "version": "3.0.4", 2059 | "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", 2060 | "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", 2061 | "dependencies": { 2062 | "lower-case": "^2.0.2", 2063 | "tslib": "^2.0.3" 2064 | } 2065 | }, 2066 | "node_modules/object-assign": { 2067 | "version": "4.1.1", 2068 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 2069 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 2070 | "engines": { 2071 | "node": ">=0.10.0" 2072 | } 2073 | }, 2074 | "node_modules/object-inspect": { 2075 | "version": "1.13.4", 2076 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", 2077 | "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", 2078 | "engines": { 2079 | "node": ">= 0.4" 2080 | }, 2081 | "funding": { 2082 | "url": "https://github.com/sponsors/ljharb" 2083 | } 2084 | }, 2085 | "node_modules/on-finished": { 2086 | "version": "2.4.1", 2087 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 2088 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 2089 | "dependencies": { 2090 | "ee-first": "1.1.1" 2091 | }, 2092 | "engines": { 2093 | "node": ">= 0.8" 2094 | } 2095 | }, 2096 | "node_modules/once": { 2097 | "version": "1.4.0", 2098 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2099 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 2100 | "dependencies": { 2101 | "wrappy": "1" 2102 | } 2103 | }, 2104 | "node_modules/openapi-types": { 2105 | "version": "12.1.3", 2106 | "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", 2107 | "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", 2108 | "peer": true 2109 | }, 2110 | "node_modules/p-limit": { 2111 | "version": "6.2.0", 2112 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz", 2113 | "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==", 2114 | "license": "MIT", 2115 | "dependencies": { 2116 | "yocto-queue": "^1.1.1" 2117 | }, 2118 | "engines": { 2119 | "node": ">=18" 2120 | }, 2121 | "funding": { 2122 | "url": "https://github.com/sponsors/sindresorhus" 2123 | } 2124 | }, 2125 | "node_modules/parseurl": { 2126 | "version": "1.3.3", 2127 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 2128 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 2129 | "engines": { 2130 | "node": ">= 0.8" 2131 | } 2132 | }, 2133 | "node_modules/path-is-absolute": { 2134 | "version": "1.0.1", 2135 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2136 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 2137 | "engines": { 2138 | "node": ">=0.10.0" 2139 | } 2140 | }, 2141 | "node_modules/path-to-regexp": { 2142 | "version": "0.1.12", 2143 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", 2144 | "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" 2145 | }, 2146 | "node_modules/picocolors": { 2147 | "version": "1.1.1", 2148 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 2149 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 2150 | "dev": true, 2151 | "license": "ISC" 2152 | }, 2153 | "node_modules/prettier": { 2154 | "version": "3.4.2", 2155 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", 2156 | "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", 2157 | "dev": true, 2158 | "license": "MIT", 2159 | "bin": { 2160 | "prettier": "bin/prettier.cjs" 2161 | }, 2162 | "engines": { 2163 | "node": ">=14" 2164 | }, 2165 | "funding": { 2166 | "url": "https://github.com/prettier/prettier?sponsor=1" 2167 | } 2168 | }, 2169 | "node_modules/proxy-addr": { 2170 | "version": "2.0.7", 2171 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 2172 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 2173 | "dependencies": { 2174 | "forwarded": "0.2.0", 2175 | "ipaddr.js": "1.9.1" 2176 | }, 2177 | "engines": { 2178 | "node": ">= 0.10" 2179 | } 2180 | }, 2181 | "node_modules/proxy-from-env": { 2182 | "version": "1.1.0", 2183 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 2184 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", 2185 | "license": "MIT" 2186 | }, 2187 | "node_modules/qs": { 2188 | "version": "6.13.0", 2189 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 2190 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 2191 | "dependencies": { 2192 | "side-channel": "^1.0.6" 2193 | }, 2194 | "engines": { 2195 | "node": ">=0.6" 2196 | }, 2197 | "funding": { 2198 | "url": "https://github.com/sponsors/ljharb" 2199 | } 2200 | }, 2201 | "node_modules/range-parser": { 2202 | "version": "1.2.1", 2203 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 2204 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 2205 | "engines": { 2206 | "node": ">= 0.6" 2207 | } 2208 | }, 2209 | "node_modules/raw-body": { 2210 | "version": "2.5.2", 2211 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 2212 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 2213 | "dependencies": { 2214 | "bytes": "3.1.2", 2215 | "http-errors": "2.0.0", 2216 | "iconv-lite": "0.4.24", 2217 | "unpipe": "1.0.0" 2218 | }, 2219 | "engines": { 2220 | "node": ">= 0.8" 2221 | } 2222 | }, 2223 | "node_modules/react": { 2224 | "version": "19.0.0", 2225 | "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", 2226 | "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", 2227 | "license": "MIT", 2228 | "peer": true, 2229 | "engines": { 2230 | "node": ">=0.10.0" 2231 | } 2232 | }, 2233 | "node_modules/resolve-pkg-maps": { 2234 | "version": "1.0.0", 2235 | "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", 2236 | "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", 2237 | "dev": true, 2238 | "funding": { 2239 | "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" 2240 | } 2241 | }, 2242 | "node_modules/safe-buffer": { 2243 | "version": "5.2.1", 2244 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2245 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 2246 | "funding": [ 2247 | { 2248 | "type": "github", 2249 | "url": "https://github.com/sponsors/feross" 2250 | }, 2251 | { 2252 | "type": "patreon", 2253 | "url": "https://www.patreon.com/feross" 2254 | }, 2255 | { 2256 | "type": "consulting", 2257 | "url": "https://feross.org/support" 2258 | } 2259 | ] 2260 | }, 2261 | "node_modules/safer-buffer": { 2262 | "version": "2.1.2", 2263 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2264 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 2265 | }, 2266 | "node_modules/secure-json-parse": { 2267 | "version": "2.7.0", 2268 | "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", 2269 | "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", 2270 | "license": "BSD-3-Clause" 2271 | }, 2272 | "node_modules/semver": { 2273 | "version": "7.7.1", 2274 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", 2275 | "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", 2276 | "dev": true, 2277 | "license": "ISC", 2278 | "bin": { 2279 | "semver": "bin/semver.js" 2280 | }, 2281 | "engines": { 2282 | "node": ">=10" 2283 | } 2284 | }, 2285 | "node_modules/send": { 2286 | "version": "0.19.0", 2287 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 2288 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 2289 | "dependencies": { 2290 | "debug": "2.6.9", 2291 | "depd": "2.0.0", 2292 | "destroy": "1.2.0", 2293 | "encodeurl": "~1.0.2", 2294 | "escape-html": "~1.0.3", 2295 | "etag": "~1.8.1", 2296 | "fresh": "0.5.2", 2297 | "http-errors": "2.0.0", 2298 | "mime": "1.6.0", 2299 | "ms": "2.1.3", 2300 | "on-finished": "2.4.1", 2301 | "range-parser": "~1.2.1", 2302 | "statuses": "2.0.1" 2303 | }, 2304 | "engines": { 2305 | "node": ">= 0.8.0" 2306 | } 2307 | }, 2308 | "node_modules/send/node_modules/debug": { 2309 | "version": "2.6.9", 2310 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 2311 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 2312 | "dependencies": { 2313 | "ms": "2.0.0" 2314 | } 2315 | }, 2316 | "node_modules/send/node_modules/debug/node_modules/ms": { 2317 | "version": "2.0.0", 2318 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 2319 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 2320 | }, 2321 | "node_modules/send/node_modules/encodeurl": { 2322 | "version": "1.0.2", 2323 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 2324 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 2325 | "engines": { 2326 | "node": ">= 0.8" 2327 | } 2328 | }, 2329 | "node_modules/serve-static": { 2330 | "version": "1.16.2", 2331 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 2332 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 2333 | "dependencies": { 2334 | "encodeurl": "~2.0.0", 2335 | "escape-html": "~1.0.3", 2336 | "parseurl": "~1.3.3", 2337 | "send": "0.19.0" 2338 | }, 2339 | "engines": { 2340 | "node": ">= 0.8.0" 2341 | } 2342 | }, 2343 | "node_modules/setprototypeof": { 2344 | "version": "1.2.0", 2345 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 2346 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 2347 | }, 2348 | "node_modules/side-channel": { 2349 | "version": "1.1.0", 2350 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 2351 | "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 2352 | "dependencies": { 2353 | "es-errors": "^1.3.0", 2354 | "object-inspect": "^1.13.3", 2355 | "side-channel-list": "^1.0.0", 2356 | "side-channel-map": "^1.0.1", 2357 | "side-channel-weakmap": "^1.0.2" 2358 | }, 2359 | "engines": { 2360 | "node": ">= 0.4" 2361 | }, 2362 | "funding": { 2363 | "url": "https://github.com/sponsors/ljharb" 2364 | } 2365 | }, 2366 | "node_modules/side-channel-list": { 2367 | "version": "1.0.0", 2368 | "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 2369 | "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 2370 | "dependencies": { 2371 | "es-errors": "^1.3.0", 2372 | "object-inspect": "^1.13.3" 2373 | }, 2374 | "engines": { 2375 | "node": ">= 0.4" 2376 | }, 2377 | "funding": { 2378 | "url": "https://github.com/sponsors/ljharb" 2379 | } 2380 | }, 2381 | "node_modules/side-channel-map": { 2382 | "version": "1.0.1", 2383 | "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 2384 | "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 2385 | "dependencies": { 2386 | "call-bound": "^1.0.2", 2387 | "es-errors": "^1.3.0", 2388 | "get-intrinsic": "^1.2.5", 2389 | "object-inspect": "^1.13.3" 2390 | }, 2391 | "engines": { 2392 | "node": ">= 0.4" 2393 | }, 2394 | "funding": { 2395 | "url": "https://github.com/sponsors/ljharb" 2396 | } 2397 | }, 2398 | "node_modules/side-channel-weakmap": { 2399 | "version": "1.0.2", 2400 | "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 2401 | "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 2402 | "dependencies": { 2403 | "call-bound": "^1.0.2", 2404 | "es-errors": "^1.3.0", 2405 | "get-intrinsic": "^1.2.5", 2406 | "object-inspect": "^1.13.3", 2407 | "side-channel-map": "^1.0.1" 2408 | }, 2409 | "engines": { 2410 | "node": ">= 0.4" 2411 | }, 2412 | "funding": { 2413 | "url": "https://github.com/sponsors/ljharb" 2414 | } 2415 | }, 2416 | "node_modules/snake-case": { 2417 | "version": "3.0.4", 2418 | "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", 2419 | "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", 2420 | "dependencies": { 2421 | "dot-case": "^3.0.4", 2422 | "tslib": "^2.0.3" 2423 | } 2424 | }, 2425 | "node_modules/snakecase-keys": { 2426 | "version": "8.0.1", 2427 | "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-8.0.1.tgz", 2428 | "integrity": "sha512-Sj51kE1zC7zh6TDlNNz0/Jn1n5HiHdoQErxO8jLtnyrkJW/M5PrI7x05uDgY3BO7OUQYKCvmeMurW6BPUdwEOw==", 2429 | "dependencies": { 2430 | "map-obj": "^4.1.0", 2431 | "snake-case": "^3.0.4", 2432 | "type-fest": "^4.15.0" 2433 | }, 2434 | "engines": { 2435 | "node": ">=18" 2436 | } 2437 | }, 2438 | "node_modules/statuses": { 2439 | "version": "2.0.1", 2440 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 2441 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 2442 | "engines": { 2443 | "node": ">= 0.8" 2444 | } 2445 | }, 2446 | "node_modules/std-env": { 2447 | "version": "3.8.0", 2448 | "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", 2449 | "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==" 2450 | }, 2451 | "node_modules/swagger-jsdoc": { 2452 | "version": "6.2.8", 2453 | "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", 2454 | "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", 2455 | "dependencies": { 2456 | "commander": "6.2.0", 2457 | "doctrine": "3.0.0", 2458 | "glob": "7.1.6", 2459 | "lodash.mergewith": "^4.6.2", 2460 | "swagger-parser": "^10.0.3", 2461 | "yaml": "2.0.0-1" 2462 | }, 2463 | "bin": { 2464 | "swagger-jsdoc": "bin/swagger-jsdoc.js" 2465 | }, 2466 | "engines": { 2467 | "node": ">=12.0.0" 2468 | } 2469 | }, 2470 | "node_modules/swagger-parser": { 2471 | "version": "10.0.3", 2472 | "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", 2473 | "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", 2474 | "dependencies": { 2475 | "@apidevtools/swagger-parser": "10.0.3" 2476 | }, 2477 | "engines": { 2478 | "node": ">=10" 2479 | } 2480 | }, 2481 | "node_modules/swagger-ui-dist": { 2482 | "version": "5.18.3", 2483 | "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.18.3.tgz", 2484 | "integrity": "sha512-G33HFW0iFNStfY2x6QXO2JYVMrFruc8AZRX0U/L71aA7WeWfX2E5Nm8E/tsipSZJeIZZbSjUDeynLK/wcuNWIw==", 2485 | "dependencies": { 2486 | "@scarf/scarf": "=1.4.0" 2487 | } 2488 | }, 2489 | "node_modules/swagger-ui-express": { 2490 | "version": "5.0.1", 2491 | "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz", 2492 | "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==", 2493 | "dependencies": { 2494 | "swagger-ui-dist": ">=5.0.0" 2495 | }, 2496 | "engines": { 2497 | "node": ">= v0.10.32" 2498 | }, 2499 | "peerDependencies": { 2500 | "express": ">=4.0.0 || >=5.0.0-beta" 2501 | } 2502 | }, 2503 | "node_modules/swr": { 2504 | "version": "2.3.0", 2505 | "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.0.tgz", 2506 | "integrity": "sha512-NyZ76wA4yElZWBHzSgEJc28a0u6QZvhb6w0azeL2k7+Q1gAzVK+IqQYXhVOC/mzi+HZIozrZvBVeSeOZNR2bqA==", 2507 | "license": "MIT", 2508 | "dependencies": { 2509 | "dequal": "^2.0.3", 2510 | "use-sync-external-store": "^1.4.0" 2511 | }, 2512 | "peerDependencies": { 2513 | "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 2514 | } 2515 | }, 2516 | "node_modules/throttleit": { 2517 | "version": "2.1.0", 2518 | "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-2.1.0.tgz", 2519 | "integrity": "sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==", 2520 | "license": "MIT", 2521 | "engines": { 2522 | "node": ">=18" 2523 | }, 2524 | "funding": { 2525 | "url": "https://github.com/sponsors/sindresorhus" 2526 | } 2527 | }, 2528 | "node_modules/toidentifier": { 2529 | "version": "1.0.1", 2530 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 2531 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 2532 | "engines": { 2533 | "node": ">=0.6" 2534 | } 2535 | }, 2536 | "node_modules/tslib": { 2537 | "version": "2.8.1", 2538 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 2539 | "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" 2540 | }, 2541 | "node_modules/tsx": { 2542 | "version": "4.19.2", 2543 | "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", 2544 | "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", 2545 | "dev": true, 2546 | "dependencies": { 2547 | "esbuild": "~0.23.0", 2548 | "get-tsconfig": "^4.7.5" 2549 | }, 2550 | "bin": { 2551 | "tsx": "dist/cli.mjs" 2552 | }, 2553 | "engines": { 2554 | "node": ">=18.0.0" 2555 | }, 2556 | "optionalDependencies": { 2557 | "fsevents": "~2.3.3" 2558 | } 2559 | }, 2560 | "node_modules/type-fest": { 2561 | "version": "4.33.0", 2562 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.33.0.tgz", 2563 | "integrity": "sha512-s6zVrxuyKbbAsSAD5ZPTB77q4YIdRctkTbJ2/Dqlinwz+8ooH2gd+YA7VA6Pa93KML9GockVvoxjZ2vHP+mu8g==", 2564 | "engines": { 2565 | "node": ">=16" 2566 | }, 2567 | "funding": { 2568 | "url": "https://github.com/sponsors/sindresorhus" 2569 | } 2570 | }, 2571 | "node_modules/type-is": { 2572 | "version": "1.6.18", 2573 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 2574 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 2575 | "dependencies": { 2576 | "media-typer": "0.3.0", 2577 | "mime-types": "~2.1.24" 2578 | }, 2579 | "engines": { 2580 | "node": ">= 0.6" 2581 | } 2582 | }, 2583 | "node_modules/typescript": { 2584 | "version": "5.7.3", 2585 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", 2586 | "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", 2587 | "dev": true, 2588 | "license": "Apache-2.0", 2589 | "bin": { 2590 | "tsc": "bin/tsc", 2591 | "tsserver": "bin/tsserver" 2592 | }, 2593 | "engines": { 2594 | "node": ">=14.17" 2595 | } 2596 | }, 2597 | "node_modules/typescript-event-target": { 2598 | "version": "1.1.1", 2599 | "resolved": "https://registry.npmjs.org/typescript-event-target/-/typescript-event-target-1.1.1.tgz", 2600 | "integrity": "sha512-dFSOFBKV6uwaloBCCUhxlD3Pr/P1a/tJdcmPrTXCHlEFD3faj0mztjcGn6VBAhQ0/Bdy8K3VWrrqwbt/ffsYsg==", 2601 | "license": "MIT" 2602 | }, 2603 | "node_modules/undici-types": { 2604 | "version": "6.20.0", 2605 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", 2606 | "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", 2607 | "license": "MIT" 2608 | }, 2609 | "node_modules/unpipe": { 2610 | "version": "1.0.0", 2611 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 2612 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 2613 | "engines": { 2614 | "node": ">= 0.8" 2615 | } 2616 | }, 2617 | "node_modules/use-sync-external-store": { 2618 | "version": "1.4.0", 2619 | "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz", 2620 | "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==", 2621 | "license": "MIT", 2622 | "peerDependencies": { 2623 | "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 2624 | } 2625 | }, 2626 | "node_modules/utils-merge": { 2627 | "version": "1.0.1", 2628 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 2629 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 2630 | "engines": { 2631 | "node": ">= 0.4.0" 2632 | } 2633 | }, 2634 | "node_modules/validator": { 2635 | "version": "13.12.0", 2636 | "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", 2637 | "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", 2638 | "engines": { 2639 | "node": ">= 0.10" 2640 | } 2641 | }, 2642 | "node_modules/vary": { 2643 | "version": "1.1.2", 2644 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 2645 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 2646 | "engines": { 2647 | "node": ">= 0.8" 2648 | } 2649 | }, 2650 | "node_modules/wrappy": { 2651 | "version": "1.0.2", 2652 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2653 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 2654 | }, 2655 | "node_modules/ws": { 2656 | "version": "8.18.0", 2657 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", 2658 | "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", 2659 | "license": "MIT", 2660 | "peer": true, 2661 | "engines": { 2662 | "node": ">=10.0.0" 2663 | }, 2664 | "peerDependencies": { 2665 | "bufferutil": "^4.0.1", 2666 | "utf-8-validate": ">=5.0.2" 2667 | }, 2668 | "peerDependenciesMeta": { 2669 | "bufferutil": { 2670 | "optional": true 2671 | }, 2672 | "utf-8-validate": { 2673 | "optional": true 2674 | } 2675 | } 2676 | }, 2677 | "node_modules/yaml": { 2678 | "version": "2.0.0-1", 2679 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", 2680 | "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", 2681 | "engines": { 2682 | "node": ">= 6" 2683 | } 2684 | }, 2685 | "node_modules/yocto-queue": { 2686 | "version": "1.1.1", 2687 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", 2688 | "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", 2689 | "license": "MIT", 2690 | "engines": { 2691 | "node": ">=12.20" 2692 | }, 2693 | "funding": { 2694 | "url": "https://github.com/sponsors/sindresorhus" 2695 | } 2696 | }, 2697 | "node_modules/z-schema": { 2698 | "version": "5.0.5", 2699 | "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", 2700 | "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", 2701 | "dependencies": { 2702 | "lodash.get": "^4.4.2", 2703 | "lodash.isequal": "^4.5.0", 2704 | "validator": "^13.7.0" 2705 | }, 2706 | "bin": { 2707 | "z-schema": "bin/z-schema" 2708 | }, 2709 | "engines": { 2710 | "node": ">=8.0.0" 2711 | }, 2712 | "optionalDependencies": { 2713 | "commander": "^9.4.1" 2714 | } 2715 | }, 2716 | "node_modules/z-schema/node_modules/commander": { 2717 | "version": "9.5.0", 2718 | "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", 2719 | "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", 2720 | "optional": true, 2721 | "engines": { 2722 | "node": "^12.20.0 || >=14" 2723 | } 2724 | }, 2725 | "node_modules/zod": { 2726 | "version": "3.24.1", 2727 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", 2728 | "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", 2729 | "license": "MIT", 2730 | "funding": { 2731 | "url": "https://github.com/sponsors/colinhacks" 2732 | } 2733 | }, 2734 | "node_modules/zod-to-json-schema": { 2735 | "version": "3.24.1", 2736 | "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.1.tgz", 2737 | "integrity": "sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==", 2738 | "license": "ISC", 2739 | "peerDependencies": { 2740 | "zod": "^3.24.1" 2741 | } 2742 | } 2743 | } 2744 | } 2745 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "open-deep-research-api", 3 | "version": "0.0.1", 4 | "main": "src/api/server.ts", 5 | "type": "module", 6 | "scripts": { 7 | "format": "prettier --write \"src/**/*.{ts}\"", 8 | "start": "node --experimental-specifier-resolution=node dist/api/server.js", 9 | "dev": "tsx watch src/api/server.ts", 10 | "build": "tsc", 11 | "build:clean": "rm -rf dist && npm run build", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "author": "", 15 | "license": "ISC", 16 | "description": "", 17 | "devDependencies": { 18 | "@ianvs/prettier-plugin-sort-imports": "^4.4.1", 19 | "@types/lodash-es": "^4.17.12", 20 | "@types/node": "^22.13.0", 21 | "prettier": "^3.4.2", 22 | "tslib": "^2.8.1", 23 | "tsx": "^4.19.2", 24 | "typescript": "^5.7.3" 25 | }, 26 | "dependencies": { 27 | "@ai-sdk/openai": "^1.1.9", 28 | "@clerk/express": "^1.3.46", 29 | "@mendable/firecrawl-js": "^1.16.0", 30 | "@types/cors": "^2.8.17", 31 | "@types/express": "^5.0.0", 32 | "@types/lodash": "^4.17.15", 33 | "@types/swagger-jsdoc": "^6.0.4", 34 | "@types/swagger-ui-express": "^4.1.7", 35 | "ai": "^4.1.17", 36 | "cors": "^2.8.5", 37 | "dotenv": "^16.4.7", 38 | "express": "^4.21.2", 39 | "js-tiktoken": "^1.0.17", 40 | "lodash-es": "^4.17.21", 41 | "p-limit": "^6.2.0", 42 | "swagger-jsdoc": "^6.2.8", 43 | "swagger-ui-express": "^5.0.1", 44 | "zod": "^3.24.1" 45 | }, 46 | "engines": { 47 | "node": "22.x" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /prettier.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('prettier').Config} */ 2 | export default { 3 | endOfLine: 'lf', 4 | semi: true, 5 | useTabs: false, 6 | singleQuote: true, 7 | arrowParens: 'avoid', 8 | tabWidth: 2, 9 | trailingComma: 'all', 10 | importOrder: [ 11 | '^(react/(.*)$)|^(react$)', 12 | '^(next/(.*)$)|^(next$)', 13 | '', 14 | '', 15 | '@repo/(.*)$', 16 | '', 17 | '^@/(.*)$', 18 | '', 19 | '^[./]', 20 | ], 21 | importOrderParserPlugins: ['typescript', 'jsx'], 22 | importOrderTypeScriptVersion: '5.7.2', 23 | plugins: ['@ianvs/prettier-plugin-sort-imports'], 24 | }; 25 | -------------------------------------------------------------------------------- /report.md: -------------------------------------------------------------------------------- 1 | # A Comprehensive Analysis of NVIDIA's RTX 5000 Series for Gaming Performance 2 | 3 | This report provides an in-depth technical and comparative analysis of NVIDIA’s new RTX 5000 series GPUs, with a focus on pure gaming performance. It covers architectural innovations, benchmarking results, design optimizations, and market positioning relative to both previous RTX generations and competing products such as AMD’s RX 9000 series. The following sections detail the extensive research conducted, incorporating insights from rigorous benchmarks, innovative engineering strategies, and comparative evaluations. 4 | 5 | --- 6 | 7 | ## 1. Introduction 8 | 9 | The RTX 5000 series marks a significant generational leap for NVIDIA in catering specifically to high-performance gaming. This new lineup targets enthusiasts and professionals alike, delivering improved frame rates, cutting-edge AI upscaling, and state-of-the-art ray tracing capabilities. As a follow-up to prior queries comparing the RTX 5000 series to its predecessors and to AMD's upcoming offerings, this report aggregates all recent findings to offer an exhaustive analysis of its performance benefits. 10 | 11 | --- 12 | 13 | ## 2. Architectural Innovations and Design Enhancements 14 | 15 | ### 2.1. New Blackwell Architecture 16 | 17 | - **Key Features:** 18 | - Integration of 5th Generation Tensor Cores and 4th Generation RT Cores. 19 | - Adoption of GDDR7 memory (up to 32GB in flagship models), offering up to 1792 GB/sec bandwidth. 20 | - Enhanced AI driven features with DLSS 4's Multi Frame Generation technology that utilizes a novel transformer model and an integrated AI management processor (AMP based on RISC-V). 21 | 22 | ### 2.2. Process Node Evolution 23 | 24 | - Although the physical node change from TSMC N4 to N4P only provides a ~5% improvement, this modest uplift is compensated with significant architectural tweaks such as: 25 | - Increased number of CUDA cores (up to 33% more in some instances compared to the RTX 4090). 26 | - Advanced power distribution management via a 30-phase VRM design in flagship models (e.g., the RTX 5090 Founders Edition). 27 | 28 | ### 2.3. PCB and Cooling Innovations 29 | 30 | - **Compact Two-Slot Design:** 31 | - Despite increased power envelopes (e.g., RTX 5090’s 575W vs. RTX 4090’s 450W), the engineering team managed to design a dense PCB that maintains a 2-slot footprint. 32 | 33 | - **Enhanced Thermal Management:** 34 | - Implementation of dual flow-through cooling systems with liquid metal and triple-walled gaskets resulted in peak temperatures stabilized around 72°C (with even the flagship RTX 5090 successfully operating under heavy 4K loads). 35 | - Advanced measures like vapor-chambers and premium phase-change thermal pads further ensure that thermal-efficiency is maintained even under high power draw conditions. 36 | 37 | - **Acoustic Engineering:** 38 | - Despite the higher TDP and increased power consumption (e.g., idle power draw for the RTX 5090 is 46W compared to 28–29W for the RTX 4090), acoustic performance is optimized to around 32.5 dBA at 1 meter via targeted airflow and noise reduction strategies. 39 | 40 | --- 41 | 42 | ## 3. Gaming Performance Benchmarks 43 | 44 | The primary focus being gaming performance, this section incorporates multiple performance metrics and independent benchmarks from both synthetic tests (such as Blender and 3DMark) and popular gaming titles like Resident Evil 4, Horizon Forbidden West, Cyberpunk 2077, and Final Fantasy XVI. 45 | 46 | ### 3.1. Relative Performance Gains Over Previous Generations 47 | 48 | - **RTX 5090:** 49 | - Delivers roughly 30–35% higher performance than the RTX 4090 in pure 4K, non-ray tracing gaming. 50 | - Offers 20–50% improvements in average frame rates across diverse gaming titles. 51 | - Demonstrates a 32% improvement in ray tracing performance alongside up to a two-fold increase in performance in specific titles. 52 | - Trade-off: Elevated power draw (575W) necessitates scrutinizing efficiency and overall FPS-per-watt metrics. 53 | 54 | - **RTX 5080 and RTX 5070-Ti:** 55 | - The RTX 5080 shows about a 15% performance uplift (both in rasterization and in ray tracing tasks) relative to the previous generation’s 4080-Super series. 56 | - The RTX 5070-Ti positions itself as a best-value proposition for gamers by delivering approximately 20% higher performance than the older 4070-Ti-Super at a lower price point ($749.99) while boasting 16GB VRAM, making it particularly effective for high-resolution gaming. 57 | 58 | ### 3.2. Technical Specifications and Numbers 59 | 60 | Table below summarizes the key specifications and performance benchmarks for representative models in the series: 61 | 62 | | Model | CUDA Cores | Boost Clock (GHz) | TGP (W) | Memory Configuration & Bandwidth | Performance Gains vs. Predecessor | 63 | |-----------------|------------|-------------------|---------|--------------------------------------------------|-----------------------------------------| 64 | | RTX 5090 | 21,760+ | Higher (e.g., ~2.62 GHz similar or above) | 575 | 32GB GDDR7, 512-bit, up to 1792 GB/sec | ~30–35% (raster), 27–35% (RT), significant DLSS gains | 65 | | RTX 5080 | 10,752 | 2.62 | 360 | High-bandwidth GDDR7 | Roughly 15–20% higher FPS in 4K gaming | 66 | | RTX 5070-Ti | 8,960 | 2.45 | 300 | 16GB VRAM, GDDR7 | ~20% gain over 4070-Ti-Super | 67 | 68 | These improvements are driven by higher core counts, enhanced architectural features, and tailored driver optimizations that have addressed frametime issues previously seen in titles like Alan Wake 2. 69 | 70 | --- 71 | 72 | ## 4. AI and Upscaling Technologies 73 | 74 | ### 4.1. DLSS 4 Multi Frame Generation 75 | 76 | - **Revolutionizing Frame Rates:** 77 | - DLSS 4 leverages a transformer-based model combined with the inbuilt RISC-V based AMP to deliver enhanced multi-frame generation. 78 | - This technology can boost performance by up to 40% in demanding, ray-traced scenes and even multiply frame rates by as much as 8X compared to traditional rendering methods. 79 | 80 | ### 4.2. NVIDIA Reflex 2 81 | 82 | - **Latency Reduction:** 83 | - NVIDIA Reflex 2 technology slashes input latency by up to 75%, ensuring a smoother and more responsive gaming experience, particularly in competitive gaming scenarios. 84 | 85 | ### 4.3. Integration with AI-Driven Content Creation 86 | 87 | - While the primary focus here is gaming, it is important to note that these AI enhancements also accelerate creative workloads, making the RTX 5000 series a versatile choice for AI research and content production. 88 | 89 | --- 90 | 91 | ## 5. Power Efficiency and Thermal Performance Considerations 92 | 93 | ### 5.1. Power Consumption Trade-offs 94 | 95 | - The series, particularly the RTX 5090, sees significant increases in power draw (e.g., idle and load differences such as 46W idle power compared to 29W for the RTX 4090). The increase in power is justified by the raw performance gains but does come with questions regarding overall efficiency, especially in FPS-per-watt metrics. 96 | 97 | ### 5.2. Thermal Efficiency Advances 98 | 99 | - **Innovative Cooling Techniques:** As outlined earlier, advanced cooling methods are crucial for stable performance at high power loads. The full flow-through cooling system ensures that despite the high TDP (up to 575W for the RTX 5090), steady-state operational temperatures remain near 72–77°C. 100 | 101 | - **Memory Thermal Characteristics:** Although the GPU core temperatures are well-managed, memory temperatures can occasionally peak up to 89–90°C under strenuous gaming loads, prompting further investigation into long-term memory reliability under prolonged usage conditions. 102 | 103 | --- 104 | 105 | ## 6. Comparative Analysis with Predecessor and Competitor Products 106 | 107 | ### 6.1. Comparisons with Previous RTX Series Models 108 | 109 | - **RTX 5000 vs. RTX 4000 Series:** 110 | - The RTX 5000 series shows a marked performance uplift across the board. For instance, while the RTX 5090 pushes around 30–35% performance improvements, the RTX 5080 and 5070-Ti deliver gains of 15% and 20% over the 4080-Super and 4070-Ti-Super, respectively. 111 | - The driver optimizations and thermal management technologies in the RTX 5000 series have also resolved issues seen in earlier generations (such as inconsistencies in frametime performance in certain titles). 112 | 113 | ### 6.2. Competitive Dynamics with AMD’s RX 9000 Series 114 | 115 | - **AMD’s Positioning:** 116 | - Although AMD is rumored to be withdrawing from the ultra-high-end market, the RX 9000 series, exemplified by the RX 9070XT (with 16GB of VRAM), shows competitive pressure. Leaked 3DMark numbers indicate performance figures close to the RTX 5070 series, emphasizing raw performance metrics in 4K gaming. 117 | - Differences in memory configuration (GDDR6 for AMD vs. GDDR7 for NVIDIA) and architectural paradigms (RDNA 4 vs. Blackwell) make efficiency and performance trade-offs a key battleground. 118 | 119 | - **Strategic Considerations:** 120 | - NVIDIA’s aggressive product segmentation, with pricing ranging from about $549 for lower-end models (e.g., RTX 5060) to nearly $2,000 for flagship variants (RTX 5090 Founders Edition), contrasts with AMD’s mid-range focus. This segmentation not only influences immediate gaming performance metrics but also longer-term upgrade cycles and market dynamics. 121 | 122 | --- 123 | 124 | ## 7. Market Impact, Value Trade-offs, and Future Outlook 125 | 126 | ### 7.1. Pricing Dynamics and Consumer Sentiment 127 | 128 | - **Premium Pricing Concerns:** 129 | - The RTX 5090 is priced around $1,999.99 compared to the RTX 4090 at $1,599.99. Although this represents a 25% higher price point, the performance boost (around 30–35%) may justify the extra cost for gamers demanding uncompromised 4K and ray-traced performance. 130 | 131 | - **Value Proposition of the RTX 5070-Ti:** 132 | - At approximately $749.99 with 16GB VRAM, the RTX 5070-Ti emerges as a clear best-value option for high-resolution gaming. Its competitive pricing relative to its performance makes it attractive for gamers who balance performance with cost efficiency. 133 | 134 | - **Consumer Debates:** 135 | - Forum discussions and expert reviews reveal a divided community, with some criticisms over aggressive segmentation and high flagship pricing, while others commend the tailored use cases such as AI-enhanced gaming and professional creative workflows. 136 | 137 | ### 7.2. Future Technological Projections and Speculative Trends 138 | 139 | - **Improved Driver Optimizations:** 140 | - Continued refinement in driver updates (addressing issues such as frametime inconsistencies) can further enhance performance in real-world gaming scenarios. 141 | 142 | - **Potential New Technologies:** 143 | - Future iterations might explore even more efficient power scaling and cooling optimizations, perhaps integrating improved liquid cooling or hybrid passive-active cooling mechanisms to further lower the thermal footprint. 144 | - Given the competitive dynamics, both NVIDIA and AMD may drive innovations around VRAM management and efficiency, which could significantly impact future pricing and segmentation strategies. 145 | 146 | - **AI and Upscaling Evolution:** 147 | - DLSS and AI-based rendering technologies are likely to become even more integral to gaming performance enhancements, with potential upcoming improvements focusing on reducing latency further and increasing real-time fidelity. 148 | 149 | --- 150 | 151 | ## 8. Conclusion 152 | 153 | The RTX 5000 series represents a robust and innovative leap in gaming GPU technology. Key takeaways include: 154 | 155 | - **Substantial Performance Increases:** A clear generational improvement over previous RTX models with substantial enhancements in 4K gaming, ray tracing, and AI-driven rendering. 156 | 157 | - **Innovative Architecture and Thermal Design:** The Blackwell architecture combined with advanced cooling solutions enables such high performance while mitigating thermal concerns typically associated with higher TDP values. 158 | 159 | - **Competitive Market Positioning:** NVIDIA’s strategy of aggressive segmentation and comprehensive performance gains reinforces its position, even as AMD’s RX 9000 series introduces competitive pressure in the mid-range segment. 160 | 161 | - **Trade-offs in Efficiency:** The significant improvements come at the cost of increased power consumption, raising considerations for both energy efficiency and operational heat management under sustained loads. 162 | 163 | This comprehensive analysis, rooted in extensive benchmarking and technical evaluations, should serve as a detailed reference for experts evaluating the RTX 5000 series for high-performance gaming. Future developments in AI rendering and thermal management are expected to further refine these impressive performance metrics, while competitive dynamics will continue to push the envelope in GPU technology. 164 | 165 | --- 166 | 167 | *Note: Some projections and speculations in this report are based on emerging trends and early benchmarking data. Continued monitoring of real-world performance and driver updates is recommended for an ongoing evaluation.* 168 | 169 | 170 | # End of Report 171 | 172 | 173 | ## Sources 174 | 175 | - https://www.tomshardware.com/reviews/gpu-hierarchy,4388.html 176 | - https://linustechtips.com/topic/1596724-my-personally-recommended-gpu-from-rtx-5000-series/ 177 | - https://www.forbes.com/sites/moorinsights/2025/01/23/nvidia-rtx-5090-graphics-card-review---get-neural-or-get-left-behind/ 178 | - https://www.neogaf.com/threads/nvidia-official-geforce-rtx-50-vs-rtx-40-benchmarks-15-to-33-performance-uplift-without-dlss-multi-frame-generation.1679651/ 179 | - https://pcoutlet.com/parts/video-cards/rtx-5070-ti-vs-rtx-5080-which-gpu-reigns-supreme 180 | - https://www.kitguru.net/components/graphic-cards/dominic-moass/nvidia-rtx-5080-review-efficiency-gains-but-a-performance-letdown/all/1/ 181 | - https://forums.pcgamer.com/threads/rtx-5000-series-review-discussion.147293/ 182 | - https://www.techradar.com/computing/gpu/nvidias-new-next-gen-gpu-benchmarks-cause-concern-among-pc-gamers-particularly-with-the-rtx-5080-but-dont-panic-yet 183 | - https://www.vcsolutions.com/blog/nvidia-rtx-5000-series-performance-unveiled/ 184 | - https://gamersnexus.net/gpus/nvidia-geforce-rtx-5090-founders-edition-review-benchmarks-gaming-thermals-power 185 | - https://www.tomshardware.com/pc-components/gpus/nvidia-geforce-rtx-5090-review 186 | - https://www.nvidia.com/en-us/geforce/news/rtx-50-series-graphics-cards-gpu-laptop-announcements/ 187 | - https://pcoutlet.com/parts/video-cards/nvidia-rtx-5000-series 188 | - https://press.asus.com/news/press-releases/asus-nvidia-geforce-rtx-50-series-graphics-cards/ 189 | - https://galaxy.ai/youtube-summarizer/the-challenges-facing-nvidias-rtx-5000-series-and-amds-rx-8000-cards-VHQkBdeXzT0 190 | - https://www.xda-developers.com/nvidia-rtx-5000-not-what-you-think/ 191 | - https://hardwarehunt.co.uk/blogs/pc-building-maintenance/amd-vs-nvidia-the-battle-between-radeon-rx-9000-and-rtx-5000?srsltid=AfmBOorJ59FR_9WsA8ol-7k9g_jPvGbbYgFK1MzbvOwRS05HQO8JdjoZ 192 | - https://hardforum.com/threads/2025-nvidia-versus-amd-ati-rematch-5000-versus-9000-series-edition.2038817/ 193 | - https://9meters.com/technology/graphics/nvidia-shows-off-geforce-rtx-5090-fe-pcb-30-phases-of-stable-575w-power 194 | - https://www.technology.org/2025/01/20/nvidias-rtx-5090-a-technological-leap-beyond-the-rtx-4090/ -------------------------------------------------------------------------------- /src/ai/providers.ts: -------------------------------------------------------------------------------- 1 | import { createOpenAI } from '@ai-sdk/openai'; 2 | import { getEncoding } from 'js-tiktoken'; 3 | 4 | import { RecursiveCharacterTextSplitter } from './text-splitter.js'; 5 | 6 | 7 | // Providers 8 | 9 | const openai = createOpenAI({ 10 | apiKey: process.env.OPENAI_KEY!, 11 | }); 12 | 13 | // Models 14 | 15 | export const gpt4Model = openai('gpt-4o', { 16 | structuredOutputs: true, 17 | }); 18 | export const gpt4MiniModel = openai('gpt-4o-mini', { 19 | structuredOutputs: true, 20 | }); 21 | export const o3MiniModel = openai('o3-mini', { 22 | reasoningEffort: 'medium', 23 | structuredOutputs: true, 24 | }); 25 | 26 | const MinChunkSize = 140; 27 | const encoder = getEncoding('o200k_base'); 28 | 29 | // trim prompt to maximum context size 30 | export function trimPrompt(prompt: string, contextSize = 120_000) { 31 | if (!prompt) { 32 | return ''; 33 | } 34 | 35 | const length = encoder.encode(prompt).length; 36 | if (length <= contextSize) { 37 | return prompt; 38 | } 39 | 40 | const overflowTokens = length - contextSize; 41 | // on average it's 3 characters per token, so multiply by 3 to get a rough estimate of the number of characters 42 | const chunkSize = prompt.length - overflowTokens * 3; 43 | if (chunkSize < MinChunkSize) { 44 | return prompt.slice(0, MinChunkSize); 45 | } 46 | 47 | const splitter = new RecursiveCharacterTextSplitter({ 48 | chunkSize, 49 | chunkOverlap: 0, 50 | }); 51 | const trimmedPrompt = splitter.splitText(prompt)[0] ?? ''; 52 | 53 | // last catch, there's a chance that the trimmed prompt is same length as the original prompt, due to how tokens are split & innerworkings of the splitter, handle this case by just doing a hard cut 54 | if (trimmedPrompt.length === prompt.length) { 55 | return trimPrompt(prompt.slice(0, chunkSize), contextSize); 56 | } 57 | 58 | // recursively trim until the prompt is within the context size 59 | return trimPrompt(trimmedPrompt, contextSize); 60 | } 61 | -------------------------------------------------------------------------------- /src/ai/text-splitter.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert'; 2 | import { describe, it } from 'node:test'; 3 | 4 | import { RecursiveCharacterTextSplitter } from './text-splitter.js'; 5 | 6 | describe('RecursiveCharacterTextSplitter', () => { 7 | it('Should correctly split text by separators', () => { 8 | const splitter = new RecursiveCharacterTextSplitter({ 9 | chunkSize: 50, 10 | chunkOverlap: 10, 11 | }); 12 | assert.deepEqual( 13 | splitter.splitText( 14 | 'Hello world, this is a test of the recursive text splitter.', 15 | ), 16 | ['Hello world', 'this is a test of the recursive text splitter'], 17 | ); 18 | 19 | splitter.chunkSize = 100; 20 | assert.deepEqual( 21 | splitter.splitText( 22 | 'Hello world, this is a test of the recursive text splitter. If I have a period, it should split along the period.', 23 | ), 24 | [ 25 | 'Hello world, this is a test of the recursive text splitter', 26 | 'If I have a period, it should split along the period.', 27 | ], 28 | ); 29 | 30 | splitter.chunkSize = 110; 31 | assert.deepEqual( 32 | splitter.splitText( 33 | 'Hello world, this is a test of the recursive text splitter. If I have a period, it should split along the period.\nOr, if there is a new line, it should prioritize splitting on new lines instead.', 34 | ), 35 | [ 36 | 'Hello world, this is a test of the recursive text splitter', 37 | 'If I have a period, it should split along the period.', 38 | 'Or, if there is a new line, it should prioritize splitting on new lines instead.', 39 | ], 40 | ); 41 | }); 42 | 43 | it('Should handle empty string', () => { 44 | const splitter = new RecursiveCharacterTextSplitter({ 45 | chunkSize: 50, 46 | chunkOverlap: 10, 47 | }); 48 | assert.deepEqual(splitter.splitText(''), []); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /src/ai/text-splitter.ts: -------------------------------------------------------------------------------- 1 | interface TextSplitterParams { 2 | chunkSize: number; 3 | 4 | chunkOverlap: number; 5 | } 6 | 7 | abstract class TextSplitter implements TextSplitterParams { 8 | chunkSize = 1000; 9 | chunkOverlap = 200; 10 | 11 | constructor(fields?: Partial) { 12 | this.chunkSize = fields?.chunkSize ?? this.chunkSize; 13 | this.chunkOverlap = fields?.chunkOverlap ?? this.chunkOverlap; 14 | if (this.chunkOverlap >= this.chunkSize) { 15 | throw new Error('Cannot have chunkOverlap >= chunkSize'); 16 | } 17 | } 18 | 19 | abstract splitText(text: string): string[]; 20 | 21 | createDocuments(texts: string[]): string[] { 22 | const documents: string[] = []; 23 | for (let i = 0; i < texts.length; i += 1) { 24 | const text = texts[i]; 25 | for (const chunk of this.splitText(text!)) { 26 | documents.push(chunk); 27 | } 28 | } 29 | return documents; 30 | } 31 | 32 | splitDocuments(documents: string[]): string[] { 33 | return this.createDocuments(documents); 34 | } 35 | 36 | private joinDocs(docs: string[], separator: string): string | null { 37 | const text = docs.join(separator).trim(); 38 | return text === '' ? null : text; 39 | } 40 | 41 | mergeSplits(splits: string[], separator: string): string[] { 42 | const docs: string[] = []; 43 | const currentDoc: string[] = []; 44 | let total = 0; 45 | for (const d of splits) { 46 | const _len = d.length; 47 | if (total + _len >= this.chunkSize) { 48 | if (total > this.chunkSize) { 49 | console.warn( 50 | `Created a chunk of size ${total}, + 51 | which is longer than the specified ${this.chunkSize}`, 52 | ); 53 | } 54 | if (currentDoc.length > 0) { 55 | const doc = this.joinDocs(currentDoc, separator); 56 | if (doc !== null) { 57 | docs.push(doc); 58 | } 59 | // Keep on popping if: 60 | // - we have a larger chunk than in the chunk overlap 61 | // - or if we still have any chunks and the length is long 62 | while ( 63 | total > this.chunkOverlap || 64 | (total + _len > this.chunkSize && total > 0) 65 | ) { 66 | total -= currentDoc[0]!.length; 67 | currentDoc.shift(); 68 | } 69 | } 70 | } 71 | currentDoc.push(d); 72 | total += _len; 73 | } 74 | const doc = this.joinDocs(currentDoc, separator); 75 | if (doc !== null) { 76 | docs.push(doc); 77 | } 78 | return docs; 79 | } 80 | } 81 | 82 | export interface RecursiveCharacterTextSplitterParams 83 | extends TextSplitterParams { 84 | separators: string[]; 85 | } 86 | 87 | export class RecursiveCharacterTextSplitter 88 | extends TextSplitter 89 | implements RecursiveCharacterTextSplitterParams 90 | { 91 | separators: string[] = ['\n\n', '\n', '.', ',', '>', '<', ' ', '']; 92 | 93 | constructor(fields?: Partial) { 94 | super(fields); 95 | this.separators = fields?.separators ?? this.separators; 96 | } 97 | 98 | splitText(text: string): string[] { 99 | const finalChunks: string[] = []; 100 | 101 | // Get appropriate separator to use 102 | let separator: string = this.separators[this.separators.length - 1]!; 103 | for (const s of this.separators) { 104 | if (s === '') { 105 | separator = s; 106 | break; 107 | } 108 | if (text.includes(s)) { 109 | separator = s; 110 | break; 111 | } 112 | } 113 | 114 | // Now that we have the separator, split the text 115 | let splits: string[]; 116 | if (separator) { 117 | splits = text.split(separator); 118 | } else { 119 | splits = text.split(''); 120 | } 121 | 122 | // Now go merging things, recursively splitting longer texts. 123 | let goodSplits: string[] = []; 124 | for (const s of splits) { 125 | if (s.length < this.chunkSize) { 126 | goodSplits.push(s); 127 | } else { 128 | if (goodSplits.length) { 129 | const mergedText = this.mergeSplits(goodSplits, separator); 130 | finalChunks.push(...mergedText); 131 | goodSplits = []; 132 | } 133 | const otherInfo = this.splitText(s); 134 | finalChunks.push(...otherInfo); 135 | } 136 | } 137 | if (goodSplits.length) { 138 | const mergedText = this.mergeSplits(goodSplits, separator); 139 | finalChunks.push(...mergedText); 140 | } 141 | return finalChunks; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/api/middleware/auth.ts: -------------------------------------------------------------------------------- 1 | import { getAuth } from '@clerk/express'; 2 | import { Request, Response, NextFunction } from 'express'; 3 | 4 | export const validateApiKey = (req: Request, res: Response, next: NextFunction): void => { 5 | const apiKey = req.headers['x-api-key']; 6 | const validApiKey = process.env.API_KEY; 7 | const auth = getAuth(req); 8 | 9 | // Check for API key authentication 10 | if (apiKey) { 11 | if (!validApiKey) { 12 | console.error('API_KEY is not set in environment variables'); 13 | res.status(500).json({ error: 'Server configuration error' }); 14 | return; 15 | } 16 | 17 | if (apiKey !== validApiKey) { 18 | res.status(403).json({ error: 'Invalid API key' }); 19 | return; 20 | } 21 | 22 | return next(); 23 | } 24 | 25 | // Check for Clerk authentication 26 | if (auth.userId) {; 27 | return next(); 28 | } 29 | 30 | // Neither authentication method is valid 31 | res.status(401).json({ error: 'Unauthorized - Provide either a valid API key or Clerk session token' }); 32 | }; -------------------------------------------------------------------------------- /src/api/server.ts: -------------------------------------------------------------------------------- 1 | import express, { Request, Response, NextFunction, RequestHandler } from 'express'; 2 | import cors from 'cors'; 3 | import swaggerUi from 'swagger-ui-express'; 4 | import { deepResearch, writeFinalReport } from '../deep-research.js'; 5 | import { specs } from './swagger.js'; 6 | import { validateApiKey } from './middleware/auth.js'; 7 | import dotenv from 'dotenv'; 8 | import { generateFeedback, FeedbackResult } from '../feedback.js'; 9 | import { clerkMiddleware } from '@clerk/express' 10 | 11 | dotenv.config(); 12 | 13 | const app = express(); 14 | const port = process.env.PORT || 3000; 15 | 16 | // Middleware 17 | app.use( 18 | cors({ 19 | origin: [ 20 | 'https://app.codeguide.dev', 21 | 'http://localhost:3000', 22 | 'http://localhost:3001', 23 | ], 24 | methods: ['GET', 'POST'], 25 | allowedHeaders: ['Content-Type', 'Authorization', 'x-api-key'], 26 | }), 27 | ); 28 | 29 | app.use(express.json()); 30 | app.use(clerkMiddleware()) 31 | 32 | // Swagger UI 33 | app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs)); 34 | 35 | // Types 36 | interface ResearchQuestionsRequest { 37 | query: string; 38 | numQuestions?: number; 39 | } 40 | 41 | interface ResearchRequest { 42 | query: string; 43 | breadth: number; 44 | depth: number; 45 | firecrawlKey?: string; 46 | questionAnswers?: { question: string; answer: string }[]; 47 | } 48 | 49 | interface ReportRequest { 50 | prompt: string; 51 | learnings: string[]; 52 | visitedUrls: string[]; 53 | } 54 | 55 | // Error handler middleware 56 | const errorHandler = (err: Error, req: Request, res: Response, next: NextFunction): void => { 57 | console.error(err.stack); 58 | res.status(500).json({ error: 'Something went wrong!' }); 59 | }; 60 | 61 | /** 62 | * @swagger 63 | * /api/research/questions: 64 | * post: 65 | * summary: Generate clarifying questions for research query 66 | * description: First step in the research process - generates questions to better understand the research direction 67 | * tags: [Research] 68 | * security: 69 | * - ApiKeyAuth: [] 70 | * - BearerAuth: [] 71 | * requestBody: 72 | * required: true 73 | * content: 74 | * application/json: 75 | * schema: 76 | * $ref: '#/components/schemas/ResearchQuestionsRequest' 77 | * responses: 78 | * 200: 79 | * description: Generated clarifying questions 80 | * content: 81 | * application/json: 82 | * schema: 83 | * $ref: '#/components/schemas/ResearchQuestionsResponse' 84 | * 400: 85 | * description: Missing or invalid parameters 86 | * 401: 87 | * description: API key is missing 88 | * 403: 89 | * description: Invalid API key 90 | * 500: 91 | * description: Server error 92 | */ 93 | const handleResearchQuestions: RequestHandler = async (req, res, next) => { 94 | try { 95 | const { query, numQuestions } = req.body as ResearchQuestionsRequest; 96 | 97 | if (!query) { 98 | res.status(400).json({ error: 'Missing required parameters' }); 99 | return; 100 | } 101 | 102 | const result: FeedbackResult = await generateFeedback({ 103 | query, 104 | numQuestions 105 | }); 106 | 107 | res.json(result); 108 | } catch (error) { 109 | console.error('Research questions generation error:', error); 110 | next(error); 111 | } 112 | }; 113 | 114 | /** 115 | * @swagger 116 | * /api/research: 117 | * post: 118 | * summary: Perform deep research on a given query 119 | * tags: [Research] 120 | * security: 121 | * - ApiKeyAuth: [] 122 | * - BearerAuth: [] 123 | * requestBody: 124 | * required: true 125 | * content: 126 | * application/json: 127 | * schema: 128 | * $ref: '#/components/schemas/ResearchRequest' 129 | * responses: 130 | * 200: 131 | * description: Research results 132 | * content: 133 | * application/json: 134 | * schema: 135 | * $ref: '#/components/schemas/ResearchResponse' 136 | * 400: 137 | * description: Missing or invalid parameters 138 | * content: 139 | * application/json: 140 | * schema: 141 | * $ref: '#/components/schemas/Error' 142 | * 401: 143 | * description: API key is missing 144 | * content: 145 | * application/json: 146 | * schema: 147 | * $ref: '#/components/schemas/Error' 148 | * 403: 149 | * description: Invalid API key 150 | * content: 151 | * application/json: 152 | * schema: 153 | * $ref: '#/components/schemas/Error' 154 | * 500: 155 | * description: Server error 156 | * content: 157 | * application/json: 158 | * schema: 159 | * $ref: '#/components/schemas/Error' 160 | */ 161 | const handleResearch: RequestHandler = async (req, res, next) => { 162 | try { 163 | const { query, breadth, depth, questionAnswers, firecrawlKey } = req.body as ResearchRequest; 164 | 165 | if (!query || !breadth || !depth) { 166 | res.status(400).json({ error: 'Missing required parameters' }); 167 | return; 168 | } 169 | 170 | // If we have question answers, append them to the query 171 | let enhancedQuery = query; 172 | if (questionAnswers && questionAnswers.length > 0) { 173 | const answersText = questionAnswers 174 | .map(qa => `${qa.question}\nAnswer: ${qa.answer}`) 175 | .join('\n\n'); 176 | enhancedQuery = `${query}\n\nAdditional Context:\n${answersText}`; 177 | } 178 | 179 | const result = await deepResearch({ 180 | query: enhancedQuery, 181 | breadth, 182 | depth, 183 | firecrawlKey 184 | }); 185 | 186 | res.json(result); 187 | } catch (error) { 188 | console.error('Research error:', error); 189 | next(error); 190 | } 191 | }; 192 | 193 | /** 194 | * @swagger 195 | * /api/report: 196 | * post: 197 | * summary: Generate a report from research findings 198 | * tags: [Report] 199 | * security: 200 | * - ApiKeyAuth: [] 201 | * - BearerAuth: [] 202 | * requestBody: 203 | * required: true 204 | * content: 205 | * application/json: 206 | * schema: 207 | * $ref: '#/components/schemas/ReportRequest' 208 | * responses: 209 | * 200: 210 | * description: Generated report 211 | * content: 212 | * application/json: 213 | * schema: 214 | * $ref: '#/components/schemas/ReportResponse' 215 | * 400: 216 | * description: Missing or invalid parameters 217 | * content: 218 | * application/json: 219 | * schema: 220 | * $ref: '#/components/schemas/Error' 221 | * 401: 222 | * description: API key is missing 223 | * content: 224 | * application/json: 225 | * schema: 226 | * $ref: '#/components/schemas/Error' 227 | * 403: 228 | * description: Invalid API key 229 | * content: 230 | * application/json: 231 | * schema: 232 | * $ref: '#/components/schemas/Error' 233 | * 500: 234 | * description: Server error 235 | * content: 236 | * application/json: 237 | * schema: 238 | * $ref: '#/components/schemas/Error' 239 | */ 240 | const handleReport: RequestHandler = async (req, res, next) => { 241 | try { 242 | const { prompt, learnings, visitedUrls } = req.body as ReportRequest; 243 | 244 | if (!prompt || !learnings || !visitedUrls) { 245 | res.status(400).json({ error: 'Missing required parameters' }); 246 | return; 247 | } 248 | 249 | const result = await writeFinalReport({ 250 | prompt, 251 | learnings, 252 | visitedUrls 253 | }); 254 | 255 | res.json({ 256 | report: result.reportMarkdown, 257 | usage: result.usage, 258 | }); 259 | } catch (error) { 260 | console.error('Report generation error:', error); 261 | next(error); 262 | } 263 | }; 264 | 265 | /** 266 | * @swagger 267 | * /health: 268 | * get: 269 | * summary: Check API health status 270 | * tags: [Health] 271 | * responses: 272 | * 200: 273 | * description: API is healthy 274 | * content: 275 | * application/json: 276 | * schema: 277 | * type: object 278 | * properties: 279 | * status: 280 | * type: string 281 | * example: ok 282 | */ 283 | app.get('/health', (_req: Request, res: Response) => { 284 | res.json({ status: 'ok' }); 285 | }); 286 | 287 | // Register routes 288 | app.post('/api/research/questions', validateApiKey, handleResearchQuestions); 289 | app.post('/api/research', validateApiKey, handleResearch); 290 | app.post('/api/report', validateApiKey, handleReport); 291 | 292 | // Error handler 293 | app.use(errorHandler); 294 | 295 | // Start server 296 | app.listen(port, () => { 297 | console.log(`Server is running on port ${port}`); 298 | console.log(`API documentation available at http://localhost:${port}/api-docs`); 299 | }); -------------------------------------------------------------------------------- /src/api/swagger.ts: -------------------------------------------------------------------------------- 1 | import swaggerJsdoc from 'swagger-jsdoc'; 2 | 3 | const options: swaggerJsdoc.Options = { 4 | definition: { 5 | openapi: '3.0.0', 6 | info: { 7 | title: 'Deep Research API', 8 | version: '1.0.0', 9 | description: 'API for performing deep research and generating reports', 10 | contact: { 11 | name: 'API Support', 12 | url: 'https://github.com/yourusername/deep-research' 13 | } 14 | }, 15 | servers: [ 16 | { 17 | url: 'http://localhost:3000', 18 | description: 'Development server' 19 | } 20 | ], 21 | components: { 22 | securitySchemes: { 23 | ApiKeyAuth: { 24 | type: 'apiKey', 25 | in: 'header', 26 | name: 'x-api-key', 27 | description: 'API key for authentication' 28 | }, 29 | BearerAuth: { 30 | type: 'http', 31 | scheme: 'bearer', 32 | bearerFormat: 'JWT', 33 | description: 'Clerk session token' 34 | } 35 | }, 36 | schemas: { 37 | ResearchRequest: { 38 | type: 'object', 39 | required: ['query', 'breadth', 'depth'], 40 | properties: { 41 | query: { 42 | type: 'string', 43 | description: 'The research query to process' 44 | }, 45 | breadth: { 46 | type: 'number', 47 | description: 'Number of parallel search queries to generate' 48 | }, 49 | depth: { 50 | type: 'number', 51 | description: 'Depth of the recursive research process' 52 | }, 53 | firecrawlKey: { 54 | type: 'string', 55 | description: 'Optional Firecrawl API key. If not provided, will use the server\'s default key' 56 | }, 57 | questionAnswers: { 58 | type: 'array', 59 | items: { 60 | type: 'object', 61 | properties: { 62 | question: { 63 | type: 'string', 64 | description: 'The feedback question' 65 | }, 66 | answer: { 67 | type: 'string', 68 | description: 'The user\'s answer to the feedback question' 69 | } 70 | } 71 | }, 72 | description: 'Optional answers to feedback questions' 73 | } 74 | } 75 | }, 76 | ResearchResponse: { 77 | type: 'object', 78 | properties: { 79 | learnings: { 80 | type: 'array', 81 | items: { 82 | type: 'string' 83 | }, 84 | description: 'List of learnings from the research' 85 | }, 86 | visitedUrls: { 87 | type: 'array', 88 | items: { 89 | type: 'string' 90 | }, 91 | description: 'List of URLs visited during research' 92 | } 93 | } 94 | }, 95 | ReportRequest: { 96 | type: 'object', 97 | required: ['prompt', 'learnings', 'visitedUrls'], 98 | properties: { 99 | prompt: { 100 | type: 'string', 101 | description: 'The prompt for generating the report' 102 | }, 103 | learnings: { 104 | type: 'array', 105 | items: { 106 | type: 'string' 107 | }, 108 | description: 'List of learnings to include in the report' 109 | }, 110 | visitedUrls: { 111 | type: 'array', 112 | items: { 113 | type: 'string' 114 | }, 115 | description: 'List of URLs used as sources' 116 | } 117 | } 118 | }, 119 | ReportResponse: { 120 | type: 'object', 121 | properties: { 122 | report: { 123 | type: 'string', 124 | description: 'Generated report in Markdown format' 125 | } 126 | } 127 | }, 128 | Error: { 129 | type: 'object', 130 | properties: { 131 | error: { 132 | type: 'string', 133 | description: 'Error message' 134 | } 135 | } 136 | }, 137 | ResearchQuestionsRequest: { 138 | type: 'object', 139 | required: ['query'], 140 | properties: { 141 | query: { 142 | type: 'string', 143 | description: 'The research query to generate clarifying questions for' 144 | }, 145 | numQuestions: { 146 | type: 'number', 147 | description: 'Optional number of questions to generate (default: 3)' 148 | } 149 | } 150 | }, 151 | ResearchQuestionsResponse: { 152 | type: 'object', 153 | properties: { 154 | questions: { 155 | type: 'array', 156 | items: { 157 | type: 'string' 158 | }, 159 | description: 'List of generated clarifying questions' 160 | } 161 | } 162 | } 163 | } 164 | }, 165 | security: [ 166 | { 167 | ApiKeyAuth: [] 168 | }, 169 | { 170 | BearerAuth: [] 171 | } 172 | ] 173 | }, 174 | apis: ['./src/api/server.ts'] 175 | }; 176 | 177 | export const specs = swaggerJsdoc(options); -------------------------------------------------------------------------------- /src/deep-research.ts: -------------------------------------------------------------------------------- 1 | import FirecrawlApp, { SearchResponse } from '@mendable/firecrawl-js'; 2 | import { generateObject } from 'ai'; 3 | import { compact } from 'lodash-es'; 4 | import pLimit from 'p-limit'; 5 | import { z } from 'zod'; 6 | 7 | import dotenv from 'dotenv'; 8 | 9 | dotenv.config(); 10 | 11 | import { o3MiniModel, trimPrompt } from './ai/providers.js'; 12 | import { systemPrompt } from './prompt.js'; 13 | 14 | 15 | type ResearchResult = { 16 | learnings: string[]; 17 | visitedUrls: string[]; 18 | usage: { 19 | totalTokens: number; 20 | promptTokens: number; 21 | completionTokens: number; 22 | }; 23 | }; 24 | 25 | // increase this if you have higher API rate limits 26 | const ConcurrencyLimit = 2; 27 | 28 | // Initialize Firecrawl with optional API key and optional base url 29 | 30 | const firecrawl = new FirecrawlApp({ 31 | apiKey: process.env.FIRECRAWL_KEY ?? '', 32 | apiUrl: process.env.FIRECRAWL_BASE_URL, 33 | }); 34 | 35 | // take en user query, return a list of SERP queries 36 | async function generateSerpQueries({ 37 | query, 38 | numQueries = 3, 39 | learnings, 40 | }: { 41 | query: string; 42 | numQueries?: number; 43 | 44 | // optional, if provided, the research will continue from the last learning 45 | learnings?: string[]; 46 | }) { 47 | const res = await generateObject({ 48 | model: o3MiniModel, 49 | system: systemPrompt(), 50 | prompt: `Given the following prompt from the user, generate a list of SERP queries to research the topic. Return a maximum of ${numQueries} queries, but feel free to return less if the original prompt is clear. Make sure each query is unique and not similar to each other: ${query}\n\n${learnings 51 | ? `Here are some learnings from previous research, use them to generate more specific queries: ${learnings.join( 52 | '\n', 53 | )}` 54 | : '' 55 | }`, 56 | schema: z.object({ 57 | queries: z 58 | .array( 59 | z.object({ 60 | query: z.string().describe('The SERP query'), 61 | researchGoal: z 62 | .string() 63 | .describe( 64 | 'First talk about the goal of the research that this query is meant to accomplish, then go deeper into how to advance the research once the results are found, mention additional research directions. Be as specific as possible, especially for additional research directions.', 65 | ), 66 | }), 67 | ) 68 | .describe(`List of SERP queries, max of ${numQueries}`), 69 | }), 70 | }); 71 | console.log( 72 | `Created ${res.object.queries.length} queries`, 73 | res.object.queries, 74 | ); 75 | 76 | return { 77 | queries: res.object.queries.slice(0, numQueries), 78 | usage: res.usage, 79 | }; 80 | } 81 | 82 | async function processSerpResult({ 83 | query, 84 | result, 85 | numLearnings = 3, 86 | numFollowUpQuestions = 3, 87 | }: { 88 | query: string; 89 | result: SearchResponse; 90 | numLearnings?: number; 91 | numFollowUpQuestions?: number; 92 | }) { 93 | const contents = compact(result.data.map(item => item.markdown)).map( 94 | content => trimPrompt(content, 25_000), 95 | ); 96 | console.log(`Ran ${query}, found ${contents.length} contents`); 97 | 98 | const res = await generateObject({ 99 | model: o3MiniModel, 100 | abortSignal: AbortSignal.timeout(60_000), 101 | system: systemPrompt(), 102 | prompt: `Given the following contents from a SERP search for the query ${query}, generate a list of learnings from the contents. Return a maximum of ${numLearnings} learnings, but feel free to return less if the contents are clear. Make sure each learning is unique and not similar to each other. The learnings should be concise and to the point, as detailed and infromation dense as possible. Make sure to include any entities like people, places, companies, products, things, etc in the learnings, as well as any exact metrics, numbers, or dates. The learnings will be used to research the topic further.\n\n${contents 103 | .map(content => `\n${content}\n`) 104 | .join('\n')}`, 105 | schema: z.object({ 106 | learnings: z 107 | .array(z.string()) 108 | .describe(`List of learnings, max of ${numLearnings}`), 109 | followUpQuestions: z 110 | .array(z.string()) 111 | .describe( 112 | `List of follow-up questions to research the topic further, max of ${numFollowUpQuestions}`, 113 | ), 114 | }), 115 | }); 116 | console.log( 117 | `Created ${res.object.learnings.length} learnings`, 118 | res.object.learnings, 119 | ); 120 | 121 | return { 122 | ...res.object, 123 | usage: res.usage, 124 | }; 125 | } 126 | 127 | export async function writeFinalReport({ 128 | prompt, 129 | learnings, 130 | visitedUrls, 131 | }: { 132 | prompt: string; 133 | learnings: string[]; 134 | visitedUrls: string[]; 135 | }) { 136 | const learningsString = trimPrompt( 137 | learnings 138 | .map(learning => `\n${learning}\n`) 139 | .join('\n'), 140 | 150_000, 141 | ); 142 | 143 | const res = await generateObject({ 144 | model: o3MiniModel, 145 | system: systemPrompt(), 146 | prompt: `Given the following prompt from the user, write a final report on the topic using the learnings from research. Make it as as detailed as possible, aim for 3 or more pages, include ALL the learnings from research:\n\n${prompt}\n\nHere are all the learnings from previous research:\n\n\n${learningsString}\n`, 147 | schema: z.object({ 148 | reportMarkdown: z 149 | .string() 150 | .describe('Final report on the topic in Markdown'), 151 | }), 152 | }); 153 | 154 | // Append the visited URLs section to the report 155 | const urlsSection = `\n\n## Sources\n\n${visitedUrls.map(url => `- ${url}`).join('\n')}`; 156 | return { 157 | reportMarkdown: res.object.reportMarkdown + urlsSection, 158 | usage: res.usage, 159 | }; 160 | } 161 | 162 | export async function deepResearch({ 163 | query, 164 | breadth, 165 | depth, 166 | learnings = [], 167 | visitedUrls = [], 168 | firecrawlKey, 169 | }: { 170 | query: string; 171 | breadth: number; 172 | depth: number; 173 | learnings?: string[]; 174 | visitedUrls?: string[]; 175 | firecrawlKey?: string; 176 | }): Promise { 177 | // Create a new Firecrawl instance if a custom key is provided 178 | const client = firecrawlKey ? new FirecrawlApp({ 179 | apiKey: firecrawlKey, 180 | apiUrl: process.env.FIRECRAWL_BASE_URL, 181 | }) : firecrawl; 182 | 183 | const serpQueriesResult = await generateSerpQueries({ 184 | query, 185 | learnings, 186 | numQueries: breadth, 187 | }); 188 | const limit = pLimit(ConcurrencyLimit); 189 | 190 | const promises = serpQueriesResult.queries.map((serpQuery) => { 191 | return limit(async () => { 192 | try { 193 | const result = await client.search(serpQuery.query, { 194 | timeout: 15000, 195 | limit: 5, 196 | scrapeOptions: { formats: ['markdown'] }, 197 | }); 198 | 199 | // Collect URLs from this search 200 | const newUrls = compact(result.data.map(item => item.url)); 201 | const newBreadth = Math.ceil(breadth / 2); 202 | const newDepth = depth - 1; 203 | 204 | const newLearningsResult = await processSerpResult({ 205 | query: serpQuery.query, 206 | result, 207 | numFollowUpQuestions: newBreadth, 208 | }); 209 | const allLearnings = [...learnings, ...newLearningsResult.learnings]; 210 | const allUrls = [...visitedUrls, ...newUrls]; 211 | 212 | if (newDepth > 0) { 213 | console.log( 214 | `Researching deeper, breadth: ${newBreadth}, depth: ${newDepth}`, 215 | ); 216 | 217 | const nextQuery = ` 218 | Previous research goal: ${serpQuery.researchGoal} 219 | Follow-up research directions: ${newLearningsResult.followUpQuestions.map(q => `\n${q}`).join('')} 220 | `.trim(); 221 | 222 | return deepResearch({ 223 | query: nextQuery, 224 | breadth: newBreadth, 225 | depth: newDepth, 226 | learnings: allLearnings, 227 | visitedUrls: allUrls, 228 | firecrawlKey, 229 | }); 230 | } else { 231 | return { 232 | learnings: allLearnings, 233 | visitedUrls: allUrls, 234 | usage: { 235 | totalTokens: serpQueriesResult.usage.totalTokens + newLearningsResult.usage.totalTokens, 236 | promptTokens: serpQueriesResult.usage.promptTokens + newLearningsResult.usage.promptTokens, 237 | completionTokens: serpQueriesResult.usage.completionTokens + newLearningsResult.usage.completionTokens, 238 | }, 239 | }; 240 | } 241 | } catch (e) { 242 | console.error(`Error running query: ${serpQuery.query}: `, e); 243 | return { 244 | learnings: [], 245 | visitedUrls: [], 246 | usage: { 247 | totalTokens: serpQueriesResult.usage.totalTokens, 248 | promptTokens: serpQueriesResult.usage.promptTokens, 249 | completionTokens: serpQueriesResult.usage.completionTokens, 250 | }, 251 | }; 252 | } 253 | }); 254 | }); 255 | 256 | const results = await Promise.all(promises) as ResearchResult[]; 257 | 258 | // Aggregate usage across all results 259 | const totalUsage = results.reduce((acc, curr) => ({ 260 | totalTokens: acc.totalTokens + curr.usage.totalTokens, 261 | promptTokens: acc.promptTokens + curr.usage.promptTokens, 262 | completionTokens: acc.completionTokens + curr.usage.completionTokens, 263 | }), { 264 | totalTokens: 0, 265 | promptTokens: 0, 266 | completionTokens: 0, 267 | }); 268 | 269 | return { 270 | learnings: [...new Set(results.flatMap(r => r.learnings))], 271 | visitedUrls: [...new Set(results.flatMap(r => r.visitedUrls))], 272 | usage: totalUsage, 273 | }; 274 | } 275 | -------------------------------------------------------------------------------- /src/feedback.ts: -------------------------------------------------------------------------------- 1 | import { generateObject } from 'ai'; 2 | import { z } from 'zod'; 3 | 4 | import { o3MiniModel } from './ai/providers.js'; 5 | import { systemPrompt } from './prompt.js'; 6 | 7 | export type FeedbackResult = { 8 | questions: string[]; 9 | usage: { 10 | totalTokens: number; 11 | promptTokens: number; 12 | completionTokens: number; 13 | }; 14 | }; 15 | 16 | export async function generateFeedback({ 17 | query, 18 | numQuestions = 3, 19 | }: { 20 | query: string; 21 | numQuestions?: number; 22 | }): Promise { 23 | const userFeedback = await generateObject({ 24 | model: o3MiniModel, 25 | system: systemPrompt(), 26 | prompt: `Given the following query from the user, ask some follow up questions to clarify the research direction. Return a maximum of ${numQuestions} questions, but feel free to return less if the original query is clear: ${query}`, 27 | schema: z.object({ 28 | questions: z 29 | .array(z.string()) 30 | .describe( 31 | `Follow up questions to clarify the research direction, max of ${numQuestions}`, 32 | ), 33 | }), 34 | }); 35 | 36 | return { 37 | questions: userFeedback.object.questions.slice(0, numQuestions), 38 | usage: userFeedback.usage, 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /src/prompt.ts: -------------------------------------------------------------------------------- 1 | export const systemPrompt = () => { 2 | const now = new Date().toISOString(); 3 | return `You are an expert researcher. Today is ${now}. Follow these instructions when responding: 4 | - You may be asked to research subjects that is after your knowledge cutoff, assume the user is right when presented with news. 5 | - The user is a highly experienced analyst, no need to simplify it, be as detailed as possible and make sure your response is correct. 6 | - Be highly organized. 7 | - Suggest solutions that I didn't think about. 8 | - Be proactive and anticipate my needs. 9 | - Treat me as an expert in all subject matter. 10 | - Mistakes erode my trust, so be accurate and thorough. 11 | - Provide detailed explanations, I'm comfortable with lots of detail. 12 | - Value good arguments over authorities, the source is irrelevant. 13 | - Consider new technologies and contrarian ideas, not just the conventional wisdom. 14 | - You may use high levels of speculation or prediction, just flag it for me.`; 15 | }; 16 | -------------------------------------------------------------------------------- /src/run.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs/promises'; 2 | import * as readline from 'readline'; 3 | 4 | import { deepResearch, writeFinalReport } from './deep-research.js'; 5 | import { generateFeedback } from './feedback.js'; 6 | 7 | 8 | const rl = readline.createInterface({ 9 | input: process.stdin, 10 | output: process.stdout, 11 | }); 12 | 13 | // Helper function to get user input 14 | function askQuestion(query: string): Promise { 15 | return new Promise(resolve => { 16 | rl.question(query, answer => { 17 | resolve(answer); 18 | }); 19 | }); 20 | } 21 | 22 | // run the agent 23 | async function run() { 24 | // Get initial query 25 | const initialQuery = await askQuestion('What would you like to research? '); 26 | 27 | // Get breath and depth parameters 28 | const breadth = 29 | parseInt(await askQuestion('Enter research breadth (recommended 2-10, default 4): '), 10) || 4; 30 | const depth = 31 | parseInt(await askQuestion('Enter research depth (recommended 1-5, default 2): '), 10) || 2; 32 | 33 | console.log(`Creating research plan...`); 34 | 35 | // Generate follow-up questions 36 | const followUpQuestions = await generateFeedback({ 37 | query: initialQuery, 38 | }); 39 | 40 | console.log( 41 | '\nTo better understand your research needs, please answer these follow-up questions:', 42 | ); 43 | 44 | // Collect answers to follow-up questions 45 | const answers: string[] = []; 46 | for (const question of followUpQuestions.questions) { 47 | const answer = await askQuestion(`\n${question}\nYour answer: `); 48 | answers.push(answer); 49 | } 50 | 51 | // Combine all information for deep research 52 | const combinedQuery = ` 53 | Initial Query: ${initialQuery} 54 | Follow-up Questions and Answers: 55 | ${followUpQuestions.questions.map((q, i) => `Q: ${q}\nA: ${answers[i]}`).join('\n')} 56 | `; 57 | 58 | console.log('\nResearching your topic...'); 59 | 60 | const { learnings, visitedUrls } = await deepResearch({ 61 | query: combinedQuery, 62 | breadth, 63 | depth, 64 | }); 65 | 66 | console.log(`\n\nLearnings:\n\n${learnings.join('\n')}`); 67 | console.log(`\n\nVisited URLs (${visitedUrls.length}):\n\n${visitedUrls.join('\n')}`); 68 | console.log('Writing final report...'); 69 | 70 | const report = await writeFinalReport({ 71 | prompt: combinedQuery, 72 | learnings, 73 | visitedUrls, 74 | }); 75 | 76 | // Save report to file 77 | await fs.writeFile('output.md', report.reportMarkdown, 'utf-8'); 78 | 79 | console.log(`\n\nFinal Report:\n\n${report.reportMarkdown}`); 80 | console.log('\nReport has been saved to output.md'); 81 | rl.close(); 82 | 83 | } 84 | 85 | run().catch(console.error); 86 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./dist", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "esModuleInterop": true, 9 | "incremental": false, 10 | "isolatedModules": true, 11 | "lib": ["es2022", "DOM", "DOM.Iterable"], 12 | "module": "NodeNext", 13 | "moduleResolution": "NodeNext", 14 | "target": "es2022", 15 | "skipLibCheck": true, 16 | "strict": true 17 | }, 18 | "include": ["src/**/*"], 19 | "exclude": ["node_modules"] 20 | } 21 | --------------------------------------------------------------------------------