├── .env.example ├── .gitignore ├── DemoScreenshots ├── DemoSetup.gif ├── researcher-demo1.png ├── researcher-demo2.png ├── researcher-demo3.png ├── researcher-demo4.png ├── researcher-demo5.png └── researcher-demo6.png ├── LICENSE ├── README.md ├── custom-mode-prompt.md ├── index.js ├── package-lock.json └── package.json /.env.example: -------------------------------------------------------------------------------- 1 | # Add your Perplexity API key below 2 | PERPLEXITY_API_KEY=Your Key Here -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User 2 | .obsidian/ 3 | 4 | # Dependencies 5 | node_modules/ 6 | 7 | # Environment variables 8 | .env 9 | 10 | # Cache file 11 | cache.json 12 | 13 | # OS generated files 14 | .DS_Store 15 | Thumbs.db -------------------------------------------------------------------------------- /DemoScreenshots/DemoSetup.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/James-Cherished-Inc/roo-research-mode/909695336c6150a2e58ff57fdc5cf0f509426e7c/DemoScreenshots/DemoSetup.gif -------------------------------------------------------------------------------- /DemoScreenshots/researcher-demo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/James-Cherished-Inc/roo-research-mode/909695336c6150a2e58ff57fdc5cf0f509426e7c/DemoScreenshots/researcher-demo1.png -------------------------------------------------------------------------------- /DemoScreenshots/researcher-demo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/James-Cherished-Inc/roo-research-mode/909695336c6150a2e58ff57fdc5cf0f509426e7c/DemoScreenshots/researcher-demo2.png -------------------------------------------------------------------------------- /DemoScreenshots/researcher-demo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/James-Cherished-Inc/roo-research-mode/909695336c6150a2e58ff57fdc5cf0f509426e7c/DemoScreenshots/researcher-demo3.png -------------------------------------------------------------------------------- /DemoScreenshots/researcher-demo4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/James-Cherished-Inc/roo-research-mode/909695336c6150a2e58ff57fdc5cf0f509426e7c/DemoScreenshots/researcher-demo4.png -------------------------------------------------------------------------------- /DemoScreenshots/researcher-demo5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/James-Cherished-Inc/roo-research-mode/909695336c6150a2e58ff57fdc5cf0f509426e7c/DemoScreenshots/researcher-demo5.png -------------------------------------------------------------------------------- /DemoScreenshots/researcher-demo6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/James-Cherished-Inc/roo-research-mode/909695336c6150a2e58ff57fdc5cf0f509426e7c/DemoScreenshots/researcher-demo6.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Roo Code Research Mode with Perplexity & Lynx 2 | 3 | This repository contains the code for a custom Roo Code mode ("ResearchMode") that integrates Perplexity API for web search and Lynx for page analysis, enabling autonomous research-augmented software engineering within the Roo Code VS Code extension. 4 | 5 | -By @https://x.com/JamesCherished 6 | 7 | ## Table of Contents 8 | 9 | - [Features](#features) 10 | - [Quick Start: Automated Setup with Roo, nothing simpler!](#quick-start-automated-setup-with-roo) 11 | - [Demo](#demo) 12 | - [Details](#details) 13 | - [Usage](#usage) 14 | - [Manual Installation / Troubleshooting](#manual-installation--troubleshooting) 15 | - [1. Prerequisites](#1-prerequisites) 16 | - [2. Clone & Install](#2-clone--install) 17 | - [3. Configure API Key](#3-configure-api-key) 18 | - [4. Configure Roo Code Manually](#4-configure-roo-code-manually) 19 | - [5. Restart VS Code](#5-restart-vs-code) 20 | - [6. Manual Server Start (If Automatic Fails)](#6-manual-server-start-if-automatic-fails) 21 | - [Full `custom_modes.json` Snippet (for Manual Setup)](#full-custom_modesjson-snippet-for-manual-setup) 22 | - [FAQ](#faq) 23 | - [Contributing](#contributing) 24 | - [Credits](#credits) 25 | - [License (MPL 2.0)](#license) 26 | 27 | ## Features 28 | 29 | * **Perplexity Integration:** Uses the Perplexity API (via a local MCP server) for high-quality, up-to-date web search results using the `sonar` model. 30 | * About $0.01 per search. You get $5 of monthly free credits with Perplexity Pro, which is enough for intensive use. You can monitor and set limits at https://www.perplexity.ai/account/api 31 | * **Lynx Integration:** Leverages the Lynx text-based browser for deep page analysis, code extraction, and documentation summarization directly within Roo Code. 32 | * **Research-Augmented Coding:** Designed for software engineers to seamlessly blend coding tasks with research, using findings to inform code generation, refactoring, and technical decisions. 33 | * **Caching:** Includes simple file-based caching (`cache.json`) for Perplexity results to conserve API credits and improve response times. 34 | * **Configurable:** Uses a `.env` file for secure API key management. 35 | * **Automatic Server Management:** Designed for Roo Code to automatically start and manage the local MCP server once configured. 36 | 37 | ## Quick Start: Automated Setup with Roo 38 | 39 | The easiest way to set up ResearchMode is to let Roo configure it for you! 40 | 41 | You can copy the Custom Mode prompt from the custom-mode-prompt.md file of this repo or from section 6 [Full `custom_modes.json` Snippet (for Manual Setup)](#full-custom_modesjson-snippet-for-manual-setup) of this README. Running any task in Research Mode programs Roo to check your workspace and set its own research capabilities autonomously for the first-time use. 42 | 43 | Alternatively, you can start a new task with the prompt below in any mode to set up everything, **including the creating of the Custom Mode** :). 44 | ### Demo 45 | 46 | 47 | ![Demo Setup](./DemoScreenshots/DemoSetup.gif) 48 | 49 | ### Details : 50 | 51 | (Replace URL with https://github.com/James-Cherished/rooresearcher.git for experimental releases, or with your fork's URL) 52 | 53 | 1. **Start Roo Code in ResearchMode with any task OR start a new task in any mode with the following prompt to create it:** 54 | 55 | ``` 56 | Task: Configure and activate the ResearchMode from this repository. 57 | 58 | Steps: 59 | 1. Clone the Repository & Install Dependencies: 60 | ```bash 61 | git clone https://github.com/James-Cherished-Inc/roo-research-mode # Or your fork's URL 62 | cd rooresearcher 63 | npm install 64 | ``` 65 | 2. Verify prerequisites: Check if Node.js (v14+), npm, and Lynx are installed and available in the system PATH. If Lynx is missing, attempt to install it using the appropriate command for the OS (e.g., `sudo apt update && sudo apt install lynx -y` for Debian/Ubuntu). 66 | 3. API Key Setup: Check if a `.env` file exists. If not, copy `.env.example` to `.env`. Ask me for my Perplexity API key (obtainable from https://www.perplexity.ai/settings/api) and update the `PERPLEXITY_API_KEY` value in the `.env` file. 67 | 4. Roo Code Configuration: 68 | a. Determine the absolute path to the `index.js` file in the current workspace (`rooresearcher`). 69 | b. Read the Roo Code MCP settings file (e.g., `~/.config/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json`, or `~/.config/VSCodium/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json` if the user uses VSCodium). Add or update the `perplexity-search` entry within `mcpServers`, ensuring the `args` contains the correct absolute path to `index.js`. 70 | c. Read the Roo Code custom modes file (e.g., `~/.config/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/custom_modes.json`). Add or update the `research-mode` definition using the JSON snippet provided in this repository's README.md (section: Manual Installation / Troubleshooting). 71 | Note: You might need my approval to edit the Roo Code configuration files (`mcp_settings.json`, `custom_modes.json`) as they are located outside the current workspace. Please request permission before applying changes to these files. 72 | 5. Make the script executable: 73 | ```bash 74 | chmod +x index.js 75 | ``` 76 | 6. Final Instructions: Inform me that the setup is complete and that I probably need to restart VS Code for the changes to take effect. 77 | ``` 78 | 79 | 2. **Follow Roo's Instructions:** Roo will guide you through the process, asking for your API key and confirmation to edit global configuration files. 80 | 81 | Once Roo confirms the setup is complete, restart VS Code. ResearchMode should now be available, and the MCP server should start automatically. 82 | 83 | --- 84 | ## Usage 85 | 86 | Once set up and the MCP server is running (ideally automatically), activate "ResearchMode" in Roo Code. You can now perform tasks like: 87 | 88 | * **Code with Research:** 89 | * "Refactor this Python function to use async/await. Search for best practices first." 90 | * This task demonstrates how to use ResearchMode to find best practices for refactoring code. Roo will search for relevant articles and documentation, and then suggest code changes based on the research findings. 91 | * **Targeted Research:** 92 | * "Find examples of Rust's `Result` type used with file I/O." 93 | * This task shows how to use ResearchMode to find specific examples of code usage. Roo will search for code snippets and examples that demonstrate how to use the `Result` type with file I/O in Rust. 94 | * **Documentation Analysis:** 95 | * "Summarize the main points of the Lynx man page using `lynx -dump 'man:lynx'`." 96 | * This task illustrates how to use ResearchMode to analyze documentation. Roo will use Lynx to extract the text content of the man page and then summarize the main points. 97 | * **Code Extraction:** 98 | * "Search for a JavaScript debounce function example and extract the code from the top result." 99 | * This task demonstrates how to use ResearchMode to find and extract code from web pages. Roo will search for a JavaScript debounce function example and then extract the code from the top result. 100 | * **Iterative Development:** 101 | * Roo will use research findings to suggest code, which you can then refine together. Roo is also instructed to document the influence of research in comments or docs. 102 | * This highlights the iterative nature of ResearchMode. Roo will continuously learn from your feedback and refine its suggestions over time. 103 | **CLI tool:** You can use the `node ./index.js` command to query the Perplexity API directly from the command line for simple queries. 104 | 105 | * First, make the script executable: `chmod +x index.js` 106 | * Then, run the command: `node ./index.js --query "your search query"` 107 | 108 | For more complex queries, or as a fallback when the MCP connection is broken, you can use POST requests to the MCP server. To do this, use the `curl` command with the following format: 109 | `curl -X POST -H "Content-Type: application/json" -d '{"query": "your search query"}' http://localhost:3000/` 110 | 111 | 112 | Here are some additional examples: 113 | 114 | * **Finding vulnerabilities:** "Find common vulnerabilities in web applications and how to prevent them." 115 | * **Learning new frameworks:** "Find a tutorial on how to use React hooks for state management." 116 | * **Debugging code:** "Explain this error message: `TypeError: Cannot read property 'length' of undefined`." 117 | * **Optimizing performance:** "Find ways to optimize the performance of this JavaScript code." 118 | --- 119 | ## Manual Installation / Troubleshooting 120 | 121 | If you prefer to configure manually or encounter issues with the automated setup: 122 | 123 | ### 1. Prerequisites 124 | Ensure the following are installed: 125 | * [Roo Code VS Code extension](https://marketplace.visualstudio.com/items?itemName=rooveterinaryinc.roo-cline). 126 | * [Node.js](https://nodejs.org/) (v14+) & npm (`node -v`, `npm -v`). Install if needed (e.g., `sudo apt update && sudo apt install nodejs npm -y` on Debian/Ubuntu). 127 | * [Lynx](https://lynx.invisible-island.net/) text browser (`lynx --version`). Install if needed. Here are some instructions for installing Lynx on different operating systems: 128 | * **Debian/Ubuntu:** `sudo apt update && sudo apt install lynx -y` 129 | * **macOS:** `brew install lynx` (requires Homebrew) 130 | * **Windows:** Download the Lynx binary from a trusted source and add it to your system's PATH. 131 | * A [Perplexity API key](https://www.perplexity.ai/settings/api). 132 | 133 | ### 2. Clone & Install 134 | ```bash 135 | git clone https://github.com/James-Cherished-Inc/roo-research-mode # Or your fork's URL 136 | cd rooresearcher 137 | npm install 138 | ``` 139 | (Replace URL with https://github.com/James-Cherished/rooresearcher.git for experimental releases, or with your fork's URL) 140 | 141 | ### 3. Configure API Key 142 | * `cp .env.example .env` 143 | * Edit `.env` and add your Perplexity API key. 144 | 145 | ### 4. Configure Roo Code Manually 146 | * **Find Config Files:** Locate Roo Code's settings directory: 147 | * Linux: `~/.config/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/` 148 | * macOS: `~/Library/Application Support/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/` 149 | * Windows: `%APPDATA%\Code\User\globalStorage\rooveterinaryinc.roo-cline\settings\` 150 | * **Edit `mcp_settings.json`:** This file configures the MCP servers that Roo Code uses to communicate with external services. Add the `perplexity-search` server entry, ensuring you use the **correct absolute path** to `index.js`. 151 | ```json 152 | // Inside mcp_settings.json -> mcpServers object 153 | "perplexity-search": { 154 | "command": "node", 155 | "args": ["/full/absolute/path/to/your/rooresearcher/index.js"], // <-- CHANGE THIS 156 | "env": {} 157 | } 158 | ``` 159 | *(If the file or `mcpServers` object doesn't exist, create them)* 160 | * The `command` field specifies the command to run the server. 161 | * The `args` field specifies the arguments to pass to the command. **Make sure to replace `/full/absolute/path/to/your/rooresearcher/index.js` with the actual absolute path to the `index.js` file in your `rooresearcher` directory.** 162 | * The `env` field specifies any environment variables to set for the server. 163 | * **Edit `custom_modes.json`:** This file defines the custom modes that are available in Roo Code. Add the `research-mode` definition to the `customModes` array. 164 | ```json 165 | // Inside custom_modes.json -> customModes array 166 | { 167 | "slug": "research-mode", 168 | "name": "ResearchMode", 169 | "roleDefinition": "You are Roo, a highly skilled software engineer and researcher...", // Full definition below 170 | "customInstructions": // Full instructions below 171 | "groups": ["read", "edit", "command", "browser", "mcp"], 172 | "source": "global" 173 | } 174 | ``` 175 | *(See full JSON snippets below if needed)* 176 | * The `slug` field specifies the unique identifier for the mode. 177 | * The `name` field specifies the display name for the mode. 178 | * The `roleDefinition` field specifies the role definition for the mode. 179 | * The `customInstructions` field specifies the custom instructions for the mode. 180 | * The `groups` field specifies the permissions for the mode. 181 | * The `source` field specifies the source of the mode definition. 182 | 183 | ### 5. Restart VS Code 184 | Restart VS Code completely after saving configuration changes. 185 | 186 | ### 6. Manual Server Start (If Automatic Fails) 187 | * If Roo Code doesn't start the server automatically (check Roo Code logs or try using the mode), you can run it manually from the `rooresearcher` directory: 188 | ```bash 189 | node index.js 190 | ``` 191 | * Keep the terminal running. If this works, the issue is likely the absolute path configured in `mcp_settings.json`. 192 | * Consider using `pm2` or `systemd` for persistent background execution if desired. 193 | 194 | 195 | #### Full `custom_modes.json` Snippet (for Manual Setup) 196 | 197 | ```json 198 | { 199 | "slug": "research-mode", 200 | "name": "ResearchMode", 201 | "roleDefinition": "You are Roo, a highly skilled software engineer and researcher. Your primary function is to design, write, refactor, and debug code, seamlessly integrating your research capabilities (Perplexity-powered web search and Lynx-based page analysis) into every stage of the development process to augment your programming abilities and make informed decisions.\\nYou automatically:\\n1. Manage the Perplexity MCP server for web search to gather relevant information and insights. \\n2. Utilize Lynx for in-depth text-based page analysis and precise code extraction. \\n3. Maintain research context across multiple queries to ensure a cohesive and comprehensive understanding of the subject matter. \\n4. Meticulously document all research influences in project files.\\n5. Preserve the original formatting of extracted code blocks to ensure accuracy and readability. \\n6. Rigorously validate the relevance and applicability of research findings before implementing them in code.\\n\\n**You confirm whether the workspace has already set up your research capabilities before proceeding. You implement your research capabilities yourself if this is your first time in this workspace.**\\n\\nYou maintain context, cite sources, and ensure all code and research actions are actionable, reproducible, and well-documented.", 202 | "customInstructions": "## To achieve your goal, follow these steps as a workflow:\n\n1. **Initiate Research:**\n a. For coding tasks requiring external knowledge, begin by clearly defining the research goal. Use the format `## [TIMESTAMP] Research Goal: [CLEAR OBJECTIVE]` to start a new research session.\n b. Formulate a search query that incorporates the code context and the specific information you need. Be as precise as possible to narrow down the results.\n You should use Perplexity to find URLs, but you may also ask the user for URLs that you will extract text from directly using Lynx.\n When researching for a specific coding task, include relevant code context (such as the current function, file snippet, or error message) in your research queries to make them more targeted and actionable. \n\n\n2. **Execute Web Search with Perplexity to find sources:**\n a. You can use the `node ./index.js` command to query the Perplexity API directly from the command line. This is a CLI command and should be run in the terminal. Use the following format:\n `node ./index.js --query \"your search query\"`\n For more complex queries, or as a fallback when the MCP connection is broken, you should use POST requests to the MCP server. To do this, use the `curl` command with the following format:\n `curl -X POST -H \"Content-Type: application/json\" -d '{\"query\": \"your search query\"}' http://localhost:3000/`\n Use the sonar-pro model (or sonar as a fallback). Return 5 results (title, URL, snippet) per query maximum, in the following format:\n ```\n 1. [Title](URL): Brief snippet\n 2. [Title](URL): Brief snippet\n ```\n\tb. Evaluate the search results and select the 1-2 most relevant sources for further analysis. Consider factors such as the source's credibility, the relevance of the content, and the clarity of the information presented.\n\n\n3. **Analyze Sources with Lynx:**\n a. Utilize Lynx in the CLI to extract and analyze the content of the selected sources. Use the following command: `lynx -dump {URL} | grep -A 15 -E 'function|class|def|interface|example'`\n b. This command will extract the text content of the page, filter it to identify code-related elements (functions, classes, etc.), and display the surrounding context.\n Lynx supports:\n - Full page dumps (`-dump`)\n - Link extraction (`-listonly`)\n - Code block identification (`grep` patterns)\n c. If Lynx encounters errors, fallback to `curl | html2text` to extract the text content.\n d. Summarize the most important points in a few key sentences.\n\n4. **Extract Code Blocks:**\n a. Carefully extract code blocks from the Lynx output, preserving the original syntax and formatting. This ensures that the code can be easily integrated into the project. You should use: `lynx -dump {URL} | grep -A 10 \"import\\|def\\|fn\\|class\"`\n b. Pay close attention to the surrounding context to understand how the code works and how it can be adapted to the specific task at hand.\n\n5. **Document Research Influences:**\n Meticulously document all research influences in the project files. When research influences a code change or technical decision, automatically document the key findings and update the code comments & project documentation with their impact.\n This includes:\n * Adding detailed code comments with source URLs to provide clear traceability. Use the following format:\n ```js\n // [IMPLEMENTATION NOTE] - Based on {Source Title}\n // {URL} - Extracted {Code/Pattern} at {Timestamp}\n ```\n * Maintaining a comprehensive research-log.md file (chronological record) to track research progress and findings.\n * Creating and maintaining a well-organized technical\_decisions.md file (key rationale) to explain the reasoning behind technical choices.\n\n6. **Integrate Code:**\n a. Before integrating any code, rigorously validate its relevance and applicability to the task at hand. Ensure that the code is compatible with the existing codebase and that it follows the project's coding standards.\n b. Annotate adapted code with origin markers to clearly indicate the source of the code.\n c. Verify security and compatibility before including any third-party code.\n\n7. **Handle Errors:**\n a. If the Perplexity API fails, retry the request once after 5 seconds. If the request continues to fail, log the error and proceed with alternative approaches.\n b. If Lynx encounters errors, fallback to `curl | html2text` to extract the text content.\n c. If a cache miss occurs, proceed with a fresh search.\n\n8. **Optimize Performance:**\n a. Cache frequent queries to reduce API usage and improve response times.\n b. Prefer text-based sites (docs, blogs) for Lynx analysis, as they tend to be more efficient and reliable.\n\n\nExample Lynx command chain for React patterns:\n```bash\nlynx -dump https://example.com/react-best-practices | \\\n grep -i -A 20 'component structure' | \\\n sed '/Advertisement/d; /Related links/d'\n```\n\n---" 203 | "groups": [ 204 | "read", 205 | "edit", 206 | "command", 207 | "browser", 208 | "mcp" 209 | ], 210 | "source": "global" // Or set to "workspace" if preferred 211 | } 212 | ``` 213 | 214 | --- 215 | 216 | ## FAQ 217 | 218 | Here are some frequently asked questions about ResearchMode: 219 | 220 | * **How do I configure the Perplexity API key?** 221 | * You can configure the Perplexity API key by editing the `.env` file in the project root directory. Add your API key to the `PERPLEXITY_API_KEY` variable. 222 | * **How do I troubleshoot common errors?** 223 | * If you encounter any errors, please check the Roo Code logs for more information. You can also try restarting the MCP server or VS Code. 224 | * **How do I optimize performance?** 225 | * You can optimize performance by caching frequent queries and by preferring text-based sites (docs, blogs) for Lynx analysis. 226 | * **Why is Lynx not working?** 227 | * Ensure that Lynx is installed correctly and is available in your system's PATH. You can test this by running `lynx --version` in your terminal. 228 | * **How do I update the `roleDefinition` and `customInstructions`?** 229 | * Edit the `custom_modes.json` file in Roo Code's settings directory. The location of this directory depends on your operating system. See the "Manual Installation / Troubleshooting" section for more information. 230 | * **How do I add screenshots or GIFs to the `README.md` file?** 231 | * You can add screenshots or GIFs to the `README.md` file by using Markdown syntax. Simply upload the image to a web server and then use the following syntax: `![Alt text](URL to image)` 232 | 233 | --- 234 | 235 | ## Contributing 236 | 237 | This is a FOSS project, made possible by Roo Code. Please feel free to share your work or contribute to this repo! 238 | 239 | Contributions to this project are welcome! If you have any ideas for new features, bug fixes, or improvements, please feel free to submit a pull request. 240 | 241 | You can better reach me on X. 242 | Discuss on reddit: https://www.reddit.com/r/RooCode/comments/1k3uy7a/my_research_mode_with_perplexity_and_lynx/ 243 | 244 | Here are some guidelines for contributing: 245 | 246 | * **Bug Reports:** If you find a bug, please submit a detailed bug report that includes steps to reproduce the bug, the expected behavior, and the actual behavior. 247 | * **Feature Requests:** If you have an idea for a new feature, please submit a feature request that describes the feature in detail and explains why it would be a valuable addition to the project. 248 | * **Code Contributions:** If you want to contribute code, please follow these steps: 249 | 1. Fork the repository. 250 | 2. Create a new branch for your changes. 251 | 3. Make your changes and commit them with clear and concise commit messages. 252 | 4. Submit a pull request to the main branch. 253 | 254 | Please ensure that your code follows the project's coding standards and that it includes appropriate unit tests. 255 | 256 | We appreciate your contributions! 257 | 258 | --- 259 | 260 | ## Credits 261 | 262 | This project would not have been possible without the following tools and libraries: 263 | 264 | * **Perplexity API:** For providing high-quality web search results. 265 | * **Lynx:** For providing a text-based browser for page analysis. 266 | * **Roo Code:** For providing a platform for building and running custom code modes. 267 | 268 | We would like to thank the developers of these tools and libraries for their contributions to the open-source community. 269 | 270 | --- 271 | 272 | ## License 273 | 274 | This project is licensed under the **Mozilla Public License 2.0 (MPL 2.0)**. See the `LICENSE` file for details. 275 | 276 | --- 277 | -------------------------------------------------------------------------------- /custom-mode-prompt.md: -------------------------------------------------------------------------------- 1 | # Role Definition: 2 | 3 | You are Roo, a highly skilled software engineer and researcher. Your primary function is to design, write, refactor, and debug code, seamlessly integrating your research capabilities (Perplexity-powered web search and Lynx-based page analysis) into every stage of the development process to augment your programming abilities and make informed decisions. 4 | You automatically: 5 | 1. Manage the Perplexity MCP server for web search to gather relevant information and insights. 6 | 2. Utilize Lynx for in-depth text-based page analysis and precise code extraction. 7 | 3. Maintain research context across multiple queries to ensure a cohesive and comprehensive understanding of the subject matter. 8 | 4. Meticulously document all research influences in project files. 9 | 5. Preserve the original formatting of extracted code blocks to ensure accuracy and readability. 10 | 6. Rigorously validate the relevance and applicability of research findings before implementing them in code. 11 | 12 | **You confirm whether the workspace has already set up your research capabilities before proceeding. You implement your research capabilities yourself if this is your first time in this workspace.** 13 | 14 | You maintain context, cite sources, and ensure all code and research actions are actionable, reproducible, and well-documented. 15 | 16 | # Mode-Specific Custom Instructions: 17 | 18 | ## To achieve your goal, follow these steps as a workflow: 19 | 20 | 1. **Initiate Research:** 21 | a. For coding tasks requiring external knowledge, begin by clearly defining the research goal. Use the format `## [TIMESTAMP] Research Goal: [CLEAR OBJECTIVE]` to start a new research session. 22 | b. Formulate a search query that incorporates the code context and the specific information you need. Be as precise as possible to narrow down the results. 23 | You should use Perplexity to find URLs, but you may also ask the user for URLs that you will extract text from directly using Lynx. 24 | When researching for a specific coding task, include relevant code context (such as the current function, file snippet, or error message) in your research queries to make them more targeted and actionable. 25 | 26 | 27 | 2. **Execute Web Search with Perplexity to find sources:** 28 | a. You can use the `node ./index.js` command to query the Perplexity API directly from the command line. This is a CLI command and should be run in the terminal. Use the following format: 29 | `node ./index.js --query "your search query"` 30 | For more complex queries, or as a fallback when the MCP connection is broken, you should use POST requests to the MCP server. To do this, use the `curl` command with the following format: 31 | `curl -X POST -H "Content-Type: application/json" -d '{"query": "your search query"}' http://localhost:3000/` 32 | Use the sonar-pro model (or sonar as a fallback). Return 5 results (title, URL, snippet) per query maximum, in the following format: 33 | ``` 34 | 1. [Title](URL): Brief snippet 35 | 2. [Title](URL): Brief snippet 36 | ``` 37 | b. Evaluate the search results and select the 1-2 most relevant sources for further analysis. Consider factors such as the source's credibility, the relevance of the content, and the clarity of the information presented. 38 | 39 | 40 | 3. **Analyze Sources with Lynx:** 41 | a. Utilize Lynx in the CLI to extract and analyze the content of the selected sources. Use the following command: `lynx -dump {URL} | grep -A 15 -E 'function|class|def|interface|example'` 42 | b. This command will extract the text content of the page, filter it to identify code-related elements (functions, classes, etc.), and display the surrounding context. 43 | Lynx supports: 44 | - Full page dumps (`-dump`) 45 | - Link extraction (`-listonly`) 46 | - Code block identification (`grep` patterns) 47 | c. If Lynx encounters errors, fallback to `curl | html2text` to extract the text content. 48 | d. Summarize the most important points in a few key sentences. 49 | 50 | 4. **Extract Code Blocks:** 51 | a. Carefully extract code blocks from the Lynx output, preserving the original syntax and formatting. This ensures that the code can be easily integrated into the project. You should use: `lynx -dump {URL} | grep -A 10 "import\|def\|fn\|class"` 52 | b. Pay close attention to the surrounding context to understand how the code works and how it can be adapted to the specific task at hand. 53 | 54 | 5. **Document Research Influences:** 55 | Meticulously document all research influences in the project files. When research influences a code change or technical decision, automatically document the key findings and update the code comments & project documentation with their impact. 56 | This includes: 57 | * Adding detailed code comments with source URLs to provide clear traceability. Use the following format: 58 | ```js 59 | // [IMPLEMENTATION NOTE] - Based on {Source Title} 60 | // {URL} - Extracted {Code/Pattern} at {Timestamp} 61 | ``` 62 | * Maintaining a comprehensive research-log.md file (chronological record) to track research progress and findings. 63 | * Creating and maintaining a well-organized technical\_decisions.md file (key rationale) to explain the reasoning behind technical choices. 64 | 65 | 6. **Integrate Code:** 66 | a. Before integrating any code, rigorously validate its relevance and applicability to the task at hand. Ensure that the code is compatible with the existing codebase and that it follows the project's coding standards. 67 | b. Annotate adapted code with origin markers to clearly indicate the source of the code. 68 | c. Verify security and compatibility before including any third-party code. 69 | 70 | 7. **Handle Errors:** 71 | a. If the Perplexity API fails, retry the request once after 5 seconds. If the request continues to fail, log the error and proceed with alternative approaches. 72 | b. If Lynx encounters errors, fallback to `curl | html2text` to extract the text content. 73 | c. If a cache miss occurs, proceed with a fresh search. 74 | 75 | 8. **Optimize Performance:** 76 | a. Cache frequent queries to reduce API usage and improve response times. 77 | b. Prefer text-based sites (docs, blogs) for Lynx analysis, as they tend to be more efficient and reliable. 78 | 79 | 80 | Example Lynx command chain for React patterns: 81 | ```bash 82 | lynx -dump https://example.com/react-best-practices | \ 83 | grep -i -A 20 'component structure' | \ 84 | sed '/Advertisement/d; /Related links/d' 85 | ``` 86 | 87 | --- 88 | 89 | ## To set up your Perplexity search capabilities for the first time in the current workspace, follow the steps of this task: 90 | 91 | Task: Configure and activate the ResearchMode from this repository. 92 | 93 | Steps: 94 | 1. Clone the Repository & Install Dependencies: 95 | ```bash 96 | git clone https://github.com/James-Cherished-Inc/roo-research-mode # Or your fork's URL 97 | cd rooresearcher 98 | npm install 99 | ``` 100 | 2. Verify prerequisites: Check if Node.js (v14+), npm, and Lynx are installed and available in the system PATH. If Lynx is missing, attempt to install it using the appropriate command for the OS (e.g., `sudo apt update && sudo apt install lynx -y` for Debian/Ubuntu). 101 | 3. API Key Setup: Check if a `.env` file exists. If not, copy `.env.example` to `.env`. Ask me for my Perplexity API key (obtainable from https://www.perplexity.ai/settings/api) and update the `PERPLEXITY_API_KEY` value in the `.env` file. 102 | 4. Roo Code Configuration: 103 | a. Determine the absolute path to the `index.js` file in the current workspace (`rooresearcher`). 104 | b. Read the Roo Code MCP settings file (e.g., `~/.config/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json`, or `~/.config/VSCodium/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json` if the user uses VSCodium). Add or update the `perplexity-search` entry within `mcpServers` and add the correct absolute path to `index.js` to `args` (don't overwrite the pre-existing ones if any). 105 | c. Read the Roo Code custom modes file (e.g., `~/.config/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/custom_modes.json`). Add or update the `research-mode` definition using the JSON snippet provided in this repository's README.md (section: Manual Installation / Troubleshooting). 106 | Note: You might need my approval to edit the Roo Code configuration files (`mcp_settings.json`, `custom_modes.json`) as they are located outside the current workspace. Please request permission before applying changes to these files. 107 | 5. Make the script executable: 108 | ```bash 109 | chmod +x index.js 110 | ``` 111 | 6. Final Instructions: Inform me that the setup is complete and that I probably need to restart VS Code for the changes to take effect. 112 | --- -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import { program } from 'commander'; 2 | import express from 'express'; 3 | import axios from 'axios'; 4 | import fs from 'fs'; 5 | import dotenv from 'dotenv'; 6 | import { fileURLToPath, pathToFileURL } from 'url'; 7 | import { dirname } from 'path'; 8 | dotenv.config(); 9 | 10 | const app = express(); 11 | app.use(express.json()); 12 | 13 | const API_KEY = process.env.PERPLEXITY_API_KEY; 14 | if (!API_KEY) { 15 | console.error('Missing PERPLEXITY_API_KEY in .env'); 16 | process.exit(1); 17 | } 18 | 19 | const CACHE_FILE = './cache.json'; 20 | 21 | async function getPerplexityResults(query) { 22 | try { 23 | const model = 'sonar-pro'; 24 | const payload = { 25 | model: model, 26 | messages: [ 27 | { 28 | role: 'user', 29 | content: `Search the web for "${query}" and return a list of up to 5 results with titles, URLs, and brief snippets.` 30 | } 31 | ], 32 | max_tokens: 1000 33 | }; 34 | 35 | const response = await axios.post( 36 | 'https://api.perplexity.ai/chat/completions', 37 | payload, 38 | { 39 | headers: { 40 | Authorization: `Bearer ${API_KEY}`, 41 | 'Content-Type': 'application/json' 42 | } 43 | } 44 | ); 45 | 46 | const content = response.data.choices?.[0]?.message?.content || ''; 47 | return content; 48 | } catch (error) { 49 | console.error('Perplexity API error:', error.response ? error.response.data : error.message); 50 | throw error; 51 | } 52 | } 53 | 54 | const __filename = fileURLToPath(import.meta.url); 55 | const __dirname = dirname(__filename); 56 | 57 | // CLI mode 58 | if (import.meta.url === pathToFileURL(process.argv[1]).href) { 59 | program 60 | .version('0.0.1') 61 | .description('CLI tool to query Perplexity API') 62 | .option('-q, --query ', 'The query to search for') 63 | .parse(process.argv); 64 | 65 | const options = program.opts(); 66 | 67 | if (options.query) { 68 | getPerplexityResults(options.query) 69 | .then(results => { 70 | console.log(results); 71 | process.exit(0); 72 | }) 73 | .catch(error => { 74 | console.error('Error:', error.message); 75 | process.exit(1); 76 | }); 77 | } else { 78 | program.outputHelp(); 79 | process.exit(1); 80 | } 81 | } else { 82 | // Server mode 83 | app.post('/', async (req, res) => { 84 | try { 85 | const query = req.body.query; 86 | const results = await getPerplexityResults(query); 87 | res.json(results); 88 | } catch (error) { 89 | console.error('Perplexity API error:', error.message); 90 | res.status(500).json({ error: error.message }); 91 | } 92 | }); 93 | 94 | app.listen(3000, () => console.log('MCP server on port 3000')); 95 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "git-public-roo-research-mode", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "axios": "^1.8.4", 9 | "commander": "^13.1.0", 10 | "dotenv": "^16.5.0", 11 | "express": "^5.1.0" 12 | }, 13 | "bin": { 14 | "rooresearch": "index.js" 15 | } 16 | }, 17 | "node_modules/accepts": { 18 | "version": "2.0.0", 19 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", 20 | "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", 21 | "license": "MIT", 22 | "dependencies": { 23 | "mime-types": "^3.0.0", 24 | "negotiator": "^1.0.0" 25 | }, 26 | "engines": { 27 | "node": ">= 0.6" 28 | } 29 | }, 30 | "node_modules/asynckit": { 31 | "version": "0.4.0", 32 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 33 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", 34 | "license": "MIT" 35 | }, 36 | "node_modules/axios": { 37 | "version": "1.8.4", 38 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", 39 | "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", 40 | "license": "MIT", 41 | "dependencies": { 42 | "follow-redirects": "^1.15.6", 43 | "form-data": "^4.0.0", 44 | "proxy-from-env": "^1.1.0" 45 | } 46 | }, 47 | "node_modules/body-parser": { 48 | "version": "2.2.0", 49 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", 50 | "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", 51 | "license": "MIT", 52 | "dependencies": { 53 | "bytes": "^3.1.2", 54 | "content-type": "^1.0.5", 55 | "debug": "^4.4.0", 56 | "http-errors": "^2.0.0", 57 | "iconv-lite": "^0.6.3", 58 | "on-finished": "^2.4.1", 59 | "qs": "^6.14.0", 60 | "raw-body": "^3.0.0", 61 | "type-is": "^2.0.0" 62 | }, 63 | "engines": { 64 | "node": ">=18" 65 | } 66 | }, 67 | "node_modules/bytes": { 68 | "version": "3.1.2", 69 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 70 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 71 | "license": "MIT", 72 | "engines": { 73 | "node": ">= 0.8" 74 | } 75 | }, 76 | "node_modules/call-bind-apply-helpers": { 77 | "version": "1.0.2", 78 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", 79 | "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 80 | "license": "MIT", 81 | "dependencies": { 82 | "es-errors": "^1.3.0", 83 | "function-bind": "^1.1.2" 84 | }, 85 | "engines": { 86 | "node": ">= 0.4" 87 | } 88 | }, 89 | "node_modules/call-bound": { 90 | "version": "1.0.4", 91 | "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", 92 | "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", 93 | "license": "MIT", 94 | "dependencies": { 95 | "call-bind-apply-helpers": "^1.0.2", 96 | "get-intrinsic": "^1.3.0" 97 | }, 98 | "engines": { 99 | "node": ">= 0.4" 100 | }, 101 | "funding": { 102 | "url": "https://github.com/sponsors/ljharb" 103 | } 104 | }, 105 | "node_modules/combined-stream": { 106 | "version": "1.0.8", 107 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 108 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 109 | "license": "MIT", 110 | "dependencies": { 111 | "delayed-stream": "~1.0.0" 112 | }, 113 | "engines": { 114 | "node": ">= 0.8" 115 | } 116 | }, 117 | "node_modules/commander": { 118 | "version": "13.1.0", 119 | "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", 120 | "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", 121 | "license": "MIT", 122 | "engines": { 123 | "node": ">=18" 124 | } 125 | }, 126 | "node_modules/content-disposition": { 127 | "version": "1.0.0", 128 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", 129 | "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", 130 | "license": "MIT", 131 | "dependencies": { 132 | "safe-buffer": "5.2.1" 133 | }, 134 | "engines": { 135 | "node": ">= 0.6" 136 | } 137 | }, 138 | "node_modules/content-type": { 139 | "version": "1.0.5", 140 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 141 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 142 | "license": "MIT", 143 | "engines": { 144 | "node": ">= 0.6" 145 | } 146 | }, 147 | "node_modules/cookie": { 148 | "version": "0.7.2", 149 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 150 | "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 151 | "license": "MIT", 152 | "engines": { 153 | "node": ">= 0.6" 154 | } 155 | }, 156 | "node_modules/cookie-signature": { 157 | "version": "1.2.2", 158 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", 159 | "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", 160 | "license": "MIT", 161 | "engines": { 162 | "node": ">=6.6.0" 163 | } 164 | }, 165 | "node_modules/debug": { 166 | "version": "4.4.0", 167 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 168 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 169 | "license": "MIT", 170 | "dependencies": { 171 | "ms": "^2.1.3" 172 | }, 173 | "engines": { 174 | "node": ">=6.0" 175 | }, 176 | "peerDependenciesMeta": { 177 | "supports-color": { 178 | "optional": true 179 | } 180 | } 181 | }, 182 | "node_modules/delayed-stream": { 183 | "version": "1.0.0", 184 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 185 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 186 | "license": "MIT", 187 | "engines": { 188 | "node": ">=0.4.0" 189 | } 190 | }, 191 | "node_modules/depd": { 192 | "version": "2.0.0", 193 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 194 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 195 | "license": "MIT", 196 | "engines": { 197 | "node": ">= 0.8" 198 | } 199 | }, 200 | "node_modules/dotenv": { 201 | "version": "16.5.0", 202 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", 203 | "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", 204 | "license": "BSD-2-Clause", 205 | "engines": { 206 | "node": ">=12" 207 | }, 208 | "funding": { 209 | "url": "https://dotenvx.com" 210 | } 211 | }, 212 | "node_modules/dunder-proto": { 213 | "version": "1.0.1", 214 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 215 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 216 | "license": "MIT", 217 | "dependencies": { 218 | "call-bind-apply-helpers": "^1.0.1", 219 | "es-errors": "^1.3.0", 220 | "gopd": "^1.2.0" 221 | }, 222 | "engines": { 223 | "node": ">= 0.4" 224 | } 225 | }, 226 | "node_modules/ee-first": { 227 | "version": "1.1.1", 228 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 229 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", 230 | "license": "MIT" 231 | }, 232 | "node_modules/encodeurl": { 233 | "version": "2.0.0", 234 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 235 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 236 | "license": "MIT", 237 | "engines": { 238 | "node": ">= 0.8" 239 | } 240 | }, 241 | "node_modules/es-define-property": { 242 | "version": "1.0.1", 243 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 244 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 245 | "license": "MIT", 246 | "engines": { 247 | "node": ">= 0.4" 248 | } 249 | }, 250 | "node_modules/es-errors": { 251 | "version": "1.3.0", 252 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 253 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 254 | "license": "MIT", 255 | "engines": { 256 | "node": ">= 0.4" 257 | } 258 | }, 259 | "node_modules/es-object-atoms": { 260 | "version": "1.1.1", 261 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 262 | "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 263 | "license": "MIT", 264 | "dependencies": { 265 | "es-errors": "^1.3.0" 266 | }, 267 | "engines": { 268 | "node": ">= 0.4" 269 | } 270 | }, 271 | "node_modules/es-set-tostringtag": { 272 | "version": "2.1.0", 273 | "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", 274 | "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", 275 | "license": "MIT", 276 | "dependencies": { 277 | "es-errors": "^1.3.0", 278 | "get-intrinsic": "^1.2.6", 279 | "has-tostringtag": "^1.0.2", 280 | "hasown": "^2.0.2" 281 | }, 282 | "engines": { 283 | "node": ">= 0.4" 284 | } 285 | }, 286 | "node_modules/escape-html": { 287 | "version": "1.0.3", 288 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 289 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", 290 | "license": "MIT" 291 | }, 292 | "node_modules/etag": { 293 | "version": "1.8.1", 294 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 295 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 296 | "license": "MIT", 297 | "engines": { 298 | "node": ">= 0.6" 299 | } 300 | }, 301 | "node_modules/express": { 302 | "version": "5.1.0", 303 | "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", 304 | "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", 305 | "license": "MIT", 306 | "dependencies": { 307 | "accepts": "^2.0.0", 308 | "body-parser": "^2.2.0", 309 | "content-disposition": "^1.0.0", 310 | "content-type": "^1.0.5", 311 | "cookie": "^0.7.1", 312 | "cookie-signature": "^1.2.1", 313 | "debug": "^4.4.0", 314 | "encodeurl": "^2.0.0", 315 | "escape-html": "^1.0.3", 316 | "etag": "^1.8.1", 317 | "finalhandler": "^2.1.0", 318 | "fresh": "^2.0.0", 319 | "http-errors": "^2.0.0", 320 | "merge-descriptors": "^2.0.0", 321 | "mime-types": "^3.0.0", 322 | "on-finished": "^2.4.1", 323 | "once": "^1.4.0", 324 | "parseurl": "^1.3.3", 325 | "proxy-addr": "^2.0.7", 326 | "qs": "^6.14.0", 327 | "range-parser": "^1.2.1", 328 | "router": "^2.2.0", 329 | "send": "^1.1.0", 330 | "serve-static": "^2.2.0", 331 | "statuses": "^2.0.1", 332 | "type-is": "^2.0.1", 333 | "vary": "^1.1.2" 334 | }, 335 | "engines": { 336 | "node": ">= 18" 337 | }, 338 | "funding": { 339 | "type": "opencollective", 340 | "url": "https://opencollective.com/express" 341 | } 342 | }, 343 | "node_modules/finalhandler": { 344 | "version": "2.1.0", 345 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", 346 | "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", 347 | "license": "MIT", 348 | "dependencies": { 349 | "debug": "^4.4.0", 350 | "encodeurl": "^2.0.0", 351 | "escape-html": "^1.0.3", 352 | "on-finished": "^2.4.1", 353 | "parseurl": "^1.3.3", 354 | "statuses": "^2.0.1" 355 | }, 356 | "engines": { 357 | "node": ">= 0.8" 358 | } 359 | }, 360 | "node_modules/follow-redirects": { 361 | "version": "1.15.9", 362 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", 363 | "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", 364 | "funding": [ 365 | { 366 | "type": "individual", 367 | "url": "https://github.com/sponsors/RubenVerborgh" 368 | } 369 | ], 370 | "license": "MIT", 371 | "engines": { 372 | "node": ">=4.0" 373 | }, 374 | "peerDependenciesMeta": { 375 | "debug": { 376 | "optional": true 377 | } 378 | } 379 | }, 380 | "node_modules/form-data": { 381 | "version": "4.0.2", 382 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", 383 | "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", 384 | "license": "MIT", 385 | "dependencies": { 386 | "asynckit": "^0.4.0", 387 | "combined-stream": "^1.0.8", 388 | "es-set-tostringtag": "^2.1.0", 389 | "mime-types": "^2.1.12" 390 | }, 391 | "engines": { 392 | "node": ">= 6" 393 | } 394 | }, 395 | "node_modules/form-data/node_modules/mime-db": { 396 | "version": "1.52.0", 397 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 398 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 399 | "license": "MIT", 400 | "engines": { 401 | "node": ">= 0.6" 402 | } 403 | }, 404 | "node_modules/form-data/node_modules/mime-types": { 405 | "version": "2.1.35", 406 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 407 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 408 | "license": "MIT", 409 | "dependencies": { 410 | "mime-db": "1.52.0" 411 | }, 412 | "engines": { 413 | "node": ">= 0.6" 414 | } 415 | }, 416 | "node_modules/forwarded": { 417 | "version": "0.2.0", 418 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 419 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 420 | "license": "MIT", 421 | "engines": { 422 | "node": ">= 0.6" 423 | } 424 | }, 425 | "node_modules/fresh": { 426 | "version": "2.0.0", 427 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", 428 | "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", 429 | "license": "MIT", 430 | "engines": { 431 | "node": ">= 0.8" 432 | } 433 | }, 434 | "node_modules/function-bind": { 435 | "version": "1.1.2", 436 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 437 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 438 | "license": "MIT", 439 | "funding": { 440 | "url": "https://github.com/sponsors/ljharb" 441 | } 442 | }, 443 | "node_modules/get-intrinsic": { 444 | "version": "1.3.0", 445 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", 446 | "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", 447 | "license": "MIT", 448 | "dependencies": { 449 | "call-bind-apply-helpers": "^1.0.2", 450 | "es-define-property": "^1.0.1", 451 | "es-errors": "^1.3.0", 452 | "es-object-atoms": "^1.1.1", 453 | "function-bind": "^1.1.2", 454 | "get-proto": "^1.0.1", 455 | "gopd": "^1.2.0", 456 | "has-symbols": "^1.1.0", 457 | "hasown": "^2.0.2", 458 | "math-intrinsics": "^1.1.0" 459 | }, 460 | "engines": { 461 | "node": ">= 0.4" 462 | }, 463 | "funding": { 464 | "url": "https://github.com/sponsors/ljharb" 465 | } 466 | }, 467 | "node_modules/get-proto": { 468 | "version": "1.0.1", 469 | "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 470 | "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 471 | "license": "MIT", 472 | "dependencies": { 473 | "dunder-proto": "^1.0.1", 474 | "es-object-atoms": "^1.0.0" 475 | }, 476 | "engines": { 477 | "node": ">= 0.4" 478 | } 479 | }, 480 | "node_modules/gopd": { 481 | "version": "1.2.0", 482 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 483 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 484 | "license": "MIT", 485 | "engines": { 486 | "node": ">= 0.4" 487 | }, 488 | "funding": { 489 | "url": "https://github.com/sponsors/ljharb" 490 | } 491 | }, 492 | "node_modules/has-symbols": { 493 | "version": "1.1.0", 494 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 495 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 496 | "license": "MIT", 497 | "engines": { 498 | "node": ">= 0.4" 499 | }, 500 | "funding": { 501 | "url": "https://github.com/sponsors/ljharb" 502 | } 503 | }, 504 | "node_modules/has-tostringtag": { 505 | "version": "1.0.2", 506 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", 507 | "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", 508 | "license": "MIT", 509 | "dependencies": { 510 | "has-symbols": "^1.0.3" 511 | }, 512 | "engines": { 513 | "node": ">= 0.4" 514 | }, 515 | "funding": { 516 | "url": "https://github.com/sponsors/ljharb" 517 | } 518 | }, 519 | "node_modules/hasown": { 520 | "version": "2.0.2", 521 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 522 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 523 | "license": "MIT", 524 | "dependencies": { 525 | "function-bind": "^1.1.2" 526 | }, 527 | "engines": { 528 | "node": ">= 0.4" 529 | } 530 | }, 531 | "node_modules/http-errors": { 532 | "version": "2.0.0", 533 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 534 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 535 | "license": "MIT", 536 | "dependencies": { 537 | "depd": "2.0.0", 538 | "inherits": "2.0.4", 539 | "setprototypeof": "1.2.0", 540 | "statuses": "2.0.1", 541 | "toidentifier": "1.0.1" 542 | }, 543 | "engines": { 544 | "node": ">= 0.8" 545 | } 546 | }, 547 | "node_modules/iconv-lite": { 548 | "version": "0.6.3", 549 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 550 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 551 | "license": "MIT", 552 | "dependencies": { 553 | "safer-buffer": ">= 2.1.2 < 3.0.0" 554 | }, 555 | "engines": { 556 | "node": ">=0.10.0" 557 | } 558 | }, 559 | "node_modules/inherits": { 560 | "version": "2.0.4", 561 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 562 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 563 | "license": "ISC" 564 | }, 565 | "node_modules/ipaddr.js": { 566 | "version": "1.9.1", 567 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 568 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 569 | "license": "MIT", 570 | "engines": { 571 | "node": ">= 0.10" 572 | } 573 | }, 574 | "node_modules/is-promise": { 575 | "version": "4.0.0", 576 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", 577 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", 578 | "license": "MIT" 579 | }, 580 | "node_modules/math-intrinsics": { 581 | "version": "1.1.0", 582 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 583 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 584 | "license": "MIT", 585 | "engines": { 586 | "node": ">= 0.4" 587 | } 588 | }, 589 | "node_modules/media-typer": { 590 | "version": "1.1.0", 591 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", 592 | "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", 593 | "license": "MIT", 594 | "engines": { 595 | "node": ">= 0.8" 596 | } 597 | }, 598 | "node_modules/merge-descriptors": { 599 | "version": "2.0.0", 600 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", 601 | "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", 602 | "license": "MIT", 603 | "engines": { 604 | "node": ">=18" 605 | }, 606 | "funding": { 607 | "url": "https://github.com/sponsors/sindresorhus" 608 | } 609 | }, 610 | "node_modules/mime-db": { 611 | "version": "1.54.0", 612 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 613 | "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 614 | "license": "MIT", 615 | "engines": { 616 | "node": ">= 0.6" 617 | } 618 | }, 619 | "node_modules/mime-types": { 620 | "version": "3.0.1", 621 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", 622 | "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", 623 | "license": "MIT", 624 | "dependencies": { 625 | "mime-db": "^1.54.0" 626 | }, 627 | "engines": { 628 | "node": ">= 0.6" 629 | } 630 | }, 631 | "node_modules/ms": { 632 | "version": "2.1.3", 633 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 634 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 635 | "license": "MIT" 636 | }, 637 | "node_modules/negotiator": { 638 | "version": "1.0.0", 639 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", 640 | "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", 641 | "license": "MIT", 642 | "engines": { 643 | "node": ">= 0.6" 644 | } 645 | }, 646 | "node_modules/object-inspect": { 647 | "version": "1.13.4", 648 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", 649 | "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", 650 | "license": "MIT", 651 | "engines": { 652 | "node": ">= 0.4" 653 | }, 654 | "funding": { 655 | "url": "https://github.com/sponsors/ljharb" 656 | } 657 | }, 658 | "node_modules/on-finished": { 659 | "version": "2.4.1", 660 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 661 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 662 | "license": "MIT", 663 | "dependencies": { 664 | "ee-first": "1.1.1" 665 | }, 666 | "engines": { 667 | "node": ">= 0.8" 668 | } 669 | }, 670 | "node_modules/once": { 671 | "version": "1.4.0", 672 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 673 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 674 | "license": "ISC", 675 | "dependencies": { 676 | "wrappy": "1" 677 | } 678 | }, 679 | "node_modules/parseurl": { 680 | "version": "1.3.3", 681 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 682 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 683 | "license": "MIT", 684 | "engines": { 685 | "node": ">= 0.8" 686 | } 687 | }, 688 | "node_modules/path-to-regexp": { 689 | "version": "8.2.0", 690 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", 691 | "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", 692 | "license": "MIT", 693 | "engines": { 694 | "node": ">=16" 695 | } 696 | }, 697 | "node_modules/proxy-addr": { 698 | "version": "2.0.7", 699 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 700 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 701 | "license": "MIT", 702 | "dependencies": { 703 | "forwarded": "0.2.0", 704 | "ipaddr.js": "1.9.1" 705 | }, 706 | "engines": { 707 | "node": ">= 0.10" 708 | } 709 | }, 710 | "node_modules/proxy-from-env": { 711 | "version": "1.1.0", 712 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 713 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", 714 | "license": "MIT" 715 | }, 716 | "node_modules/qs": { 717 | "version": "6.14.0", 718 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", 719 | "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", 720 | "license": "BSD-3-Clause", 721 | "dependencies": { 722 | "side-channel": "^1.1.0" 723 | }, 724 | "engines": { 725 | "node": ">=0.6" 726 | }, 727 | "funding": { 728 | "url": "https://github.com/sponsors/ljharb" 729 | } 730 | }, 731 | "node_modules/range-parser": { 732 | "version": "1.2.1", 733 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 734 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 735 | "license": "MIT", 736 | "engines": { 737 | "node": ">= 0.6" 738 | } 739 | }, 740 | "node_modules/raw-body": { 741 | "version": "3.0.0", 742 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", 743 | "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", 744 | "license": "MIT", 745 | "dependencies": { 746 | "bytes": "3.1.2", 747 | "http-errors": "2.0.0", 748 | "iconv-lite": "0.6.3", 749 | "unpipe": "1.0.0" 750 | }, 751 | "engines": { 752 | "node": ">= 0.8" 753 | } 754 | }, 755 | "node_modules/router": { 756 | "version": "2.2.0", 757 | "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", 758 | "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", 759 | "license": "MIT", 760 | "dependencies": { 761 | "debug": "^4.4.0", 762 | "depd": "^2.0.0", 763 | "is-promise": "^4.0.0", 764 | "parseurl": "^1.3.3", 765 | "path-to-regexp": "^8.0.0" 766 | }, 767 | "engines": { 768 | "node": ">= 18" 769 | } 770 | }, 771 | "node_modules/safe-buffer": { 772 | "version": "5.2.1", 773 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 774 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 775 | "funding": [ 776 | { 777 | "type": "github", 778 | "url": "https://github.com/sponsors/feross" 779 | }, 780 | { 781 | "type": "patreon", 782 | "url": "https://www.patreon.com/feross" 783 | }, 784 | { 785 | "type": "consulting", 786 | "url": "https://feross.org/support" 787 | } 788 | ], 789 | "license": "MIT" 790 | }, 791 | "node_modules/safer-buffer": { 792 | "version": "2.1.2", 793 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 794 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 795 | "license": "MIT" 796 | }, 797 | "node_modules/send": { 798 | "version": "1.2.0", 799 | "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", 800 | "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", 801 | "license": "MIT", 802 | "dependencies": { 803 | "debug": "^4.3.5", 804 | "encodeurl": "^2.0.0", 805 | "escape-html": "^1.0.3", 806 | "etag": "^1.8.1", 807 | "fresh": "^2.0.0", 808 | "http-errors": "^2.0.0", 809 | "mime-types": "^3.0.1", 810 | "ms": "^2.1.3", 811 | "on-finished": "^2.4.1", 812 | "range-parser": "^1.2.1", 813 | "statuses": "^2.0.1" 814 | }, 815 | "engines": { 816 | "node": ">= 18" 817 | } 818 | }, 819 | "node_modules/serve-static": { 820 | "version": "2.2.0", 821 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", 822 | "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", 823 | "license": "MIT", 824 | "dependencies": { 825 | "encodeurl": "^2.0.0", 826 | "escape-html": "^1.0.3", 827 | "parseurl": "^1.3.3", 828 | "send": "^1.2.0" 829 | }, 830 | "engines": { 831 | "node": ">= 18" 832 | } 833 | }, 834 | "node_modules/setprototypeof": { 835 | "version": "1.2.0", 836 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 837 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", 838 | "license": "ISC" 839 | }, 840 | "node_modules/side-channel": { 841 | "version": "1.1.0", 842 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 843 | "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 844 | "license": "MIT", 845 | "dependencies": { 846 | "es-errors": "^1.3.0", 847 | "object-inspect": "^1.13.3", 848 | "side-channel-list": "^1.0.0", 849 | "side-channel-map": "^1.0.1", 850 | "side-channel-weakmap": "^1.0.2" 851 | }, 852 | "engines": { 853 | "node": ">= 0.4" 854 | }, 855 | "funding": { 856 | "url": "https://github.com/sponsors/ljharb" 857 | } 858 | }, 859 | "node_modules/side-channel-list": { 860 | "version": "1.0.0", 861 | "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 862 | "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 863 | "license": "MIT", 864 | "dependencies": { 865 | "es-errors": "^1.3.0", 866 | "object-inspect": "^1.13.3" 867 | }, 868 | "engines": { 869 | "node": ">= 0.4" 870 | }, 871 | "funding": { 872 | "url": "https://github.com/sponsors/ljharb" 873 | } 874 | }, 875 | "node_modules/side-channel-map": { 876 | "version": "1.0.1", 877 | "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 878 | "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 879 | "license": "MIT", 880 | "dependencies": { 881 | "call-bound": "^1.0.2", 882 | "es-errors": "^1.3.0", 883 | "get-intrinsic": "^1.2.5", 884 | "object-inspect": "^1.13.3" 885 | }, 886 | "engines": { 887 | "node": ">= 0.4" 888 | }, 889 | "funding": { 890 | "url": "https://github.com/sponsors/ljharb" 891 | } 892 | }, 893 | "node_modules/side-channel-weakmap": { 894 | "version": "1.0.2", 895 | "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 896 | "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 897 | "license": "MIT", 898 | "dependencies": { 899 | "call-bound": "^1.0.2", 900 | "es-errors": "^1.3.0", 901 | "get-intrinsic": "^1.2.5", 902 | "object-inspect": "^1.13.3", 903 | "side-channel-map": "^1.0.1" 904 | }, 905 | "engines": { 906 | "node": ">= 0.4" 907 | }, 908 | "funding": { 909 | "url": "https://github.com/sponsors/ljharb" 910 | } 911 | }, 912 | "node_modules/statuses": { 913 | "version": "2.0.1", 914 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 915 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 916 | "license": "MIT", 917 | "engines": { 918 | "node": ">= 0.8" 919 | } 920 | }, 921 | "node_modules/toidentifier": { 922 | "version": "1.0.1", 923 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 924 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 925 | "license": "MIT", 926 | "engines": { 927 | "node": ">=0.6" 928 | } 929 | }, 930 | "node_modules/type-is": { 931 | "version": "2.0.1", 932 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", 933 | "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", 934 | "license": "MIT", 935 | "dependencies": { 936 | "content-type": "^1.0.5", 937 | "media-typer": "^1.1.0", 938 | "mime-types": "^3.0.0" 939 | }, 940 | "engines": { 941 | "node": ">= 0.6" 942 | } 943 | }, 944 | "node_modules/unpipe": { 945 | "version": "1.0.0", 946 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 947 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 948 | "license": "MIT", 949 | "engines": { 950 | "node": ">= 0.8" 951 | } 952 | }, 953 | "node_modules/vary": { 954 | "version": "1.1.2", 955 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 956 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 957 | "license": "MIT", 958 | "engines": { 959 | "node": ">= 0.8" 960 | } 961 | }, 962 | "node_modules/wrappy": { 963 | "version": "1.0.2", 964 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 965 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 966 | "license": "ISC" 967 | } 968 | } 969 | } 970 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "bin": { 3 | "rooresearch": "index.js" 4 | }, 5 | "dependencies": { 6 | "axios": "^1.8.4", 7 | "commander": "^13.1.0", 8 | "dotenv": "^16.5.0", 9 | "express": "^5.1.0" 10 | }, 11 | "type": "module" 12 | } 13 | --------------------------------------------------------------------------------