├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── lib ├── librwkv-arm64.dylib ├── librwkv-arm64.so ├── librwkv.dylib ├── librwkv.so ├── rwkv-avx.dll ├── rwkv-avx2.dll └── rwkv-avx512.dll ├── package-lock.json ├── package.json ├── src ├── RWKV.js ├── ai_utils.js ├── cli.js ├── cpp_bind.js └── rwkv_models.js └── test ├── cpp_bind.test.js └── rwkv.test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Usual system / hidden files 2 | .* 3 | 4 | # Node modules 5 | node_modules 6 | 7 | # Exclude out weights 8 | raven/ 9 | models/ 10 | *.bin 11 | 12 | # Include back gitignore 13 | !.gitignore 14 | !.npmignore -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Common hidden file stuff 2 | .* 3 | 4 | # Node modules 5 | node_modules 6 | 7 | # Downloaded bin weights 8 | **/*.bin 9 | raven/ 10 | models/ 11 | model/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Eugene Cheah (@picocreator) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RWKV.cpp NodeJS bindings 2 | 3 | Arguably the easiest way to get RWKV.cpp running on node.js 4 | 5 | This project primary use case, is to be used as a nodejs library for running RWKV.cpp 6 | 7 | The CLI tooling, is simply a helper tooling, to do quick demo's or benchmark via node.js locally 8 | 9 | **World model is not yet supported** 10 | 11 | > This is not a pure JS solution, and depends on the [precompiled RWKV.cpp binaries found here](https://github.com/saharNooby/rwkv.cpp) 12 | > 13 | > Additionally V2 breaks compatiblity with V1, due to changes in quantization weights. 14 | 15 | ## Running it as a JS lib 16 | ```.js 17 | const RWKV = require("RWKV-cpp-node"); 18 | 19 | // Load the module with the pre-qunatized cpp weights 20 | const raven = new RWKV("") 21 | 22 | // You must call the setup before completion 23 | await raven.setup(); 24 | 25 | // Call the completion API 26 | let res = await raven.completion("RWKV is a") 27 | 28 | // And log, or do something with the result 29 | console.log( res.completion ) 30 | ``` 31 | 32 | ## Running it as a CLI 33 | ```.bash 34 | # Install globally 35 | npm install -g rwkv-cpp-node 36 | 37 | # This will start the interactive CLI, 38 | # which will guide you in downloading, and running the chat model 39 | rwkv-cpp-node --setup 40 | 41 | # You can run the chat model, with thread count 42 | # / gpu offload % (experimental, not optimized) 43 | rwkv-cpp-node --threads 4 --gpu 100% 44 | 45 | # For benchmarking 46 | rwkv-cpp-node --threads 4 --gpu 0 --dragon --size 100 47 | ``` 48 | 49 | # What is RWKV? 50 | 51 | RWKV, is a LLM which which can switch between "transformer" and "RNN" mode. 52 | 53 | This gives it the best of both worlds 54 | - High scalable training in transformer 55 | - Low overheads when infering each token in RNN mode 56 | 57 | Along with the following benefits 58 | - Theoretically Infinite context size 59 | - Embedding support via hidden states 60 | 61 | For more details on the math involved, and how this model works on a more technical basis. [Refer to the official project](https://github.com/BlinkDL/RWKV-LM) 62 | 63 | # JS CLI demo 64 | 65 | If you just want to give it a spin, the fastest way is to use npm. 66 | First perform the setup (it will download the RWKV files into your home directory) 67 | 68 | ```.bash 69 | # Install globally 70 | npm install -g rwkv-cpp-node 71 | 72 | # First run the setup 73 | rwkv-cpp-node --setup 74 | ``` 75 | 76 | You can then choose a model to download ... 77 | 78 | ``` 79 | --setup call detected, starting setup process... 80 | RWKV model will be downloaded into ~/.rwkv/ 81 | ? Select a RWKV raven model to download: (Use arrow keys) 82 | ❯ RWKV raven 1B5 v11 (Small, Fast) - 2.82 GB 83 | RWKV raven 7B v11 (Q8_0) - 8.09 GB 84 | RWKV raven 7B v11 (Q8_0, multilingual, performs slightly worse for english) - 8.09 GB 85 | RWKV raven 14B v11 (Q8_0) - 15.25 GB 86 | RWKV Pile 169M (Q8_0, lacks instruct tuning, use only for testing) - 0.24 GB 87 | ``` 88 | 89 | > PS: The file size equals to the approximate amount of storage and ram your system needs 90 | 91 | Subsequently, you can run the interactive chat mode 92 | 93 | ```.bash 94 | # Load the interactive chat 95 | rwkv-cpp-node 96 | ``` 97 | 98 | Which would start an interactive shell session, with something like the following 99 | 100 | ``` 101 | -------------------------------------- 102 | Starting RWKV chat mode 103 | -------------------------------------- 104 | Loading model from /root/.rwkv/raven_1b5_v11.bin ... 105 | The following is a conversation between the user and bot 106 | -------------------------------------- 107 | ? User: Hi 108 | Bot: How can I help you? 109 | ? User: Tell me something interesting about ravens 110 | Bot: RAVEN. I am most fascinated by the raven because of its incredible rate of survival. Ravens have been observed to live longer than any other bird, rumored to reach over 200 years old. They have the ability to live for over 1,000 years, a remarkable feat. This makes them the odd man out among birds! 111 | ``` 112 | 113 | > PS: RWKV like all chat models, can and do lie about stuff. 114 | 115 | Finally if you want to run a custom model, or just run the benchmark 116 | 117 | ```.bash 118 | # If you want to run with a pre downloaded model 119 | rwkv-cpp-node --modelPath "" 120 | 121 | # If you want to run the "--dragon" prompt benchmark 122 | rwkv-cpp-node --dragon 123 | rwkv-cpp-node --modelPath "" --dragon 124 | ``` 125 | 126 | # JS Lib Setup 127 | 128 | Install the node module 129 | 130 | ```.bash 131 | npm i rwkv-cpp-node 132 | ``` 133 | 134 | Download one of the prequantized rwkv.cpp weights, from hugging face (raven, is RWKV pretrained weights with fine-tuned instruction sets) 135 | - [RWKV-4-rave-ggml-quantized](https://huggingface.co/latestissue/rwkv-4-raven-ggml-quantized/) 136 | 137 | Alternatively you can download one of the [raven pretrained weights from the hugging face repo](https://huggingface.co/BlinkDL/rwkv-4-raven/tree/main). 138 | And perform your own quantization conversion using the [original rwkv.cpp project](https://github.com/saharNooby/rwkv.cpp) 139 | 140 | # JS Usage Details 141 | 142 | The JS interface for the RWKV model is async/promises based 143 | 144 | ```.javascript 145 | const RWKV = require("RWKV-cpp-node"); 146 | 147 | // Load the module with the pre-qunatized cpp weights 148 | const raven = new RWKV({ 149 | path: "" 150 | ... other params ... 151 | }) 152 | 153 | // You must call the setup before completion 154 | await raven.setup(); 155 | 156 | // Call the completion API 157 | let res = await raven.completion("RWKV is a") 158 | 159 | // And log, or do something with the result 160 | console.log( res.completion ) 161 | ``` 162 | 163 | Advance setup options 164 | 165 | ```.javascript 166 | // You can setup with the following parameters with a config object (instead of a string path) 167 | const raven = new RWKV({ 168 | // Path to your cpp weights 169 | path: "", 170 | 171 | // Threads count to use, this is auto detected based on your number of vCPU 172 | // if its not configured, uses 4 with gpu offloading, else uses half of vCPU detected 173 | threads: 4, 174 | 175 | // Number of layers (eg. 12), or % of the model (eg: 50%) to offload to the gpu 176 | // defaults: 0 177 | gpuOffload: 0, 178 | 179 | // Number of concurrent inferences, the model is cloned while sharing the weights 180 | // for each concurrent instances configured. This is only useful in server prod env 181 | // deafults: 1 182 | concurrent: 1, 183 | 184 | // Batch size of the input to process, this is only useful with gpuOffload 185 | // Defaults to 64 with gpuOffload, else 1 186 | // --- 187 | // batchSize: 64, 188 | 189 | // 190 | // Cache size for the RKWV state, This help optimize the repeated RWKV calls 191 | // in use cases such as "conversation", allow it to skip the previous chat computation 192 | // 193 | // it is worth noting that the 7B model takes up about 2.64 MB for the state buffer, 194 | // meaning you will need atleast 264 MB of RAM for a cachesize of 100 195 | // 196 | // This defaults to 50 197 | // Set to false or 0 to disable 198 | // 199 | stateCacheSize: 50 200 | }); 201 | await raven.setup(); 202 | ``` 203 | 204 | Completion API options 205 | 206 | ```.javascript 207 | // Lets perform a completion, with more options 208 | let res = await raven.completion({ 209 | 210 | // The prompt to use 211 | prompt: "", 212 | 213 | // Completion default settings 214 | // See openai docs for more details on what these do for your output if you do not understand them 215 | // https://platform.openai.com/docs/api-reference/completions 216 | max_tokens: 64, 217 | temperature: 1.0, 218 | top_p: 1.0, 219 | stop: [ "\n" ], 220 | 221 | // Streaming of output, either token by token, or the full complete output stream 222 | streamCallback: function(tokenStr, fullCompletionStr) { 223 | // .... 224 | }, 225 | 226 | // Existing RWKV hidden state, represented as a Flaot32Array 227 | // do not use this unless you REALLY KNOW WHAT YOUR DOING 228 | // 229 | // This will skip the state caching logic 230 | initState: (Special Float32Array) 231 | }); 232 | 233 | // Additionally if you have a commonly reused instruction set prefix, you can preload this 234 | // using either of the following (requires the stateCacheSize to not be disabled) 235 | await raven.preloadPrompt( "" ) 236 | await raven.completion({ prompt:"", max_tokens:0 }) 237 | ``` 238 | 239 | Completion output format 240 | 241 | ```.javascript 242 | // The following is a sample of the result object format 243 | let resFormat = { 244 | // Completion generated 245 | completion: '', 246 | 247 | // Prompt used 248 | prompt: '', 249 | 250 | // Token usage numbers 251 | usage: { 252 | promptTokens: 41, 253 | completionTokens: 64, 254 | totalTokens: 105, 255 | // number of tokens in the prompt that was previously cached 256 | promptTokensCached: 39 257 | }, 258 | 259 | // Performance statistics of the completion operation 260 | // 261 | // the following perf numbers is from a single 262 | // `Intel(R) Xeon(R) CPU E5-2695 v3 @ 2.30GHz` 263 | // an old 2014 processor, with 28 vCPU 264 | // with the 14B model Q8_0 quantized 265 | // 266 | perf: { 267 | // Time taken in ms for each segment 268 | promptTime: 954, 269 | completionTime: 35907, 270 | totalTime: 36861, 271 | 272 | // Time taken in ms to process each token at the respective phase 273 | timePerPrompt: 477, // This excludes cached tokens 274 | timePerCompletion: 561.046875, 275 | timePerFullPrompt: 23.26829268292683, // This includes cached tokens (if any) 276 | 277 | // The average tokens per second 278 | promptPerSecond: 2.0964360587002098, // This excludes cached tokens 279 | completionPerSecond: 1.7823822652964603, 280 | fullPromptPerSecond: 42.9769392033543 // This includes cached tokens (if any) 281 | } 282 | } 283 | ``` 284 | 285 | # Want lower level CPP based binding access? 286 | 287 | You can call our cpp_bind interface code via 288 | 289 | ``` 290 | const cpp_bind = require("rwkv-cpp-node").cpp_bind; 291 | 292 | // You can find the code here : https://github.com/RWKV/RWKV-cpp-node/blob/main/src/cpp_bind.js 293 | ``` 294 | 295 | # What can be improved? 296 | 297 | - ~~[Add GPU support via RWKV-cpp-cuda project](https://github.com/harrisonvanderbyl/rwkv-cpp-cuda)~~ 298 | - [RWKV-tokenizer-node library performance](https://github.com/PicoCreator/RWKV-tokenizer-node/issues/1) 299 | - ~~[Add MMAP support for RWKV.cpp](https://github.com/saharNooby/rwkv.cpp/issues/50)~~ 300 | - ~~[Reducing JS and RWKV.cpp back and forth for prompt eval](https://github.com/saharNooby/rwkv.cpp/pull/49)~~ 301 | - Validate and add support for X arch / OS 302 | - If your system is not supported, try to do a build on the rwkv.cpp project 303 | - [Add it to the lib folder](https://github.com/PicoCreator/RWKV-cpp-node/tree/main/lib) 304 | - [Modify the OS / Architecture detection code](https://github.com/PicoCreator/RWKV-cpp-node/blob/main/src/cpp_bind.js#L19) 305 | - ~~Utility function to download the model weights / quantize them ??~~ 306 | - ~~CLI tooling to quickly setup / download ??~~ 307 | - varient of `preloadPrompt` which gurantee the saved prompt does not get cache evicted ?? 308 | 309 | # Known issues 310 | 311 | - You need macOS 12 and above 312 | 313 | # How to run the unit test? 314 | 315 | ```.bash 316 | # Download the test model 317 | mkdir -p ./raven/ 318 | wget -O raven_1b5_v12_Q8_0.bin https://huggingface.co/latestissue/rwkv-4-raven-ggml-quantized/resolve/main/q8_0-RWKV-4-Raven-1B5-v12-Eng98%25-Other2%25-20230520-ctx4096.bin 319 | 320 | # Run the test 321 | npm run test 322 | ``` 323 | 324 | # Designated maintainer 325 | 326 | [@picocreator](https://github.com/PicoCreator) - is the current maintainer of the project, ping him on the RWKV discord if you have any questions on this project 327 | 328 | # Special thanks & refrences 329 | 330 | @saharNooby - original rwkv.cpp implementation 331 | 332 | - https://github.com/saharNooby/rwkv.cpp 333 | 334 | @BlinkDL - for the main rwkv project 335 | 336 | - https://github.com/BlinkDL/RWKV-LM 337 | 338 | # [ THIS IS OUTDATED ] Time taken per token completion for RWKV.cpp v1 339 | 340 | | Model Size | Download Size | RAM usage | AWS c6g.4xlarge (arm64, 8 Core, 16 vCPU) | AWS c6gd.16xlarge (arm64, 32 Core, 64 vCPU) | M2 Pro, Mac Mini (6 P core + 4 E core) | Oracle A1 (4 Cores) | AMD Ryzen 7 3700X (x64, 8 Core, 16 vCPU) | 341 | |------------|---------------|-----------|------------------------------------------|---------------------------------------------|-----------------------------------------|---------------------|------------------------------------------| 342 | | 1.5B | 2.82 GB | ~ 3.0 GB | 94.699 ms | 81.497 ms | 57.448 ms | 177.025 ms | 283.681 ms | 343 | | 3B | 5.56 GB | ~ 5.7 GB | 139.038 ms | 109.676 ms | 103.013 ms | 317.793 ms | 564.116 ms | 344 | | 7B (Q5_1) | 5.65 GB | ~ 7.1 GB | | | 180.137 ms | 482.916 ms | | 345 | | 7B (Q8_0) | 8.09 GB | ~ 8.3 GB | 167.148 ms | 126.856 ms | 140.261 ms | 382.687 ms | 406.984 ms | 346 | | 7B | 13.77 GB | ~ 14.9 GB | 259.888 ms | 175.069 ms | 210.280 ms | 733.818 ms | 729.948 ms | 347 | | 14B (Q8_0) | 15.25 GB | ~ 16.4 GB | 269.201 ms | 199.114 ms | 243.889 ms | 688.014 ms | 738.947 ms | 348 | | 14B | 26.36 GB | ~ 27.9 GB | 460.963 ms | 273.277 ms | | 883.386 ms | | 349 | 350 | ** Note: There are know performance bottleneck issue in the tokenizer, and sampler written in nodejs, as its a single threaded operation, between each "token" in nodejs (which takes ~10ms). And would penalize smaller model more then larger models. 351 | 352 | > Thanks to @Tomeno & @Cahya for contributing benchmark numbers ofr their A1 and M2 Pro respectively 353 | 354 | The above is done by downloading the respective model via `rwkv-cpp-node --setup`, and performing the `rwkv-cpp-node --dragon` benchmark. Which would give the following JSON at the end 355 | 356 | ``` 357 | ... output of the benchmark ... 358 | {"promptTime":178,"completionTime":109676,"totalTime":109854,"timePerPrompt":89,"timePerCompletion":109.676,"timePerFullPrompt":4.341463414634147,"promptPerSecond":11.235955056179776,"completionPerSecond":9.117765053430103,"fullPromptPerSecond":230.33707865168537} 359 | ``` 360 | 361 | timePerCompletion : is then extracted and used in the above table. 362 | 363 | > Minor notes: 7B (Q5_1) uses ~ 7.1 GB ram, 7B (Q4_3) uses ~ 6.3 GB ram, making them ideal targets for 8GB ram systems 364 | -------------------------------------------------------------------------------- /lib/librwkv-arm64.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RWKV/RWKV-cpp-node/1629e836886d4103447c602900355b823b9b5198/lib/librwkv-arm64.dylib -------------------------------------------------------------------------------- /lib/librwkv-arm64.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RWKV/RWKV-cpp-node/1629e836886d4103447c602900355b823b9b5198/lib/librwkv-arm64.so -------------------------------------------------------------------------------- /lib/librwkv.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RWKV/RWKV-cpp-node/1629e836886d4103447c602900355b823b9b5198/lib/librwkv.dylib -------------------------------------------------------------------------------- /lib/librwkv.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RWKV/RWKV-cpp-node/1629e836886d4103447c602900355b823b9b5198/lib/librwkv.so -------------------------------------------------------------------------------- /lib/rwkv-avx.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RWKV/RWKV-cpp-node/1629e836886d4103447c602900355b823b9b5198/lib/rwkv-avx.dll -------------------------------------------------------------------------------- /lib/rwkv-avx2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RWKV/RWKV-cpp-node/1629e836886d4103447c602900355b823b9b5198/lib/rwkv-avx2.dll -------------------------------------------------------------------------------- /lib/rwkv-avx512.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RWKV/RWKV-cpp-node/1629e836886d4103447c602900355b823b9b5198/lib/rwkv-avx512.dll -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rwkv-cpp-node", 3 | "version": "2.0.5", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "rwkv-cpp-node", 9 | "version": "2.0.5", 10 | "license": "MIT", 11 | "dependencies": { 12 | "inquirer": "^9.2.1", 13 | "koffi": "^2.5.0", 14 | "lru-cache": "^7.18.1", 15 | "node-fetch": "^3.3.1", 16 | "progress": "^2.0.3", 17 | "promise-queue": "^2.2.5", 18 | "rwkv-tokenizer-node": "^1.0.3" 19 | }, 20 | "bin": { 21 | "rwkv-cpp-node": "src/cli.js" 22 | }, 23 | "devDependencies": { 24 | "chai": "^4.3.7", 25 | "chai-as-promised": "^7.1.1", 26 | "mocha": "^10.2.0" 27 | }, 28 | "engines": { 29 | "node": ">=18.0.0" 30 | }, 31 | "optionalDependencies": { 32 | "cpu-features": "^0.0.7" 33 | } 34 | }, 35 | "node_modules/ansi-colors": { 36 | "version": "4.1.1", 37 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 38 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 39 | "dev": true, 40 | "engines": { 41 | "node": ">=6" 42 | } 43 | }, 44 | "node_modules/ansi-escapes": { 45 | "version": "6.2.0", 46 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", 47 | "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", 48 | "dependencies": { 49 | "type-fest": "^3.0.0" 50 | }, 51 | "engines": { 52 | "node": ">=14.16" 53 | }, 54 | "funding": { 55 | "url": "https://github.com/sponsors/sindresorhus" 56 | } 57 | }, 58 | "node_modules/ansi-regex": { 59 | "version": "5.0.1", 60 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 61 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 62 | "dev": true, 63 | "engines": { 64 | "node": ">=8" 65 | } 66 | }, 67 | "node_modules/ansi-styles": { 68 | "version": "4.3.0", 69 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 70 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 71 | "dev": true, 72 | "dependencies": { 73 | "color-convert": "^2.0.1" 74 | }, 75 | "engines": { 76 | "node": ">=8" 77 | }, 78 | "funding": { 79 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 80 | } 81 | }, 82 | "node_modules/anymatch": { 83 | "version": "3.1.3", 84 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 85 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 86 | "dev": true, 87 | "dependencies": { 88 | "normalize-path": "^3.0.0", 89 | "picomatch": "^2.0.4" 90 | }, 91 | "engines": { 92 | "node": ">= 8" 93 | } 94 | }, 95 | "node_modules/argparse": { 96 | "version": "2.0.1", 97 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 98 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 99 | "dev": true 100 | }, 101 | "node_modules/assertion-error": { 102 | "version": "1.1.0", 103 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 104 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 105 | "dev": true, 106 | "engines": { 107 | "node": "*" 108 | } 109 | }, 110 | "node_modules/balanced-match": { 111 | "version": "1.0.2", 112 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 113 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 114 | "dev": true 115 | }, 116 | "node_modules/base64-js": { 117 | "version": "1.5.1", 118 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 119 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 120 | "funding": [ 121 | { 122 | "type": "github", 123 | "url": "https://github.com/sponsors/feross" 124 | }, 125 | { 126 | "type": "patreon", 127 | "url": "https://www.patreon.com/feross" 128 | }, 129 | { 130 | "type": "consulting", 131 | "url": "https://feross.org/support" 132 | } 133 | ] 134 | }, 135 | "node_modules/binary-extensions": { 136 | "version": "2.2.0", 137 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 138 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 139 | "dev": true, 140 | "engines": { 141 | "node": ">=8" 142 | } 143 | }, 144 | "node_modules/bl": { 145 | "version": "5.1.0", 146 | "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", 147 | "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", 148 | "dependencies": { 149 | "buffer": "^6.0.3", 150 | "inherits": "^2.0.4", 151 | "readable-stream": "^3.4.0" 152 | } 153 | }, 154 | "node_modules/brace-expansion": { 155 | "version": "2.0.1", 156 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 157 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 158 | "dev": true, 159 | "dependencies": { 160 | "balanced-match": "^1.0.0" 161 | } 162 | }, 163 | "node_modules/braces": { 164 | "version": "3.0.2", 165 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 166 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 167 | "dev": true, 168 | "dependencies": { 169 | "fill-range": "^7.0.1" 170 | }, 171 | "engines": { 172 | "node": ">=8" 173 | } 174 | }, 175 | "node_modules/browser-stdout": { 176 | "version": "1.3.1", 177 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 178 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 179 | "dev": true 180 | }, 181 | "node_modules/buffer": { 182 | "version": "6.0.3", 183 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", 184 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", 185 | "funding": [ 186 | { 187 | "type": "github", 188 | "url": "https://github.com/sponsors/feross" 189 | }, 190 | { 191 | "type": "patreon", 192 | "url": "https://www.patreon.com/feross" 193 | }, 194 | { 195 | "type": "consulting", 196 | "url": "https://feross.org/support" 197 | } 198 | ], 199 | "dependencies": { 200 | "base64-js": "^1.3.1", 201 | "ieee754": "^1.2.1" 202 | } 203 | }, 204 | "node_modules/buildcheck": { 205 | "version": "0.0.6", 206 | "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", 207 | "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==", 208 | "optional": true, 209 | "engines": { 210 | "node": ">=10.0.0" 211 | } 212 | }, 213 | "node_modules/camelcase": { 214 | "version": "6.3.0", 215 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", 216 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", 217 | "dev": true, 218 | "engines": { 219 | "node": ">=10" 220 | }, 221 | "funding": { 222 | "url": "https://github.com/sponsors/sindresorhus" 223 | } 224 | }, 225 | "node_modules/chai": { 226 | "version": "4.3.7", 227 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", 228 | "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", 229 | "dev": true, 230 | "dependencies": { 231 | "assertion-error": "^1.1.0", 232 | "check-error": "^1.0.2", 233 | "deep-eql": "^4.1.2", 234 | "get-func-name": "^2.0.0", 235 | "loupe": "^2.3.1", 236 | "pathval": "^1.1.1", 237 | "type-detect": "^4.0.5" 238 | }, 239 | "engines": { 240 | "node": ">=4" 241 | } 242 | }, 243 | "node_modules/chai-as-promised": { 244 | "version": "7.1.1", 245 | "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", 246 | "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", 247 | "dev": true, 248 | "dependencies": { 249 | "check-error": "^1.0.2" 250 | }, 251 | "peerDependencies": { 252 | "chai": ">= 2.1.2 < 5" 253 | } 254 | }, 255 | "node_modules/chalk": { 256 | "version": "4.1.2", 257 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 258 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 259 | "dev": true, 260 | "dependencies": { 261 | "ansi-styles": "^4.1.0", 262 | "supports-color": "^7.1.0" 263 | }, 264 | "engines": { 265 | "node": ">=10" 266 | }, 267 | "funding": { 268 | "url": "https://github.com/chalk/chalk?sponsor=1" 269 | } 270 | }, 271 | "node_modules/chalk/node_modules/supports-color": { 272 | "version": "7.2.0", 273 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 274 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 275 | "dev": true, 276 | "dependencies": { 277 | "has-flag": "^4.0.0" 278 | }, 279 | "engines": { 280 | "node": ">=8" 281 | } 282 | }, 283 | "node_modules/chardet": { 284 | "version": "0.7.0", 285 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 286 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" 287 | }, 288 | "node_modules/check-error": { 289 | "version": "1.0.2", 290 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 291 | "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", 292 | "dev": true, 293 | "engines": { 294 | "node": "*" 295 | } 296 | }, 297 | "node_modules/chokidar": { 298 | "version": "3.5.3", 299 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 300 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 301 | "dev": true, 302 | "funding": [ 303 | { 304 | "type": "individual", 305 | "url": "https://paulmillr.com/funding/" 306 | } 307 | ], 308 | "dependencies": { 309 | "anymatch": "~3.1.2", 310 | "braces": "~3.0.2", 311 | "glob-parent": "~5.1.2", 312 | "is-binary-path": "~2.1.0", 313 | "is-glob": "~4.0.1", 314 | "normalize-path": "~3.0.0", 315 | "readdirp": "~3.6.0" 316 | }, 317 | "engines": { 318 | "node": ">= 8.10.0" 319 | }, 320 | "optionalDependencies": { 321 | "fsevents": "~2.3.2" 322 | } 323 | }, 324 | "node_modules/cli-cursor": { 325 | "version": "4.0.0", 326 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", 327 | "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", 328 | "dependencies": { 329 | "restore-cursor": "^4.0.0" 330 | }, 331 | "engines": { 332 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 333 | }, 334 | "funding": { 335 | "url": "https://github.com/sponsors/sindresorhus" 336 | } 337 | }, 338 | "node_modules/cli-spinners": { 339 | "version": "2.9.0", 340 | "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", 341 | "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==", 342 | "engines": { 343 | "node": ">=6" 344 | }, 345 | "funding": { 346 | "url": "https://github.com/sponsors/sindresorhus" 347 | } 348 | }, 349 | "node_modules/cli-width": { 350 | "version": "4.0.0", 351 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz", 352 | "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==", 353 | "engines": { 354 | "node": ">= 12" 355 | } 356 | }, 357 | "node_modules/cliui": { 358 | "version": "7.0.4", 359 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 360 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 361 | "dev": true, 362 | "dependencies": { 363 | "string-width": "^4.2.0", 364 | "strip-ansi": "^6.0.0", 365 | "wrap-ansi": "^7.0.0" 366 | } 367 | }, 368 | "node_modules/clone": { 369 | "version": "1.0.4", 370 | "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", 371 | "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", 372 | "engines": { 373 | "node": ">=0.8" 374 | } 375 | }, 376 | "node_modules/color-convert": { 377 | "version": "2.0.1", 378 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 379 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 380 | "dev": true, 381 | "dependencies": { 382 | "color-name": "~1.1.4" 383 | }, 384 | "engines": { 385 | "node": ">=7.0.0" 386 | } 387 | }, 388 | "node_modules/color-name": { 389 | "version": "1.1.4", 390 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 391 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 392 | "dev": true 393 | }, 394 | "node_modules/concat-map": { 395 | "version": "0.0.1", 396 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 397 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 398 | "dev": true 399 | }, 400 | "node_modules/cpu-features": { 401 | "version": "0.0.7", 402 | "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.7.tgz", 403 | "integrity": "sha512-fjzFmsUKKCrC9GrM1eQTvQx18e+kjXFzjRLvJPNEDjk31+bJ6ZiV6uchv/hzbzXVIgbWdrEyyX1IFKwse65+8w==", 404 | "hasInstallScript": true, 405 | "optional": true, 406 | "dependencies": { 407 | "buildcheck": "~0.0.6", 408 | "nan": "^2.17.0" 409 | }, 410 | "engines": { 411 | "node": ">=10.0.0" 412 | } 413 | }, 414 | "node_modules/data-uri-to-buffer": { 415 | "version": "4.0.1", 416 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", 417 | "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", 418 | "engines": { 419 | "node": ">= 12" 420 | } 421 | }, 422 | "node_modules/debug": { 423 | "version": "4.3.4", 424 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 425 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 426 | "dev": true, 427 | "dependencies": { 428 | "ms": "2.1.2" 429 | }, 430 | "engines": { 431 | "node": ">=6.0" 432 | }, 433 | "peerDependenciesMeta": { 434 | "supports-color": { 435 | "optional": true 436 | } 437 | } 438 | }, 439 | "node_modules/decamelize": { 440 | "version": "4.0.0", 441 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 442 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 443 | "dev": true, 444 | "engines": { 445 | "node": ">=10" 446 | }, 447 | "funding": { 448 | "url": "https://github.com/sponsors/sindresorhus" 449 | } 450 | }, 451 | "node_modules/deep-eql": { 452 | "version": "4.1.3", 453 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", 454 | "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", 455 | "dev": true, 456 | "dependencies": { 457 | "type-detect": "^4.0.0" 458 | }, 459 | "engines": { 460 | "node": ">=6" 461 | } 462 | }, 463 | "node_modules/defaults": { 464 | "version": "1.0.4", 465 | "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", 466 | "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", 467 | "dependencies": { 468 | "clone": "^1.0.2" 469 | }, 470 | "funding": { 471 | "url": "https://github.com/sponsors/sindresorhus" 472 | } 473 | }, 474 | "node_modules/diff": { 475 | "version": "5.0.0", 476 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 477 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", 478 | "dev": true, 479 | "engines": { 480 | "node": ">=0.3.1" 481 | } 482 | }, 483 | "node_modules/eastasianwidth": { 484 | "version": "0.2.0", 485 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 486 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" 487 | }, 488 | "node_modules/emoji-regex": { 489 | "version": "8.0.0", 490 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 491 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 492 | "dev": true 493 | }, 494 | "node_modules/escalade": { 495 | "version": "3.1.1", 496 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 497 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 498 | "dev": true, 499 | "engines": { 500 | "node": ">=6" 501 | } 502 | }, 503 | "node_modules/escape-string-regexp": { 504 | "version": "4.0.0", 505 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 506 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 507 | "dev": true, 508 | "engines": { 509 | "node": ">=10" 510 | }, 511 | "funding": { 512 | "url": "https://github.com/sponsors/sindresorhus" 513 | } 514 | }, 515 | "node_modules/external-editor": { 516 | "version": "3.1.0", 517 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", 518 | "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", 519 | "dependencies": { 520 | "chardet": "^0.7.0", 521 | "iconv-lite": "^0.4.24", 522 | "tmp": "^0.0.33" 523 | }, 524 | "engines": { 525 | "node": ">=4" 526 | } 527 | }, 528 | "node_modules/fetch-blob": { 529 | "version": "3.2.0", 530 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", 531 | "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", 532 | "funding": [ 533 | { 534 | "type": "github", 535 | "url": "https://github.com/sponsors/jimmywarting" 536 | }, 537 | { 538 | "type": "paypal", 539 | "url": "https://paypal.me/jimmywarting" 540 | } 541 | ], 542 | "dependencies": { 543 | "node-domexception": "^1.0.0", 544 | "web-streams-polyfill": "^3.0.3" 545 | }, 546 | "engines": { 547 | "node": "^12.20 || >= 14.13" 548 | } 549 | }, 550 | "node_modules/figures": { 551 | "version": "5.0.0", 552 | "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", 553 | "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", 554 | "dependencies": { 555 | "escape-string-regexp": "^5.0.0", 556 | "is-unicode-supported": "^1.2.0" 557 | }, 558 | "engines": { 559 | "node": ">=14" 560 | }, 561 | "funding": { 562 | "url": "https://github.com/sponsors/sindresorhus" 563 | } 564 | }, 565 | "node_modules/figures/node_modules/escape-string-regexp": { 566 | "version": "5.0.0", 567 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", 568 | "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", 569 | "engines": { 570 | "node": ">=12" 571 | }, 572 | "funding": { 573 | "url": "https://github.com/sponsors/sindresorhus" 574 | } 575 | }, 576 | "node_modules/figures/node_modules/is-unicode-supported": { 577 | "version": "1.3.0", 578 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", 579 | "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", 580 | "engines": { 581 | "node": ">=12" 582 | }, 583 | "funding": { 584 | "url": "https://github.com/sponsors/sindresorhus" 585 | } 586 | }, 587 | "node_modules/fill-range": { 588 | "version": "7.0.1", 589 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 590 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 591 | "dev": true, 592 | "dependencies": { 593 | "to-regex-range": "^5.0.1" 594 | }, 595 | "engines": { 596 | "node": ">=8" 597 | } 598 | }, 599 | "node_modules/find-up": { 600 | "version": "5.0.0", 601 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 602 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 603 | "dev": true, 604 | "dependencies": { 605 | "locate-path": "^6.0.0", 606 | "path-exists": "^4.0.0" 607 | }, 608 | "engines": { 609 | "node": ">=10" 610 | }, 611 | "funding": { 612 | "url": "https://github.com/sponsors/sindresorhus" 613 | } 614 | }, 615 | "node_modules/flat": { 616 | "version": "5.0.2", 617 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 618 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 619 | "dev": true, 620 | "bin": { 621 | "flat": "cli.js" 622 | } 623 | }, 624 | "node_modules/formdata-polyfill": { 625 | "version": "4.0.10", 626 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", 627 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", 628 | "dependencies": { 629 | "fetch-blob": "^3.1.2" 630 | }, 631 | "engines": { 632 | "node": ">=12.20.0" 633 | } 634 | }, 635 | "node_modules/fs.realpath": { 636 | "version": "1.0.0", 637 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 638 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 639 | "dev": true 640 | }, 641 | "node_modules/get-caller-file": { 642 | "version": "2.0.5", 643 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 644 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 645 | "dev": true, 646 | "engines": { 647 | "node": "6.* || 8.* || >= 10.*" 648 | } 649 | }, 650 | "node_modules/get-func-name": { 651 | "version": "2.0.0", 652 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 653 | "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", 654 | "dev": true, 655 | "engines": { 656 | "node": "*" 657 | } 658 | }, 659 | "node_modules/glob": { 660 | "version": "7.2.0", 661 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 662 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 663 | "dev": true, 664 | "dependencies": { 665 | "fs.realpath": "^1.0.0", 666 | "inflight": "^1.0.4", 667 | "inherits": "2", 668 | "minimatch": "^3.0.4", 669 | "once": "^1.3.0", 670 | "path-is-absolute": "^1.0.0" 671 | }, 672 | "engines": { 673 | "node": "*" 674 | }, 675 | "funding": { 676 | "url": "https://github.com/sponsors/isaacs" 677 | } 678 | }, 679 | "node_modules/glob-parent": { 680 | "version": "5.1.2", 681 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 682 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 683 | "dev": true, 684 | "dependencies": { 685 | "is-glob": "^4.0.1" 686 | }, 687 | "engines": { 688 | "node": ">= 6" 689 | } 690 | }, 691 | "node_modules/glob/node_modules/brace-expansion": { 692 | "version": "1.1.11", 693 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 694 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 695 | "dev": true, 696 | "dependencies": { 697 | "balanced-match": "^1.0.0", 698 | "concat-map": "0.0.1" 699 | } 700 | }, 701 | "node_modules/glob/node_modules/minimatch": { 702 | "version": "3.1.2", 703 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 704 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 705 | "dev": true, 706 | "dependencies": { 707 | "brace-expansion": "^1.1.7" 708 | }, 709 | "engines": { 710 | "node": "*" 711 | } 712 | }, 713 | "node_modules/has-flag": { 714 | "version": "4.0.0", 715 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 716 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 717 | "dev": true, 718 | "engines": { 719 | "node": ">=8" 720 | } 721 | }, 722 | "node_modules/he": { 723 | "version": "1.2.0", 724 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 725 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 726 | "dev": true, 727 | "bin": { 728 | "he": "bin/he" 729 | } 730 | }, 731 | "node_modules/iconv-lite": { 732 | "version": "0.4.24", 733 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 734 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 735 | "dependencies": { 736 | "safer-buffer": ">= 2.1.2 < 3" 737 | }, 738 | "engines": { 739 | "node": ">=0.10.0" 740 | } 741 | }, 742 | "node_modules/ieee754": { 743 | "version": "1.2.1", 744 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 745 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 746 | "funding": [ 747 | { 748 | "type": "github", 749 | "url": "https://github.com/sponsors/feross" 750 | }, 751 | { 752 | "type": "patreon", 753 | "url": "https://www.patreon.com/feross" 754 | }, 755 | { 756 | "type": "consulting", 757 | "url": "https://feross.org/support" 758 | } 759 | ] 760 | }, 761 | "node_modules/inflight": { 762 | "version": "1.0.6", 763 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 764 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 765 | "dev": true, 766 | "dependencies": { 767 | "once": "^1.3.0", 768 | "wrappy": "1" 769 | } 770 | }, 771 | "node_modules/inherits": { 772 | "version": "2.0.4", 773 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 774 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 775 | }, 776 | "node_modules/inquirer": { 777 | "version": "9.2.1", 778 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.1.tgz", 779 | "integrity": "sha512-M7LcHl1GcKt8na7NKNvqkiB3btN73+Z5NjhbckpTi9Yr8Ul7sTHXe7cFEudH0WMPcvHfQ4pHjpVOnhaQ4IC4fw==", 780 | "dependencies": { 781 | "ansi-escapes": "^6.2.0", 782 | "chalk": "^5.2.0", 783 | "cli-cursor": "^4.0.0", 784 | "cli-width": "^4.0.0", 785 | "external-editor": "^3.0.3", 786 | "figures": "^5.0.0", 787 | "lodash": "^4.17.21", 788 | "mute-stream": "1.0.0", 789 | "ora": "^6.3.0", 790 | "run-async": "^2.4.0", 791 | "rxjs": "^7.8.1", 792 | "string-width": "^5.1.2", 793 | "strip-ansi": "^7.0.1", 794 | "through": "^2.3.6", 795 | "wrap-ansi": "^8.1.0" 796 | }, 797 | "engines": { 798 | "node": ">=14.18.0" 799 | } 800 | }, 801 | "node_modules/inquirer/node_modules/ansi-regex": { 802 | "version": "6.0.1", 803 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 804 | "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", 805 | "engines": { 806 | "node": ">=12" 807 | }, 808 | "funding": { 809 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 810 | } 811 | }, 812 | "node_modules/inquirer/node_modules/ansi-styles": { 813 | "version": "6.2.1", 814 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 815 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 816 | "engines": { 817 | "node": ">=12" 818 | }, 819 | "funding": { 820 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 821 | } 822 | }, 823 | "node_modules/inquirer/node_modules/chalk": { 824 | "version": "5.2.0", 825 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", 826 | "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", 827 | "engines": { 828 | "node": "^12.17.0 || ^14.13 || >=16.0.0" 829 | }, 830 | "funding": { 831 | "url": "https://github.com/chalk/chalk?sponsor=1" 832 | } 833 | }, 834 | "node_modules/inquirer/node_modules/emoji-regex": { 835 | "version": "9.2.2", 836 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 837 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" 838 | }, 839 | "node_modules/inquirer/node_modules/string-width": { 840 | "version": "5.1.2", 841 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 842 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 843 | "dependencies": { 844 | "eastasianwidth": "^0.2.0", 845 | "emoji-regex": "^9.2.2", 846 | "strip-ansi": "^7.0.1" 847 | }, 848 | "engines": { 849 | "node": ">=12" 850 | }, 851 | "funding": { 852 | "url": "https://github.com/sponsors/sindresorhus" 853 | } 854 | }, 855 | "node_modules/inquirer/node_modules/strip-ansi": { 856 | "version": "7.0.1", 857 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", 858 | "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", 859 | "dependencies": { 860 | "ansi-regex": "^6.0.1" 861 | }, 862 | "engines": { 863 | "node": ">=12" 864 | }, 865 | "funding": { 866 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 867 | } 868 | }, 869 | "node_modules/inquirer/node_modules/wrap-ansi": { 870 | "version": "8.1.0", 871 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", 872 | "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 873 | "dependencies": { 874 | "ansi-styles": "^6.1.0", 875 | "string-width": "^5.0.1", 876 | "strip-ansi": "^7.0.1" 877 | }, 878 | "engines": { 879 | "node": ">=12" 880 | }, 881 | "funding": { 882 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 883 | } 884 | }, 885 | "node_modules/is-binary-path": { 886 | "version": "2.1.0", 887 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 888 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 889 | "dev": true, 890 | "dependencies": { 891 | "binary-extensions": "^2.0.0" 892 | }, 893 | "engines": { 894 | "node": ">=8" 895 | } 896 | }, 897 | "node_modules/is-extglob": { 898 | "version": "2.1.1", 899 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 900 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 901 | "dev": true, 902 | "engines": { 903 | "node": ">=0.10.0" 904 | } 905 | }, 906 | "node_modules/is-fullwidth-code-point": { 907 | "version": "3.0.0", 908 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 909 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 910 | "dev": true, 911 | "engines": { 912 | "node": ">=8" 913 | } 914 | }, 915 | "node_modules/is-glob": { 916 | "version": "4.0.3", 917 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 918 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 919 | "dev": true, 920 | "dependencies": { 921 | "is-extglob": "^2.1.1" 922 | }, 923 | "engines": { 924 | "node": ">=0.10.0" 925 | } 926 | }, 927 | "node_modules/is-interactive": { 928 | "version": "2.0.0", 929 | "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", 930 | "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", 931 | "engines": { 932 | "node": ">=12" 933 | }, 934 | "funding": { 935 | "url": "https://github.com/sponsors/sindresorhus" 936 | } 937 | }, 938 | "node_modules/is-number": { 939 | "version": "7.0.0", 940 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 941 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 942 | "dev": true, 943 | "engines": { 944 | "node": ">=0.12.0" 945 | } 946 | }, 947 | "node_modules/is-plain-obj": { 948 | "version": "2.1.0", 949 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 950 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 951 | "dev": true, 952 | "engines": { 953 | "node": ">=8" 954 | } 955 | }, 956 | "node_modules/is-unicode-supported": { 957 | "version": "0.1.0", 958 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", 959 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", 960 | "dev": true, 961 | "engines": { 962 | "node": ">=10" 963 | }, 964 | "funding": { 965 | "url": "https://github.com/sponsors/sindresorhus" 966 | } 967 | }, 968 | "node_modules/js-yaml": { 969 | "version": "4.1.0", 970 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 971 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 972 | "dev": true, 973 | "dependencies": { 974 | "argparse": "^2.0.1" 975 | }, 976 | "bin": { 977 | "js-yaml": "bin/js-yaml.js" 978 | } 979 | }, 980 | "node_modules/koffi": { 981 | "version": "2.5.0", 982 | "resolved": "https://registry.npmjs.org/koffi/-/koffi-2.5.0.tgz", 983 | "integrity": "sha512-xGajsqLR+WToUwUxLklnYp2Hjx9+glwjQBNDeGHKpb2zuUMDScGgyNAkJMwKsbqQGI47RXxjzx1xKyHSI1AG6Q==", 984 | "hasInstallScript": true 985 | }, 986 | "node_modules/locate-path": { 987 | "version": "6.0.0", 988 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 989 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 990 | "dev": true, 991 | "dependencies": { 992 | "p-locate": "^5.0.0" 993 | }, 994 | "engines": { 995 | "node": ">=10" 996 | }, 997 | "funding": { 998 | "url": "https://github.com/sponsors/sindresorhus" 999 | } 1000 | }, 1001 | "node_modules/lodash": { 1002 | "version": "4.17.21", 1003 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1004 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 1005 | }, 1006 | "node_modules/log-symbols": { 1007 | "version": "4.1.0", 1008 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", 1009 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", 1010 | "dev": true, 1011 | "dependencies": { 1012 | "chalk": "^4.1.0", 1013 | "is-unicode-supported": "^0.1.0" 1014 | }, 1015 | "engines": { 1016 | "node": ">=10" 1017 | }, 1018 | "funding": { 1019 | "url": "https://github.com/sponsors/sindresorhus" 1020 | } 1021 | }, 1022 | "node_modules/loupe": { 1023 | "version": "2.3.6", 1024 | "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", 1025 | "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", 1026 | "dev": true, 1027 | "dependencies": { 1028 | "get-func-name": "^2.0.0" 1029 | } 1030 | }, 1031 | "node_modules/lru-cache": { 1032 | "version": "7.18.3", 1033 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", 1034 | "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", 1035 | "engines": { 1036 | "node": ">=12" 1037 | } 1038 | }, 1039 | "node_modules/mimic-fn": { 1040 | "version": "2.1.0", 1041 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 1042 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 1043 | "engines": { 1044 | "node": ">=6" 1045 | } 1046 | }, 1047 | "node_modules/minimatch": { 1048 | "version": "5.0.1", 1049 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", 1050 | "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", 1051 | "dev": true, 1052 | "dependencies": { 1053 | "brace-expansion": "^2.0.1" 1054 | }, 1055 | "engines": { 1056 | "node": ">=10" 1057 | } 1058 | }, 1059 | "node_modules/mocha": { 1060 | "version": "10.2.0", 1061 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", 1062 | "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", 1063 | "dev": true, 1064 | "dependencies": { 1065 | "ansi-colors": "4.1.1", 1066 | "browser-stdout": "1.3.1", 1067 | "chokidar": "3.5.3", 1068 | "debug": "4.3.4", 1069 | "diff": "5.0.0", 1070 | "escape-string-regexp": "4.0.0", 1071 | "find-up": "5.0.0", 1072 | "glob": "7.2.0", 1073 | "he": "1.2.0", 1074 | "js-yaml": "4.1.0", 1075 | "log-symbols": "4.1.0", 1076 | "minimatch": "5.0.1", 1077 | "ms": "2.1.3", 1078 | "nanoid": "3.3.3", 1079 | "serialize-javascript": "6.0.0", 1080 | "strip-json-comments": "3.1.1", 1081 | "supports-color": "8.1.1", 1082 | "workerpool": "6.2.1", 1083 | "yargs": "16.2.0", 1084 | "yargs-parser": "20.2.4", 1085 | "yargs-unparser": "2.0.0" 1086 | }, 1087 | "bin": { 1088 | "_mocha": "bin/_mocha", 1089 | "mocha": "bin/mocha.js" 1090 | }, 1091 | "engines": { 1092 | "node": ">= 14.0.0" 1093 | }, 1094 | "funding": { 1095 | "type": "opencollective", 1096 | "url": "https://opencollective.com/mochajs" 1097 | } 1098 | }, 1099 | "node_modules/mocha/node_modules/ms": { 1100 | "version": "2.1.3", 1101 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1102 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1103 | "dev": true 1104 | }, 1105 | "node_modules/ms": { 1106 | "version": "2.1.2", 1107 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1108 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1109 | "dev": true 1110 | }, 1111 | "node_modules/mute-stream": { 1112 | "version": "1.0.0", 1113 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", 1114 | "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", 1115 | "engines": { 1116 | "node": "^14.17.0 || ^16.13.0 || >=18.0.0" 1117 | } 1118 | }, 1119 | "node_modules/nan": { 1120 | "version": "2.17.0", 1121 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", 1122 | "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", 1123 | "optional": true 1124 | }, 1125 | "node_modules/nanoid": { 1126 | "version": "3.3.3", 1127 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", 1128 | "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", 1129 | "dev": true, 1130 | "bin": { 1131 | "nanoid": "bin/nanoid.cjs" 1132 | }, 1133 | "engines": { 1134 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1135 | } 1136 | }, 1137 | "node_modules/node-domexception": { 1138 | "version": "1.0.0", 1139 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 1140 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", 1141 | "funding": [ 1142 | { 1143 | "type": "github", 1144 | "url": "https://github.com/sponsors/jimmywarting" 1145 | }, 1146 | { 1147 | "type": "github", 1148 | "url": "https://paypal.me/jimmywarting" 1149 | } 1150 | ], 1151 | "engines": { 1152 | "node": ">=10.5.0" 1153 | } 1154 | }, 1155 | "node_modules/node-fetch": { 1156 | "version": "3.3.1", 1157 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", 1158 | "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", 1159 | "dependencies": { 1160 | "data-uri-to-buffer": "^4.0.0", 1161 | "fetch-blob": "^3.1.4", 1162 | "formdata-polyfill": "^4.0.10" 1163 | }, 1164 | "engines": { 1165 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 1166 | }, 1167 | "funding": { 1168 | "type": "opencollective", 1169 | "url": "https://opencollective.com/node-fetch" 1170 | } 1171 | }, 1172 | "node_modules/normalize-path": { 1173 | "version": "3.0.0", 1174 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1175 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1176 | "dev": true, 1177 | "engines": { 1178 | "node": ">=0.10.0" 1179 | } 1180 | }, 1181 | "node_modules/once": { 1182 | "version": "1.4.0", 1183 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1184 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1185 | "dev": true, 1186 | "dependencies": { 1187 | "wrappy": "1" 1188 | } 1189 | }, 1190 | "node_modules/onetime": { 1191 | "version": "5.1.2", 1192 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 1193 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 1194 | "dependencies": { 1195 | "mimic-fn": "^2.1.0" 1196 | }, 1197 | "engines": { 1198 | "node": ">=6" 1199 | }, 1200 | "funding": { 1201 | "url": "https://github.com/sponsors/sindresorhus" 1202 | } 1203 | }, 1204 | "node_modules/ora": { 1205 | "version": "6.3.0", 1206 | "resolved": "https://registry.npmjs.org/ora/-/ora-6.3.0.tgz", 1207 | "integrity": "sha512-1/D8uRFY0ay2kgBpmAwmSA404w4OoPVhHMqRqtjvrcK/dnzcEZxMJ+V4DUbyICu8IIVRclHcOf5wlD1tMY4GUQ==", 1208 | "dependencies": { 1209 | "chalk": "^5.0.0", 1210 | "cli-cursor": "^4.0.0", 1211 | "cli-spinners": "^2.6.1", 1212 | "is-interactive": "^2.0.0", 1213 | "is-unicode-supported": "^1.1.0", 1214 | "log-symbols": "^5.1.0", 1215 | "stdin-discarder": "^0.1.0", 1216 | "strip-ansi": "^7.0.1", 1217 | "wcwidth": "^1.0.1" 1218 | }, 1219 | "engines": { 1220 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 1221 | }, 1222 | "funding": { 1223 | "url": "https://github.com/sponsors/sindresorhus" 1224 | } 1225 | }, 1226 | "node_modules/ora/node_modules/ansi-regex": { 1227 | "version": "6.0.1", 1228 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 1229 | "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", 1230 | "engines": { 1231 | "node": ">=12" 1232 | }, 1233 | "funding": { 1234 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 1235 | } 1236 | }, 1237 | "node_modules/ora/node_modules/chalk": { 1238 | "version": "5.2.0", 1239 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", 1240 | "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", 1241 | "engines": { 1242 | "node": "^12.17.0 || ^14.13 || >=16.0.0" 1243 | }, 1244 | "funding": { 1245 | "url": "https://github.com/chalk/chalk?sponsor=1" 1246 | } 1247 | }, 1248 | "node_modules/ora/node_modules/is-unicode-supported": { 1249 | "version": "1.3.0", 1250 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", 1251 | "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", 1252 | "engines": { 1253 | "node": ">=12" 1254 | }, 1255 | "funding": { 1256 | "url": "https://github.com/sponsors/sindresorhus" 1257 | } 1258 | }, 1259 | "node_modules/ora/node_modules/log-symbols": { 1260 | "version": "5.1.0", 1261 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", 1262 | "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", 1263 | "dependencies": { 1264 | "chalk": "^5.0.0", 1265 | "is-unicode-supported": "^1.1.0" 1266 | }, 1267 | "engines": { 1268 | "node": ">=12" 1269 | }, 1270 | "funding": { 1271 | "url": "https://github.com/sponsors/sindresorhus" 1272 | } 1273 | }, 1274 | "node_modules/ora/node_modules/strip-ansi": { 1275 | "version": "7.0.1", 1276 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", 1277 | "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", 1278 | "dependencies": { 1279 | "ansi-regex": "^6.0.1" 1280 | }, 1281 | "engines": { 1282 | "node": ">=12" 1283 | }, 1284 | "funding": { 1285 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 1286 | } 1287 | }, 1288 | "node_modules/os-tmpdir": { 1289 | "version": "1.0.2", 1290 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 1291 | "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", 1292 | "engines": { 1293 | "node": ">=0.10.0" 1294 | } 1295 | }, 1296 | "node_modules/p-limit": { 1297 | "version": "3.1.0", 1298 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1299 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1300 | "dev": true, 1301 | "dependencies": { 1302 | "yocto-queue": "^0.1.0" 1303 | }, 1304 | "engines": { 1305 | "node": ">=10" 1306 | }, 1307 | "funding": { 1308 | "url": "https://github.com/sponsors/sindresorhus" 1309 | } 1310 | }, 1311 | "node_modules/p-locate": { 1312 | "version": "5.0.0", 1313 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1314 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1315 | "dev": true, 1316 | "dependencies": { 1317 | "p-limit": "^3.0.2" 1318 | }, 1319 | "engines": { 1320 | "node": ">=10" 1321 | }, 1322 | "funding": { 1323 | "url": "https://github.com/sponsors/sindresorhus" 1324 | } 1325 | }, 1326 | "node_modules/path-exists": { 1327 | "version": "4.0.0", 1328 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1329 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1330 | "dev": true, 1331 | "engines": { 1332 | "node": ">=8" 1333 | } 1334 | }, 1335 | "node_modules/path-is-absolute": { 1336 | "version": "1.0.1", 1337 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1338 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1339 | "dev": true, 1340 | "engines": { 1341 | "node": ">=0.10.0" 1342 | } 1343 | }, 1344 | "node_modules/pathval": { 1345 | "version": "1.1.1", 1346 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 1347 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 1348 | "dev": true, 1349 | "engines": { 1350 | "node": "*" 1351 | } 1352 | }, 1353 | "node_modules/picomatch": { 1354 | "version": "2.3.1", 1355 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1356 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1357 | "dev": true, 1358 | "engines": { 1359 | "node": ">=8.6" 1360 | }, 1361 | "funding": { 1362 | "url": "https://github.com/sponsors/jonschlinkert" 1363 | } 1364 | }, 1365 | "node_modules/progress": { 1366 | "version": "2.0.3", 1367 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1368 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1369 | "engines": { 1370 | "node": ">=0.4.0" 1371 | } 1372 | }, 1373 | "node_modules/promise-queue": { 1374 | "version": "2.2.5", 1375 | "resolved": "https://registry.npmjs.org/promise-queue/-/promise-queue-2.2.5.tgz", 1376 | "integrity": "sha512-p/iXrPSVfnqPft24ZdNNLECw/UrtLTpT3jpAAMzl/o5/rDsGCPo3/CQS2611flL6LkoEJ3oQZw7C8Q80ZISXRQ==", 1377 | "engines": { 1378 | "node": ">= 0.8.0" 1379 | } 1380 | }, 1381 | "node_modules/randombytes": { 1382 | "version": "2.1.0", 1383 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1384 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1385 | "dev": true, 1386 | "dependencies": { 1387 | "safe-buffer": "^5.1.0" 1388 | } 1389 | }, 1390 | "node_modules/readable-stream": { 1391 | "version": "3.6.2", 1392 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 1393 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 1394 | "dependencies": { 1395 | "inherits": "^2.0.3", 1396 | "string_decoder": "^1.1.1", 1397 | "util-deprecate": "^1.0.1" 1398 | }, 1399 | "engines": { 1400 | "node": ">= 6" 1401 | } 1402 | }, 1403 | "node_modules/readdirp": { 1404 | "version": "3.6.0", 1405 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1406 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1407 | "dev": true, 1408 | "dependencies": { 1409 | "picomatch": "^2.2.1" 1410 | }, 1411 | "engines": { 1412 | "node": ">=8.10.0" 1413 | } 1414 | }, 1415 | "node_modules/require-directory": { 1416 | "version": "2.1.1", 1417 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1418 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 1419 | "dev": true, 1420 | "engines": { 1421 | "node": ">=0.10.0" 1422 | } 1423 | }, 1424 | "node_modules/restore-cursor": { 1425 | "version": "4.0.0", 1426 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", 1427 | "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", 1428 | "dependencies": { 1429 | "onetime": "^5.1.0", 1430 | "signal-exit": "^3.0.2" 1431 | }, 1432 | "engines": { 1433 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 1434 | }, 1435 | "funding": { 1436 | "url": "https://github.com/sponsors/sindresorhus" 1437 | } 1438 | }, 1439 | "node_modules/run-async": { 1440 | "version": "2.4.1", 1441 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", 1442 | "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", 1443 | "engines": { 1444 | "node": ">=0.12.0" 1445 | } 1446 | }, 1447 | "node_modules/rwkv-tokenizer-node": { 1448 | "version": "1.0.3", 1449 | "resolved": "https://registry.npmjs.org/rwkv-tokenizer-node/-/rwkv-tokenizer-node-1.0.3.tgz", 1450 | "integrity": "sha512-hjsF+6z72ZhHkp7kdGh0a/jFwheMXJgIog+n/VEGAT0HmFNDqVEPmgbhAPxCDi3qRhmkZmpBslNz0thIIY2fxA==" 1451 | }, 1452 | "node_modules/rxjs": { 1453 | "version": "7.8.1", 1454 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", 1455 | "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", 1456 | "dependencies": { 1457 | "tslib": "^2.1.0" 1458 | } 1459 | }, 1460 | "node_modules/safe-buffer": { 1461 | "version": "5.2.1", 1462 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1463 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1464 | "funding": [ 1465 | { 1466 | "type": "github", 1467 | "url": "https://github.com/sponsors/feross" 1468 | }, 1469 | { 1470 | "type": "patreon", 1471 | "url": "https://www.patreon.com/feross" 1472 | }, 1473 | { 1474 | "type": "consulting", 1475 | "url": "https://feross.org/support" 1476 | } 1477 | ] 1478 | }, 1479 | "node_modules/safer-buffer": { 1480 | "version": "2.1.2", 1481 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1482 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1483 | }, 1484 | "node_modules/serialize-javascript": { 1485 | "version": "6.0.0", 1486 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", 1487 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", 1488 | "dev": true, 1489 | "dependencies": { 1490 | "randombytes": "^2.1.0" 1491 | } 1492 | }, 1493 | "node_modules/signal-exit": { 1494 | "version": "3.0.7", 1495 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 1496 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" 1497 | }, 1498 | "node_modules/stdin-discarder": { 1499 | "version": "0.1.0", 1500 | "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", 1501 | "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", 1502 | "dependencies": { 1503 | "bl": "^5.0.0" 1504 | }, 1505 | "engines": { 1506 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 1507 | }, 1508 | "funding": { 1509 | "url": "https://github.com/sponsors/sindresorhus" 1510 | } 1511 | }, 1512 | "node_modules/string_decoder": { 1513 | "version": "1.3.0", 1514 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1515 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1516 | "dependencies": { 1517 | "safe-buffer": "~5.2.0" 1518 | } 1519 | }, 1520 | "node_modules/string-width": { 1521 | "version": "4.2.3", 1522 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1523 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1524 | "dev": true, 1525 | "dependencies": { 1526 | "emoji-regex": "^8.0.0", 1527 | "is-fullwidth-code-point": "^3.0.0", 1528 | "strip-ansi": "^6.0.1" 1529 | }, 1530 | "engines": { 1531 | "node": ">=8" 1532 | } 1533 | }, 1534 | "node_modules/strip-ansi": { 1535 | "version": "6.0.1", 1536 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1537 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1538 | "dev": true, 1539 | "dependencies": { 1540 | "ansi-regex": "^5.0.1" 1541 | }, 1542 | "engines": { 1543 | "node": ">=8" 1544 | } 1545 | }, 1546 | "node_modules/strip-json-comments": { 1547 | "version": "3.1.1", 1548 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1549 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1550 | "dev": true, 1551 | "engines": { 1552 | "node": ">=8" 1553 | }, 1554 | "funding": { 1555 | "url": "https://github.com/sponsors/sindresorhus" 1556 | } 1557 | }, 1558 | "node_modules/supports-color": { 1559 | "version": "8.1.1", 1560 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 1561 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 1562 | "dev": true, 1563 | "dependencies": { 1564 | "has-flag": "^4.0.0" 1565 | }, 1566 | "engines": { 1567 | "node": ">=10" 1568 | }, 1569 | "funding": { 1570 | "url": "https://github.com/chalk/supports-color?sponsor=1" 1571 | } 1572 | }, 1573 | "node_modules/through": { 1574 | "version": "2.3.8", 1575 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1576 | "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" 1577 | }, 1578 | "node_modules/tmp": { 1579 | "version": "0.0.33", 1580 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1581 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1582 | "dependencies": { 1583 | "os-tmpdir": "~1.0.2" 1584 | }, 1585 | "engines": { 1586 | "node": ">=0.6.0" 1587 | } 1588 | }, 1589 | "node_modules/to-regex-range": { 1590 | "version": "5.0.1", 1591 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1592 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1593 | "dev": true, 1594 | "dependencies": { 1595 | "is-number": "^7.0.0" 1596 | }, 1597 | "engines": { 1598 | "node": ">=8.0" 1599 | } 1600 | }, 1601 | "node_modules/tslib": { 1602 | "version": "2.5.0", 1603 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", 1604 | "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" 1605 | }, 1606 | "node_modules/type-detect": { 1607 | "version": "4.0.8", 1608 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 1609 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 1610 | "dev": true, 1611 | "engines": { 1612 | "node": ">=4" 1613 | } 1614 | }, 1615 | "node_modules/type-fest": { 1616 | "version": "3.10.0", 1617 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.10.0.tgz", 1618 | "integrity": "sha512-hmAPf1datm+gt3c2mvu0sJyhFy6lTkIGf0GzyaZWxRLnabQfPUqg6tF95RPg6sLxKI7nFLGdFxBcf2/7+GXI+A==", 1619 | "engines": { 1620 | "node": ">=14.16" 1621 | }, 1622 | "funding": { 1623 | "url": "https://github.com/sponsors/sindresorhus" 1624 | }, 1625 | "peerDependencies": { 1626 | "typescript": ">=4.7.0" 1627 | } 1628 | }, 1629 | "node_modules/typescript": { 1630 | "version": "5.0.4", 1631 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", 1632 | "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", 1633 | "peer": true, 1634 | "bin": { 1635 | "tsc": "bin/tsc", 1636 | "tsserver": "bin/tsserver" 1637 | }, 1638 | "engines": { 1639 | "node": ">=12.20" 1640 | } 1641 | }, 1642 | "node_modules/util-deprecate": { 1643 | "version": "1.0.2", 1644 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1645 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 1646 | }, 1647 | "node_modules/wcwidth": { 1648 | "version": "1.0.1", 1649 | "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", 1650 | "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", 1651 | "dependencies": { 1652 | "defaults": "^1.0.3" 1653 | } 1654 | }, 1655 | "node_modules/web-streams-polyfill": { 1656 | "version": "3.2.1", 1657 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", 1658 | "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", 1659 | "engines": { 1660 | "node": ">= 8" 1661 | } 1662 | }, 1663 | "node_modules/workerpool": { 1664 | "version": "6.2.1", 1665 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", 1666 | "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", 1667 | "dev": true 1668 | }, 1669 | "node_modules/wrap-ansi": { 1670 | "version": "7.0.0", 1671 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1672 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1673 | "dev": true, 1674 | "dependencies": { 1675 | "ansi-styles": "^4.0.0", 1676 | "string-width": "^4.1.0", 1677 | "strip-ansi": "^6.0.0" 1678 | }, 1679 | "engines": { 1680 | "node": ">=10" 1681 | }, 1682 | "funding": { 1683 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1684 | } 1685 | }, 1686 | "node_modules/wrappy": { 1687 | "version": "1.0.2", 1688 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1689 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 1690 | "dev": true 1691 | }, 1692 | "node_modules/y18n": { 1693 | "version": "5.0.8", 1694 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 1695 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 1696 | "dev": true, 1697 | "engines": { 1698 | "node": ">=10" 1699 | } 1700 | }, 1701 | "node_modules/yargs": { 1702 | "version": "16.2.0", 1703 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 1704 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 1705 | "dev": true, 1706 | "dependencies": { 1707 | "cliui": "^7.0.2", 1708 | "escalade": "^3.1.1", 1709 | "get-caller-file": "^2.0.5", 1710 | "require-directory": "^2.1.1", 1711 | "string-width": "^4.2.0", 1712 | "y18n": "^5.0.5", 1713 | "yargs-parser": "^20.2.2" 1714 | }, 1715 | "engines": { 1716 | "node": ">=10" 1717 | } 1718 | }, 1719 | "node_modules/yargs-parser": { 1720 | "version": "20.2.4", 1721 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 1722 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 1723 | "dev": true, 1724 | "engines": { 1725 | "node": ">=10" 1726 | } 1727 | }, 1728 | "node_modules/yargs-unparser": { 1729 | "version": "2.0.0", 1730 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 1731 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 1732 | "dev": true, 1733 | "dependencies": { 1734 | "camelcase": "^6.0.0", 1735 | "decamelize": "^4.0.0", 1736 | "flat": "^5.0.2", 1737 | "is-plain-obj": "^2.1.0" 1738 | }, 1739 | "engines": { 1740 | "node": ">=10" 1741 | } 1742 | }, 1743 | "node_modules/yocto-queue": { 1744 | "version": "0.1.0", 1745 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 1746 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 1747 | "dev": true, 1748 | "engines": { 1749 | "node": ">=10" 1750 | }, 1751 | "funding": { 1752 | "url": "https://github.com/sponsors/sindresorhus" 1753 | } 1754 | } 1755 | } 1756 | } 1757 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rwkv-cpp-node", 3 | "version": "2.0.5", 4 | "description": "RWKV.cpp bindings for node.js - includes CLI tooling to quickly download and run your RWKV raven models", 5 | "main": "src/RWKV.js", 6 | "scripts": { 7 | "test": "mocha \"./test/**/*.test.js\" --exit --trace-warnings" 8 | }, 9 | "bin": { 10 | "rwkv-cpp-node": "./src/cli.js" 11 | }, 12 | "keywords": [ 13 | "RWKV", 14 | "AI", 15 | "LLM", 16 | "RWKV.cpp" 17 | ], 18 | "homepage": "https://github.com/RWKV/RWKV-cpp-node/", 19 | "author": "Eugene Cheah (@picocreator)", 20 | "license": "MIT", 21 | "dependencies": { 22 | "inquirer": "^9.2.1", 23 | "koffi": "^2.5.0", 24 | "lru-cache": "^7.18.1", 25 | "node-fetch": "^3.3.1", 26 | "progress": "^2.0.3", 27 | "promise-queue": "^2.2.5", 28 | "rwkv-tokenizer-node": "^1.0.3" 29 | }, 30 | "optionalDependencies": { 31 | "cpu-features": "^0.0.7" 32 | }, 33 | "devDependencies": { 34 | "chai": "^4.3.7", 35 | "chai-as-promised": "^7.1.1", 36 | "mocha": "^10.2.0" 37 | }, 38 | "engines": { 39 | "node": ">=18.0.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/RWKV.js: -------------------------------------------------------------------------------- 1 | //--------------------------- 2 | // Dependencies 3 | //--------------------------- 4 | 5 | const fs = require("fs") 6 | const os = require("os"); 7 | const tokenizer = require("rwkv-tokenizer-node"); 8 | const cpp_bind = require("./cpp_bind").promises; 9 | const ai_utils = require("./ai_utils"); 10 | const LRUCache = require("lru-cache"); 11 | const promise_queue = require("promise-queue"); 12 | 13 | //--------------------------- 14 | // Implementation 15 | //--------------------------- 16 | 17 | /** 18 | * RWKV js class wrapper 19 | * 20 | * Allows the use of the RWKV CPP library from JS 21 | * This library is used to load and infer the RWKV model 22 | * 23 | * It should not be used for training or model conversion 24 | */ 25 | class RWKV { 26 | //------------- 27 | // Class Setup 28 | //------------- 29 | 30 | /** 31 | * Constructor, with the RWKV CPP model path 32 | * 33 | * If initialized with a string, it is assumed to be the model path 34 | * 35 | * If initialized with an object, you can use the following parameters 36 | * 37 | * - path: the model path 38 | * 39 | * - threads: the number of threads to use 40 | * (defaults to half the number of vCPUs) 41 | * 42 | * - gpuOffload: either the number of layers to offload, or a string ending with % 43 | * used to indicate the % of layers of offload from the model 44 | * 45 | * - concurrent: the number of concurrent inferences to allow at a time 46 | * (defaults to 1) 47 | * 48 | * - batchSize: the batch size to use for input inference handling 49 | * (defaults to 64 if gpuOffload, else 1) 50 | * 51 | * - stateCacheSize: the hidden state cache size to use, 52 | * useful to speed up inference of a chat like model 53 | * (defaults to 50) 54 | * 55 | * @param {Object|String} config object, or the model path string 56 | */ 57 | constructor(config) { 58 | // Check if the config is a string, if so normalize it to a config obj 59 | if (typeof config === "string") { 60 | config = { 61 | path: config 62 | }; 63 | } 64 | 65 | // Get the CPU thread count 66 | if (config.threads != null) { 67 | config.threads = parseInt(config.threads); 68 | } 69 | if (config.threads == null || config.threads <= 0 || isNaN(config.threads)) { 70 | if( config.gpuOffload != null && parseInt(config.gpuOffload) > 0) { 71 | // With gpu offloading, the optimal seems to be a light mix of cpu 72 | config.threads = 4; 73 | } else { 74 | // Use half the number of vCPUs 75 | config.threads = os.cpus().length / 2; 76 | } 77 | } 78 | 79 | // Store the used config 80 | this._config = config; 81 | } 82 | 83 | /** 84 | * Setup the RWKV context 85 | */ 86 | async setup() { 87 | // Get the config object 88 | let config = this._config; 89 | 90 | // Get the file size 91 | let fileStat = await fs.promises.stat(config.path); 92 | if( fileStat.isFile() == false ) { 93 | throw new Error("RWKV model path is not a file: " + config.path); 94 | } 95 | let fileSize = fileStat.size; 96 | this._fileSize = fileSize; 97 | 98 | // Load the cpp context, and store it 99 | let mainCtx = await cpp_bind.rwkv_init_from_file(config.path, config.threads); 100 | this._mainCtx = mainCtx; 101 | 102 | // Get the state and logits size 103 | this._state_size = await cpp_bind.rwkv_get_state_len(mainCtx); 104 | this._logits_size = await cpp_bind.rwkv_get_logits_len(mainCtx); 105 | 106 | // Offload layers 107 | let gpu_layers = config.gpuOffload || 0; 108 | if( gpu_layers.toString().endsWith("%") ) { 109 | // Get the int value 110 | let gpu_layers_percent = parseInt(gpu_layers); 111 | 112 | // Get the number of layers 113 | let num_layers = await cpp_bind.rwkv_get_n_layer(mainCtx); 114 | 115 | // Compute the number of layers to offload 116 | gpu_layers = Math.floor(num_layers * gpu_layers_percent / 100); 117 | } 118 | 119 | // GPU offloading if needed 120 | if (gpu_layers > 0) { 121 | await cpp_bind.rwkv_gpu_offload_layers(mainCtx, gpu_layers); 122 | } 123 | this._gpu_layers = gpu_layers; 124 | 125 | // Get the number of concurrent inferences 126 | let concurrent = config.concurrent || 1; 127 | 128 | // Prepare the work ctx array, used for seperate concurrent inferences 129 | let workCtxArray = [mainCtx]; 130 | for(let i=1; i { 156 | // state: [state buffer], 157 | // logits: [logits buffer], 158 | // prompt: [prompt string], 159 | // tokens: [token array] 160 | // } 161 | // --- 162 | // State cache, keeps the last N states in memory 163 | if (config.stateCacheSize === false || config.stateCacheSize <= 0) { 164 | // Disable the cache 165 | this._stateCache = null; 166 | } else { 167 | // Create the cache 168 | this._stateCache = new LRUCache({ 169 | max: config.stateCacheSize || 50, 170 | }); 171 | } 172 | } 173 | 174 | /** 175 | * Cleanup the RWKV context - do not perform concurrent call of this operation 176 | */ 177 | async free() { 178 | // Destroy the context array 179 | if(this._workCtxArray) { 180 | for(let i=this._workCtxArray.length - 1; i>=1; i--) { 181 | await cpp_bind.rwkv_free(this._workCtxArray[i]); 182 | } 183 | this._workCtxArray = null; 184 | } 185 | // Destroy the main context 186 | if (this._mainCtx) { 187 | let p = await cpp_bind.rwkv_free(this._mainCtx); 188 | this._mainCtx = null; 189 | await p; 190 | } 191 | } 192 | 193 | //------------- 194 | // Queue handling ops 195 | //------------- 196 | 197 | /** 198 | * @private mehthod (do not use API directly, it will not be maintained) 199 | * 200 | * For the given async function, assign it to a worker, with the shortest queue. 201 | * The function is only invoked when the worker is ready to accept the function. 202 | * 203 | * This is used internally to distribute requests across worker contexts. 204 | * While limiting execution to only 1 per worker. 205 | * 206 | * @param {Function} func - the async function to assign 207 | */ 208 | async _assignFunctionToWorker(func) { 209 | // self ref 210 | let self = this; 211 | 212 | // First lets join the shared queue 213 | return await this._sharedWorkQueue.add(async () => { 214 | // Get the worker with the shortest queue, for us to assign the function to 215 | // --- 216 | let shortestQueue = this._workQueueArr[0]; 217 | let shortestQueueIdx = 0; 218 | let shortestQueueLength = shortestQueue.getPendingLength() + shortestQueue.getQueueLength(); 219 | for(let i=1; i { 230 | // Invoke the function, with worker instance, and the queue index 231 | return await func(self._workCtxArray[shortestQueueIdx], shortestQueueIdx); 232 | }); 233 | }); 234 | } 235 | 236 | /** 237 | * The number of active worker processes 238 | * @returns {number} the number of active workers 239 | */ 240 | activeWorkCount() { 241 | return this._sharedWorkQueue.getPendingLength(); 242 | } 243 | 244 | /** 245 | * The number of pending work requests 246 | * @returns {number} the number of pending work requests 247 | */ 248 | pendingWorkCount() { 249 | return this._sharedWorkQueue.getQueueLength(); 250 | } 251 | 252 | //------------- 253 | // Internal ops 254 | //------------- 255 | 256 | /** 257 | * @private mehthod (do not use API directly, it will not be maintained) 258 | * 259 | * Given the existing state, and the input string, get the completed hidden state buffer. 260 | * This operation DOES NOT use the internal cache. 261 | * 262 | * @param {Float32Array} inState - existing state to compute from 263 | * @param {Array} tokenArr - array of tokens to compute 264 | * @param {*} workerCtx - the worker context to use 265 | * 266 | * @returns {Object} the hidden state buffer and logits buffer 267 | */ 268 | async _getHiddenState_fromExistingState_andTokenArr(inState, tokenArr, workerCtx) { 269 | // Edge case handling when tokenArr is empty 270 | if (tokenArr == null || tokenArr.length == 0) { 271 | throw new Error("RWKV token array is empty"); 272 | } 273 | if( workerCtx == null ) { 274 | throw new Error("RWKV worker context is null"); 275 | } 276 | 277 | // Get the batch size 278 | let batchSize = this._config.batchSize; 279 | 280 | if( batchSize == null || batchSize <= 0 ) { 281 | if( this._config._gpu_layers > 0 ) { 282 | batchSize = 64; 283 | } else { 284 | batchSize = 1; 285 | } 286 | } 287 | 288 | // Prepare the output state to use 289 | let outputState = new Float32Array(this._state_size); 290 | 291 | // Copy the input state into the output state 292 | if (inState != null) { 293 | outputState.set(inState); 294 | } 295 | 296 | // Prepare the logit buffer (can be ignored safely) 297 | let logits = new Float32Array(this._logits_size); 298 | 299 | // Compute the hidden state for each token 300 | for (let i = 0; i < tokenArr.length; i += batchSize) { 301 | // Individual tokens 302 | if( batchSize == 1 ) { 303 | if ( 304 | (await cpp_bind.rwkv_eval( 305 | workerCtx, 306 | tokenArr[i], 307 | outputState, 308 | outputState, 309 | logits 310 | )) == false 311 | ) { 312 | throw new Error("RWKV unexpected eval failed"); 313 | } 314 | } else { 315 | const chunk = tokenArr.slice(i, i + batchSize); 316 | if ( 317 | (await cpp_bind.rwkv_eval_sequence( 318 | workerCtx, 319 | chunk, 320 | chunk.length, 321 | outputState, 322 | outputState, 323 | logits 324 | )) == false 325 | ) { 326 | throw new Error("RWKV unexpected eval failed"); 327 | } 328 | } 329 | } 330 | 331 | // Return the output state 332 | return { 333 | state: outputState, 334 | logits: logits, 335 | }; 336 | } 337 | 338 | /** 339 | * Internal function, throw if the context is not set 340 | */ 341 | _checkContext() { 342 | if (!this._mainCtx) { 343 | throw new Error("RWKV context is not set, have you called setup()?"); 344 | } 345 | } 346 | 347 | /** 348 | * @private mehthod (do not use API directly, it will not be maintained) 349 | * 350 | * Given the input string, get the hidden state buffer. 351 | * Fetching it from the internal cache when possible. 352 | * 353 | * Also updates the cache with a copy of the new state 354 | * 355 | * @param {String} input string to get the hidden state for 356 | * @param {Array} inputTokens - array of tokens to compute 357 | * @param {*} workerCtx - the worker context to use 358 | * 359 | * @returns {Object} the hidden state buffer and logits buffer, along with input string and tokens 360 | */ 361 | async _getHiddenState_fromFullInputString(input, inputTokens, workerCtx) { 362 | // Existing cached state obj 363 | let cachedState = null; 364 | 365 | // Throw if the input is empty 366 | if (input == null || input.length == 0) { 367 | throw new Error("RWKV input string is empty (are you missing a prompt?)"); 368 | } 369 | 370 | // Try to get matching existing state from the cache first 371 | // --- 372 | if (this._stateCache) { 373 | // Get all the cache keys 374 | let keys = []; 375 | for (const key of this._stateCache.keys()) { 376 | keys.push(key); 377 | } 378 | 379 | // Sort the keys by length, longest first 380 | keys = keys.sort((a, b) => b.length - a.length); 381 | 382 | // Loop over the keys, see if we can find a match 383 | for (const prefixKey of keys) { 384 | if (input.startsWith(prefixKey)) { 385 | // Found a matching key, lets proceed to check the tokens 386 | let candidateState = this._stateCache.get(prefixKey); 387 | if( candidateState == null ) { 388 | // candidate state was evicted from cache, skip 389 | continue; 390 | } 391 | 392 | // Check if the token array matches 393 | let inputTokensSlice = inputTokens.slice(candidateState.tokens.length); 394 | for( let i=0; i